diff --git a/Engine/source/T3D/Scene.cpp b/Engine/source/T3D/Scene.cpp index 719004766..2a5a20d6c 100644 --- a/Engine/source/T3D/Scene.cpp +++ b/Engine/source/T3D/Scene.cpp @@ -361,15 +361,19 @@ DefineEngineMethod(Scene, getRootScene, S32, (),, } DefineEngineMethod(Scene, addDynamicObject, void, (SceneObject* sceneObj), (nullAsType()), - "Get the root Scene object that is loaded.\n" - "@return The id of the Root Scene. Will be 0 if no root scene is loaded") + "Adds an object to the scene's dynamic objects list. Used for things spawned as part of gameplay and not permanent objects to be saved out as part of the level proper.") { object->addDynamicObject(sceneObj); } +DefineEngineMethod(Scene, clearDynamicObjects, void, (),, + "Clears all objects from the scene's dynamic objects list.") +{ + object->clearDynamicObjects(); +} + DefineEngineMethod(Scene, removeDynamicObject, void, (SceneObject* sceneObj), (nullAsType()), - "Get the root Scene object that is loaded.\n" - "@return The id of the Root Scene. Will be 0 if no root scene is loaded") + "Removes an object from the scene's dynamic objects list.") { object->removeDynamicObject(sceneObj); } diff --git a/Engine/source/T3D/Scene.h b/Engine/source/T3D/Scene.h index b26344c7e..3a912b4ea 100644 --- a/Engine/source/T3D/Scene.h +++ b/Engine/source/T3D/Scene.h @@ -65,6 +65,7 @@ public: void addDynamicObject(SceneObject* object); void removeDynamicObject(SceneObject* object); + void clearDynamicObjects() { mDynamicObjects.clear(); } void dumpUtilizedAssets(); diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index e82400446..dad23da0a 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -2184,6 +2184,29 @@ void ShapeBase::getEyeCameraTransform(IDisplayDevice *displayDevice, U32 eyeId, *outMat = cameraTransform * temp; } +void ShapeBase::getNodeTransform(const char* nodeName, const MatrixF& xfm, MatrixF* outMat) +{ + if (!mShapeInstance) + return; + + S32 nodeIDx = mDataBlock->getShapeResource()->findNode(nodeName); + + MatrixF nodeTransform(xfm); + const Point3F& scale = getScale(); + if (nodeIDx != -1) + { + nodeTransform = mShapeInstance->mNodeTransforms[nodeIDx]; + nodeTransform.mul(xfm); + } + // The position of the mount point needs to be scaled. + Point3F position = nodeTransform.getPosition(); + position.convolve(scale); + nodeTransform.setPosition(position); + // Also we would like the object to be scaled to the model. + outMat->mul(mObjToWorld, nodeTransform); + return; +} + void ShapeBase::getCameraParameters(F32 *min,F32* max,Point3F* off,MatrixF* rot) { *min = mDataBlock->cameraMinDist; diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index ae823b6b9..8ba0c9023 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -1594,6 +1594,8 @@ public: /// @param pos Muzzle point (out) void getMuzzlePoint(U32 imageSlot,Point3F* pos); + virtual void getNodeTransform(const char* nodeName, const MatrixF& xfm, MatrixF* outMat); + /// @} /// @name Transforms diff --git a/Engine/source/afx/ea/afxEA_AnimClip.cpp b/Engine/source/afx/ea/afxEA_AnimClip.cpp index 4f1240f27..25f811cb1 100644 --- a/Engine/source/afx/ea/afxEA_AnimClip.cpp +++ b/Engine/source/afx/ea/afxEA_AnimClip.cpp @@ -128,7 +128,7 @@ bool afxEA_AnimClip::ea_update(F32 dt) if (go_for_it) { F32 rate = clip_data->rate/mProp_time_factor; - F32 pos = mFmod(mLife_elapsed, anim_lifetime)/anim_lifetime; + F32 pos = (anim_lifetime>0) ? mFmod(mLife_elapsed, anim_lifetime)/anim_lifetime : 0; pos = mFmod(pos + clip_data->pos_offset, 1.0); if (clip_data->rate < 0) pos = 1.0f - pos; diff --git a/Engine/source/forest/editor/forestEditorCtrl.cpp b/Engine/source/forest/editor/forestEditorCtrl.cpp index 9735cf191..f43a1b23d 100644 --- a/Engine/source/forest/editor/forestEditorCtrl.cpp +++ b/Engine/source/forest/editor/forestEditorCtrl.cpp @@ -160,7 +160,7 @@ void ForestEditorCtrl::get3DCursor( GuiCursor *&cursor, void ForestEditorCtrl::on3DMouseDown( const Gui3DMouseEvent &evt ) { - if ( !mForest && !updateActiveForest( true ) ) + if ( !mForest || !updateActiveForest( true ) ) return; if ( mTool ) diff --git a/Engine/source/gui/controls/guiBitmapBorderCtrl.cpp b/Engine/source/gui/controls/guiBitmapBorderCtrl.cpp index d9f7c1c5f..0d3cd3c96 100644 --- a/Engine/source/gui/controls/guiBitmapBorderCtrl.cpp +++ b/Engine/source/gui/controls/guiBitmapBorderCtrl.cpp @@ -48,7 +48,13 @@ class GuiBitmapBorderCtrl : public GuiControl }; RectI *mBitmapBounds; ///< bmp is [3*n], bmpHL is [3*n + 1], bmpNA is [3*n + 2] GFXTexHandle mTextureObject; + ColorI mColor; + public: + GuiBitmapBorderCtrl(); + + static void initPersistFields(); + bool onWake(); void onSleep(); void onRender(Point2I offset, const RectI &updateRect); @@ -104,6 +110,21 @@ ConsoleDocClass( GuiBitmapBorderCtrl, "@ingroup GuiImages" ); +GuiBitmapBorderCtrl::GuiBitmapBorderCtrl() +{ + mColor.set(255,255,255, 255); +} + +void GuiBitmapBorderCtrl::initPersistFields() +{ + docsURL; + addGroup("Bitmap"); + addField("color", TypeColorI, Offset(mColor, GuiBitmapBorderCtrl), "color mul"); + endGroup("Bitmap"); + + Parent::initPersistFields(); +} + bool GuiBitmapBorderCtrl::onWake() { if (! Parent::onWake()) @@ -153,6 +174,8 @@ void GuiBitmapBorderCtrl::onRender(Point2I offset, const RectI &updateRect) drawUtil->drawRectFill(winRect, mProfile->mFillColor); drawUtil->clearBitmapModulation(); + drawUtil->setBitmapModulation(mColor); + drawUtil->drawBitmapSR(mTextureObject, offset, mBitmapBounds[BorderTopLeft]); drawUtil->drawBitmapSR(mTextureObject, Point2I(offset.x + getWidth() - mBitmapBounds[BorderTopRight].extent.x, offset.y), mBitmapBounds[BorderTopRight]); diff --git a/Engine/source/math/mMatrix.h b/Engine/source/math/mMatrix.h index d245e55ec..18981eeea 100644 --- a/Engine/source/math/mMatrix.h +++ b/Engine/source/math/mMatrix.h @@ -228,7 +228,8 @@ public: //------------------------------------ friend MatrixF operator * ( const MatrixF &m1, const MatrixF &m2 ); MatrixF& operator *= ( const MatrixF &m ); - + MatrixF &operator = (const MatrixF &m); + bool isNaN(); // Static identity matrix const static MatrixF Identity; }; @@ -596,6 +597,20 @@ inline MatrixF& MatrixF::operator *= ( const MatrixF &m1 ) return (*this); } +inline MatrixF &MatrixF::operator = (const MatrixF &m1) +{ + for (U32 i=0;i<16;i++) + this->m[i] = m1.m[i]; + return (*this); +} +inline bool MatrixF::isNaN() +{ + bool isaNaN = false; + for (U32 i = 0; i < 16; i++) + if (mIsNaN_F(m[i])) + isaNaN = true; + return isaNaN; +} //------------------------------------ // Non-member methods //------------------------------------ diff --git a/Engine/source/scene/sceneContainer.cpp b/Engine/source/scene/sceneContainer.cpp index 57bb9760b..81a437392 100644 --- a/Engine/source/scene/sceneContainer.cpp +++ b/Engine/source/scene/sceneContainer.cpp @@ -1485,7 +1485,7 @@ ConsoleFunctionGroupBegin( Containers, "Functions for ray casting and spatial q //----------------------------------------------------------------------------- DefineEngineFunction( containerBoxEmpty, bool, - ( U32 mask, Point3F center, F32 xRadius, F32 yRadius, F32 zRadius, bool useClientContainer ), ( -1, -1, false ), + ( U32 mask, Point3F center, F32 xRadius, F32 yRadius, F32 zRadius, bool useClientContainer, SceneObject* ignoreObj), ( -1, -1, false, nullAsType()), "@brief See if any objects of the given types are present in box of given extent.\n\n" "@note Extent parameter is last since only one radius is often needed. If " "one radius is provided, the yRadius and zRadius are assumed to be the same. Unfortunately, " @@ -1519,8 +1519,12 @@ DefineEngineFunction( containerBoxEmpty, bool, polyList.mPlaneList[5].set(B.maxExtents, VectorF(0,0,1)); SceneContainer* pContainer = useClientContainer ? &gClientContainer : &gServerContainer; - - return ! pContainer->buildPolyList(PLC_Collision, B, mask, &polyList); + if (ignoreObj) + ignoreObj->disableCollision(); + bool ret = !pContainer->buildPolyList(PLC_Collision, B, mask, &polyList); + if (ignoreObj) + ignoreObj->enableCollision(); + return ret; } //----------------------------------------------------------------------------- diff --git a/Engine/source/scene/sceneObject.cpp b/Engine/source/scene/sceneObject.cpp index d0799e9ea..52ffd545a 100644 --- a/Engine/source/scene/sceneObject.cpp +++ b/Engine/source/scene/sceneObject.cpp @@ -521,8 +521,14 @@ void SceneObject::resetWorldBox() AssertFatal(mObjBox.isValidBox(), "SceneObject::resetWorldBox - Bad object box!"); mWorldBox = mObjBox; - mWorldBox.minExtents.convolve(mObjScale); - mWorldBox.maxExtents.convolve(mObjScale); + + Point3F scale = Point3F(mFabs(mObjScale.x), mFabs(mObjScale.y), mFabs(mObjScale.z)); + mWorldBox.minExtents.convolve(scale); + mWorldBox.maxExtents.convolve(scale); + + if (mObjToWorld.isNaN()) + mObjToWorld.identity(); + mObjToWorld.mul(mWorldBox); AssertFatal(mWorldBox.isValidBox(), "SceneObject::resetWorldBox - Bad world box!"); @@ -585,11 +591,16 @@ void SceneObject::resetRenderWorldBox() AssertFatal( mObjBox.isValidBox(), "Bad object box!" ); mRenderWorldBox = mObjBox; - mRenderWorldBox.minExtents.convolve( mObjScale ); - mRenderWorldBox.maxExtents.convolve( mObjScale ); + Point3F scale = Point3F(mFabs(mObjScale.x), mFabs(mObjScale.y), mFabs(mObjScale.z)); + mRenderWorldBox.minExtents.convolve(scale); + mRenderWorldBox.maxExtents.convolve(scale); + + if (mRenderObjToWorld.isNaN()) + mRenderObjToWorld.identity(); + mRenderObjToWorld.mul( mRenderWorldBox ); - AssertFatal( mRenderWorldBox.isValidBox(), "Bad world box!" ); + AssertFatal( mRenderWorldBox.isValidBox(), "Bad Render world box!" ); // Create mRenderWorldSphere from mRenderWorldBox.