tamlCustom.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _TAML_CUSTOM_H_
  23. #define _TAML_CUSTOM_H_
  24. #ifndef _FACTORY_CACHE_H_
  25. #include "core/factoryCache.h"
  26. #endif
  27. #ifndef _STRINGTABLE_H_
  28. #include "core/stringTable.h"
  29. #endif
  30. #ifndef _CONSOLE_H_
  31. #include "console/console.h"
  32. #endif
  33. #ifndef _CONSOLETYPES_H_
  34. #include "console/consoleTypes.h"
  35. #endif
  36. #ifndef B2_MATH_H
  37. //TODO: Look at this
  38. //#include "box2d/Common/b2Math.h"
  39. #endif
  40. #ifndef _COLOR_H_
  41. #include "core/color.h"
  42. #endif
  43. #ifndef _SIMBASE_H_
  44. #include "console/simBase.h"
  45. #endif
  46. #include "core/util/safeDelete.h"
  47. #include "math/mMath.h"
  48. //-----------------------------------------------------------------------------
  49. #define MAX_TAML_NODE_FIELDVALUE_LENGTH 2048
  50. //-----------------------------------------------------------------------------
  51. class TamlWriteNode;
  52. class TamlCustomNode;
  53. class TamlCustomField;
  54. extern FactoryCache<TamlCustomNode> TamlCustomNodeFactory;
  55. extern FactoryCache<TamlCustomField> TamlCustomFieldFactory;
  56. typedef Vector<TamlCustomNode*> TamlCustomNodeVector;
  57. typedef Vector<TamlCustomField*> TamlCustomFieldVector;
  58. //-----------------------------------------------------------------------------
  59. class TamlCustomField : public IFactoryObjectReset
  60. {
  61. public:
  62. TamlCustomField()
  63. {
  64. resetState();
  65. }
  66. virtual ~TamlCustomField()
  67. {
  68. // Everything should already be cleared in a state reset.
  69. // Touching any memory here is dangerous as this type is typically
  70. // held in a static factory cache until shutdown at which point
  71. // pretty much anything or everything could be invalid!
  72. }
  73. virtual void resetState( void )
  74. {
  75. mFieldName = StringTable->EmptyString();
  76. *mFieldValue = 0;
  77. }
  78. void set( const char* pFieldName, const char* pFieldValue );
  79. inline void setFieldValue( const char* pFieldName, const ColorI& fieldValue )
  80. {
  81. // Fetch the field value.
  82. const char* pFieldValue = Con::getData( TypeColorI, &const_cast<ColorI&>(fieldValue), 0 );
  83. // Did we get a field value?
  84. if ( pFieldValue == NULL )
  85. {
  86. // No, so warn.
  87. Con::warnf( "Taml: Failed to add node field name '%s' with ColorI value.", pFieldName );
  88. pFieldValue = StringTable->EmptyString();
  89. }
  90. set( pFieldName, pFieldValue );
  91. }
  92. inline void setFieldValue( const char* pFieldName, const LinearColorF& fieldValue )
  93. {
  94. // Fetch the field value.
  95. const char* pFieldValue = Con::getData( TypeColorF, &const_cast<LinearColorF&>(fieldValue), 0 );
  96. // Did we get a field value?
  97. if ( pFieldValue == NULL )
  98. {
  99. // No, so warn.
  100. Con::warnf( "Taml: Failed to add node field name '%s' with LinearColorF value.", pFieldName );
  101. pFieldValue = StringTable->EmptyString();
  102. }
  103. set( pFieldName, pFieldValue );
  104. }
  105. inline void setFieldValue( const char* pFieldName, const Point2I& fieldValue )
  106. {
  107. char fieldValueBuffer[32];
  108. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%d %d", fieldValue.x, fieldValue.y );
  109. set( pFieldName, fieldValueBuffer );
  110. }
  111. inline void setFieldValue( const char* pFieldName, const Point2F& fieldValue )
  112. {
  113. char fieldValueBuffer[32];
  114. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%.5g %0.5g", fieldValue.x, fieldValue.y );
  115. set( pFieldName, fieldValueBuffer );
  116. }
  117. inline void setFieldValue( const char* pFieldName, const Point3I& fieldValue )
  118. {
  119. char fieldValueBuffer[32];
  120. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%d %d %d", fieldValue.x, fieldValue.y, fieldValue.z );
  121. set( pFieldName, fieldValueBuffer );
  122. }
  123. inline void setFieldValue( const char* pFieldName, const Point3F& fieldValue )
  124. {
  125. char fieldValueBuffer[32];
  126. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%.5g %0.5g %.5g", fieldValue.x, fieldValue.y, fieldValue.z );
  127. set( pFieldName, fieldValueBuffer );
  128. }
  129. inline void setFieldValue( const char* pFieldName, const RectF& fieldValue )
  130. {
  131. char fieldValueBuffer[32];
  132. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%.5g %0.5g %.5g %.5g",
  133. fieldValue.point.x, fieldValue.point.y, fieldValue.extent.x, fieldValue.extent.y);
  134. set( pFieldName, fieldValueBuffer );
  135. }
  136. inline void setFieldValue( const char* pFieldName, const QuatF& fieldValue )
  137. {
  138. char fieldValueBuffer[32];
  139. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%.5g %0.5g %.5g %.5g", fieldValue.x, fieldValue.y, fieldValue.z, fieldValue.w );
  140. set( pFieldName, fieldValueBuffer );
  141. }
  142. inline void setFieldValue( const char* pFieldName, const AngAxisF& fieldValue )
  143. {
  144. char fieldValueBuffer[32];
  145. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%.5g %0.5g %.5g %.5g", fieldValue.axis.x, fieldValue.axis.y, fieldValue.axis.z, fieldValue.angle );
  146. set( pFieldName, fieldValueBuffer );
  147. }
  148. inline void setFieldValue( const char* pFieldName, const U32 fieldValue )
  149. {
  150. char fieldValueBuffer[16];
  151. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%d", fieldValue );
  152. set( pFieldName, fieldValueBuffer );
  153. }
  154. inline void setFieldValue( const char* pFieldName, const bool fieldValue )
  155. {
  156. char fieldValueBuffer[16];
  157. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%d", fieldValue );
  158. set( pFieldName, fieldValueBuffer );
  159. }
  160. inline void setFieldValue( const char* pFieldName, const S32 fieldValue )
  161. {
  162. char fieldValueBuffer[16];
  163. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%d", fieldValue );
  164. set( pFieldName, fieldValueBuffer );
  165. }
  166. inline void setFieldValue( const char* pFieldName, const float fieldValue )
  167. {
  168. char fieldValueBuffer[16];
  169. dSprintf( fieldValueBuffer, sizeof(fieldValueBuffer), "%.5g", fieldValue );
  170. set( pFieldName, fieldValueBuffer );
  171. }
  172. inline void setFieldValue( const char* pFieldName, const char* fieldValue )
  173. {
  174. set( pFieldName, fieldValue );
  175. }
  176. inline void getFieldValue( LinearColorF& fieldValue ) const
  177. {
  178. fieldValue.set( 1.0f, 1.0f, 1.0f, 1.0f );
  179. // Set color.
  180. const char* argv = (char*)mFieldValue;
  181. Con::setData( TypeColorF, &fieldValue, 0, 1, &argv );
  182. }
  183. inline void getFieldValue( ColorI& fieldValue ) const
  184. {
  185. fieldValue.set( 255, 255, 255, 255 );
  186. // Set color.
  187. const char* argv = (char*)mFieldValue;
  188. Con::setData( TypeColorI, &fieldValue, 0, 1, &argv );
  189. }
  190. inline void getFieldValue( Point2I& fieldValue ) const
  191. {
  192. if ( dSscanf( mFieldValue, "%d %d", &fieldValue.x, &fieldValue.y ) != 2 )
  193. {
  194. // Warn.
  195. Con::warnf( "TamlCustomField - Reading point2I but it has an incorrect format: '%s'.", mFieldValue );
  196. }
  197. }
  198. inline void getFieldValue( Point2F& fieldValue ) const
  199. {
  200. if ( dSscanf( mFieldValue, "%g %g", &fieldValue.x, &fieldValue.y ) != 2 )
  201. {
  202. // Warn.
  203. Con::warnf( "TamlCustomField - Reading point2F but it has an incorrect format: '%s'.", mFieldValue );
  204. }
  205. }
  206. inline void getFieldValue( Point3I& fieldValue ) const
  207. {
  208. if ( dSscanf( mFieldValue, "%d %d %d", &fieldValue.x, &fieldValue.y, &fieldValue.z ) != 3 )
  209. {
  210. // Warn.
  211. Con::warnf( "TamlCustomField - Reading point3I but it has an incorrect format: '%s'.", mFieldValue );
  212. }
  213. }
  214. inline void getFieldValue( Point3F& fieldValue ) const
  215. {
  216. if ( dSscanf( mFieldValue, "%g %g %g", &fieldValue.x, &fieldValue.y, &fieldValue.z ) != 3 )
  217. {
  218. // Warn.
  219. Con::warnf( "TamlCustomField - Reading point3F but it has an incorrect format: '%s'.", mFieldValue );
  220. }
  221. }
  222. inline void getFieldValue( RectF& fieldValue ) const
  223. {
  224. if ( dSscanf( mFieldValue, "%g %g %g %g", &fieldValue.point.x, &fieldValue.point.y, &fieldValue.extent.x, &fieldValue.extent.y ) != 3 )
  225. {
  226. // Warn.
  227. Con::warnf( "TamlCustomField - Reading RectF but it has an incorrect format: '%s'.", mFieldValue );
  228. }
  229. }
  230. inline void getFieldValue( QuatF& fieldValue ) const
  231. {
  232. if ( dSscanf( mFieldValue, "%g %g %g %g", &fieldValue.x, &fieldValue.y, &fieldValue.z, &fieldValue.w ) != 4 )
  233. {
  234. // Warn.
  235. Con::warnf( "TamlCustomField - Reading QuatF but it has an incorrect format: '%s'.", mFieldValue );
  236. }
  237. }
  238. inline void getFieldValue( AngAxisF& fieldValue ) const
  239. {
  240. if ( dSscanf( mFieldValue, "%g %g %g %g", &fieldValue.axis.x, &fieldValue.axis.y, &fieldValue.axis.z, &fieldValue.angle ) != 4 )
  241. {
  242. // Warn.
  243. Con::warnf( "TamlCustomField - Reading AngAxisF but it has an incorrect format: '%s'.", mFieldValue );
  244. }
  245. }
  246. inline void getFieldValue( bool& fieldValue ) const
  247. {
  248. fieldValue = dAtob( mFieldValue );
  249. }
  250. inline void getFieldValue( S32& fieldValue ) const
  251. {
  252. fieldValue = dAtoi( mFieldValue );
  253. }
  254. inline void getFieldValue( U32& fieldValue ) const
  255. {
  256. fieldValue = (U32)dAtoi( mFieldValue );
  257. }
  258. inline void getFieldValue( F32& fieldValue ) const
  259. {
  260. fieldValue = dAtof( mFieldValue );
  261. }
  262. inline const char* getFieldValue( void ) const
  263. {
  264. return mFieldValue;
  265. }
  266. inline StringTableEntry getFieldName( void ) const { return mFieldName; }
  267. bool fieldNameBeginsWith( const char* pComparison ) const
  268. {
  269. const U32 comparisonLength = dStrlen( pComparison );
  270. const U32 fieldNameLength = dStrlen( mFieldName );
  271. if ( comparisonLength == 0 || fieldNameLength == 0 || comparisonLength > fieldNameLength )
  272. return false;
  273. StringTableEntry comparison = StringTable->insert( pComparison );
  274. char fieldNameBuffer[1024];
  275. // Sanity!
  276. AssertFatal( fieldNameLength < sizeof(fieldNameBuffer), "TamlCustomField: Field name is too long." );
  277. dStrcpy( fieldNameBuffer, mFieldName, 1024 );
  278. fieldNameBuffer[fieldNameLength-1] = 0;
  279. StringTableEntry fieldName = StringTable->insert( fieldNameBuffer );
  280. return ( fieldName == comparison );
  281. }
  282. inline bool isValueEmpty( void ) const { return *mFieldValue == 0; }
  283. private:
  284. StringTableEntry mFieldName;
  285. char mFieldValue[MAX_TAML_NODE_FIELDVALUE_LENGTH];
  286. };
  287. //-----------------------------------------------------------------------------
  288. class TamlCustomNode : public IFactoryObjectReset
  289. {
  290. public:
  291. TamlCustomNode()
  292. {
  293. // Reset proxy object.
  294. // NOTE: This MUST be done before the state is reset otherwise we'll be touching uninitialized stuff.
  295. mpProxyWriteNode = NULL;
  296. mpProxyObject = NULL;
  297. resetState();
  298. }
  299. virtual ~TamlCustomNode()
  300. {
  301. // Everything should already be cleared in a state reset.
  302. // Touching any memory here is dangerous as this type is typically
  303. // held in a static factory cache until shutdown at which point
  304. // pretty much anything or everything could be invalid!
  305. }
  306. virtual void resetState( void )
  307. {
  308. // We don't need to delete the write node as it'll get destroyed when the compilation is reset!
  309. mpProxyWriteNode = NULL;
  310. mpProxyObject = NULL;
  311. // Cache the children.
  312. while ( mChildren.size() > 0 )
  313. {
  314. TamlCustomNodeFactory.cacheObject( mChildren.back() );
  315. mChildren.pop_back();
  316. }
  317. // Cache the fields.
  318. while( mFields.size() > 0 )
  319. {
  320. TamlCustomFieldFactory.cacheObject( mFields.back() );
  321. mFields.pop_back();
  322. }
  323. // Reset the node name.
  324. mNodeName = StringTable->EmptyString();
  325. // Reset node text.
  326. mNodeText.resetState();
  327. // Reset the ignore empty flag.
  328. mIgnoreEmpty = false;
  329. }
  330. inline TamlCustomNode* addNode( SimObject* pProxyObject )
  331. {
  332. // Sanity!
  333. AssertFatal( pProxyObject != NULL, "Field object cannot be NULL." );
  334. AssertFatal( mpProxyWriteNode == NULL, "Field write node must be NULL." );
  335. // Create a custom node.
  336. TamlCustomNode* pCustomNode = TamlCustomNodeFactory.createObject();
  337. // Set node name.
  338. pCustomNode->setNodeName( pProxyObject->getClassName() );
  339. // Set proxy object.
  340. pCustomNode->mpProxyObject = pProxyObject;
  341. // Store node.
  342. mChildren.push_back( pCustomNode );
  343. return pCustomNode;
  344. }
  345. inline TamlCustomNode* addNode( const char* pNodeName, const bool ignoreEmpty = true )
  346. {
  347. // Create a custom node.
  348. TamlCustomNode* pCustomNode = TamlCustomNodeFactory.createObject();
  349. // Fetch node name.
  350. pCustomNode->setNodeName( pNodeName );
  351. // Set ignore-empty flag.
  352. pCustomNode->setIgnoreEmpty( ignoreEmpty );
  353. // Store node.
  354. mChildren.push_back( pCustomNode );
  355. return pCustomNode;
  356. }
  357. inline void removeNode( const U32 index )
  358. {
  359. // Sanity!
  360. AssertFatal( index < (U32)mChildren.size(), "tamlCustomNode::removeNode() - Index is out of bounds." );
  361. // Cache the custom node.
  362. TamlCustomNodeFactory.cacheObject( mChildren[index] );
  363. // Remove it.
  364. mChildren.erase( index );
  365. }
  366. inline const TamlCustomNode* findNode( const char* pNodeName ) const
  367. {
  368. // Sanity!
  369. AssertFatal( pNodeName != NULL, "Cannot find Taml node name that is NULL." );
  370. // Fetch node name.
  371. StringTableEntry nodeName = StringTable->insert( pNodeName );
  372. // Find node.
  373. for( Vector<TamlCustomNode*>::const_iterator nodeItr = mChildren.begin(); nodeItr != mChildren.end(); ++nodeItr )
  374. {
  375. if ( (*nodeItr)->getNodeName() == nodeName )
  376. return (*nodeItr);
  377. }
  378. return NULL;
  379. }
  380. inline TamlCustomField* addField( const char* pFieldName, const ColorI& fieldValue )
  381. {
  382. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  383. pNodeField->setFieldValue( pFieldName, fieldValue );
  384. return registerField( pNodeField );
  385. }
  386. inline TamlCustomField* addField( const char* pFieldName, const LinearColorF& fieldValue )
  387. {
  388. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  389. pNodeField->setFieldValue( pFieldName, fieldValue );
  390. return registerField( pNodeField );
  391. }
  392. inline TamlCustomField* addField( const char* pFieldName, const Point2I& fieldValue )
  393. {
  394. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  395. pNodeField->setFieldValue( pFieldName, fieldValue );
  396. return registerField( pNodeField );
  397. }
  398. inline TamlCustomField* addField( const char* pFieldName, const Point2F& fieldValue )
  399. {
  400. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  401. pNodeField->setFieldValue( pFieldName, fieldValue );
  402. return registerField( pNodeField );
  403. }
  404. inline TamlCustomField* addField( const char* pFieldName, const Point3I& fieldValue )
  405. {
  406. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  407. pNodeField->setFieldValue( pFieldName, fieldValue );
  408. return registerField( pNodeField );
  409. }
  410. inline TamlCustomField* addField( const char* pFieldName, const Point3F& fieldValue )
  411. {
  412. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  413. pNodeField->setFieldValue( pFieldName, fieldValue );
  414. return registerField( pNodeField );
  415. }
  416. inline TamlCustomField* addField( const char* pFieldName, const RectF& fieldValue )
  417. {
  418. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  419. pNodeField->setFieldValue( pFieldName, fieldValue );
  420. return registerField( pNodeField );
  421. }
  422. inline TamlCustomField* addField( const char* pFieldName, const QuatF& fieldValue )
  423. {
  424. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  425. pNodeField->setFieldValue( pFieldName, fieldValue );
  426. return registerField( pNodeField );
  427. }
  428. inline TamlCustomField* addField( const char* pFieldName, const AngAxisF& fieldValue )
  429. {
  430. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  431. pNodeField->setFieldValue( pFieldName, fieldValue );
  432. return registerField( pNodeField );
  433. }
  434. inline TamlCustomField* addField( const char* pFieldName, const U32 fieldValue )
  435. {
  436. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  437. pNodeField->setFieldValue( pFieldName, fieldValue );
  438. return registerField( pNodeField );
  439. }
  440. inline TamlCustomField* addField( const char* pFieldName, const bool fieldValue )
  441. {
  442. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  443. pNodeField->setFieldValue( pFieldName, fieldValue );
  444. return registerField( pNodeField );
  445. }
  446. inline TamlCustomField* addField( const char* pFieldName, const S32 fieldValue )
  447. {
  448. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  449. pNodeField->setFieldValue( pFieldName, fieldValue );
  450. return registerField( pNodeField );
  451. }
  452. inline TamlCustomField* addField( const char* pFieldName, const float fieldValue )
  453. {
  454. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  455. pNodeField->setFieldValue( pFieldName, fieldValue );
  456. return registerField( pNodeField );
  457. }
  458. inline TamlCustomField* addField( const char* pFieldName, const char* fieldValue )
  459. {
  460. TamlCustomField* pNodeField = TamlCustomFieldFactory.createObject();
  461. pNodeField->setFieldValue( pFieldName, fieldValue );
  462. return registerField( pNodeField );
  463. }
  464. inline const TamlCustomField* findField( const char* pFieldName ) const
  465. {
  466. // Sanity!
  467. AssertFatal( pFieldName != NULL, "Cannot find Taml field name that is NULL." );
  468. // Fetch field name.
  469. StringTableEntry fieldName = StringTable->insert( pFieldName );
  470. // Find node field.
  471. for( TamlCustomFieldVector::const_iterator fieldItr = mFields.begin(); fieldItr != mFields.end(); ++fieldItr )
  472. {
  473. if ( (*fieldItr)->getFieldName() == fieldName )
  474. return (*fieldItr);
  475. }
  476. return NULL;
  477. }
  478. inline void setNodeName( const char* pNodeName )
  479. {
  480. // Sanity!
  481. AssertFatal( pNodeName != NULL, "Cannot add a NULL node name." );
  482. mNodeName = StringTable->insert( pNodeName );
  483. }
  484. inline StringTableEntry getNodeName( void ) const { return mNodeName; }
  485. void setWriteNode( TamlWriteNode* pWriteNode );
  486. inline void setNodeText( const char* pNodeText )
  487. {
  488. AssertFatal( dStrlen( pNodeText ) < MAX_TAML_NODE_FIELDVALUE_LENGTH, "Custom node text is too long." );
  489. mNodeText.set( StringTable->EmptyString(), pNodeText );
  490. }
  491. inline const TamlCustomField& getNodeTextField( void ) const { return mNodeText; }
  492. inline TamlCustomField& getNodeTextField( void ) { return mNodeText; }
  493. inline const Vector<TamlCustomNode*>& getChildren( void ) const { return mChildren; }
  494. inline const TamlCustomFieldVector& getFields( void ) const { return mFields; }
  495. inline bool isProxyObject( void ) const { return mpProxyObject != NULL; }
  496. template<typename T> T* getProxyObject( const bool deleteIfNotType ) const
  497. {
  498. // Return nothing if no proxy object.
  499. if ( mpProxyObject == NULL )
  500. return NULL;
  501. // Cast object to specified type.
  502. T* pTypeCast = dynamic_cast<T*>( mpProxyObject );
  503. // Destroy the object if not the specified type and requested to do so.
  504. if ( deleteIfNotType && pTypeCast == NULL )
  505. {
  506. mpProxyObject->deleteObject();
  507. return NULL;
  508. }
  509. return pTypeCast;
  510. }
  511. inline const TamlWriteNode* getProxyWriteNode( void ) const { return mpProxyWriteNode; }
  512. inline bool isEmpty( void ) const { return mNodeText.isValueEmpty() && mFields.size() == 0 && mChildren.size() == 0; }
  513. inline void setIgnoreEmpty( const bool ignoreEmpty ) { mIgnoreEmpty = ignoreEmpty; }
  514. inline bool getIgnoreEmpty( void ) const { return mIgnoreEmpty; }
  515. private:
  516. inline TamlCustomField* registerField( TamlCustomField* pCustomField )
  517. {
  518. #ifdef TORQUE_DEBUG
  519. // Ensure a field name conflict does not exist.
  520. for( Vector<TamlCustomField*>::iterator nodeFieldItr = mFields.begin(); nodeFieldItr != mFields.end(); ++nodeFieldItr )
  521. {
  522. // Skip if field name is not the same.
  523. if ( pCustomField->getFieldName() != (*nodeFieldItr)->getFieldName() )
  524. continue;
  525. // Warn!
  526. Con::warnf("Conflicting Taml node field name of '%s' in node '%s'.", pCustomField->getFieldName(), mNodeName );
  527. // Cache node field.
  528. TamlCustomFieldFactory.cacheObject( pCustomField );
  529. return NULL;
  530. }
  531. // Ensure the field value is not too long.
  532. if ( dStrlen( pCustomField->getFieldValue() ) >= MAX_TAML_NODE_FIELDVALUE_LENGTH )
  533. {
  534. // Warn.
  535. Con::warnf("Taml field name '%s' has a field value that is too long (Max:%d): '%s'.",
  536. pCustomField->getFieldName(),
  537. MAX_TAML_NODE_FIELDVALUE_LENGTH,
  538. pCustomField->getFieldValue() );
  539. // Cache node field.
  540. TamlCustomFieldFactory.cacheObject( pCustomField );
  541. return NULL;
  542. }
  543. #endif
  544. // Store node field.
  545. mFields.push_back( pCustomField );
  546. return pCustomField;
  547. }
  548. inline TamlCustomField* createField( void ) const { return TamlCustomFieldFactory.createObject(); }
  549. private:
  550. StringTableEntry mNodeName;
  551. TamlCustomField mNodeText;
  552. Vector<TamlCustomNode*> mChildren;
  553. TamlCustomFieldVector mFields;
  554. bool mIgnoreEmpty;
  555. SimObject* mpProxyObject;
  556. TamlWriteNode* mpProxyWriteNode;
  557. };
  558. //-----------------------------------------------------------------------------
  559. class TamlCustomNodes : public IFactoryObjectReset
  560. {
  561. public:
  562. TamlCustomNodes()
  563. {
  564. }
  565. virtual ~TamlCustomNodes()
  566. {
  567. resetState();
  568. }
  569. virtual void resetState( void )
  570. {
  571. // Cache the nodes.
  572. while ( mNodes.size() > 0 )
  573. {
  574. TamlCustomNodeFactory.cacheObject( mNodes.back() );
  575. mNodes.pop_back();
  576. }
  577. }
  578. inline TamlCustomNode* addNode( const char* pNodeName, const bool ignoreEmpty = true )
  579. {
  580. // Create a custom node.
  581. TamlCustomNode* pCustomNode = TamlCustomNodeFactory.createObject();
  582. // Set node name.
  583. pCustomNode->setNodeName( pNodeName );
  584. // Set ignore-empty flag.
  585. pCustomNode->setIgnoreEmpty( ignoreEmpty );
  586. #ifdef TORQUE_DEBUG
  587. // Ensure a node name conflict does not exist.
  588. for( TamlCustomNodeVector::iterator nodeItr = mNodes.begin(); nodeItr != mNodes.end(); ++nodeItr )
  589. {
  590. // Skip if node name is not the same.
  591. if ( pCustomNode->getNodeName() != (*nodeItr)->getNodeName() )
  592. continue;
  593. // Warn!
  594. Con::warnf("Conflicting Taml custom node name of '%s'.", pNodeName );
  595. // Cache node.
  596. TamlCustomNodeFactory.cacheObject( pCustomNode );
  597. return NULL;
  598. }
  599. #endif
  600. // Store node.
  601. mNodes.push_back( pCustomNode );
  602. return pCustomNode;
  603. }
  604. inline void removeNode( const U32 index )
  605. {
  606. // Sanity!
  607. AssertFatal( index < (U32)mNodes.size(), "tamlCustomNode::removeNode() - Index is out of bounds." );
  608. // Cache the custom node.
  609. TamlCustomNodeFactory.cacheObject( mNodes[index] );
  610. // Remove it.
  611. mNodes.erase( index );
  612. }
  613. inline const TamlCustomNode* findNode( const char* pNodeName ) const
  614. {
  615. // Sanity!
  616. AssertFatal( pNodeName != NULL, "Cannot find Taml node name that is NULL." );
  617. // Fetch node name.
  618. StringTableEntry nodeName = StringTable->insert( pNodeName );
  619. // Find node.
  620. for( Vector<TamlCustomNode*>::const_iterator nodeItr = mNodes.begin(); nodeItr != mNodes.end(); ++nodeItr )
  621. {
  622. if ( (*nodeItr)->getNodeName() == nodeName )
  623. return (*nodeItr);
  624. }
  625. return NULL;
  626. }
  627. inline const TamlCustomNodeVector& getNodes( void ) const { return mNodes; }
  628. private:
  629. TamlCustomNodeVector mNodes;
  630. };
  631. #endif // _TAML_CUSTOM_H_