00001 #include "global.h"
00002 #include "MercuryObject.h"
00003 #include "MercuryDisplay.h"
00004 #include "MercuryLog.h"
00005
00006 MercuryObjectRegister OBJECTREGISTER;
00007
00008 MercuryObject::MercuryObject()
00009 :MercuryObjectBase()
00010 {
00011 m_bClone = false;
00012 m_initalized = false;
00013 }
00014
00015 MercuryObject::MercuryObject( const MString & name )
00016 :MercuryObjectBase()
00017 {
00018 m_bClone = false;
00019 m_initalized = false;
00020 SetName(m_name);
00021 }
00022
00023 void MercuryObject::Init()
00024 {
00025 MercuryObjectBase::Init();
00026
00027 m_bMarkedForDestroy = false;
00028 m_hidden = false;
00029 m_pMaterial = NULL;
00030
00031 m_modColor.m_alpha = m_modColor.m_shininess = 1.0f;
00032
00033 m_halignment = LEFT;
00034 m_valignment = TOP;
00035 m_drawable = false;
00036 m_width = m_height = 0;
00037
00038 m_state = LOADED;
00039
00040 m_initalized = true;
00041
00042 m_culled = false;
00043
00044 m_glState.Enable(MGLS_ALL);
00045 m_inheretedGLState.Enable(MGLS_ALL);
00046
00047 Tweening.AttachToObject( this );
00048 OBJECTREGISTER.Register( this, m_name );
00049 }
00050
00051 MercuryObject::~MercuryObject()
00052 {
00053 OBJECTREGISTER.Unregister( m_name );
00054
00055
00056
00057 if( !m_bClone )
00058 FOREACH_Object(m_objects, i)
00059 if ( i->bAutoDelete )
00060 SAFE_DELETE(i->pObject);
00061
00062 m_pMaterial = NULL;
00063 }
00064
00065 void MercuryObject::Update( const float dTime )
00066 {
00067 ASSERT_M(m_initalized,"Object '" + GetName() + "'not initialized.");
00068
00069 if ((m_state == UNLOADED) || (dTime == 0))
00070 return;
00071
00072 if ( m_bMarkedForDestroy )
00073 {
00074 ((MercuryObject*)m_parentObject)->RemoveObject( this );
00075 return;
00076 }
00077
00078 WorldStack.Push();
00079
00080 Tweening.Update( dTime );
00081
00082 if ( !IsHidden() )
00083 {
00084 Prerender();
00085 ComputeInheritedGLState();
00086 }
00087
00088
00089
00090
00091 MDequeIterator<ParentHoldPair> child = m_objects.begin();
00092 while (child != m_objects.end())
00093 (child++)->pObject->Update(dTime);
00094
00095 WorldStack.Pop();
00096 }
00097
00098 void MercuryObject::Prerender()
00099 {
00100
00101 switch(m_halignment)
00102 {
00103 case LEFT:
00104 SetAlignX(0);
00105 break;
00106 case CENTER:
00107 SetAlignX(-m_width / 2.0f);
00108 break;
00109 case RIGHT:
00110 SetAlignX(-(float)m_width);
00111 break;
00112 }
00113 switch(m_valignment)
00114 {
00115 case TOP:
00116 SetAlignY(0);
00117 break;
00118 case VCENTER:
00119 SetAlignY(-m_height / 2.0f);
00120 break;
00121 case BOTTOM:
00122 SetAlignY(-(float)m_height);
00123 break;
00124 }
00125
00126 CalculateMatrices();
00127 }
00128
00129 void MercuryObject::ComputeCull()
00130 {
00131
00132
00133 if (m_parentObject)
00134 {
00135 m_culled = ((MercuryObject*)m_parentObject)->IsCulled();
00136 if (m_culled)
00137 return;
00138 }
00139 m_culled = !DISPLAY->IsVisible( GetPosition(), GetScaledRadius(), m_finalMatrix );
00140 }
00141
00142 void MercuryObject::ComputeInheritedGLState()
00143 {
00144 m_inheretedGLState = m_glState;
00145 if (m_parentObject)
00146 m_inheretedGLState &= ((MercuryObject*)m_parentObject)->GetInheritedGLState();
00147 }
00148
00149 void MercuryObject::Render()
00150 {
00151 if ( IsHidden() || (m_state == UNLOADED))
00152 return;
00153
00154
00155
00156 ComputeCull();
00157
00158 if ( IsCulled() )
00159 return;
00160
00161 if ( GetInheritedGLState().GetState(MGLS_OPAQUE) )
00162 CustomRender();
00163 else
00164 DISPLAY->AddTranslucentObject(this);
00165
00166 MDequeIterator<ParentHoldPair> child = m_objects.begin();
00167 while (child != m_objects.end())
00168 (child++)->pObject->Render();
00169 }
00170
00171 void MercuryObject::CustomRender()
00172 {
00173 if (m_fVisRadius > 0)
00174 DISPLAY->FindLights(m_finalMatrix, m_fVisRadius);
00175
00176
00177
00178 if (m_drawable)
00179 {
00180 DISPLAY->SetStates( GetInheritedGLState() );
00181 DISPLAY->EnableShaders(m_pMaterial);
00182 DISPLAY->EnableTextures(m_pMaterial);
00183
00184 DISPLAY->SetMaterial(&m_finalMaterial);
00185
00186 Draw();
00187 }
00188 }
00189
00190 void MercuryObject::AddObject(MercuryObject* object, bool bParentDelete)
00191 {
00192 ASSERT(object->m_initalized);
00193
00194 ParentHoldPair c;
00195 c.bAutoDelete = bParentDelete;
00196 c.pObject = object;
00197
00198 m_objects.push_back(c);
00199 object->SetParentObject(this);
00200
00201
00202 SortDrawOrder();
00203
00204
00205 object->CalculateRealColor();
00206 }
00207
00208 void MercuryObject::SetDrawOrder(int order)
00209 {
00210 MercuryObjectBase::SetDrawOrder(order);
00211
00212
00213 if (m_parentObject)
00214 ((MercuryObject*)m_parentObject)->SortDrawOrder();
00215 }
00216
00217 void MercuryObject::SortDrawOrder()
00218 {
00219 TSortDrawOrder(m_objects);
00220 }
00221
00222 #include "MercuryObjectFactory.h"
00223
00224 CLASS_FUNCTION_VOID_NOARGS( MercuryObject, Destroy );
00225 CLASS_FUNCTION_VOID_ONEARG( MercuryObject, SetName, TYPECASTMSTRING , const char * );
00226 CLASS_FUNCTION_VOID_TWOARGS( MercuryObject, AddObject, (MercuryObject*)(void*), void *, (bool), bool );
00227 CLASS_FUNCTION_TWOARGS( MercuryObject, RemoveObject, bool, (MercuryObject*)(void*), void *, (bool), bool );
00228 CLASS_FUNCTION_VOID_ONEARG( MercuryObject, SetMaterial, (MercuryMaterial*)(void*), MercuryMaterial* );
00229 CLASS_FUNCTION_VOID_FOURARGS( MercuryObject, SetDiffusef, (float), float, (float), float, (float), float, (float), float );
00230 CLASS_FUNCTION_VOID_FOURARGS( MercuryObject, SetSpecularf, (float), float, (float), float, (float), float, (float), float );
00231 CLASS_FUNCTION_VOID_FOURARGS( MercuryObject, SetEmissivef, (float), float, (float), float, (float), float, (float), float );
00232 CLASS_FUNCTION_VOID_FOURARGS( MercuryObject, SetAmbientf, (float), float, (float), float, (float), float, (float), float );
00233 CLASS_FUNCTION_NOARGS( MercuryObject, GetName, const char * );
00234 CLASS_FUNCTION_NOARGS( MercuryObject, GetMaterial, const MercuryMaterial * );
00235
00236 CLASS_FUNCTION_THREEARGS( MercuryObject, Spawn, MercuryObject*,TYPECASTMSTRING , const char *, TYPECASTMSTRING, const char *, (PROJECTIONTYPE)(int), int );
00237 CLASS_FUNCTION_NOARGS( MercuryObject, GetNumChildren, int );
00238 CLASS_FUNCTION_NOARGS( MercuryObject, GetHAlignment, int );
00239 CLASS_FUNCTION_VOID_ONEARG( MercuryObject, SetHAlignment, (MercuryObject::HALIGN)(int), int );
00240 CLASS_FUNCTION_NOARGS( MercuryObject, GetVAlignment, int );
00241 CLASS_FUNCTION_VOID_ONEARG( MercuryObject, SetVAlignment, (MercuryObject::VALIGN)(int), int );
00242
00243 PSElement PS_MercuryObject_FinishTweening( MercuryCommandHandler * pThs, const PStack & pParameters )
00244 {
00245 ((MercuryObject*)pThs)->Tweening.FinishTweening();
00246 return PSElement();
00247 }
00248 RUN_STATEMENT_AT_BOOT( REGISTER_MercuryObject_FinishTweening, MercuryObjectFactory::GetInstance().RegisterFunction( &PS_MercuryObject_FinishTweening, "MercuryObject", "FinishTweening" ); )
00249 EXPORTPREFIX void HGEXPORT MercuryObject_FinishTweening( void * pThs )
00250 {
00251 ((MercuryObject*)pThs)->Tweening.FinishTweening();
00252 } EXPORTSUFFIX
00253
00254
00255 PSElement PS_MercuryObject_StopTweening( MercuryCommandHandler * pThs, const PStack & pParameters )
00256 {
00257 ((MercuryObject*)pThs)->Tweening.StopTweening();
00258 return PSElement();
00259 }
00260 RUN_STATEMENT_AT_BOOT( REGISTER_MercuryObject_StopTweening, MercuryObjectFactory::GetInstance().RegisterFunction( &PS_MercuryObject_StopTweening, "MercuryObject", "StopTweening" ); )
00261 EXPORTPREFIX void HGEXPORT MercuryObject_StopTweening( void * pThs )
00262 {
00263 ((MercuryObject*)pThs)->Tweening.StopTweening();
00264 } EXPORTSUFFIX
00265
00266
00267 PSElement PS_MercuryObject_AddCommand( MercuryCommandHandler * pThs, const PStack & pParameters )
00268 {
00269 ((MercuryObject*)pThs)->Tweening.AddCommand( pParameters.PeekItem(0), (MercuryTweenState::SPACE)(int)pParameters.PeekItem(1), pParameters.PeekItem(2) );
00270 return PSElement();
00271 }
00272 RUN_STATEMENT_AT_BOOT( REGISTER_MercuryObject_AddCommand, MercuryObjectFactory::GetInstance().RegisterFunction( &PS_MercuryObject_AddCommand, "MercuryObject", "AddCommand" ); )
00273 EXPORTPREFIX void HGEXPORT MercuryObject_AddCommand( void * pThs, const char * p1, int p2, const char * p3 )
00274 {
00275 ((MercuryObject*)pThs)->Tweening.AddCommand( p1, (MercuryTweenState::SPACE) p2, p3 );
00276 } EXPORTSUFFIX
00277
00278
00279 void MercuryObject::SetName( const MString& name )
00280 {
00281 OBJECTREGISTER.Unregister( m_name );
00282 m_name=name;
00283 OBJECTREGISTER.Register( this, m_name );
00284 }
00285
00286 bool MercuryObject::ReplaceObject(MercuryObject* object, MercuryObject* newobject)
00287 {
00288 ASSERT(object->m_initalized);
00289
00290 FOREACH_Object(m_objects, i)
00291 if (i->pObject == object)
00292 {
00293 i->pObject->SetParentObject(NULL);
00294 i->pObject = newobject;
00295
00296 i->pObject->SetParentObject(this);
00297
00298 SortDrawOrder();
00299
00300 i->pObject->CalculateRealColor();
00301 return true;
00302 }
00303
00304 return false;
00305 }
00306
00307 bool MercuryObject::RemoveObject(MercuryObject* object, bool bAllowDelete )
00308 {
00309 FOREACH_Object(m_objects, i)
00310 if (i->pObject == object)
00311 {
00312 i->pObject->SetParentObject(NULL);
00313
00314 if (i->bAutoDelete && bAllowDelete && !m_bClone )
00315 SAFE_DELETE( i->pObject );
00316
00317 i->pObject = NULL;
00318 m_objects.erase(i);
00319 return true;
00320 }
00321
00322 return false;
00323 }
00324
00325 void MercuryObject::CalculateRealColor()
00326 {
00327 m_realColor = m_modColor;
00328
00329 if (m_parentObject != NULL)
00330 m_realColor *= ((MercuryObject*)m_parentObject)->m_realColor;
00331
00332 m_finalMaterial = m_realColor;
00333
00334 if (m_pMaterial != NULL)
00335 m_finalMaterial *= *m_pMaterial;
00336
00337
00338 FOREACH_Object(m_objects, child)
00339 child->pObject->CalculateRealColor();
00340 }
00341
00342 MercuryObject * MercuryObject::Spawn( const MString & sClass, const MString & sName, PROJECTIONTYPE projection )
00343 {
00344 MercuryObject * pObject = MercuryObjectFactory::GetInstance().GenerateObject( sClass, sName );
00345 if ( pObject == NULL )
00346 return false;
00347
00348 pObject->Init();
00349
00350 AddObject( pObject, true );
00351 return pObject;
00352 }
00353
00354 MercuryObjectRegister::MercuryObjectRegister()
00355 :NOTFOUND(-5280)
00356 {
00357 if ( !MESSAGEMAN )
00358 MESSAGEMAN = new MercuryMessageManager;
00359 MESSAGEMAN->Subscribe( "ObjectStopTweening", MercuryCallback( SendCompiledMessage, (void*)1 ) );
00360 MESSAGEMAN->Subscribe( "ObjectFinishTweening", MercuryCallback( SendCompiledMessage, (void*)2 ) );
00361 MESSAGEMAN->Subscribe( "ObjectAddCommand", MercuryCallback( SendCompiledMessage, (void*)3 ) );
00362 MESSAGEMAN->Subscribe( "LogAllObjects", MercuryCallback( SendCompiledMessage, (void*)4 ) );
00363 }
00364
00365 void MercuryObjectRegister::Register( MercuryObject * obj, const MString & name )
00366 {
00367 m_mObjects[name] = obj;
00368 if ( GetCountOfObject( name ) == NOTFOUND )
00369 m_mObjectCounts[name]=1;
00370 else
00371 ++m_mObjectCounts[name];
00372 }
00373
00374 void MercuryObjectRegister::Unregister( const MString & name )
00375 {
00376 if ( --m_mObjectCounts[name] == 0 )
00377 m_mObjectCounts.remove( name );
00378 m_mObjects.remove( name );
00379 }
00380
00381 MercuryObject * MercuryObjectRegister::GetObjectFromName( const MString & name )
00382 {
00383 MercuryObject ** ret = m_mObjects.get( name );
00384 if( ret )
00385 return *ret;
00386 else
00387 return NULL;
00388 }
00389
00390 void MercuryObjectRegister::SendCompiledMessage( const MString &message, void * data, PStack & info )
00391 {
00392 switch ( (MVPtr)data )
00393 {
00394 case 4:
00395 {
00396 LOG.Info( "Logging all currently created objects." );
00397 LOG.Info( ssprintf( "Current noname allocations: %d", GetCountOfObject( "" ) ) );
00398 LOG.Info( "Memory Address:ObjectName Count" );
00399 MVector< MString > vNames;
00400 OBJECTREGISTER.m_mObjects.VectorIndicies( vNames );
00401 for( unsigned int i = 0; i < vNames.size(); i++ )
00402 LOG.Info( ssprintf( "%X:%s %d", OBJECTREGISTER.m_mObjects[vNames[i]], vNames[i].c_str(), GetCountOfObject( vNames[i] ) ) );
00403 }
00404 return;
00405 }
00406
00407 MString sObjectName = info.PopItem().GetValueS();
00408 MercuryObject * res;
00409
00410 res = OBJECTREGISTER.GetObjectFromName( sObjectName );
00411
00412 if ( !res )
00413 return;
00414
00415 switch ( (MVPtr)data )
00416 {
00417 case 1:
00418 res->Tweening.StopTweening();
00419 break;
00420 case 2:
00421 res->Tweening.FinishTweening();
00422 break;
00423 case 3:
00424 res->Tweening.AddCommand( info.PopItem().GetValueS() );
00425 break;
00426 }
00427 }
00428
00429 int MercuryObjectRegister::GetCountOfObject( const MString & name )
00430 {
00431 if( m_mObjectCounts.get( name ) )
00432 return *(m_mObjectCounts.get( name ));
00433 else
00434 return 0;
00435 }
00436
00437 void MercuryObjectRegister::ShutDown()
00438 {
00439 m_mObjects.clear();
00440 m_mObjectCounts.clear();
00441 }
00442 long HGEXPORT GetObjectByName( const char * sName )
00443 {
00444 return (long)OBJECTREGISTER.GetObjectFromName( sName );
00445 }
00446
00447 REGISTER_OBJECT_TYPE( MercuryObject );
00448
00449 MHash< MercuryObject * > MercuryObjectRegister::m_mObjects;
00450 MHash< int > MercuryObjectRegister::m_mObjectCounts;
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478