Merge pull request #2189 from Areloch/AnimationAssetImprovements

Bugfixes and improvements for the animation component and related assets
This commit is contained in:
Areloch 2018-02-13 14:54:38 -06:00 committed by GitHub
commit 0cd9813b8c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 130 additions and 15 deletions

View file

@ -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)
{
}

View file

@ -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)

View file

@ -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;

View file

@ -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()

View file

@ -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;
}

View file

@ -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;