// AnimNode.cpp: implementation of the CAnimNode class. // ////////////////////////////////////////////////////////////////////// // TODO : jkyle - need to implement SetValue and GetValue for the ParamNode derivatives #include "stdafx.h" #include "animscript.h" #include "AnimNode.h" #include "AnimScriptDoc.h" #include "modifycurveparam.h" #include "modifyfloat.h" #include "modifypathdlg.h" #include "modifyattribdlg.h" #include #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif // This is the exact text used for save and load of data file key names, index matches enum in AnimNode.h char g_szParamKeyName[][40] = { "AnimType", "Start", "Position", "Anim", "StartOverlapCurve", "EndOverlapCurve", "TransitionStart", "PlayOldStateTill", "OverrideNewStatePosition", "StartNewState", "PitchAttrib", "RollAttrib", "SpeedAttrib", "FastAnim", "SlowAnim", "SlowSpeedMultiplier", "LerpTime", "SlowUpAnim", "SlowEvenAnim", "SlowDownAnim", "FastUpAnim", "FastEvenAnim", "FastDownAnim", "UpAnim", "EvenAnim", "DownAnim", "LeftAnim", "RightAnim", "SlowLeftAnim", "SlowRightAnim", "FastLeftAnim", "FastRightAnim", "InvalidAnim" }; // This is a mapping of all animation types with the parameter type int g_arrAnimTypeParams[][2] = { {MechWarrior4::AnimationStateEngine::PoseType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::CycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::CycleType,PARAM_ANIM}, {MechWarrior4::AnimationStateEngine::SpeedCycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::SpeedCycleType,PARAM_ANIM}, {MechWarrior4::AnimationStateEngine::SpeedCycleType,PARAM_SPEEDATTRIB}, {MechWarrior4::AnimationStateEngine::SpeedBlenderCycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::SpeedBlenderCycleType,PARAM_SLOWANIM}, {MechWarrior4::AnimationStateEngine::SpeedBlenderCycleType,PARAM_FASTANIM}, {MechWarrior4::AnimationStateEngine::SpeedBlenderCycleType,PARAM_SPEEDATTRIB}, {MechWarrior4::AnimationStateEngine::SpeedBlenderCycleType,PARAM_SLOWSPEEDMULTIPLIER}, {MechWarrior4::AnimationStateEngine::LerpCycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::LerpCycleType,PARAM_LERPTIME}, {MechWarrior4::AnimationStateEngine::LerpCycleType,PARAM_ANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWUPANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWEVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWDOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTUPANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTEVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTDOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_PITCHATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_ROLLATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SPEEDATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWSPEEDMULTIPLIER}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_UPANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_EVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_DOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_ROLLATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_PITCHATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_SPEEDATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_UPANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_EVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_DOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_LEFTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_RIGHTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_ROLLATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_PITCHATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightBlenderCycleType,PARAM_SPEEDATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWUPANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWEVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWDOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWLEFTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWRIGHTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTUPANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTEVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTDOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTLEFTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_FASTRIGHTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_ROLLATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_PITCHATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SPEEDATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightSpeedBlenderCycleType,PARAM_SLOWSPEEDMULTIPLIER}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_UPANIM}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_EVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_DOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_LEFTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_RIGHTANIM}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_ROLLATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_PITCHATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_POSITION}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_EVENANIM}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_DOWNANIM}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_ROLLATTRIB}, {MechWarrior4::AnimationStateEngine::FullHeightPoseHolderType,PARAM_PITCHATTRIB} }; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //**************************// // The base class for Animation States and Transition States CAnimNode::CAnimNode(CString strName) { m_bValid = false; m_strName = strName; m_hItem = NULL; } CAnimNode::~CAnimNode() { } CParamNode *CAnimNode::GetParam(int iKey) { CObject *pObj; if (m_mapParams.Lookup(iKey,pObj)) { CParamNode *pNode = (CParamNode *)pObj; return pNode; } return NULL; } // returns the value it replaced if at all CParamNode *CAnimNode::SetParam(int iKey,CParamNode *pNode) { assert(iKey>=0); assert(iKeyGetEntry(pNode->GetKeyString(),&pData)) { pNode->SetValue(pData); } } CParamNode *pOldNode = SetParam(iType,pNode); if (pOldNode) { // Might want to set the new node's value to the old one CString strValue = pOldNode->GetValue(); pNode->SetValue(strValue); } CAnimScriptDoc::m_listParamNodes.AddHead(pNode); } return pNode; } // Given a known Animation type, create the parameters that go with it void CAnimNode::CreateAnimTypeParams(CAnimTypeNode *pNode,Page *page) { assert(pNode); CMapWordToPtr mapInvalid; //map the invalid types so we can remove them // Add the valid parameters int iSize = sizeof(g_arrAnimTypeParams)>>3; for (int x=0;xm_iType == iType) { CreateParam(iParam,page); mapInvalid[iParam] = 0; } else { void *pNul; if (!mapInvalid.Lookup(iParam,pNul)) pNul = (void *)1; mapInvalid[iParam] = pNul; } } // Now go through the param map and remove anything that is also in m_mapInvalid POSITION pos = m_mapParams.GetStartPosition(); while (pos) { WORD iKey; CObject *pObj; m_mapParams.GetNextAssoc(pos,iKey,pObj); CParamNode *pParam = (CParamNode *)pObj; void *pNul; if (mapInvalid.Lookup(iKey,pNul)) { if (pNul) { // iKey is invalid m_mapParams.RemoveKey(iKey); POSITION delpos = CAnimScriptDoc::m_listParamNodes.Find(pParam); CAnimScriptDoc::m_listParamNodes.RemoveAt(delpos); delete pParam; } } } } bool CAnimNode::SaveState(NotationFile *file) { if (this->m_bValid) { Page *page = file->AddPage(this->m_strName); Register_Object(page); POSITION pos = m_mapParams.GetStartPosition(); while (pos) { WORD iKey; CObject *pObj; m_mapParams.GetNextAssoc(pos,iKey,pObj); CParamNode *pParam = (CParamNode *)pObj; page->AppendEntry(pParam->GetKeyString(),pParam->GetValue()); } Unregister_Object(page); // delete page; } return true; } //**************************// CAnimStateNode::CAnimStateNode(CString strName) : CAnimNode(strName) { m_bIsTransition = false; } CAnimStateNode::~CAnimStateNode() { } bool CAnimStateNode::LoadState(Page *page) { CreateParam(PARAM_START,page); return CAnimNode::LoadState(page); } //**************************// CTransStateNode::CTransStateNode (CAnimStateNode *pNodeX,CAnimStateNode *pNodeY) : CAnimStateNode((pNodeX?pNodeX->GetName():"")+"::"+(pNodeY?pNodeY->GetName():"")) { m_pStartNode = pNodeX; m_pEndNode = pNodeY; m_bIsTransition = true; } CTransStateNode::~CTransStateNode() { } bool CTransStateNode::LoadState(Page *page) { bool bret = CAnimStateNode::LoadState(page); CreateParam(PARAM_STARTOVERLAPCURVE,page); CreateParam(PARAM_ENDOVERLAPCURVE,page); CreateParam(PARAM_TRANSITIONSTART,page); CreateParam(PARAM_PLAYOLDSTATETILL,page); CreateParam(PARAM_OVERRIDENEWSTATEPOSITION,page); CreateParam(PARAM_STARTNEWSTATE,page); return bret; } //**************************// CParamNode::CParamNode() { m_iParamType = -1; } CString CParamNode::GetKeyString() { return g_szParamKeyName[m_iParamType]; } CString CParamNode::GetValueString() { CString strValue("UNDEFINED"); return strValue; } bool CParamNode::OnModify() { // Can't modify CParamNode because it is the base class return false; } CString CParamNode::GetValue() { CString strValue("UNDEFINED"); return strValue; } bool CParamNode::SetValue(CString) { return true; } //Enum defines for this are in AnimationState.hpp enumerated // in the range of {0,MechWarrior4::AnimationStateEngine::AnimTypeCount} // ********************************************************************** char g_szAnimationTypeNames[][50] = { "PoseType", "FullHeightPoseHolderType", "CycleType", "SpeedCycleType", "LerpCycleType", "FullHeightSpeedBlenderCycleType", "FullHeightBlenderCycleType", "SpeedBlenderCycleType", /* "PoseType", "HeightPoseHolderType", "FullHeightPoseHolderType", "CycleType", "SpeedCycleType", "LerpCycleType", "HeightSpeedBlenderCycleType", "HeightBlenderCycleType", "FullHeightSpeedBlenderCycleType", "FullHeightBlenderCycleType", "SpeedBlenderCycleType", */ }; #define ANIMATIONTYPENAME_COUNT 11 CAnimTypeNode::CAnimTypeNode(int iType) { m_iParamType = PARAM_ANIMTYPE; m_iType = iType; m_iIndex = -1; if ((iType>0)&&(iType<=ANIMATIONTYPENAME_COUNT)) m_strName = g_szAnimationTypeNames[iType-1]; } CString CAnimTypeNode::GetValueString() { return m_strName; } bool CAnimTypeNode::OnModify() { // Can't modify AnimType from the modify button (actually shouldn't ever show up because it is filtered out return false; } CString CAnimTypeNode::GetValue() { return m_strName; } bool CAnimTypeNode::SetValue(CString) { return true; } //Enum defines for this are in AnimationState.hpp enumerated // in the range of {0,MechWarrior4::AnimCurve::CurveTypeCount} // ********************************************************************** char g_szCurveTypeNames[][40] = { " None", "LinearUpCurveType", "CubedCurveType", "EaseUpCurveType", "EdgeCurveType", "BumpCurveType", "EaseUpSplineCurveType", "CurveUpCurveType", "SpikeUpCurveType", "BellCurveType", "SpikeCurveType", "LongBumpCurveType", "BumpSpikeCurveType", "SpikeBellCurveType" }; #define CURVETYPENAMECOUNT 14 CCurveTypeNode::CCurveTypeNode(int iParamType,int iType) { m_iParamType = iParamType; m_iType = iType-1; // So that -1 is "None" or NULL // m_iIndex = -1; if ((iType>=0)&&(iType<=CURVETYPENAMECOUNT)) m_strName = g_szCurveTypeNames[iType]; InitializeClass(); curveType = m_iType; curveMin = 0.0; curveMax = 1.0; timeStart = 0.0; timeEnd = 1.0; invertTime = false; invertScale = false; } CString CCurveTypeNode::GetValueString() { return CString(g_szCurveTypeNames[m_iType+1]); } bool CCurveTypeNode::OnModify() { CModifyCurveParam dlg; dlg.m_pCurveNode = this; return (IDOK == dlg.DoModal()); } CString CCurveTypeNode::GetValue() { CString str; str.Format("%d %f %f %f %f %d %d", curveType, curveMin, curveMax, timeStart, timeEnd, invertTime, invertScale); return str; } bool CCurveTypeNode::SetValue(CString str) { if (str.GetLength()) { LoadCurve(str); m_iType = curveType; } return true; } // ********************************************************************** char g_szAttribTypeNames[][30] = { "SpeedDemandMPS", "CurrentSpeedMPS", "LocalGroundPitch", "LocalGroundRoll" }; #define ATTRIBTYPENAMECOUNT 4 CAttribTypeNode::CAttribTypeNode(int iParamType,int iType) { m_iParamType = iParamType; m_iType = iType; // So that -1 is "None" or NULL if ((iType>=0)&&(iType<=ATTRIBTYPENAMECOUNT)) m_strName = g_szAttribTypeNames[iType]; } CString CAttribTypeNode::GetValueString() { return m_strName; } bool CAttribTypeNode::OnModify() { CModifyAttribDlg dlg; dlg.m_pAttribNode = this; return (IDOK == dlg.DoModal()); } CString CAttribTypeNode::GetValue() { return m_strName; } bool CAttribTypeNode::SetValue(CString str) { void *pData = MechWarrior4::Vehicle::DefaultData; return true; } // ********************************************************************** CFloatNode::CFloatNode(int iParamType) { m_iParamType = iParamType; switch (iParamType) { case PARAM_SLOWSPEEDMULTIPLIER: { m_fValue = 1.0f; break; } default: { m_fValue = 0.0f; } } // void *pData = MechWarrior4::Vehicle::DefaultData; } CString CFloatNode::GetValueString() { CString strValue; strValue.Format("%f",m_fValue); return strValue; } bool CFloatNode::OnModify() { CModifyFloat dlg; dlg.m_pFloatNode = this; return (IDOK == dlg.DoModal()); } CString CFloatNode::GetValue() { CString strValue; strValue.Format("%f",m_fValue); return strValue; } bool CFloatNode::SetValue(CString str) { m_fValue = atof(str); return true; } // ********************************************************************** CPathNode::CPathNode(int iParamType) { m_iParamType = iParamType; m_pAnimData = NULL; } CPathNode::~CPathNode() { if (m_pAnimData) delete m_pAnimData; m_pAnimData = NULL; } CString CPathNode::GetValueString() { return m_strPath; } bool CPathNode::OnModify() { CModifyPathDlg dlg; dlg.m_pPathNode = this; return (IDOK == dlg.DoModal()); } CString CPathNode::GetValue() { if (m_strPath.GetLength()==0) { int x=1; x++; } return m_strPath; } bool CPathNode::SetValue(CString str) { m_strPath = str; if (m_pAnimData) delete m_pAnimData; m_pAnimData = new MW4Animation::AnimData(); if (str.GetLength()&&!m_pAnimData->Load(m_strPath+".mw4anim")) { // We had a problem loading the animation assert(false); delete m_pAnimData; m_pAnimData = NULL; } return true; }