Files
Jedi-Academy/tools/ModView/anims.cpp
2013-04-04 14:32:05 -07:00

415 lines
11 KiB
C++

// 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());
}