2
0

SceneObject.cc 132 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052
  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 _SCENE_OBJECT_H_
  23. #include "2d/sceneobject/SceneObject.h"
  24. #endif
  25. #ifndef _DGL_H_
  26. #include "graphics/dgl.h"
  27. #endif
  28. #ifndef _COLOR_H_
  29. #include "graphics/color.h"
  30. #endif
  31. #ifndef _BITSTREAM_H_
  32. #include "io/bitStream.h"
  33. #endif
  34. #ifndef _MMATHFN_H_
  35. #include "math/mMathFn.h"
  36. #endif
  37. #ifndef _CONSOLETYPES_H_
  38. #include "console/consoleTypes.h"
  39. #endif
  40. #ifndef _SIMBASE_H_
  41. #include "sim/simBase.h"
  42. #endif
  43. #ifndef _BEHAVIORTEMPLATE_H_
  44. #include "component/behaviors/behaviorTemplate.h"
  45. #endif
  46. #ifndef _SCENE_OBJECT_TIMER_EVENT_H_
  47. #include "2d/sceneobject/SceneObjectTimerEvent.h"
  48. #endif
  49. #ifndef _SCENE_OBJECT_MOVE_TO_EVENT_H_
  50. #include "2d/sceneobject/SceneObjectMoveToEvent.h"
  51. #endif
  52. #ifndef _SCENE_OBJECT_ROTATE_TO_EVENT_H_
  53. #include "2d/sceneobject/SceneObjectRotateToEvent.h"
  54. #endif
  55. #ifndef _RENDER_PROXY_H_
  56. #include "2d/core/RenderProxy.h"
  57. #endif
  58. #ifndef _STRINGUNIT_H_
  59. #include "string/stringUnit.h"
  60. #endif
  61. // Script bindings.
  62. #include "SceneObject_ScriptBinding.h"
  63. // Debug Profiling.
  64. #include "debug/profiler.h"
  65. //-----------------------------------------------------------------------------
  66. IMPLEMENT_CONOBJECT(SceneObject);
  67. //-----------------------------------------------------------------------------
  68. // Scene-Object counter.
  69. static U32 sGlobalSceneObjectCount = 0;
  70. static U32 sSceneObjectMasterSerialId = 0;
  71. // Collision shape property names.
  72. static bool collisionShapePropertiesInitialized = false;
  73. static StringTableEntry shapeCustomPropertyName;
  74. static StringTableEntry shapeDensityName;
  75. static StringTableEntry shapeFrictionName;
  76. static StringTableEntry shapeRestitutionName;
  77. static StringTableEntry shapeSensorName;
  78. static StringTableEntry circleTypeName;
  79. static StringTableEntry circleRadiusName;
  80. static StringTableEntry circleOffsetName;
  81. static StringTableEntry polygonTypeName;
  82. static StringTableEntry polygonPointName;
  83. static StringTableEntry chainTypeName;
  84. static StringTableEntry chainPointName;
  85. static StringTableEntry chainAdjacentStartName;
  86. static StringTableEntry chainAdjacentEndName;
  87. static StringTableEntry edgeTypeName;
  88. static StringTableEntry edgeStartName;
  89. static StringTableEntry edgeEndName;
  90. static StringTableEntry edgeAdjacentStartName;
  91. static StringTableEntry edgeAdjacentEndName;
  92. //------------------------------------------------------------------------------
  93. // Important: If these defaults are changed then modify the associated "write" field protected methods to ensure
  94. // that the associated field is persisted if not the default.
  95. SceneObject::SceneObject() :
  96. /// Scene.
  97. mpScene(NULL),
  98. mpTargetScene(NULL),
  99. /// Lifetime.
  100. mLifetime(0.0f),
  101. mLifetimeActive(false),
  102. /// Layers.
  103. mSceneLayer(0),
  104. mSceneLayerMask(BIT(mSceneLayer)),
  105. mSceneLayerDepth(0.0f),
  106. /// Scene groups.
  107. mSceneGroup(0),
  108. mSceneGroupMask(BIT(mSceneGroup)),
  109. /// Area.
  110. mWorldProxyId(-1),
  111. /// Position / Angle.
  112. mPreTickPosition( 0.0f, 0.0f ),
  113. mPreTickAngle( 0.0f ),
  114. mRenderPosition( 0.0f, 0.0f ),
  115. mRenderAngle( 0.0f ),
  116. mSpatialDirty( true ),
  117. /// Body.
  118. mpBody(NULL),
  119. mWorldQueryKey(0),
  120. /// Collision control.
  121. mCollisionLayerMask(MASK_ALL),
  122. mCollisionGroupMask(MASK_ALL),
  123. mCollisionSuppress(false),
  124. mGatherContacts(false),
  125. mpCurrentContacts(NULL),
  126. /// Render visibility.
  127. mVisible(true),
  128. /// Render blending.
  129. mBlendMode(true),
  130. mSrcBlendFactor(GL_SRC_ALPHA),
  131. mDstBlendFactor(GL_ONE_MINUS_SRC_ALPHA),
  132. mBlendColor(ColorF(1.0f,1.0f,1.0f,1.0f)),
  133. mAlphaTest(-1.0f),
  134. /// Render sorting.
  135. mSortPoint(0.0f,0.0f),
  136. /// Input events.
  137. mUseInputEvents(false),
  138. /// Script callbacks.
  139. mUpdateCallback(false),
  140. mCollisionCallback(false),
  141. mSleepingCallback(false),
  142. /// Debug mode.
  143. mDebugMask(0X00000000),
  144. /// Camera mounting.
  145. mpAttachedCamera(NULL),
  146. /// GUI attachment.
  147. mAttachedGuiSizeControl(false),
  148. mpAttachedGui(NULL),
  149. mpAttachedGuiSceneWindow(NULL),
  150. /// Pathing.
  151. mAttachedToPath(NULL),
  152. /// Safe deletion.
  153. mBeingSafeDeleted(false),
  154. mSafeDeleteReady(true),
  155. /// Miscellaneous.
  156. mBatchIsolated(false),
  157. mSerialiseKey(0),
  158. mEditorTickAllowed(true),
  159. mPickingAllowed(true),
  160. mAlwaysInScope(false),
  161. mPeriodicTimerID(0),
  162. mMoveToEventId(0),
  163. mRotateToEventId(0),
  164. mSerialId(0),
  165. mRenderGroup( StringTable->EmptyString )
  166. {
  167. // Initialize collision shape field names.
  168. if ( !collisionShapePropertiesInitialized )
  169. {
  170. shapeCustomPropertyName = StringTable->insert( "CollisionShapes" );
  171. shapeDensityName = StringTable->insert( "Density" );
  172. shapeFrictionName = StringTable->insert( "Friction" );
  173. shapeRestitutionName = StringTable->insert( "Restitution" );
  174. shapeSensorName = StringTable->insert( "Sensor" );
  175. circleTypeName = StringTable->insert( "Circle" );
  176. circleRadiusName = StringTable->insert( "Radius" );
  177. circleOffsetName = StringTable->insert( "Offset" );
  178. polygonTypeName = StringTable->insert( "Polygon" );
  179. polygonPointName = StringTable->insert( "Point" );
  180. chainTypeName = StringTable->insert( "Chain" );
  181. chainPointName = polygonPointName;
  182. chainAdjacentStartName = StringTable->insert( "AdjacentStartPoint" );
  183. chainAdjacentEndName = StringTable->insert( "AdjacentEndPoint" );
  184. edgeTypeName = StringTable->insert( "Edge" );
  185. edgeStartName = StringTable->insert( "Point0" );
  186. edgeEndName = StringTable->insert( "Point1" );
  187. edgeAdjacentStartName = chainAdjacentStartName;
  188. edgeAdjacentEndName = chainAdjacentEndName;
  189. // Flag as initialized.
  190. collisionShapePropertiesInitialized = true;
  191. }
  192. // Set Vector Associations.
  193. VECTOR_SET_ASSOCIATION( mDestroyNotifyList );
  194. VECTOR_SET_ASSOCIATION( mCollisionFixtureDefs );
  195. VECTOR_SET_ASSOCIATION( mCollisionFixtures );
  196. // Assign scene-object index.
  197. mSerialId = ++sSceneObjectMasterSerialId;
  198. sGlobalSceneObjectCount++;
  199. // Initialize the body definition.
  200. // Important: If these defaults are changed then modify the associated "write" field protected methods to ensure
  201. // that the associated field is persisted if not the default.
  202. mBodyDefinition.userData = static_cast<PhysicsProxy*>(this);
  203. mBodyDefinition.position.Set(0.0f, 0.0f);
  204. mBodyDefinition.angle = 0.0f;
  205. mBodyDefinition.linearVelocity.Set(0.0f, 0.0f);
  206. mBodyDefinition.angularVelocity = 0.0f;
  207. mBodyDefinition.linearDamping = 0.0f;
  208. mBodyDefinition.angularDamping = 0.0f;
  209. mBodyDefinition.allowSleep = true;
  210. mBodyDefinition.awake = true;
  211. mBodyDefinition.fixedRotation = false;
  212. mBodyDefinition.bullet = false;
  213. mBodyDefinition.type = b2_dynamicBody;
  214. mBodyDefinition.active = true;
  215. mBodyDefinition.gravityScale = 1.0f;
  216. // Initialize the default fixture definition.
  217. // Important: If these defaults are changed then modify the associated "write" field protected methods to ensure
  218. // that the associated field is persisted if not the default.
  219. mDefaultFixture.userData = static_cast<PhysicsProxy*>(this);
  220. mDefaultFixture.density = 1.0f;
  221. mDefaultFixture.friction = 0.2f;
  222. mDefaultFixture.restitution = 0.0f;
  223. mDefaultFixture.isSensor = false;
  224. mDefaultFixture.shape = NULL;
  225. // Set last awake state.
  226. mLastAwakeState = !mBodyDefinition.allowSleep || mBodyDefinition.awake;
  227. // Turn-off auto-sizing.
  228. mAutoSizing = false;
  229. // Set size.
  230. setSize( Vector2::getOne() );
  231. }
  232. //-----------------------------------------------------------------------------
  233. SceneObject::~SceneObject()
  234. {
  235. // Are we in a Scene?
  236. if ( mpScene )
  237. {
  238. // Yes, so remove from Scene.
  239. mpScene->removeFromScene( this );
  240. }
  241. // Decrease scene-object count.
  242. --sGlobalSceneObjectCount;
  243. }
  244. //-----------------------------------------------------------------------------
  245. void SceneObject::initPersistFields()
  246. {
  247. // Call parent.
  248. Parent::initPersistFields();
  249. /// Lifetime.
  250. addProtectedField("Lifetime", TypeF32, Offset(mLifetime, SceneObject), &setLifetime, &defaultProtectedGetFn, &writeLifetime, "");
  251. /// Scene Layers.
  252. addProtectedField("SceneLayer", TypeS32, Offset(mSceneLayer, SceneObject), &setSceneLayer, &defaultProtectedGetFn, &writeSceneLayer, "");
  253. addProtectedField("SceneLayerDepth", TypeF32, Offset(mSceneLayerDepth, SceneObject), &setSceneLayerDepth, &defaultProtectedGetFn, &writeSceneLayerDepth, "" );
  254. // Scene Groups.
  255. addProtectedField("SceneGroup", TypeS32, Offset(mSceneGroup, SceneObject), &setSceneGroup, &defaultProtectedGetFn, &writeSceneGroup, "");
  256. /// Area.
  257. addProtectedField("Size", TypeVector2, Offset( mSize, SceneObject), &setSize, &defaultProtectedGetFn, &writeSize, "");
  258. /// Position / Angle.
  259. addProtectedField("Position", TypeVector2, NULL, &setPosition, &getPosition, &writePosition, "");
  260. addProtectedField("Angle", TypeF32, NULL, &setAngle, &getAngle, &writeAngle, "");
  261. addProtectedField("FixedAngle", TypeBool, NULL, &setFixedAngle, &getFixedAngle, &writeFixedAngle, "");
  262. /// Body.
  263. addProtectedField("BodyType", TypeEnum, NULL, &setBodyType, &getBodyType, &writeBodyType, 1, &bodyTypeTable, "" );
  264. addProtectedField("Active", TypeBool, NULL, &setActive, &getActive, &writeActive, "" );
  265. addProtectedField("Awake", TypeBool, NULL, &setAwake, &getAwake, &writeAwake, "" );
  266. addProtectedField("Bullet", TypeBool, NULL, &setBullet, &getBullet, &writeBullet, "" );
  267. addProtectedField("SleepingAllowed", TypeBool, NULL, &setSleepingAllowed, &getSleepingAllowed, &writeSleepingAllowed, "" );
  268. /// Collision control.
  269. addProtectedField("CollisionGroups", TypeS32, Offset(mCollisionGroupMask, SceneObject), &setCollisionGroups, &defaultProtectedGetFn, &writeCollisionGroups, "");
  270. addProtectedField("CollisionLayers", TypeS32, Offset(mCollisionLayerMask, SceneObject), &setCollisionLayers, &defaultProtectedGetFn, &writeCollisionLayers, "");
  271. addField("CollisionSuppress", TypeBool, Offset(mCollisionSuppress, SceneObject), &writeCollisionSuppress, "");
  272. addProtectedField("GatherContacts", TypeBool, NULL, &setGatherContacts, &defaultProtectedGetFn, &writeGatherContacts, "");
  273. addProtectedField("DefaultDensity", TypeF32, Offset( mDefaultFixture.density, SceneObject), &setDefaultDensity, &defaultProtectedGetFn, &writeDefaultDensity, "");
  274. addProtectedField("DefaultFriction", TypeF32, Offset( mDefaultFixture.friction, SceneObject), &setDefaultFriction, &defaultProtectedGetFn, &writeDefaultFriction, "");
  275. addProtectedField("DefaultRestitution", TypeF32, Offset( mDefaultFixture.restitution, SceneObject), &setDefaultRestitution, &defaultProtectedGetFn, &writeDefaultRestitution, "");
  276. /// Velocities.
  277. addProtectedField("LinearVelocity", TypeVector2, NULL, &setLinearVelocity, &getLinearVelocity, &writeLinearVelocity, "");
  278. addProtectedField("AngularVelocity", TypeF32, NULL, &setAngularVelocity, &getAngularVelocity, &writeAngularVelocity, "");
  279. addProtectedField("LinearDamping", TypeF32, NULL, &setLinearDamping, &getLinearDamping, &writeLinearDamping, "");
  280. addProtectedField("AngularDamping", TypeF32, NULL, &setAngularDamping, &getAngularDamping, &writeAngularDamping, "");
  281. /// Gravity scaling.
  282. addProtectedField("GravityScale", TypeF32, NULL, &setGravityScale, &getGravityScale, &writeGravityScale, "");
  283. /// Render visibility.
  284. addField("Visible", TypeBool, Offset(mVisible, SceneObject), &writeVisible, "");
  285. /// Render blending.
  286. addField("BlendMode", TypeBool, Offset(mBlendMode, SceneObject), &writeBlendMode, "");
  287. addField("SrcBlendFactor", TypeEnum, Offset(mSrcBlendFactor, SceneObject), &writeSrcBlendFactor, 1, &srcBlendFactorTable);
  288. addField("DstBlendFactor", TypeEnum, Offset(mDstBlendFactor, SceneObject), &writeDstBlendFactor, 1, &dstBlendFactorTable);
  289. addField("BlendColor", TypeColorF, Offset(mBlendColor, SceneObject), &writeBlendColor, "");
  290. addField("AlphaTest", TypeF32, Offset(mAlphaTest, SceneObject), &writeAlphaTest, "");
  291. /// Render sorting.
  292. addField("SortPoint", TypeVector2, Offset(mSortPoint, SceneObject), &writeSortPoint, "");
  293. addField("RenderGroup", TypeString, Offset(mRenderGroup, SceneObject), &writeRenderGroup, "");
  294. /// Input events.
  295. addField("UseInputEvents", TypeBool, Offset(mUseInputEvents, SceneObject), &writeUseInputEvents, "");
  296. // Script callbacks.
  297. addField("UpdateCallback", TypeBool, Offset(mUpdateCallback, SceneObject), &writeUpdateCallback, "");
  298. addField("CollisionCallback", TypeBool, Offset(mCollisionCallback, SceneObject), &writeCollisionCallback, "");
  299. addField("SleepingCallback", TypeBool, Offset(mSleepingCallback, SceneObject), &writeSleepingCallback, "");
  300. /// Scene.
  301. addProtectedField("scene", TypeSimObjectPtr, Offset(mpScene, SceneObject), &setScene, &defaultProtectedGetFn, &writeScene, "");
  302. }
  303. //-----------------------------------------------------------------------------
  304. bool SceneObject::onAdd()
  305. {
  306. // Call Parent.
  307. if(!Parent::onAdd())
  308. return false;
  309. // Add to any target scene.
  310. if ( mpTargetScene )
  311. {
  312. // Add to the target scene.
  313. mpTargetScene->addToScene(this);
  314. mpTargetScene = NULL;
  315. }
  316. // Perform the callback.
  317. Con::executef(this, 1, "onAdd");
  318. // Return Okay.
  319. return true;
  320. }
  321. //-----------------------------------------------------------------------------
  322. void SceneObject::onRemove()
  323. {
  324. // Perform the callback.
  325. Con::executef(this, 1, "onRemove");
  326. // Detach Any GUI Control.
  327. detachGui();
  328. // Remove from Scene.
  329. if ( getScene() )
  330. getScene()->removeFromScene( this );
  331. // Call Parent.
  332. Parent::onRemove();
  333. }
  334. //-----------------------------------------------------------------------------
  335. void SceneObject::onDestroyNotify( SceneObject* pSceneObject )
  336. {
  337. }
  338. //-----------------------------------------------------------------------------
  339. void SceneObject::OnRegisterScene( Scene* pScene )
  340. {
  341. // Sanity!
  342. AssertFatal( mpScene == NULL, "Cannot register to a scene if already registered." );
  343. AssertFatal( mpBody == NULL, "Cannot create a physics body if one already exists." );
  344. // Initialize contact gathering.
  345. initializeContactGathering();
  346. // Set scene.
  347. mpScene = pScene;
  348. // Create the physics body.
  349. mpBody = pScene->getWorld()->CreateBody( &mBodyDefinition );
  350. // Set active status.
  351. if ( !isEnabled() ) mpBody->SetActive( false );
  352. // Create fixtures.
  353. for( typeCollisionFixtureDefVector::iterator itr = mCollisionFixtureDefs.begin(); itr != mCollisionFixtureDefs.end(); itr++ )
  354. {
  355. // Fetch fixture definition.
  356. b2FixtureDef* pFixtureDef = (*itr);
  357. // Create fixture.
  358. b2Fixture* pFixture = mpBody->CreateFixture( pFixtureDef );
  359. // Push fixture.
  360. mCollisionFixtures.push_back( pFixture );
  361. // Destroy fixture shape.
  362. delete pFixtureDef->shape;
  363. // Destroy fixture definition.
  364. delete pFixtureDef;
  365. }
  366. // Clear offline fixture definitions.
  367. mCollisionFixtureDefs.clear();
  368. // Calculate current AABB.
  369. CoreMath::mCalculateAABB( getLocalSizedOOBB(), mpBody->GetTransform(), &mCurrentAABB );
  370. // Create world proxy Id.
  371. mWorldProxyId = pScene->getWorldQuery()->add( this );
  372. // Reset the spatials.
  373. resetTickSpatials();
  374. // Notify components.
  375. notifyComponentsAddToScene();
  376. }
  377. //-----------------------------------------------------------------------------
  378. void SceneObject::OnUnregisterScene( Scene* pScene )
  379. {
  380. // Sanity!
  381. AssertFatal( mpScene == pScene, "Cannot unregister from a scene that is not registered." );
  382. AssertFatal( mpBody != NULL, "Cannot unregister physics body as it does not exist." );
  383. // Notify components.
  384. notifyComponentsRemoveFromScene();
  385. // Copy fixtures to fixture definitions.
  386. for( typeCollisionFixtureVector::iterator itr = mCollisionFixtures.begin(); itr != mCollisionFixtures.end(); itr++ )
  387. {
  388. // Fetch fixture.
  389. b2Fixture* pFixture = (*itr);
  390. // Create fixture definition.
  391. b2FixtureDef* pFixtureDef = new b2FixtureDef();
  392. pFixtureDef->density = pFixture->GetDensity();
  393. pFixtureDef->friction = pFixture->GetFriction();
  394. pFixtureDef->restitution = pFixture->GetRestitution();
  395. pFixtureDef->isSensor = pFixture->IsSensor();
  396. pFixtureDef->userData = this;
  397. pFixtureDef->shape = pFixture->GetShape()->Clone( pScene->getBlockAllocator() );
  398. // Push fixture definition.
  399. mCollisionFixtureDefs.push_back( pFixtureDef );
  400. }
  401. // Clear our fixture references.
  402. // The actual fixtures will get destroyed when the body is destroyed so no need to destroy them here.
  403. mCollisionFixtures.clear();
  404. // Transfer physics body configuration back to definition.
  405. mBodyDefinition.type = getBodyType();
  406. mBodyDefinition.position = getPosition();
  407. mBodyDefinition.angle = getAngle();
  408. mBodyDefinition.linearVelocity = getLinearVelocity();
  409. mBodyDefinition.angularVelocity = getAngularVelocity();
  410. mBodyDefinition.linearDamping = getLinearDamping();
  411. mBodyDefinition.angularDamping = getAngularDamping();
  412. mBodyDefinition.gravityScale = getGravityScale();
  413. mBodyDefinition.allowSleep = getSleepingAllowed();
  414. mBodyDefinition.awake = getAwake();
  415. mBodyDefinition.fixedRotation = getFixedAngle();
  416. mBodyDefinition.bullet = getBullet();
  417. mBodyDefinition.active = getActive();
  418. // Destroy current contacts.
  419. delete mpCurrentContacts;
  420. mpCurrentContacts = NULL;
  421. // Destroy the physics body.
  422. mpScene->getWorld()->DestroyBody( mpBody );
  423. mpBody = NULL;
  424. // Destroy world proxy Id.
  425. if ( mWorldProxyId != -1 )
  426. {
  427. mpScene->getWorldQuery()->remove( this );
  428. mWorldProxyId = -1;
  429. }
  430. // Reset scene.
  431. mpScene = NULL;
  432. }
  433. //-----------------------------------------------------------------------------
  434. void SceneObject::resetTickSpatials( const bool resize )
  435. {
  436. // Set coincident pre-tick, current & render.
  437. mPreTickPosition = mRenderPosition = getPosition();
  438. mPreTickAngle = mRenderAngle = getAngle();
  439. // Fetch body transform.
  440. b2Transform bodyXform = getTransform();
  441. // Calculate current AABB.
  442. CoreMath::mCalculateAABB( getLocalSizedOOBB(), bodyXform, &mCurrentAABB );
  443. // Set coincident AABBs.
  444. mPreTickAABB = mCurrentAABB;
  445. // Calculate render OOBB.
  446. CoreMath::mCalculateOOBB( getLocalSizedOOBB(), bodyXform, mRenderOOBB );
  447. // Update world proxy (if in scene).
  448. if ( mpScene )
  449. {
  450. // Fetch world query.
  451. WorldQuery* pWorldQuery = mpScene->getWorldQuery();
  452. // Are we resizing the object?
  453. if ( resize )
  454. {
  455. // Yes, so we need to recreate a proxy.
  456. pWorldQuery->remove( this );
  457. mWorldProxyId = pWorldQuery->add( this );
  458. }
  459. else
  460. {
  461. // No, so we can simply update the proxy.
  462. pWorldQuery->update( this, mCurrentAABB, b2Vec2( 0.0f, 0.0f ) );
  463. }
  464. }
  465. // Flag spatial changed.
  466. mSpatialDirty = true;
  467. }
  468. //-----------------------------------------------------------------------------
  469. void SceneObject::preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
  470. {
  471. // Debug Profiling.
  472. PROFILE_SCOPE(SceneObject_PreIntegrate);
  473. // Finish if nothing is dirty.
  474. if ( !mSpatialDirty )
  475. return;
  476. // Reset spatial changed.
  477. mSpatialDirty = false;
  478. mPreTickPosition = mRenderPosition = getPosition();
  479. mPreTickAngle = mRenderAngle = getAngle();
  480. mPreTickAABB = mCurrentAABB;
  481. // Calculate render OOBB.
  482. CoreMath::mCalculateOOBB( getLocalSizedOOBB(), getTransform(), mRenderOOBB );
  483. }
  484. //-----------------------------------------------------------------------------
  485. void SceneObject::integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats )
  486. {
  487. // Debug Profiling.
  488. PROFILE_SCOPE(SceneObject_IntegrateObject);
  489. // Fetch position.
  490. const b2Vec2 position = getPosition();
  491. // Has the angle or position changed?
  492. if ( mPreTickAngle != getAngle() ||
  493. mPreTickPosition.x != position.x ||
  494. mPreTickPosition.y != position.y )
  495. {
  496. // Yes, so flag spatial dirty.
  497. mSpatialDirty = true;
  498. // Calculate current AABB.
  499. CoreMath::mCalculateAABB( getLocalSizedOOBB(), getTransform(), &mCurrentAABB );
  500. // Calculate tick AABB.
  501. b2AABB tickAABB;
  502. tickAABB.Combine( mPreTickAABB, mCurrentAABB );
  503. // Calculate tick displacement.
  504. b2Vec2 tickDisplacement = position - mPreTickPosition;
  505. // Update world proxy.
  506. mpScene->getWorldQuery()->update( this, tickAABB, tickDisplacement );
  507. }
  508. // Update Lifetime.
  509. if ( mLifetimeActive && !getScene()->getIsEditorScene() )
  510. {
  511. updateLifetime( elapsedTime );
  512. }
  513. // Update Any Attached GUI.
  514. if ( mpAttachedGui && mpAttachedGuiSceneWindow )
  515. {
  516. updateAttachedGui();
  517. }
  518. // Are we attached to a camera?
  519. if ( mpAttachedCamera )
  520. {
  521. // Yes, so calculate camera mount.
  522. mpAttachedCamera->calculateCameraMount( elapsedTime );
  523. }
  524. }
  525. //-----------------------------------------------------------------------------
  526. void SceneObject::postIntegrate(const F32 totalTime, const F32 elapsedTime, DebugStats *pDebugStats)
  527. {
  528. // Debug Profiling.
  529. PROFILE_SCOPE(SceneObject_PostIntegrate);
  530. // Finish if no scene.
  531. if( !getScene() )
  532. return;
  533. // Notify components.
  534. notifyComponentsUpdate();
  535. // Script "onUpdate".
  536. if ( mUpdateCallback )
  537. {
  538. PROFILE_SCOPE(SceneObject_onUpdateCallback);
  539. Con::executef(this, 1, "onUpdate");
  540. }
  541. // Are we using the sleeping callback?
  542. if ( mSleepingCallback )
  543. {
  544. PROFILE_SCOPE(SceneObject_onWakeSleepCallback);
  545. // Yes, so fetch the current awake state.
  546. const bool currentAwakeState = getAwake();
  547. // Did we change awake state?
  548. if ( currentAwakeState != mLastAwakeState )
  549. {
  550. // Yes, so update last awake state.
  551. mLastAwakeState = currentAwakeState;
  552. // Perform the appropriate callback.
  553. if ( currentAwakeState )
  554. Con::executef(this, 1, "onWake");
  555. else
  556. Con::executef(this, 1, "onSleep");
  557. }
  558. }
  559. }
  560. //-----------------------------------------------------------------------------
  561. void SceneObject::interpolateObject( const F32 timeDelta )
  562. {
  563. // Debug Profiling.
  564. PROFILE_SCOPE(SceneObject_InterpolateObject);
  565. if ( mSpatialDirty )
  566. {
  567. // Debug Profiling.
  568. PROFILE_SCOPE(SceneObject_InterpolatePositionAngle);
  569. if ( timeDelta < 1.0f )
  570. {
  571. // Calculate render position.
  572. const b2Vec2 position = getPosition();
  573. b2Vec2 positionDelta = position - mPreTickPosition;
  574. positionDelta *= timeDelta;
  575. mRenderPosition = position - positionDelta;
  576. // Calculate render angle.
  577. const F32 angle = getAngle();
  578. F32 relativeAngle = angle - mPreTickAngle;
  579. if ( relativeAngle > b2_pi )
  580. relativeAngle -= b2_pi2;
  581. else if ( relativeAngle < -b2_pi )
  582. relativeAngle += b2_pi2;
  583. mRenderAngle = angle - (relativeAngle * timeDelta);
  584. }
  585. else
  586. {
  587. mRenderPosition = mPreTickPosition;
  588. mRenderAngle = mPreTickAngle;
  589. }
  590. // Calculate render transform.
  591. b2Transform renderXF( mRenderPosition, b2Rot(mRenderAngle) );
  592. // Calculate render OOBB.
  593. CoreMath::mCalculateOOBB( getLocalSizedOOBB(), renderXF, mRenderOOBB );
  594. }
  595. // Update Any Attached GUI.
  596. if ( mpAttachedGui && mpAttachedGuiSceneWindow )
  597. {
  598. updateAttachedGui();
  599. }
  600. // Are we attached to a camera?
  601. if ( mpAttachedCamera )
  602. {
  603. // Yes, so interpolate camera mount.
  604. mpAttachedCamera->interpolateCameraMount( timeDelta );
  605. }
  606. };
  607. //-----------------------------------------------------------------------------
  608. void SceneObject::sceneRenderFallback( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer )
  609. {
  610. // Debug Profiling.
  611. PROFILE_SCOPE(SceneObject_SceneRenderFallback);
  612. // Fetch the 'cannot render' proxy.
  613. RenderProxy* pNoImageRenderProxy = Sim::findObject<RenderProxy>( CANNOT_RENDER_PROXY_NAME );
  614. // Finish if no render proxy available or it can't render.
  615. if ( pNoImageRenderProxy == NULL || !pNoImageRenderProxy->validRender() )
  616. return;
  617. // Fetch render AABB.
  618. const b2Vec2* pRenderOOBB = getRenderOOBB();
  619. // Render using render proxy.
  620. pNoImageRenderProxy->render(
  621. false, false,
  622. pRenderOOBB[0], pRenderOOBB[1], pRenderOOBB[2], pRenderOOBB[3],
  623. pBatchRenderer );
  624. }
  625. //-----------------------------------------------------------------------------
  626. void SceneObject::sceneRenderOverlay( const SceneRenderState* sceneRenderState )
  627. {
  628. // Debug Profiling.
  629. PROFILE_SCOPE(SceneObject_SceneRenderOverlay);
  630. // Get Scene.
  631. Scene* pScene = getScene();
  632. // Cannot do anything without scene!
  633. if ( !pScene )
  634. return;
  635. // Don't draw debug if not enabled.
  636. if ( !isEnabled() )
  637. return;
  638. // Get merged Local/Scene Debug Mask.
  639. U32 debugMask = getDebugMask() | pScene->getDebugMask();
  640. // Finish here if we're not rendering any debug info or only have scene-rendered debug options.
  641. if ( !debugMask || (debugMask & ~(Scene::SCENE_DEBUG_METRICS | Scene::SCENE_DEBUG_JOINTS)) == 0 )
  642. return;
  643. // Clear blending.
  644. glDisable( GL_BLEND );
  645. glDisable( GL_TEXTURE_2D );
  646. // AABB debug draw.
  647. if ( debugMask & Scene::SCENE_DEBUG_AABB )
  648. {
  649. pScene->mDebugDraw.DrawAABB( mCurrentAABB );
  650. }
  651. // OOBB debug draw.
  652. if ( debugMask & Scene::SCENE_DEBUG_OOBB )
  653. {
  654. pScene->mDebugDraw.DrawOOBB( mRenderOOBB );
  655. }
  656. // Asleep debug draw.
  657. if ( !getAwake() && debugMask & Scene::SCENE_DEBUG_SLEEP )
  658. {
  659. pScene->mDebugDraw.DrawAsleep( mRenderOOBB );
  660. }
  661. // Collision Shapes.
  662. if ( debugMask & Scene::SCENE_DEBUG_COLLISION_SHAPES )
  663. {
  664. pScene->mDebugDraw.DrawCollisionShapes( getRenderTransform(), getBody() );
  665. }
  666. // Position and local center of mass.
  667. if ( debugMask & Scene::SCENE_DEBUG_POSITION_AND_COM )
  668. {
  669. const b2Vec2 renderPosition = getRenderPosition();
  670. pScene->mDebugDraw.DrawPoint( renderPosition + getLocalCenter(), 6, b2Color( 0.0f, 1.0f, 0.4f ) );
  671. pScene->mDebugDraw.DrawPoint( renderPosition, 4, b2Color( 0.0f, 0.4f, 1.0f ) );
  672. }
  673. // Sort Points.
  674. if ( debugMask & Scene::SCENE_DEBUG_SORT_POINTS )
  675. {
  676. pScene->mDebugDraw.DrawSortPoint( getRenderPosition(), getSize(), mSortPoint );
  677. }
  678. }
  679. //-----------------------------------------------------------------------------
  680. U32 SceneObject::packUpdate(NetConnection * conn, U32 mask, BitStream *stream)
  681. {
  682. return 0;
  683. }
  684. //-----------------------------------------------------------------------------
  685. void SceneObject::unpackUpdate(NetConnection * conn, BitStream *stream)
  686. {
  687. }
  688. //-----------------------------------------------------------------------------
  689. void SceneObject::setEnabled( const bool enabled )
  690. {
  691. // Call parent.
  692. Parent::setEnabled( enabled );
  693. // If we have a scene, modify active.
  694. if ( mpScene )
  695. {
  696. mpBody->SetActive( enabled );
  697. }
  698. }
  699. //-----------------------------------------------------------------------------
  700. void SceneObject::setLifetime( const F32 lifetime )
  701. {
  702. // Debug Profiling.
  703. PROFILE_SCOPE(SceneObject_setLifetime);
  704. // Usage Flag.
  705. mLifetimeActive = mGreaterThanZero( lifetime );
  706. // Is life active?
  707. if ( mLifetimeActive )
  708. {
  709. // Yes, so set to incoming lifetime.
  710. mLifetime = lifetime;
  711. }
  712. else
  713. {
  714. // No, so reset it to be safe.
  715. mLifetime = 0.0f;
  716. }
  717. }
  718. //-----------------------------------------------------------------------------
  719. void SceneObject::updateLifetime( const F32 elapsedTime )
  720. {
  721. // Update Lifetime.
  722. if ( mLifetimeActive )
  723. {
  724. // Reduce Lifetime.
  725. setLifetime( getLifetime() - elapsedTime );
  726. // Are we now dead?
  727. if ( mLessThanOrEqual( getLifetime(), 0.0f) )
  728. {
  729. // Yes, so reset lifetime.
  730. setLifetime( 0.0f );
  731. // Initiate Death!
  732. safeDelete();
  733. }
  734. }
  735. }
  736. //-----------------------------------------------------------------------------
  737. void SceneObject::setSceneLayer( const U32 sceneLayer )
  738. {
  739. // Check Layer.
  740. if ( sceneLayer > (MAX_LAYERS_SUPPORTED-1) )
  741. {
  742. Con::warnf("SceneObject::setSceneLayer() - Invalid scene layer '%d' (0-31).", sceneLayer);
  743. return;
  744. }
  745. // Set Layer.
  746. mSceneLayer = sceneLayer;
  747. // Set Layer Mask.
  748. mSceneLayerMask = BIT( mSceneLayer );
  749. }
  750. //-----------------------------------------------------------------------------
  751. bool SceneObject::setSceneLayerDepthFront( void )
  752. {
  753. // Fetch the scene.
  754. Scene* pScene = getScene();
  755. // Finish if no scene or only a single object.
  756. if ( pScene == NULL || pScene->getSceneObjectCount() == 1 )
  757. return false;
  758. // Fetch scene objects.
  759. typeSceneObjectVector layerList;
  760. pScene->getSceneObjects( layerList, getSceneLayer() );
  761. // Fetch layer object count.
  762. const U32 layerObjectCount = (U32)layerList.size();
  763. // Sort the layer.
  764. dQsort(layerList.address(), layerObjectCount, sizeof(SceneObject*), sceneObjectLayerDepthSort);
  765. // Reset object index.
  766. U32 objectIndex = 0;
  767. // Find object index.
  768. for ( ; objectIndex < layerObjectCount; ++objectIndex )
  769. {
  770. // Stop if this is the current object index.
  771. if ( layerList[objectIndex] == this )
  772. break;
  773. }
  774. // Finish if already at front of layer.
  775. if ( objectIndex == layerObjectCount-1 )
  776. return false;
  777. // Fetch furthest front depth.
  778. const F32 frontDepth = layerList.last()->getSceneLayerDepth();
  779. // Adjust depth to be in front.
  780. setSceneLayerDepth( frontDepth - 1.0f );
  781. return true;
  782. }
  783. //-----------------------------------------------------------------------------
  784. bool SceneObject::setSceneLayerDepthBack( void )
  785. {
  786. // Fetch the scene.
  787. Scene* pScene = getScene();
  788. // Finish if no scene or only a single object.
  789. if ( pScene == NULL || pScene->getSceneObjectCount() == 1 )
  790. return false;
  791. // Fetch scene objects.
  792. typeSceneObjectVector layerList;
  793. pScene->getSceneObjects( layerList, getSceneLayer() );
  794. // Fetch layer object count.
  795. const U32 layerObjectCount = (U32)layerList.size();
  796. // Sort the layer.
  797. dQsort(layerList.address(), layerObjectCount, sizeof(SceneObject*), sceneObjectLayerDepthSort);
  798. // Reset object index.
  799. U32 objectIndex = 0;
  800. // Find object index.
  801. for ( ; objectIndex < layerObjectCount; ++objectIndex )
  802. {
  803. // Stop if this is the current object index.
  804. if ( layerList[objectIndex] == this )
  805. break;
  806. }
  807. // Finish if already at back of layer.
  808. if ( objectIndex == 0 )
  809. return false;
  810. // Fetch furthest back depth.
  811. const F32 backDepth = layerList.first()->getSceneLayerDepth();
  812. // Adjust depth to be in back.
  813. setSceneLayerDepth( backDepth + 1.0f );
  814. return true;
  815. }
  816. //-----------------------------------------------------------------------------
  817. bool SceneObject::setSceneLayerDepthForward( void )
  818. {
  819. // Fetch the scene.
  820. Scene* pScene = getScene();
  821. // Finish if no scene or only a single object.
  822. if ( pScene == NULL || pScene->getSceneObjectCount() == 1 )
  823. return false;
  824. // Fetch scene objects.
  825. typeSceneObjectVector layerList;
  826. pScene->getSceneObjects( layerList, getSceneLayer() );
  827. // Fetch layer object count.
  828. const U32 layerObjectCount = (U32)layerList.size();
  829. // Sort the layer.
  830. dQsort(layerList.address(), layerObjectCount, sizeof(SceneObject*), sceneObjectLayerDepthSort);
  831. // Reset object index.
  832. U32 objectIndex = 0;
  833. // Find object index.
  834. for ( ; objectIndex < layerObjectCount; ++objectIndex )
  835. {
  836. // Stop if this is the current object index.
  837. if ( layerList[objectIndex] == this )
  838. break;
  839. }
  840. // Finish if already at the front of the layer.
  841. if ( objectIndex == layerObjectCount-1 )
  842. return false;
  843. // Fetch forwards depth.
  844. const F32 forwardDepth = layerList[objectIndex+1]->getSceneLayerDepth();
  845. // Adjust depth to be forward.
  846. setSceneLayerDepth( forwardDepth - 0.5f );
  847. // Finish if we were almost at the front anyway.
  848. if ( objectIndex == layerObjectCount-2 )
  849. return true;
  850. // Adjust next objects forwards.
  851. for( U32 forwardIndex = objectIndex+2; forwardIndex < layerObjectCount; ++forwardIndex )
  852. {
  853. // Fetch scene object.
  854. SceneObject* forwardSceneObject = layerList[forwardIndex];
  855. // Adjust depth to be forwards.
  856. forwardSceneObject->setSceneLayerDepth( forwardSceneObject->getSceneLayerDepth() - 1.0f );
  857. }
  858. return true;
  859. }
  860. //-----------------------------------------------------------------------------
  861. bool SceneObject::setSceneLayerDepthBackward( void )
  862. {
  863. // Fetch the scene.
  864. Scene* pScene = getScene();
  865. // Finish if no scene or only a single object.
  866. if ( pScene == NULL || pScene->getSceneObjectCount() == 1 )
  867. return false;
  868. // Fetch scene objects.
  869. typeSceneObjectVector layerList;
  870. pScene->getSceneObjects( layerList, getSceneLayer() );
  871. // Fetch layer object count.
  872. const U32 layerObjectCount = (U32)layerList.size();
  873. // Sort the layer.
  874. dQsort(layerList.address(), layerObjectCount, sizeof(SceneObject*), sceneObjectLayerDepthSort);
  875. // Reset object index.
  876. U32 objectIndex = 0;
  877. // Find object index.
  878. for ( ; objectIndex < layerObjectCount; ++objectIndex )
  879. {
  880. // Stop if this is the current object index.
  881. if ( layerList[objectIndex] == this )
  882. break;
  883. }
  884. // Finish if already at the back of the layer.
  885. if ( objectIndex == 0 )
  886. return false;
  887. // Fetch backwards depth.
  888. const F32 backDepth = layerList[objectIndex-1]->getSceneLayerDepth();
  889. // Adjust depth to be backwards.
  890. setSceneLayerDepth( backDepth + 0.5f );
  891. // Finish if we were almost at the back anyway.
  892. if ( objectIndex == 1 )
  893. return true;
  894. // Adjust previous objects backwards.
  895. for( U32 backIndex = 0; backIndex < (objectIndex-1); ++backIndex )
  896. {
  897. // Fetch scene object.
  898. SceneObject* backSceneObject = layerList[backIndex];
  899. // Adjust depth to be backwards.
  900. backSceneObject->setSceneLayerDepth( backSceneObject->getSceneLayerDepth() + 1.0f );
  901. }
  902. return true;
  903. }
  904. //-----------------------------------------------------------------------------
  905. void SceneObject::setSceneGroup( const U32 sceneGroup )
  906. {
  907. // Check Group.
  908. if ( sceneGroup > 31 )
  909. {
  910. Con::warnf("SceneObject::setSceneGroup() - Invalid scene group '%d' (0-31).", sceneGroup);
  911. return;
  912. }
  913. // Set Group.
  914. mSceneGroup = sceneGroup;
  915. // Set Group Mask.
  916. mSceneGroupMask = BIT( mSceneGroup );
  917. }
  918. //-----------------------------------------------------------------------------
  919. void SceneObject::setArea( const Vector2& corner1, const Vector2& corner2 )
  920. {
  921. // Debug Profiling.
  922. PROFILE_SCOPE(SceneObject_SetArea);
  923. // Calculate Normalized region.
  924. const Vector2 topLeft((corner1.x <= corner2.x) ? corner1.x : corner2.x, (corner1.y <= corner2.y) ? corner1.y : corner2.y);
  925. const Vector2 bottomRight((corner1.x > corner2.x) ? corner1.x : corner2.x, (corner1.y > corner2.y) ? corner1.y : corner2.y);
  926. // Calculate New Size.
  927. const Vector2 size = bottomRight - topLeft;
  928. // Calculate New Position.
  929. const Vector2 position = topLeft + (size * 0.5f);
  930. // Reset angle.
  931. setAngle( 0.0f );
  932. // Set Position/Size.
  933. setPosition( position );
  934. setSize( size );
  935. }
  936. //-----------------------------------------------------------------------------
  937. void SceneObject::setSize( const Vector2& size )
  938. {
  939. // Debug Profiling.
  940. PROFILE_SCOPE(SceneObject_SetSize);
  941. mSize = size;
  942. // Calculate half size.
  943. const F32 halfWidth = size.x * 0.5f;
  944. const F32 halfHeight = size.y * 0.5f;
  945. // Set local size OOBB.
  946. mLocalSizeOOBB[0].Set( -halfWidth, -halfHeight );
  947. mLocalSizeOOBB[1].Set( +halfWidth, -halfHeight );
  948. mLocalSizeOOBB[2].Set( +halfWidth, +halfHeight );
  949. mLocalSizeOOBB[3].Set( -halfWidth, +halfHeight );
  950. if ( mpScene )
  951. {
  952. // Reset tick spatials.
  953. resetTickSpatials( true );
  954. }
  955. }
  956. //-----------------------------------------------------------------------------
  957. void SceneObject::setPosition( const Vector2& position )
  958. {
  959. // Debug Profiling.
  960. PROFILE_SCOPE(SceneObject_SetPosition);
  961. if ( mpScene )
  962. {
  963. mpBody->SetTransform( position, mpBody->GetAngle() );
  964. // Reset tick spatials.
  965. resetTickSpatials();
  966. }
  967. else
  968. {
  969. mBodyDefinition.position = position;
  970. }
  971. }
  972. //-----------------------------------------------------------------------------
  973. void SceneObject::setAngle( const F32 radians )
  974. {
  975. // Debug Profiling.
  976. PROFILE_SCOPE(SceneObject_SetAngle);
  977. if ( mpScene )
  978. {
  979. mpBody->SetTransform( mpBody->GetPosition(), radians );
  980. // Reset tick spatials.
  981. resetTickSpatials();
  982. }
  983. else
  984. {
  985. mBodyDefinition.angle = radians;
  986. }
  987. }
  988. //-----------------------------------------------------------------------------
  989. Vector2 SceneObject::getLocalPoint( const Vector2 &worldPoint )
  990. {
  991. if ( mpScene )
  992. {
  993. return mpBody->GetLocalPoint( worldPoint );
  994. }
  995. // Calculate body definition transform.
  996. const b2Transform transform( mBodyDefinition.position, b2Rot(mBodyDefinition.angle) );
  997. return b2MulT(transform, worldPoint);
  998. }
  999. //-----------------------------------------------------------------------------
  1000. Vector2 SceneObject::getWorldPoint( const Vector2 &localPoint )
  1001. {
  1002. if ( mpScene )
  1003. {
  1004. return mpBody->GetWorldPoint( localPoint );
  1005. }
  1006. // Calculate body definition transform.
  1007. const b2Transform transform( mBodyDefinition.position, b2Rot(mBodyDefinition.angle) );
  1008. return b2Mul(transform, localPoint);
  1009. }
  1010. //-----------------------------------------------------------------------------
  1011. Vector2 SceneObject::getLocalVector( const Vector2& worldVector )
  1012. {
  1013. if ( mpScene )
  1014. {
  1015. return mpBody->GetLocalVector( worldVector );
  1016. }
  1017. // Calculate body definition transform.
  1018. const b2Transform transform( mBodyDefinition.position, b2Rot(mBodyDefinition.angle) );
  1019. return b2MulT(transform.q, worldVector);
  1020. }
  1021. //-----------------------------------------------------------------------------
  1022. Vector2 SceneObject::getWorldVector( const Vector2& localVector )
  1023. {
  1024. if ( mpScene )
  1025. {
  1026. return mpBody->GetWorldVector( localVector );
  1027. }
  1028. // Calculate body definition transform.
  1029. const b2Transform transform( mBodyDefinition.position, b2Rot(mBodyDefinition.angle) );
  1030. return b2Mul(transform.q, localVector);
  1031. }
  1032. //-----------------------------------------------------------------------------
  1033. bool SceneObject::getIsPointInOOBB( const Vector2& worldPoint )
  1034. {
  1035. // Fetch local point.
  1036. Vector2 localPoint = getLocalPoint( worldPoint );
  1037. // Turn the local point into an absolute component distance.
  1038. localPoint.absolute();
  1039. const Vector2 halfSize = getHalfSize();
  1040. // Check distance.
  1041. return !( localPoint.x > halfSize.x || localPoint.y > halfSize.y );
  1042. }
  1043. //-----------------------------------------------------------------------------
  1044. bool SceneObject::getIsPointInCollisionShape( const U32 shapeIndex, const Vector2& worldPoint )
  1045. {
  1046. // Sanity!
  1047. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getIsPointInCollisionShape() - Invalid shape index." );
  1048. // Sanity!
  1049. if ( !mpScene )
  1050. {
  1051. Con::warnf( "SceneObject::getIsPointInCollisionShape() - Cannot test for point, object not in scene." );
  1052. return false;
  1053. }
  1054. // Fetch fixture.
  1055. b2Fixture* pFixture = mCollisionFixtures[shapeIndex];
  1056. // Fetch local point.
  1057. const Vector2 localPoint = getLocalPoint( worldPoint );
  1058. // Test point.
  1059. return pFixture->TestPoint( localPoint );
  1060. }
  1061. //-----------------------------------------------------------------------------
  1062. void SceneObject::setBodyType( const b2BodyType type )
  1063. {
  1064. // Sanity!
  1065. AssertFatal( type == b2_staticBody || type == b2_kinematicBody || type == b2_dynamicBody, "Invalid body type." );
  1066. if ( mpScene )
  1067. {
  1068. mpBody->SetType( type );
  1069. return;
  1070. }
  1071. else
  1072. {
  1073. mBodyDefinition.type = type;
  1074. }
  1075. }
  1076. //-----------------------------------------------------------------------------
  1077. void SceneObject::applyForce( const Vector2& worldForce, const bool wake )
  1078. {
  1079. // Ignore if not in scene.
  1080. if ( !mpScene )
  1081. return;
  1082. applyForce( worldForce, getPosition() + getLocalCenter(), wake );
  1083. }
  1084. //-----------------------------------------------------------------------------
  1085. void SceneObject::applyForce( const Vector2& worldForce, const Vector2& worldPoint, const bool wake )
  1086. {
  1087. // Ignore if not in scene.
  1088. if ( !mpScene )
  1089. return;
  1090. getBody()->ApplyForce( worldForce, worldPoint, wake );
  1091. }
  1092. //-----------------------------------------------------------------------------
  1093. void SceneObject::applyTorque( const F32 torque, const bool wake )
  1094. {
  1095. // Ignore if not in scene.
  1096. if ( !mpScene )
  1097. return;
  1098. getBody()->ApplyTorque( torque, wake );
  1099. }
  1100. //-----------------------------------------------------------------------------
  1101. void SceneObject::applyLinearImpulse( const Vector2& worldImpulse, const bool wake )
  1102. {
  1103. // Ignore if not in scene.
  1104. if ( !mpScene )
  1105. return;
  1106. applyLinearImpulse( worldImpulse, getPosition() + getLocalCenter(), wake );
  1107. }
  1108. //-----------------------------------------------------------------------------
  1109. void SceneObject::applyLinearImpulse( const Vector2& worldImpulse, const Vector2& worldPoint, const bool wake )
  1110. {
  1111. // Ignore if not in scene.
  1112. if ( !mpScene )
  1113. return;
  1114. getBody()->ApplyLinearImpulse( worldImpulse, worldPoint, wake );
  1115. }
  1116. //-----------------------------------------------------------------------------
  1117. void SceneObject::applyAngularImpulse( const F32 impulse, const bool wake )
  1118. {
  1119. // Ignore if not in scene.
  1120. if ( !mpScene )
  1121. return;
  1122. getBody()->ApplyAngularImpulse( impulse, wake );
  1123. }
  1124. //-----------------------------------------------------------------------------
  1125. void SceneObject::setCollisionMasks( const U32 groupMask, const U32 layerMask )
  1126. {
  1127. // Set Group/Layer Collision Masks.
  1128. mCollisionGroupMask = groupMask;
  1129. mCollisionLayerMask = layerMask;
  1130. }
  1131. //-----------------------------------------------------------------------------
  1132. void SceneObject::setCollisionAgainst( const SceneObject* pSceneObject, const bool clearMasks )
  1133. {
  1134. // Do we need to clear existing masks?
  1135. if ( clearMasks )
  1136. {
  1137. // Yes, so just set the masks to the referenced-objects' masks.
  1138. setCollisionMasks( pSceneObject->getSceneGroupMask(), pSceneObject->getSceneLayerMask() );
  1139. }
  1140. else
  1141. {
  1142. // No, so merge with existing masks.
  1143. setCollisionMasks( getCollisionGroupMask() | pSceneObject->getSceneGroupMask(), getCollisionLayerMask() | pSceneObject->getSceneLayerMask() );
  1144. }
  1145. }
  1146. //-----------------------------------------------------------------------------
  1147. void SceneObject::setDefaultDensity( const F32 density, const bool updateShapes )
  1148. {
  1149. mDefaultFixture.density = density;
  1150. // Early-out if not updating shapes.
  1151. if ( !updateShapes )
  1152. return;
  1153. if ( mpScene )
  1154. {
  1155. // Update live fixtures.
  1156. for( U32 index = 0; index < (U32)mCollisionFixtures.size(); ++index )
  1157. {
  1158. mCollisionFixtures[index]->SetDensity( density );
  1159. }
  1160. // Update the body mass data.
  1161. mpBody->ResetMassData();
  1162. return;
  1163. }
  1164. // Update offline fixture definitions.
  1165. for( U32 index = 0; index < (U32)mCollisionFixtureDefs.size(); ++index )
  1166. {
  1167. mCollisionFixtureDefs[index]->density = density;
  1168. }
  1169. }
  1170. //-----------------------------------------------------------------------------
  1171. void SceneObject::setDefaultFriction( const F32 friction, const bool updateShapes )
  1172. {
  1173. mDefaultFixture.friction = friction;
  1174. // Early-out if not updating shapes.
  1175. if ( !updateShapes )
  1176. return;
  1177. if ( mpScene )
  1178. {
  1179. // Update live fixtures.
  1180. for( U32 index = 0; index < (U32)mCollisionFixtures.size(); ++index )
  1181. {
  1182. mCollisionFixtures[index]->SetFriction( friction );
  1183. }
  1184. return;
  1185. }
  1186. // Update offline fixture definitions.
  1187. for( U32 index = 0; index < (U32)mCollisionFixtureDefs.size(); ++index )
  1188. {
  1189. mCollisionFixtureDefs[index]->friction = friction;
  1190. }
  1191. }
  1192. //-----------------------------------------------------------------------------
  1193. void SceneObject::setDefaultRestitution( const F32 restitution, const bool updateShapes )
  1194. {
  1195. mDefaultFixture.restitution = restitution;
  1196. // Early-out if not updating shapes.
  1197. if ( !updateShapes )
  1198. return;
  1199. if ( mpScene )
  1200. {
  1201. // Update live fixtures.
  1202. for( U32 index = 0; index < (U32)mCollisionFixtures.size(); ++index )
  1203. {
  1204. mCollisionFixtures[index]->SetRestitution( restitution );
  1205. }
  1206. return;
  1207. }
  1208. // Update offline fixture definitions.
  1209. for( U32 index = 0; index < (U32)mCollisionFixtureDefs.size(); ++index )
  1210. {
  1211. mCollisionFixtureDefs[index]->restitution = restitution;
  1212. }
  1213. }
  1214. //-----------------------------------------------------------------------------
  1215. void SceneObject::initializeContactGathering( void )
  1216. {
  1217. // Are we gathering contacts?
  1218. if ( !mGatherContacts )
  1219. {
  1220. // No, so do we have any current contacts?
  1221. if ( mpCurrentContacts )
  1222. {
  1223. // Yes, so destroy them.
  1224. delete mpCurrentContacts;
  1225. mpCurrentContacts = NULL;
  1226. }
  1227. return;
  1228. }
  1229. // Clear current contacts if already present.
  1230. if ( mpCurrentContacts != NULL )
  1231. {
  1232. mpCurrentContacts->clear();
  1233. return;
  1234. }
  1235. // Generate current contacts.
  1236. mpCurrentContacts = new typeContactVector();
  1237. }
  1238. //-----------------------------------------------------------------------------
  1239. void SceneObject::onBeginCollision( const TickContact& tickContact )
  1240. {
  1241. // Finish if we're not gathering contacts.
  1242. if ( !mGatherContacts )
  1243. return;
  1244. // Sanity!
  1245. AssertFatal( mpCurrentContacts != NULL, "SceneObject::onBeginCollision() - Contacts not initialized correctly." );
  1246. AssertFatal( tickContact.mpSceneObjectA == this || tickContact.mpSceneObjectB == this, "SceneObject::onBeginCollision() - Contact does not involve this scene object." );
  1247. // Keep contact.
  1248. mpCurrentContacts->push_back( tickContact );
  1249. }
  1250. //-----------------------------------------------------------------------------
  1251. void SceneObject::onEndCollision( const TickContact& tickContact )
  1252. {
  1253. // Finish if we're not gathering contacts.
  1254. if ( !mGatherContacts )
  1255. return;
  1256. // Sanity!
  1257. AssertFatal( mpCurrentContacts != NULL, "SceneObject::onBeginCollision() - Contacts not initialized correctly." );
  1258. AssertFatal( tickContact.mpSceneObjectA == this || tickContact.mpSceneObjectB == this, "SceneObject::onEndCollision() - Contact does not involve this scene object." );
  1259. // Remove contact.
  1260. for( typeContactVector::iterator contactItr = mpCurrentContacts->begin(); contactItr != mpCurrentContacts->end(); ++contactItr )
  1261. {
  1262. // Is this is the correct contact?
  1263. if ( contactItr->mpContact == tickContact.mpContact )
  1264. {
  1265. // Yes, so remove it.
  1266. mpCurrentContacts->erase_fast( contactItr );
  1267. return;
  1268. }
  1269. }
  1270. }
  1271. //-----------------------------------------------------------------------------
  1272. bool SceneObject::moveTo( const Vector2& targetWorldPoint, const U32 time, const bool autoStop, const bool warpToTarget )
  1273. {
  1274. // Check in a scene.
  1275. if ( !getScene() )
  1276. {
  1277. Con::warnf("Cannot move object (%d) to a point as it is not in a scene.", getId() );
  1278. return false;
  1279. }
  1280. // Check not a static body.
  1281. if ( getBodyType() == b2_staticBody )
  1282. {
  1283. Con::warnf("Cannot move object (%d) to a point as it is a static body.", getId() );
  1284. return false;
  1285. }
  1286. // Cancel any previous event.
  1287. if ( mMoveToEventId != 0 )
  1288. {
  1289. Sim::cancelEvent( mMoveToEventId );
  1290. mMoveToEventId = 0;
  1291. }
  1292. // Calculate relative position.
  1293. const Vector2 relativePosition = targetWorldPoint - getPosition();
  1294. // Calculate linear velocity to use over time.
  1295. const Vector2 linearVelocity = relativePosition / (time * 0.001f);
  1296. // Set the linear velocity.
  1297. setLinearVelocity( linearVelocity );
  1298. // Create and post event.
  1299. SceneObjectMoveToEvent* pEvent = new SceneObjectMoveToEvent( targetWorldPoint, autoStop, warpToTarget );
  1300. mMoveToEventId = Sim::postEvent(this, pEvent, Sim::getCurrentTime() + time );
  1301. return true;
  1302. }
  1303. //-----------------------------------------------------------------------------
  1304. bool SceneObject::rotateTo( const F32 targetAngle, const U32 time, const bool autoStop, const bool warpToTarget )
  1305. {
  1306. // Check in a scene.
  1307. if ( !getScene() )
  1308. {
  1309. Con::warnf("Cannot rotate object (%d) to an angle as it is not in a scene.", getId() );
  1310. return false;
  1311. }
  1312. // Check not a static body.
  1313. if ( getBodyType() == b2_staticBody )
  1314. {
  1315. Con::warnf("Cannot move object (%d) to an angle as it is a static body.", getId() );
  1316. return false;
  1317. }
  1318. // Cancel any previous event.
  1319. if ( mRotateToEventId != 0 )
  1320. {
  1321. Sim::cancelEvent( mRotateToEventId );
  1322. mRotateToEventId = 0;
  1323. }
  1324. // Calculate relative angle.
  1325. const F32 relativeAngle = targetAngle - getAngle();
  1326. // Calculate delta angle.
  1327. const F32 deltaAngle = mAtan( mSin( relativeAngle ), mCos( relativeAngle ) );
  1328. // Calculate angular velocity over time.
  1329. const F32 angularVelocity = deltaAngle / (time * 0.001f);
  1330. // Set angular velocity.
  1331. setAngularVelocity( angularVelocity );
  1332. // Create and post event.
  1333. SceneObjectRotateToEvent* pEvent = new SceneObjectRotateToEvent( targetAngle, autoStop, warpToTarget );
  1334. mRotateToEventId = Sim::postEvent(this, pEvent, Sim::getCurrentTime() + time );
  1335. return true;
  1336. }
  1337. //-----------------------------------------------------------------------------
  1338. void SceneObject::cancelMoveTo( const bool autoStop )
  1339. {
  1340. // Only cancel an active moveTo event
  1341. if ( mMoveToEventId != 0 )
  1342. {
  1343. Sim::cancelEvent( mMoveToEventId );
  1344. mMoveToEventId = 0;
  1345. // Should we auto stop?
  1346. if ( autoStop )
  1347. {
  1348. // Yes, so remove linear velocity
  1349. setLinearVelocity( Vector2::getZero() );
  1350. }
  1351. }
  1352. }
  1353. //-----------------------------------------------------------------------------
  1354. void SceneObject::cancelRotateTo( const bool autoStop )
  1355. {
  1356. // Only cancel an active rotateTo event
  1357. if ( mRotateToEventId != 0 )
  1358. {
  1359. Sim::cancelEvent( mRotateToEventId );
  1360. mRotateToEventId = 0;
  1361. // Should we auto stop?
  1362. if ( autoStop )
  1363. {
  1364. // Yes, so remove angular velocity
  1365. setAngularVelocity( 0.0f );
  1366. }
  1367. }
  1368. }
  1369. //-----------------------------------------------------------------------------
  1370. b2Shape::Type SceneObject::getCollisionShapeType( U32 shapeIndex ) const
  1371. {
  1372. // Sanity!
  1373. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionShapeType() - Invalid shape index." );
  1374. if ( mpScene )
  1375. {
  1376. return mCollisionFixtures[shapeIndex]->GetType();
  1377. }
  1378. return mCollisionFixtureDefs[shapeIndex]->shape->GetType();
  1379. }
  1380. //-----------------------------------------------------------------------------
  1381. S32 SceneObject::getCollisionShapeIndex( const b2Fixture* pFixture ) const
  1382. {
  1383. // Iterate collision shapes.
  1384. S32 collisionShapeIndex = 0;
  1385. for( typeCollisionFixtureVector::const_iterator collisionShapeItr = mCollisionFixtures.begin(); collisionShapeItr != mCollisionFixtures.end(); ++collisionShapeItr, ++collisionShapeIndex )
  1386. {
  1387. // Return index if this is the collision shape we are searching for.
  1388. if ( pFixture == *collisionShapeItr )
  1389. return collisionShapeIndex;
  1390. }
  1391. // Not found.
  1392. return -1;
  1393. }
  1394. //-----------------------------------------------------------------------------
  1395. void SceneObject::setCollisionShapeDefinition( const U32 shapeIndex, const b2FixtureDef& fixtureDef )
  1396. {
  1397. // We only set specific features of a fixture definition here.
  1398. setCollisionShapeDensity( shapeIndex, fixtureDef.density );
  1399. setCollisionShapeFriction( shapeIndex, fixtureDef.friction );
  1400. setCollisionShapeRestitution( shapeIndex, fixtureDef.restitution );
  1401. setCollisionShapeIsSensor( shapeIndex, fixtureDef.isSensor );
  1402. }
  1403. //-----------------------------------------------------------------------------
  1404. b2FixtureDef SceneObject::getCollisionShapeDefinition( const U32 shapeIndex ) const
  1405. {
  1406. // Sanity!
  1407. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionShapeDefinition() - Invalid shape index." );
  1408. if ( mpScene )
  1409. {
  1410. // Fetch fixture.
  1411. const b2Fixture* pFixture = mCollisionFixtures[shapeIndex];
  1412. b2FixtureDef fixtureDef;
  1413. fixtureDef.density = pFixture->GetDensity();
  1414. fixtureDef.friction = pFixture->GetFriction();
  1415. fixtureDef.restitution = pFixture->GetRestitution();
  1416. fixtureDef.isSensor = pFixture->IsSensor();
  1417. fixtureDef.filter = pFixture->GetFilterData();
  1418. fixtureDef.shape = pFixture->GetShape();
  1419. return fixtureDef;
  1420. }
  1421. return *mCollisionFixtureDefs[shapeIndex];
  1422. }
  1423. //-----------------------------------------------------------------------------
  1424. const b2CircleShape* SceneObject::getCollisionCircleShape( const U32 shapeIndex ) const
  1425. {
  1426. // Sanity!
  1427. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionCircleShape() - Invalid shape index." );
  1428. // Fetch shape definition.
  1429. const b2FixtureDef fixtureDef = getCollisionShapeDefinition( shapeIndex );
  1430. // Sanity!
  1431. AssertFatal( fixtureDef.shape->GetType() == b2Shape::e_circle, "SceneObject::getCollisionCircleShape() - Shape is not a circle shape." );
  1432. // Fetch circle shape.
  1433. const b2CircleShape* pShape = dynamic_cast<const b2CircleShape*>( fixtureDef.shape );
  1434. // Sanity!
  1435. AssertFatal( pShape != NULL, "SceneObject::getCollisionCircleShape() - Invalid circle shape." );
  1436. return pShape;
  1437. }
  1438. //-----------------------------------------------------------------------------
  1439. const b2PolygonShape* SceneObject::getCollisionPolygonShape( const U32 shapeIndex ) const
  1440. {
  1441. // Sanity!
  1442. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionPolygonShape() - Invalid shape index." );
  1443. // Fetch shape definition.
  1444. const b2FixtureDef fixtureDef = getCollisionShapeDefinition( shapeIndex );
  1445. // Sanity!
  1446. AssertFatal( fixtureDef.shape->GetType() == b2Shape::e_polygon, "SceneObject::getCollisionPolygonShape() - Shape is not a polygon shape." );
  1447. // Fetch shape.
  1448. const b2PolygonShape* pShape = dynamic_cast<const b2PolygonShape*>( fixtureDef.shape );
  1449. // Sanity!
  1450. AssertFatal( pShape != NULL, "SceneObject::getCollisionPolygonShape() - Invalid polygon shape." );
  1451. return pShape;
  1452. }
  1453. //-----------------------------------------------------------------------------
  1454. const b2ChainShape* SceneObject::getCollisionChainShape( const U32 shapeIndex ) const
  1455. {
  1456. // Sanity!
  1457. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionChainShape() - Invalid shape index." );
  1458. // Fetch shape definition.
  1459. const b2FixtureDef fixtureDef = getCollisionShapeDefinition( shapeIndex );
  1460. // Sanity!
  1461. AssertFatal( fixtureDef.shape->GetType() == b2Shape::e_chain, "SceneObject::getCollisionChainShape() - Shape is not a chain shape." );
  1462. // Fetch shape.
  1463. const b2ChainShape* pShape = dynamic_cast<const b2ChainShape*>( fixtureDef.shape );
  1464. // Sanity!
  1465. AssertFatal( pShape != NULL, "SceneObject::getCollisionChainShape() - Invalid chain shape." );
  1466. return pShape;
  1467. }
  1468. //-----------------------------------------------------------------------------
  1469. const b2EdgeShape* SceneObject::getCollisionEdgeShape( const U32 shapeIndex ) const
  1470. {
  1471. // Sanity!
  1472. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionEdgeShape() - Invalid shape index." );
  1473. // Fetch shape definition.
  1474. const b2FixtureDef fixtureDef = getCollisionShapeDefinition( shapeIndex );
  1475. // Sanity!
  1476. AssertFatal( fixtureDef.shape->GetType() == b2Shape::e_edge, "SceneObject::getCollisionEdgeShape() - Shape is not a edge shape." );
  1477. // Fetch shape.
  1478. const b2EdgeShape* pShape = dynamic_cast<const b2EdgeShape*>( fixtureDef.shape );
  1479. // Sanity!
  1480. AssertFatal( pShape != NULL, "SceneObject::getCollisionEdgeShape() - Invalid edge shape." );
  1481. return pShape;
  1482. }
  1483. //-----------------------------------------------------------------------------
  1484. void SceneObject::setCollisionShapeDensity( const U32 shapeIndex, const F32 density )
  1485. {
  1486. // Sanity!
  1487. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::setCollisionShapeDensity() - Invalid shape index." );
  1488. if ( mpScene )
  1489. {
  1490. // Update live fixture.
  1491. mCollisionFixtures[shapeIndex]->SetDensity( density );
  1492. // Update the body mass data.
  1493. mpBody->ResetMassData();
  1494. return;
  1495. }
  1496. // Update offline fixture definition.
  1497. mCollisionFixtureDefs[shapeIndex]->density = density;
  1498. }
  1499. //-----------------------------------------------------------------------------
  1500. F32 SceneObject::getCollisionShapeDensity( const U32 shapeIndex ) const
  1501. {
  1502. // Sanity!
  1503. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionShapeDensity() - Invalid shape index." );
  1504. if ( mpScene )
  1505. {
  1506. // Use live fixture.
  1507. return mCollisionFixtures[shapeIndex]->GetDensity();
  1508. }
  1509. // Use offline fixture definition.
  1510. return mCollisionFixtureDefs[shapeIndex]->density;
  1511. }
  1512. //-----------------------------------------------------------------------------
  1513. void SceneObject::setCollisionShapeFriction( const U32 shapeIndex, const F32 friction )
  1514. {
  1515. // Sanity!
  1516. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::setCollisionShapeFriction() - Invalid shape index." );
  1517. if ( mpScene )
  1518. {
  1519. // Fetch the fixture.
  1520. b2Fixture* pFixture = mCollisionFixtures[shapeIndex];
  1521. // Update live fixture.
  1522. pFixture->SetFriction( friction );
  1523. // Re-filter fixture.
  1524. pFixture->Refilter();
  1525. return;
  1526. }
  1527. // Update offline fixture definition.
  1528. mCollisionFixtureDefs[shapeIndex]->friction = friction;
  1529. }
  1530. //-----------------------------------------------------------------------------
  1531. F32 SceneObject::getCollisionShapeFriction( const U32 shapeIndex ) const
  1532. {
  1533. // Sanity!
  1534. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionShapeFriction() - Invalid shape index." );
  1535. if ( mpScene )
  1536. {
  1537. // Use live fixture.
  1538. return mCollisionFixtures[shapeIndex]->GetFriction();
  1539. }
  1540. // Use offline fixture definition.
  1541. return mCollisionFixtureDefs[shapeIndex]->friction;
  1542. }
  1543. //-----------------------------------------------------------------------------
  1544. void SceneObject::setCollisionShapeRestitution( const U32 shapeIndex, const F32 restitution )
  1545. {
  1546. // Sanity!
  1547. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::setCollisionShapeRestitution() - Invalid shape index." );
  1548. if ( mpScene )
  1549. {
  1550. // Fetch the fixture.
  1551. b2Fixture* pFixture = mCollisionFixtures[shapeIndex];
  1552. // Update live fixture.
  1553. pFixture->SetRestitution( restitution );
  1554. // Re-filter fixture.
  1555. pFixture->Refilter();
  1556. return;
  1557. }
  1558. // Update offline fixture definition.
  1559. mCollisionFixtureDefs[shapeIndex]->restitution = restitution;
  1560. }
  1561. //-----------------------------------------------------------------------------
  1562. F32 SceneObject::getCollisionShapeRestitution( const U32 shapeIndex ) const
  1563. {
  1564. // Sanity!
  1565. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionShapeRestitution() - Invalid shape index." );
  1566. if ( mpScene )
  1567. {
  1568. // Use live fixture.
  1569. return mCollisionFixtures[shapeIndex]->GetRestitution();
  1570. }
  1571. // Use offline fixture definition.
  1572. return mCollisionFixtureDefs[shapeIndex]->restitution;
  1573. }
  1574. //-----------------------------------------------------------------------------
  1575. void SceneObject::setCollisionShapeIsSensor( const U32 shapeIndex, const bool isSensor )
  1576. {
  1577. // Sanity!
  1578. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::setCollisionShapeIsSensor() - Invalid shape index." );
  1579. if ( mpScene )
  1580. {
  1581. // Fetch the fixture.
  1582. b2Fixture* pFixture = mCollisionFixtures[shapeIndex];
  1583. // Update live fixture.
  1584. pFixture->SetSensor( isSensor );
  1585. // Re-filter fixture.
  1586. pFixture->Refilter();
  1587. return;
  1588. }
  1589. // Update offline fixture definition.
  1590. mCollisionFixtureDefs[shapeIndex]->isSensor = isSensor;
  1591. }
  1592. //-----------------------------------------------------------------------------
  1593. bool SceneObject::getCollisionShapeIsSensor( const U32 shapeIndex ) const
  1594. {
  1595. // Sanity!
  1596. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::getCollisionShapeIsSensor() - Invalid shape index." );
  1597. if ( mpScene )
  1598. {
  1599. // Use live fixture.
  1600. return mCollisionFixtures[shapeIndex]->IsSensor();
  1601. }
  1602. // Use offline fixture definition.
  1603. return mCollisionFixtureDefs[shapeIndex]->isSensor;
  1604. }
  1605. //-----------------------------------------------------------------------------
  1606. void SceneObject::deleteCollisionShape( const U32 shapeIndex )
  1607. {
  1608. // Sanity!
  1609. AssertFatal( shapeIndex < getCollisionShapeCount(), "SceneObject::deleteCollisionShape() - Invalid shape index." );
  1610. if ( mpScene )
  1611. {
  1612. mpBody->DestroyFixture( mCollisionFixtures[ shapeIndex ] );
  1613. mCollisionFixtures.erase_fast( shapeIndex );
  1614. return;
  1615. }
  1616. mCollisionFixtureDefs.erase_fast( shapeIndex );
  1617. }
  1618. //-----------------------------------------------------------------------------
  1619. void SceneObject::clearCollisionShapes( void )
  1620. {
  1621. // Delete all collision shapes.
  1622. while ( getCollisionShapeCount() > 0 )
  1623. {
  1624. deleteCollisionShape( 0 );
  1625. }
  1626. }
  1627. //-----------------------------------------------------------------------------
  1628. S32 SceneObject::createCircleCollisionShape( const F32 radius )
  1629. {
  1630. // Debug Profiling.
  1631. PROFILE_SCOPE(SceneObject_CreateCircleCollisionShape);
  1632. return createCircleCollisionShape( radius, b2Vec2(0.0f, 0.0f) );
  1633. }
  1634. //-----------------------------------------------------------------------------
  1635. S32 SceneObject::createCircleCollisionShape( const F32 radius, const b2Vec2& localPosition )
  1636. {
  1637. // Sanity!
  1638. if ( radius <= 0.0f )
  1639. {
  1640. Con::errorf("SceneObject::createCircleCollisionShape() - Invalid radius of %g.", radius);
  1641. return -1;
  1642. }
  1643. // Configure fixture definition.
  1644. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1645. b2CircleShape* pShape = new b2CircleShape();
  1646. pShape->m_p = localPosition;
  1647. pShape->m_radius = radius;
  1648. pFixtureDef->shape = pShape;
  1649. if ( mpScene )
  1650. {
  1651. // Create and push fixture.
  1652. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1653. // Destroy shape and fixture.
  1654. delete pShape;
  1655. delete pFixtureDef;
  1656. return mCollisionFixtures.size()-1;
  1657. }
  1658. // Push fixture definition.
  1659. mCollisionFixtureDefs.push_back( pFixtureDef );
  1660. return mCollisionFixtureDefs.size()-1;
  1661. }
  1662. //-----------------------------------------------------------------------------
  1663. F32 SceneObject::getCircleCollisionShapeRadius( const U32 shapeIndex ) const
  1664. {
  1665. // Fetch shape.
  1666. const b2CircleShape* pShape = getCollisionCircleShape( shapeIndex );
  1667. return pShape->m_radius;
  1668. }
  1669. //-----------------------------------------------------------------------------
  1670. Vector2 SceneObject::getCircleCollisionShapeLocalPosition( const U32 shapeIndex ) const
  1671. {
  1672. // Fetch shape.
  1673. const b2CircleShape* pShape = getCollisionCircleShape( shapeIndex );
  1674. return pShape->m_p;
  1675. }
  1676. //-----------------------------------------------------------------------------
  1677. S32 SceneObject::createPolygonCollisionShape( const U32 pointCount, const b2Vec2* localPoints )
  1678. {
  1679. // Debug Profiling.
  1680. PROFILE_SCOPE(SceneObject_CreatePolygonCollisionShape);
  1681. // Sanity!
  1682. if ( pointCount < 3 || pointCount > b2_maxPolygonVertices )
  1683. {
  1684. Con::errorf("SceneObject::createPolygonCollisionShape() - Invalid point count of %d.", pointCount);
  1685. return -1;
  1686. }
  1687. // Configure fixture definition.
  1688. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1689. b2PolygonShape* pShape = new b2PolygonShape();
  1690. pShape->Set( localPoints, pointCount );
  1691. pFixtureDef->shape = pShape;
  1692. if ( mpScene )
  1693. {
  1694. // Create and push fixture.
  1695. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1696. // Destroy shape and fixture.
  1697. delete pShape;
  1698. delete pFixtureDef;
  1699. return mCollisionFixtures.size()-1;
  1700. }
  1701. // Push fixture definition.
  1702. mCollisionFixtureDefs.push_back( pFixtureDef );
  1703. return mCollisionFixtureDefs.size()-1;
  1704. }
  1705. //-----------------------------------------------------------------------------
  1706. S32 SceneObject::createPolygonBoxCollisionShape( const F32 width, const F32 height )
  1707. {
  1708. // Debug Profiling.
  1709. PROFILE_SCOPE(SceneObject_CreatePolygonBoxCollisionShapeWidthHeight);
  1710. // Sanity!
  1711. if ( width <= 0.0f )
  1712. {
  1713. Con::errorf("SceneObject::createPolygonBoxCollisionShape() - Invalid width of %g.", width);
  1714. return -1;
  1715. }
  1716. if ( height <= 0.0f )
  1717. {
  1718. Con::errorf("SceneObject::createPolygonBoxCollisionShape() - Invalid height of %g.", height);
  1719. return -1;
  1720. }
  1721. // Configure fixture definition.
  1722. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1723. b2PolygonShape* pShape = new b2PolygonShape();
  1724. pShape->SetAsBox( width * 0.5f, height * 0.5f );
  1725. pFixtureDef->shape = pShape;
  1726. if ( mpScene )
  1727. {
  1728. // Create and push fixture.
  1729. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1730. // Destroy shape and fixture.
  1731. delete pShape;
  1732. delete pFixtureDef;
  1733. return mCollisionFixtures.size()-1;
  1734. }
  1735. // Push fixture definition.
  1736. mCollisionFixtureDefs.push_back( pFixtureDef );
  1737. return mCollisionFixtureDefs.size()-1;
  1738. }
  1739. //-----------------------------------------------------------------------------
  1740. S32 SceneObject::createPolygonBoxCollisionShape( const F32 width, const F32 height, const b2Vec2& localCentroid )
  1741. {
  1742. // Debug Profiling.
  1743. PROFILE_SCOPE(SceneObject_CreatePolygonBoxCollisionShapeWidthHeightCentroid);
  1744. // Sanity!
  1745. if ( width <= 0.0f )
  1746. {
  1747. Con::errorf("SceneObject::createPolygonBoxCollisionShape() - Invalid width of %g.", width);
  1748. return -1;
  1749. }
  1750. if ( height <= 0.0f )
  1751. {
  1752. Con::errorf("SceneObject::createPolygonBoxCollisionShape() - Invalid height of %g.", height);
  1753. return -1;
  1754. }
  1755. // Configure fixture definition.
  1756. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1757. b2PolygonShape* pShape = new b2PolygonShape();
  1758. pShape->SetAsBox( width * 0.5f, height * 0.5f, localCentroid, 0.0f );
  1759. pFixtureDef->shape = pShape;
  1760. if ( mpScene )
  1761. {
  1762. // Create and push fixture.
  1763. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1764. // Destroy shape and fixture.
  1765. delete pShape;
  1766. delete pFixtureDef;
  1767. return mCollisionFixtures.size()-1;
  1768. }
  1769. // Push fixture definition.
  1770. mCollisionFixtureDefs.push_back( pFixtureDef );
  1771. return mCollisionFixtureDefs.size()-1;
  1772. }
  1773. //-----------------------------------------------------------------------------
  1774. S32 SceneObject::createPolygonBoxCollisionShape( const F32 width, const F32 height, const b2Vec2& localCentroid, const F32 rotation )
  1775. {
  1776. // Debug Profiling.
  1777. PROFILE_SCOPE(SceneObject_CreatePolygonBoxCollisionShapeWidthHeightCentroidRotation);
  1778. // Sanity!
  1779. if ( width <= 0.0f )
  1780. {
  1781. Con::errorf("SceneObject::createPolygonBoxCollisionShape() - Invalid width of %g.", width);
  1782. return -1;
  1783. }
  1784. if ( height <= 0.0f )
  1785. {
  1786. Con::errorf("SceneObject::createPolygonBoxCollisionShape() - Invalid height of %g.", height);
  1787. return -1;
  1788. }
  1789. // Configure fixture definition.
  1790. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1791. b2PolygonShape* pShape = new b2PolygonShape();
  1792. pShape->SetAsBox( width * 0.5f, height * 0.5f, localCentroid, rotation );
  1793. pFixtureDef->shape = pShape;
  1794. if ( mpScene )
  1795. {
  1796. // Create and push fixture.
  1797. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1798. // Destroy shape and fixture.
  1799. delete pShape;
  1800. delete pFixtureDef;
  1801. return mCollisionFixtures.size()-1;
  1802. }
  1803. // Push fixture definition.
  1804. mCollisionFixtureDefs.push_back( pFixtureDef );
  1805. return mCollisionFixtureDefs.size()-1;
  1806. }
  1807. //-----------------------------------------------------------------------------
  1808. U32 SceneObject::getPolygonCollisionShapePointCount( const U32 shapeIndex ) const
  1809. {
  1810. // Fetch shape.
  1811. const b2PolygonShape* pShape = getCollisionPolygonShape( shapeIndex );
  1812. return pShape->GetVertexCount();
  1813. }
  1814. //-----------------------------------------------------------------------------
  1815. Vector2 SceneObject::getPolygonCollisionShapeLocalPoint( const U32 shapeIndex, const U32 pointIndex ) const
  1816. {
  1817. // Fetch shape.
  1818. const b2PolygonShape* pShape = getCollisionPolygonShape( shapeIndex );
  1819. // Sanity!
  1820. AssertFatal( pointIndex < (U32)pShape->GetVertexCount(), "SceneObject::getPolygonCollisionShapeLocalPoint() - Invalid local point index." );
  1821. return pShape->GetVertex( pointIndex );
  1822. }
  1823. //-----------------------------------------------------------------------------
  1824. S32 SceneObject::createChainCollisionShape( const U32 pointCount, const b2Vec2* localPoints )
  1825. {
  1826. // Debug Profiling.
  1827. PROFILE_SCOPE(SceneObject_CreateChainCollisionShape);
  1828. // Sanity!
  1829. if ( pointCount < 2 )
  1830. {
  1831. Con::errorf("SceneObject::createChainCollisionShape() - Invalid point count of %d.", pointCount);
  1832. return -1;
  1833. }
  1834. // Configure fixture definition.
  1835. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1836. b2ChainShape* pShape = new b2ChainShape();
  1837. pShape->CreateChain( localPoints, pointCount );
  1838. pFixtureDef->shape = pShape;
  1839. if ( mpScene )
  1840. {
  1841. // Create and push fixture.
  1842. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1843. // Destroy shape and fixture.
  1844. delete pShape;
  1845. delete pFixtureDef;
  1846. return mCollisionFixtures.size()-1;
  1847. }
  1848. // Push fixture definition.
  1849. mCollisionFixtureDefs.push_back( pFixtureDef );
  1850. return mCollisionFixtureDefs.size()-1;
  1851. }
  1852. //-----------------------------------------------------------------------------
  1853. S32 SceneObject::createChainCollisionShape( const U32 pointCount, const b2Vec2* localPoints,
  1854. const bool hasAdjacentLocalPositionStart, const bool hasAdjacentLocalPositionEnd,
  1855. const b2Vec2& adjacentLocalPositionStart, const b2Vec2& adjacentLocalPositionEnd )
  1856. {
  1857. // Debug Profiling.
  1858. PROFILE_SCOPE(SceneObject_CreateChainCollisionShapeAdjacents);
  1859. // Sanity!
  1860. if ( pointCount < 2 )
  1861. {
  1862. Con::errorf("SceneObject::createChainCollisionShape() - Invalid point count of %d.", pointCount);
  1863. return -1;
  1864. }
  1865. // Configure fixture definition.
  1866. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1867. b2ChainShape* pShape = new b2ChainShape();
  1868. pShape->CreateChain( localPoints, pointCount );
  1869. if ( hasAdjacentLocalPositionStart )
  1870. pShape->SetPrevVertex( adjacentLocalPositionStart );
  1871. if ( hasAdjacentLocalPositionEnd )
  1872. pShape->SetNextVertex( adjacentLocalPositionEnd );
  1873. pFixtureDef->shape = pShape;
  1874. if ( mpScene )
  1875. {
  1876. // Create and push fixture.
  1877. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1878. // Destroy shape and fixture.
  1879. delete pShape;
  1880. delete pFixtureDef;
  1881. return mCollisionFixtures.size()-1;
  1882. }
  1883. // Push fixture definition.
  1884. mCollisionFixtureDefs.push_back( pFixtureDef );
  1885. return mCollisionFixtureDefs.size()-1;
  1886. }
  1887. //-----------------------------------------------------------------------------
  1888. U32 SceneObject::getChainCollisionShapePointCount( const U32 shapeIndex ) const
  1889. {
  1890. // Fetch shape.
  1891. const b2ChainShape* pShape = getCollisionChainShape( shapeIndex );
  1892. return pShape->m_count;
  1893. }
  1894. //-----------------------------------------------------------------------------
  1895. Vector2 SceneObject::getChainCollisionShapeLocalPoint( const U32 shapeIndex, const U32 pointIndex ) const
  1896. {
  1897. // Fetch shape.
  1898. const b2ChainShape* pShape = getCollisionChainShape( shapeIndex );
  1899. // Sanity!
  1900. AssertFatal( pointIndex < (U32)pShape->m_count, "SceneObject::getChainCollisionShapeLocalPoint() - Invalid local point index." );
  1901. return pShape->m_vertices[ pointIndex ];
  1902. }
  1903. //-----------------------------------------------------------------------------
  1904. bool SceneObject::getChainCollisionShapeHasAdjacentStart( const U32 shapeIndex ) const
  1905. {
  1906. // Fetch shape.
  1907. const b2ChainShape* pShape = getCollisionChainShape( shapeIndex );
  1908. return pShape->m_hasPrevVertex;
  1909. }
  1910. //-----------------------------------------------------------------------------
  1911. bool SceneObject::getChainCollisionShapeHasAdjacentEnd( const U32 shapeIndex ) const
  1912. {
  1913. // Fetch shape.
  1914. const b2ChainShape* pShape = getCollisionChainShape( shapeIndex );
  1915. return pShape->m_hasNextVertex;
  1916. }
  1917. //-----------------------------------------------------------------------------
  1918. Vector2 SceneObject::getChainCollisionShapeAdjacentStart( const U32 shapeIndex ) const
  1919. {
  1920. // Fetch shape.
  1921. const b2ChainShape* pShape = getCollisionChainShape( shapeIndex );
  1922. return pShape->m_prevVertex;
  1923. }
  1924. //-----------------------------------------------------------------------------
  1925. Vector2 SceneObject::getChainCollisionShapeAdjacentEnd( const U32 shapeIndex ) const
  1926. {
  1927. // Fetch shape.
  1928. const b2ChainShape* pShape = getCollisionChainShape( shapeIndex );
  1929. return pShape->m_nextVertex;
  1930. }
  1931. //-----------------------------------------------------------------------------
  1932. S32 SceneObject::createEdgeCollisionShape( const b2Vec2& localPositionStart, const b2Vec2& localPositionEnd )
  1933. {
  1934. // Debug Profiling.
  1935. PROFILE_SCOPE(SceneObject_CreateEdgeCollisionShape);
  1936. // Configure fixture definition.
  1937. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1938. b2EdgeShape* pShape = new b2EdgeShape();
  1939. pShape->Set( localPositionStart, localPositionEnd );
  1940. pFixtureDef->shape = pShape;
  1941. if ( mpScene )
  1942. {
  1943. // Create and push fixture.
  1944. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1945. // Destroy shape and fixture.
  1946. delete pShape;
  1947. delete pFixtureDef;
  1948. return mCollisionFixtures.size()-1;
  1949. }
  1950. // Push fixture definition.
  1951. mCollisionFixtureDefs.push_back( pFixtureDef );
  1952. return mCollisionFixtureDefs.size()-1;
  1953. }
  1954. //-----------------------------------------------------------------------------
  1955. S32 SceneObject::createEdgeCollisionShape( const b2Vec2& localPositionStart, const b2Vec2& localPositionEnd,
  1956. const bool hasAdjacentLocalPositionStart, const bool hasAdjacentLocalPositionEnd,
  1957. const b2Vec2& adjacentLocalPositionStart, const b2Vec2& adjacentLocalPositionEnd )
  1958. {
  1959. // Debug Profiling.
  1960. PROFILE_SCOPE(SceneObject_CreateEdgeCollisionShapeAdjacents);
  1961. // Configure fixture definition.
  1962. b2FixtureDef* pFixtureDef = new b2FixtureDef( mDefaultFixture );
  1963. b2EdgeShape* pShape = new b2EdgeShape();
  1964. pShape->Set( localPositionStart, localPositionEnd );
  1965. pShape->m_hasVertex0 = hasAdjacentLocalPositionStart;
  1966. pShape->m_hasVertex3 = hasAdjacentLocalPositionEnd;
  1967. pShape->m_vertex0 = adjacentLocalPositionStart;
  1968. pShape->m_vertex3 = adjacentLocalPositionEnd;
  1969. pFixtureDef->shape = pShape;
  1970. if ( mpScene )
  1971. {
  1972. // Create and push fixture.
  1973. mCollisionFixtures.push_back( mpBody->CreateFixture( pFixtureDef ) );
  1974. // Destroy shape and fixture.
  1975. delete pShape;
  1976. delete pFixtureDef;
  1977. return mCollisionFixtures.size()-1;
  1978. }
  1979. // Push fixture definition.
  1980. mCollisionFixtureDefs.push_back( pFixtureDef );
  1981. return mCollisionFixtureDefs.size()-1;
  1982. }
  1983. //-----------------------------------------------------------------------------
  1984. Vector2 SceneObject::getEdgeCollisionShapeLocalPositionStart( const U32 shapeIndex ) const
  1985. {
  1986. // Fetch shape.
  1987. const b2EdgeShape* pShape = getCollisionEdgeShape( shapeIndex );
  1988. return pShape->m_vertex1;
  1989. }
  1990. //-----------------------------------------------------------------------------
  1991. Vector2 SceneObject::getEdgeCollisionShapeLocalPositionEnd( const U32 shapeIndex ) const
  1992. {
  1993. // Fetch shape.
  1994. const b2EdgeShape* pShape = getCollisionEdgeShape( shapeIndex );
  1995. return pShape->m_vertex2;
  1996. }
  1997. //-----------------------------------------------------------------------------
  1998. bool SceneObject::getEdgeCollisionShapeHasAdjacentStart( const U32 shapeIndex ) const
  1999. {
  2000. // Fetch shape.
  2001. const b2EdgeShape* pShape = getCollisionEdgeShape( shapeIndex );
  2002. return pShape->m_hasVertex0;
  2003. }
  2004. //-----------------------------------------------------------------------------
  2005. bool SceneObject::getEdgeCollisionShapeHasAdjacentEnd( const U32 shapeIndex ) const
  2006. {
  2007. // Fetch shape.
  2008. const b2EdgeShape* pShape = getCollisionEdgeShape( shapeIndex );
  2009. return pShape->m_hasVertex3;
  2010. }
  2011. //-----------------------------------------------------------------------------
  2012. Vector2 SceneObject::getEdgeCollisionShapeAdjacentStart( const U32 shapeIndex ) const
  2013. {
  2014. // Fetch shape.
  2015. const b2EdgeShape* pShape = getCollisionEdgeShape( shapeIndex );
  2016. return pShape->m_vertex0;
  2017. }
  2018. //-----------------------------------------------------------------------------
  2019. Vector2 SceneObject::getEdgeCollisionShapeAdjacentEnd( const U32 shapeIndex ) const
  2020. {
  2021. // Fetch shape.
  2022. const b2EdgeShape* pShape = getCollisionEdgeShape( shapeIndex );
  2023. return pShape->m_vertex3;
  2024. }
  2025. //-----------------------------------------------------------------------------
  2026. void SceneObject::setBlendOptions( void )
  2027. {
  2028. // Set Blend Status.
  2029. if ( mBlendMode )
  2030. {
  2031. // Enable Blending.
  2032. glEnable( GL_BLEND );
  2033. // Set Blend Function.
  2034. glBlendFunc( mSrcBlendFactor, mDstBlendFactor );
  2035. // Set Colour.
  2036. glColor4f(mBlendColor.red,mBlendColor.green,mBlendColor.blue,mBlendColor.alpha );
  2037. }
  2038. else
  2039. {
  2040. // Disable Blending.
  2041. glDisable( GL_BLEND );
  2042. // Reset Colour.
  2043. glColor4f(1,1,1,1);
  2044. }
  2045. // Set Alpha Test.
  2046. if ( mAlphaTest >= 0.0f )
  2047. {
  2048. // Enable Test.
  2049. glEnable( GL_ALPHA_TEST );
  2050. glAlphaFunc( GL_GREATER, mAlphaTest );
  2051. }
  2052. else
  2053. {
  2054. // Disable Test.
  2055. glDisable( GL_ALPHA_TEST );
  2056. }
  2057. }
  2058. //-----------------------------------------------------------------------------
  2059. void SceneObject::resetBlendOptions( void )
  2060. {
  2061. // Disable Blending.
  2062. glDisable( GL_BLEND );
  2063. glDisable( GL_ALPHA_TEST);
  2064. // Reset Colour.
  2065. glColor4f(1,1,1,1);
  2066. }
  2067. //---------------------------------------------------------------------------------------------
  2068. void SceneObject::onInputEvent( StringTableEntry name, const GuiEvent& event, const Vector2& worldMousePosition )
  2069. {
  2070. // Debug Profiling.
  2071. PROFILE_SCOPE(SceneObject_OnInputEvent);
  2072. // Argument Buffers.
  2073. char argBuffer[3][32];
  2074. // ID
  2075. dSprintf(argBuffer[0], 32, "%d", event.eventID);
  2076. // Format Mouse-Position Buffer.
  2077. dSprintf(argBuffer[1], 32, "%g %g", worldMousePosition.x, worldMousePosition.y);
  2078. // Optional double click
  2079. dSprintf(argBuffer[2], 32, "%d", event.mouseClickCount);
  2080. // Call Scripts.
  2081. Con::executef(this, 4, name, argBuffer[0], argBuffer[1], argBuffer[2]);
  2082. }
  2083. //-----------------------------------------------------------------------------
  2084. void SceneObject::attachGui( GuiControl* pGuiControl, SceneWindow* pSceneWindow, const bool sizeControl )
  2085. {
  2086. // Attach Gui Control.
  2087. mpAttachedGui = pGuiControl;
  2088. // Attach SceneWindow.
  2089. mpAttachedGuiSceneWindow = pSceneWindow;
  2090. // Set Size Gui Flag.
  2091. mAttachedGuiSizeControl = sizeControl;
  2092. // Register Gui Control/Window References.
  2093. mpAttachedGui->registerReference( (SimObject**)&mpAttachedGui );
  2094. mpAttachedGuiSceneWindow->registerReference( (SimObject**)&mpAttachedGuiSceneWindow );
  2095. // Check/Adjust Parentage.
  2096. if ( mpAttachedGui->getParent() != mpAttachedGuiSceneWindow )
  2097. {
  2098. // Warn.
  2099. // Remove GuiControl from existing parent (if it has one).
  2100. if ( mpAttachedGui->getParent() )
  2101. {
  2102. mpAttachedGui->getParent()->removeObject( mpAttachedGui );
  2103. }
  2104. // Add it to the scene-window.
  2105. mpAttachedGuiSceneWindow->addObject( mpAttachedGui );
  2106. }
  2107. }
  2108. //-----------------------------------------------------------------------------
  2109. void SceneObject::detachGui( void )
  2110. {
  2111. // Unregister Gui Control Reference.
  2112. if ( mpAttachedGui )
  2113. {
  2114. // [neo, 5/7/2007 - #2997]
  2115. // Changed to UNregisterReference was registerReference which would crash later
  2116. mpAttachedGui->unregisterReference( (SimObject**)&mpAttachedGui );
  2117. mpAttachedGui = NULL;
  2118. }
  2119. // Unregister Gui Control Reference.
  2120. if ( mpAttachedGuiSceneWindow )
  2121. {
  2122. mpAttachedGuiSceneWindow->registerReference( (SimObject**)&mpAttachedGuiSceneWindow );
  2123. mpAttachedGuiSceneWindow = NULL;
  2124. }
  2125. }
  2126. //-----------------------------------------------------------------------------
  2127. void SceneObject::updateAttachedGui( void )
  2128. {
  2129. // Debug Profiling.
  2130. PROFILE_SCOPE(SceneObject_updateAttachedGui);
  2131. // Finish if either Gui Control or Window is invalid.
  2132. if ( !mpAttachedGui || !mpAttachedGuiSceneWindow )
  2133. return;
  2134. // Ignore if we're not in the scene that the scene-window is attached to.
  2135. if ( getScene() != mpAttachedGuiSceneWindow->getScene() )
  2136. {
  2137. // Warn.
  2138. Con::warnf("SceneObject::updateAttachedGui() - SceneWindow is not attached to my Scene!");
  2139. // Detach from GUI Control.
  2140. detachGui();
  2141. // Finish Here.
  2142. return;
  2143. }
  2144. // Calculate the GUI Controls' dimensions.
  2145. Point2I topLeftI, extentI;
  2146. // Size Control?
  2147. if ( mAttachedGuiSizeControl )
  2148. {
  2149. // Yes, so fetch Clip Rectangle; this forms the area we want to fix the Gui-Control to.
  2150. const RectF objAABB = getAABBRectangle();
  2151. // Fetch Top-Left.
  2152. Vector2 upperLeft = Vector2( objAABB.point.x, objAABB.point.y + objAABB.extent.y );
  2153. Vector2 lowerRight = Vector2( objAABB.point.x + objAABB.extent.x, objAABB.point.y );
  2154. // Convert Scene to Window Coordinates.
  2155. mpAttachedGuiSceneWindow->sceneToWindowPoint( upperLeft, upperLeft );
  2156. mpAttachedGuiSceneWindow->sceneToWindowPoint( lowerRight, lowerRight );
  2157. // Convert Control Dimensions.
  2158. topLeftI.set( S32(upperLeft.x), S32(upperLeft.y) );
  2159. extentI.set( S32(lowerRight.x-upperLeft.x), S32(lowerRight.y-upperLeft.y) );
  2160. }
  2161. else
  2162. {
  2163. // No, so center GUI-Control on objects position but don't resize it.
  2164. // Calculate Position from World Clip.
  2165. const RectF clipRectangle = getAABBRectangle();
  2166. // Calculate center position.
  2167. const Vector2 centerPosition = clipRectangle.point + Vector2(clipRectangle.len_x()*0.5f, clipRectangle.len_y()*0.5f);
  2168. // Convert Scene to Window Coordinates.
  2169. Vector2 positionI;
  2170. mpAttachedGuiSceneWindow->sceneToWindowPoint( centerPosition, positionI );
  2171. // Fetch Control Extents (which don't change here).
  2172. extentI = mpAttachedGui->getExtent();
  2173. // Calculate new top-left.
  2174. topLeftI.set( S32(positionI.x-extentI.x/2), S32(positionI.y-extentI.y/2) );
  2175. }
  2176. // Set Control Dimensions.
  2177. mpAttachedGui->resize( topLeftI, extentI );
  2178. }
  2179. //-----------------------------------------------------------------------------
  2180. void SceneObject::copyFrom( SceneObject* pSceneObject, const bool copyDynamicFields )
  2181. {
  2182. // Copy the specified object.
  2183. pSceneObject->copyTo( this );
  2184. // Copy over dynamic fields if requested.
  2185. if ( copyDynamicFields )
  2186. pSceneObject->assignDynamicFieldsFrom( this );
  2187. }
  2188. //-----------------------------------------------------------------------------
  2189. void SceneObject::copyTo( SimObject* obj )
  2190. {
  2191. // Debug Profiling.
  2192. PROFILE_SCOPE(SceneObject_CopyTo);
  2193. // Call parent.
  2194. Parent::copyTo(obj);
  2195. // Fetch object.
  2196. SceneObject* pSceneObject = dynamic_cast<SceneObject*>(obj);
  2197. // Sanity!
  2198. AssertFatal(pSceneObject != NULL, "SceneObject::copyTo() - Object is not the correct type.");
  2199. /// Lifetime.
  2200. pSceneObject->setLifetime( getLifetime() );
  2201. /// Scene Layers.
  2202. pSceneObject->setSceneLayer( getSceneLayer() );
  2203. /// Scene groups.
  2204. pSceneObject->setSceneGroup( getSceneGroup() );
  2205. /// Area.
  2206. pSceneObject->setSize( getSize() );
  2207. /// Position / Angle.
  2208. pSceneObject->setPosition( getPosition() );
  2209. pSceneObject->setAngle( getAngle() );
  2210. pSceneObject->setFixedAngle( getFixedAngle() );
  2211. /// Body.
  2212. pSceneObject->setBodyType( getBodyType() );
  2213. pSceneObject->setActive( getActive() );
  2214. pSceneObject->setAwake( getAwake() );
  2215. pSceneObject->setBullet( getBullet() );
  2216. pSceneObject->setSleepingAllowed( getSleepingAllowed() );
  2217. /// Collision control.
  2218. pSceneObject->setCollisionGroups( getCollisionGroupMask() );
  2219. pSceneObject->setCollisionLayers( getCollisionLayerMask() );
  2220. pSceneObject->setCollisionSuppress( getCollisionSuppress() );
  2221. pSceneObject->setGatherContacts( getGatherContacts() );
  2222. pSceneObject->setDefaultDensity( getDefaultDensity() );
  2223. pSceneObject->setDefaultFriction( getDefaultFriction() );
  2224. pSceneObject->setDefaultRestitution( getDefaultRestitution() );
  2225. /// Velocities.
  2226. pSceneObject->setLinearVelocity( getLinearVelocity() );
  2227. pSceneObject->setAngularVelocity( getAngularVelocity() );
  2228. pSceneObject->setLinearDamping( getLinearDamping() );
  2229. pSceneObject->setAngularDamping( getAngularDamping() );
  2230. /// Gravity scaling.
  2231. pSceneObject->setGravityScale( getGravityScale() );
  2232. /// Collision shapes.
  2233. copyCollisionShapes( pSceneObject, true );
  2234. /// Render visibility.
  2235. pSceneObject->setVisible( getVisible() );
  2236. /// Render blending.
  2237. pSceneObject->setBlendMode( getBlendMode() );
  2238. pSceneObject->setSrcBlendFactor( getSrcBlendFactor() );
  2239. pSceneObject->setDstBlendFactor( getDstBlendFactor() );
  2240. pSceneObject->setBlendColor( getBlendColor() );
  2241. pSceneObject->setAlphaTest( getAlphaTest() );
  2242. /// Render sorting.
  2243. pSceneObject->setSortPoint( getSortPoint() );
  2244. /// Input events.
  2245. pSceneObject->setUseInputEvents( getUseInputEvents() );
  2246. // Script callbacks.
  2247. pSceneObject->setUpdateCallback( getUpdateCallback() );
  2248. pSceneObject->setCollisionCallback( getCollisionCallback() );
  2249. pSceneObject->setSleepingCallback( getSleepingCallback() );
  2250. /// Misc.
  2251. pSceneObject->setBatchIsolated( getBatchIsolated() );
  2252. /// Debug mode.
  2253. setDebugOn( getDebugMask() );
  2254. }
  2255. //-----------------------------------------------------------------------------
  2256. S32 SceneObject::copyCollisionShapes( SceneObject* pSceneObject, const bool clearTargetShapes, const S32 shapeIndex )
  2257. {
  2258. // Sanity!
  2259. AssertFatal( pSceneObject != NULL, "SceneObject::copyCollisionShapes() - Cannot copy to a NULL scene object." );
  2260. // Clear the collision shapes.
  2261. if ( clearTargetShapes )
  2262. pSceneObject->clearCollisionShapes();
  2263. // Fetch collision shape count.
  2264. const U32 collisionShapeCount = getCollisionShapeCount();
  2265. // If a shape index is specified, is it valid?
  2266. if ( shapeIndex != INVALID_COLLISION_SHAPE_INDEX && shapeIndex >= (S32)collisionShapeCount )
  2267. {
  2268. // No, so warn.
  2269. Con::warnf( "SceneObject::copyCollisionShapes() - Invalid shape index '%d'.", shapeIndex );
  2270. return INVALID_COLLISION_SHAPE_INDEX;
  2271. }
  2272. // Finish if there are no collision shapes.
  2273. if ( collisionShapeCount == 0 )
  2274. return INVALID_COLLISION_SHAPE_INDEX;
  2275. // Calculate shape range.
  2276. const U32 startShapeIndex = shapeIndex >= 0 ? shapeIndex : 0;
  2277. const U32 endShapeIndex = shapeIndex >= 0 ? shapeIndex : collisionShapeCount -1;
  2278. // Iterate collision shapes.
  2279. for ( U32 index = startShapeIndex; index <= endShapeIndex; ++index )
  2280. {
  2281. b2FixtureDef fixtureDef;
  2282. if ( mpScene )
  2283. {
  2284. // Fetch fixture.
  2285. b2Fixture* pFixture = mCollisionFixtures[index];
  2286. // Fetch common details.
  2287. fixtureDef.density = pFixture->GetDensity();
  2288. fixtureDef.friction = pFixture->GetFriction();
  2289. fixtureDef.restitution = pFixture->GetRestitution();
  2290. fixtureDef.isSensor = pFixture->IsSensor();
  2291. fixtureDef.shape = pFixture->GetShape();
  2292. }
  2293. else
  2294. {
  2295. // Fetch fixture def.
  2296. b2FixtureDef* pFixtureDef = mCollisionFixtureDefs[index];
  2297. // Fetch common details.
  2298. fixtureDef = *pFixtureDef;
  2299. }
  2300. S32 newShapeIndex;
  2301. // Fetch shape type.
  2302. const b2Shape::Type shapeType = fixtureDef.shape->GetType();
  2303. // Copy appropriate shape type.
  2304. switch( shapeType )
  2305. {
  2306. case b2Shape::e_circle:
  2307. newShapeIndex = copyCircleCollisionShapeTo( pSceneObject, fixtureDef );
  2308. // Return the new shape if we're copying a specific index.
  2309. if ( shapeIndex >= 0 )
  2310. return newShapeIndex;
  2311. continue;
  2312. case b2Shape::e_polygon:
  2313. newShapeIndex = copyPolygonCollisionShapeTo( pSceneObject, fixtureDef );
  2314. // Return the new shape if we're copying a specific index.
  2315. if ( shapeIndex >= 0 )
  2316. return newShapeIndex;
  2317. continue;
  2318. case b2Shape::e_chain:
  2319. newShapeIndex = copyChainCollisionShapeTo( pSceneObject, fixtureDef );
  2320. // Return the new shape if we're copying a specific index.
  2321. if ( shapeIndex >= 0 )
  2322. return newShapeIndex;
  2323. continue;
  2324. case b2Shape::e_edge:
  2325. newShapeIndex = copyEdgeCollisionShapeTo( pSceneObject, fixtureDef );
  2326. // Return the new shape if we're copying a specific index.
  2327. if ( shapeIndex >= 0 )
  2328. return newShapeIndex;
  2329. continue;
  2330. default:
  2331. AssertFatal( false, "SceneObject::copyCollisionShapes() - Unsupported collision shape type encountered." );
  2332. }
  2333. }
  2334. // Return the first index if we're copying all the shapes.
  2335. if ( shapeIndex < 0 )
  2336. return 0;
  2337. return INVALID_COLLISION_SHAPE_INDEX;
  2338. }
  2339. //-----------------------------------------------------------------------------
  2340. S32 SceneObject::copyCircleCollisionShapeTo( SceneObject* pSceneObject, const b2FixtureDef& fixtureDef ) const
  2341. {
  2342. // Fetch shape.
  2343. const b2CircleShape* pShape = dynamic_cast<const b2CircleShape*>( fixtureDef.shape );
  2344. // Check shape.
  2345. if ( !pShape )
  2346. {
  2347. Con::errorf("SceneObject::copyCircleCollisionShapeTo() - Invalid shape.");
  2348. return INVALID_COLLISION_SHAPE_INDEX;
  2349. }
  2350. // Fetch shape details.
  2351. const F32 radius = pShape->m_radius;
  2352. const b2Vec2 localPosition = pShape->m_p;
  2353. // Copy shape.
  2354. const S32 shapeIndex = pSceneObject->createCircleCollisionShape( radius, localPosition );
  2355. // Was shape created.
  2356. if ( shapeIndex != -1 )
  2357. {
  2358. // Yes, so configure shape.
  2359. pSceneObject->setCollisionShapeDefinition( shapeIndex, fixtureDef );
  2360. }
  2361. return shapeIndex;
  2362. }
  2363. //-----------------------------------------------------------------------------
  2364. S32 SceneObject::copyPolygonCollisionShapeTo( SceneObject* pSceneObject, const b2FixtureDef& fixtureDef ) const
  2365. {
  2366. // Fetch shape.
  2367. const b2PolygonShape* pShape = dynamic_cast<const b2PolygonShape*>( fixtureDef.shape );
  2368. // Check shape.
  2369. if ( !pShape )
  2370. {
  2371. Con::errorf("SceneObject::copyPolygonCollisionShapeTo() - Invalid shape.");
  2372. return INVALID_COLLISION_SHAPE_INDEX;
  2373. }
  2374. // Fetch point count.
  2375. const U32 pointCount = pShape->GetVertexCount();
  2376. // Fetch local points.
  2377. const b2Vec2* plocalPoints = pShape->m_vertices;
  2378. // Copy shape.
  2379. const S32 shapeIndex = pSceneObject->createPolygonCollisionShape( pointCount, plocalPoints );
  2380. // Was shape created.
  2381. if ( shapeIndex != -1 )
  2382. {
  2383. // Yes, so configure shape.
  2384. pSceneObject->setCollisionShapeDefinition( shapeIndex, fixtureDef );
  2385. }
  2386. return shapeIndex;
  2387. }
  2388. //-----------------------------------------------------------------------------
  2389. S32 SceneObject::copyChainCollisionShapeTo( SceneObject* pSceneObject, const b2FixtureDef& fixtureDef ) const
  2390. {
  2391. // Fetch shape.
  2392. const b2ChainShape* pShape = dynamic_cast<const b2ChainShape*>( fixtureDef.shape );
  2393. // Check shape.
  2394. if ( !pShape )
  2395. {
  2396. Con::errorf("SceneObject::copyChainCollisionShapeTo() - Invalid shape.");
  2397. return INVALID_COLLISION_SHAPE_INDEX;
  2398. }
  2399. // Fetch point count.
  2400. const U32 pointCount = pShape->m_count;
  2401. // Fetch local points.
  2402. b2Vec2* localPoints = pShape->m_vertices;
  2403. // Fetch adjacent positions.
  2404. const bool hasAdjacentLocalPositionStart = pShape->m_hasPrevVertex;
  2405. const bool hasAdjacentLocalPositionEnd = pShape->m_hasNextVertex;
  2406. const b2Vec2 adjacentLocalPositionStart = pShape->m_prevVertex;
  2407. const b2Vec2 adjacentLocalPositionEnd = pShape->m_nextVertex;
  2408. // Create shape.
  2409. const S32 shapeIndex = pSceneObject->createChainCollisionShape(
  2410. pointCount, localPoints,
  2411. hasAdjacentLocalPositionStart, hasAdjacentLocalPositionEnd,
  2412. adjacentLocalPositionStart, adjacentLocalPositionEnd);
  2413. // Was shape created.
  2414. if ( shapeIndex != -1 )
  2415. {
  2416. // Yes, so configure shape.
  2417. pSceneObject->setCollisionShapeDefinition( shapeIndex, fixtureDef );
  2418. }
  2419. return shapeIndex;
  2420. }
  2421. //-----------------------------------------------------------------------------
  2422. S32 SceneObject::copyEdgeCollisionShapeTo( SceneObject* pSceneObject, const b2FixtureDef& fixtureDef ) const
  2423. {
  2424. // Fetch shape.
  2425. const b2EdgeShape* pShape = dynamic_cast<const b2EdgeShape*>( fixtureDef.shape );
  2426. // Check shape.
  2427. if ( !pShape )
  2428. {
  2429. Con::errorf("SceneObject::copyEdgeCollisionShapeTo() - Invalid shape.");
  2430. return INVALID_COLLISION_SHAPE_INDEX;
  2431. }
  2432. // Fetch positions.
  2433. const b2Vec2 localPosition1 = pShape->m_vertex1;
  2434. const b2Vec2 localPosition2 = pShape->m_vertex2;
  2435. const bool hasAdjacentLocalPosition1 = pShape->m_hasVertex0;
  2436. const bool hasAdjacentLocalPosition2 = pShape->m_hasVertex3;
  2437. const b2Vec2 adjacentLocalPosition1 = pShape->m_vertex0;
  2438. const b2Vec2 adjacentLocalPosition2 = pShape->m_vertex3;
  2439. // Create shape.
  2440. const S32 shapeIndex = pSceneObject->createEdgeCollisionShape(
  2441. localPosition1, localPosition2,
  2442. hasAdjacentLocalPosition1, hasAdjacentLocalPosition2,
  2443. adjacentLocalPosition1, adjacentLocalPosition2 );
  2444. // Was shape created.
  2445. if ( shapeIndex != -1 )
  2446. {
  2447. // Yes, so configure shape.
  2448. pSceneObject->setCollisionShapeDefinition( shapeIndex, fixtureDef );
  2449. }
  2450. return shapeIndex;
  2451. }
  2452. //-----------------------------------------------------------------------------
  2453. void SceneObject::safeDelete( void )
  2454. {
  2455. // Are we in a scene?
  2456. if ( getScene() )
  2457. {
  2458. // Yes, so add a delete-request to the scene.
  2459. getScene()->addDeleteRequest( this );
  2460. }
  2461. else
  2462. {
  2463. // No, so use standard SimObject helper.
  2464. deleteObject();
  2465. }
  2466. }
  2467. //-----------------------------------------------------------------------------
  2468. void SceneObject::addDestroyNotification( SceneObject* pSceneObject )
  2469. {
  2470. // Search list to see if we're already in it (finish if we are).
  2471. for ( U32 n = 0; n < (U32)mDestroyNotifyList.size(); n++ )
  2472. {
  2473. // In the list already?
  2474. if ( mDestroyNotifyList[n].mpSceneObject == pSceneObject )
  2475. {
  2476. // Yes, so just bump-up the reference count.
  2477. mDestroyNotifyList[n].mRefCount++;
  2478. // Finish here.
  2479. return;
  2480. }
  2481. }
  2482. // Add Destroy Notification.
  2483. tDestroyNotification notification;
  2484. notification.mpSceneObject = pSceneObject;
  2485. notification.mRefCount = 1;
  2486. // Add Notification.
  2487. mDestroyNotifyList.push_back( notification );
  2488. }
  2489. //-----------------------------------------------------------------------------
  2490. void SceneObject::removeDestroyNotification( SceneObject* pSceneObject )
  2491. {
  2492. // Find object in notification list.
  2493. for ( U32 n = 0; n < (U32)mDestroyNotifyList.size(); n++ )
  2494. {
  2495. // Our object?
  2496. if ( mDestroyNotifyList[n].mpSceneObject == pSceneObject )
  2497. {
  2498. // Yes, so reduce reference count.
  2499. mDestroyNotifyList[n].mRefCount--;
  2500. // Finish Here.
  2501. return;
  2502. }
  2503. }
  2504. }
  2505. //-----------------------------------------------------------------------------
  2506. void SceneObject::processDestroyNotifications( void )
  2507. {
  2508. // Find object in notification list.
  2509. while( mDestroyNotifyList.size() )
  2510. {
  2511. // Fetch Notification Item.
  2512. tDestroyNotification notification = mDestroyNotifyList.first();
  2513. // Only action if we've got a reference active.
  2514. if ( notification.mRefCount > 0 )
  2515. // Call Destroy Notification.
  2516. notification.mpSceneObject->onDestroyNotify( this );
  2517. // Remove it.
  2518. mDestroyNotifyList.pop_front();
  2519. }
  2520. // Sanity!
  2521. AssertFatal( mDestroyNotifyList.size() == 0, "SceneObject::processDestroyNotifications() - Notifications still pending!" );
  2522. }
  2523. //-----------------------------------------------------------------------------
  2524. void SceneObject::notifyComponentsAddToScene( void )
  2525. {
  2526. // Debug Profiling.
  2527. PROFILE_SCOPE(SceneObject_NotifyComponentsAddToScene);
  2528. // Notify components.
  2529. VectorPtr<SimComponent*>& componentList = lockComponentList();
  2530. for( SimComponentIterator itr = componentList.begin(); itr != componentList.end(); ++itr )
  2531. {
  2532. SimComponent *pComponent = *itr;
  2533. if( pComponent != NULL )
  2534. pComponent->onAddToScene();
  2535. }
  2536. unlockComponentList();
  2537. }
  2538. //-----------------------------------------------------------------------------
  2539. void SceneObject::notifyComponentsRemoveFromScene( void )
  2540. {
  2541. // Debug Profiling.
  2542. PROFILE_SCOPE(SceneObject_NotifyComponentsRemoveFromScene);
  2543. // Notify components.
  2544. VectorPtr<SimComponent*>& componentList = lockComponentList();
  2545. for( SimComponentIterator itr = componentList.begin(); itr != componentList.end(); ++itr )
  2546. {
  2547. SimComponent *pComponent = *itr;
  2548. if( pComponent != NULL )
  2549. pComponent->onRemoveFromScene();
  2550. }
  2551. unlockComponentList();
  2552. }
  2553. //-----------------------------------------------------------------------------
  2554. void SceneObject::notifyComponentsUpdate( void )
  2555. {
  2556. // Debug Profiling.
  2557. PROFILE_SCOPE(SceneObject_NotifyComponentsUpdate);
  2558. // Notify components.
  2559. VectorPtr<SimComponent*>& componentList = lockComponentList();
  2560. for( SimComponentIterator itr = componentList.begin(); itr != componentList.end(); ++itr )
  2561. {
  2562. SimComponent *pComponent = *itr;
  2563. if( pComponent != NULL )
  2564. pComponent->onUpdate();
  2565. }
  2566. unlockComponentList();
  2567. }
  2568. //-----------------------------------------------------------------------------
  2569. BehaviorInstance* SceneObject::behavior(const char *name)
  2570. {
  2571. // Debug Profiling.
  2572. PROFILE_SCOPE(SceneObject_BehaviorName);
  2573. StringTableEntry stName = StringTable->insert(name);
  2574. VectorPtr<SimComponent *>&componentList = lockComponentList();
  2575. for( SimComponentIterator nItr = componentList.begin(); nItr != componentList.end(); nItr++ )
  2576. {
  2577. BehaviorInstance* pComponent = dynamic_cast<BehaviorInstance*>(*nItr);
  2578. if( pComponent && StringTable->insert(pComponent->getTemplateName()) == stName )
  2579. {
  2580. unlockComponentList();
  2581. return pComponent;
  2582. }
  2583. }
  2584. unlockComponentList();
  2585. return NULL;
  2586. }
  2587. //-----------------------------------------------------------------------------
  2588. U32 SceneObject::getGlobalSceneObjectCount( void )
  2589. {
  2590. return sGlobalSceneObjectCount;
  2591. }
  2592. //-----------------------------------------------------------------------------
  2593. void SceneObject::onTamlCustomWrite( TamlCustomProperties& customProperties )
  2594. {
  2595. // Debug Profiling.
  2596. PROFILE_SCOPE(SceneObject_OnTamlCustomWrite);
  2597. // Call parent.
  2598. Parent::onTamlCustomWrite( customProperties );
  2599. // Fetch collision shape count.
  2600. const U32 collisionShapeCount = getCollisionShapeCount();
  2601. // Finish if no collision shapes.
  2602. if ( collisionShapeCount == 0 )
  2603. return;
  2604. // Add collision shape property.
  2605. TamlCustomProperty* pCollisionShapeProperty = customProperties.addProperty( shapeCustomPropertyName );
  2606. // Iterate collision shapes.
  2607. for ( U32 shapeIndex = 0; shapeIndex < collisionShapeCount; ++shapeIndex )
  2608. {
  2609. // Fetch collision shape definition.
  2610. b2FixtureDef fixtureDef = getCollisionShapeDefinition( shapeIndex );
  2611. // Add collision shape alias.
  2612. // NOTE: The name of the alias will get updated shortly.
  2613. TamlPropertyAlias* pCollisionShapeAlias = pCollisionShapeProperty->addAlias( StringTable->EmptyString );
  2614. // Add common collision shape fields.
  2615. if ( mNotEqual( getDefaultDensity(), fixtureDef.density ) )
  2616. pCollisionShapeAlias->addField( shapeDensityName, fixtureDef.density );
  2617. if ( mNotEqual( getDefaultFriction(), fixtureDef.friction ) )
  2618. pCollisionShapeAlias->addField( shapeFrictionName, fixtureDef.friction );
  2619. if ( mNotEqual( getDefaultRestitution(), fixtureDef.restitution ) )
  2620. pCollisionShapeAlias->addField( shapeRestitutionName, fixtureDef.restitution );
  2621. if ( fixtureDef.isSensor == true )
  2622. pCollisionShapeAlias->addField( shapeSensorName, fixtureDef.isSensor );
  2623. // Populate collision shape appropriately.
  2624. switch( fixtureDef.shape->GetType() )
  2625. {
  2626. case b2Shape::e_circle:
  2627. {
  2628. // Set alias name.
  2629. pCollisionShapeAlias->mAliasName = StringTable->insert( circleTypeName );
  2630. // Fetch shape.
  2631. const b2CircleShape* pShape = dynamic_cast<const b2CircleShape*>( fixtureDef.shape );
  2632. // Sanity!
  2633. AssertFatal( pShape != NULL, "SceneObject::onTamlCustomWrite() - Invalid circle shape type returned." );
  2634. // Add radius property.
  2635. pCollisionShapeAlias->addField( circleRadiusName, pShape->m_radius );
  2636. // Add offset property (if not zero).
  2637. if ( !Vector2(pShape->m_p).isZero() )
  2638. pCollisionShapeAlias->addField( circleOffsetName, pShape->m_p );
  2639. }
  2640. break;
  2641. case b2Shape::e_polygon:
  2642. {
  2643. // Set alias name.
  2644. pCollisionShapeAlias->mAliasName = StringTable->insert( polygonTypeName );
  2645. // Fetch shape.
  2646. const b2PolygonShape* pShape = dynamic_cast<const b2PolygonShape*>( fixtureDef.shape );
  2647. // Sanity!
  2648. AssertFatal( pShape != NULL, "SceneObject::onTamlCustomWrite() - Invalid polygon shape type returned." );
  2649. // Fetch point count.
  2650. const U32 pointCount = pShape->GetVertexCount();
  2651. // Add shape properties.
  2652. for ( U32 pointIndex = 0; pointIndex < pointCount; ++pointIndex )
  2653. {
  2654. // Format point index name.
  2655. char pointIndexBuffer[16];
  2656. dSprintf( pointIndexBuffer, sizeof(pointIndexBuffer), "%s%d", polygonPointName, pointIndex );
  2657. // Add point property.
  2658. pCollisionShapeAlias->addField( pointIndexBuffer, pShape->GetVertex( pointIndex ) );
  2659. }
  2660. }
  2661. break;
  2662. case b2Shape::e_chain:
  2663. {
  2664. // Set alias name.
  2665. pCollisionShapeAlias->mAliasName = StringTable->insert( chainTypeName );
  2666. // Fetch shape.
  2667. const b2ChainShape* pShape = dynamic_cast<const b2ChainShape*>( fixtureDef.shape );
  2668. // Sanity!
  2669. AssertFatal( pShape != NULL, "SceneObject::onTamlCustomWrite() - Invalid chain shape type returned." );
  2670. // Fetch point count.
  2671. const U32 pointCount = pShape->m_count;
  2672. // Add shape properties.
  2673. for ( U32 pointIndex = 0; pointIndex < pointCount; ++pointIndex )
  2674. {
  2675. // Format point index name.
  2676. char pointIndexBuffer[16];
  2677. dSprintf( pointIndexBuffer, sizeof(pointIndexBuffer), "%s%d", chainPointName, pointIndex );
  2678. // Add point property.
  2679. pCollisionShapeAlias->addField( pointIndexBuffer, pShape->m_vertices[pointIndex] );
  2680. }
  2681. // Add adjacent start point (if specified).
  2682. if ( pShape->m_hasPrevVertex )
  2683. pCollisionShapeAlias->addField( chainAdjacentStartName, pShape->m_prevVertex );
  2684. // Add adjacent end point (if specified).
  2685. if ( pShape->m_hasNextVertex )
  2686. pCollisionShapeAlias->addField( chainAdjacentEndName, pShape->m_nextVertex );
  2687. }
  2688. break;
  2689. case b2Shape::e_edge:
  2690. {
  2691. // Set alias name.
  2692. pCollisionShapeAlias->mAliasName = StringTable->insert( edgeTypeName );
  2693. // Fetch shape.
  2694. const b2EdgeShape* pShape = dynamic_cast<const b2EdgeShape*>( fixtureDef.shape );
  2695. // Sanity!
  2696. AssertFatal( pShape != NULL, "SceneObject::onTamlCustomWrite() - Invalid edge shape type returned." );
  2697. // Add start/end points.
  2698. pCollisionShapeAlias->addField( edgeStartName, pShape->m_vertex1 );
  2699. pCollisionShapeAlias->addField( edgeEndName, pShape->m_vertex2 );
  2700. // Add adjacent start point (if specified).
  2701. if ( pShape->m_hasVertex0 )
  2702. pCollisionShapeAlias->addField( edgeAdjacentStartName, pShape->m_vertex0 );
  2703. // Add adjacent end point (if specified).
  2704. if ( pShape->m_hasVertex3 )
  2705. pCollisionShapeAlias->addField( edgeAdjacentEndName, pShape->m_vertex3 );
  2706. }
  2707. break;
  2708. default:
  2709. // Sanity!
  2710. AssertFatal( false, "SceneObject::onTamlCustomWrite() - Unknown shape type detected." );
  2711. }
  2712. }
  2713. }
  2714. //-----------------------------------------------------------------------------
  2715. void SceneObject::onTamlCustomRead( const TamlCustomProperties& customProperties )
  2716. {
  2717. // Debug Profiling.
  2718. PROFILE_SCOPE(SceneObject_OnTamlCustomRead);
  2719. // Call parent.
  2720. Parent::onTamlCustomRead( customProperties );
  2721. // Find collision shape custom property.
  2722. const TamlCustomProperty* pCollisionShapeProperty = customProperties.findProperty( shapeCustomPropertyName );
  2723. // Finish if we don't have collision shapes.
  2724. if ( pCollisionShapeProperty == NULL )
  2725. return;
  2726. // Iterate collision shapes.
  2727. for( TamlCustomProperty::const_iterator propertyAliasItr = pCollisionShapeProperty->begin(); propertyAliasItr != pCollisionShapeProperty->end(); ++propertyAliasItr )
  2728. {
  2729. // Fetch property alias.
  2730. TamlPropertyAlias* pPropertyAlias = *propertyAliasItr;
  2731. // Fetch alias name.
  2732. StringTableEntry aliasName = pPropertyAlias->mAliasName;
  2733. // Ready common fields.
  2734. F32 shapeDensity = getDefaultDensity();
  2735. F32 shapeFriction = getDefaultFriction();
  2736. F32 shapeRestitution = getDefaultRestitution();
  2737. bool shapeSensor = false;
  2738. S32 shapeIndex;
  2739. // Is this a circle shape?
  2740. if ( aliasName == circleTypeName )
  2741. {
  2742. // Yes, so ready fields.
  2743. F32 radius = 0.0f;
  2744. b2Vec2 offset( 0.0f, 0.0f );
  2745. // Iterate property fields.
  2746. for ( TamlPropertyAlias::const_iterator propertyFieldItr = pPropertyAlias->begin(); propertyFieldItr != pPropertyAlias->end(); ++propertyFieldItr )
  2747. {
  2748. // Fetch property field.
  2749. TamlPropertyField* pPropertyField = *propertyFieldItr;
  2750. // Fetch property field name.
  2751. StringTableEntry fieldName = pPropertyField->getFieldName();
  2752. // Check common fields.
  2753. if ( fieldName == shapeDensityName )
  2754. {
  2755. pPropertyField->getFieldValue( shapeDensity );
  2756. }
  2757. else if ( fieldName == shapeFrictionName )
  2758. {
  2759. pPropertyField->getFieldValue( shapeFriction );
  2760. }
  2761. else if ( fieldName == shapeRestitutionName )
  2762. {
  2763. pPropertyField->getFieldValue( shapeRestitution );
  2764. }
  2765. else if ( fieldName == shapeSensorName )
  2766. {
  2767. pPropertyField->getFieldValue( shapeSensor );
  2768. }
  2769. // Check circle fields.
  2770. else if ( fieldName == circleRadiusName )
  2771. {
  2772. pPropertyField->getFieldValue( radius );
  2773. }
  2774. else if ( fieldName == circleOffsetName )
  2775. {
  2776. pPropertyField->getFieldValue( offset );
  2777. }
  2778. }
  2779. // Is radius valid?
  2780. if ( radius <= 0.0f )
  2781. {
  2782. // No, so warn.
  2783. Con::warnf( "SceneObject::onTamlCustomRead() - Invalid radius on circle collision shape '%g'. Using default.", radius );
  2784. // Set default.
  2785. radius = 1.0f;
  2786. }
  2787. // Create shape.
  2788. shapeIndex = createCircleCollisionShape( radius, offset );
  2789. }
  2790. // Is this a polygon shape?
  2791. else if ( aliasName == polygonTypeName )
  2792. {
  2793. // Yes, so ready fields.
  2794. b2Vec2 points[b2_maxPolygonVertices];
  2795. U32 pointCount = 0;
  2796. // Iterate property fields.
  2797. for ( TamlPropertyAlias::const_iterator propertyFieldItr = pPropertyAlias->begin(); propertyFieldItr != pPropertyAlias->end(); ++propertyFieldItr )
  2798. {
  2799. // Fetch property field.
  2800. TamlPropertyField* pPropertyField = *propertyFieldItr;
  2801. // Fetch property field name.
  2802. StringTableEntry fieldName = pPropertyField->getFieldName();
  2803. // Check common fields.
  2804. if ( fieldName == shapeDensityName )
  2805. {
  2806. pPropertyField->getFieldValue( shapeDensity );
  2807. }
  2808. else if ( fieldName == shapeFrictionName )
  2809. {
  2810. pPropertyField->getFieldValue( shapeFriction );
  2811. }
  2812. else if ( fieldName == shapeRestitutionName )
  2813. {
  2814. pPropertyField->getFieldValue( shapeRestitution );
  2815. }
  2816. else if ( fieldName == shapeSensorName )
  2817. {
  2818. pPropertyField->getFieldValue( shapeSensor );
  2819. }
  2820. // Check polygon fields.
  2821. else if ( pPropertyField->fieldNameBeginsWith( polygonPointName ) )
  2822. {
  2823. // Is the point count at maximum?
  2824. if ( pointCount == b2_maxPolygonVertices )
  2825. {
  2826. // Yes, so warn.
  2827. Con::warnf( "SceneObject::onTamlCustomRead() - Polygon point count exceed the maximum points '%d'.", b2_maxPolygonVertices );
  2828. continue;
  2829. }
  2830. b2Vec2 point;
  2831. pPropertyField->getFieldValue( point );
  2832. points[pointCount++] = point;
  2833. }
  2834. }
  2835. // Is point count valid?
  2836. if ( pointCount == 0 )
  2837. {
  2838. // No, so warn.
  2839. Con::warnf( "SceneObject::onTamlCustomRead() - No points on polygon collision shape." );
  2840. continue;
  2841. }
  2842. // Create shape.
  2843. shapeIndex = createPolygonCollisionShape( pointCount, points );
  2844. }
  2845. // Is this a chain shape?
  2846. else if ( aliasName == chainTypeName )
  2847. {
  2848. // Yes, so ready fields.
  2849. Vector<b2Vec2> points;
  2850. bool hasAdjacentStartPoint;
  2851. bool hasAdjacentEndPoint;
  2852. b2Vec2 adjacentStartPoint;
  2853. b2Vec2 adjacentEndPoint;
  2854. // Iterate property fields.
  2855. for ( TamlPropertyAlias::const_iterator propertyFieldItr = pPropertyAlias->begin(); propertyFieldItr != pPropertyAlias->end(); ++propertyFieldItr )
  2856. {
  2857. // Fetch property field.
  2858. TamlPropertyField* pPropertyField = *propertyFieldItr;
  2859. // Fetch property field name.
  2860. StringTableEntry fieldName = pPropertyField->getFieldName();
  2861. // Check common fields.
  2862. if ( fieldName == shapeDensityName )
  2863. {
  2864. pPropertyField->getFieldValue( shapeDensity );
  2865. }
  2866. else if ( fieldName == shapeFrictionName )
  2867. {
  2868. pPropertyField->getFieldValue( shapeFriction );
  2869. }
  2870. else if ( fieldName == shapeRestitutionName )
  2871. {
  2872. pPropertyField->getFieldValue( shapeRestitution );
  2873. }
  2874. else if ( fieldName == shapeSensorName )
  2875. {
  2876. pPropertyField->getFieldValue( shapeSensor );
  2877. }
  2878. // Check chain fields.
  2879. else if ( pPropertyField->fieldNameBeginsWith( chainPointName ) )
  2880. {
  2881. b2Vec2 point;
  2882. pPropertyField->getFieldValue( point );
  2883. points.push_back( point );
  2884. }
  2885. else if ( fieldName == chainAdjacentStartName )
  2886. {
  2887. pPropertyField->getFieldValue( adjacentStartPoint );
  2888. hasAdjacentStartPoint = true;
  2889. }
  2890. else if ( fieldName == chainAdjacentEndName )
  2891. {
  2892. pPropertyField->getFieldValue( adjacentEndPoint );
  2893. hasAdjacentEndPoint = true;
  2894. }
  2895. }
  2896. // Is point count valid?
  2897. if ( points.size() == 0 )
  2898. {
  2899. // No, so warn.
  2900. Con::warnf( "SceneObject::onTamlCustomRead() - No points on chain collision shape." );
  2901. continue;
  2902. }
  2903. // Create shape.
  2904. shapeIndex = createChainCollisionShape( points.size(), points.address(), hasAdjacentStartPoint, hasAdjacentEndPoint, adjacentStartPoint, adjacentEndPoint );
  2905. }
  2906. // Is this an edge shape?
  2907. else if ( aliasName == edgeTypeName )
  2908. {
  2909. // Yes, so ready fields.
  2910. b2Vec2 point0;
  2911. b2Vec2 point1;
  2912. bool hasAdjacentStartPoint;
  2913. bool hasAdjacentEndPoint;
  2914. b2Vec2 adjacentStartPoint;
  2915. b2Vec2 adjacentEndPoint;
  2916. // Iterate property fields.
  2917. for ( TamlPropertyAlias::const_iterator propertyFieldItr = pPropertyAlias->begin(); propertyFieldItr != pPropertyAlias->end(); ++propertyFieldItr )
  2918. {
  2919. // Fetch property field.
  2920. TamlPropertyField* pPropertyField = *propertyFieldItr;
  2921. // Fetch property field name.
  2922. StringTableEntry fieldName = pPropertyField->getFieldName();
  2923. // Check common fields.
  2924. if ( fieldName == shapeDensityName )
  2925. {
  2926. pPropertyField->getFieldValue( shapeDensity );
  2927. }
  2928. else if ( fieldName == shapeFrictionName )
  2929. {
  2930. pPropertyField->getFieldValue( shapeFriction );
  2931. }
  2932. else if ( fieldName == shapeRestitutionName )
  2933. {
  2934. pPropertyField->getFieldValue( shapeRestitution );
  2935. }
  2936. else if ( fieldName == shapeSensorName )
  2937. {
  2938. pPropertyField->getFieldValue( shapeSensor );
  2939. }
  2940. // Check edge fields.
  2941. else if ( fieldName == edgeStartName )
  2942. {
  2943. pPropertyField->getFieldValue( point0 );
  2944. }
  2945. else if ( fieldName == edgeEndName )
  2946. {
  2947. pPropertyField->getFieldValue( point1 );
  2948. }
  2949. else if ( fieldName == edgeAdjacentStartName )
  2950. {
  2951. pPropertyField->getFieldValue( adjacentStartPoint );
  2952. hasAdjacentStartPoint = true;
  2953. }
  2954. else if ( fieldName == edgeAdjacentEndName )
  2955. {
  2956. pPropertyField->getFieldValue( adjacentEndPoint );
  2957. hasAdjacentEndPoint = true;
  2958. }
  2959. }
  2960. // Create shape.
  2961. shapeIndex = createEdgeCollisionShape( point0, point1, hasAdjacentStartPoint, hasAdjacentEndPoint, adjacentStartPoint, adjacentEndPoint );
  2962. }
  2963. // Unknown shape type!
  2964. else
  2965. {
  2966. // Warn.
  2967. Con::warnf( "Unknown shape type of '%s' encountered.", aliasName );
  2968. // Sanity!
  2969. AssertFatal( false, "SceneObject::onTamlCustomRead() - Unknown shape type detected." );
  2970. continue;
  2971. }
  2972. // Set common properties.
  2973. setCollisionShapeDensity( shapeIndex, shapeDensity );
  2974. setCollisionShapeFriction( shapeIndex, shapeFriction );
  2975. setCollisionShapeRestitution( shapeIndex, shapeRestitution );
  2976. setCollisionShapeIsSensor( shapeIndex, shapeSensor );
  2977. }
  2978. }
  2979. //-----------------------------------------------------------------------------
  2980. bool SceneObject::writeField(StringTableEntry fieldname, const char* value)
  2981. {
  2982. if (!Parent::writeField(fieldname, value))
  2983. return false;
  2984. // Never save the scene field.
  2985. if (dStricmp(fieldname, "scene") == 0)
  2986. return false;
  2987. return true;
  2988. }
  2989. //------------------------------------------------------------------------------
  2990. S32 QSORT_CALLBACK SceneObject::sceneObjectLayerDepthSort(const void* a, const void* b)
  2991. {
  2992. // Fetch scene objects.
  2993. SceneObject* pSceneObjectA = *((SceneObject**)a);
  2994. SceneObject* pSceneObjectB = *((SceneObject**)b);
  2995. // Fetch layers.
  2996. const U32 layerA = pSceneObjectA->getSceneLayer();
  2997. const U32 layerB = pSceneObjectB->getSceneLayer();
  2998. if ( layerA < layerB )
  2999. return -1;
  3000. if ( layerA > layerB )
  3001. return 1;
  3002. // Fetch layer depths.
  3003. const F32 depthA = pSceneObjectA->getSceneLayerDepth();
  3004. const F32 depthB = pSceneObjectB->getSceneLayerDepth();
  3005. return depthA < depthB ? 1 : depthA > depthB ? -1 : pSceneObjectA->getSerialId() - pSceneObjectB->getSerialId();
  3006. }
  3007. //-----------------------------------------------------------------------------
  3008. static EnumTable::Enums bodyTypeLookup[] =
  3009. {
  3010. { b2_staticBody, "static" },
  3011. { b2_kinematicBody, "kinematic" },
  3012. { b2_dynamicBody, "dynamic" },
  3013. };
  3014. EnumTable bodyTypeTable(sizeof(bodyTypeLookup) / sizeof(EnumTable::Enums), &bodyTypeLookup[0]);
  3015. //-----------------------------------------------------------------------------
  3016. static EnumTable::Enums collisionShapeTypeLookup[] =
  3017. {
  3018. { b2Shape::e_circle, "circle" },
  3019. { b2Shape::e_edge, "edge" },
  3020. { b2Shape::e_polygon, "polygon" },
  3021. { b2Shape::e_chain, "chain" },
  3022. };
  3023. EnumTable collisionShapeTypeTable(sizeof(collisionShapeTypeLookup) / sizeof(EnumTable::Enums), &collisionShapeTypeLookup[0]);
  3024. //-----------------------------------------------------------------------------
  3025. static EnumTable::Enums srcBlendFactorLookup[] =
  3026. {
  3027. { GL_ZERO, "ZERO" },
  3028. { GL_ONE, "ONE" },
  3029. { GL_DST_COLOR, "DST_COLOR" },
  3030. { GL_ONE_MINUS_DST_COLOR, "ONE_MINUS_DST_COLOR" },
  3031. { GL_SRC_ALPHA, "SRC_ALPHA" },
  3032. { GL_ONE_MINUS_SRC_ALPHA, "ONE_MINUS_SRC_ALPHA" },
  3033. { GL_DST_ALPHA, "DST_ALPHA" },
  3034. { GL_ONE_MINUS_DST_ALPHA, "ONE_MINUS_DST_ALPHA" },
  3035. { GL_SRC_ALPHA_SATURATE, "SRC_ALPHA_SATURATE" },
  3036. };
  3037. EnumTable srcBlendFactorTable(sizeof(srcBlendFactorLookup) / sizeof(EnumTable::Enums), &srcBlendFactorLookup[0]);
  3038. //-----------------------------------------------------------------------------
  3039. static EnumTable::Enums dstBlendFactorLookup[] =
  3040. {
  3041. { GL_ZERO, "ZERO" },
  3042. { GL_ONE, "ONE" },
  3043. { GL_SRC_COLOR, "SRC_COLOR" },
  3044. { GL_ONE_MINUS_SRC_COLOR, "ONE_MINUS_SRC_COLOR" },
  3045. { GL_SRC_ALPHA, "SRC_ALPHA" },
  3046. { GL_ONE_MINUS_SRC_ALPHA, "ONE_MINUS_SRC_ALPHA" },
  3047. { GL_DST_ALPHA, "DST_ALPHA" },
  3048. { GL_ONE_MINUS_DST_ALPHA, "ONE_MINUS_DST_ALPHA" },
  3049. };
  3050. EnumTable dstBlendFactorTable(sizeof(dstBlendFactorLookup) / sizeof(EnumTable::Enums), &dstBlendFactorLookup[0]);
  3051. //-----------------------------------------------------------------------------
  3052. b2BodyType SceneObject::getBodyTypeEnum(const char* label)
  3053. {
  3054. // Search for Mnemonic.
  3055. for (U32 i = 0; i < (sizeof(bodyTypeLookup) / sizeof(EnumTable::Enums)); i++)
  3056. {
  3057. if( dStricmp(bodyTypeLookup[i].label, label) == 0)
  3058. return (b2BodyType)bodyTypeLookup[i].index;
  3059. }
  3060. // Warn.
  3061. Con::warnf("SceneObject::getBodyTypeEnum() - Invalid body type of '%s'", label );
  3062. return (b2BodyType)-1;
  3063. }
  3064. //-----------------------------------------------------------------------------
  3065. const char* SceneObject::getBodyTypeDescription(const b2BodyType bodyType)
  3066. {
  3067. // Search for Mnemonic.
  3068. for (U32 i = 0; i < (sizeof(bodyTypeLookup) / sizeof(EnumTable::Enums)); i++)
  3069. {
  3070. if( bodyTypeLookup[i].index == bodyType )
  3071. return bodyTypeLookup[i].label;
  3072. }
  3073. // Warn.
  3074. Con::warnf( "SceneObject::getBodyTypeDescription() - Invalid body type." );
  3075. return StringTable->EmptyString;
  3076. }
  3077. //-----------------------------------------------------------------------------
  3078. b2Shape::Type SceneObject::getCollisionShapeTypeEnum(const char* label)
  3079. {
  3080. // Search for Mnemonic.
  3081. for (U32 i = 0; i < (sizeof(collisionShapeTypeLookup) / sizeof(EnumTable::Enums)); i++)
  3082. {
  3083. if( dStricmp(collisionShapeTypeLookup[i].label, label) == 0)
  3084. return (b2Shape::Type)collisionShapeTypeLookup[i].index;
  3085. }
  3086. // Warn!
  3087. Con::warnf("SceneObject::getCollisionShapeTypeEnum() - Invalid collision shape type of '%s'", label );
  3088. return b2Shape::e_typeCount;
  3089. }
  3090. //-----------------------------------------------------------------------------
  3091. const char* SceneObject::getCollisionShapeTypeDescription(const b2Shape::Type collisionShapeType)
  3092. {
  3093. // Search for Mnemonic.
  3094. for (U32 i = 0; i < (sizeof(collisionShapeTypeLookup) / sizeof(EnumTable::Enums)); i++)
  3095. {
  3096. if( collisionShapeTypeLookup[i].index == collisionShapeType )
  3097. return collisionShapeTypeLookup[i].label;
  3098. }
  3099. // Warn.
  3100. Con::warnf( "SceneObject::getCollisionShapeTypeDescription() - Invalid collision shape type." );
  3101. return StringTable->EmptyString;
  3102. }
  3103. //-----------------------------------------------------------------------------
  3104. S32 SceneObject::getSrcBlendFactorEnum(const char* label)
  3105. {
  3106. // Search for Mnemonic.
  3107. for (U32 i = 0; i < (sizeof(srcBlendFactorLookup) / sizeof(EnumTable::Enums)); i++)
  3108. {
  3109. if( dStricmp(srcBlendFactorLookup[i].label, label) == 0)
  3110. return(srcBlendFactorLookup[i].index);
  3111. }
  3112. // Warn.
  3113. Con::warnf("SceneObject::getSrcBlendFactorEnum() - Invalid source blend factor of '%s'", label );
  3114. return GL_INVALID_BLEND_FACTOR;
  3115. }
  3116. //-----------------------------------------------------------------------------
  3117. const char* SceneObject::getSrcBlendFactorDescription(const GLenum factor)
  3118. {
  3119. // Search for Mnemonic.
  3120. for (U32 i = 0; i < (sizeof(srcBlendFactorLookup) / sizeof(EnumTable::Enums)); i++)
  3121. {
  3122. if( srcBlendFactorLookup[i].index == (S32)factor )
  3123. return srcBlendFactorLookup[i].label;
  3124. }
  3125. // Warn.
  3126. Con::warnf( "SceneObject::getSrcBlendFactorDescription() - Invalid source blend factor." );
  3127. return StringTable->EmptyString;
  3128. }
  3129. //-----------------------------------------------------------------------------
  3130. S32 SceneObject::getDstBlendFactorEnum(const char* label)
  3131. {
  3132. // Search for Mnemonic.
  3133. for (U32 i = 0; i < (sizeof(dstBlendFactorLookup) / sizeof(EnumTable::Enums)); i++)
  3134. {
  3135. if( dStricmp(dstBlendFactorLookup[i].label, label) == 0)
  3136. return(dstBlendFactorLookup[i].index);
  3137. }
  3138. // Warn.
  3139. Con::warnf("SceneObject::getSrcBlendFactorEnum() - Invalid destination blend factor of '%s'", label );
  3140. return GL_INVALID_BLEND_FACTOR;
  3141. }
  3142. //-----------------------------------------------------------------------------
  3143. const char* SceneObject::getDstBlendFactorDescription(const GLenum factor)
  3144. {
  3145. // Search for Mnemonic.
  3146. for(U32 i = 0; i < (sizeof(dstBlendFactorLookup) / sizeof(EnumTable::Enums)); i++)
  3147. {
  3148. if( dstBlendFactorLookup[i].index == (S32)factor )
  3149. return dstBlendFactorLookup[i].label;
  3150. }
  3151. // Warn.
  3152. Con::warnf( "SceneObject::getDstBlendFactorDescription() - Invalid destination blend factor." );
  3153. return StringTable->EmptyString;
  3154. }