diff --git a/Engine/source/T3D/assets/ShapeAnimationAsset.cpp b/Engine/source/T3D/assets/ShapeAnimationAsset.cpp index ee10bbe40..4c2b0283e 100644 --- a/Engine/source/T3D/assets/ShapeAnimationAsset.cpp +++ b/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) +{ + } \ No newline at end of file diff --git a/Engine/source/T3D/assets/ShapeAnimationAsset.h b/Engine/source/T3D/assets/ShapeAnimationAsset.h index 673607d53..0b7bf1790 100644 --- a/Engine/source/T3D/assets/ShapeAnimationAsset.h +++ b/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 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) diff --git a/Engine/source/T3D/assets/ShapeAsset.cpp b/Engine/source/T3D/assets/ShapeAsset.cpp index 099c3c117..2bce369ea 100644 --- a/Engine/source/T3D/assets/ShapeAsset.cpp +++ b/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 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; diff --git a/Engine/source/T3D/components/animation/animationComponent.cpp b/Engine/source/T3D/components/animation/animationComponent.cpp index c8fd645d0..cd7c2534c 100644 --- a/Engine/source/T3D/components/animation/animationComponent.cpp +++ b/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() diff --git a/Engine/source/ts/collada/colladaImport.cpp b/Engine/source/ts/collada/colladaImport.cpp index f3aea309e..1cc2909b0 100644 --- a/Engine/source/ts/collada/colladaImport.cpp +++ b/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; } diff --git a/Templates/BaseGame/game/tools/shapeEditor/scripts/shapeEditorActions.ed.cs b/Templates/BaseGame/game/tools/shapeEditor/scripts/shapeEditorActions.ed.cs index 3847226f6..15bd4cc9b 100644 --- a/Templates/BaseGame/game/tools/shapeEditor/scripts/shapeEditorActions.ed.cs +++ b/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 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;