SceneObject.cc 165 KB

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