summaryrefslogtreecommitdiffstats
path: root/src/animation/AnimManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/animation/AnimManager.cpp')
-rw-r--r--src/animation/AnimManager.cpp382
1 files changed, 236 insertions, 146 deletions
diff --git a/src/animation/AnimManager.cpp b/src/animation/AnimManager.cpp
index 8fb1576c..fefe56fb 100644
--- a/src/animation/AnimManager.cpp
+++ b/src/animation/AnimManager.cpp
@@ -10,6 +10,9 @@
#include "AnimBlendAssociation.h"
#include "AnimBlendAssocGroup.h"
#include "AnimManager.h"
+#include "Streaming.h"
+
+//--MIAMI: code done (except for pointless TODO)
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
@@ -78,13 +81,13 @@ AnimAssocDesc aStdAnimDescs[] = {
{ ANIM_BOMBER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
{ ANIM_HGUN_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
{ ANIM_AK_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_NOWALK },
- { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
- { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
+// { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_IDLE, ASSOC_REPEAT },
{ ANIM_FIGHT2_IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL },
{ ANIM_FIGHT_SH_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION },
@@ -260,13 +263,13 @@ char const *aStdAnimations[] = {
"bomber",
"WEAPON_hgun_rload",
"WEAPON_AK_rload",
- "FPS_PUNCH",
- "FPS_BAT",
- "FPS_UZI",
- "FPS_PUMP",
- "FPS_AK",
- "FPS_M16",
- "FPS_ROCKET",
+// "FPS_PUNCH",
+// "FPS_BAT",
+// "FPS_UZI",
+// "FPS_PUMP",
+// "FPS_AK",
+// "FPS_M16",
+// "FPS_ROCKET",
"FIGHTIDLE",
"FIGHT2IDLE",
"FIGHTsh_F",
@@ -564,8 +567,6 @@ CAnimManager::Initialise(void)
ms_numAnimations = 0;
ms_numAnimBlocks = 0;
ms_animCache.Init(25);
-
-// dumpanimdata();
}
void
@@ -573,31 +574,48 @@ CAnimManager::Shutdown(void)
{
int i;
- ms_animCache.Shutdown();
+ for(i = 0; i < NUMANIMBLOCKS; i++)
+ CStreaming::RemoveAnim(i);
for(i = 0; i < ms_numAnimations; i++)
ms_aAnimations[i].Shutdown();
+ ms_animCache.Shutdown();
+
delete[] ms_aAnimAssocGroups;
}
void
CAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier)
{
- if(!hier->compressed){
- if(hier->linkPtr){
- hier->linkPtr->Remove();
- ms_animCache.head.Insert(hier->linkPtr);
- }
+ if(hier->compressed2){
+ if(hier->totalLength == 0.0f)
+ hier->CalcTotalTimeCompressed();
}else{
- CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);
- if(link == nil){
- ms_animCache.tail.prev->item->RemoveUncompressedData();
- ms_animCache.Remove(ms_animCache.tail.prev);
- link = ms_animCache.Insert(hier);
+ if(!hier->compressed){
+ if(hier->linkPtr){
+ hier->linkPtr->Remove();
+ ms_animCache.head.Insert(hier->linkPtr);
+ }
+ }else{
+ CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);
+ if(link == nil){
+ ms_animCache.tail.prev->item->RemoveUncompressedData();
+ ms_animCache.Remove(ms_animCache.tail.prev);
+ link = ms_animCache.Insert(hier);
+ }
+ hier->linkPtr = link;
+ hier->Uncompress();
}
- hier->linkPtr = link;
- hier->Uncompress();
+ }
+}
+
+void
+CAnimManager::RemoveFromUncompressedCache(CAnimBlendHierarchy *hier)
+{
+ if(hier->linkPtr){
+ ms_animCache.Remove(hier->linkPtr);
+ hier->linkPtr = nil;
}
}
@@ -612,6 +630,73 @@ CAnimManager::GetAnimationBlock(const char *name)
return nil;
}
+int32
+CAnimManager::GetAnimationBlockIndex(const char *name)
+{
+ int i;
+
+ for(i = 0; i < ms_numAnimBlocks; i++)
+ if(strcasecmp(ms_aAnimBlocks[i].name, name) == 0)
+ return i;
+ return -1;
+}
+
+int32
+CAnimManager::RegisterAnimBlock(const char *name)
+{
+ CAnimBlock *animBlock = GetAnimationBlock(name);
+ if(animBlock == nil){
+ animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
+ strncpy(animBlock->name, name, MAX_ANIMBLOCK_NAME);
+ animBlock->numAnims = 0;
+ assert(animBlock->refCount == 0);
+ }
+ return animBlock - ms_aAnimBlocks;
+}
+
+int32
+CAnimManager::GetNumRefsToAnimBlock(int32 block)
+{
+ return ms_aAnimBlocks[block].refCount;
+}
+
+void
+CAnimManager::AddAnimBlockRef(int32 block)
+{
+ ms_aAnimBlocks[block].refCount++;
+}
+
+void
+CAnimManager::RemoveAnimBlockRefWithoutDelete(int32 block)
+{
+ ms_aAnimBlocks[block].refCount--;
+}
+
+void
+CAnimManager::RemoveAnimBlockRef(int32 block)
+{
+ ms_aAnimBlocks[block].refCount--;
+ if(ms_aAnimBlocks[block].refCount == 0)
+ CStreaming::RemoveAnim(block);
+}
+
+void
+CAnimManager::RemoveAnimBlock(int32 block)
+{
+ int i;
+ CAnimBlock *animblock;
+
+ animblock = &ms_aAnimBlocks[block];
+ debug("Removing ANIMS %s\n", animblock->name);
+ for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++)
+ if(ms_aAnimAssocGroups[i].animBlock == animblock)
+ ms_aAnimAssocGroups[i].DestroyAssociations();
+ for(i = 0; i < animblock->numAnims; i++)
+ ms_aAnimations[animblock->firstIndex + i].Shutdown();
+ animblock->isLoaded = false;
+ animblock->refCount = 0;
+}
+
CAnimBlendHierarchy*
CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
{
@@ -619,7 +704,7 @@ CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
CAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex];
for(i = 0; i < animBlock->numAnims; i++){
- if(!CGeneral::faststricmp(hier->name, name))
+ if(strcasecmp(hier->name, name) == 0)
return hier;
hier++;
}
@@ -740,23 +825,32 @@ CAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId a
void
CAnimManager::LoadAnimFiles(void)
{
- int i, j;
-
LoadAnimFile("ANIM\\PED.IFP");
-
- // Create all assoc groups
ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];
+ CreateAnimAssocGroups();
+}
+
+void
+CAnimManager::CreateAnimAssocGroups(void)
+{
+ int i, j;
+
for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++){
+ CAnimBlock *block = GetAnimationBlock(ms_aAnimAssocDefinitions[i].blockName);
+ if(block == nil || !block->isLoaded || ms_aAnimAssocGroups[i].assocList)
+ continue;
+
CBaseModelInfo *mi = CModelInfo::GetModelInfo(ms_aAnimAssocDefinitions[i].modelIndex);
RpClump *clump = (RpClump*)mi->CreateInstance();
RpAnimBlendClumpInit(clump);
CAnimBlendAssocGroup *group = &ms_aAnimAssocGroups[i];
const AnimAssocDefinition *def = &ms_aAnimAssocDefinitions[i];
+ group->groupId = i;
+ group->firstAnimId = def->animDescs[0].animId;
group->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims);
for(j = 0; j < group->numAssociations; j++)
group->GetAnimation(j)->flags |= def->animDescs[j].flags;
#ifdef PED_SKIN
- // forgot on xbox/android
if(IsClumpSkinned(clump))
RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
#endif
@@ -767,15 +861,16 @@ CAnimManager::LoadAnimFiles(void)
void
CAnimManager::LoadAnimFile(const char *filename)
{
- int fd;
- fd = CFileMgr::OpenFile(filename, "rb");
- assert(fd > 0);
- LoadAnimFile(fd, true);
- CFileMgr::CloseFile(fd);
+ RwStream *stream;
+ stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
+ assert(stream);
+ LoadAnimFile(stream, true);
+ RwStreamClose(stream, nil);
}
+//--MIAMI: done (except maybe implement some unimplemented compression?)
void
-CAnimManager::LoadAnimFile(int fd, bool compress)
+CAnimManager::LoadAnimFile(RwStream *stream, bool compress, char (*somename)[32])
{
#define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3)
struct IfpHeader {
@@ -783,127 +878,121 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
uint32 size;
};
IfpHeader anpk, info, name, dgan, cpan, anim;
- int numANPK;
char buf[256];
- int i, j, k, l;
+ int j, k, l;
float *fbuf = (float*)buf;
- CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
- if(strncmp(anpk.ident, "ANLF", 4) == 0){
- ROUNDSIZE(anpk.size);
- CFileMgr::Read(fd, buf, anpk.size);
- numANPK = *(int*)buf;
- }else if(strncmp(anpk.ident, "ANPK", 4) == 0){
- CFileMgr::Seek(fd, -8, 1);
- numANPK = 1;
+ // block name
+ RwStreamRead(stream, &anpk, sizeof(IfpHeader));
+ ROUNDSIZE(anpk.size);
+ RwStreamRead(stream, &info, sizeof(IfpHeader));
+ ROUNDSIZE(info.size);
+ RwStreamRead(stream, buf, info.size);
+ CAnimBlock *animBlock = GetAnimationBlock(buf+4);
+ if(animBlock){
+ if(animBlock->numAnims == 0){
+ animBlock->numAnims = *(int*)buf;
+ animBlock->firstIndex = ms_numAnimations;
+ }
+ }else{
+ animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
+ strncpy(animBlock->name, buf+4, MAX_ANIMBLOCK_NAME);
+ animBlock->numAnims = *(int*)buf;
+ animBlock->firstIndex = ms_numAnimations;
}
- for(i = 0; i < numANPK; i++){
- // block name
- CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
- ROUNDSIZE(anpk.size);
- CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
- ROUNDSIZE(info.size);
- CFileMgr::Read(fd, buf, info.size);
- CAnimBlock *animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
- strncpy(animBlock->name, buf+4, 24);
- animBlock->numAnims = *(int*)buf;
+ debug("Loading ANIMS %s\n", animBlock->name);
+ animBlock->isLoaded = true;
- animBlock->firstIndex = ms_numAnimations;
+ int animIndex = animBlock->firstIndex;
+ for(j = 0; j < animBlock->numAnims; j++){
+ CAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++];
- for(j = 0; j < animBlock->numAnims; j++){
- CAnimBlendHierarchy *hier = &ms_aAnimations[ms_numAnimations++];
+ // animation name
+ RwStreamRead(stream, &name, sizeof(IfpHeader));
+ ROUNDSIZE(name.size);
+ RwStreamRead(stream, buf, name.size);
+ hier->SetName(buf);
- // animation name
- CFileMgr::Read(fd, (char*)&name, sizeof(IfpHeader));
- ROUNDSIZE(name.size);
- CFileMgr::Read(fd, buf, name.size);
- hier->SetName(buf);
+ // TODO(MIAMI)? some unused crap here
+ hier->compressed = false;
+ hier->compressed2 = false;
- // DG info has number of nodes/sequences
- CFileMgr::Read(fd, (char*)&dgan, sizeof(IfpHeader));
+ // DG info has number of nodes/sequences
+ RwStreamRead(stream, (char*)&dgan, sizeof(IfpHeader));
+ ROUNDSIZE(dgan.size);
+ RwStreamRead(stream, (char*)&info, sizeof(IfpHeader));
+ ROUNDSIZE(info.size);
+ RwStreamRead(stream, buf, info.size);
+ hier->numSequences = *(int*)buf;
+ hier->sequences = new CAnimBlendSequence[hier->numSequences];
+
+ CAnimBlendSequence *seq = hier->sequences;
+ for(k = 0; k < hier->numSequences; k++, seq++){
+ // Each node has a name and key frames
+ RwStreamRead(stream, &cpan, sizeof(IfpHeader));
ROUNDSIZE(dgan.size);
- CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
- ROUNDSIZE(info.size);
- CFileMgr::Read(fd, buf, info.size);
- hier->numSequences = *(int*)buf;
- hier->sequences = new CAnimBlendSequence[hier->numSequences];
-
- CAnimBlendSequence *seq = hier->sequences;
- for(k = 0; k < hier->numSequences; k++, seq++){
- // Each node has a name and key frames
- CFileMgr::Read(fd, (char*)&cpan, sizeof(IfpHeader));
- ROUNDSIZE(dgan.size);
- CFileMgr::Read(fd, (char*)&anim, sizeof(IfpHeader));
- ROUNDSIZE(anim.size);
- CFileMgr::Read(fd, buf, anim.size);
- int numFrames = *(int*)(buf+28);
+ RwStreamRead(stream, &anim, sizeof(IfpHeader));
+ ROUNDSIZE(anim.size);
+ RwStreamRead(stream, buf, anim.size);
+ int numFrames = *(int*)(buf+28);
#ifdef PED_SKIN
- if(anim.size == 44)
- seq->SetBoneTag(*(int*)(buf+40));
+ if(anim.size == 44)
+ seq->SetBoneTag(*(int*)(buf+40));
#endif
- seq->SetName(buf);
- if(numFrames == 0)
- continue;
-
- CFileMgr::Read(fd, (char*)&info, sizeof(info));
- if(strncmp(info.ident, "KR00", 4) == 0){
- seq->SetNumFrames(numFrames, false);
- KeyFrame *kf = seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x14);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->deltaTime = fbuf[4]; // absolute time here
- }
- }else if(strncmp(info.ident, "KRT0", 4) == 0){
- seq->SetNumFrames(numFrames, true);
- KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x20);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->translation.x = fbuf[4];
- kf->translation.y = fbuf[5];
- kf->translation.z = fbuf[6];
- kf->deltaTime = fbuf[7]; // absolute time here
- }
- }else if(strncmp(info.ident, "KRTS", 4) == 0){
- seq->SetNumFrames(numFrames, true);
- KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
- for(l = 0; l < numFrames; l++, kf++){
- CFileMgr::Read(fd, buf, 0x2C);
- kf->rotation.x = -fbuf[0];
- kf->rotation.y = -fbuf[1];
- kf->rotation.z = -fbuf[2];
- kf->rotation.w = fbuf[3];
- kf->translation.x = fbuf[4];
- kf->translation.y = fbuf[5];
- kf->translation.z = fbuf[6];
- // scaling ignored
- kf->deltaTime = fbuf[10]; // absolute time here
- }
+ seq->SetName(buf);
+ if(numFrames == 0)
+ continue;
+
+ RwStreamRead(stream, &info, sizeof(info));
+ if(strncmp(info.ident, "KR00", 4) == 0){
+ seq->SetNumFrames(numFrames, false, false);
+ KeyFrame *kf = seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x14);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->deltaTime = fbuf[4]; // absolute time here
}
-
- // convert absolute time to deltas
- for(l = seq->numFrames-1; l > 0; l--){
- KeyFrame *kf1 = seq->GetKeyFrame(l);
- KeyFrame *kf2 = seq->GetKeyFrame(l-1);
- kf1->deltaTime -= kf2->deltaTime;
+ }else if(strncmp(info.ident, "KRT0", 4) == 0){
+ seq->SetNumFrames(numFrames, true, false);
+ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x20);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->translation.x = fbuf[4];
+ kf->translation.y = fbuf[5];
+ kf->translation.z = fbuf[6];
+ kf->deltaTime = fbuf[7]; // absolute time here
+ }
+ }else if(strncmp(info.ident, "KRTS", 4) == 0){
+ seq->SetNumFrames(numFrames, true, false);
+ KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
+ for(l = 0; l < numFrames; l++, kf++){
+ RwStreamRead(stream, buf, 0x2C);
+ kf->rotation.x = -fbuf[0];
+ kf->rotation.y = -fbuf[1];
+ kf->rotation.z = -fbuf[2];
+ kf->rotation.w = fbuf[3];
+ kf->translation.x = fbuf[4];
+ kf->translation.y = fbuf[5];
+ kf->translation.z = fbuf[6];
+ // scaling ignored
+ kf->deltaTime = fbuf[10]; // absolute time here
}
}
-
- hier->RemoveQuaternionFlips();
- if(compress)
- hier->RemoveUncompressedData();
- else
- hier->CalcTotalTime();
}
+
+ hier->RemoveQuaternionFlips();
+ hier->CalcTotalTime();
}
+ if(animIndex > ms_numAnimations)
+ ms_numAnimations = animIndex;
}
void
@@ -913,5 +1002,6 @@ CAnimManager::RemoveLastAnimFile(void)
ms_numAnimBlocks--;
ms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex;
for(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++)
- ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].RemoveAnimSequences();
+ ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].Shutdown();
+ ms_aAnimBlocks[ms_numAnimBlocks].isLoaded = false;
}