Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

728 lines
18 KiB
C++

// 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 <assert.h>
#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(iKey<PARAM_COUNT);
CObject *pObj = m_mapParams[iKey];
CParamNode *pOldNode = NULL;
if (pObj)
pOldNode = (CParamNode *)pObj;
m_mapParams[iKey] = pNode;
return pOldNode;
}
bool CAnimNode::LoadState(Page *page)
{
CAnimTypeNode *pType = (CAnimTypeNode *)GetParam(PARAM_ANIMTYPE);
CreateAnimTypeParams(pType,page);
return true;
}
CParamNode *CAnimNode::CreateParam(int iType,Page *page)
{
CParamNode *pNode = NULL;
switch (iType)
{
case PARAM_ANIMTYPE:
return NULL; // This type is not a created parameter
case PARAM_START:
case PARAM_POSITION:
case PARAM_SLOWSPEEDMULTIPLIER:
case PARAM_LERPTIME:
{
pNode = new CFloatNode(iType);
break;
}
case PARAM_ANIM:
case PARAM_FASTANIM:
case PARAM_SLOWANIM:
case PARAM_SLOWUPANIM:
case PARAM_SLOWEVENANIM:
case PARAM_SLOWDOWNANIM:
case PARAM_FASTUPANIM:
case PARAM_FASTEVENANIM:
case PARAM_FASTDOWNANIM:
case PARAM_UPANIM:
case PARAM_EVENANIM:
case PARAM_DOWNANIM:
case PARAM_LEFTANIM:
case PARAM_RIGHTANIM:
case PARAM_SLOWLEFTANIM:
case PARAM_SLOWRIGHTANIM:
case PARAM_FASTLEFTANIM:
case PARAM_FASTRIGHTANIM:
{
pNode = new CPathNode(iType);
break;
}
case PARAM_STARTOVERLAPCURVE:
case PARAM_ENDOVERLAPCURVE:
{
pNode = new CCurveTypeNode(iType,0);
break;
}
case PARAM_TRANSITIONSTART:
case PARAM_PLAYOLDSTATETILL:
case PARAM_OVERRIDENEWSTATEPOSITION:
case PARAM_STARTNEWSTATE:
{
pNode = new CFloatNode(iType);
break;
}
case PARAM_SPEEDATTRIB:
case PARAM_PITCHATTRIB:
case PARAM_ROLLATTRIB:
{
pNode = new CAttribTypeNode(iType,0);
break;
}
default:
{
}
}
if (pNode)
{
CString strValue;
if (page)
{
const char *pData = NULL;
if (page->GetEntry(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;x<iSize;x++)
{
int iType = g_arrAnimTypeParams[x][0];
int iParam = g_arrAnimTypeParams[x][1];
if (pNode->m_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;
}