852 lines
21 KiB
C++
852 lines
21 KiB
C++
// Filename:- script.cpp
|
|
//
|
|
// file to control model-loading scripts (scripts are purely a viewer convenience for multiple-bolt stuff)
|
|
//
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "includes.h"
|
|
#include "ModViewTreeView.h"
|
|
#include "glm_code.h"
|
|
#include "R_Model.h"
|
|
#include "R_Surface.h"
|
|
#include "textures.h"
|
|
#include "TEXT.H"
|
|
#include "sequence.h"
|
|
#include "model.h"
|
|
#include "GenericParser2.h"
|
|
//
|
|
#include "script.h"
|
|
|
|
|
|
|
|
|
|
CGenericParser2 theParser;
|
|
|
|
|
|
|
|
LPCSTR Script_GetExtension(void)
|
|
{
|
|
return sSCRIPT_EXTENSION;
|
|
}
|
|
|
|
|
|
LPCSTR Script_GetFilter(bool bStandAlone /* = true */)
|
|
{
|
|
static char sFilterString[1024];
|
|
|
|
strcpy(sFilterString, "ModView script files (*" sSCRIPT_EXTENSION ")|*" sSCRIPT_EXTENSION "|");
|
|
|
|
strcat(sFilterString,bStandAlone?"|":"");
|
|
return sFilterString;
|
|
}
|
|
|
|
|
|
/*
|
|
bool CString_ExtractLine(CString &strSrc, CString &strDst)
|
|
{
|
|
int iLoc = strSrc.Find("\n");
|
|
if (iLoc!= -1)
|
|
{
|
|
strDst = strSrc.Left(iLoc);
|
|
strSrc = strSrc.Mid(iLoc+1);
|
|
}
|
|
|
|
return (iLoc!=-1);
|
|
}
|
|
|
|
bool CString_ExtractUntil(CString &strSrc, CString &strDst, char cSeperator)
|
|
{
|
|
int iLoc = strSrc.Find(cSeperator);
|
|
if (iLoc!= -1)
|
|
{
|
|
strDst = strSrc.Left(iLoc);
|
|
strSrc = strSrc.Mid(iLoc+1);
|
|
}
|
|
|
|
return (iLoc!=-1);
|
|
}
|
|
*/
|
|
|
|
typedef map<ModelContainer_t*, string> HandleXref_t;
|
|
HandleXref_t HandleXRefs;
|
|
|
|
static CString strHandlesSoFar; // semicolon-delineated string of all handle names, for quick ifdef check
|
|
|
|
static void Script_Clear()
|
|
{
|
|
HandleXRefs.clear();
|
|
strHandlesSoFar = ';'; // initial state = ';' so all finds can check ";<name;"
|
|
}
|
|
|
|
|
|
// generates a unique handlename based on the input suggestion...
|
|
//
|
|
static LPCSTR GenerateHandleName(LPCSTR psIdealBaseName)
|
|
{
|
|
static CString strReturn;
|
|
|
|
int iAlternative = 0;
|
|
|
|
do
|
|
{
|
|
strReturn = psIdealBaseName;
|
|
strReturn.MakeLower();
|
|
|
|
if (iAlternative++)
|
|
strReturn += va("_%d",iAlternative);
|
|
}
|
|
while (strHandlesSoFar.Find(va(";%s;",(LPCSTR) strReturn)) != -1); // note ';' at both ends of find() arg
|
|
|
|
strHandlesSoFar += strReturn;
|
|
strHandlesSoFar += ";"; // doesn't really matter what this is, as long as each name gets seperated
|
|
|
|
return (LPCSTR) strReturn;
|
|
}
|
|
|
|
|
|
static void R_ModelContainer_WriteOptional(ModelContainer_t* pContainer, void *pvData, bool bIsBolt )
|
|
{
|
|
FILE *fhText = (FILE *) pvData;
|
|
|
|
if (Model_GetG2SurfaceRootOverride(pContainer) != -1)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_SURFACENAME_ROOTOVERRIDE, Model_GetSurfaceName(pContainer->hModel, Model_GetG2SurfaceRootOverride(pContainer->hModel)));
|
|
}
|
|
|
|
// name of secondary anim start bone MUST be written out before iSequenceLockNumber_Secondary, or reading won't work...
|
|
//
|
|
if (Model_SecondaryAnimLockingActive(pContainer))
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_BONENAME_SECONDARYSTART, Model_GetBoneName(pContainer->hModel, Model_GetSecondaryAnimStart(pContainer->hModel)));
|
|
}
|
|
|
|
if (pContainer->iSequenceLockNumber_Primary != -1)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_LOCKSEQUENCE, Model_Sequence_GetName(pContainer->hModel, pContainer->iSequenceLockNumber_Primary));
|
|
}
|
|
|
|
if (pContainer->iSequenceLockNumber_Secondary != -1)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_LOCKSEQUENCE_SECONDARY, Model_Sequence_GetName(pContainer->hModel, pContainer->iSequenceLockNumber_Secondary));
|
|
}
|
|
|
|
if (pContainer->bSeqMultiLock_Primary_Active)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_MULTISEQ_PRIMARYLOCK, sANY_NONBLANK_STRING);
|
|
}
|
|
|
|
if (pContainer->bSeqMultiLock_Secondary_Active)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_MULTISEQ_SECONDARYLOCK, sANY_NONBLANK_STRING);
|
|
}
|
|
|
|
// group...
|
|
if (pContainer->SeqMultiLock_Primary.size())
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\n",sSCRIPTKEYWORD_MULTISEQ_PRIMARYLIST);
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "{\n");
|
|
|
|
for (int i=0; i<pContainer->SeqMultiLock_Primary.size(); i++)
|
|
{
|
|
LPCSTR psSeqName = Model_Sequence_GetName(pContainer, pContainer->SeqMultiLock_Primary[i]);
|
|
|
|
if (psSeqName)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t\t":"\t\t");
|
|
fprintf(fhText, "name%d\t\"%s\"\n",i,psSeqName);
|
|
}
|
|
}
|
|
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "}\n");
|
|
}
|
|
|
|
// group...
|
|
if (pContainer->SeqMultiLock_Secondary.size())
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\n",sSCRIPTKEYWORD_MULTISEQ_SECONDARYLIST);
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "{\n");
|
|
|
|
for (int i=0; i<pContainer->SeqMultiLock_Secondary.size(); i++)
|
|
{
|
|
LPCSTR psSeqName = Model_Sequence_GetName(pContainer, pContainer->SeqMultiLock_Secondary[i]);
|
|
|
|
if (psSeqName)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t\t":"\t\t");
|
|
fprintf(fhText, "name%d\t\"%s\"\n",i,psSeqName);
|
|
}
|
|
}
|
|
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "}\n");
|
|
}
|
|
|
|
if (pContainer->SkinSets.size())
|
|
{
|
|
if (!pContainer->strCurrentSkinFile.empty() && !pContainer->strCurrentSkinEthnic.empty())
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_SKINFILE, pContainer->strCurrentSkinFile.c_str());
|
|
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\t\"%s\"\n",sSCRIPTKEYWORD_ETHNIC, pContainer->strCurrentSkinEthnic.c_str());
|
|
}
|
|
}
|
|
|
|
if (pContainer->OldSkinSets.size())
|
|
{
|
|
if (!pContainer->strCurrentSkinFile.empty())
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\t\"%s\"\n",sSCRIPTKEYWORD_OLDSKINFILE, pContainer->strCurrentSkinFile.c_str());
|
|
}
|
|
}
|
|
|
|
// write out all surfaces that are ON that weren't defaulted to ON (ie user-changed)...
|
|
//
|
|
int
|
|
iNumSurfaces = Model_GetNumSurfacesDifferentFromDefault(pContainer,SURF_ON);
|
|
if (iNumSurfaces)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\n",sSCRIPTKEYWORD_SURFACES_ON);
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "{\n");
|
|
|
|
for (int i=0; i<iNumSurfaces; i++)
|
|
{
|
|
LPCSTR psSurfaceName = Model_GetSurfaceDifferentFromDefault(pContainer,SURF_ON,i);
|
|
if (psSurfaceName)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t\t":"\t\t");
|
|
fprintf(fhText, "name%d\t\"%s\"\n",i,psSurfaceName );
|
|
}
|
|
}
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "}\n");
|
|
}
|
|
|
|
// write out all surfaces that are OFF that weren't defaulted to OFF (ie user-changed)...
|
|
//
|
|
iNumSurfaces = Model_GetNumSurfacesDifferentFromDefault(pContainer,SURF_OFF);
|
|
if (iNumSurfaces)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\n",sSCRIPTKEYWORD_SURFACES_OFF);
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "{\n");
|
|
|
|
for (int i=0; i<iNumSurfaces; i++)
|
|
{
|
|
LPCSTR psSurfaceName = Model_GetSurfaceDifferentFromDefault(pContainer,SURF_OFF,i);
|
|
if (psSurfaceName)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t\t":"\t\t");
|
|
fprintf(fhText, "name%d\t\"%s\"\n",i, psSurfaceName);
|
|
}
|
|
}
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "}\n");
|
|
}
|
|
|
|
// write out all surfaces that are OFF+NOCHILDREN (ie user-changed)...
|
|
//
|
|
iNumSurfaces = Model_GetNumSurfacesDifferentFromDefault(pContainer,SURF_NO_DESCENDANTS);
|
|
if (iNumSurfaces)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "%s\n",sSCRIPTKEYWORD_SURFACES_OFFNOCHILDREN);
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "{\n");
|
|
|
|
for (int i=0; i<iNumSurfaces; i++)
|
|
{
|
|
LPCSTR psSurfaceName = Model_GetSurfaceDifferentFromDefault(pContainer,SURF_NO_DESCENDANTS,i);
|
|
if (psSurfaceName)
|
|
{
|
|
fprintf(fhText, bIsBolt?"\t\t\t":"\t\t");
|
|
fprintf(fhText, "name%d\t\"%s\"\n",i, psSurfaceName);
|
|
}
|
|
}
|
|
fprintf(fhText, bIsBolt?"\t\t":"\t");
|
|
fprintf(fhText, "}\n");
|
|
}
|
|
}
|
|
|
|
static void R_ModelContainer_CallBack_WriteBolts(ModelContainer_t* pContainer, void *pvData )
|
|
{
|
|
FILE *fhText = (FILE *) pvData;
|
|
|
|
CString strHandleName = GenerateHandleName(Filename_WithoutPath(Filename_WithoutExt(pContainer->sLocalPathName)));
|
|
|
|
HandleXRefs[ pContainer ] = strHandleName;
|
|
|
|
// main model or bolton?
|
|
if (pContainer->pBoneBolt_ParentContainer == NULL && pContainer->pSurfaceBolt_ParentContainer == NULL)
|
|
{
|
|
// parent...
|
|
//
|
|
/* eg:
|
|
|
|
name "mainwpn"
|
|
modelfile "models/weapons/m4/m4.glm"
|
|
|
|
*/
|
|
|
|
fprintf(fhText, "\t%s\t\t\"%s\"\n",sSCRIPTKEYWORD_NAME, (LPCSTR) strHandleName);
|
|
fprintf(fhText, "\t%s\t\"%s\"\n",sSCRIPTKEYWORD_MODELFILE, (LPCSTR) pContainer->sLocalPathName);
|
|
|
|
R_ModelContainer_WriteOptional(pContainer, pvData, false );
|
|
}
|
|
else
|
|
{
|
|
// bolton...(surface or bone)
|
|
//
|
|
/* eg:
|
|
|
|
boltmodel
|
|
{
|
|
name "ar buffer"
|
|
modelfile "models/test/m4/buffer/buffer.glm"
|
|
parent "mainwpn"
|
|
bolttobone "gun"
|
|
locksequence "right_hand_idle"
|
|
}
|
|
|
|
*/
|
|
|
|
fprintf(fhText, "\t%s\n",sSCRIPTKEYWORD_BOLTMODEL);
|
|
fprintf(fhText, "\t{\n");
|
|
fprintf(fhText, "\t\t%s\t\"%s\"\n",sSCRIPTKEYWORD_NAME, (LPCSTR) strHandleName);
|
|
fprintf(fhText, "\t\t%s\t\"%s\"\n",sSCRIPTKEYWORD_MODELFILE, (LPCSTR) pContainer->sLocalPathName);
|
|
//
|
|
// we're bolted to either a bone or a surface (never both), so...
|
|
//
|
|
if (pContainer->pBoneBolt_ParentContainer)
|
|
{
|
|
fprintf(fhText, "\t\t%s\t\"%s\"\n",sSCRIPTKEYWORD_PARENT, HandleXRefs[pContainer->pBoneBolt_ParentContainer].c_str());
|
|
fprintf(fhText, "\t\t%s\t\"%s\"\n",sSCRIPTKEYWORD_BOLTTOBONE, Model_GetBoltName(pContainer->pBoneBolt_ParentContainer,pContainer->iBoneBolt_ParentBoltIndex, true)); // bBoltIsBone
|
|
}
|
|
else
|
|
{
|
|
fprintf(fhText, "\t\t%s\t\"%s\"\n",sSCRIPTKEYWORD_PARENT, HandleXRefs[pContainer->pSurfaceBolt_ParentContainer].c_str());
|
|
fprintf(fhText, "\t\t%s\t\"%s\"\n",sSCRIPTKEYWORD_BOLTTOSURFACE, Model_GetBoltName(pContainer->pSurfaceBolt_ParentContainer,pContainer->iSurfaceBolt_ParentBoltIndex, false)); // bBoltIsBone
|
|
}
|
|
|
|
R_ModelContainer_WriteOptional(pContainer, pvData, true );
|
|
|
|
fprintf(fhText, "\t}\n");
|
|
}
|
|
|
|
fprintf(fhText,"\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Script_Write(LPCSTR psFullPathedFilename)
|
|
{
|
|
FILE *fhText = NULL;
|
|
|
|
if (Model_Loaded())
|
|
{
|
|
Script_Clear();
|
|
|
|
fhText = fopen(psFullPathedFilename,"wt");
|
|
|
|
if (fhText)
|
|
{
|
|
fprintf(fhText,va("%s\n{\n",sSCRIPTKEYWORD_LOADMODEL));
|
|
|
|
R_ModelContainer_Apply(&AppVars.Container, R_ModelContainer_CallBack_WriteBolts, fhText);
|
|
|
|
fprintf(fhText,"}\n");
|
|
|
|
fprintf(fhText,"\n"); // cosmetic
|
|
|
|
fclose(fhText);
|
|
}
|
|
}
|
|
|
|
return !!fhText;
|
|
}
|
|
|
|
|
|
|
|
// search for certain optional arguments for the model that's just been loaded (whether bolt or primary)..
|
|
//
|
|
// return = errmess, else NULL for ok
|
|
//
|
|
static LPCSTR Script_Parse_ReadOptionalArgs(ModelContainer_t *pContainer, CGPGroup *pParseGroup)
|
|
{
|
|
LPCSTR psError = NULL;
|
|
|
|
// I know this code has loads of spurious string constructors, but I don't care. It's nice and readable,
|
|
// and adds no user-noticeable overhead to file reading...
|
|
//
|
|
do
|
|
{
|
|
string strSurfaceName = pParseGroup->FindPairValue(sSCRIPTKEYWORD_SURFACENAME_ROOTOVERRIDE, "");
|
|
if (strSurfaceName.length())
|
|
{
|
|
if (!Model_SetG2SurfaceRootOverride (pContainer, strSurfaceName.c_str()))
|
|
{
|
|
psError = va("Failed to set model root-surface override \"%s\"",strSurfaceName.c_str());
|
|
}
|
|
}
|
|
|
|
// name of secondary anim start bone MUST be written out before iSequenceLockNumber_Secondary, or reading won't work...
|
|
//
|
|
string strBoneName = pParseGroup->FindPairValue(sSCRIPTKEYWORD_BONENAME_SECONDARYSTART, "");
|
|
if (strBoneName.length())
|
|
{
|
|
if (!Model_SetSecondaryAnimStart(pContainer->hModel, strBoneName.c_str()))
|
|
{
|
|
psError = va("Failed to set secondary anim start bone \"%s\"",strBoneName.c_str());
|
|
break;
|
|
}
|
|
}
|
|
|
|
// "locksequence"...?
|
|
//
|
|
string strSequence = pParseGroup->FindPairValue(sSCRIPTKEYWORD_LOCKSEQUENCE, "");
|
|
if (strSequence.length())
|
|
{
|
|
if (!Model_Sequence_Lock(pContainer->hModel,strSequence.c_str(),true)) // errors displayed internally
|
|
{
|
|
psError = "Failed to lock primary sequence";
|
|
break;
|
|
}
|
|
}
|
|
|
|
// "locksequence_secondary"...?
|
|
//
|
|
strSequence = pParseGroup->FindPairValue(sSCRIPTKEYWORD_LOCKSEQUENCE_SECONDARY, "");
|
|
if (strSequence.length())
|
|
{
|
|
if (!Model_Sequence_Lock(pContainer->hModel,strSequence.c_str(),false)) // errors displayed internally
|
|
{
|
|
psError = "Failed to lock secondary sequence";
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// "skinfile"...?
|
|
//
|
|
string strSkinFile = pParseGroup->FindPairValue(sSCRIPTKEYWORD_SKINFILE, "");
|
|
if (strSkinFile.length())
|
|
{
|
|
string strEthnic = pParseGroup->FindPairValue(sSCRIPTKEYWORD_ETHNIC, "");
|
|
if (strEthnic.length())
|
|
{
|
|
if (!Skins_ApplyEthnic( pContainer, strSkinFile.c_str(), strEthnic.c_str(),false/*findmeste true*/,true))
|
|
{
|
|
psError = va("Failed to apply ethnic \"%s\" of skin \"%s\"",strSkinFile.c_str(), strEthnic.c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// "oldskinfile"...?
|
|
//
|
|
string strOldSkinFile = pParseGroup->FindPairValue(sSCRIPTKEYWORD_OLDSKINFILE, "");
|
|
if (strOldSkinFile.length())
|
|
{
|
|
if (!OldSkins_Apply( pContainer, strOldSkinFile.c_str() ))
|
|
{
|
|
psError = va("Failed to apply skin \"%s\"",strOldSkinFile.c_str());
|
|
break;
|
|
}
|
|
}
|
|
|
|
// multisequence primary and secondary locking...
|
|
//
|
|
string
|
|
strLock = pParseGroup->FindPairValue(sSCRIPTKEYWORD_MULTISEQ_PRIMARYLOCK, "");
|
|
if (strLock.length())
|
|
{
|
|
Model_MultiSeq_SetActive(pContainer->hModel, true, true);
|
|
}
|
|
|
|
strLock = pParseGroup->FindPairValue(sSCRIPTKEYWORD_MULTISEQ_SECONDARYLOCK, "");
|
|
if (strLock.length())
|
|
{
|
|
Model_MultiSeq_SetActive(pContainer->hModel, false, true);
|
|
}
|
|
|
|
// multisequence primary and secondary lists...
|
|
//
|
|
CGPGroup*
|
|
pSubGroup = pParseGroup->FindSubGroup(sSCRIPTKEYWORD_MULTISEQ_PRIMARYLIST);
|
|
if (pSubGroup)
|
|
{
|
|
CGPValue *pValue = pSubGroup->GetPairs();
|
|
while (pValue)
|
|
{
|
|
// string strJunk = (*it).first; // eg 'name0'
|
|
string strSequence = pValue->GetTopValue();
|
|
|
|
int iSeqNum = Model_Sequence_IndexForName(pContainer, strSequence.c_str());
|
|
if (iSeqNum != -1)
|
|
{
|
|
Model_MultiSeq_Add( pContainer->hModel, iSeqNum, true, false);
|
|
}
|
|
|
|
pValue = pValue->GetNext();
|
|
}
|
|
}
|
|
pSubGroup = pParseGroup->FindSubGroup(sSCRIPTKEYWORD_MULTISEQ_SECONDARYLIST);
|
|
if (pSubGroup)
|
|
{
|
|
CGPValue *pValue = pSubGroup->GetPairs();
|
|
while (pValue)
|
|
{
|
|
// string strJunk = (*it).first; // eg 'name0'
|
|
string strSequence = pValue->GetTopValue();
|
|
|
|
int iSeqNum = Model_Sequence_IndexForName(pContainer, strSequence.c_str());
|
|
if (iSeqNum != -1)
|
|
{
|
|
Model_MultiSeq_Add( pContainer->hModel, iSeqNum, false, false);
|
|
}
|
|
|
|
pValue = pValue->GetNext();
|
|
}
|
|
}
|
|
|
|
// now read in any surfaces that were set ON, OFF, or OFF+NO CHILDREN by the user...
|
|
//
|
|
pSubGroup = pParseGroup->FindSubGroup(sSCRIPTKEYWORD_SURFACES_ON);
|
|
if (pSubGroup)
|
|
{
|
|
CGPValue *pValue = pSubGroup->GetPairs();
|
|
while (pValue)
|
|
{
|
|
// string strJunk = (*it).first; // eg 'name0'
|
|
string strSurface = pValue->GetTopValue();
|
|
|
|
Model_GLMSurface_SetStatus( pContainer->hModel, strSurface.c_str(), SURF_ON);
|
|
|
|
pValue = pValue->GetNext();
|
|
}
|
|
}
|
|
|
|
pSubGroup = pParseGroup->FindSubGroup(sSCRIPTKEYWORD_SURFACES_OFF);
|
|
if (pSubGroup)
|
|
{
|
|
CGPValue *pValue = pSubGroup->GetPairs();
|
|
while (pValue)
|
|
{
|
|
// string strJunk = (*it).first; // eg 'name0'
|
|
string strSurface = pValue->GetTopValue();
|
|
|
|
Model_GLMSurface_SetStatus( pContainer->hModel, strSurface.c_str(), SURF_OFF);
|
|
|
|
pValue = pValue->GetNext();
|
|
}
|
|
}
|
|
|
|
pSubGroup = pParseGroup->FindSubGroup(sSCRIPTKEYWORD_SURFACES_OFFNOCHILDREN);
|
|
if (pSubGroup)
|
|
{
|
|
CGPValue *pValue = pSubGroup->GetPairs();
|
|
while (pValue)
|
|
{
|
|
// string strJunk = (*it).first; // eg 'name0'
|
|
string strSurface = pValue->GetTopValue();
|
|
|
|
Model_GLMSurface_SetStatus( pContainer->hModel, strSurface.c_str(), SURF_NO_DESCENDANTS);
|
|
|
|
pValue = pValue->GetNext();
|
|
}
|
|
}
|
|
|
|
// ...
|
|
}
|
|
while(0);
|
|
|
|
|
|
if (psError)
|
|
{
|
|
static string strErrors;
|
|
strErrors = psError;
|
|
strErrors.insert(0,"Script_Parse_ReadOptionalArgs(): ");
|
|
|
|
return strErrors.c_str();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static LPCSTR Script_Parse_BoltModel(CGPGroup *pParseGroup)
|
|
{
|
|
LPCSTR psError = NULL;
|
|
|
|
do
|
|
{
|
|
// "name"...
|
|
//
|
|
string strHandle = pParseGroup->FindPairValue(sSCRIPTKEYWORD_NAME, "");
|
|
if (! (strHandle.length()))
|
|
{
|
|
psError = "No '" sSCRIPTKEYWORD_NAME "' keyword found!";
|
|
break;
|
|
}
|
|
|
|
// "modelfile"...
|
|
//
|
|
string strModelFile = pParseGroup->FindPairValue(sSCRIPTKEYWORD_MODELFILE, "");
|
|
if (! (strModelFile.length()))
|
|
{
|
|
psError = "No '" sSCRIPTKEYWORD_MODELFILE "' keyword found!";
|
|
break;
|
|
}
|
|
|
|
// "parent"...
|
|
//
|
|
string strParentHandle = pParseGroup->FindPairValue(sSCRIPTKEYWORD_PARENT, "");
|
|
if (! (strParentHandle.length()))
|
|
{
|
|
psError = "No '" sSCRIPTKEYWORD_PARENT "' keyword found!";
|
|
break;
|
|
}
|
|
|
|
// "bolttobone" or "bolttosurface"
|
|
//
|
|
string strBoltToBone = pParseGroup->FindPairValue(sSCRIPTKEYWORD_BOLTTOBONE, "");
|
|
string strBoltToSurface = pParseGroup->FindPairValue(sSCRIPTKEYWORD_BOLTTOSURFACE, "");
|
|
if ( !(strBoltToBone.length()) && !(strBoltToSurface.length()) )
|
|
{
|
|
psError = "No '" sSCRIPTKEYWORD_BOLTTOBONE "' or '" sSCRIPTKEYWORD_BOLTTOSURFACE "' keyword found!";
|
|
break;
|
|
}
|
|
|
|
// check parent handle is valid...
|
|
//
|
|
ModelContainer_t *pParentContainer = NULL;
|
|
for (HandleXref_t::iterator it = HandleXRefs.begin(); it!=HandleXRefs.end(); it++)
|
|
{
|
|
pParentContainer = (*it).first;
|
|
string sThisName = (*it).second;
|
|
|
|
if (sThisName == strParentHandle)
|
|
break;
|
|
}
|
|
if (pParentContainer == NULL)
|
|
{
|
|
psError = va("Unknown parent handle \"%s\"",strParentHandle.c_str());
|
|
break;
|
|
}
|
|
|
|
|
|
// read model in...
|
|
//
|
|
char *psFullPathedFileName = va("%s%s",gamedir,strModelFile.c_str());
|
|
//
|
|
// bolt to bone?
|
|
//
|
|
if (strBoltToBone.length())
|
|
{
|
|
if (!Model_LoadBoltOn(psFullPathedFileName, pParentContainer->hModel, strBoltToBone.c_str(), true, false)) // bBoltIsBone, bBoltReplacesAllExisting
|
|
{
|
|
psError = va("Failed to load bonebolt-model \"%s\"",psFullPathedFileName);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// bolt to surface...
|
|
//
|
|
if (!Model_LoadBoltOn(psFullPathedFileName, pParentContainer->hModel, strBoltToSurface.c_str(), false, false)) // bBoltIsBone, bBoltReplacesAllExisting
|
|
{
|
|
psError = va("Failed to load surfacebolt-model \"%s\"",psFullPathedFileName);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// loaded ok...
|
|
//
|
|
ModelContainer_t *pThisContainer = ModelContainer_FindFromModelHandle( AppVars.hModelLastLoaded );
|
|
HandleXRefs[pThisContainer] = strHandle;
|
|
|
|
Script_Parse_ReadOptionalArgs(pThisContainer, pParseGroup);
|
|
}
|
|
while(0);
|
|
|
|
|
|
if (psError)
|
|
{
|
|
static string strErrors;
|
|
strErrors = psError;
|
|
strErrors.insert(0,"Script_Parse_BoltModel(): ");
|
|
|
|
return strErrors.c_str();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
static LPCSTR Script_Parse_LoadModel(CGPGroup *pParseGroup)
|
|
{
|
|
LPCSTR psError = NULL;
|
|
|
|
do
|
|
{
|
|
// "name"...
|
|
//
|
|
string strHandle = pParseGroup->FindPairValue(sSCRIPTKEYWORD_NAME, "");
|
|
if (! (strHandle.length()))
|
|
{
|
|
psError = "No '" sSCRIPTKEYWORD_NAME "' keyword found!";
|
|
break;
|
|
}
|
|
|
|
// "modelfile"...
|
|
//
|
|
string strModelFile = pParseGroup->FindPairValue(sSCRIPTKEYWORD_MODELFILE, "");
|
|
if (! (strModelFile.length()))
|
|
{
|
|
psError = "No '" sSCRIPTKEYWORD_MODELFILE "' keyword found!";
|
|
break;
|
|
}
|
|
|
|
|
|
// read model in... (need to make local version of this to pass, va() gets used too much during load
|
|
//
|
|
extern bool Document_ModelLoadPrimary(LPCSTR psFilename);
|
|
//char *psFullPathModelName = va("%s%s",gamedir,strModelFile.c_str());
|
|
char sFullPathModelName[MAX_PATH];
|
|
strncpy(sFullPathModelName,va("%s%s",gamedir,strModelFile.c_str()),sizeof(sFullPathModelName)-1);
|
|
sFullPathModelName[sizeof(sFullPathModelName)-1]='\0';
|
|
|
|
if (!Document_ModelLoadPrimary( sFullPathModelName ))
|
|
{
|
|
psError = va("Failed to load primary model %s",sFullPathModelName);
|
|
break;
|
|
}
|
|
|
|
// loaded ok...
|
|
//
|
|
ModelContainer_t *pThisContainer = &AppVars.Container;
|
|
HandleXRefs[pThisContainer] = strHandle;
|
|
|
|
psError = Script_Parse_ReadOptionalArgs(pThisContainer, pParseGroup);
|
|
if (psError)
|
|
break;
|
|
|
|
// now check for boltons...
|
|
//
|
|
CGPGroup *pSubGroup = pParseGroup->GetSubGroups();
|
|
while (pSubGroup)
|
|
{
|
|
string strSubGroupType = pSubGroup->GetName();
|
|
|
|
if (strSubGroupType == sSCRIPTKEYWORD_BOLTMODEL)
|
|
{
|
|
if ((psError = Script_Parse_BoltModel(pSubGroup))!=NULL)
|
|
break;
|
|
}
|
|
|
|
pSubGroup = pSubGroup->GetNext();
|
|
}
|
|
if (psError)
|
|
break;
|
|
}
|
|
while(0);
|
|
|
|
|
|
if (psError)
|
|
{
|
|
static string strErrors;
|
|
strErrors = psError;
|
|
strErrors.insert(0,"Script_Parse_LoadModel(): ");
|
|
|
|
return strErrors.c_str();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
bool Script_Read(LPCSTR psFullPathedFilename)
|
|
{
|
|
LPCSTR psError = NULL;
|
|
char *psData = NULL;
|
|
|
|
int iSize = LoadFile(psFullPathedFilename, (void**)&psData);
|
|
if (iSize != -1)
|
|
{
|
|
SetQdirFromPath( psFullPathedFilename );
|
|
|
|
Script_Clear();
|
|
|
|
char *psDataPtr = psData;
|
|
|
|
// parse it...
|
|
//
|
|
if (theParser.Parse(&psDataPtr, true))
|
|
{
|
|
CGPGroup *pFileGroup = theParser.GetBaseParseGroup();
|
|
|
|
CGPGroup *pParseGroup_LoadModel = pFileGroup->FindSubGroup(sSCRIPTKEYWORD_LOADMODEL);//, true);
|
|
|
|
if (pParseGroup_LoadModel)
|
|
{
|
|
// special optional arg for NPC->MVS hackiness...
|
|
//
|
|
string strBaseDir = pParseGroup_LoadModel->FindPairValue(sSCRIPTKEYWORD_BASEDIR, "");
|
|
if (!strBaseDir.empty())
|
|
{
|
|
SetQdirFromPath( strBaseDir.c_str() );
|
|
}
|
|
|
|
psError = Script_Parse_LoadModel(pParseGroup_LoadModel);
|
|
}
|
|
else
|
|
{
|
|
psError = "Unable to find keyword '" sSCRIPTKEYWORD_LOADMODEL "'";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
psError = va("{} - Brace mismatch error in file \"%s\"!",psFullPathedFilename);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
psError = "File not found";
|
|
}
|
|
|
|
SAFEFREE(psData);
|
|
|
|
if (psError)
|
|
{
|
|
ErrorBox(va("Error while reading script file: \"%s\":\n\n%s",psFullPathedFilename,psError));
|
|
}
|
|
|
|
return !psError;
|
|
}
|
|
|
|
|
|
/////////////////// eof /////////////////
|
|
|
|
|