#include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __NOPT_ASSERT__ #include #endif namespace Obj { #ifdef __NOPT_ASSERT__ extern bool DebugSkaterScripts; #endif CEvent::CEvent() { m_flags = 0; } CEvent::~CEvent() { if (m_flags & mCONTROLS_OWN_DATA && mp_data) delete mp_data; } void CEvent::MarkRead(uint32 receiverId, uint32 script) { Obj::CTracker* p_tracker = Obj::CTracker::Instance(); p_tracker->LogEventRead(this, receiverId, script); m_flags |= mREAD; } void CEvent::MarkHandled(uint32 receiverId, uint32 script) { Obj::CTracker* p_tracker = Obj::CTracker::Instance(); p_tracker->LogEventHandled(this, receiverId, script); m_flags |= mHANDLED; } int CEvent::sExtractControllerIndex(CEvent *pEvent) { int controller = 0; Script::CStruct *pData = pEvent->GetData(); if (pData) pData->GetInteger("controller", &controller); return controller; } CEventListener::CEventListener() { m_registered = false; m_ref_count = 0; } CEventListener::~CEventListener() { CTracker* p_tracker = CTracker::Instance(); p_tracker->UnregisterEventListener(this); Dbg_MsgAssert(m_ref_count == 0, ("Event listener still being referenced")); } /* The flags are for optimization purposes. Don't allow events that aren't targeted to the attached object if it isn't necessary -- this will speed things up. pObject = NULL means no associated CObject, which is legal, but you must set mALL_ALL_EVENTS */ void CEventListener::RegisterWithTracker(CObject *pObject) { mp_object = pObject; CTracker* p_tracker = CTracker::Instance(); p_tracker->RegisterEventListener(this); } /* Called by CTracker singleton on every event listener that is registered, whenever CTracker receives an event. */ void CEventListener::event_filter(CEvent *pEvent) { if (mp_object) { #ifdef __NOPT_ASSERT__ // if (mp_object->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT) // ((Front::CScreenElement *) mp_object.Convert())->debug_verify_integrity(); #endif } // TRICKY DELETE // Can in theory lead to the destruction of any CObject or any listener. // Will assert if this listener gets destroyed pass_event_to_listener(pEvent); if (mp_object) { #ifdef __NOPT_ASSERT__ // if (mp_object->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT) // ((Front::CScreenElement *) mp_object.Convert())->debug_verify_integrity(); #endif } } CEventHandlerTable::CEventHandlerTable() { m_num_entries = 0; mp_tab = NULL; m_valid = true; m_in_immediate_use_counter = 0; m_changed = false; } CEventHandlerTable::~CEventHandlerTable() { Dbg_Assert(!m_in_immediate_use_counter); if (mp_tab) { for (int i = 0; i < m_num_entries; i++) { if (mp_tab[i].p_params) { delete mp_tab[i].p_params; } } delete [] mp_tab; } } void CEventHandlerTable::GetDebugInfo(Script::CStruct *p_info) { #ifdef __DEBUG_CODE__ if (mp_tab && m_num_entries) { Script::CArray *p_array=new Script::CArray; p_array->SetSizeAndType(m_num_entries,ESYMBOLTYPE_STRUCTURE); for (int i=0; iAddChecksum(CRCD(0x7321a8d6,"Type"), mp_tab[i].type); p_ex->AddChecksum(CRCD(0xd1e70f97,"Event_Script"), mp_tab[i].script); p_ex->AddChecksum(CRCD(0x923fbb3a, "Group"), mp_tab[i].group); p_array->SetStructure(i,p_ex); } else { Script::CStruct *p_ex = new Script::CStruct; p_ex->AddChecksum(NO_NAME, CRCD(0xd3d5f556, "DeadEntry")); p_array->SetStructure(i,p_ex); } } p_info->AddArrayPointer(CRCD(0x3e55ff39,"mp_event_handler_table"),p_array); } #endif } // Add a single event to the table // replacing any existing event handler with the same ex type void CEventHandlerTable::AddEvent(uint32 ex, uint32 scr, uint32 group, bool exception, Script::CStruct *p_params) { Entry *p_entry = NULL; // if there is no mp_tab, then we'll need to create a single entry one if (!mp_tab) { m_num_entries = 1; mp_tab = new Entry[1]; p_entry = mp_tab; } else { // otherwise see it it exists, and if so, then simply replace it int i; for (i = 0; ip_params) { delete p_entry->p_params; } goto GOT_ENTRY; // goto useful } } // check for empty slots, and use them for (i = 0; ienabled = true; p_entry->exception = exception; p_entry->group = group; if (p_params) { // printf ("Allocating parameters\n"); // if params are passed, then we need to make a copy of them p_entry->p_params = new Script::CStruct(*p_params); } else { p_entry->p_params = NULL; } p_entry->script = scr; p_entry->type = ex; // Need to flag it as changed, so we can break out of pass_event // if an event causes a change in the table (which we are iterating over) m_changed = true; } void CEventHandlerTable::add_from_script(Script::CArray *pArray, bool replace) { Dbg_Assert(pArray); int new_entries = pArray->GetSize(); if (replace && !new_entries) { // if no new entries, and we are "replacing", then delete any existing table // and return if (mp_tab) { for (int i = 0; i < m_num_entries; i++) { if (mp_tab[i].p_params) { delete mp_tab[i].p_params; } } delete [] mp_tab; mp_tab = NULL; m_num_entries = 0; m_changed = true; } return; } /* // Optimization for adding a single entry if (new_entries == 1) { // get the type, script pair, and any params and flags Script::CStruct *pEventStruct = pArray->GetStructure(0); Script::CComponent *p_left = pEventStruct->GetNextComponent(NULL); Dbg_MsgAssert(p_left, ("missing 'type' half of event handler pair")); Dbg_Assert(p_left->mType == ESYMBOLTYPE_NAME); Script::CComponent *p_right = pEventStruct->GetNextComponent(p_left); Dbg_MsgAssert(p_right, ("missing 'handler' half of event handler pair")); Dbg_Assert(p_right->mType == ESYMBOLTYPE_NAME); uint32 type = p_left->mChecksum; Entry *p_entry = NULL; // if it's a "replace" entry, then we scan through to see if we already have an entry // then we delete it, and can use that slot if (replace) { for (int i = 0; i < m_num_entries; i++) { if (mp_tab[i].type == type) { mp_tab[i].script = vDEAD_ENTRY; // delete the original parameters, whilst (while!) we are at it if (mp_tab[i].p_params) { delete mp_tab[i].p_params; mp_tab[i].p_params = NULL; } p_entry = &mp_tab[i]; break; } } } // if not got one via replace, we need to look for an empty slot // 95% of the time there should be one, as the table // will expand to the max size required, and will not shrink // so we only need to add slots during expansion. for (int i = 0; i < m_num_entries; i++) { if (mp_tab[i].script == vDEAD_ENTRY) { p_entry = &mp_tab[i]; break; } } if (p_entry) { // DANG! This is a chunk of cut and paste code from below // this event handler container is in serious need // of refactoring // Mick, if the event handler has a "params" structure // then add it to the entry. // (note, have to be careful in cleaning these up) Script::CStruct *p_params; if (pEventStruct->GetStructure(CRCD(0x7031f10c,"params"),&p_params)) { printf ("Allocating Params\n"); p_entry->p_params = new Script::CStruct(*p_params); } else { p_entry->p_params = NULL; } if (!pEventStruct->GetChecksum(CRCD(0x923fbb3a, "Group"), &p_entry->group)) { p_entry->group = vDEFAULT_GROUP; } p_entry->exception = pEventStruct->ContainsFlag(CRCD(0x80367192,"Exception")); p_entry->type = p_left->mChecksum; p_entry->script = p_right->mChecksum; Dbg_MsgAssert(p_entry->script,("Adding Null script in event handler")); p_entry->enabled = true; m_changed = true; return; } } */ Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap()); // create new table (this is the one with problems with p_params) // the values are not initialized // so if it's allocated over an old one, then // errors might occur // printf("Allocating memory for %d new entries\n",new_entries); Entry *p_edit_tab = new Entry[m_num_entries + new_entries]; #ifdef __NOPT_ASSERT__ int first_edit_entry = m_num_entries; #endif int new_entry_index = 0; // transfer the new entries from script array into new table for (int i = 0; i < new_entries; i++) { // get the type, script pair, and any params and flags Script::CStruct *pEventStruct = pArray->GetStructure(i); Script::CComponent *p_left = pEventStruct->GetNextComponent(NULL); Dbg_MsgAssert(p_left, ("missing 'type' half of event handler pair")); Dbg_Assert(p_left->mType == ESYMBOLTYPE_NAME); Script::CComponent *p_right = pEventStruct->GetNextComponent(p_left); Dbg_MsgAssert(p_right, ("missing 'handler' half of event handler pair")); Dbg_Assert(p_right->mType == ESYMBOLTYPE_NAME); if (replace) { // remove entry from old table, if it exists in there remove_entry(p_left->mChecksum); } Entry *p_entry = p_edit_tab + new_entry_index++; // Mick, if the event handler has a "params" structure // then add it to the entry. // (note, have to be careful in cleaning these up) Script::CStruct *p_params; if (pEventStruct->GetStructure(CRCD(0x7031f10c,"params"),&p_params)) { Dbg_MsgAssert( (i + first_edit_entry) < (m_num_entries + new_entries), ( "Array overflow" ) ); p_entry->p_params = new Script::CStruct(*p_params); } else { p_entry->p_params = NULL; } if (!pEventStruct->GetChecksum(CRCD(0x923fbb3a, "Group"), &p_entry->group)) { p_entry->group = vDEFAULT_GROUP; } p_entry->exception = pEventStruct->ContainsFlag(CRCD(0x80367192,"Exception")); p_entry->type = p_left->mChecksum; p_entry->script = p_right->mChecksum; Dbg_MsgAssert(p_entry->script,("Adding Null script in event handler")); p_entry->enabled = true; m_changed = true; } // if member table already exists, copy it into new one, at the end // (append to items already added) // Note that some entries in the original table might have been deleted, so // the size of mp_tab might end up being bigger than that indicated by m_num_entries // but the extra at the end is just garbage. // This is most common when you Set individual events on // and already existing table that contains that event // (old code would have left an uninitialized gap, causing very obscure bugs) if (mp_tab) { for (int i = 0; i < m_num_entries; i++) { p_edit_tab[new_entry_index++] = mp_tab[i]; } } delete [] mp_tab; // old table has been coped over, so we can delete it mp_tab = p_edit_tab; // and make the newly constructed table the active table m_num_entries = new_entry_index; // set the number of entries to the actual counted entries (not the size of the array) Mem::Manager::sHandle().PopContext(); } // doesn't change the array size, just marks entry dead (and deletes p_params struct) void CEventHandlerTable::remove_entry(uint32 type) { for (int i = 0; i < m_num_entries; i++) { if (mp_tab[i].type == type) { mp_tab[i].type = 0; mp_tab[i].script = vDEAD_ENTRY; // delete the original parameters, whilst (while!) we are at it if (mp_tab[i].p_params) { delete mp_tab[i].p_params; mp_tab[i].p_params = NULL; } } } // Note, we don't set m_changed here, as the table has not really changed // just one entry has changed // we will set the m_changed flag if compress_table later removed this entry } // removes all entries with the given group id // or remove them all if "all_groups" is specifed void CEventHandlerTable::remove_group(uint32 group) { for (int i = 0; i < m_num_entries; i++) { if (mp_tab[i].group == group || group == CRCD(0x8b713e0e,"all_groups")) { mp_tab[i].script = vDEAD_ENTRY; if (mp_tab[i].p_params) { delete mp_tab[i].p_params; mp_tab[i].p_params = NULL; } } } } // changes size of table, removing dead entries void CEventHandlerTable::compress_table() { if (!mp_tab) return; // count up dead entries int num_dead = 0; int in = 0; for (; in < m_num_entries; in++) { if (mp_tab[in].script == vDEAD_ENTRY) num_dead++; } if (num_dead == 0) return; int new_size = m_num_entries - num_dead; m_changed = true; // Mick - If new table has zero size, then don't allocate it // just delete the old table, and set it to NULL if ( 0 == new_size) { for (int i = 0; i < m_num_entries; i++) { // we're about to remove an entry // so delete its params if necessary if ( mp_tab[i].p_params ) { delete mp_tab[i].p_params; mp_tab[i].p_params = NULL; } } delete[] mp_tab; mp_tab = NULL; m_num_entries = 0; } else { Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().FrontEndHeap()); Entry *p_new_tab = new Entry[new_size]; Mem::Manager::sHandle().PopContext(); int out = 0; for (in = 0; in < m_num_entries; in++) { if (mp_tab[in].script != vDEAD_ENTRY) { p_new_tab[out++] = mp_tab[in]; } else { // we're about to remove an entry // so delete its params if necessary if ( mp_tab[in].p_params ) { delete mp_tab[in].p_params; mp_tab[in].p_params = NULL; } } } delete[] mp_tab; mp_tab = p_new_tab; m_num_entries = new_size; } } void CEventHandlerTable::set_event_enable(uint32 type, bool state) { for (int i = 0; i < m_num_entries; i++) { if (mp_tab[i].type == type) mp_tab[i].enabled = state; } } #ifdef __SCRIPT_EVENT_TABLE__ void CEventHandlerTable::pass_event(CEvent *pEvent, Script::CScript *pScript, bool broadcast) { // if it's a screen element, check that events aren't blocked #ifdef __NOPT_ASSERT__ // if ( ( pObject->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT ) && // ( pObject->GetFlags() & Front::CScreenElement::vEVENTS_BLOCKED ) ) // { // return; // } #endif // __NOPT_ASSERT__ #if 1 bool old_m_changed = m_changed; m_changed = false; #else // only clear the m_changed flag if we are not recursing into here if (!m_in_immediate_use_counter) { m_changed = false; } #endif m_in_immediate_use_counter++; #ifndef __PLAT_WN32__ // Need to assert that mp_tab is valid (or we have no entries in it) Dbg_MsgAssert(!m_num_entries || Mem::Valid(mp_tab),("Invalid event handler table for Event %s", Script::FindChecksumName(pEvent->GetType()))); #endif Entry *p_entry = mp_tab; for (int i = 0; i < m_num_entries; i++) { if (p_entry->type == pEvent->GetType() && p_entry->script != vDEAD_ENTRY && p_entry->enabled) { Script::CScript *p_new_script = NULL; Script::CStruct *p_params = NULL; Script::CStruct *p_passed_params = NULL; // printf ("%s calls %s\n",Script::FindChecksumName(p_entry->type),Script::FindChecksumName(p_entry->script)); if (pEvent->GetData()) { // there is event data, so copy it into a new structure p_params = new Script::CStruct(); // and then merge the parameters in with it if (p_entry->p_params) { *p_params += *(p_entry->p_params); } *p_params += *(pEvent->GetData()); p_passed_params = p_params; // using p_params like this is safe, since SpawnScript makes its own copy } else { p_passed_params = p_entry->p_params; } if (p_entry->exception) { #ifdef __NOPT_ASSERT__ if (DebugSkaterScripts && (pEvent->GetTarget() == 0 || pEvent->GetSource())) { printf("%d: Exception %s, Script %s, Target %s, Source %s\n", (int)Tmr::GetRenderFrame(), Script::FindChecksumName(pEvent->GetType()), Script::FindChecksumName(p_entry->script), pEvent->GetTarget() ? Script::FindChecksumName(pEvent->GetTarget()) : "Skater", pEvent->GetSource() ? Script::FindChecksumName(pEvent->GetSource()) : "Skater" ); } #endif // If it's an exception, we check to see if the object // has flagged an "OnExceptionRun" if (pScript->GetOnExceptionScriptChecksum()) { // Pass in the name of the exception so that certain exceptions can be ignored. Script::CStruct *pFoo=new Script::CStruct; pFoo->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int)p_entry->exception); // Script::RunScript(pScript->GetOnExceptionScriptChecksum(), pFoo, pScript->mpObject ); // Dan: interrupt instead of run uint32 checksum = pScript->GetOnExceptionScriptChecksum(); pScript->SetOnExceptionScriptChecksum(0); // clear it once it has been run pScript->Interrupt(checksum, pFoo); delete pFoo; } // the OnException script may alter the table if (p_entry->script != vDEAD_ENTRY) { // Exceptions act like a GOTO, so we just set the script we are running on to this new script // the object reamins the same pScript->SetScript(p_entry->script,p_passed_params,pScript->mpObject); pScript->Update(); } } else { // Current Screen element code relies on spawned scripts // as they don't update their own scripts // but we are moving to an "Interrupt" model, so we // only support this "Spawned" model for the screen elements if (pScript->mpObject && pScript->mpObject->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT) { // Normal events spawn a new script running on the same object as the current script (if any) p_new_script = Script::SpawnScript(p_entry->script, p_passed_params, 0, NULL); #ifdef __NOPT_ASSERT__ p_new_script->SetCommentString("Spawned by CEventHandlerTable::pass_event, 1"); #endif p_new_script->mpObject = pScript->mpObject; p_new_script->Update(); } else { // Instead of spawning, just interrupt the current script pScript->Interrupt(p_entry->script, p_passed_params); } } if (p_params) { delete p_params; } Dbg_MsgAssert((*(uint32*)this) != 0x01010101,("%s\nCEventHandlerTable deleted whilst being used",p_new_script->GetScriptInfo())); //p_new_script->mpObject = NULL; // do logging //pEvent->MarkHandled(pObject->GetID(), p_entry->script); pEvent->MarkHandled(0, p_entry->script); // receiver id not important } p_entry++; if (!m_valid) { // Looks like the spawned script deleted the CObject, invalidating this event handler table. // Exit now. If the outermost pass_event() in a recursive chain, then kill self. m_in_immediate_use_counter--; if (!m_in_immediate_use_counter) delete this; return; } if (m_changed) { break; } } // if we were previously flagged as changed, or some other function flagged us as changed // then say we have changed m_changed = m_changed || old_m_changed; m_in_immediate_use_counter--; } #else void CEventHandlerTable::pass_event(CEvent *pEvent, CObject *pObject, bool broadcast) { // if it's a screen element, check that events aren't blocked #ifdef __NOPT_ASSERT__ if ( ( pObject->GetFlags() & Front::CScreenElement::vIS_SCREEN_ELEMENT ) ) { Front::CScreenElement* pScreenElement = (Front::CScreenElement*)pObject; if ( pScreenElement->EventsBlocked() ) { return; } } #endif // __NOPT_ASSERT__ // only clear the m_changed flag if we are not recursing into here if (!m_in_immediate_use_counter) { m_changed = false; } m_in_immediate_use_counter++; Entry *p_entry = mp_tab; for (int i = 0; i < m_num_entries; i++) { // if (broadcast && !p_entry->broadcast) // { // p_entry++; // continue; // } if (p_entry->type == pEvent->GetType() && p_entry->script != vDEAD_ENTRY && p_entry->enabled) { Script::CScript *p_new_script = NULL; Script::CStruct *p_params = NULL; Script::CStruct *p_passed_params = NULL; // visual debugging, if there is a source and target, and they are different // then draw a line between the two objects #ifdef __NOPT_ASSERT__ if (Script::GetInteger(CRCD(0xffc8c5f8,"Display_event_arrows"))) { if (pObject->GetFlags() & Obj::CObject::vCOMPOSITE) { uint32 source_id = pEvent->GetSource(); // printf ("Source = 0x%x %s, target = 0x%x, %s\n",source_id, Script::FindChecksumName(source_id),pObject->GetID(),Script::FindChecksumName(pObject->GetID())); if ( source_id != pObject->GetID() ) { Obj::CObject * p_source_object = Obj::CTracker::Instance()->GetObject(source_id); if (p_source_object) { // printf ("objects types %d, %d\n",pObject->GetType(), p_source_object->GetType()); // and we only want to do it if they are composite object if (pObject->GetFlags() & Obj::CObject::vCOMPOSITE && p_source_object->GetFlags() & Obj::CObject::vCOMPOSITE) // eek! { Gfx::AddDebugArrow(((CCompositeObject*)p_source_object)->GetPos(),((CCompositeObject*)pObject)->GetPos(),0xff00ff,0xff00ff,200); } } else { printf ("No Source object found\n"); } } } } if (DebugSkaterScripts && (pObject->GetID() == 0 || pEvent->GetSource() == 0)) { printf("%d: Exception %s, Script %s, Target %s, Source %s\n", (int)Tmr::GetRenderFrame(), Script::FindChecksumName(pEvent->GetType()), Script::FindChecksumName(p_entry->script), pEvent->GetTarget() ? Script::FindChecksumName(pEvent->GetTarget()) : "Skater", pEvent->GetSource() ? Script::FindChecksumName(pEvent->GetSource()) : "Skater" ); } #endif if (pEvent->GetData()) { // there is event data, so copy it into a new structure p_params = new Script::CStruct(); // and then merge the parameters in with it if (p_entry->p_params) { *p_params += *(p_entry->p_params); } *p_params += *(pEvent->GetData()); p_passed_params = p_params; // using p_params like this is safe, since SpawnScript makes its own copy } else { p_passed_params = p_entry->p_params; } if (p_entry->exception) { // If it's an exception, we check to see if the object // has flagged an "OnExceptionRun" // Ooh, we need to run a script, so better make sure mp_script points to something. if (pObject->GetScript()==NULL) { pObject->SetScript( new Script::CScript); #ifdef __NOPT_ASSERT__ pObject->GetScript()->SetCommentString("Created in CEventHandlerTable::pass_event(...) (exception)"); #endif } // Now we're safe. Note: mp_script will get cleaned up by the CObject destructor. if (pObject->GetOnExceptionScriptChecksum()) { // printf ("Running onException script %s\n",Script::FindChecksumName(pObject->GetOnExceptionScriptChecksum())); // Pass in the name of the exception so that certain exceptions can be ignored. Script::CStruct *pFoo=new Script::CStruct; pFoo->AddComponent(NONAME, ESYMBOLTYPE_NAME, (int)p_entry->exception); Script::RunScript(pObject->GetOnExceptionScriptChecksum(), pFoo, pObject ); delete pFoo; pObject->SetOnExceptionScriptChecksum(0); // clear it once it has been run } // An exception will act like a "goto" Script::CScript *p_old_script = pObject->GetScript(); // printf("RUNNING exception %s script %s on object %s\n",Script::FindChecksumName(p_entry->type),Script::FindChecksumName(p_entry->script),Script::FindChecksumName(pObject->GetID())); p_old_script->SetScript(p_entry->script,p_passed_params,pObject); p_old_script->Update(); } else { // Normal events spawn a script running on an object // printf("SPAWNING exception %s script %s on object %s\n",Script::FindChecksumName(p_entry->type),Script::FindChecksumName(p_entry->script),Script::FindChecksumName(pObject->GetID())); p_new_script = Script::SpawnScript(p_entry->script, p_passed_params, 0, NULL); #ifdef __NOPT_ASSERT__ p_new_script->SetCommentString("Spawned by CEventHandlerTable::pass_event, 1"); #endif p_new_script->mpObject = pObject; p_new_script->Update(); } if (p_params) { delete p_params; } Dbg_MsgAssert((*(uint32*)this) != 0x01010101,("%s\nCEventHandlerTable deleted whilst being used",p_new_script->GetScriptInfo())); //p_new_script->mpObject = NULL; // do logging pEvent->MarkHandled(pObject->GetID(), p_entry->script); } p_entry++; if (!m_valid) { // Looks like the spawned script deleted the CObject, invalidating this event handler table. // Exit now. If the outermost pass_event() in a recursive chain, then kill self. m_in_immediate_use_counter--; if (!m_in_immediate_use_counter) delete this; return; } if (m_changed) { break; } } m_in_immediate_use_counter--; } #endif #ifdef __SCRIPT_EVENT_TABLE__ // Register all the entries in this even table with the event receiver table in the tracker // (Hey, maybe store the script in here, allow multiple entries and do away with this table?) void CEventHandlerTable::register_all(Script::CScript *p_script) { Entry *p_entry = mp_tab; for (int i = 0; i < m_num_entries; i++) { // if it's a live entry, then add it as a receiver if (p_entry->type && p_entry->script && p_entry->script != vDEAD_ENTRY) { Obj::CTracker::Instance()->RegisterEventReceiver(p_entry->type, p_script); } p_entry++; } } // Flush out all references from the Event Receiver table to this object, based on the event handler table void CEventHandlerTable::unregister_all(Script::CScript *p_script) { Entry *p_entry = mp_tab; for (int i = 0; i < m_num_entries; i++) { if (p_entry->type) { Obj::CTracker::Instance()->UnregisterEventReceiver(p_entry->type, p_script); } p_entry++; } } #else // Register all the entries in this even table with the event receiver table in the tracker // (Hey, maybe store the script in here, allow multiple entries and do away with this table?) void CEventHandlerTable::register_all(CObject *p_object) { Entry *p_entry = mp_tab; for (int i = 0; i < m_num_entries; i++) { if (p_entry->type && p_entry->script) { Obj::CTracker::Instance()->RegisterEventReceiver(p_entry->type, p_object); } p_entry++; } } // Flush out all references from the Event Receiver table to this object, based on the event handler table void CEventHandlerTable::unregister_all(CObject *p_object) { Entry *p_entry = mp_tab; for (int i = 0; i < m_num_entries; i++) { if (p_entry->type) { Obj::CTracker::Instance()->UnregisterEventReceiver(p_entry->type, p_object); } p_entry++; } } #endif // Dump the given table void CEventHandlerTable::sPrintTable ( CEventHandlerTable* table ) { # if !defined( __PLAT_NGC__ ) || ( defined( __PLAT_NGC__ ) && !defined( __NOPT_FINAL__ ) ) printf("====================================\n"); printf("Event Handler Table:\n"); if (table) { for (int i = 0; i < table->m_num_entries; i++) { Entry* p_entry = table->mp_tab + i; printf("------------------------------------\n"); printf(" Type : %s\n", Script::FindChecksumName(p_entry->type)); printf(" Script : %s\n", Script::FindChecksumName(p_entry->script)); printf(" Group : %s\n", Script::FindChecksumName(p_entry->group)); printf(" Exception: %s\n", p_entry->exception ? "yes" : "no"); } } else { printf(" Emtpy\n"); } printf("====================================\n"); #endif // __NOPT_FINAL__ } }