mirror of
https://git.rip/DMCA_FUCKER/re3.git
synced 2024-12-24 18:00:01 +00:00
Merge remote-tracking branch 'upstream/miami' into miami
This commit is contained in:
commit
756e4dd068
|
@ -3,16 +3,23 @@
|
||||||
#include "ctype.h"
|
#include "ctype.h"
|
||||||
|
|
||||||
#include "General.h"
|
#include "General.h"
|
||||||
|
#include "RwHelper.h"
|
||||||
|
#include "ModelIndices.h"
|
||||||
#include "ModelInfo.h"
|
#include "ModelInfo.h"
|
||||||
#include "AnimManager.h"
|
#include "AnimManager.h"
|
||||||
#include "RpAnimBlend.h"
|
#include "RpAnimBlend.h"
|
||||||
#include "AnimBlendAssociation.h"
|
#include "AnimBlendAssociation.h"
|
||||||
#include "AnimBlendAssocGroup.h"
|
#include "AnimBlendAssocGroup.h"
|
||||||
|
|
||||||
|
//--MIAMI: file done
|
||||||
|
|
||||||
CAnimBlendAssocGroup::CAnimBlendAssocGroup(void)
|
CAnimBlendAssocGroup::CAnimBlendAssocGroup(void)
|
||||||
{
|
{
|
||||||
|
animBlock = nil;
|
||||||
assocList = nil;
|
assocList = nil;
|
||||||
numAssociations = 0;
|
numAssociations = 0;
|
||||||
|
firstAnimId = 0;
|
||||||
|
groupId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAnimBlendAssocGroup::~CAnimBlendAssocGroup(void)
|
CAnimBlendAssocGroup::~CAnimBlendAssocGroup(void)
|
||||||
|
@ -43,6 +50,7 @@ CAnimBlendAssocGroup::GetAnimation(const char *name)
|
||||||
for(i = 0; i < numAssociations; i++)
|
for(i = 0; i < numAssociations; i++)
|
||||||
if(!CGeneral::faststricmp(assocList[i].hierarchy->name, name))
|
if(!CGeneral::faststricmp(assocList[i].hierarchy->name, name))
|
||||||
return &assocList[i];
|
return &assocList[i];
|
||||||
|
debug("\n\nCan't find the fucking animation %s\n\n\n", name);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +110,15 @@ GetModelFromName(const char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
CBaseModelInfo *mi;
|
CBaseModelInfo *mi;
|
||||||
|
char playername[32];
|
||||||
|
|
||||||
|
if(strncasecmp(name, "CSplay", 6) == 0 &&
|
||||||
|
strncasecmp(CModelInfo::GetModelInfo(MI_PLAYER)->GetName(), "ig", 2) == 0){
|
||||||
|
strcpy(playername, CModelInfo::GetModelInfo(MI_PLAYER)->GetName());
|
||||||
|
playername[0] = 'C';
|
||||||
|
playername[1] = 'S';
|
||||||
|
name = playername;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < MODELINFOSIZE; i++){
|
for(i = 0; i < MODELINFOSIZE; i++){
|
||||||
mi = CModelInfo::GetModelInfo(i);
|
mi = CModelInfo::GetModelInfo(i);
|
||||||
|
@ -118,8 +135,7 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name)
|
||||||
int i;
|
int i;
|
||||||
CAnimBlock *animBlock;
|
CAnimBlock *animBlock;
|
||||||
|
|
||||||
if(assocList)
|
DestroyAssociations();
|
||||||
DestroyAssociations();
|
|
||||||
|
|
||||||
animBlock = CAnimManager::GetAnimationBlock(name);
|
animBlock = CAnimManager::GetAnimationBlock(name);
|
||||||
assocList = new CAnimBlendAssociation[animBlock->numAnims];
|
assocList = new CAnimBlendAssociation[animBlock->numAnims];
|
||||||
|
@ -128,13 +144,18 @@ CAnimBlendAssocGroup::CreateAssociations(const char *name)
|
||||||
for(i = 0; i < animBlock->numAnims; i++){
|
for(i = 0; i < animBlock->numAnims; i++){
|
||||||
CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(animBlock->firstIndex + i);
|
CAnimBlendHierarchy *anim = CAnimManager::GetAnimation(animBlock->firstIndex + i);
|
||||||
CBaseModelInfo *model = GetModelFromName(anim->name);
|
CBaseModelInfo *model = GetModelFromName(anim->name);
|
||||||
assert(model);
|
if(model){
|
||||||
printf("Associated anim %s with model %s\n", anim->name, model->GetName());
|
debug("Associated anim %s with model %s\n", anim->name, model->GetName());
|
||||||
RpClump *clump = (RpClump*)model->CreateInstance();
|
RpClump *clump = (RpClump*)model->CreateInstance();
|
||||||
RpAnimBlendClumpInit(clump);
|
RpAnimBlendClumpInit(clump);
|
||||||
assocList[i].Init(clump, anim);
|
assocList[i].Init(clump, anim);
|
||||||
RpClumpDestroy(clump);
|
if(IsClumpSkinned(clump))
|
||||||
assocList[i].animId = i;
|
RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
|
||||||
|
RpClumpDestroy(clump);
|
||||||
|
assocList[i].animId = firstAnimId + i;
|
||||||
|
assocList[i].groupId = groupId;
|
||||||
|
}else
|
||||||
|
debug("\n\nCANNOT FIND MODELINFO WITH NAME %s\n\n\n", anim->name);
|
||||||
}
|
}
|
||||||
numAssociations = animBlock->numAnims;
|
numAssociations = animBlock->numAnims;
|
||||||
}
|
}
|
||||||
|
@ -144,10 +165,8 @@ void
|
||||||
CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs)
|
CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump, const char **animNames, int numAssocs)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
CAnimBlock *animBlock;
|
|
||||||
|
|
||||||
if(assocList)
|
DestroyAssociations();
|
||||||
DestroyAssociations();
|
|
||||||
|
|
||||||
animBlock = CAnimManager::GetAnimationBlock(blockName);
|
animBlock = CAnimManager::GetAnimationBlock(blockName);
|
||||||
assocList = new CAnimBlendAssociation[numAssocs];
|
assocList = new CAnimBlendAssociation[numAssocs];
|
||||||
|
@ -155,7 +174,8 @@ CAnimBlendAssocGroup::CreateAssociations(const char *blockName, RpClump *clump,
|
||||||
numAssociations = 0;
|
numAssociations = 0;
|
||||||
for(i = 0; i < numAssocs; i++){
|
for(i = 0; i < numAssocs; i++){
|
||||||
assocList[i].Init(clump, CAnimManager::GetAnimation(animNames[i], animBlock));
|
assocList[i].Init(clump, CAnimManager::GetAnimation(animNames[i], animBlock));
|
||||||
assocList[i].animId = i;
|
assocList[i].animId = firstAnimId + i;
|
||||||
|
assocList[i].groupId = groupId;
|
||||||
}
|
}
|
||||||
numAssociations = numAssocs;
|
numAssociations = numAssocs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
class CAnimBlendAssociation;
|
class CAnimBlendAssociation;
|
||||||
|
struct CAnimBlock;
|
||||||
|
|
||||||
class CAnimBlendAssocGroup
|
class CAnimBlendAssocGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
CAnimBlock *animBlock;
|
||||||
CAnimBlendAssociation *assocList;
|
CAnimBlendAssociation *assocList;
|
||||||
int32 numAssociations;
|
int32 numAssociations;
|
||||||
|
int32 firstAnimId;
|
||||||
|
int32 groupId; // id of self in ms_aAnimAssocGroups
|
||||||
|
|
||||||
CAnimBlendAssocGroup(void);
|
CAnimBlendAssocGroup(void);
|
||||||
~CAnimBlendAssocGroup(void);
|
~CAnimBlendAssocGroup(void);
|
||||||
|
|
|
@ -7,8 +7,11 @@
|
||||||
#include "AnimBlendAssociation.h"
|
#include "AnimBlendAssociation.h"
|
||||||
#include "RwHelper.h"
|
#include "RwHelper.h"
|
||||||
|
|
||||||
|
//--MIAMI: file done except for one TODO
|
||||||
|
|
||||||
CAnimBlendAssociation::CAnimBlendAssociation(void)
|
CAnimBlendAssociation::CAnimBlendAssociation(void)
|
||||||
{
|
{
|
||||||
|
groupId = -1;
|
||||||
nodes = nil;
|
nodes = nil;
|
||||||
blendAmount = 1.0f;
|
blendAmount = 1.0f;
|
||||||
blendDelta = 0.0f;
|
blendDelta = 0.0f;
|
||||||
|
@ -54,8 +57,8 @@ CAnimBlendAssociation::AllocateAnimBlendNodeArray(int n)
|
||||||
void
|
void
|
||||||
CAnimBlendAssociation::FreeAnimBlendNodeArray(void)
|
CAnimBlendAssociation::FreeAnimBlendNodeArray(void)
|
||||||
{
|
{
|
||||||
assert(nodes != nil);
|
if(nodes)
|
||||||
RwFreeAlign(nodes);
|
RwFreeAlign(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -75,7 +78,10 @@ CAnimBlendAssociation::Init(RpClump *clump, CAnimBlendHierarchy *hier)
|
||||||
// NB: This is where the order of nodes is defined
|
// NB: This is where the order of nodes is defined
|
||||||
for(i = 0; i < hier->numSequences; i++){
|
for(i = 0; i < hier->numSequences; i++){
|
||||||
CAnimBlendSequence *seq = &hier->sequences[i];
|
CAnimBlendSequence *seq = &hier->sequences[i];
|
||||||
frame = RpAnimBlendClumpFindFrame(clump, seq->name);
|
if(seq->boneTag == -1)
|
||||||
|
frame = RpAnimBlendClumpFindFrame(clump, seq->name);
|
||||||
|
else
|
||||||
|
frame = RpAnimBlendClumpFindBone(clump, seq->boneTag);
|
||||||
if(frame && seq->numFrames > 0)
|
if(frame && seq->numFrames > 0)
|
||||||
nodes[frame - clumpData->frames].sequence = seq;
|
nodes[frame - clumpData->frames].sequence = seq;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +96,7 @@ CAnimBlendAssociation::Init(CAnimBlendAssociation &assoc)
|
||||||
numNodes = assoc.numNodes;
|
numNodes = assoc.numNodes;
|
||||||
flags = assoc.flags;
|
flags = assoc.flags;
|
||||||
animId = assoc.animId;
|
animId = assoc.animId;
|
||||||
|
groupId = assoc.groupId;
|
||||||
AllocateAnimBlendNodeArray(numNodes);
|
AllocateAnimBlendNodeArray(numNodes);
|
||||||
for(i = 0; i < numNodes; i++){
|
for(i = 0; i < numNodes; i++){
|
||||||
nodes[i] = assoc.nodes[i];
|
nodes[i] = assoc.nodes[i];
|
||||||
|
@ -129,9 +136,15 @@ CAnimBlendAssociation::SetCurrentTime(float time)
|
||||||
if(!IsRepeating())
|
if(!IsRepeating())
|
||||||
return;
|
return;
|
||||||
CAnimManager::UncompressAnimation(hierarchy);
|
CAnimManager::UncompressAnimation(hierarchy);
|
||||||
for(i = 0; i < numNodes; i++)
|
if(hierarchy->compressed2){
|
||||||
if(nodes[i].sequence)
|
for(i = 0; i < numNodes; i++)
|
||||||
nodes[i].FindKeyFrame(currentTime);
|
if(nodes[i].sequence)
|
||||||
|
nodes[i].SetupKeyFrameCompressed();
|
||||||
|
}else{
|
||||||
|
for(i = 0; i < numNodes; i++)
|
||||||
|
if(nodes[i].sequence)
|
||||||
|
nodes[i].FindKeyFrame(currentTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -146,14 +159,20 @@ CAnimBlendAssociation::Start(float time)
|
||||||
flags |= ASSOC_RUNNING;
|
flags |= ASSOC_RUNNING;
|
||||||
SetCurrentTime(time);
|
SetCurrentTime(time);
|
||||||
}
|
}
|
||||||
|
bool
|
||||||
void
|
|
||||||
CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
|
CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
|
||||||
{
|
{
|
||||||
if(!IsRunning())
|
if(!IsRunning())
|
||||||
return;
|
return true;
|
||||||
|
if(currentTime >= hierarchy->totalLength){
|
||||||
|
flags &= ~ASSOC_RUNNING;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(MIAMI): we still need this for some reason
|
||||||
|
#ifndef NOT_YET
|
||||||
timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;
|
timeStep = (flags & ASSOC_MOVEMENT ? relSpeed*hierarchy->totalLength : speed) * timeDelta;
|
||||||
|
#endif
|
||||||
currentTime += timeStep;
|
currentTime += timeStep;
|
||||||
|
|
||||||
if(currentTime >= hierarchy->totalLength){
|
if(currentTime >= hierarchy->totalLength){
|
||||||
|
@ -163,7 +182,6 @@ CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
|
||||||
currentTime -= hierarchy->totalLength;
|
currentTime -= hierarchy->totalLength;
|
||||||
else{
|
else{
|
||||||
currentTime = hierarchy->totalLength;
|
currentTime = hierarchy->totalLength;
|
||||||
flags &= ~ASSOC_RUNNING;
|
|
||||||
if(flags & ASSOC_FADEOUTWHENDONE){
|
if(flags & ASSOC_FADEOUTWHENDONE){
|
||||||
flags |= ASSOC_DELETEFADEDOUT;
|
flags |= ASSOC_DELETEFADEDOUT;
|
||||||
blendDelta = -4.0f;
|
blendDelta = -4.0f;
|
||||||
|
@ -174,6 +192,7 @@ CAnimBlendAssociation::UpdateTime(float timeDelta, float relSpeed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return whether we still exist after this function
|
// return whether we still exist after this function
|
||||||
|
|
|
@ -37,7 +37,8 @@ public:
|
||||||
|
|
||||||
CAnimBlendLink link;
|
CAnimBlendLink link;
|
||||||
|
|
||||||
int numNodes; // taken from CAnimBlendClumpData::numFrames
|
int16 numNodes; // taken from CAnimBlendClumpData::numFrames
|
||||||
|
int16 groupId; // ID of CAnimBlendAssocGroup this is in
|
||||||
// NB: Order of these depends on order of nodes in Clump this was built from
|
// NB: Order of these depends on order of nodes in Clump this was built from
|
||||||
CAnimBlendNode *nodes;
|
CAnimBlendNode *nodes;
|
||||||
CAnimBlendHierarchy *hierarchy;
|
CAnimBlendHierarchy *hierarchy;
|
||||||
|
@ -46,8 +47,8 @@ public:
|
||||||
float currentTime;
|
float currentTime;
|
||||||
float speed;
|
float speed;
|
||||||
float timeStep;
|
float timeStep;
|
||||||
int32 animId;
|
int16 animId;
|
||||||
int32 flags;
|
int16 flags;
|
||||||
int32 callbackType;
|
int32 callbackType;
|
||||||
void (*callback)(CAnimBlendAssociation*, void*);
|
void (*callback)(CAnimBlendAssociation*, void*);
|
||||||
void *callbackArg;
|
void *callbackArg;
|
||||||
|
@ -75,7 +76,7 @@ public:
|
||||||
void SetCurrentTime(float time);
|
void SetCurrentTime(float time);
|
||||||
void SyncAnimation(CAnimBlendAssociation *other);
|
void SyncAnimation(CAnimBlendAssociation *other);
|
||||||
void Start(float time);
|
void Start(float time);
|
||||||
void UpdateTime(float timeDelta, float relSpeed);
|
bool UpdateTime(float timeDelta, float relSpeed);
|
||||||
bool UpdateBlend(float timeDelta);
|
bool UpdateBlend(float timeDelta);
|
||||||
|
|
||||||
void SetRun(void) { flags |= ASSOC_RUNNING; }
|
void SetRun(void) { flags |= ASSOC_RUNNING; }
|
||||||
|
@ -86,4 +87,3 @@ public:
|
||||||
return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link));
|
return (CAnimBlendAssociation*)((uint8*)l - offsetof(CAnimBlendAssociation, link));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert(sizeof(CAnimBlendAssociation) == 0x40, "CAnimBlendAssociation: error");
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "AnimBlendClumpData.h"
|
#include "AnimBlendClumpData.h"
|
||||||
#include "RwHelper.h"
|
#include "RwHelper.h"
|
||||||
|
|
||||||
|
//--MIAMI: file done
|
||||||
|
|
||||||
CAnimBlendClumpData::CAnimBlendClumpData(void)
|
CAnimBlendClumpData::CAnimBlendClumpData(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,9 +35,6 @@ class CAnimBlendClumpData
|
||||||
public:
|
public:
|
||||||
CAnimBlendLink link;
|
CAnimBlendLink link;
|
||||||
int32 numFrames;
|
int32 numFrames;
|
||||||
#ifdef PED_SKIN
|
|
||||||
int32 modelNumber; // doesn't seem to be used
|
|
||||||
#endif
|
|
||||||
CVector *velocity;
|
CVector *velocity;
|
||||||
// order of frames is determined by RW hierarchy
|
// order of frames is determined by RW hierarchy
|
||||||
AnimBlendFrameData *frames;
|
AnimBlendFrameData *frames;
|
||||||
|
@ -50,6 +47,3 @@ public:
|
||||||
#endif
|
#endif
|
||||||
void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg);
|
void ForAllFrames(void (*cb)(AnimBlendFrameData*, void*), void *arg);
|
||||||
};
|
};
|
||||||
#ifndef PED_SKIN
|
|
||||||
static_assert(sizeof(CAnimBlendClumpData) == 0x14, "CAnimBlendClumpData: error");
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include "AnimBlendSequence.h"
|
#include "AnimBlendSequence.h"
|
||||||
#include "AnimBlendHierarchy.h"
|
#include "AnimBlendHierarchy.h"
|
||||||
|
#include "AnimManager.h"
|
||||||
|
|
||||||
|
//--MIAMI: file done
|
||||||
|
|
||||||
CAnimBlendHierarchy::CAnimBlendHierarchy(void)
|
CAnimBlendHierarchy::CAnimBlendHierarchy(void)
|
||||||
{
|
{
|
||||||
|
@ -15,9 +18,10 @@ CAnimBlendHierarchy::CAnimBlendHierarchy(void)
|
||||||
void
|
void
|
||||||
CAnimBlendHierarchy::Shutdown(void)
|
CAnimBlendHierarchy::Shutdown(void)
|
||||||
{
|
{
|
||||||
|
CAnimManager::RemoveFromUncompressedCache(this);
|
||||||
RemoveAnimSequences();
|
RemoveAnimSequences();
|
||||||
|
totalLength = 0.0f;
|
||||||
compressed = 0;
|
compressed = 0;
|
||||||
linkPtr = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -30,15 +34,44 @@ void
|
||||||
CAnimBlendHierarchy::CalcTotalTime(void)
|
CAnimBlendHierarchy::CalcTotalTime(void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
float totalTime = 0.0f;
|
|
||||||
|
totalLength = 0.0f;
|
||||||
|
|
||||||
for(i = 0; i < numSequences; i++){
|
for(i = 0; i < numSequences; i++){
|
||||||
float seqTime = 0.0f;
|
#ifdef FIX_BUGS
|
||||||
for(j = 0; j < sequences[i].numFrames; j++)
|
if(sequences[i].numFrames == 0)
|
||||||
seqTime += sequences[i].GetKeyFrame(j)->deltaTime;
|
continue;
|
||||||
totalTime = Max(totalTime, seqTime);
|
#endif
|
||||||
|
|
||||||
|
totalLength = Max(totalLength, sequences[i].GetKeyFrame(sequences[i].numFrames-1)->deltaTime);
|
||||||
|
for(j = sequences[i].numFrames-1; j > 0; j--){
|
||||||
|
KeyFrame *kf1 = sequences[i].GetKeyFrame(j);
|
||||||
|
KeyFrame *kf2 = sequences[i].GetKeyFrame(j-1);
|
||||||
|
kf1->deltaTime -= kf2->deltaTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CAnimBlendHierarchy::CalcTotalTimeCompressed(void)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
totalLength = 0.0f;
|
||||||
|
|
||||||
|
for(i = 0; i < numSequences; i++){
|
||||||
|
#ifdef FIX_BUGS
|
||||||
|
if(sequences[i].numFrames == 0)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
totalLength = Max(totalLength, sequences[i].GetKeyFrameCompressed(sequences[i].numFrames-1)->deltaTime/60.0f);
|
||||||
|
for(j = sequences[i].numFrames-1; j > 0; j--){
|
||||||
|
KeyFrame *kf1 = sequences[i].GetKeyFrameCompressed(j);
|
||||||
|
KeyFrame *kf2 = sequences[i].GetKeyFrameCompressed(j-1);
|
||||||
|
kf1->deltaTime -= kf2->deltaTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
totalLength = totalTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -53,17 +86,19 @@ CAnimBlendHierarchy::RemoveQuaternionFlips(void)
|
||||||
void
|
void
|
||||||
CAnimBlendHierarchy::RemoveAnimSequences(void)
|
CAnimBlendHierarchy::RemoveAnimSequences(void)
|
||||||
{
|
{
|
||||||
if(sequences)
|
delete[] sequences;
|
||||||
delete[] sequences;
|
sequences = nil;
|
||||||
numSequences = 0;
|
numSequences = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CAnimBlendHierarchy::Uncompress(void)
|
CAnimBlendHierarchy::Uncompress(void)
|
||||||
{
|
{
|
||||||
if(totalLength == 0.0f)
|
|
||||||
CalcTotalTime();
|
|
||||||
compressed = 0;
|
compressed = 0;
|
||||||
|
if(totalLength == 0.0f){
|
||||||
|
RemoveQuaternionFlips();
|
||||||
|
CalcTotalTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -11,7 +11,8 @@ public:
|
||||||
char name[24];
|
char name[24];
|
||||||
CAnimBlendSequence *sequences;
|
CAnimBlendSequence *sequences;
|
||||||
int16 numSequences;
|
int16 numSequences;
|
||||||
int16 compressed; // not really used
|
bool compressed; // not really used
|
||||||
|
bool compressed2; // not really used
|
||||||
float totalLength;
|
float totalLength;
|
||||||
CLink<CAnimBlendHierarchy*> *linkPtr;
|
CLink<CAnimBlendHierarchy*> *linkPtr;
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ public:
|
||||||
void Shutdown(void);
|
void Shutdown(void);
|
||||||
void SetName(char *name);
|
void SetName(char *name);
|
||||||
void CalcTotalTime(void);
|
void CalcTotalTime(void);
|
||||||
|
void CalcTotalTimeCompressed(void);
|
||||||
void RemoveQuaternionFlips(void);
|
void RemoveQuaternionFlips(void);
|
||||||
void RemoveAnimSequences(void);
|
void RemoveAnimSequences(void);
|
||||||
void Uncompress(void);
|
void Uncompress(void);
|
||||||
|
|
|
@ -23,5 +23,6 @@ public:
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
if(next)
|
if(next)
|
||||||
next->prev = prev;
|
next->prev = prev;
|
||||||
|
Init();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
#include "AnimBlendAssociation.h"
|
#include "AnimBlendAssociation.h"
|
||||||
#include "AnimBlendNode.h"
|
#include "AnimBlendNode.h"
|
||||||
|
|
||||||
|
//--MIAMI: file done
|
||||||
|
|
||||||
void
|
void
|
||||||
CAnimBlendNode::Init(void)
|
CAnimBlendNode::Init(void)
|
||||||
{
|
{
|
||||||
frameA = 0;
|
frameA = -1;
|
||||||
frameB = 0;
|
frameB = -1;
|
||||||
remainingTime = 0.0f;
|
remainingTime = 0.0f;
|
||||||
sequence = nil;
|
sequence = nil;
|
||||||
association = nil;
|
association = nil;
|
||||||
|
@ -92,7 +94,9 @@ CAnimBlendNode::FindKeyFrame(float t)
|
||||||
frameA = 0;
|
frameA = 0;
|
||||||
frameB = frameA;
|
frameB = frameA;
|
||||||
|
|
||||||
if(sequence->numFrames >= 2){
|
if(sequence->numFrames == 1){
|
||||||
|
remainingTime = 0.0f;
|
||||||
|
}else{
|
||||||
frameA++;
|
frameA++;
|
||||||
|
|
||||||
// advance until t is between frameB and frameA
|
// advance until t is between frameB and frameA
|
||||||
|
@ -101,8 +105,11 @@ CAnimBlendNode::FindKeyFrame(float t)
|
||||||
frameB = frameA++;
|
frameB = frameA++;
|
||||||
if(frameA >= sequence->numFrames){
|
if(frameA >= sequence->numFrames){
|
||||||
// reached end of animation
|
// reached end of animation
|
||||||
if(!association->IsRepeating())
|
if(!association->IsRepeating()){
|
||||||
|
CalcDeltas();
|
||||||
|
remainingTime = 0.0f;
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
frameA = 0;
|
frameA = 0;
|
||||||
frameB = 0;
|
frameB = 0;
|
||||||
}
|
}
|
||||||
|
@ -115,6 +122,25 @@ CAnimBlendNode::FindKeyFrame(float t)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CAnimBlendNode::SetupKeyFrameCompressed(void)
|
||||||
|
{
|
||||||
|
if(sequence->numFrames < 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
frameA = 1;
|
||||||
|
frameB = 0;
|
||||||
|
|
||||||
|
if(sequence->numFrames == 1){
|
||||||
|
frameA = 0;
|
||||||
|
remainingTime = 0.0f;
|
||||||
|
}else
|
||||||
|
remainingTime = sequence->GetKeyFrameCompressed(frameA)->deltaTime/60.0f;
|
||||||
|
|
||||||
|
CalcDeltasCompressed();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CAnimBlendNode::CalcDeltas(void)
|
CAnimBlendNode::CalcDeltas(void)
|
||||||
{
|
{
|
||||||
|
@ -129,6 +155,20 @@ CAnimBlendNode::CalcDeltas(void)
|
||||||
invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta);
|
invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CAnimBlendNode::CalcDeltasCompressed(void)
|
||||||
|
{
|
||||||
|
if((sequence->type & CAnimBlendSequence::KF_ROT) == 0)
|
||||||
|
return;
|
||||||
|
KeyFrame *kfA = sequence->GetKeyFrameCompressed(frameA);
|
||||||
|
KeyFrame *kfB = sequence->GetKeyFrameCompressed(frameB);
|
||||||
|
float cos = DotProduct(kfA->rotation, kfB->rotation);
|
||||||
|
if(cos > 1.0f)
|
||||||
|
cos = 1.0f;
|
||||||
|
theta = Acos(cos);
|
||||||
|
invSin = theta == 0.0f ? 0.0f : 1.0f/Sin(theta);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
|
CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
|
||||||
{
|
{
|
||||||
|
@ -138,7 +178,7 @@ CAnimBlendNode::GetCurrentTranslation(CVector &trans, float weight)
|
||||||
if(blend > 0.0f){
|
if(blend > 0.0f){
|
||||||
KeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);
|
KeyFrameTrans *kfA = (KeyFrameTrans*)sequence->GetKeyFrame(frameA);
|
||||||
KeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);
|
KeyFrameTrans *kfB = (KeyFrameTrans*)sequence->GetKeyFrame(frameB);
|
||||||
float t = (kfA->deltaTime - remainingTime)/kfA->deltaTime;
|
float t = kfA->deltaTime == 0.0f ? 0.0f : (kfA->deltaTime - remainingTime)/kfA->deltaTime;
|
||||||
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
if(sequence->type & CAnimBlendSequence::KF_TRANS){
|
||||||
trans = kfB->translation + t*(kfA->translation - kfB->translation);
|
trans = kfB->translation + t*(kfA->translation - kfB->translation);
|
||||||
trans *= blend;
|
trans *= blend;
|
||||||
|
|
|
@ -22,7 +22,9 @@ public:
|
||||||
bool Update(CVector &trans, CQuaternion &rot, float weight);
|
bool Update(CVector &trans, CQuaternion &rot, float weight);
|
||||||
bool NextKeyFrame(void);
|
bool NextKeyFrame(void);
|
||||||
bool FindKeyFrame(float t);
|
bool FindKeyFrame(float t);
|
||||||
|
bool SetupKeyFrameCompressed(void);
|
||||||
void CalcDeltas(void);
|
void CalcDeltas(void);
|
||||||
|
void CalcDeltasCompressed(void);
|
||||||
void GetCurrentTranslation(CVector &trans, float weight);
|
void GetCurrentTranslation(CVector &trans, float weight);
|
||||||
void GetEndTranslation(CVector &trans, float weight);
|
void GetEndTranslation(CVector &trans, float weight);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "AnimBlendSequence.h"
|
#include "AnimBlendSequence.h"
|
||||||
|
|
||||||
|
//--MIAMI: file done
|
||||||
|
|
||||||
CAnimBlendSequence::CAnimBlendSequence(void)
|
CAnimBlendSequence::CAnimBlendSequence(void)
|
||||||
{
|
{
|
||||||
type = 0;
|
type = 0;
|
||||||
|
@ -17,6 +19,8 @@ CAnimBlendSequence::~CAnimBlendSequence(void)
|
||||||
{
|
{
|
||||||
if(keyFrames)
|
if(keyFrames)
|
||||||
RwFree(keyFrames);
|
RwFree(keyFrames);
|
||||||
|
if(keyFramesCompressed)
|
||||||
|
RwFree(keyFramesCompressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -26,18 +30,21 @@ CAnimBlendSequence::SetName(char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CAnimBlendSequence::SetNumFrames(int numFrames, bool translation)
|
CAnimBlendSequence::SetNumFrames(int numFrames, bool translation, bool compressed)
|
||||||
{
|
{
|
||||||
int sz;
|
|
||||||
|
|
||||||
if(translation){
|
if(translation){
|
||||||
sz = sizeof(KeyFrameTrans);
|
|
||||||
type |= KF_ROT | KF_TRANS;
|
type |= KF_ROT | KF_TRANS;
|
||||||
|
if(compressed)
|
||||||
|
keyFramesCompressed = RwMalloc(sizeof(KeyFrameTrans) * numFrames);
|
||||||
|
else
|
||||||
|
keyFrames = RwMalloc(sizeof(KeyFrameTrans) * numFrames);
|
||||||
}else{
|
}else{
|
||||||
sz = sizeof(KeyFrame);
|
|
||||||
type |= KF_ROT;
|
type |= KF_ROT;
|
||||||
|
if(compressed)
|
||||||
|
keyFramesCompressed = RwMalloc(sizeof(KeyFrame) * numFrames);
|
||||||
|
else
|
||||||
|
keyFrames = RwMalloc(sizeof(KeyFrame) * numFrames);
|
||||||
}
|
}
|
||||||
keyFrames = RwMalloc(sz * numFrames);
|
|
||||||
this->numFrames = numFrames;
|
this->numFrames = numFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,18 @@ public:
|
||||||
CAnimBlendSequence(void);
|
CAnimBlendSequence(void);
|
||||||
virtual ~CAnimBlendSequence(void);
|
virtual ~CAnimBlendSequence(void);
|
||||||
void SetName(char *name);
|
void SetName(char *name);
|
||||||
void SetNumFrames(int numFrames, bool translation);
|
void SetNumFrames(int numFrames, bool translation, bool compressed);
|
||||||
void RemoveQuaternionFlips(void);
|
void RemoveQuaternionFlips(void);
|
||||||
KeyFrame *GetKeyFrame(int n) {
|
KeyFrame *GetKeyFrame(int n) {
|
||||||
return type & KF_TRANS ?
|
return type & KF_TRANS ?
|
||||||
&((KeyFrameTrans*)keyFrames)[n] :
|
&((KeyFrameTrans*)keyFrames)[n] :
|
||||||
&((KeyFrame*)keyFrames)[n];
|
&((KeyFrame*)keyFrames)[n];
|
||||||
}
|
}
|
||||||
|
KeyFrame *GetKeyFrameCompressed(int n) {
|
||||||
|
return type & KF_TRANS ?
|
||||||
|
&((KeyFrameTrans*)keyFramesCompressed)[n] :
|
||||||
|
&((KeyFrame*)keyFramesCompressed)[n];
|
||||||
|
}
|
||||||
bool HasTranslation(void) { return !!(type & KF_TRANS); }
|
bool HasTranslation(void) { return !!(type & KF_TRANS); }
|
||||||
// TODO? these are unused
|
// TODO? these are unused
|
||||||
// void Uncompress(void);
|
// void Uncompress(void);
|
||||||
|
|
|
@ -10,9 +10,12 @@
|
||||||
#include "AnimBlendAssociation.h"
|
#include "AnimBlendAssociation.h"
|
||||||
#include "AnimBlendAssocGroup.h"
|
#include "AnimBlendAssocGroup.h"
|
||||||
#include "AnimManager.h"
|
#include "AnimManager.h"
|
||||||
|
#include "Streaming.h"
|
||||||
|
|
||||||
CAnimBlock CAnimManager::ms_aAnimBlocks[2];
|
//--MIAMI: code done (except for pointless TODO)
|
||||||
CAnimBlendHierarchy CAnimManager::ms_aAnimations[250];
|
|
||||||
|
CAnimBlock CAnimManager::ms_aAnimBlocks[NUMANIMBLOCKS];
|
||||||
|
CAnimBlendHierarchy CAnimManager::ms_aAnimations[NUMANIMATIONS];
|
||||||
int32 CAnimManager::ms_numAnimBlocks;
|
int32 CAnimManager::ms_numAnimBlocks;
|
||||||
int32 CAnimManager::ms_numAnimations;
|
int32 CAnimManager::ms_numAnimations;
|
||||||
CAnimBlendAssocGroup *CAnimManager::ms_aAnimAssocGroups;
|
CAnimBlendAssocGroup *CAnimManager::ms_aAnimAssocGroups;
|
||||||
|
@ -564,8 +567,6 @@ CAnimManager::Initialise(void)
|
||||||
ms_numAnimations = 0;
|
ms_numAnimations = 0;
|
||||||
ms_numAnimBlocks = 0;
|
ms_numAnimBlocks = 0;
|
||||||
ms_animCache.Init(25);
|
ms_animCache.Init(25);
|
||||||
|
|
||||||
// dumpanimdata();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -573,31 +574,48 @@ CAnimManager::Shutdown(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ms_animCache.Shutdown();
|
for(i = 0; i < NUMANIMBLOCKS; i++)
|
||||||
|
CStreaming::RemoveAnim(i);
|
||||||
|
|
||||||
for(i = 0; i < ms_numAnimations; i++)
|
for(i = 0; i < ms_numAnimations; i++)
|
||||||
ms_aAnimations[i].Shutdown();
|
ms_aAnimations[i].Shutdown();
|
||||||
|
|
||||||
|
ms_animCache.Shutdown();
|
||||||
|
|
||||||
delete[] ms_aAnimAssocGroups;
|
delete[] ms_aAnimAssocGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier)
|
CAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier)
|
||||||
{
|
{
|
||||||
if(!hier->compressed){
|
if(hier->compressed2){
|
||||||
if(hier->linkPtr){
|
if(hier->totalLength == 0.0f)
|
||||||
hier->linkPtr->Remove();
|
hier->CalcTotalTimeCompressed();
|
||||||
ms_animCache.head.Insert(hier->linkPtr);
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
CLink<CAnimBlendHierarchy*> *link = ms_animCache.Insert(hier);
|
if(!hier->compressed){
|
||||||
if(link == nil){
|
if(hier->linkPtr){
|
||||||
ms_animCache.tail.prev->item->RemoveUncompressedData();
|
hier->linkPtr->Remove();
|
||||||
ms_animCache.Remove(ms_animCache.tail.prev);
|
ms_animCache.head.Insert(hier->linkPtr);
|
||||||
link = ms_animCache.Insert(hier);
|
}
|
||||||
|
}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;
|
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*
|
CAnimBlendHierarchy*
|
||||||
CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
|
CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
|
||||||
{
|
{
|
||||||
|
@ -619,7 +704,7 @@ CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock)
|
||||||
CAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex];
|
CAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex];
|
||||||
|
|
||||||
for(i = 0; i < animBlock->numAnims; i++){
|
for(i = 0; i < animBlock->numAnims; i++){
|
||||||
if(!CGeneral::faststricmp(hier->name, name))
|
if(strcasecmp(hier->name, name) == 0)
|
||||||
return hier;
|
return hier;
|
||||||
hier++;
|
hier++;
|
||||||
}
|
}
|
||||||
|
@ -739,24 +824,33 @@ CAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId a
|
||||||
|
|
||||||
void
|
void
|
||||||
CAnimManager::LoadAnimFiles(void)
|
CAnimManager::LoadAnimFiles(void)
|
||||||
|
{
|
||||||
|
LoadAnimFile("ANIM\\PED.IFP");
|
||||||
|
ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];
|
||||||
|
CreateAnimAssocGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CAnimManager::CreateAnimAssocGroups(void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
LoadAnimFile("ANIM\\PED.IFP");
|
|
||||||
|
|
||||||
// Create all assoc groups
|
|
||||||
ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS];
|
|
||||||
for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++){
|
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);
|
CBaseModelInfo *mi = CModelInfo::GetModelInfo(ms_aAnimAssocDefinitions[i].modelIndex);
|
||||||
RpClump *clump = (RpClump*)mi->CreateInstance();
|
RpClump *clump = (RpClump*)mi->CreateInstance();
|
||||||
RpAnimBlendClumpInit(clump);
|
RpAnimBlendClumpInit(clump);
|
||||||
CAnimBlendAssocGroup *group = &CAnimManager::ms_aAnimAssocGroups[i];
|
CAnimBlendAssocGroup *group = &ms_aAnimAssocGroups[i];
|
||||||
const AnimAssocDefinition *def = &CAnimManager::ms_aAnimAssocDefinitions[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);
|
group->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims);
|
||||||
for(j = 0; j < group->numAssociations; j++)
|
for(j = 0; j < group->numAssociations; j++)
|
||||||
group->GetAnimation(j)->flags |= def->animDescs[j].flags;
|
group->GetAnimation(j)->flags |= def->animDescs[j].flags;
|
||||||
#ifdef PED_SKIN
|
#ifdef PED_SKIN
|
||||||
// forgot on xbox/android
|
|
||||||
if(IsClumpSkinned(clump))
|
if(IsClumpSkinned(clump))
|
||||||
RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
|
RpClumpForAllAtomics(clump, AtomicRemoveAnimFromSkinCB, nil);
|
||||||
#endif
|
#endif
|
||||||
|
@ -767,15 +861,16 @@ CAnimManager::LoadAnimFiles(void)
|
||||||
void
|
void
|
||||||
CAnimManager::LoadAnimFile(const char *filename)
|
CAnimManager::LoadAnimFile(const char *filename)
|
||||||
{
|
{
|
||||||
int fd;
|
RwStream *stream;
|
||||||
fd = CFileMgr::OpenFile(filename, "rb");
|
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
|
||||||
assert(fd > 0);
|
assert(stream);
|
||||||
LoadAnimFile(fd, true);
|
LoadAnimFile(stream, true);
|
||||||
CFileMgr::CloseFile(fd);
|
RwStreamClose(stream, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--MIAMI: done (except maybe implement some unimplemented compression?)
|
||||||
void
|
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)
|
#define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3)
|
||||||
struct IfpHeader {
|
struct IfpHeader {
|
||||||
|
@ -783,127 +878,130 @@ CAnimManager::LoadAnimFile(int fd, bool compress)
|
||||||
uint32 size;
|
uint32 size;
|
||||||
};
|
};
|
||||||
IfpHeader anpk, info, name, dgan, cpan, anim;
|
IfpHeader anpk, info, name, dgan, cpan, anim;
|
||||||
int numANPK;
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int i, j, k, l;
|
int j, k, l;
|
||||||
float *fbuf = (float*)buf;
|
float *fbuf = (float*)buf;
|
||||||
|
|
||||||
CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
|
// block name
|
||||||
if(strncmp(anpk.ident, "ANLF", 4) == 0){
|
RwStreamRead(stream, &anpk, sizeof(IfpHeader));
|
||||||
ROUNDSIZE(anpk.size);
|
ROUNDSIZE(anpk.size);
|
||||||
CFileMgr::Read(fd, buf, anpk.size);
|
RwStreamRead(stream, &info, sizeof(IfpHeader));
|
||||||
numANPK = *(int*)buf;
|
ROUNDSIZE(info.size);
|
||||||
}else if(strncmp(anpk.ident, "ANPK", 4) == 0){
|
RwStreamRead(stream, buf, info.size);
|
||||||
CFileMgr::Seek(fd, -8, 1);
|
CAnimBlock *animBlock = GetAnimationBlock(buf+4);
|
||||||
numANPK = 1;
|
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++){
|
debug("Loading ANIMS %s\n", animBlock->name);
|
||||||
// block name
|
animBlock->isLoaded = true;
|
||||||
CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader));
|
|
||||||
ROUNDSIZE(anpk.size);
|
int animIndex = animBlock->firstIndex;
|
||||||
CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
|
for(j = 0; j < animBlock->numAnims; j++){
|
||||||
|
CAnimBlendHierarchy *hier = &ms_aAnimations[animIndex++];
|
||||||
|
|
||||||
|
// animation name
|
||||||
|
RwStreamRead(stream, &name, sizeof(IfpHeader));
|
||||||
|
ROUNDSIZE(name.size);
|
||||||
|
RwStreamRead(stream, 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
|
||||||
|
RwStreamRead(stream, (char*)&dgan, sizeof(IfpHeader));
|
||||||
|
ROUNDSIZE(dgan.size);
|
||||||
|
RwStreamRead(stream, (char*)&info, sizeof(IfpHeader));
|
||||||
ROUNDSIZE(info.size);
|
ROUNDSIZE(info.size);
|
||||||
CFileMgr::Read(fd, buf, info.size);
|
RwStreamRead(stream, buf, info.size);
|
||||||
CAnimBlock *animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++];
|
hier->numSequences = *(int*)buf;
|
||||||
strncpy(animBlock->name, buf+4, 24);
|
hier->sequences = new CAnimBlendSequence[hier->numSequences];
|
||||||
animBlock->numAnims = *(int*)buf;
|
|
||||||
|
|
||||||
animBlock->firstIndex = ms_numAnimations;
|
CAnimBlendSequence *seq = hier->sequences;
|
||||||
|
for(k = 0; k < hier->numSequences; k++, seq++){
|
||||||
for(j = 0; j < animBlock->numAnims; j++){
|
// Each node has a name and key frames
|
||||||
CAnimBlendHierarchy *hier = &ms_aAnimations[ms_numAnimations++];
|
RwStreamRead(stream, &cpan, sizeof(IfpHeader));
|
||||||
|
|
||||||
// animation name
|
|
||||||
CFileMgr::Read(fd, (char*)&name, sizeof(IfpHeader));
|
|
||||||
ROUNDSIZE(name.size);
|
|
||||||
CFileMgr::Read(fd, buf, name.size);
|
|
||||||
hier->SetName(buf);
|
|
||||||
|
|
||||||
// DG info has number of nodes/sequences
|
|
||||||
CFileMgr::Read(fd, (char*)&dgan, sizeof(IfpHeader));
|
|
||||||
ROUNDSIZE(dgan.size);
|
ROUNDSIZE(dgan.size);
|
||||||
CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader));
|
RwStreamRead(stream, &anim, sizeof(IfpHeader));
|
||||||
ROUNDSIZE(info.size);
|
ROUNDSIZE(anim.size);
|
||||||
CFileMgr::Read(fd, buf, info.size);
|
RwStreamRead(stream, buf, anim.size);
|
||||||
hier->numSequences = *(int*)buf;
|
int numFrames = *(int*)(buf+28);
|
||||||
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);
|
|
||||||
#ifdef PED_SKIN
|
#ifdef PED_SKIN
|
||||||
if(anim.size == 44)
|
if(anim.size == 44)
|
||||||
seq->SetBoneTag(*(int*)(buf+40));
|
seq->SetBoneTag(*(int*)(buf+40));
|
||||||
#endif
|
#endif
|
||||||
seq->SetName(buf);
|
seq->SetName(buf);
|
||||||
if(numFrames == 0)
|
if(numFrames == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CFileMgr::Read(fd, (char*)&info, sizeof(info));
|
RwStreamRead(stream, &info, sizeof(info));
|
||||||
if(strncmp(info.ident, "KR00", 4) == 0){
|
if(strncmp(info.ident, "KR00", 4) == 0){
|
||||||
seq->SetNumFrames(numFrames, false);
|
seq->SetNumFrames(numFrames, false, false);
|
||||||
KeyFrame *kf = seq->GetKeyFrame(0);
|
KeyFrame *kf = seq->GetKeyFrame(0);
|
||||||
for(l = 0; l < numFrames; l++, kf++){
|
for(l = 0; l < numFrames; l++, kf++){
|
||||||
CFileMgr::Read(fd, buf, 0x14);
|
RwStreamRead(stream, buf, 0x14);
|
||||||
kf->rotation.x = -fbuf[0];
|
kf->rotation.x = -fbuf[0];
|
||||||
kf->rotation.y = -fbuf[1];
|
kf->rotation.y = -fbuf[1];
|
||||||
kf->rotation.z = -fbuf[2];
|
kf->rotation.z = -fbuf[2];
|
||||||
kf->rotation.w = fbuf[3];
|
kf->rotation.w = fbuf[3];
|
||||||
kf->deltaTime = fbuf[4]; // absolute time here
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}else if(strncmp(info.ident, "KRT0", 4) == 0){
|
||||||
// convert absolute time to deltas
|
seq->SetNumFrames(numFrames, true, false);
|
||||||
for(l = seq->numFrames-1; l > 0; l--){
|
KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0);
|
||||||
KeyFrame *kf1 = seq->GetKeyFrame(l);
|
for(l = 0; l < numFrames; l++, kf++){
|
||||||
KeyFrame *kf2 = seq->GetKeyFrame(l-1);
|
RwStreamRead(stream, buf, 0x20);
|
||||||
kf1->deltaTime -= kf2->deltaTime;
|
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)
|
// convert absolute time to deltas
|
||||||
hier->RemoveUncompressedData();
|
for(l = seq->numFrames-1; l > 0; l--){
|
||||||
else
|
KeyFrame *kf1 = seq->GetKeyFrame(l);
|
||||||
hier->CalcTotalTime();
|
KeyFrame *kf2 = seq->GetKeyFrame(l-1);
|
||||||
|
kf1->deltaTime -= kf2->deltaTime;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hier->RemoveQuaternionFlips();
|
||||||
|
hier->CalcTotalTime();
|
||||||
}
|
}
|
||||||
|
if(animIndex > ms_numAnimations)
|
||||||
|
ms_numAnimations = animIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -913,5 +1011,6 @@ CAnimManager::RemoveLastAnimFile(void)
|
||||||
ms_numAnimBlocks--;
|
ms_numAnimBlocks--;
|
||||||
ms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex;
|
ms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex;
|
||||||
for(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++)
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,17 +31,21 @@ enum AssocGroupId
|
||||||
ASSOCGRP_ROCKETLEFT,
|
ASSOCGRP_ROCKETLEFT,
|
||||||
ASSOCGRP_ROCKETRIGHT,
|
ASSOCGRP_ROCKETRIGHT,
|
||||||
|
|
||||||
NUM_ANIM_ASSOC_GROUPS
|
NUM_ANIM_ASSOC_GROUPS // should be 61 in the end
|
||||||
};
|
};
|
||||||
|
|
||||||
class CAnimBlendAssociation;
|
class CAnimBlendAssociation;
|
||||||
class CAnimBlendAssocGroup;
|
class CAnimBlendAssocGroup;
|
||||||
|
|
||||||
|
#define MAX_ANIMBLOCK_NAME 20
|
||||||
|
|
||||||
// A block of hierarchies
|
// A block of hierarchies
|
||||||
struct CAnimBlock
|
struct CAnimBlock
|
||||||
{
|
{
|
||||||
char name[24];
|
char name[MAX_ANIMBLOCK_NAME];
|
||||||
int32 firstIndex;
|
bool isLoaded;
|
||||||
|
int16 refCount;
|
||||||
|
int32 firstIndex; // first animtion in ms_aAnimations
|
||||||
int32 numAnims;
|
int32 numAnims;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,8 +68,8 @@ struct AnimAssocDefinition
|
||||||
class CAnimManager
|
class CAnimManager
|
||||||
{
|
{
|
||||||
static const AnimAssocDefinition ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS];
|
static const AnimAssocDefinition ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS];
|
||||||
static CAnimBlock ms_aAnimBlocks[2];
|
static CAnimBlock ms_aAnimBlocks[NUMANIMBLOCKS];
|
||||||
static CAnimBlendHierarchy ms_aAnimations[250];
|
static CAnimBlendHierarchy ms_aAnimations[NUMANIMATIONS];
|
||||||
static int32 ms_numAnimBlocks;
|
static int32 ms_numAnimBlocks;
|
||||||
static int32 ms_numAnimations;
|
static int32 ms_numAnimations;
|
||||||
static CAnimBlendAssocGroup *ms_aAnimAssocGroups;
|
static CAnimBlendAssocGroup *ms_aAnimAssocGroups;
|
||||||
|
@ -75,7 +79,15 @@ public:
|
||||||
static void Initialise(void);
|
static void Initialise(void);
|
||||||
static void Shutdown(void);
|
static void Shutdown(void);
|
||||||
static void UncompressAnimation(CAnimBlendHierarchy *anim);
|
static void UncompressAnimation(CAnimBlendHierarchy *anim);
|
||||||
|
static void RemoveFromUncompressedCache(CAnimBlendHierarchy *hier);
|
||||||
static CAnimBlock *GetAnimationBlock(const char *name);
|
static CAnimBlock *GetAnimationBlock(const char *name);
|
||||||
|
static int32 GetAnimationBlockIndex(const char *name);
|
||||||
|
static int32 RegisterAnimBlock(const char *name);
|
||||||
|
static int32 GetNumRefsToAnimBlock(int32 block);
|
||||||
|
static void AddAnimBlockRef(int32 block);
|
||||||
|
static void RemoveAnimBlockRefWithoutDelete(int32 block);
|
||||||
|
static void RemoveAnimBlockRef(int32 block);
|
||||||
|
static void RemoveAnimBlock(int32 block);
|
||||||
static CAnimBlendHierarchy *GetAnimation(const char *name, CAnimBlock *animBlock);
|
static CAnimBlendHierarchy *GetAnimation(const char *name, CAnimBlock *animBlock);
|
||||||
static CAnimBlendHierarchy *GetAnimation(int32 n) { return &ms_aAnimations[n]; }
|
static CAnimBlendHierarchy *GetAnimation(int32 n) { return &ms_aAnimations[n]; }
|
||||||
static const char *GetAnimGroupName(AssocGroupId groupId);
|
static const char *GetAnimGroupName(AssocGroupId groupId);
|
||||||
|
@ -87,6 +99,7 @@ public:
|
||||||
static CAnimBlendAssociation *BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta);
|
static CAnimBlendAssociation *BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta);
|
||||||
static void LoadAnimFiles(void);
|
static void LoadAnimFiles(void);
|
||||||
static void LoadAnimFile(const char *filename);
|
static void LoadAnimFile(const char *filename);
|
||||||
static void LoadAnimFile(int fd, bool compress);
|
static void LoadAnimFile(RwStream *stream, bool compress, char (*somename)[32] = nil);
|
||||||
|
static void CreateAnimAssocGroups(void);
|
||||||
static void RemoveLastAnimFile(void);
|
static void RemoveLastAnimFile(void);
|
||||||
};
|
};
|
||||||
|
|
|
@ -185,23 +185,28 @@ CCutsceneMgr::LoadCutsceneData(const char *szCutsceneName)
|
||||||
CGame::DrasticTidyUpMemory(true);
|
CGame::DrasticTidyUpMemory(true);
|
||||||
|
|
||||||
strcpy(ms_cutsceneName, szCutsceneName);
|
strcpy(ms_cutsceneName, szCutsceneName);
|
||||||
file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
|
|
||||||
|
RwStream *stream;
|
||||||
|
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, "ANIM\\CUTS.IMG");
|
||||||
|
assert(stream);
|
||||||
|
|
||||||
// Load animations
|
// Load animations
|
||||||
sprintf(gString, "%s.IFP", szCutsceneName);
|
sprintf(gString, "%s.IFP", szCutsceneName);
|
||||||
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
|
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
|
||||||
CStreaming::MakeSpaceFor(size << 11);
|
CStreaming::MakeSpaceFor(size << 11);
|
||||||
CStreaming::ImGonnaUseStreamingMemory();
|
CStreaming::ImGonnaUseStreamingMemory();
|
||||||
CFileMgr::Seek(file, offset << 11, SEEK_SET);
|
RwStreamSkip(stream, offset << 11);
|
||||||
CAnimManager::LoadAnimFile(file, false);
|
CAnimManager::LoadAnimFile(stream, false);
|
||||||
ms_cutsceneAssociations.CreateAssociations(szCutsceneName);
|
ms_cutsceneAssociations.CreateAssociations(szCutsceneName);
|
||||||
CStreaming::IHaveUsedStreamingMemory();
|
CStreaming::IHaveUsedStreamingMemory();
|
||||||
ms_animLoaded = true;
|
ms_animLoaded = true;
|
||||||
} else {
|
} else {
|
||||||
ms_animLoaded = false;
|
ms_animLoaded = false;
|
||||||
}
|
}
|
||||||
|
RwStreamClose(stream, nil);
|
||||||
|
|
||||||
// Load camera data
|
// Load camera data
|
||||||
|
file = CFileMgr::OpenFile("ANIM\\CUTS.IMG", "rb");
|
||||||
sprintf(gString, "%s.DAT", szCutsceneName);
|
sprintf(gString, "%s.DAT", szCutsceneName);
|
||||||
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
|
if (ms_pCutsceneDir->FindItem(gString, offset, size)) {
|
||||||
CFileMgr::Seek(file, offset << 11, SEEK_SET);
|
CFileMgr::Seek(file, offset << 11, SEEK_SET);
|
||||||
|
|
|
@ -386,7 +386,6 @@ RpAnimBlendClumpFillFrameArray(RpClump *clump, AnimBlendFrameData **frames)
|
||||||
|
|
||||||
AnimBlendFrameData *pFrameDataFound;
|
AnimBlendFrameData *pFrameDataFound;
|
||||||
|
|
||||||
// FrameFindCallBack on PS2
|
|
||||||
void
|
void
|
||||||
FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
|
FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
|
||||||
{
|
{
|
||||||
|
@ -395,7 +394,6 @@ FrameFindByNameCBnonskin(AnimBlendFrameData *frame, void *arg)
|
||||||
pFrameDataFound = frame;
|
pFrameDataFound = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PED_SKIN
|
|
||||||
void
|
void
|
||||||
FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
|
FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
|
||||||
{
|
{
|
||||||
|
@ -403,21 +401,33 @@ FrameFindByNameCBskin(AnimBlendFrameData *frame, void *arg)
|
||||||
if(name && CGeneral::faststricmp(name, (char*)arg) == 0)
|
if(name && CGeneral::faststricmp(name, (char*)arg) == 0)
|
||||||
pFrameDataFound = frame;
|
pFrameDataFound = frame;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
void
|
||||||
|
FrameFindByBoneCB(AnimBlendFrameData *frame, void *arg)
|
||||||
|
{
|
||||||
|
if(frame->nodeID == (int32)(uintptr)arg)
|
||||||
|
pFrameDataFound = frame;
|
||||||
|
}
|
||||||
|
|
||||||
AnimBlendFrameData*
|
AnimBlendFrameData*
|
||||||
RpAnimBlendClumpFindFrame(RpClump *clump, const char *name)
|
RpAnimBlendClumpFindFrame(RpClump *clump, const char *name)
|
||||||
{
|
{
|
||||||
pFrameDataFound = nil;
|
pFrameDataFound = nil;
|
||||||
#ifdef PED_SKIN
|
|
||||||
if(IsClumpSkinned(clump))
|
if(IsClumpSkinned(clump))
|
||||||
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBskin, (void*)name);
|
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBskin, (void*)name);
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBnonskin, (void*)name);
|
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByNameCBnonskin, (void*)name);
|
||||||
return pFrameDataFound;
|
return pFrameDataFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimBlendFrameData*
|
||||||
|
RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag)
|
||||||
|
{
|
||||||
|
pFrameDataFound = nil;
|
||||||
|
(*RPANIMBLENDCLUMPDATA(clump))->ForAllFrames(FrameFindByBoneCB, (void*)boneTag);
|
||||||
|
return pFrameDataFound;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta)
|
RpAnimBlendClumpUpdateAnimations(RpClump *clump, float timeDelta)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@ void RpAnimBlendClumpInit(RpClump *clump);
|
||||||
bool RpAnimBlendClumpIsInitialized(RpClump *clump);
|
bool RpAnimBlendClumpIsInitialized(RpClump *clump);
|
||||||
void RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames);
|
void RpAnimBlendClumpFillFrameArray(RpClump* clump, AnimBlendFrameData** frames);
|
||||||
AnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name);
|
AnimBlendFrameData *RpAnimBlendClumpFindFrame(RpClump *clump, const char *name);
|
||||||
|
AnimBlendFrameData *RpAnimBlendClumpFindBone(RpClump *clump, uint32 boneTag);
|
||||||
void FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg);
|
void FillFrameArrayCallBack(AnimBlendFrameData *frame, void *arg);
|
||||||
CAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id);
|
CAnimBlendAssociation *RpAnimBlendClumpGetAssociation(RpClump *clump, uint32 id);
|
||||||
CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation(RpClump *clump, CAnimBlendAssociation **assocRet, float *blendRet);
|
CAnimBlendAssociation *RpAnimBlendClumpGetMainAssociation(RpClump *clump, CAnimBlendAssociation **assocRet, float *blendRet);
|
||||||
|
|
|
@ -1529,7 +1529,6 @@ CCamera::UpdateTargetEntity(void)
|
||||||
pTargetEntity = FindPlayerVehicle();
|
pTargetEntity = FindPlayerVehicle();
|
||||||
else{
|
else{
|
||||||
pTargetEntity = FindPlayerPed();
|
pTargetEntity = FindPlayerPed();
|
||||||
#ifndef GTA_PS2_STUFF
|
|
||||||
// this keeps the camera on the player while entering cars
|
// this keeps the camera on the player while entering cars
|
||||||
if(PLAYER->GetPedState() == PED_ENTER_CAR ||
|
if(PLAYER->GetPedState() == PED_ENTER_CAR ||
|
||||||
PLAYER->GetPedState() == PED_CARJACK ||
|
PLAYER->GetPedState() == PED_CARJACK ||
|
||||||
|
@ -1539,7 +1538,6 @@ CCamera::UpdateTargetEntity(void)
|
||||||
if(!enteringCar)
|
if(!enteringCar)
|
||||||
if(Cams[ActiveCam].CamTargetEntity != pTargetEntity)
|
if(Cams[ActiveCam].CamTargetEntity != pTargetEntity)
|
||||||
Cams[ActiveCam].CamTargetEntity = pTargetEntity;
|
Cams[ActiveCam].CamTargetEntity = pTargetEntity;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cantOpen = true;
|
bool cantOpen = true;
|
||||||
|
@ -1558,16 +1556,9 @@ CCamera::UpdateTargetEntity(void)
|
||||||
|
|
||||||
if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){
|
if((PLAYER->GetPedState() == PED_CARJACK || PLAYER->GetPedState() == PED_OPEN_DOOR) && !cantOpen){
|
||||||
if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS)
|
if(!enteringCar && CarZoomIndicator != CAM_ZOOM_1STPRS)
|
||||||
#ifdef GTA_PS2_STUFF
|
|
||||||
// dunno if this has any amazing effects
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
pTargetEntity = PLAYER->m_pMyVehicle;
|
pTargetEntity = PLAYER->m_pMyVehicle;
|
||||||
if(PLAYER->m_pMyVehicle == nil)
|
if(PLAYER->m_pMyVehicle == nil)
|
||||||
pTargetEntity = PLAYER;
|
pTargetEntity = PLAYER;
|
||||||
#ifdef GTA_PS2_STUFF
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PLAYER->GetPedState() == PED_EXIT_CAR)
|
if(PLAYER->GetPedState() == PED_EXIT_CAR)
|
||||||
|
|
|
@ -39,7 +39,7 @@ CColStore::AddColSlot(const char *name)
|
||||||
ColDef *def = ms_pColPool->New();
|
ColDef *def = ms_pColPool->New();
|
||||||
assert(def);
|
assert(def);
|
||||||
def->isLoaded = false;
|
def->isLoaded = false;
|
||||||
def->a = 0;
|
def->unused = 0;
|
||||||
def->bounds.left = 1000000.0f;
|
def->bounds.left = 1000000.0f;
|
||||||
def->bounds.top = 1000000.0f;
|
def->bounds.top = 1000000.0f;
|
||||||
def->bounds.right = -1000000.0f;
|
def->bounds.right = -1000000.0f;
|
||||||
|
@ -133,6 +133,7 @@ CColStore::LoadAllCollision(void)
|
||||||
for(i = 1; i < COLSTORESIZE; i++)
|
for(i = 1; i < COLSTORESIZE; i++)
|
||||||
if(GetSlot(i))
|
if(GetSlot(i))
|
||||||
CStreaming::RequestCol(i, 0);
|
CStreaming::RequestCol(i, 0);
|
||||||
|
|
||||||
CStreaming::LoadAllRequestedModels(false);
|
CStreaming::LoadAllRequestedModels(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "templates.h"
|
#include "templates.h"
|
||||||
|
|
||||||
struct ColDef { // made up name
|
struct ColDef { // made up name
|
||||||
int32 a;
|
int32 unused;
|
||||||
bool isLoaded;
|
bool isLoaded;
|
||||||
CRect bounds;
|
CRect bounds;
|
||||||
char name[20];
|
char name[20];
|
||||||
|
|
|
@ -358,7 +358,7 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
|
||||||
|
|
||||||
*dot = '\0';
|
*dot = '\0';
|
||||||
|
|
||||||
if(!CGeneral::faststricmp(dot+1, "DFF")){
|
if(strncasecmp(dot+1, "DFF", 3) == 0){
|
||||||
if(CModelInfo::GetModelInfo(direntry.name, &modelId)){
|
if(CModelInfo::GetModelInfo(direntry.name, &modelId)){
|
||||||
bAddToStreaming = true;
|
bAddToStreaming = true;
|
||||||
}else{
|
}else{
|
||||||
|
@ -370,13 +370,13 @@ CStreaming::LoadCdDirectory(const char *dirname, int n)
|
||||||
#endif
|
#endif
|
||||||
lastID = -1;
|
lastID = -1;
|
||||||
}
|
}
|
||||||
}else if(!CGeneral::faststricmp(dot+1, "TXD")){
|
}else if(strncasecmp(dot+1, "TXD", 3) == 0){
|
||||||
modelId = CTxdStore::FindTxdSlot(direntry.name);
|
modelId = CTxdStore::FindTxdSlot(direntry.name);
|
||||||
if(modelId == -1)
|
if(modelId == -1)
|
||||||
modelId = CTxdStore::AddTxdSlot(direntry.name);
|
modelId = CTxdStore::AddTxdSlot(direntry.name);
|
||||||
modelId += STREAM_OFFSET_TXD;
|
modelId += STREAM_OFFSET_TXD;
|
||||||
bAddToStreaming = true;
|
bAddToStreaming = true;
|
||||||
}else if(!CGeneral::faststricmp(dot+1, "COL")){
|
}else if(strncasecmp(dot+1, "COL", 3) == 0){
|
||||||
modelId = CColStore::FindColSlot(direntry.name);
|
modelId = CColStore::FindColSlot(direntry.name);
|
||||||
if(modelId == -1)
|
if(modelId == -1)
|
||||||
modelId = CColStore::AddColSlot(direntry.name);
|
modelId = CColStore::AddColSlot(direntry.name);
|
||||||
|
@ -413,7 +413,7 @@ GetObjectName(int streamId)
|
||||||
sprintf(objname, "%s.dff", CModelInfo::GetModelInfo(streamId)->GetName());
|
sprintf(objname, "%s.dff", CModelInfo::GetModelInfo(streamId)->GetName());
|
||||||
else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL)
|
else if(streamId >= STREAM_OFFSET_TXD && streamId < STREAM_OFFSET_COL)
|
||||||
sprintf(objname, "%s.txd", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD));
|
sprintf(objname, "%s.txd", CTxdStore::GetTxdName(streamId-STREAM_OFFSET_TXD));
|
||||||
else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO)
|
else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM)
|
||||||
sprintf(objname, "%s.col", CColStore::GetColName(streamId-STREAM_OFFSET_COL));
|
sprintf(objname, "%s.col", CColStore::GetColName(streamId-STREAM_OFFSET_COL));
|
||||||
// TODO(MIAMI): IFP
|
// TODO(MIAMI): IFP
|
||||||
return objname;
|
return objname;
|
||||||
|
@ -506,7 +506,7 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
|
||||||
RwStreamClose(stream, &mem);
|
RwStreamClose(stream, &mem);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}else if(streamId >= STREAM_OFFSET_COL && streamId < NUMSTREAMINFO){
|
}else if(streamId >= STREAM_OFFSET_COL && streamId < STREAM_OFFSET_ANIM){
|
||||||
if(!CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length)){
|
if(!CColStore::LoadCol(streamId-STREAM_OFFSET_COL, mem.start, mem.length)){
|
||||||
debug("Failed to load %s.col\n", CColStore::GetColName(streamId - STREAM_OFFSET_COL));
|
debug("Failed to load %s.col\n", CColStore::GetColName(streamId - STREAM_OFFSET_COL));
|
||||||
RemoveModel(streamId);
|
RemoveModel(streamId);
|
||||||
|
@ -514,6 +514,8 @@ CStreaming::ConvertBufferToObject(int8 *buf, int32 streamId)
|
||||||
RwStreamClose(stream, &mem);
|
RwStreamClose(stream, &mem);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}else if(streamId >= STREAM_OFFSET_ANIM){
|
||||||
|
assert(streamId < NUMSTREAMINFO);
|
||||||
// TODO(MIAMI): IFP
|
// TODO(MIAMI): IFP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,7 +831,7 @@ CStreaming::RemoveModel(int32 id)
|
||||||
CModelInfo::GetModelInfo(id)->DeleteRwObject();
|
CModelInfo::GetModelInfo(id)->DeleteRwObject();
|
||||||
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
|
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
|
||||||
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
|
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
|
||||||
else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO)
|
else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)
|
||||||
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
|
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
|
||||||
// TODO(MIAMI): IFP
|
// TODO(MIAMI): IFP
|
||||||
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
|
ms_memoryUsed -= ms_aInfoForModel[id].GetCdSize()*CDSTREAM_SECTOR_SIZE;
|
||||||
|
@ -854,7 +856,7 @@ CStreaming::RemoveModel(int32 id)
|
||||||
RpClumpGtaCancelStream();
|
RpClumpGtaCancelStream();
|
||||||
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
|
else if(id >= STREAM_OFFSET_TXD && id < STREAM_OFFSET_COL)
|
||||||
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
|
CTxdStore::RemoveTxd(id - STREAM_OFFSET_TXD);
|
||||||
else if(id >= STREAM_OFFSET_COL && id < NUMSTREAMINFO)
|
else if(id >= STREAM_OFFSET_COL && id < STREAM_OFFSET_ANIM)
|
||||||
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
|
CColStore::RemoveCol(id - STREAM_OFFSET_COL);
|
||||||
// TODO(MIAMI): IFP
|
// TODO(MIAMI): IFP
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
enum {
|
enum {
|
||||||
STREAM_OFFSET_TXD = MODELINFOSIZE,
|
STREAM_OFFSET_TXD = MODELINFOSIZE,
|
||||||
STREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE,
|
STREAM_OFFSET_COL = STREAM_OFFSET_TXD+TXDSTORESIZE,
|
||||||
NUMSTREAMINFO = STREAM_OFFSET_COL+COLSTORESIZE
|
STREAM_OFFSET_ANIM = STREAM_OFFSET_COL+COLSTORESIZE,
|
||||||
|
NUMSTREAMINFO = STREAM_OFFSET_ANIM+NUMANIMBLOCKS
|
||||||
};
|
};
|
||||||
|
|
||||||
enum StreamFlags
|
enum StreamFlags
|
||||||
|
@ -118,16 +119,19 @@ public:
|
||||||
static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }
|
static bool HasModelLoaded(int32 id) { return ms_aInfoForModel[id].m_loadState == STREAMSTATE_LOADED; }
|
||||||
static bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); }
|
static bool HasTxdLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_TXD); }
|
||||||
static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); }
|
static bool HasColLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_COL); }
|
||||||
|
static bool HasAnimLoaded(int32 id) { return HasModelLoaded(id+STREAM_OFFSET_ANIM); }
|
||||||
static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; }
|
static bool CanRemoveModel(int32 id) { return (ms_aInfoForModel[id].m_flags & STREAMFLAGS_CANT_REMOVE) == 0; }
|
||||||
static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); }
|
static bool CanRemoveTxd(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_TXD); }
|
||||||
static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); }
|
static bool CanRemoveCol(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_COL); }
|
||||||
|
static bool CanRemoveAnim(int32 id) { return CanRemoveModel(id+STREAM_OFFSET_ANIM); }
|
||||||
static void RequestModel(int32 model, int32 flags);
|
static void RequestModel(int32 model, int32 flags);
|
||||||
static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); }
|
static void ReRequestModel(int32 model) { RequestModel(model, ms_aInfoForModel[model].m_flags); }
|
||||||
static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); }
|
static void RequestTxd(int32 txd, int32 flags) { RequestModel(txd + STREAM_OFFSET_TXD, flags); }
|
||||||
static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); }
|
static void ReRequestTxd(int32 txd) { ReRequestModel(txd + STREAM_OFFSET_TXD); }
|
||||||
static void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); }
|
static void RequestCol(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_COL, flags); }
|
||||||
static void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); }
|
static void ReRequestCol(int32 col) { ReRequestModel(col + STREAM_OFFSET_COL); }
|
||||||
static void RequestSubway(void);
|
static void RequestAnim(int32 col, int32 flags) { RequestModel(col + STREAM_OFFSET_ANIM, flags); }
|
||||||
|
static void ReRequestAnim(int32 col) { ReRequestModel(col + STREAM_OFFSET_ANIM); }
|
||||||
static void RequestBigBuildings(eLevelName level);
|
static void RequestBigBuildings(eLevelName level);
|
||||||
static void RequestBigBuildings(eLevelName level, const CVector &pos);
|
static void RequestBigBuildings(eLevelName level, const CVector &pos);
|
||||||
static void InstanceBigBuildings(eLevelName level, const CVector &pos);
|
static void InstanceBigBuildings(eLevelName level, const CVector &pos);
|
||||||
|
@ -140,6 +144,7 @@ public:
|
||||||
static void RemoveModel(int32 id);
|
static void RemoveModel(int32 id);
|
||||||
static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); }
|
static void RemoveTxd(int32 id) { RemoveModel(id + STREAM_OFFSET_TXD); }
|
||||||
static void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); }
|
static void RemoveCol(int32 id) { RemoveModel(id + STREAM_OFFSET_COL); }
|
||||||
|
static void RemoveAnim(int32 id) { RemoveModel(id + STREAM_OFFSET_ANIM); }
|
||||||
static void RemoveUnusedBuildings(eLevelName level);
|
static void RemoveUnusedBuildings(eLevelName level);
|
||||||
static void RemoveBuildings(eLevelName level);
|
static void RemoveBuildings(eLevelName level);
|
||||||
static void RemoveUnusedBigBuildings(eLevelName level);
|
static void RemoveUnusedBigBuildings(eLevelName level);
|
||||||
|
@ -149,7 +154,6 @@ public:
|
||||||
static bool RemoveLeastUsedModel(uint32 excludeMask);
|
static bool RemoveLeastUsedModel(uint32 excludeMask);
|
||||||
static void RemoveAllUnusedModels(void);
|
static void RemoveAllUnusedModels(void);
|
||||||
static void RemoveUnusedModelsInLoadedList(void);
|
static void RemoveUnusedModelsInLoadedList(void);
|
||||||
static bool RemoveReferencedTxds(int32 mem);
|
|
||||||
static int32 GetAvailableVehicleSlot(void);
|
static int32 GetAvailableVehicleSlot(void);
|
||||||
static bool IsTxdUsedByRequestedModels(int32 txdId);
|
static bool IsTxdUsedByRequestedModels(int32 txdId);
|
||||||
static bool AddToLoadedVehiclesList(int32 modelId);
|
static bool AddToLoadedVehiclesList(int32 modelId);
|
||||||
|
|
|
@ -187,6 +187,7 @@ public:
|
||||||
|
|
||||||
#if (defined(_MSC_VER))
|
#if (defined(_MSC_VER))
|
||||||
extern int strcasecmp(const char *str1, const char *str2);
|
extern int strcasecmp(const char *str1, const char *str2);
|
||||||
|
extern int strncasecmp(const char *str1, const char *str2, size_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v))
|
#define clamp(v, low, high) ((v)<(low) ? (low) : (v)>(high) ? (high) : (v))
|
||||||
|
|
|
@ -38,6 +38,9 @@ enum Config {
|
||||||
NUMCUTSCENEOBJECTS = 50, // does not exist in VC
|
NUMCUTSCENEOBJECTS = 50, // does not exist in VC
|
||||||
// TODO(MIAMI): colmodel pool
|
// TODO(MIAMI): colmodel pool
|
||||||
|
|
||||||
|
NUMANIMBLOCKS = 35,
|
||||||
|
NUMANIMATIONS = 450,
|
||||||
|
|
||||||
NUMTEMPOBJECTS = 30,
|
NUMTEMPOBJECTS = 30,
|
||||||
|
|
||||||
// Path data
|
// Path data
|
||||||
|
|
|
@ -1678,5 +1678,9 @@ int strcasecmp(const char* str1, const char* str2)
|
||||||
{
|
{
|
||||||
return _strcmpi(str1, str2);
|
return _strcmpi(str1, str2);
|
||||||
}
|
}
|
||||||
|
int strncasecmp(const char *str1, const char *str2, size_t len)
|
||||||
|
{
|
||||||
|
return _strnicmp(str1, str2, len);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
|
@ -3150,5 +3150,9 @@ int strcasecmp(const char *str1, const char *str2)
|
||||||
{
|
{
|
||||||
return _strcmpi(str1, str2);
|
return _strcmpi(str1, str2);
|
||||||
}
|
}
|
||||||
|
int strncasecmp(const char *str1, const char *str2, size_t len)
|
||||||
|
{
|
||||||
|
return _strnicmp(str1, str2, len);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue