diff options
| author | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:31:46 -0800 |
|---|---|---|
| committer | Jørgen P. Tjernø <[email protected]> | 2013-12-02 19:46:31 -0800 |
| commit | f56bb35301836e56582a575a75864392a0177875 (patch) | |
| tree | de61ddd39de3e7df52759711950b4c288592f0dc /mp/src/fgdlib/gdclass.cpp | |
| parent | Mark some more files as text. (diff) | |
| download | source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip | |
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/fgdlib/gdclass.cpp')
| -rw-r--r-- | mp/src/fgdlib/gdclass.cpp | 2082 |
1 files changed, 1041 insertions, 1041 deletions
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 <tier0/memdbgon.h>
-
-
-//-----------------------------------------------------------------------------
-// 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:
-//
-// <helpername>(<parameter 0> <parameter 1> ... <parameter n>)
-//
-// 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<const char *> *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 <tier0/memdbgon.h> + + +//----------------------------------------------------------------------------- +// 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: +// +// <helpername>(<parameter 0> <parameter 1> ... <parameter n>) +// +// 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<const char *> *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()); + } + } + } +} + + + |