From f56bb35301836e56582a575a75864392a0177875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Mon, 2 Dec 2013 19:31:46 -0800 Subject: Fix line endings. WHAMMY. --- mp/src/fgdlib/gdclass.cpp | 2082 ++++++++++++++++++++++----------------------- 1 file changed, 1041 insertions(+), 1041 deletions(-) (limited to 'mp/src/fgdlib/gdclass.cpp') diff --git a/mp/src/fgdlib/gdclass.cpp b/mp/src/fgdlib/gdclass.cpp index be07610e..1de57b6a 100644 --- a/mp/src/fgdlib/gdclass.cpp +++ b/mp/src/fgdlib/gdclass.cpp @@ -1,1041 +1,1041 @@ -//========= Copyright Valve Corporation, All rights reserved. ============// -// -// Purpose: -// -//============================================================================= - -#include "fgdlib/GameData.h" // FGDLIB: eliminate dependency -#include "fgdlib/GDClass.h" - -// memdbgon must be the last include file in a .cpp file!!! -#include - - -//----------------------------------------------------------------------------- -// Purpose: Constructor. -//----------------------------------------------------------------------------- -GDclass::GDclass(void) -{ - m_nVariables = 0; - m_bBase = false; - m_bSolid = false; - m_bBase = false; - m_bSolid = false; - m_bModel = false; - m_bMove = false; - m_bKeyFrame = false; - m_bPoint = false; - m_bNPC = false; - m_bFilter = false; - - m_bHalfGridSnap = false; - - m_bGotSize = false; - m_bGotColor = false; - - m_rgbColor.r = 220; - m_rgbColor.g = 30; - m_rgbColor.b = 220; - m_rgbColor.a = 0; - - m_pszDescription = NULL; - - for (int i = 0; i < 3; i++) - { - m_bmins[i] = -8; - m_bmaxs[i] = 8; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Destructor. Frees variable and helper lists. -//----------------------------------------------------------------------------- -GDclass::~GDclass(void) -{ - // - // Free variables. - // - int nCount = m_Variables.Count(); - for (int i = 0; i < nCount; i++) - { - GDinputvariable *pvi = m_Variables.Element(i); - delete pvi; - } - m_Variables.RemoveAll(); - - // - // Free helpers. - // - nCount = m_Helpers.Count(); - for (int i = 0; i < nCount; i++) - { - CHelperInfo *pHelper = m_Helpers.Element(i); - delete pHelper; - } - m_Helpers.RemoveAll(); - - // - // Free inputs. - // - nCount = m_Inputs.Count(); - for (int i = 0; i < nCount; i++) - { - CClassInput *pInput = m_Inputs.Element(i); - delete pInput; - } - m_Inputs.RemoveAll(); - - // - // Free outputs. - // - nCount = m_Outputs.Count(); - for (int i = 0; i < nCount; i++) - { - CClassOutput *pOutput = m_Outputs.Element(i); - delete pOutput; - } - m_Outputs.RemoveAll(); - - delete m_pszDescription; -} - - -//----------------------------------------------------------------------------- -// Purpose: Adds the base class's variables to our variable list. Acquires the -// base class's bounding box and color, if any. -// Input : pszBase - Name of base class to add. -//----------------------------------------------------------------------------- -void GDclass::AddBase(GDclass *pBase) -{ - int iBaseIndex; - Parent->ClassForName(pBase->GetName(), &iBaseIndex); - - // - // Add variables from base - update variable table - // - for (int i = 0; i < pBase->GetVariableCount(); i++) - { - GDinputvariable *pVar = pBase->GetVariableAt(i); - AddVariable(pVar, pBase, iBaseIndex, i); - } - - // - // Add inputs from the base. - // UNDONE: need to use references to inputs & outputs to conserve memory - // - int nCount = pBase->GetInputCount(); - for (int i = 0; i < nCount; i++) - { - CClassInput *pInput = pBase->GetInput(i); - - CClassInput *pNew = new CClassInput; - *pNew = *pInput; - AddInput(pNew); - } - - // - // Add outputs from the base. - // - nCount = pBase->GetOutputCount(); - for (int i = 0; i < nCount; i++) - { - CClassOutput *pOutput = pBase->GetOutput(i); - - CClassOutput *pNew = new CClassOutput; - *pNew = *pOutput; - AddOutput(pNew); - } - - // - // If we don't have a bounding box, try to get the base's box. - // - if (!m_bGotSize) - { - if (pBase->GetBoundBox(m_bmins, m_bmaxs)) - { - m_bGotSize = true; - } - } - - // - // If we don't have a color, use the base's color. - // - if (!m_bGotColor) - { - m_rgbColor = pBase->GetColor(); - m_bGotColor = true; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: Adds the given GDInputVariable to this GDClass's list of variables. -// Input : pVar - -// pBase - -// iBaseIndex - -// iVarIndex - -// Output : Returns TRUE if the pVar pointer was copied directly into this GDClass, -// FALSE if not. If this function returns TRUE, pVar should not be -// deleted by the caller. -//----------------------------------------------------------------------------- -BOOL GDclass::AddVariable(GDinputvariable *pVar, GDclass *pBase, int iBaseIndex, int iVarIndex) -{ - int iThisIndex; - GDinputvariable *pThisVar = VarForName(pVar->GetName(), &iThisIndex); - - // - // Check to see if we are overriding an existing variable definition. - // - if (pThisVar != NULL) - { - // - // Same name, different type. Flag this as an error. - // - if (pThisVar->GetType() != pVar->GetType()) - { - return(false); - } - - GDinputvariable *pAddVar; - bool bReturn; - - // - // Check to see if we need to combine a choices/flags array. - // - if (pVar->GetType() == ivFlags || pVar->GetType() == ivChoices) - { - // - // Combine two variables' flags into a new variable. Add the new - // variable to the local variable list and modify the old variable's - // position in our variable map to reflect the new local variable. - // This way, we can have multiple inheritance. - // - GDinputvariable *pNewVar = new GDinputvariable; - - *pNewVar = *pVar; - pNewVar->Merge(*pThisVar); - - pAddVar = pNewVar; - bReturn = false; - } - else - { - pAddVar = pVar; - bReturn = true; - } - - if (m_VariableMap[iThisIndex][0] == -1) - { - // - // "pThisVar" is a leaf variable - we can remove since it is overridden. - // - int nIndex = m_Variables.Find(pThisVar); - Assert(nIndex != -1); - delete pThisVar; - - m_Variables.Element(nIndex) = pAddVar; - - // - // No need to modify variable map - we just replaced - // the pointer in the local variable list. - // - } - else - { - // - // "pThisVar" was declared in a base class - we can replace the reference in - // our variable map with the new variable. - // - m_VariableMap[iThisIndex][0] = iBaseIndex; - - if (iBaseIndex == -1) - { - m_Variables.AddToTail(pAddVar); - m_VariableMap[iThisIndex][1] = m_Variables.Count() - 1; - } - else - { - m_VariableMap[iThisIndex][1] = iVarIndex; - } - } - - return(bReturn); - } - - // - // New variable. - // - if (iBaseIndex == -1) - { - // - // Variable declared in the leaf class definition - add it to the list. - // - m_Variables.AddToTail(pVar); - } - - // - // Too many variables already declared in this class definition - abort. - // - if (m_nVariables == GD_MAX_VARIABLES) - { - //CUtlString str; - //str.Format("Too many gamedata variables for class \"%s\"", m_szName); - //AfxMessageBox(str); - - return(false); - } - - // - // Add the variable to our list. - // - m_VariableMap[m_nVariables][0] = iBaseIndex; - m_VariableMap[m_nVariables][1] = iVarIndex; - ++m_nVariables; - - // - // We added the pointer to our list of items (see Variables.AddToTail, above) so - // we must return true here. - // - return(true); -} - - -//----------------------------------------------------------------------------- -// Finds an input by name. -//----------------------------------------------------------------------------- -CClassInput *GDclass::FindInput(const char *szName) -{ - int nCount = GetInputCount(); - for (int i = 0; i < nCount; i++) - { - CClassInput *pInput = GetInput(i); - if (!stricmp(pInput->GetName(), szName)) - { - return(pInput); - } - } - - return(NULL); -} - - -//----------------------------------------------------------------------------- -// Finds an output by name. -//----------------------------------------------------------------------------- -CClassOutput *GDclass::FindOutput(const char *szName) -{ - int nCount = GetOutputCount(); - for (int i = 0; i < nCount; i++) - { - CClassOutput *pOutput = GetOutput(i); - if (!stricmp(pOutput->GetName(), szName)) - { - return(pOutput); - } - } - - return(NULL); -} - - -//----------------------------------------------------------------------------- -// Purpose: Gets the mins and maxs of the class's bounding box as read from the -// FGD file. This controls the onscreen representation of any entities -// derived from this class. -// Input : pfMins - Receives minimum X, Y, and Z coordinates for the class. -// pfMaxs - Receives maximum X, Y, and Z coordinates for the class. -// Output : Returns TRUE if this class has a specified bounding box, FALSE if not. -//----------------------------------------------------------------------------- -BOOL GDclass::GetBoundBox(Vector& pfMins, Vector& pfMaxs) -{ - if (m_bGotSize) - { - pfMins[0] = m_bmins[0]; - pfMins[1] = m_bmins[1]; - pfMins[2] = m_bmins[2]; - - pfMaxs[0] = m_bmaxs[0]; - pfMaxs[1] = m_bmaxs[1]; - pfMaxs[2] = m_bmaxs[2]; - } - - return(m_bGotSize); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CHelperInfo *GDclass::GetHelper(int nIndex) -{ - return m_Helpers.Element(nIndex); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CClassInput *GDclass::GetInput(int nIndex) -{ - return m_Inputs.Element(nIndex); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -CClassOutput *GDclass::GetOutput(int nIndex) -{ - return m_Outputs.Element(nIndex); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : tr - -// pGD - -// Output : Returns TRUE if worth continuing, FALSE otherwise. -//----------------------------------------------------------------------------- -BOOL GDclass::InitFromTokens(TokenReader& tr, GameData *pGD) -{ - Parent = pGD; - - // - // Initialize VariableMap - // - for (int i = 0; i < GD_MAX_VARIABLES; i++) - { - m_VariableMap[i][0] = -1; - m_VariableMap[i][1] = -1; - } - - // - // Parse all specifiers (base, size, color, etc.) - // - if (!ParseSpecifiers(tr)) - { - return(FALSE); - } - - // - // Specifiers should be followed by an "=" - // - if (!GDSkipToken(tr, OPERATOR, "=")) - { - return(FALSE); - } - - // - // Parse the class name. - // - if (!GDGetToken(tr, m_szName, sizeof(m_szName), IDENT)) - { - return(FALSE); - } - - // - // Check next operator - if ":", we have a description - if "[", - // we have no description. - // - char szToken[MAX_TOKEN]; - if ((tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR) && IsToken(szToken, ":")) - { - // Skip ":" - tr.NextToken(szToken, sizeof(szToken)); - - // - // Free any existing description and set the pointer to NULL so that GDGetToken - // allocates memory for us. - // - delete m_pszDescription; - m_pszDescription = NULL; - - // Load description - if (!GDGetTokenDynamic(tr, &m_pszDescription, STRING)) - { - return(FALSE); - } - } - - // - // Opening square brace. - // - if (!GDSkipToken(tr, OPERATOR, "[")) - { - return(FALSE); - } - - // - // Get class variables. - // - if (!ParseVariables(tr)) - { - return(FALSE); - } - - // - // Closing square brace. - // - if (!GDSkipToken(tr, OPERATOR, "]")) - { - return(FALSE); - } - - return(TRUE); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseBase(TokenReader &tr) -{ - char szToken[MAX_TOKEN]; - - while (1) - { - if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT)) - { - return(false); - } - - // - // Find base class in list of classes. - // - GDclass *pBase = Parent->ClassForName(szToken); - if (pBase == NULL) - { - GDError(tr, "undefined base class '%s", szToken); - return(false); - } - - AddBase(pBase); - - if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR)) - { - return(false); - } - - if (IsToken(szToken, ")")) - { - break; - } - else if (!IsToken(szToken, ",")) - { - GDError(tr, "expecting ',' or ')', but found %s", szToken); - return(false); - } - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseColor(TokenReader &tr) -{ - char szToken[MAX_TOKEN]; - - // - // Red. - // - if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) - { - return(false); - } - BYTE r = atoi(szToken); - - // - // Green. - // - if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) - { - return(false); - } - BYTE g = atoi(szToken); - - // - // Blue. - // - if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) - { - return(false); - } - BYTE b = atoi(szToken); - - m_rgbColor.r = r; - m_rgbColor.g = g; - m_rgbColor.b = b; - m_rgbColor.a = 0; - - m_bGotColor = true; - - if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, ")")) - { - return(false); - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: Parses a helper from the FGD file. Helpers are of the following format: -// -// ( ... ) -// -// When this function is called, the helper name has already been parsed. -// Input : tr - Tokenreader to use for parsing. -// pszHelperName - Name of the helper being declared. -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseHelper(TokenReader &tr, char *pszHelperName) -{ - char szToken[MAX_TOKEN]; - - CHelperInfo *pHelper = new CHelperInfo; - pHelper->SetName(pszHelperName); - - bool bCloseParen = false; - while (!bCloseParen) - { - trtoken_t eType = tr.PeekTokenType(szToken,sizeof(szToken)); - - if (eType == OPERATOR) - { - if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR)) - { - delete pHelper; - return(false); - } - - if (IsToken(szToken, ")")) - { - bCloseParen = true; - } - else if (IsToken(szToken, "=")) - { - delete pHelper; - return(false); - } - } - else - { - if (!GDGetToken(tr, szToken, sizeof(szToken), eType)) - { - delete pHelper; - return(false); - } - else - { - pHelper->AddParameter(szToken); - } - } - } - - m_Helpers.AddToTail(pHelper); - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseSize(TokenReader &tr) -{ - char szToken[MAX_TOKEN]; - - // - // Mins. - // - for (int i = 0; i < 3; i++) - { - if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) - { - return(false); - } - - m_bmins[i] = (float)atof(szToken); - } - - if (tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR && IsToken(szToken, ",")) - { - // - // Skip "," - // - tr.NextToken(szToken, sizeof(szToken)); - - // - // Get maxes. - // - for (int i = 0; i < 3; i++) - { - if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) - { - return(false); - } - m_bmaxs[i] = (float)atof(szToken); - } - } - else - { - // - // Split mins across origin. - // - for (int i = 0; i < 3; i++) - { - float div2 = m_bmins[i] / 2; - m_bmaxs[i] = div2; - m_bmins[i] = -div2; - } - } - - m_bGotSize = true; - - if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, ")")) - { - return(false); - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseSpecifiers(TokenReader &tr) -{ - char szToken[MAX_TOKEN]; - - while (tr.PeekTokenType() == IDENT) - { - tr.NextToken(szToken, sizeof(szToken)); - - // - // Handle specifiers that don't have any parens after them. - // - if (IsToken(szToken, "halfgridsnap")) - { - m_bHalfGridSnap = true; - } - else - { - // - // Handle specifiers require parens after them. - // - if (!GDSkipToken(tr, OPERATOR, "(")) - { - return(false); - } - - if (IsToken(szToken, "base")) - { - if (!ParseBase(tr)) - { - return(false); - } - } - else if (IsToken(szToken, "size")) - { - if (!ParseSize(tr)) - { - return(false); - } - } - else if (IsToken(szToken, "color")) - { - if (!ParseColor(tr)) - { - return(false); - } - } - else if (!ParseHelper(tr, szToken)) - { - return(false); - } - } - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads an input using a given token reader. If the input is -// read successfully, the input is added to this class. If not, a -// parsing failure is returned. -// Input : tr - Token reader to use for parsing. -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseInput(TokenReader &tr) -{ - char szToken[MAX_TOKEN]; - - if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT, "input")) - { - return(false); - } - - CClassInput *pInput = new CClassInput; - - bool bReturn = ParseInputOutput(tr, pInput); - if (bReturn) - { - AddInput(pInput); - } - else - { - delete pInput; - } - - return(bReturn); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads an input or output using a given token reader. -// Input : tr - Token reader to use for parsing. -// pInputOutput - Input or output to fill out. -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseInputOutput(TokenReader &tr, CClassInputOutputBase *pInputOutput) -{ - char szToken[MAX_TOKEN]; - - // - // Read the name. - // - if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT)) - { - return(false); - } - - pInputOutput->SetName(szToken); - - // - // Read the type. - // - if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, "(")) - { - return(false); - } - - if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT)) - { - return(false); - } - - InputOutputType_t eType = pInputOutput->SetType(szToken); - if (eType == iotInvalid) - { - GDError(tr, "bad input/output type '%s'", szToken); - return(false); - } - - if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, ")")) - { - return(false); - } - - // - // Check the next operator - if ':', we have a description. - // - if ((tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR) && (IsToken(szToken, ":"))) - { - // - // Skip the ":". - // - tr.NextToken(szToken, sizeof(szToken)); - - // - // Read the description. - // - char *pszDescription; - if (!GDGetTokenDynamic(tr, &pszDescription, STRING)) - { - return(false); - } - - pInputOutput->SetDescription(pszDescription); - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: Reads an output using a given token reader. If the output is -// read successfully, the output is added to this class. If not, a -// parsing failure is returned. -// Input : tr - Token reader to use for parsing. -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseOutput(TokenReader &tr) -{ - char szToken[MAX_TOKEN]; - - if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT, "output")) - { - return(false); - } - - CClassOutput *pOutput = new CClassOutput; - - bool bReturn = ParseInputOutput(tr, pOutput); - if (bReturn) - { - AddOutput(pOutput); - } - else - { - delete pOutput; - } - - return(bReturn); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : &tr - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool GDclass::ParseVariables(TokenReader &tr) -{ - while (1) - { - char szToken[MAX_TOKEN]; - - if (tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR) - { - break; - } - - if (!stricmp(szToken, "input")) - { - if (!ParseInput(tr)) - { - return(false); - } - - continue; - } - - if (!stricmp(szToken, "output")) - { - if (!ParseOutput(tr)) - { - return(false); - } - - continue; - } - - if (!stricmp(szToken, "key")) - { - GDGetToken(tr, szToken, sizeof(szToken)); - } - - GDinputvariable * var = new GDinputvariable; - if (!var->InitFromTokens(tr)) - { - delete var; - return(false); - } - - int nDupIndex; - GDinputvariable *pDupVar = VarForName(var->GetName(), &nDupIndex); - - // check for duplicate variable definitions - if (pDupVar) - { - // Same name, different type. - if (pDupVar->GetType() != var->GetType()) - { - char szError[_MAX_PATH]; - - sprintf(szError, "%s: Variable '%s' is multiply defined with different types.", GetName(), var->GetName()); - GDError(tr, szError); - } - } - - if (!AddVariable(var, this, -1, m_Variables.Count())) - { - delete var; - } - } - - return(true); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : iIndex - -// Output : GDinputvariable * -//----------------------------------------------------------------------------- -GDinputvariable *GDclass::GetVariableAt(int iIndex) -{ - if ( iIndex < 0 || iIndex >= m_nVariables ) - return NULL; - - if (m_VariableMap[iIndex][0] == -1) - { - return m_Variables.Element(m_VariableMap[iIndex][1]); - } - - // find var's owner - GDclass *pVarClass = Parent->GetClass(m_VariableMap[iIndex][0]); - - // find var in pVarClass - return pVarClass->GetVariableAt(m_VariableMap[iIndex][1]); -} - - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -GDinputvariable *GDclass::VarForName(const char *pszName, int *piIndex) -{ - for(int i = 0; i < GetVariableCount(); i++) - { - GDinputvariable *pVar = GetVariableAt(i); - if(!strcmpi(pVar->GetName(), pszName)) - { - if(piIndex) - piIndex[0] = i; - return pVar; - } - } - - return NULL; -} - -void GDclass::GetHelperForGDVar( GDinputvariable *pVar, CUtlVector *pszHelperName ) -{ - const char *pszName = pVar->GetName(); - for( int i = 0; i < GetHelperCount(); i++ ) - { - CHelperInfo *pHelper = GetHelper( i ); - int nParamCount = pHelper->GetParameterCount(); - for ( int j = 0; j < nParamCount; j++ ) - { - if ( !strcmpi( pszName, pHelper->GetParameter( j ) ) ) - { - pszHelperName->AddToTail(pHelper->GetName()); - } - } - } -} - - - +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "fgdlib/GameData.h" // FGDLIB: eliminate dependency +#include "fgdlib/GDClass.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include + + +//----------------------------------------------------------------------------- +// Purpose: Constructor. +//----------------------------------------------------------------------------- +GDclass::GDclass(void) +{ + m_nVariables = 0; + m_bBase = false; + m_bSolid = false; + m_bBase = false; + m_bSolid = false; + m_bModel = false; + m_bMove = false; + m_bKeyFrame = false; + m_bPoint = false; + m_bNPC = false; + m_bFilter = false; + + m_bHalfGridSnap = false; + + m_bGotSize = false; + m_bGotColor = false; + + m_rgbColor.r = 220; + m_rgbColor.g = 30; + m_rgbColor.b = 220; + m_rgbColor.a = 0; + + m_pszDescription = NULL; + + for (int i = 0; i < 3; i++) + { + m_bmins[i] = -8; + m_bmaxs[i] = 8; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor. Frees variable and helper lists. +//----------------------------------------------------------------------------- +GDclass::~GDclass(void) +{ + // + // Free variables. + // + int nCount = m_Variables.Count(); + for (int i = 0; i < nCount; i++) + { + GDinputvariable *pvi = m_Variables.Element(i); + delete pvi; + } + m_Variables.RemoveAll(); + + // + // Free helpers. + // + nCount = m_Helpers.Count(); + for (int i = 0; i < nCount; i++) + { + CHelperInfo *pHelper = m_Helpers.Element(i); + delete pHelper; + } + m_Helpers.RemoveAll(); + + // + // Free inputs. + // + nCount = m_Inputs.Count(); + for (int i = 0; i < nCount; i++) + { + CClassInput *pInput = m_Inputs.Element(i); + delete pInput; + } + m_Inputs.RemoveAll(); + + // + // Free outputs. + // + nCount = m_Outputs.Count(); + for (int i = 0; i < nCount; i++) + { + CClassOutput *pOutput = m_Outputs.Element(i); + delete pOutput; + } + m_Outputs.RemoveAll(); + + delete m_pszDescription; +} + + +//----------------------------------------------------------------------------- +// Purpose: Adds the base class's variables to our variable list. Acquires the +// base class's bounding box and color, if any. +// Input : pszBase - Name of base class to add. +//----------------------------------------------------------------------------- +void GDclass::AddBase(GDclass *pBase) +{ + int iBaseIndex; + Parent->ClassForName(pBase->GetName(), &iBaseIndex); + + // + // Add variables from base - update variable table + // + for (int i = 0; i < pBase->GetVariableCount(); i++) + { + GDinputvariable *pVar = pBase->GetVariableAt(i); + AddVariable(pVar, pBase, iBaseIndex, i); + } + + // + // Add inputs from the base. + // UNDONE: need to use references to inputs & outputs to conserve memory + // + int nCount = pBase->GetInputCount(); + for (int i = 0; i < nCount; i++) + { + CClassInput *pInput = pBase->GetInput(i); + + CClassInput *pNew = new CClassInput; + *pNew = *pInput; + AddInput(pNew); + } + + // + // Add outputs from the base. + // + nCount = pBase->GetOutputCount(); + for (int i = 0; i < nCount; i++) + { + CClassOutput *pOutput = pBase->GetOutput(i); + + CClassOutput *pNew = new CClassOutput; + *pNew = *pOutput; + AddOutput(pNew); + } + + // + // If we don't have a bounding box, try to get the base's box. + // + if (!m_bGotSize) + { + if (pBase->GetBoundBox(m_bmins, m_bmaxs)) + { + m_bGotSize = true; + } + } + + // + // If we don't have a color, use the base's color. + // + if (!m_bGotColor) + { + m_rgbColor = pBase->GetColor(); + m_bGotColor = true; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Adds the given GDInputVariable to this GDClass's list of variables. +// Input : pVar - +// pBase - +// iBaseIndex - +// iVarIndex - +// Output : Returns TRUE if the pVar pointer was copied directly into this GDClass, +// FALSE if not. If this function returns TRUE, pVar should not be +// deleted by the caller. +//----------------------------------------------------------------------------- +BOOL GDclass::AddVariable(GDinputvariable *pVar, GDclass *pBase, int iBaseIndex, int iVarIndex) +{ + int iThisIndex; + GDinputvariable *pThisVar = VarForName(pVar->GetName(), &iThisIndex); + + // + // Check to see if we are overriding an existing variable definition. + // + if (pThisVar != NULL) + { + // + // Same name, different type. Flag this as an error. + // + if (pThisVar->GetType() != pVar->GetType()) + { + return(false); + } + + GDinputvariable *pAddVar; + bool bReturn; + + // + // Check to see if we need to combine a choices/flags array. + // + if (pVar->GetType() == ivFlags || pVar->GetType() == ivChoices) + { + // + // Combine two variables' flags into a new variable. Add the new + // variable to the local variable list and modify the old variable's + // position in our variable map to reflect the new local variable. + // This way, we can have multiple inheritance. + // + GDinputvariable *pNewVar = new GDinputvariable; + + *pNewVar = *pVar; + pNewVar->Merge(*pThisVar); + + pAddVar = pNewVar; + bReturn = false; + } + else + { + pAddVar = pVar; + bReturn = true; + } + + if (m_VariableMap[iThisIndex][0] == -1) + { + // + // "pThisVar" is a leaf variable - we can remove since it is overridden. + // + int nIndex = m_Variables.Find(pThisVar); + Assert(nIndex != -1); + delete pThisVar; + + m_Variables.Element(nIndex) = pAddVar; + + // + // No need to modify variable map - we just replaced + // the pointer in the local variable list. + // + } + else + { + // + // "pThisVar" was declared in a base class - we can replace the reference in + // our variable map with the new variable. + // + m_VariableMap[iThisIndex][0] = iBaseIndex; + + if (iBaseIndex == -1) + { + m_Variables.AddToTail(pAddVar); + m_VariableMap[iThisIndex][1] = m_Variables.Count() - 1; + } + else + { + m_VariableMap[iThisIndex][1] = iVarIndex; + } + } + + return(bReturn); + } + + // + // New variable. + // + if (iBaseIndex == -1) + { + // + // Variable declared in the leaf class definition - add it to the list. + // + m_Variables.AddToTail(pVar); + } + + // + // Too many variables already declared in this class definition - abort. + // + if (m_nVariables == GD_MAX_VARIABLES) + { + //CUtlString str; + //str.Format("Too many gamedata variables for class \"%s\"", m_szName); + //AfxMessageBox(str); + + return(false); + } + + // + // Add the variable to our list. + // + m_VariableMap[m_nVariables][0] = iBaseIndex; + m_VariableMap[m_nVariables][1] = iVarIndex; + ++m_nVariables; + + // + // We added the pointer to our list of items (see Variables.AddToTail, above) so + // we must return true here. + // + return(true); +} + + +//----------------------------------------------------------------------------- +// Finds an input by name. +//----------------------------------------------------------------------------- +CClassInput *GDclass::FindInput(const char *szName) +{ + int nCount = GetInputCount(); + for (int i = 0; i < nCount; i++) + { + CClassInput *pInput = GetInput(i); + if (!stricmp(pInput->GetName(), szName)) + { + return(pInput); + } + } + + return(NULL); +} + + +//----------------------------------------------------------------------------- +// Finds an output by name. +//----------------------------------------------------------------------------- +CClassOutput *GDclass::FindOutput(const char *szName) +{ + int nCount = GetOutputCount(); + for (int i = 0; i < nCount; i++) + { + CClassOutput *pOutput = GetOutput(i); + if (!stricmp(pOutput->GetName(), szName)) + { + return(pOutput); + } + } + + return(NULL); +} + + +//----------------------------------------------------------------------------- +// Purpose: Gets the mins and maxs of the class's bounding box as read from the +// FGD file. This controls the onscreen representation of any entities +// derived from this class. +// Input : pfMins - Receives minimum X, Y, and Z coordinates for the class. +// pfMaxs - Receives maximum X, Y, and Z coordinates for the class. +// Output : Returns TRUE if this class has a specified bounding box, FALSE if not. +//----------------------------------------------------------------------------- +BOOL GDclass::GetBoundBox(Vector& pfMins, Vector& pfMaxs) +{ + if (m_bGotSize) + { + pfMins[0] = m_bmins[0]; + pfMins[1] = m_bmins[1]; + pfMins[2] = m_bmins[2]; + + pfMaxs[0] = m_bmaxs[0]; + pfMaxs[1] = m_bmaxs[1]; + pfMaxs[2] = m_bmaxs[2]; + } + + return(m_bGotSize); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +CHelperInfo *GDclass::GetHelper(int nIndex) +{ + return m_Helpers.Element(nIndex); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +CClassInput *GDclass::GetInput(int nIndex) +{ + return m_Inputs.Element(nIndex); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +CClassOutput *GDclass::GetOutput(int nIndex) +{ + return m_Outputs.Element(nIndex); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : tr - +// pGD - +// Output : Returns TRUE if worth continuing, FALSE otherwise. +//----------------------------------------------------------------------------- +BOOL GDclass::InitFromTokens(TokenReader& tr, GameData *pGD) +{ + Parent = pGD; + + // + // Initialize VariableMap + // + for (int i = 0; i < GD_MAX_VARIABLES; i++) + { + m_VariableMap[i][0] = -1; + m_VariableMap[i][1] = -1; + } + + // + // Parse all specifiers (base, size, color, etc.) + // + if (!ParseSpecifiers(tr)) + { + return(FALSE); + } + + // + // Specifiers should be followed by an "=" + // + if (!GDSkipToken(tr, OPERATOR, "=")) + { + return(FALSE); + } + + // + // Parse the class name. + // + if (!GDGetToken(tr, m_szName, sizeof(m_szName), IDENT)) + { + return(FALSE); + } + + // + // Check next operator - if ":", we have a description - if "[", + // we have no description. + // + char szToken[MAX_TOKEN]; + if ((tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR) && IsToken(szToken, ":")) + { + // Skip ":" + tr.NextToken(szToken, sizeof(szToken)); + + // + // Free any existing description and set the pointer to NULL so that GDGetToken + // allocates memory for us. + // + delete m_pszDescription; + m_pszDescription = NULL; + + // Load description + if (!GDGetTokenDynamic(tr, &m_pszDescription, STRING)) + { + return(FALSE); + } + } + + // + // Opening square brace. + // + if (!GDSkipToken(tr, OPERATOR, "[")) + { + return(FALSE); + } + + // + // Get class variables. + // + if (!ParseVariables(tr)) + { + return(FALSE); + } + + // + // Closing square brace. + // + if (!GDSkipToken(tr, OPERATOR, "]")) + { + return(FALSE); + } + + return(TRUE); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &tr - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseBase(TokenReader &tr) +{ + char szToken[MAX_TOKEN]; + + while (1) + { + if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT)) + { + return(false); + } + + // + // Find base class in list of classes. + // + GDclass *pBase = Parent->ClassForName(szToken); + if (pBase == NULL) + { + GDError(tr, "undefined base class '%s", szToken); + return(false); + } + + AddBase(pBase); + + if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR)) + { + return(false); + } + + if (IsToken(szToken, ")")) + { + break; + } + else if (!IsToken(szToken, ",")) + { + GDError(tr, "expecting ',' or ')', but found %s", szToken); + return(false); + } + } + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &tr - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseColor(TokenReader &tr) +{ + char szToken[MAX_TOKEN]; + + // + // Red. + // + if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) + { + return(false); + } + BYTE r = atoi(szToken); + + // + // Green. + // + if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) + { + return(false); + } + BYTE g = atoi(szToken); + + // + // Blue. + // + if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) + { + return(false); + } + BYTE b = atoi(szToken); + + m_rgbColor.r = r; + m_rgbColor.g = g; + m_rgbColor.b = b; + m_rgbColor.a = 0; + + m_bGotColor = true; + + if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, ")")) + { + return(false); + } + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: Parses a helper from the FGD file. Helpers are of the following format: +// +// ( ... ) +// +// When this function is called, the helper name has already been parsed. +// Input : tr - Tokenreader to use for parsing. +// pszHelperName - Name of the helper being declared. +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseHelper(TokenReader &tr, char *pszHelperName) +{ + char szToken[MAX_TOKEN]; + + CHelperInfo *pHelper = new CHelperInfo; + pHelper->SetName(pszHelperName); + + bool bCloseParen = false; + while (!bCloseParen) + { + trtoken_t eType = tr.PeekTokenType(szToken,sizeof(szToken)); + + if (eType == OPERATOR) + { + if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR)) + { + delete pHelper; + return(false); + } + + if (IsToken(szToken, ")")) + { + bCloseParen = true; + } + else if (IsToken(szToken, "=")) + { + delete pHelper; + return(false); + } + } + else + { + if (!GDGetToken(tr, szToken, sizeof(szToken), eType)) + { + delete pHelper; + return(false); + } + else + { + pHelper->AddParameter(szToken); + } + } + } + + m_Helpers.AddToTail(pHelper); + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &tr - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseSize(TokenReader &tr) +{ + char szToken[MAX_TOKEN]; + + // + // Mins. + // + for (int i = 0; i < 3; i++) + { + if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) + { + return(false); + } + + m_bmins[i] = (float)atof(szToken); + } + + if (tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR && IsToken(szToken, ",")) + { + // + // Skip "," + // + tr.NextToken(szToken, sizeof(szToken)); + + // + // Get maxes. + // + for (int i = 0; i < 3; i++) + { + if (!GDGetToken(tr, szToken, sizeof(szToken), INTEGER)) + { + return(false); + } + m_bmaxs[i] = (float)atof(szToken); + } + } + else + { + // + // Split mins across origin. + // + for (int i = 0; i < 3; i++) + { + float div2 = m_bmins[i] / 2; + m_bmaxs[i] = div2; + m_bmins[i] = -div2; + } + } + + m_bGotSize = true; + + if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, ")")) + { + return(false); + } + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &tr - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseSpecifiers(TokenReader &tr) +{ + char szToken[MAX_TOKEN]; + + while (tr.PeekTokenType() == IDENT) + { + tr.NextToken(szToken, sizeof(szToken)); + + // + // Handle specifiers that don't have any parens after them. + // + if (IsToken(szToken, "halfgridsnap")) + { + m_bHalfGridSnap = true; + } + else + { + // + // Handle specifiers require parens after them. + // + if (!GDSkipToken(tr, OPERATOR, "(")) + { + return(false); + } + + if (IsToken(szToken, "base")) + { + if (!ParseBase(tr)) + { + return(false); + } + } + else if (IsToken(szToken, "size")) + { + if (!ParseSize(tr)) + { + return(false); + } + } + else if (IsToken(szToken, "color")) + { + if (!ParseColor(tr)) + { + return(false); + } + } + else if (!ParseHelper(tr, szToken)) + { + return(false); + } + } + } + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads an input using a given token reader. If the input is +// read successfully, the input is added to this class. If not, a +// parsing failure is returned. +// Input : tr - Token reader to use for parsing. +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseInput(TokenReader &tr) +{ + char szToken[MAX_TOKEN]; + + if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT, "input")) + { + return(false); + } + + CClassInput *pInput = new CClassInput; + + bool bReturn = ParseInputOutput(tr, pInput); + if (bReturn) + { + AddInput(pInput); + } + else + { + delete pInput; + } + + return(bReturn); +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads an input or output using a given token reader. +// Input : tr - Token reader to use for parsing. +// pInputOutput - Input or output to fill out. +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseInputOutput(TokenReader &tr, CClassInputOutputBase *pInputOutput) +{ + char szToken[MAX_TOKEN]; + + // + // Read the name. + // + if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT)) + { + return(false); + } + + pInputOutput->SetName(szToken); + + // + // Read the type. + // + if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, "(")) + { + return(false); + } + + if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT)) + { + return(false); + } + + InputOutputType_t eType = pInputOutput->SetType(szToken); + if (eType == iotInvalid) + { + GDError(tr, "bad input/output type '%s'", szToken); + return(false); + } + + if (!GDGetToken(tr, szToken, sizeof(szToken), OPERATOR, ")")) + { + return(false); + } + + // + // Check the next operator - if ':', we have a description. + // + if ((tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR) && (IsToken(szToken, ":"))) + { + // + // Skip the ":". + // + tr.NextToken(szToken, sizeof(szToken)); + + // + // Read the description. + // + char *pszDescription; + if (!GDGetTokenDynamic(tr, &pszDescription, STRING)) + { + return(false); + } + + pInputOutput->SetDescription(pszDescription); + } + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: Reads an output using a given token reader. If the output is +// read successfully, the output is added to this class. If not, a +// parsing failure is returned. +// Input : tr - Token reader to use for parsing. +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseOutput(TokenReader &tr) +{ + char szToken[MAX_TOKEN]; + + if (!GDGetToken(tr, szToken, sizeof(szToken), IDENT, "output")) + { + return(false); + } + + CClassOutput *pOutput = new CClassOutput; + + bool bReturn = ParseInputOutput(tr, pOutput); + if (bReturn) + { + AddOutput(pOutput); + } + else + { + delete pOutput; + } + + return(bReturn); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &tr - +// Output : Returns true on success, false on failure. +//----------------------------------------------------------------------------- +bool GDclass::ParseVariables(TokenReader &tr) +{ + while (1) + { + char szToken[MAX_TOKEN]; + + if (tr.PeekTokenType(szToken,sizeof(szToken)) == OPERATOR) + { + break; + } + + if (!stricmp(szToken, "input")) + { + if (!ParseInput(tr)) + { + return(false); + } + + continue; + } + + if (!stricmp(szToken, "output")) + { + if (!ParseOutput(tr)) + { + return(false); + } + + continue; + } + + if (!stricmp(szToken, "key")) + { + GDGetToken(tr, szToken, sizeof(szToken)); + } + + GDinputvariable * var = new GDinputvariable; + if (!var->InitFromTokens(tr)) + { + delete var; + return(false); + } + + int nDupIndex; + GDinputvariable *pDupVar = VarForName(var->GetName(), &nDupIndex); + + // check for duplicate variable definitions + if (pDupVar) + { + // Same name, different type. + if (pDupVar->GetType() != var->GetType()) + { + char szError[_MAX_PATH]; + + sprintf(szError, "%s: Variable '%s' is multiply defined with different types.", GetName(), var->GetName()); + GDError(tr, szError); + } + } + + if (!AddVariable(var, this, -1, m_Variables.Count())) + { + delete var; + } + } + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : iIndex - +// Output : GDinputvariable * +//----------------------------------------------------------------------------- +GDinputvariable *GDclass::GetVariableAt(int iIndex) +{ + if ( iIndex < 0 || iIndex >= m_nVariables ) + return NULL; + + if (m_VariableMap[iIndex][0] == -1) + { + return m_Variables.Element(m_VariableMap[iIndex][1]); + } + + // find var's owner + GDclass *pVarClass = Parent->GetClass(m_VariableMap[iIndex][0]); + + // find var in pVarClass + return pVarClass->GetVariableAt(m_VariableMap[iIndex][1]); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +GDinputvariable *GDclass::VarForName(const char *pszName, int *piIndex) +{ + for(int i = 0; i < GetVariableCount(); i++) + { + GDinputvariable *pVar = GetVariableAt(i); + if(!strcmpi(pVar->GetName(), pszName)) + { + if(piIndex) + piIndex[0] = i; + return pVar; + } + } + + return NULL; +} + +void GDclass::GetHelperForGDVar( GDinputvariable *pVar, CUtlVector *pszHelperName ) +{ + const char *pszName = pVar->GetName(); + for( int i = 0; i < GetHelperCount(); i++ ) + { + CHelperInfo *pHelper = GetHelper( i ); + int nParamCount = pHelper->GetParameterCount(); + for ( int j = 0; j < nParamCount; j++ ) + { + if ( !strcmpi( pszName, pHelper->GetParameter( j ) ) ) + { + pszHelperName->AddToTail(pHelper->GetName()); + } + } + } +} + + + -- cgit v1.2.3