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.
886 lines
22 KiB
C++
886 lines
22 KiB
C++
//===========================================================================//
|
|
// File: AnimationState.cpp
|
|
//---------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ---------------------------------------------------------- //
|
|
// 02/23/999 JSE Inital coding
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1998, Microsoft Corp. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#include "MW4Headers.hpp"
|
|
|
|
|
|
#include "Vehicle.hpp"
|
|
#include "AnimationState.hpp"
|
|
|
|
//#############################################################################
|
|
//########################## AnimationStateEngine ########################
|
|
//#############################################################################
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
int AnimationStateEngine::GetAnimHolderType(const char *type_name)
|
|
{
|
|
Check_Pointer(type_name);
|
|
|
|
if (!_stricmp(type_name, "PoseType"))
|
|
{
|
|
return PoseType;
|
|
}
|
|
else if (!_stricmp(type_name, "CycleType"))
|
|
{
|
|
return CycleType;
|
|
}
|
|
else if (!_stricmp(type_name, "SpeedCycleType"))
|
|
{
|
|
return SpeedCycleType;
|
|
}
|
|
else if (!_stricmp(type_name, "LerpCycleType"))
|
|
{
|
|
return LerpCycleType;
|
|
}
|
|
else if (!_stricmp(type_name, "FullHeightSpeedBlenderCycleType"))
|
|
{
|
|
return FullHeightSpeedBlenderCycleType;
|
|
}
|
|
else if (!_stricmp(type_name, "FullHeightBlenderCycleType"))
|
|
{
|
|
return FullHeightBlenderCycleType;
|
|
}
|
|
else if (!_stricmp(type_name, "SpeedBlenderCycleType"))
|
|
{
|
|
return SpeedBlenderCycleType;
|
|
}
|
|
else if (!_stricmp(type_name, "FullHeightPoseHolderType"))
|
|
{
|
|
return FullHeightPoseHolderType;
|
|
}
|
|
else
|
|
{
|
|
STOP(("AnimationStateEngine::GetAnimHolderType : %s Not a valid type", type_name));
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
size_t AnimationStateEngine::GetAnimHolderSize(int type)
|
|
{
|
|
Verify(type < AnimTypeCount);
|
|
Verify(type > 0);
|
|
|
|
switch (type)
|
|
{
|
|
case PoseType:
|
|
return sizeof(PoseHolder);
|
|
|
|
case CycleType:
|
|
return sizeof(CycleHolder);
|
|
|
|
case SpeedCycleType:
|
|
return sizeof(SpeedCycleHolder);
|
|
|
|
case LerpCycleType:
|
|
return sizeof(LerpCycleHolder);
|
|
|
|
case FullHeightSpeedBlenderCycleType:
|
|
return sizeof(FullHeightSpeedBlenderCycleHolder);
|
|
|
|
case FullHeightBlenderCycleType:
|
|
return sizeof(FullHeightBlenderCycleHolder);
|
|
|
|
case SpeedBlenderCycleType:
|
|
return sizeof(SpeedBlenderCycleHolder);
|
|
|
|
case FullHeightPoseHolderType:
|
|
return sizeof(FullHeightPoseHolder);
|
|
|
|
|
|
default:
|
|
STOP(("AnimationStateEngine::GetAnimHolderSize - All types not defined!"));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
AnimHolder *AnimationStateEngine::MakeAnimHolder(int type)
|
|
{
|
|
Verify(type < AnimTypeCount);
|
|
Verify(type > 0);
|
|
|
|
switch (type)
|
|
{
|
|
case PoseType:
|
|
return new PoseHolder;
|
|
|
|
case CycleType:
|
|
return new CycleHolder;
|
|
|
|
case SpeedCycleType:
|
|
return new SpeedCycleHolder();
|
|
|
|
case LerpCycleType:
|
|
return new LerpCycleHolder();
|
|
|
|
case FullHeightSpeedBlenderCycleType:
|
|
return new FullHeightSpeedBlenderCycleHolder();
|
|
|
|
case FullHeightBlenderCycleType:
|
|
return new FullHeightBlenderCycleHolder();
|
|
|
|
case SpeedBlenderCycleType:
|
|
return new SpeedBlenderCycleHolder();
|
|
|
|
case FullHeightPoseHolderType:
|
|
return new FullHeightPoseHolder();
|
|
|
|
default:
|
|
STOP(("AnimationStateEngine::MakeAnimHolder - All types not defined!"));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
MW4Animation::AnimInstance *AnimationStateEngine::LoadOrMakeAnimInstance(const char *animation_name)
|
|
{
|
|
Stuff::ChainIteratorOf<MW4Animation::AnimInstance*> iterator(&animInstancesLoaded);
|
|
MW4Animation::AnimInstance *anim_instance;
|
|
|
|
while ((anim_instance = iterator.ReadAndNext()) != NULL)
|
|
{
|
|
if(!_stricmp(anim_instance->animData->animHeaderBlock->animationName, animation_name))
|
|
{
|
|
return anim_instance;
|
|
}
|
|
}
|
|
|
|
// make anim_instance
|
|
anim_instance = MW4Animation::AnimInstanceManager::Anim_Instance_Manager->MakeAnimInstance(
|
|
animation_name,
|
|
(MW4Animation::AnimInstanceManager::UserDefinedSearchFunction)Vehicle::FindChildMoverIndexUserData,
|
|
(void *)vehicleParent
|
|
);
|
|
|
|
Check_Object(anim_instance);
|
|
Check_Object(anim_instance);
|
|
|
|
animInstancesLoaded.Add(anim_instance);
|
|
|
|
return anim_instance;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void AnimationStateEngine::LoadScript(const char *filename, bool run_minimal)
|
|
{
|
|
|
|
//SPEW(("jerryeds", "LOAD SCRIPT : %s", filename));
|
|
|
|
Verify(!alreadyLoaded);
|
|
alreadyLoaded = true;
|
|
|
|
// open the notation file
|
|
Check_Pointer(filename);
|
|
|
|
gos_PushCurrentHeap(g_AnimScript);
|
|
|
|
Adept::Resource anim_res(filename);
|
|
if(!anim_res.DoesResourceExist())
|
|
{
|
|
SPEW((0,"AnimationScript not in props.build : %s", filename));
|
|
return;
|
|
}
|
|
anim_res.LoadData();
|
|
|
|
NotationFile script_notefile(&anim_res);
|
|
|
|
// spin thru and load appropriate type of anim holder
|
|
NotationFile::PageIterator *pages = script_notefile.MakePageIterator();
|
|
Check_Object(pages);
|
|
|
|
|
|
int anim_holder_count = 0;
|
|
int total_curve_count = 0;
|
|
|
|
Page *page;
|
|
while ((page = pages->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(page);
|
|
const char* anim_state_name = page->GetName();
|
|
Check_Pointer(anim_state_name);
|
|
|
|
//SPEW(("jerryeds", "CREATE : %s", anim_state_name));
|
|
|
|
// load the states
|
|
if (strstr(anim_state_name, "::") == NULL)
|
|
{
|
|
// load the state based off of type (anim, transition or expression)
|
|
AnimationState *new_anim_state = new AnimationState(this);
|
|
Check_Object(new_anim_state);
|
|
|
|
new_anim_state->PreLoad(page);
|
|
anim_holder_count += new_anim_state->GetAnimHolderCount(page);
|
|
total_curve_count += new_anim_state->GetCurveCount(page);
|
|
|
|
animStatesLoaded.Add(new_anim_state);
|
|
|
|
}
|
|
else if (strstr(anim_state_name, "::") != NULL) // load the transitions
|
|
{
|
|
// load the transition based off of type (anim, transition or expression)
|
|
TransitionState *new_anim_state = new TransitionState(this);
|
|
Check_Object(new_anim_state);
|
|
|
|
new_anim_state->PreLoad(page);
|
|
anim_holder_count += new_anim_state->GetAnimHolderCount(page);
|
|
total_curve_count += new_anim_state->GetCurveCount(page);
|
|
|
|
transitionsLoaded.Add(new_anim_state);
|
|
|
|
}
|
|
else
|
|
{
|
|
STOP(("AnimationStateEngine::LoadScript : INVALID CODE - SHOULD NEVER REACH HERE"));
|
|
}
|
|
}
|
|
|
|
//allocate curves and animholders
|
|
|
|
animHoldersCount = anim_holder_count;
|
|
Verify(animHoldersCount > 0);
|
|
|
|
animHolderArray = new AnimHolder*[animHoldersCount];
|
|
Register_Pointer(animHolderArray);
|
|
|
|
|
|
animCurvesCount = total_curve_count;
|
|
if (animCurvesCount != 0)
|
|
{
|
|
animCurves = new AnimCurve[animCurvesCount];
|
|
Register_Pointer(animCurves);
|
|
}
|
|
|
|
// Now load each animHolder which will:
|
|
// load each animinstances
|
|
// load the curves
|
|
|
|
|
|
|
|
int current_curve = 0;
|
|
int current_holder = 0;
|
|
|
|
Stuff::ChainIteratorOf<AnimationState*> s_iterator(&animStatesLoaded);
|
|
Stuff::ChainIteratorOf<TransitionState*> t_iterator(&transitionsLoaded);
|
|
|
|
|
|
AnimationState *current_state;
|
|
AnimationState *current_transition;
|
|
|
|
pages->First();
|
|
while ((page = pages->ReadAndNext()) != NULL)
|
|
{
|
|
const char* anim_state_name = page->GetName();
|
|
Check_Pointer(anim_state_name);
|
|
|
|
//SPEW(("jerryeds", "LOAD : %s", anim_state_name));
|
|
|
|
if (strstr(anim_state_name, "::") == NULL)
|
|
{
|
|
current_state = s_iterator.ReadAndNext();
|
|
Check_Object(current_state);
|
|
|
|
current_state->LoadScriptEntry(page, current_holder, current_curve, run_minimal);
|
|
current_state->CalculateChainTimes();
|
|
current_state->LoadIterators(run_minimal);
|
|
}
|
|
else if (strstr(anim_state_name, "::") != NULL)
|
|
{
|
|
current_transition = t_iterator.ReadAndNext();
|
|
Check_Object(current_transition);
|
|
|
|
current_transition->LoadScriptEntry(page, current_holder, current_curve, run_minimal);
|
|
current_transition->CalculateChainTimes();
|
|
current_transition->LoadIterators(run_minimal);
|
|
}
|
|
else
|
|
{
|
|
STOP(("AnimationStateEngine::LoadScript : INVALID CODE - SHOULD NEVER REACH HERE"));
|
|
}
|
|
}
|
|
|
|
Verify(s_iterator.GetCurrent() == NULL);
|
|
Verify(t_iterator.GetCurrent() == NULL);
|
|
|
|
|
|
Check_Object(pages);
|
|
delete pages;
|
|
|
|
anim_res.UnloadData();
|
|
|
|
gos_PopCurrentHeap();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void AnimationState::PreLoad(Page *page)
|
|
{
|
|
Check_Object(page);
|
|
Check_Object(animStateEngine);
|
|
|
|
// look up state
|
|
StateEngine::ClassData *state_class_data;
|
|
state_class_data = animStateEngine->GetClassData();
|
|
Check_Object(state_class_data);
|
|
|
|
const StateEngine::StateEntry *state_entry = state_class_data->FindStateEntry(page->GetName());
|
|
|
|
if(state_entry != NULL)
|
|
{
|
|
Check_Object(state_entry);
|
|
myState = state_entry->stateNumber;
|
|
}
|
|
else
|
|
{
|
|
myState = -1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void TransitionState::PreLoad(Page *page)
|
|
{
|
|
|
|
Check_Object(page);
|
|
|
|
char *copy_name;
|
|
char *first_name;
|
|
char *second_name;
|
|
|
|
const char* page_name = page->GetName();
|
|
Check_Pointer(page_name);
|
|
copy_name = new char [strlen(page_name)+1];
|
|
Register_Pointer(copy_name);
|
|
|
|
Str_Copy(copy_name, page_name, strlen(page_name)+1);
|
|
|
|
first_name = copy_name;
|
|
second_name = strstr(copy_name, "::");
|
|
*second_name = '\0';
|
|
second_name++;
|
|
*second_name = '\0';
|
|
second_name++;
|
|
|
|
|
|
// look up state
|
|
StateEngine::ClassData *state_class_data;
|
|
state_class_data = animStateEngine->GetClassData();
|
|
Check_Object(state_class_data);
|
|
|
|
const StateEngine::StateEntry *state_entry =
|
|
state_class_data->FindStateEntry(first_name);
|
|
|
|
if(state_entry != NULL)
|
|
{
|
|
Check_Object(state_entry);
|
|
myState = state_entry->stateNumber;
|
|
}
|
|
else
|
|
{
|
|
myState = -1;
|
|
}
|
|
|
|
state_entry =
|
|
state_class_data->FindStateEntry(second_name);
|
|
|
|
if(state_entry != NULL)
|
|
{
|
|
Check_Object(state_entry);
|
|
transitionToState = state_entry->stateNumber;
|
|
}
|
|
else
|
|
{
|
|
transitionToState = -1;
|
|
}
|
|
|
|
|
|
const char *entry_data;
|
|
|
|
page->GetEntry("TransitionStart", &entry_data, true);
|
|
if(!_strnicmp(entry_data, "any", 3))
|
|
{
|
|
transitionStart = StartAnyWhereToken;
|
|
}
|
|
else
|
|
{
|
|
transitionStart = AtoF(entry_data);
|
|
Verify(transitionStart >= 0.0f);
|
|
Verify(transitionStart <= 1.0f);
|
|
}
|
|
|
|
|
|
page->GetEntry("PlayOldStateTill", &playOldStateTill, true);
|
|
page->GetEntry("StartNewState", &startNewState, true);
|
|
|
|
const char *override_text;
|
|
page->GetEntry("OverrideNewStatePosition", &override_text, true);
|
|
if (!_stricmp(override_text, "default"))
|
|
{
|
|
overrideNewStatePosition = -1;
|
|
}
|
|
else
|
|
{
|
|
overrideNewStatePosition = AtoF(override_text);
|
|
Verify(overrideNewStatePosition >= 0.0f);
|
|
Verify(overrideNewStatePosition <= 1.0f);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Verify(playOldStateTill >= 0.0f);
|
|
Verify(playOldStateTill <= 1.0f);
|
|
Verify(startNewState >= 0.0f);
|
|
Verify(startNewState <= 1.0f);
|
|
Verify(startNewState >= playOldStateTill); // these are only allowed to *touch* not overlap
|
|
|
|
Unregister_Pointer(copy_name);
|
|
delete[] copy_name;
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void AnimationState::LoadScriptEntry(Page *page, int ¤t_holder, int ¤t_curve, bool run_minimal)
|
|
{
|
|
Check_Object(page);
|
|
Check_Object(animStateEngine);
|
|
|
|
|
|
|
|
// load all my children
|
|
Page::NoteIterator *notes = page->MakeNoteIterator();
|
|
Check_Object(notes);
|
|
|
|
|
|
firstAnim = current_holder;
|
|
animCount = 0;
|
|
|
|
NameList *anim_param_list = NULL;
|
|
|
|
if (!page->GetEntry("CarryOver", &carryOver))
|
|
{
|
|
carryOver = true;
|
|
}
|
|
|
|
Note *note;
|
|
while ((note = notes->ReadAndNext()) != NULL)
|
|
{
|
|
Check_Object(note);
|
|
const char* anim_type_name = note->GetName();
|
|
Check_Pointer(anim_type_name);
|
|
const char* note_data;
|
|
note->GetEntry(¬e_data);
|
|
|
|
if (!_stricmp(anim_type_name, "AnimType"))
|
|
{
|
|
|
|
// load based off of list
|
|
if (anim_param_list != NULL)
|
|
{
|
|
|
|
LoadAnimHolder(anim_param_list, firstAnim + animCount, current_curve, run_minimal);
|
|
Check_Object(anim_param_list);
|
|
delete anim_param_list;
|
|
anim_param_list = NULL;
|
|
++animCount;
|
|
}
|
|
|
|
|
|
Verify(anim_param_list == NULL);
|
|
anim_param_list = new NameList();
|
|
Check_Object(anim_param_list);
|
|
|
|
anim_param_list->AddEntry(note->GetName(), (void*)note_data);
|
|
|
|
}
|
|
else
|
|
{
|
|
// in effect this spins till it gets the first animtype
|
|
if (anim_param_list != NULL)
|
|
{
|
|
anim_param_list->AddEntry(note->GetName(), (void*)note_data);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (anim_param_list != NULL)
|
|
{
|
|
LoadAnimHolder(anim_param_list, firstAnim + animCount, current_curve, run_minimal);
|
|
Check_Object(anim_param_list);
|
|
delete anim_param_list;
|
|
anim_param_list = NULL;
|
|
++animCount;
|
|
}
|
|
|
|
Verify(animCount > 0);
|
|
|
|
//SPEW(("jerryeds", "LOAD %s : %d", page->GetName(), animCount));
|
|
|
|
|
|
Check_Object(notes);
|
|
delete notes;
|
|
|
|
current_holder += animCount;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void TransitionState::LoadScriptEntry(Page *page, int ¤t_holder, int ¤t_curve, bool run_minimal)
|
|
{
|
|
Check_Object(page);
|
|
Check_Object(animStateEngine);
|
|
|
|
AnimationState::LoadScriptEntry(page, current_holder, current_curve, run_minimal);
|
|
|
|
//now load my curves...
|
|
const char *curve_param;
|
|
|
|
page->GetEntry("StartOverlapCurve", &curve_param, true);
|
|
startOverlapCurve = current_curve;
|
|
animStateEngine->animCurves[current_curve].LoadCurve(curve_param);
|
|
current_curve++;
|
|
Verify(current_curve <= animStateEngine->animCurvesCount);
|
|
|
|
page->GetEntry("EndOverlapCurve", &curve_param, true);
|
|
endOverlapCurve = current_curve;
|
|
animStateEngine->animCurves[current_curve].LoadCurve(curve_param);
|
|
current_curve++;
|
|
Verify(current_curve <= animStateEngine->animCurvesCount);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void AnimationState::LoadAnimHolder(NameList *param_list, int anim_holder_count, int ¤t_curve, bool run_minimal)
|
|
{
|
|
// This name list has only the animation parameters and nothing else.
|
|
// Now we can use the search interface to make it work pretty
|
|
|
|
|
|
// figure out the type
|
|
|
|
NameList::Entry *page = param_list->FindEntry("AnimType");
|
|
Check_Object(page);
|
|
|
|
int type = animStateEngine->GetAnimHolderType(page->GetChar());
|
|
|
|
// load generic data
|
|
Verify(anim_holder_count < animStateEngine->animHoldersCount);
|
|
|
|
AnimHolder *anim_holder = animStateEngine->MakeAnimHolder(type);
|
|
animStateEngine->animHolderArray[anim_holder_count] = anim_holder;
|
|
Check_Pointer(animStateEngine->animHolderArray[anim_holder_count]);
|
|
Register_Pointer(animStateEngine->animHolderArray[anim_holder_count]);
|
|
|
|
|
|
anim_holder->animType = type;
|
|
|
|
page = param_list->FindEntry("Start");
|
|
Check_Object(page);
|
|
const char *contents = page->GetChar();
|
|
|
|
if (!_strnicmp(contents, "after", 5))
|
|
{
|
|
anim_holder->startDelay = 0.0f;
|
|
sscanf(contents, "after %d", &anim_holder->waitForAnim);
|
|
}
|
|
else
|
|
{
|
|
anim_holder->waitForAnim = AnimHolder::NoStartAfterToken;
|
|
anim_holder->startDelay = page->GetAtof();
|
|
}
|
|
|
|
|
|
animStateEngine->animHolderArray[anim_holder_count]->Load(animStateEngine, param_list, run_minimal);
|
|
|
|
|
|
|
|
anim_holder->firstCurve = current_curve;
|
|
anim_holder->curveCount = 0;
|
|
|
|
//load the curves
|
|
page = param_list->GetFirstEntry();
|
|
|
|
while(page != NULL)
|
|
{
|
|
if (!_stricmp(page->GetName(), "Curve"))
|
|
{
|
|
//load er up
|
|
animStateEngine->animCurves[anim_holder->firstCurve+anim_holder->curveCount].LoadCurve(page->GetChar());
|
|
|
|
anim_holder->curveCount++;
|
|
}
|
|
else if(!_stricmp(page->GetName(), "CurveMask"))
|
|
{
|
|
Verify(anim_holder->curveCount != 0);
|
|
// verify we already have a curve...
|
|
|
|
animStateEngine->animCurves[anim_holder->firstCurve+anim_holder->curveCount].LoadMasks(page->GetChar());
|
|
|
|
}
|
|
page = page->GetNextEntry();
|
|
}
|
|
|
|
|
|
current_curve += anim_holder->curveCount;
|
|
Verify(current_curve <= animStateEngine->animCurvesCount);
|
|
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
size_t AnimationState::GetAnimHolderCount(Page *page)
|
|
{
|
|
Check_Object(page);
|
|
|
|
// spin thru and load appropriate type of anim holder
|
|
ChainOf<Note*> *type_chain = page->MakeNoteChain("AnimType");
|
|
Check_Object(type_chain);
|
|
Page::NoteIterator pages(type_chain);
|
|
|
|
int anim_holder_count = pages.GetSize();
|
|
|
|
Check_Object(type_chain);
|
|
delete type_chain;
|
|
|
|
return anim_holder_count;
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
int AnimationState::GetCurveCount(Page *page)
|
|
{
|
|
Check_Object(page);
|
|
|
|
// spin thru and load appropriate type of anim holder
|
|
ChainOf<Note*> *curve_chain = page->MakeNoteChain("Curve");
|
|
Check_Object(curve_chain);
|
|
Page::NoteIterator pages(curve_chain);
|
|
|
|
int curve_count = pages.GetSize();
|
|
|
|
Check_Object(curve_chain);
|
|
delete curve_chain;
|
|
|
|
|
|
return curve_count;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
int TransitionState::GetCurveCount(Page *page)
|
|
{
|
|
return AnimationState::GetCurveCount(page) + 2;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
|
|
//#################################### BIG NOTE ######################################
|
|
// This is kind of tricky.
|
|
// The problem lies in the fact that these guys can dynamicly scale
|
|
// themselevs. Which makes calculating this part a wee bit hard.
|
|
|
|
// It seems as if the solution is to treat each
|
|
// animation or chain of animations independantly
|
|
// when calculating the state position we figure
|
|
// out how much time has gone by since the state
|
|
// started. Based off of that we dead reckon each
|
|
// chain of animations from current position to finish.
|
|
// based off of that we will have the "longest" animation
|
|
// chain. Then we simply see where it is percentage wise.
|
|
|
|
// in order to do this we must have each animation know if it in
|
|
// a chain and if so how much percentage of it is used for the anim
|
|
|
|
// This is will be a slow function if there are a lot of
|
|
// chained animations
|
|
|
|
void AnimationState::CalculateChainTimes()
|
|
{
|
|
|
|
// we are measuring total time of chained animations
|
|
Verify(animCount > 0);
|
|
|
|
|
|
for (int i = 0; i < animCount; ++i)
|
|
{
|
|
AnimHolder *anim_holder = animStateEngine->animHolderArray[i+firstAnim];
|
|
Check_Pointer(anim_holder);
|
|
|
|
if (anim_holder->waitForAnim != AnimHolder::NoStartAfterToken)
|
|
{
|
|
// we have a chain here...
|
|
// recurse the chain and adjust...
|
|
|
|
// this algorithim depends on order so...
|
|
Verify(anim_holder->waitForAnim < i);
|
|
Verify(anim_holder->waitForAnim >= 0);
|
|
Verify(anim_holder->waitForAnim < animCount);
|
|
|
|
Stuff::Scalar total_time = 0.0f;
|
|
RecurseAndCalculateChainTime(total_time, i);
|
|
|
|
}
|
|
else
|
|
{
|
|
anim_holder->startPercentage = 0.0f;
|
|
anim_holder->percentageOfChain = 1.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void AnimationState::RecurseAndCalculateChainTime(Stuff::Scalar &total_time, int current_anim)
|
|
{
|
|
AnimHolder *anim_holder = animStateEngine->animHolderArray[current_anim+firstAnim];
|
|
Check_Pointer(anim_holder);
|
|
|
|
total_time += anim_holder->GetTimeTotal();
|
|
|
|
|
|
if (anim_holder->waitForAnim != AnimHolder::NoStartAfterToken)
|
|
{
|
|
Verify(anim_holder->waitForAnim < current_anim);
|
|
Verify(anim_holder->waitForAnim >= 0);
|
|
Verify(anim_holder->waitForAnim < animCount);
|
|
RecurseAndCalculateChainTime(total_time, anim_holder->waitForAnim);
|
|
}
|
|
|
|
// depth first iteratation
|
|
// so we start at the bottom of the list
|
|
|
|
|
|
// calculate our percentage of the total time..
|
|
if (!Small_Enough(total_time))
|
|
{
|
|
if (!Small_Enough(anim_holder->GetTimeTotal()))
|
|
{
|
|
anim_holder->percentageOfChain = anim_holder->GetTimeTotal() / total_time;
|
|
}
|
|
else
|
|
{
|
|
anim_holder->percentageOfChain = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
anim_holder->percentageOfChain = 0;
|
|
}
|
|
|
|
|
|
// calculate our start position
|
|
if (anim_holder->waitForAnim == AnimHolder::NoStartAfterToken)
|
|
{
|
|
// first one starts at zero (internal delay is handled by the holder)
|
|
anim_holder->startPercentage = 0.0f;
|
|
}
|
|
else
|
|
{
|
|
// our start is the waiting states start plus his percentage
|
|
AnimHolder *wait_anim_holder = animStateEngine->animHolderArray[anim_holder->waitForAnim+firstAnim];
|
|
Check_Pointer(wait_anim_holder);
|
|
anim_holder->startPercentage = wait_anim_holder->startPercentage + wait_anim_holder->percentageOfChain;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
AnimCurve::AnimCurve()
|
|
{
|
|
curveType = NULLAnimType;
|
|
|
|
curveMin = -1.0f;
|
|
curveMax = -1.0f;
|
|
timeStart = -1.0f;
|
|
timeEnd = -1.0f;
|
|
|
|
invertTime = false;
|
|
invertScale = false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void AnimCurve::LoadCurve(const char *curve_text)
|
|
{
|
|
int invert_time_test = -1;
|
|
int invert_scale_test = -1;
|
|
|
|
sscanf(curve_text, "%d %f %f %f %f %d %d", &curveType, &curveMin, &curveMax, &timeStart, &timeEnd, &invert_time_test, &invert_scale_test);
|
|
// sscanf(curve_text, "%f", &curveMin);
|
|
// sscanf(curve_text, "%f", &curveMax);
|
|
// sscanf(curve_text, "%f", &timeStart);
|
|
// sscanf(curve_text, "%f", &timeEnd);
|
|
// sscanf(curve_text, "%d", &invert_time_test);
|
|
// sscanf(curve_text, "%d", &invert_scale_test);
|
|
|
|
Verify(curveType >= 0 && curveType < CurveTypeCount);
|
|
Verify(curveMin >= 0.0f && curveMin <= 1.0f);
|
|
Verify(curveMax >= 0.0f && curveMax <= 1.0f);
|
|
Verify(timeStart >= 0.0f && timeStart <= 1.0f);
|
|
Verify(timeEnd >= 0.0f && timeEnd <= 1.0f);
|
|
Verify(invert_time_test == 0 || invert_time_test == 1);
|
|
Verify(invert_scale_test == 0 || invert_scale_test == 1);
|
|
|
|
invertTime = (invert_time_test)?true:false;
|
|
invertScale = (invert_scale_test)?true:false;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
void AnimCurve::LoadMasks(const char *mask_text)
|
|
{
|
|
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|