Browse Source

Merge pull request #2189 from Areloch/AnimationAssetImprovements

Bugfixes and improvements for the animation component and related assets
Areloch 7 years ago
parent
commit
7af3de2517

+ 45 - 1
Engine/source/T3D/assets/ShapeAnimationAsset.cpp

@@ -92,8 +92,13 @@ ConsoleSetType(TypeShapeAnimationAssetPtr)
 
 //-----------------------------------------------------------------------------
 
-ShapeAnimationAsset::ShapeAnimationAsset()
+ShapeAnimationAsset::ShapeAnimationAsset() : 
+   mIsEmbedded(false), mIsCyclical(true), mIsBlend(false), mBlendFrame(0), mStartFrame(0), mEndFrame(-1), mPadRotation(true), mPadTransforms(false)
 {
+   mFileName = StringTable->EmptyString();
+   mAnimationName = StringTable->EmptyString();
+
+   mBlendAnimAssetName = StringTable->EmptyString();
 }
 
 //-----------------------------------------------------------------------------
@@ -116,6 +121,14 @@ void ShapeAnimationAsset::initPersistFields()
    addField("animationFile", TypeFilename, Offset(mFileName, ShapeAnimationAsset), "Path to the file name containing the animation");
    addField("animationName", TypeString, Offset(mAnimationName, ShapeAnimationAsset), "Name of the animation");
 
+   addField("isEmbedded", TypeBool, Offset(mIsEmbedded, ShapeAnimationAsset), "If true, this animation asset just referrs to an embedded animation of a regular shape mesh. If false, it is a self-contained animation file");
+
+   addField("isCyclic", TypeBool, Offset(mIsCyclical, ShapeAnimationAsset), "Is this animation looping?");
+
+   addField("isBlend", TypeBool, Offset(mIsBlend, ShapeAnimationAsset), "Is this animation blended with another?");
+   addField("blendRefAnimation", TypeString, Offset(mBlendAnimAssetName, ShapeAnimationAsset), "AssetID of the animation to reference for our blending");
+   addField("blendFrame", TypeS32, Offset(mBlendFrame, ShapeAnimationAsset), "Which frame of the reference animation do we use for our blending");
+
    addField("startFrame", TypeS32, Offset(mStartFrame, ShapeAnimationAsset), "What frame does this animation clip start on");
    addField("endFrame", TypeS32, Offset(mEndFrame, ShapeAnimationAsset), "What fram does this animation clip end on");
    addField("padRotation", TypeBool, Offset(mPadRotation, ShapeAnimationAsset), "Are the rotation values padded");
@@ -128,4 +141,35 @@ void ShapeAnimationAsset::copyTo(SimObject* object)
 {
    // Call to parent.
    Parent::copyTo(object);
+}
+
+void ShapeAnimationAsset::initializeAsset(void)
+{
+   if (!mIsEmbedded)
+   {
+      //If we're not embedded, we need to load in our initial shape and do some prepwork
+
+      char filenameBuf[1024];
+      Con::expandScriptFilename(filenameBuf, sizeof(filenameBuf), mFileName);
+
+      mSourceShape = ResourceManager::get().load(filenameBuf);
+
+      if (!mSourceShape->addSequence("ambient", "", mAnimationName, mStartFrame, mEndFrame, mPadRotation, mPadTransforms))
+      {
+         Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to do initial setup of the animation clip named %s for asset %s", mAnimationName, getAssetName());
+         return;
+      }
+
+      S32 sequenceId = mSourceShape->findSequence(mAnimationName);
+
+      if(mIsCyclical)
+         mSourceShape->sequences[sequenceId].flags |= TSShape::Cyclic;
+      else
+         mSourceShape->sequences[sequenceId].flags &= (~(TSShape::Cyclic));
+   }
+}
+
+void ShapeAnimationAsset::onAssetRefresh(void)
+{
+
 }

+ 26 - 2
Engine/source/T3D/assets/ShapeAnimationAsset.h

@@ -37,6 +37,12 @@
 #ifndef _ASSET_FIELD_TYPES_H_
 #include "assets/assetFieldTypes.h"
 #endif
+#ifndef _TSSHAPE_H_
+#include "ts/tsShape.h"
+#endif
+#ifndef __RESOURCE_H__
+#include "core/resource.h"
+#endif
 
 //-----------------------------------------------------------------------------
 class ShapeAnimationAsset : public AssetBase
@@ -46,6 +52,15 @@ class ShapeAnimationAsset : public AssetBase
 protected:
    StringTableEntry   mFileName;
 
+   bool            mIsEmbedded;
+   bool            mIsCyclical;
+
+   bool            mIsBlend;
+
+   StringTableEntry mBlendAnimAssetName;
+
+   S32 mBlendFrame;
+
    //
    StringTableEntry mAnimationName;
    S32 mStartFrame;
@@ -53,6 +68,8 @@ protected:
    bool mPadRotation;
    bool mPadTransforms;
 
+   Resource<TSShape> mSourceShape;
+
 public:
    ShapeAnimationAsset();
    virtual ~ShapeAnimationAsset();
@@ -65,18 +82,25 @@ public:
    DECLARE_CONOBJECT(ShapeAnimationAsset);
 
 protected:
-   virtual void            initializeAsset(void) {}
-   virtual void            onAssetRefresh(void) {}
+   virtual void            initializeAsset(void);
+   virtual void            onAssetRefresh(void);
 
 public:
    StringTableEntry getAnimationFilename() { return mFileName; }
    StringTableEntry getAnimationName() { return mAnimationName; }
+   StringTableEntry getBlendAnimationName() { return mBlendAnimAssetName; }
 
    S32 getStartFrame() { return mStartFrame; }
    S32 getEndFrame() { return mEndFrame; }
 
    bool getPadRotation() { return mPadRotation; }
    bool getPadTransforms() { return mPadTransforms; }
+
+   bool isEmbedded() { return mIsEmbedded; }
+   bool isCyclic() { return mIsCyclical; }
+   bool isBlend() { return mIsBlend; }
+
+   S32 getBlendFrame() { return mBlendFrame; }
 };
 
 DefineConsoleType(TypeShapeAnimationAssetPtr, ShapeAnimationAsset)

+ 36 - 4
Engine/source/T3D/assets/ShapeAsset.cpp

@@ -182,17 +182,49 @@ bool ShapeAsset::loadShape()
       return false; //if it failed to load, bail out
    }
 
+   bool hasBlends = false;
+
    //Now that we've successfully loaded our shape and have any materials and animations loaded
    //we need to set up the animations we're using on our shape
-   for (U32 i = 0; i < mAnimationAssets.size(); i++)
+   for (S32 i = mAnimationAssets.size()-1; i >= 0; --i)
    {
-      String srcName;
+      String srcName = mAnimationAssets[i]->getAnimationName();
       String srcPath(mAnimationAssets[i]->getAnimationFilename());
-      SplitSequencePathAndName(srcPath, srcName);
+      //SplitSequencePathAndName(srcPath, srcName);
 
-      if (!mShape->addSequence(srcPath, srcName, mAnimationAssets[i]->getAnimationName(), 
+      if (!mShape->addSequence(srcPath, srcName, srcName,
          mAnimationAssets[i]->getStartFrame(), mAnimationAssets[i]->getEndFrame(), mAnimationAssets[i]->getPadRotation(), mAnimationAssets[i]->getPadTransforms()))
          return false;
+
+      if (mAnimationAssets[i]->isBlend())
+         hasBlends = true;
+   }
+
+   //if any of our animations are blends, set those up now
+   if (hasBlends)
+   {
+      for (U32 i=0; i < mAnimationAssets.size(); ++i)
+      {
+         if (mAnimationAssets[i]->isBlend() && mAnimationAssets[i]->getBlendAnimationName() != StringTable->EmptyString())
+         {
+            //gotta do a bit of logic here.
+            //First, we need to make sure the anim asset we depend on for our blend is loaded
+            AssetPtr<ShapeAnimationAsset> blendAnimAsset = mAnimationAssets[i]->getBlendAnimationName();
+
+            if (blendAnimAsset.isNull())
+            {
+               Con::errorf("ShapeAsset::initializeAsset - Unable to acquire reference animation asset %s for asset %s to blend!", mAnimationAssets[i]->getBlendAnimationName(), mAnimationAssets[i]->getAssetName());
+               return false;
+            }
+
+            String refAnimName = blendAnimAsset->getAnimationName();
+            if (!mShape->setSequenceBlend(mAnimationAssets[i]->getAnimationName(), true, blendAnimAsset->getAnimationName(), mAnimationAssets[i]->getBlendFrame()))
+            {
+               Con::errorf("ShapeAnimationAsset::initializeAsset - Unable to set animation clip %s for asset %s to blend!", mAnimationAssets[i]->getAnimationName(), mAnimationAssets[i]->getAssetName());
+               return false;
+            }
+         }
+      }
    }
 
    return true;

+ 4 - 4
Engine/source/T3D/components/animation/animationComponent.cpp

@@ -222,7 +222,7 @@ U32 AnimationComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stre
 {
    U32 retMask = Parent::packUpdate(con, mask, stream);
 
-   /*for (int i = 0; i < MaxScriptThreads; i++)
+   for (int i = 0; i < MaxScriptThreads; i++)
    {
       Thread& st = mAnimationThreads[i];
       if (stream->writeFlag((st.sequence != -1 || st.state == Thread::Destroy) && (mask & (ThreadMaskN << i))))
@@ -234,7 +234,7 @@ U32 AnimationComponent::packUpdate(NetConnection *con, U32 mask, BitStream *stre
          stream->writeFlag(st.atEnd);
          stream->writeFlag(st.transition);
       }
-   }*/
+   }
 
    return retMask;
 }
@@ -243,7 +243,7 @@ void AnimationComponent::unpackUpdate(NetConnection *con, BitStream *stream)
 {
    Parent::unpackUpdate(con, stream);
 
-   /*for (S32 i = 0; i < MaxScriptThreads; i++) 
+   for (S32 i = 0; i < MaxScriptThreads; i++) 
    {
       if (stream->readFlag()) 
       {
@@ -260,7 +260,7 @@ void AnimationComponent::unpackUpdate(NetConnection *con, BitStream *stream)
          else
             updateThread(st);
       }
-   }*/
+   }
 }
 
 void AnimationComponent::processTick()

+ 12 - 1
Engine/source/ts/collada/colladaImport.cpp

@@ -198,7 +198,7 @@ DefineConsoleFunction( enumColladaForImport, bool, (const char * shapePath, cons
       for (S32 j = 0; j < libraryMats->getMaterial_array().getCount(); j++)
       {
          domMaterial* mat = libraryMats->getMaterial_array()[j];
-         tree->insertItem(matsID, _GetNameOrId(mat), _GetNameOrId(mat), "", 0, 0);
+         tree->insertItem(matsID, _GetNameOrId(mat), "", "", 0, 0);
       }
    }
 
@@ -256,5 +256,16 @@ DefineConsoleFunction( enumColladaForImport, bool, (const char * shapePath, cons
    else
       tree->setDataField(StringTable->insert("_upAxis"), 0, "Z_AXIS");
 
+   char shapesStr[16];
+   dSprintf(shapesStr, 16, "%i", stats.numMeshes);
+   char materialsStr[16];
+   dSprintf(materialsStr, 16, "%i", stats.numMaterials);
+   char animationsStr[16];
+   dSprintf(animationsStr, 16, "%i", stats.numClips);
+
+   tree->setItemValue(nodesID, StringTable->insert(shapesStr));
+   tree->setItemValue(matsID, StringTable->insert(materialsStr));
+   tree->setItemValue(animsID, StringTable->insert(animationsStr));
+
    return true;
 }

+ 7 - 3
Templates/BaseGame/game/tools/shapeEditor/scripts/shapeEditorActions.ed.cs

@@ -346,10 +346,11 @@ function ActionAddSequence::doit( %this )
       %assetDef = AssetDatabase.acquireAsset(%this.seqName);
       %moduleName = getWord(getToken(%this.seqName, ":", 0),0);
       
-      %idx = ShapeEdSequenceList.rowCount();
+      //TODO, properly ignore <rootpose> and ambient entries for our idx values, but only if they're there!
+      %idx = ShapeEdSequenceList.rowCount() - 2;
       
-      %matSet = "ShapeEditorPlugin.selectedAssetDef.animationSequence"@%idx@"=\"@Asset="@%moduleName@":"@%this.seqName.assetName@"\";";
-      eval(%matSet);
+      %animSet = "ShapeEditorPlugin.selectedAssetDef.animationSequence"@%idx@"=\"@Asset="@%moduleName@":"@%assetDef.assetName@"\";";
+      eval(%animSet);
       
       %assetPath = AssetDatabase.getAssetFilePath(ShapeEditorPlugin.selectedAssetId);
       
@@ -357,6 +358,9 @@ function ActionAddSequence::doit( %this )
       
       AssetDatabase.refreshAsset(ShapeEditorPlugin.selectedAssetId);
       
+      //force a refresh
+      ShapeEdPropWindow.update_onShapeSelectionChanged();
+      
       return true;
    }
    return false;