Initial commit.
This commit is contained in:
414
tools/ModView/anims.cpp
Normal file
414
tools/ModView/anims.cpp
Normal file
@@ -0,0 +1,414 @@
|
||||
// Filename:- anims.cpp
|
||||
//
|
||||
// Module to read basic animation-description files...
|
||||
//
|
||||
// Currently reads either "<name>.frames" and/or "animtion.cfg" files...
|
||||
//
|
||||
#include "stdafx.h"
|
||||
#include "includes.h"
|
||||
//
|
||||
#include "sequence.h"
|
||||
//
|
||||
#include "anims.h"
|
||||
|
||||
|
||||
|
||||
bool Anims_ReadFile_FRAMES(ModelContainer_t *pContainer, LPCSTR psLocalFilename_GLA)
|
||||
{
|
||||
LPCSTR psFilename = va("%s%s.frames",gamedir,Filename_WithoutExt(psLocalFilename_GLA));
|
||||
|
||||
FILE *fHandle = fopen(psFilename,"rt");
|
||||
|
||||
if (fHandle)
|
||||
{
|
||||
// file format is like this per XSI...
|
||||
//
|
||||
// models/test/m4/m44keith.xsi
|
||||
// {
|
||||
// startframe "0"
|
||||
// duration "2"
|
||||
// }
|
||||
//
|
||||
// so...
|
||||
|
||||
Sequence_t Sequence;
|
||||
|
||||
bool bStartFrameRead = false;
|
||||
bool bDurationRead = false;
|
||||
bool bFPSRead = false;
|
||||
|
||||
char sLine[1024];
|
||||
|
||||
while (fgets(sLine,sizeof(sLine)-1,fHandle)!=NULL)
|
||||
{
|
||||
if (bStartFrameRead && bDurationRead && bFPSRead)
|
||||
{
|
||||
pContainer->SequenceList.push_back(Sequence);
|
||||
bStartFrameRead = false;
|
||||
bDurationRead = false;
|
||||
bFPSRead = false;
|
||||
}
|
||||
|
||||
sLine[sizeof(sLine)-1]='\0';
|
||||
strlwr(sLine);
|
||||
|
||||
// :-)
|
||||
CString str(sLine);
|
||||
str.TrimLeft();
|
||||
str.TrimRight();
|
||||
str.Replace("\"","");
|
||||
strcpy(sLine,str);
|
||||
|
||||
if (strstr(sLine,".xsi"))
|
||||
{
|
||||
Sequence_Clear(&Sequence);
|
||||
strcpy(Sequence.sName,Filename_WithoutPath(Filename_WithoutExt(sLine)));
|
||||
|
||||
// these can be really long...
|
||||
strncpy(Sequence.sNameWithPath,Filename_WithoutExt(sLine),sizeof(Sequence.sNameWithPath));
|
||||
Sequence.sNameWithPath[sizeof(Sequence.sNameWithPath)-1]='\0';
|
||||
}
|
||||
else
|
||||
if (strnicmp(sLine,"startframe",strlen("startframe"))==0)
|
||||
{
|
||||
CString str(&sLine[strlen("startframe")]);
|
||||
str.Replace("\"","");
|
||||
Sequence.iStartFrame = atoi(str);
|
||||
|
||||
bStartFrameRead = true;
|
||||
}
|
||||
else
|
||||
if (strnicmp(sLine,"duration",strlen("duration"))==0)
|
||||
{
|
||||
CString str(&sLine[strlen("duration")]);
|
||||
str.Replace("\"","");
|
||||
Sequence.iFrameCount = atoi(str);
|
||||
|
||||
bDurationRead = true;
|
||||
}
|
||||
else
|
||||
if (strnicmp(sLine,"fps",strlen("fps"))==0)
|
||||
{
|
||||
CString str(&sLine[strlen("fps")]);
|
||||
str.Replace("\"","");
|
||||
Sequence.iFPS = atoi(str);
|
||||
|
||||
bFPSRead = true;
|
||||
}
|
||||
}
|
||||
fclose(fHandle);
|
||||
}
|
||||
|
||||
return !!(pContainer->SequenceList.size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Code pasted from MD3View and hacked about a bit..............
|
||||
//
|
||||
// this has now been re-written to only add to pulldown menus when all menus have been scanned, this way
|
||||
// I can strcat frame info to the seq names while keeping a smooth tabbing line...
|
||||
//
|
||||
// Note that this function can automatically read either ID format or Raven format files transparently...
|
||||
//
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
string sName;
|
||||
int iStartFrame;
|
||||
int iFrameCount;
|
||||
int iLoopFrame;
|
||||
int iFrameSpeed;
|
||||
bool bMultiSeq;
|
||||
} Sequence_t;
|
||||
*/
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
char sName[MAX_QPATH]; // eg "run1"
|
||||
int iStartFrame;
|
||||
int iFrameCount;
|
||||
int iLoopFrame; // -1 for no wrap, else framenum to add to iStartFrame
|
||||
// int iFrameSpeed;
|
||||
// bool bMultiSeq;
|
||||
bool bIsDefault; // only true if no anim/enum file found
|
||||
} Sequence_t;
|
||||
*/
|
||||
|
||||
static bool LoadAnimationCFG(LPCSTR psFullPath, ModelContainer_t *pContainer, FILE *handle)//, HDC hDC) // hDC for text metrics
|
||||
{
|
||||
// int iLongestTextMetric = 0;
|
||||
// SIZE Size;
|
||||
bool bOk = false;
|
||||
|
||||
// FILE *handle = fopen(psFullPath,"rt");
|
||||
|
||||
if (handle)
|
||||
{
|
||||
static char sLineBuffer[2048];
|
||||
|
||||
int iFirstFrameAfterBoth = -1; // stuff I need to do for ID's non-folded frame numbers
|
||||
int iFirstFrameAfterTorso= -1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
ZEROMEM(sLineBuffer);
|
||||
if (!fgets(sLineBuffer,sizeof(sLineBuffer),handle))
|
||||
{
|
||||
if (ferror(handle))
|
||||
{
|
||||
ErrorBox(va("Error while reading \"%s\"!",psFullPath));
|
||||
// ClearAnimationCFG();
|
||||
}
|
||||
break; // whether error or EOF
|
||||
}
|
||||
|
||||
char sComment[2048] = {0}; // keep comments now because of the way ID cfg files work
|
||||
|
||||
// zap any comments...
|
||||
//
|
||||
char *p = strstr(sLineBuffer,"//");
|
||||
if (p)
|
||||
{
|
||||
strcpy(sComment,p+2);
|
||||
*p=0;
|
||||
}
|
||||
|
||||
// update, to read ID cfg files, we need to skip over some stuff that Raven ones don't have...
|
||||
//
|
||||
// our cfg files don't have "sex" (how depressingly apt...)
|
||||
//
|
||||
if (strnicmp(sLineBuffer,"sex",3)==0)
|
||||
continue;
|
||||
//
|
||||
// or this other crap either...
|
||||
//
|
||||
if (strnicmp(sLineBuffer,"footsteps",9)==0)
|
||||
continue;
|
||||
if (strnicmp(sLineBuffer,"headoffset",10)==0)
|
||||
continue;
|
||||
if (strnicmp(sLineBuffer,"soundpath",9)==0)
|
||||
continue;
|
||||
|
||||
Sequence_t seq;
|
||||
memset(&seq,0,sizeof(seq));
|
||||
|
||||
char sLine[2048];
|
||||
int iElementsDone = sscanf( sLineBuffer, "%s %d %d %d %d", &sLine, &seq.iStartFrame, &seq.iFrameCount, &seq.iLoopFrame, &seq.iFPS );
|
||||
if (iElementsDone == EOF)
|
||||
continue; // probably skipping over a comment line
|
||||
|
||||
bool bElementsScannedOk = false;
|
||||
|
||||
if (iElementsDone == 5)
|
||||
{
|
||||
// then it must be a Raven line...
|
||||
//
|
||||
bElementsScannedOk = true;
|
||||
// mdview.bAnimIsMultiPlayerFormat = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// try scanning it as an ID line...
|
||||
//
|
||||
iElementsDone = sscanf( sLineBuffer, "%d %d %d %d", &seq.iStartFrame, &seq.iFrameCount, &seq.iLoopFrame, &seq.iFPS );
|
||||
if (iElementsDone == 4)
|
||||
{
|
||||
// mdview.bAnimIsMultiPlayerFormat = true;
|
||||
// scanned an ID line in ok, now convert it to Raven format...
|
||||
//
|
||||
iElementsDone = sscanf( sComment, "%s", &sLine ); // grab anim name from original saved comment
|
||||
if (iElementsDone == 1)
|
||||
{
|
||||
// ... and convert their loop format to ours...
|
||||
//
|
||||
if (seq.iLoopFrame == 0)
|
||||
{
|
||||
seq.iLoopFrame = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
seq.iLoopFrame = seq.iFrameCount - seq.iLoopFrame;
|
||||
}
|
||||
|
||||
|
||||
// now do the folding number stuff since ID don't do it in their files...
|
||||
//
|
||||
if ( !strnicmp(sLine,"TORSO_",6) && iFirstFrameAfterBoth == -1)
|
||||
{
|
||||
iFirstFrameAfterBoth = seq.iStartFrame;
|
||||
}
|
||||
if ( !strnicmp(sLine,"LEGS_",5))
|
||||
{
|
||||
if (iFirstFrameAfterTorso == -1)
|
||||
{
|
||||
iFirstFrameAfterTorso = seq.iStartFrame;
|
||||
}
|
||||
|
||||
// now correct the leg framenumber...
|
||||
//
|
||||
if (iFirstFrameAfterBoth != -1) // if it did, then there'd be no torso frames, so no adj nec.
|
||||
{
|
||||
seq.iStartFrame -= (iFirstFrameAfterTorso - iFirstFrameAfterBoth);
|
||||
}
|
||||
}
|
||||
|
||||
bElementsScannedOk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bElementsScannedOk)
|
||||
{
|
||||
strcpy(seq.sName,sLine);//seq.sName = sLine;
|
||||
|
||||
pContainer->SequenceList.push_back(seq);
|
||||
|
||||
//
|
||||
// this line seems to be ok...
|
||||
//
|
||||
// OutputDebugString(va("%s %d %d %d %d\n",seq.sName.c_str(), seq.iStartFrame, seq.iFrameCount, seq.iLoopFrame, seq.iFrameSpeed ));
|
||||
|
||||
|
||||
// "both" or "torso" get added to 'upper' menu...
|
||||
//
|
||||
/* if ( (!strnicmp(seq.sName.c_str(),"BOTH_",5)) || (!strnicmp(seq.sName.c_str(),"TORSO_",6)) )
|
||||
{
|
||||
Sequences_UpperAnims.push_back(seq);
|
||||
if (iAnimLockLongestString < strlen(seq.sName.c_str()))
|
||||
iAnimLockLongestString = strlen(seq.sName.c_str());
|
||||
|
||||
if (GetTextExtentPoint( hDC, // HDC hdc, // handle to device context
|
||||
seq.sName.c_str(), // LPCTSTR lpString, // pointer to text string
|
||||
strlen(seq.sName.c_str()), // int cbString, // number of characters in string
|
||||
&Size // LPSIZE lpSize // pointer to structure for string size
|
||||
)
|
||||
)
|
||||
{
|
||||
if (iLongestTextMetric < Size.cx)
|
||||
iLongestTextMetric = Size.cx;
|
||||
}
|
||||
|
||||
// Menu_UpperAnims_AddItem(seq.sName.c_str());
|
||||
}
|
||||
|
||||
// "both" or "legs" get added to 'lower' menu...
|
||||
//
|
||||
if ( (!strnicmp(seq.sName.c_str(),"BOTH_",5)) || (!strnicmp(seq.sName.c_str(),"LEGS_",5)) )
|
||||
{
|
||||
Sequences_LowerAnims.push_back(seq);
|
||||
if (iAnimLockLongestString < strlen(seq.sName.c_str()))
|
||||
iAnimLockLongestString = strlen(seq.sName.c_str());
|
||||
|
||||
if (GetTextExtentPoint( hDC, // HDC hdc, // handle to device context
|
||||
seq.sName.c_str(), // LPCTSTR lpString, // pointer to text string
|
||||
strlen(seq.sName.c_str()), // int cbString, // number of characters in string
|
||||
&Size // LPSIZE lpSize // pointer to structure for string size
|
||||
)
|
||||
)
|
||||
{
|
||||
if (iLongestTextMetric < Size.cx)
|
||||
iLongestTextMetric = Size.cx;
|
||||
}
|
||||
|
||||
// Menu_LowerAnims_AddItem(seq.sName.c_str());
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// so do we report this as an error or what?
|
||||
//
|
||||
ErrorBox(sLineBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(handle);
|
||||
/*
|
||||
// now add to menus... (this code is awful, it was simple at first then mutated with feature-add)
|
||||
//
|
||||
char sLine[2048];
|
||||
vector< Sequence_t >::iterator it;
|
||||
for (it=Sequences_UpperAnims.begin(); it!=Sequences_UpperAnims.end(); it++)
|
||||
{
|
||||
sprintf(sLine,(*it).sName.c_str());
|
||||
|
||||
while (1)
|
||||
{
|
||||
GetTextExtentPoint( hDC, // HDC hdc, // handle to device context
|
||||
sLine, // LPCTSTR lpString, // pointer to text string
|
||||
strlen(sLine), // int cbString, // number of characters in string
|
||||
&Size // LPSIZE lpSize // pointer to structure for string size
|
||||
);
|
||||
if (Size.cx >= iLongestTextMetric)
|
||||
break;
|
||||
|
||||
strcat(sLine," ");
|
||||
}
|
||||
|
||||
Menu_UpperAnims_AddItem(va("%s (%d...%d)%s",sLine,(*it).iStartFrame,((*it).iStartFrame+(*it).iFrameCount)-1,((*it).iLoopFrame==-1)?"":va(" Loop %d",(*it).iStartFrame+(*it).iLoopFrame)));
|
||||
}
|
||||
|
||||
for (it=Sequences_LowerAnims.begin(); it!=Sequences_LowerAnims.end(); it++)
|
||||
{
|
||||
sprintf(sLine,(*it).sName.c_str());
|
||||
|
||||
while (1)
|
||||
{
|
||||
GetTextExtentPoint( hDC, // HDC hdc, // handle to device context
|
||||
sLine, // LPCTSTR lpString, // pointer to text string
|
||||
strlen(sLine), // int cbString, // number of characters in string
|
||||
&Size // LPSIZE lpSize // pointer to structure for string size
|
||||
);
|
||||
if (Size.cx >= iLongestTextMetric)
|
||||
break;
|
||||
|
||||
strcat(sLine," ");
|
||||
}
|
||||
|
||||
Menu_LowerAnims_AddItem(va("%s (%d...%d)%s",sLine,(*it).iStartFrame,((*it).iStartFrame+(*it).iFrameCount)-1,((*it).iLoopFrame==-1)?"":va(" Loop %d",(*it).iStartFrame+(*it).iLoopFrame)));
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// a bit of sanity checking, to cope with something Bob tried to do... :-)
|
||||
//
|
||||
Sequence_t* pSeq = NULL;
|
||||
gl_model* pModel;
|
||||
|
||||
if ((pModel = pModel_Lower)!=0)
|
||||
{
|
||||
pSeq = Animation_GetLowerSequence(Animation_GetNumLowerSequences()-1);
|
||||
ReportFrameMismatches(pSeq,pModel);
|
||||
}
|
||||
|
||||
if ((pModel = pModel_Upper)!=0)
|
||||
{
|
||||
pSeq = Animation_GetUpperSequence(Animation_GetNumUpperSequences()-1);
|
||||
ReportFrameMismatches(pSeq,pModel);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//return bOk;
|
||||
return !!(pContainer->SequenceList.size());
|
||||
}
|
||||
|
||||
bool Anims_ReadFile_ANIMATION_CFG(ModelContainer_t *pContainer, LPCSTR psLocalFilename_GLA)
|
||||
{
|
||||
LPCSTR psFilename = va("%s%s/animation.cfg",gamedir,Filename_PathOnly(psLocalFilename_GLA));
|
||||
|
||||
FILE *fHandle = fopen(psFilename,"rt");
|
||||
|
||||
if (fHandle)
|
||||
{
|
||||
if (LoadAnimationCFG(psFilename, pContainer, fHandle))
|
||||
{
|
||||
//
|
||||
}
|
||||
fclose(fHandle);
|
||||
}
|
||||
|
||||
return !!(pContainer->SequenceList.size());
|
||||
}
|
||||
Reference in New Issue
Block a user