Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

349 lines
11 KiB

  1. //======= Copyright � 1996-2007, Valve Corporation, All rights reserved. ======
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #ifndef VALVEPYTHON_H
  7. #define VALVEPYTHON_H
  8. #if defined( _WIN32 )
  9. #pragma once
  10. #endif
  11. // Python includes
  12. #include <Python.h>
  13. // Valve includes
  14. #include "interface.h"
  15. #include "tier1/utlvector.h"
  16. #include "tier1/utlstring.h"
  17. //-----------------------------------------------------------------------------
  18. // Finds the GetAppFactory function in the specified python module and returns
  19. // the app factory handle or NULL on error
  20. //-----------------------------------------------------------------------------
  21. CreateInterfaceFn ValvePythonAppFactory( const char *pGetAppFactory = "GetAppFactory" );
  22. //=============================================================================
  23. //
  24. // Should be called by each module's init function
  25. //
  26. //=============================================================================
  27. bool ValvePythonInit( CreateInterfaceFn pInFactory = NULL );
  28. //=============================================================================
  29. //
  30. // Python command factory class
  31. //
  32. //=============================================================================
  33. class CValvePythonCommand
  34. {
  35. public:
  36. // Constructor
  37. CValvePythonCommand( const char *pName, PyCFunction pMeth, int nFlags, const char *pDoc )
  38. : m_name( pName )
  39. , m_pMeth( pMeth )
  40. , m_nFlags( nFlags )
  41. , m_doc( pDoc )
  42. {
  43. m_pNextFactory = s_pFirstFactory;
  44. s_pFirstFactory = this;
  45. }
  46. static void Register( char *pModuleName );
  47. protected:
  48. void Register( CUtlVector< PyMethodDef > &pyMethodDefs );
  49. private:
  50. // The next factory
  51. CValvePythonCommand *m_pNextFactory;
  52. static CValvePythonCommand *s_pFirstFactory;
  53. // Has to stay in same place in memory for duration of python
  54. static CUtlVector< PyMethodDef > s_pyMethodDefs;
  55. CUtlString m_name;
  56. PyCFunction m_pMeth;
  57. const int m_nFlags;
  58. CUtlString m_doc;
  59. };
  60. //-----------------------------------------------------------------------------
  61. // Macro to install a valve python command
  62. //
  63. // Use it like this:
  64. //
  65. // PYTHON_COMMAND( foo, METH_VARARGS, "The documentation for foo" )
  66. //-----------------------------------------------------------------------------
  67. #define PYTHON_COMMAND( _name, _flags, _doc ) \
  68. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs ); \
  69. static CValvePythonCommand _name##_command( #_name, _name##_pythonFunc, _flags, _doc ); \
  70. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs )
  71. //-----------------------------------------------------------------------------
  72. // Macro to install a valve python command which uses keywords in the interface
  73. //
  74. // Use it like this:
  75. //
  76. // PYTHON_COMMAND( foo, METH_VARARGS, "The documentation for foo" )
  77. //-----------------------------------------------------------------------------
  78. #define PYTHON_COMMAND_KEYWORDS( _name, _flags, _doc ) \
  79. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords ); \
  80. static CValvePythonCommand _name##_command( #_name, reinterpret_cast< PyCFunction >( _name##_pythonFunc ), _flags, _doc ); \
  81. extern "C" static PyObject *_name##_pythonFunc( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords )
  82. //=============================================================================
  83. //
  84. // Python sub module factory class
  85. //
  86. //=============================================================================
  87. class CValvePythonSubModule
  88. {
  89. public:
  90. typedef void ( *PythonInitFunc_t )( void );
  91. // Constructor
  92. CValvePythonSubModule( const char *pName, PythonInitFunc_t pInitFunc )
  93. : m_name( "_" )
  94. , m_pInitFunc( pInitFunc )
  95. {
  96. m_name += pName;
  97. m_pNextFactory = s_pFirstFactory;
  98. s_pFirstFactory = this;
  99. }
  100. static void Register( PyObject *pPackage );
  101. private:
  102. // The next factory
  103. CValvePythonSubModule *m_pNextFactory;
  104. static CValvePythonSubModule *s_pFirstFactory;
  105. CUtlString m_name;
  106. PythonInitFunc_t m_pInitFunc;
  107. };
  108. //-----------------------------------------------------------------------------
  109. // Macro to install a valve python command
  110. //
  111. // Use it like this:
  112. //
  113. // PYTHON_COMMAND( foo, METH_VARARGS, "The documentation for foo" )
  114. //-----------------------------------------------------------------------------
  115. #define PYTHON_SUBMODULE( _name ) \
  116. extern "C" void init_##_name( void ); \
  117. static CValvePythonSubModule _name##_submodule( #_name, init_##_name );
  118. // Support for implemented extended python commands which can take multiple position arguments and specified keyword arguments
  119. //
  120. typedef enum _pytypes
  121. {
  122. PY_FIELD_VOID = 0, // No type or value
  123. PY_FIELD_BOOLEAN, // boolean, implemented as an int, I may use this as a hint for compression
  124. PY_FIELD_CHARACTER, // a byte
  125. PY_FIELD_UTLSTRING, // CUtlString
  126. PY_FIELD_SHORT, // 2 byte integer
  127. PY_FIELD_INTEGER, // Any integer or enum
  128. PY_FIELD_FLOAT, // Any floating point value
  129. PY_FIELD_VECTOR, // Any vector, QAngle, or AngularImpulse
  130. PY_FIELD_QUATERNION, // A quaternion
  131. PY_FIELD_VMATRIX, // a Vmatrix (output coords are NOT worldspace)
  132. PY_FIELD_MATRIX3X4, // matrix3x4_t
  133. PY_FIELD_TYPECOUNT, // MUST BE LAST
  134. } pytype_t;
  135. #define _PY_PARAMETER(var_name,type,parameter_name,help) { type, #var_name, offsetof(classNameTypedef, var_name), -1, parameter_name, help, NULL, sizeof( ((classNameTypedef *)0)->var_name ) }
  136. #define _PY_ARGUMENT(var_name,type,argument_index,help) { type, #var_name, offsetof(classNameTypedef, var_name), argument_index, "", help, NULL, sizeof( ((classNameTypedef *)0)->var_name ) }
  137. #define DEFINE_PY_PARAMETER(var_name,type,parameter_name,help) _PY_PARAMETER(var_name, type, parameter_name, help )
  138. #define DEFINE_PY_ARGUMENT(var_name,type,argument_index,help) _PY_ARGUMENT(var_name, type, argument_index, help )
  139. struct pydatamap_t;
  140. struct pytypedescription_t;
  141. #define SIZE_OF_ARRAY(p) _ARRAYSIZE(p)
  142. #define DECLARE_PY_PARAMETER_DESC() \
  143. static pydatamap_t m_ParameterMap; \
  144. static pydatamap_t *GetBaseParameterMap(); \
  145. template <typename T> friend void ParameterMapAccess(T *, pydatamap_t **p); \
  146. template <typename T> friend pydatamap_t *ParameterMapInit(T *); \
  147. virtual pydatamap_t *GetParameterMap( void );
  148. #define BEGIN_PY_PARAMETERS( className ) \
  149. pydatamap_t className::m_ParameterMap = { 0, 0, #className, NULL }; \
  150. pydatamap_t *className::GetParameterMap( void ) { return &m_ParameterMap; } \
  151. pydatamap_t *className::GetBaseParameterMap() { pydatamap_t *pResult; ParameterMapAccess((BaseClass *)NULL, &pResult); return pResult; } \
  152. BEGIN_PY_PARAMETERS_GUTS( className )
  153. #define BEGIN_PY_PARAMETERS_NO_BASE( className ) \
  154. pydatamap_t className::m_ParameterMap = { 0, 0, #className, NULL }; \
  155. pydatamap_t *className::GetParameterMap( void ) { return &m_ParameterMap; } \
  156. pydatamap_t *className::GetBaseParameterMap() { return NULL; } \
  157. BEGIN_PY_PARAMETERS_GUTS( className )
  158. #define BEGIN_PY_PARAMETERS_GUTS( className ) \
  159. template <typename T> pydatamap_t *ParameterMapInit(T *); \
  160. template <> pydatamap_t *ParameterMapInit<className>( className * ); \
  161. namespace className##_ParameterMapInit \
  162. { \
  163. pydatamap_t *g_DataMapHolder = ParameterMapInit( (className *)NULL ); /* This can/will be used for some clean up duties later */ \
  164. } \
  165. \
  166. template <> pydatamap_t *ParameterMapInit<className>( className * ) \
  167. { \
  168. typedef className classNameTypedef; \
  169. static CParameterGeneratedNameHolder nameHolder(#className); \
  170. className::m_ParameterMap.baseMap = className::GetBaseParameterMap(); \
  171. static pytypedescription_t dataDesc[] = \
  172. { \
  173. { PY_FIELD_VOID,0,0,0,0,0,0 }, /* so you can define "empty" tables */
  174. #define END_PY_PARAMETERS() \
  175. }; \
  176. \
  177. if ( sizeof( dataDesc ) > sizeof( dataDesc[0] ) ) \
  178. { \
  179. classNameTypedef::m_ParameterMap.dataNumFields = SIZE_OF_ARRAY( dataDesc ) - 1; \
  180. classNameTypedef::m_ParameterMap.dataDesc = &dataDesc[1]; \
  181. } \
  182. else \
  183. { \
  184. classNameTypedef::m_ParameterMap.dataNumFields = 1; \
  185. classNameTypedef::m_ParameterMap.dataDesc = dataDesc; \
  186. } \
  187. return &classNameTypedef::m_ParameterMap; \
  188. }
  189. #define IMPLEMENT_NULL_PY_PARAMETERS( derivedClass ) \
  190. BEGIN_PY_PARAMETERS_GUTS( derivedClass ) \
  191. END_PY_PARAMETERS()
  192. struct pytypedescription_t
  193. {
  194. pytype_t type;
  195. const char *var_name;
  196. int offset;
  197. // index of the argument in the script file function call
  198. int argument_index;
  199. // the name of the parameter in script files
  200. const char *parameter_name;
  201. const char *help;
  202. // For embedding additional datatables inside this one
  203. pydatamap_t *td; // NOT HOOKED UP YET!!!
  204. // Stores the actual member variable size in bytes
  205. int fieldSizeInBytes;
  206. };
  207. struct pydatamap_t
  208. {
  209. pytypedescription_t *dataDesc;
  210. int dataNumFields;
  211. char const *dataClassName;
  212. pydatamap_t *baseMap;
  213. };
  214. template <typename T>
  215. inline void ParameterMapAccess(T *ignored, pydatamap_t **p)
  216. {
  217. *p = &T::m_ParameterMap;
  218. }
  219. //-----------------------------------------------------------------------------
  220. class CParameterGeneratedNameHolder
  221. {
  222. public:
  223. CParameterGeneratedNameHolder( const char *pszBase )
  224. : m_pszBase(pszBase)
  225. {
  226. m_nLenBase = strlen( m_pszBase );
  227. }
  228. ~CParameterGeneratedNameHolder()
  229. {
  230. for ( int i = 0; i < m_Names.Count(); i++ )
  231. {
  232. delete m_Names[i];
  233. }
  234. }
  235. const char *GenerateName( const char *pszIdentifier )
  236. {
  237. char *pBuf = new char[m_nLenBase + strlen(pszIdentifier) + 1];
  238. strcpy( pBuf, m_pszBase );
  239. strcat( pBuf, pszIdentifier );
  240. m_Names.AddToTail( pBuf );
  241. return pBuf;
  242. }
  243. private:
  244. const char *m_pszBase;
  245. size_t m_nLenBase;
  246. CUtlVector<char *> m_Names;
  247. };
  248. #define PYTHON_COMMAND_EXTENDED( _className ) \
  249. static _className g_##_className##Instance;\
  250. extern "C" static PyObject *g_##_className##Dispatch( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords ) \
  251. { \
  252. return g_##_className##Instance.DispatchRaw( pSelf, pArgs, pKeywords ); \
  253. } \
  254. static CValvePythonCommand _className##_command( g_##_className##Instance.GetName(), reinterpret_cast< PyCFunction >( g_##_className##Dispatch ), g_##_className##Instance.GetFlags(), g_##_className##Instance.GetDoc() ); \
  255. class CBasePythonCommand
  256. {
  257. DECLARE_PY_PARAMETER_DESC();
  258. public:
  259. CBasePythonCommand( const char *pchCommandName, int nFlags, char const *pchHelpText, pydatamap_t *pDataMap );
  260. PyObject *DispatchRaw( PyObject *pSelf, PyObject *pArgs, PyObject *pKeywords );
  261. char const *GetName() const;
  262. char const *GetDoc() const;
  263. int GetFlags() const;
  264. virtual PyObject *Dispatch( CUtlVector< CUtlString > &args, CUtlVector< int > &typedArgs ) = 0;
  265. virtual void SetDefaults() = 0;
  266. private:
  267. void InitParameters();
  268. void ProcessArguments( PyObject *pArgs, PyObject *pKeywords, CUtlVector< CUtlString > &args, CUtlVector< int > &typedArgs );
  269. pytypedescription_t *FindParameter( char const *pchName );
  270. pytypedescription_t *FindArgument( int index );
  271. void ExtractParameter( char const *pchName, pytypedescription_t *pTypeDescription, PyObject *pValue );
  272. template <class T>
  273. inline bool IsParameterTypeValid( pytype_t, T * ) const;
  274. protected:
  275. CUtlString BuildAutoGeneratedField( char const *pchParameterName, char const *pchPrefix, int *pCounter );
  276. template < class T >
  277. inline bool GetParameter( char const *pchParameterName, T *value );
  278. protected:
  279. char const *m_pchCommandName;
  280. int m_nFlags;
  281. char const *m_pchBaseHelpText;
  282. CUtlString m_HelpText;
  283. pydatamap_t *m_pDataMap;
  284. };
  285. #endif // VALVEPYTHON_H