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