mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-09-01 23:19:18 +00:00
upload "kind" alien swarm
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
//============ Copyright (c) Valve Corporation, All rights reserved. ============
|
||||
//
|
||||
// Boilerplate template code to generically instantiate tilegen
|
||||
// classes by name and parse them from KeyValues files.
|
||||
//
|
||||
//===============================================================================
|
||||
|
||||
#ifndef TILEGEN_CLASS_FACTORIES_H
|
||||
#define TILEGEN_CLASS_FACTORIES_H
|
||||
|
||||
#if defined( COMPILER_MSVC )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "utlvector.h"
|
||||
#include "KeyValues.h"
|
||||
#include "tilegen_class_interfaces.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This function must be called at least once before any tilegen
|
||||
// expression, action, or range classes are parsed.
|
||||
// Subsequent calls are ignored.
|
||||
//-----------------------------------------------------------------------------
|
||||
void RegisterAllTilegenClasses();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The most generic, abstract base form of a tilegen class factory.
|
||||
// Each derived template instantiation is capable of instantiating a single
|
||||
// kind of tilegen class derived from TTilegenInterface.
|
||||
//
|
||||
// TTilegenInterface - the type of interface this class factory returns,
|
||||
// e.g. ITilegenExpression< int >, ITilegenRange< const CExit * >,
|
||||
// ITilegenAction
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TTilegenInterface >
|
||||
class ITilegenClassFactory
|
||||
{
|
||||
public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates an instance of the tilegen class this factory is templated on.
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual TTilegenInterface * CreateInstance() = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Gets the friendly string name of the tilegen class this factory produces.
|
||||
//-----------------------------------------------------------------------------
|
||||
virtual const char *GetName() = 0;
|
||||
|
||||
static TTilegenInterface *ReadLiteralValue( KeyValues *pKeyValues )
|
||||
{
|
||||
// Only some tilegen classes can be loaded this way.
|
||||
Log_Warning( LOG_TilegenLayoutSystem, "Tilegen class does not support literal values.\n" );
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
// Annoying workaround due to template specialization rules.
|
||||
// I want these implemented in a .cpp elsewhere but if I simply do a template prototype and define the function elsewhere,
|
||||
// it won't specialize. So I need a fully implemented template specialization to call these functions.
|
||||
ITilegenExpression< int > *ReadLiteralIntValue( KeyValues *pKeyValues );
|
||||
ITilegenExpression< bool > *ReadLiteralBoolValue( KeyValues *pKeyValues );
|
||||
ITilegenExpression< float > *ReadLiteralFloatValue( KeyValues *pKeyValues );
|
||||
ITilegenExpression< const char * > *ReadLiteralStringValue( KeyValues *pKeyValues );
|
||||
|
||||
// Class factory specializations to handle parsing literal values...
|
||||
|
||||
ITilegenExpression< int > *ITilegenClassFactory< ITilegenExpression< int > >::ReadLiteralValue( KeyValues *pKeyValues )
|
||||
{
|
||||
return ReadLiteralIntValue( pKeyValues );
|
||||
}
|
||||
|
||||
ITilegenExpression< bool > *ITilegenClassFactory< ITilegenExpression< bool > >::ReadLiteralValue( KeyValues *pKeyValues )
|
||||
{
|
||||
return ReadLiteralBoolValue( pKeyValues );
|
||||
}
|
||||
|
||||
ITilegenExpression< float > *ITilegenClassFactory< ITilegenExpression< float > >::ReadLiteralValue( KeyValues *pKeyValues )
|
||||
{
|
||||
return ReadLiteralFloatValue( pKeyValues );
|
||||
}
|
||||
|
||||
ITilegenExpression< char const * > *ITilegenClassFactory< ITilegenExpression< char const * > >::ReadLiteralValue( KeyValues *pKeyValues )
|
||||
{
|
||||
return ReadLiteralStringValue( pKeyValues );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Implementation of a generic tilegen class factory which
|
||||
// can be specialized to implement either expression, action, and range class
|
||||
// factories.
|
||||
//
|
||||
// TTilegenInterface - the type of interface this class factory produces,
|
||||
// e.g. ITilegenExpression< int >, ITilegenRange< const CExit * >,
|
||||
// ITilegenAction
|
||||
// TTilegenClass - the specific class (which must derive from
|
||||
// TTilegenInterface) that this factory actually produduces,
|
||||
// e.g. CTilegenExpression_Add, CTilegenRange_NewOpenExits,
|
||||
// CTilegenAction_SwitchState
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TTilegenInterface, typename TTilegenClass >
|
||||
class CTilegenClassFactory : public ITilegenClassFactory< TTilegenInterface >
|
||||
{
|
||||
public:
|
||||
virtual TTilegenInterface * CreateInstance() { return new TTilegenClass(); }
|
||||
virtual const char *GetName();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class factory type to produce tilegen expressions.
|
||||
//
|
||||
// TExpressionValue - the type the expression class returns, e.g. bool, int
|
||||
// TExpressionClass - the specific type of the expression, e.g.
|
||||
// CTilegenExpression_Add
|
||||
//
|
||||
// TExpressionClass must derive from ITilegenExpression< TExpressionValue >
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TExpressionValue, typename TExpressionClass >
|
||||
class CTilegenExpressionClassFactory : public CTilegenClassFactory< ITilegenExpression< TExpressionValue >, TExpressionClass >
|
||||
{
|
||||
public:
|
||||
// Must be implemented for each specialization of CTilegenExpressionClassFactory
|
||||
// (see macro IMPLEMENT_TILEGEN_EXPRESSION in tilegen_class_factories.cpp).
|
||||
virtual const char *GetName();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class factory type to produce tilegen actions.
|
||||
//
|
||||
// TActionClass - the specific type of the action, e.g.
|
||||
// CTilegenAction_SwitchState
|
||||
//
|
||||
// TActionClass must derive from ITilegenAction
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TActionClass >
|
||||
class CTilegenActionClassFactory : public CTilegenClassFactory< ITilegenAction, TActionClass >
|
||||
{
|
||||
public:
|
||||
// Must be implemented for each specialization of CTilegenActionClassFactory
|
||||
// (see macro IMPLEMENT_TILEGEN_ACTION in tilegen_class_factories.cpp).
|
||||
virtual const char *GetName();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class factory type to produce tilegen ranges.
|
||||
//
|
||||
// TElementValue - the type of each element in the range, e.g. const CExit *
|
||||
// TRangeClass - the specific type of the range, e.g.
|
||||
// CTilegenRange_NewOpenExits, CTilegenRange_ClosedExits
|
||||
//
|
||||
// TRangeClass must derive from ITilegenRange< TElementValue >
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TElementValue, typename TRangeClass >
|
||||
class CTilegenRangeClassFactory : public CTilegenClassFactory< ITilegenRange< TElementValue >, TRangeClass >
|
||||
{
|
||||
public:
|
||||
// Must be implemented for each specialization of CTilegenRangeClassFactory
|
||||
// (see macro IMPLEMENT_TILEGEN_RANGE in tilegen_class_factories.cpp).
|
||||
virtual const char *GetName();
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A class registry which is capable of instantiating any class
|
||||
// which has a class factory instance registered with it.
|
||||
// A list of class factories is tracked and searched by string when
|
||||
// an instance of a particular type is requested.
|
||||
//
|
||||
// TTilegenInterface - base interface class which is returned when a
|
||||
// new instance is created.
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TTilegenInterface >
|
||||
class CTilegenClassRegistry
|
||||
{
|
||||
typedef ITilegenClassFactory< TTilegenInterface > TTilegenClassFactoryInterface;
|
||||
public:
|
||||
// @TODO: do we need cleanup the CUtlVector for each instance of this class?
|
||||
// If so, we're better off making implicit linked lists, since
|
||||
// each factory class is statically allocated..
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Registers a new factory instance which can produce a specific type of
|
||||
// tilegen class.
|
||||
//-----------------------------------------------------------------------------
|
||||
static void AddFactory( TTilegenClassFactoryInterface *pFactory )
|
||||
{
|
||||
m_FactoryList.AddToTail( pFactory );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates an instance of the class specified by pClassName
|
||||
//-----------------------------------------------------------------------------
|
||||
static TTilegenInterface *CreateInstance( const char *pClassName )
|
||||
{
|
||||
for ( int i = 0; i < m_FactoryList.Count(); ++ i )
|
||||
{
|
||||
if ( Q_stricmp( m_FactoryList[i]->GetName(), pClassName ) == 0 )
|
||||
{
|
||||
return m_FactoryList[i]->CreateInstance();
|
||||
}
|
||||
}
|
||||
Log_Warning( LOG_TilegenLayoutSystem, "Class %s not found in %s. Check the class name spelling and the context in which it is used.\n", pClassName, m_pFactoryName );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
static CUtlVector< TTilegenClassFactoryInterface * > m_FactoryList;
|
||||
static const char *m_pFactoryName;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Parses KeyValues data and instantiates the appropriate class
|
||||
//
|
||||
// bCreateEmptyInstance is used in the rare case where the caller needs
|
||||
// the object created but not actually loaded from KeyValues.
|
||||
// (One example of this is CTilegenExpression_MapReduce, which uses binary
|
||||
// operators to fold/reduce values together but does not need any state
|
||||
// in the operators to function.
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TTilegenInterface >
|
||||
static TTilegenInterface *CreateFromKeyValues( KeyValues *pKeyValues, bool bCreateEmptyInstance = false )
|
||||
{
|
||||
if ( pKeyValues->GetFirstSubKey() == NULL )
|
||||
{
|
||||
// Code to handle literal/inline values
|
||||
return ITilegenClassFactory< TTilegenInterface >::ReadLiteralValue( pKeyValues );
|
||||
}
|
||||
|
||||
const char *pClassName = pKeyValues->GetString( "class", NULL );
|
||||
if ( pClassName == NULL )
|
||||
{
|
||||
Log_Warning( LOG_TilegenLayoutSystem, "No class name specified for class instantiation in key values.\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TTilegenInterface *pNewClass = CTilegenClassRegistry< TTilegenInterface >::CreateInstance( pClassName );
|
||||
if ( pNewClass != NULL && !bCreateEmptyInstance && !pNewClass->LoadFromKeyValues( pKeyValues ) )
|
||||
{
|
||||
delete pNewClass;
|
||||
pNewClass = NULL;
|
||||
}
|
||||
return pNewClass;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates the appropriate tilegen class from the specified sub-key
|
||||
// of KeyValues data.
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TTilegenClass >
|
||||
bool CreateFromKeyValuesBlock( KeyValues *pParentKV, const char *pKeyName, const char *pParentClassName, TTilegenClass **ppClass, bool bOptional = false, bool bCreateEmptyInstance = false )
|
||||
{
|
||||
KeyValues *pSubKey = pParentKV->FindKey( pKeyName );
|
||||
*ppClass = NULL;
|
||||
if ( pSubKey == NULL )
|
||||
{
|
||||
if ( bOptional )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Log_Warning( LOG_TilegenLayoutSystem, "Could not load sub-key '%s' for parent class '%s'.\n", pKeyName, pParentClassName );
|
||||
return false;
|
||||
}
|
||||
|
||||
*ppClass = CreateFromKeyValues< TTilegenClass >( pSubKey, bCreateEmptyInstance );
|
||||
if ( *ppClass == NULL )
|
||||
{
|
||||
Log_Warning( LOG_TilegenLayoutSystem, "Could not create class for sub-key '%s' for parent class '%s'.\n", pKeyName, pParentClassName );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates the appropriate tilegen expression class from the specified sub-key
|
||||
// of KeyValues data.
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TExpressionValue >
|
||||
bool CreateExpressionFromKeyValuesBlock( KeyValues *pParentKV, const char *pKeyName, const char *pParentClassName, ITilegenExpression< TExpressionValue > **ppClass, bool bOptional = false, bool bCreateEmptyInstance = false )
|
||||
{
|
||||
return CreateFromKeyValuesBlock< ITilegenExpression< TExpressionValue > >( pParentKV, pKeyName, pParentClassName, ppClass, bOptional, bCreateEmptyInstance );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates the appropriate tilegen action and boolean expression class
|
||||
// (if present) from the specified KeyValues data.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CreateActionAndCondition( KeyValues *pKeyValues, ITilegenAction **ppAction, ITilegenExpression< bool > **ppCondition );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates the appropriate tilegen action and boolean expression class
|
||||
// (if present) from the specified sub-key of KeyValues data.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CreateActionAndConditionFromKeyValuesBlock( KeyValues *pParentKV, const char *pKeyName, const char *pParentClassName, ITilegenAction **ppAction, ITilegenExpression< bool > **ppCondition );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates the appropriate tilegen range class from the specified sub-key
|
||||
// of KeyValues data.
|
||||
//-----------------------------------------------------------------------------
|
||||
template< typename TElementValue >
|
||||
bool CreateRangeFromKeyValuesBlock( KeyValues *pParentKV, const char *pKeyName, const char *pParentClassName, ITilegenRange< TElementValue > **ppClass )
|
||||
{
|
||||
return CreateFromKeyValuesBlock< ITilegenRange< TElementValue > >( pParentKV, pKeyName, pParentClassName, ppClass );
|
||||
}
|
||||
|
||||
#endif // TILEGEN_CLASS_FACTORIES_H
|
||||
Reference in New Issue
Block a user