CompositeSprite.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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 _COMPOSITE_SPRITE_H_
  23. #include "2d/sceneobject/CompositeSprite.h"
  24. #endif
  25. #ifndef _SPRITE_BATCH_QUERY_H_
  26. #include "2d/core/SpriteBatchQuery.h"
  27. #endif
  28. #ifndef _RENDER_PROXY_H_
  29. #include "2d/core/RenderProxy.h"
  30. #endif
  31. // Script bindings.
  32. #include "2d/sceneobject/CompositeSprite_ScriptBinding.h"
  33. //------------------------------------------------------------------------------
  34. static EnumTable::Enums batchLayoutTypeLookup[] =
  35. {
  36. { CompositeSprite::NO_LAYOUT, "off" },
  37. { CompositeSprite::RECTILINEAR_LAYOUT, "rect" },
  38. { CompositeSprite::ISOMETRIC_LAYOUT, "iso" },
  39. { CompositeSprite::CUSTOM_LAYOUT, "custom" },
  40. };
  41. EnumTable batchLayoutTypeTable(sizeof(batchLayoutTypeLookup) / sizeof(EnumTable::Enums), &batchLayoutTypeLookup[0]);
  42. //-----------------------------------------------------------------------------
  43. CompositeSprite::BatchLayoutType CompositeSprite::getBatchLayoutTypeEnum(const char* label)
  44. {
  45. // Search for Mnemonic.
  46. for (U32 i = 0; i < (sizeof(batchLayoutTypeLookup) / sizeof(EnumTable::Enums)); i++)
  47. {
  48. if( dStricmp(batchLayoutTypeLookup[i].label, label) == 0)
  49. return (BatchLayoutType)batchLayoutTypeLookup[i].index;
  50. }
  51. // Warn.
  52. Con::warnf("CompositeSprite::getBatchLayoutTypeEnum() - Invalid batch layout type of '%s'", label );
  53. return CompositeSprite::INVALID_LAYOUT;
  54. }
  55. //-----------------------------------------------------------------------------
  56. const char* CompositeSprite::getBatchLayoutTypeDescription(const CompositeSprite::BatchLayoutType batchLayoutType )
  57. {
  58. // Search for Mnemonic.
  59. for (U32 i = 0; i < (sizeof(batchLayoutTypeLookup) / sizeof(EnumTable::Enums)); i++)
  60. {
  61. if( batchLayoutTypeLookup[i].index == batchLayoutType )
  62. return batchLayoutTypeLookup[i].label;
  63. }
  64. // Warn.
  65. Con::warnf( "CompositeSprite::getBatchLayoutTypeDescription() - Invalid batch layout type.");
  66. return StringTable->EmptyString;
  67. }
  68. //------------------------------------------------------------------------------
  69. CompositeSprite::CompositeSprite() :
  70. mBatchLayoutType( NO_LAYOUT )
  71. {
  72. // Set as auto-sizing.
  73. mAutoSizing = true;
  74. }
  75. //------------------------------------------------------------------------------
  76. CompositeSprite::~CompositeSprite()
  77. {
  78. }
  79. //------------------------------------------------------------------------------
  80. void CompositeSprite::initPersistFields()
  81. {
  82. // Call parent.
  83. Parent::initPersistFields();
  84. /// Defaults.
  85. addProtectedField( "DefaultSpriteStride", TypeVector2, Offset(mDefaultSpriteStride, CompositeSprite), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeDefaultSpriteStride, "");
  86. addProtectedField( "DefaultSpriteSize", TypeVector2, Offset(mDefaultSpriteSize, CompositeSprite), &defaultProtectedSetFn, &defaultProtectedGetFn, &writeDefaultSpriteSize, "");
  87. addProtectedField( "DefaultSpriteAngle", TypeF32, Offset(mDefaultSpriteSize, CompositeSprite), &setDefaultSpriteAngle, &getDefaultSpriteAngle, &writeDefaultSpriteAngle, "");
  88. addProtectedField( "BatchLayout", TypeEnum, Offset(mBatchLayoutType, CompositeSprite), &setBatchLayout, &defaultProtectedGetFn, &writeBatchLayout, 1, &batchLayoutTypeTable, "");
  89. addProtectedField( "BatchCulling", TypeBool, Offset(mBatchCulling, CompositeSprite), &setBatchCulling, &defaultProtectedGetFn, &writeBatchCulling, "");
  90. addField( "BatchIsolated", TypeBool, Offset(mBatchIsolated, CompositeSprite), &writeBatchIsolated, "");
  91. addField( "BatchSortMode", TypeEnum, Offset(mBatchSortMode, CompositeSprite), &writeBatchSortMode, 1, &SceneRenderQueue::renderSortTable, "");
  92. }
  93. //-----------------------------------------------------------------------------
  94. bool CompositeSprite::onAdd()
  95. {
  96. // Call parent.
  97. if ( !Parent::onAdd() )
  98. return false;
  99. // Call sprite batch.
  100. return SpriteBatch::onAdd();
  101. }
  102. //-----------------------------------------------------------------------------
  103. void CompositeSprite::onRemove()
  104. {
  105. // Call sprite batch.
  106. SpriteBatch::onRemove();
  107. // Call parent.
  108. Parent::onRemove();
  109. }
  110. //-----------------------------------------------------------------------------
  111. void CompositeSprite::preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
  112. {
  113. // Are the spatials dirty?
  114. if ( getSpatialDirty() )
  115. {
  116. // Yes, so update the world transform.
  117. setBatchTransform( getRenderTransform() );
  118. }
  119. // Are the render extents dirty?
  120. if ( getLocalExtentsDirty() )
  121. {
  122. // Yes, so set size as local extents.
  123. setSize( getLocalExtents() );
  124. }
  125. // Call parent.
  126. Parent::preIntegrate( totalTime, elapsedTime, pDebugStats );
  127. }
  128. //-----------------------------------------------------------------------------
  129. void CompositeSprite::integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
  130. {
  131. // Call Parent.
  132. Parent::integrateObject( totalTime, elapsedTime, pDebugStats );
  133. // Finish if the spatials are NOT dirty.
  134. if ( !getSpatialDirty() )
  135. return;
  136. // Update the batch world transform.
  137. setBatchTransform( getRenderTransform() );
  138. }
  139. //-----------------------------------------------------------------------------
  140. void CompositeSprite::interpolateObject( const F32 timeDelta )
  141. {
  142. // Call parent.
  143. Parent::interpolateObject( timeDelta );
  144. // Finish if the spatials are NOT dirty.
  145. if ( !getSpatialDirty() )
  146. return;
  147. // Update the batch world transform.
  148. setBatchTransform( getRenderTransform() );
  149. }
  150. //-----------------------------------------------------------------------------
  151. void CompositeSprite::scenePrepareRender( const SceneRenderState* pSceneRenderState, SceneRenderQueue* pSceneRenderQueue )
  152. {
  153. // Prepare render.
  154. SpriteBatch::prepareRender( this, pSceneRenderState, pSceneRenderQueue );
  155. }
  156. //-----------------------------------------------------------------------------
  157. void CompositeSprite::sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
  158. {
  159. // Render.
  160. SpriteBatch::render( pSceneRenderState, pSceneRenderRequest, pBatchRenderer );
  161. }
  162. //------------------------------------------------------------------------------
  163. void CompositeSprite::copyTo(SimObject* object)
  164. {
  165. // Call to parent.
  166. Parent::copyTo(object);
  167. // Fetch object.
  168. CompositeSprite* pCompositeSprite = dynamic_cast<CompositeSprite*>(object);
  169. // Sanity!
  170. AssertFatal(pCompositeSprite != NULL, "CompositeSprite::copyTo() - Object is not the correct type.");
  171. // Copy batch layout.
  172. pCompositeSprite->setBatchLayout( getBatchLayout() );
  173. // Call sprite batch.
  174. SpriteBatch::copyTo( dynamic_cast<SpriteBatch*>(object) );
  175. }
  176. //------------------------------------------------------------------------------
  177. void CompositeSprite::setBatchLayout( const BatchLayoutType& batchLayoutType )
  178. {
  179. // Finish if no change.
  180. if ( mBatchLayoutType == batchLayoutType )
  181. return;
  182. // Do we already have some sprites?
  183. if ( getSpriteCount() > 0 )
  184. {
  185. // Yes, so warn.
  186. Con::warnf( "CompositeSprite::setBatchLayout() - Changing the batch layout with existing sprites is not allowed. Clear the sprites first." );
  187. return;
  188. }
  189. // Set layout type.
  190. mBatchLayoutType = batchLayoutType;
  191. }
  192. //------------------------------------------------------------------------------
  193. SpriteBatchItem* CompositeSprite::createSprite( const SpriteBatchItem::LogicalPosition& logicalPosition )
  194. {
  195. // Handle layout type appropriately.
  196. switch( mBatchLayoutType )
  197. {
  198. // No layout.
  199. case NO_LAYOUT:
  200. return SpriteBatch::createSprite( logicalPosition );
  201. // Rectilinear layout.
  202. case RECTILINEAR_LAYOUT:
  203. return createSpriteRectilinearLayout( logicalPosition );
  204. // Isometric layout.
  205. case ISOMETRIC_LAYOUT:
  206. return createSpriteIsometricLayout( logicalPosition );
  207. case CUSTOM_LAYOUT:
  208. return createCustomLayout( logicalPosition );
  209. default:
  210. // Warn.
  211. Con::warnf( "CompositeSprite::createSprite() - Unknown layout type encountered." );
  212. return SpriteBatch::createSprite( logicalPosition );
  213. }
  214. }
  215. //-----------------------------------------------------------------------------
  216. SpriteBatchItem* CompositeSprite::createSpriteRectilinearLayout( const SpriteBatchItem::LogicalPosition& logicalPosition )
  217. {
  218. // Do we have a valid logical position?
  219. if ( logicalPosition.getArgCount() != 2 )
  220. {
  221. // No, so warn.
  222. Con::warnf( "Invalid logical position specified for composite sprite." );
  223. return NULL;
  224. }
  225. // Does the sprite position already exist?
  226. if ( findSpritePosition( logicalPosition ) != NULL )
  227. {
  228. // Yes, so warn.
  229. Con::warnf( "Cannot add sprite at logical position '%s' as one already exists.", logicalPosition.getString() );
  230. return NULL;
  231. }
  232. // Create the sprite.
  233. SpriteBatchItem* pSpriteBatchItem = SpriteBatch::createSprite();
  234. // Set sprite logical position.
  235. pSpriteBatchItem->setLogicalPosition( logicalPosition );
  236. // Set the sprite default position.
  237. pSpriteBatchItem->setLocalPosition( logicalPosition.getAsVector2().mult( getDefaultSpriteStride() ) );
  238. // Set the sprite default size and angle.
  239. pSpriteBatchItem->setSize( SpriteBatch::getDefaultSpriteSize() );
  240. pSpriteBatchItem->setLocalAngle( SpriteBatch::getDefaultSpriteAngle() );
  241. return pSpriteBatchItem;
  242. }
  243. //-----------------------------------------------------------------------------
  244. SpriteBatchItem* CompositeSprite::createSpriteIsometricLayout( const SpriteBatchItem::LogicalPosition& logicalPosition )
  245. {
  246. // Do we have a valid logical position?
  247. if ( logicalPosition.getArgCount() != 2 )
  248. {
  249. // No, so warn.
  250. Con::warnf( "Invalid logical position specified for composite rectilinear sprite." );
  251. return NULL;
  252. }
  253. // Does the sprite position already exist?
  254. if ( findSpritePosition( logicalPosition ) != NULL )
  255. {
  256. // Yes, so warn.
  257. Con::warnf( "Cannot add sprite at logical position '%s' as one already exists.", logicalPosition.getString() );
  258. return NULL;
  259. }
  260. // Create the sprite.
  261. SpriteBatchItem* pSpriteBatchItem = SpriteBatch::createSprite();
  262. // Set sprite logical position.
  263. pSpriteBatchItem->setLogicalPosition( logicalPosition );
  264. // Fetch sprite stride.
  265. const Vector2 spriteStride = getDefaultSpriteStride();
  266. // Fetch logical coordinates.
  267. Vector2 position = logicalPosition.getAsVector2();
  268. // Calculate position.
  269. position.Set( (position.x * spriteStride.x) + (position.y * spriteStride.x), (position.x * spriteStride.y) + (position.y * -spriteStride.y) );
  270. // Set the sprite default position.
  271. pSpriteBatchItem->setLocalPosition( position );
  272. // Set the sprite default size and angle.
  273. pSpriteBatchItem->setSize( getDefaultSpriteSize() );
  274. pSpriteBatchItem->setLocalAngle( SpriteBatch::getDefaultSpriteAngle() );
  275. return pSpriteBatchItem;
  276. }
  277. //-----------------------------------------------------------------------------
  278. SpriteBatchItem* CompositeSprite::createCustomLayout( const SpriteBatchItem::LogicalPosition& logicalPosition )
  279. {
  280. // Do we have a valid logical position?
  281. if ( logicalPosition.isValid() )
  282. {
  283. // Does the sprite already exist?
  284. if ( findSpritePosition( logicalPosition ) != NULL )
  285. {
  286. // Yes, so warn.
  287. Con::warnf( "Cannot add sprite at logical position '%s' as one already exists.", logicalPosition.getString() );
  288. return NULL;
  289. }
  290. }
  291. // Create the sprite.
  292. SpriteBatchItem* pSpriteBatchItem = SpriteBatch::createSprite();
  293. // Set sprite logical position if it's valid.
  294. if ( logicalPosition.isValid() )
  295. pSpriteBatchItem->setLogicalPosition( logicalPosition );
  296. // Retrieve the local position from the custom layout callback.
  297. const char* pLocalPosition = Con::executef(this, 2, "onCustomLayout", logicalPosition.getString() );
  298. // Was a local position returned.
  299. if ( pLocalPosition != NULL && dStrlen(pLocalPosition) != 0 )
  300. {
  301. // Fetch the local position.
  302. Vector2 position(0.0f, 0.0f);
  303. Con::setData( TypeVector2, &position, 0, 1, &pLocalPosition );
  304. // Set the sprite default position.
  305. pSpriteBatchItem->setLocalPosition( position );
  306. }
  307. // Set the sprite default size and angle.
  308. pSpriteBatchItem->setSize( getDefaultSpriteSize() );
  309. pSpriteBatchItem->setLocalAngle( SpriteBatch::getDefaultSpriteAngle() );
  310. return pSpriteBatchItem;
  311. }
  312. //-----------------------------------------------------------------------------
  313. void CompositeSprite::onTamlCustomWrite( TamlCustomNodes& customNodes )
  314. {
  315. // Call parent.
  316. Parent::onTamlCustomWrite( customNodes );
  317. // Write node with sprite batch.
  318. SpriteBatch::onTamlCustomWrite( customNodes );
  319. }
  320. //-----------------------------------------------------------------------------
  321. void CompositeSprite::onTamlCustomRead( const TamlCustomNodes& customNodes )
  322. {
  323. // Call parent.
  324. Parent::onTamlCustomRead( customNodes );
  325. // Read node with sprite batch.
  326. SpriteBatch::onTamlCustomRead( customNodes );
  327. }
  328. //-----------------------------------------------------------------------------
  329. static void WriteCustomTamlSchema( const AbstractClassRep* pClassRep, TiXmlElement* pParentElement )
  330. {
  331. // Sanity!
  332. AssertFatal( pClassRep != NULL, "CompositeSprite::WriteCustomTamlSchema() - ClassRep cannot be NULL." );
  333. AssertFatal( pParentElement != NULL, "CompositeSprite::WriteCustomTamlSchema() - Parent Element cannot be NULL." );
  334. // Write sprite batch.
  335. SpriteBatch::WriteCustomTamlSchema( pClassRep, pParentElement );
  336. }
  337. //-----------------------------------------------------------------------------
  338. IMPLEMENT_CONOBJECT_SCHEMA(CompositeSprite, WriteCustomTamlSchema);