#include #include "munga.h" #pragma hdrstop #include "watcher.h" #include "entity.h" #include "cstr.h" #include "objstrm.h" #include "namelist.h" #include "subsystm.h" //############################################################################# //########################## AttributeWatcher ########################### //############################################################################# // //############################################################################# //############################################################################# // AttributeWatcher::~AttributeWatcher() { } // //############################################################################# //############################################################################# // AttributeWatcher::AttributeWatcher( PlugStream *stream, Entity *entity ): Component(stream) { Check(stream); Check(entity); #if 0 // // Get attribute ptr // int subsystem_ID; DynamicMemoryStream_Read(stream, &subsystem_ID); Simulation *simulation; if ((simulation = entity->GetSubsystem(subsystem_ID)) == NULL) { simulation = entity; } Check(simulation); Simulation::AttributeID attribute_ID; DynamicMemoryStream_Read(stream, &attribute_ID); attributePointer = simulation->GetAttributePointer(attribute_ID); Check_Pointer(attributePointer); #else // // HACK - Get attribute pointer using names // CString subsystem_name; *stream >> subsystem_name; if ((simulation = entity->FindSubsystem(subsystem_name)) == NULL) { #if DEBUG_LEVEL>0 { CString entity_name("Entity"); if (!(subsystem_name == entity_name)) { Dump(subsystem_name); } Verify(subsystem_name == entity_name); } #else { CString entity_name("Entity"); if (!(subsystem_name == entity_name)) { DEBUG_STREAM << "AttributeWatcher::AttributeWatcher - subsystem " << subsystem_name << "\n"; Fail("AttributeWatcher::AttributeWatcher - subsystem not found\n"); } } #endif simulation = entity; } Check(simulation); CString attribute_name; *stream >> attribute_name; #if DEBUG_LEVEL>2 Tell("AttributeWatcher::AttributeWatcher - " << attribute_name << "\n"); #endif attributePointer = simulation->GetAttributePointer(attribute_name); if (getenv("BT_ATTRBIND_LOG")) { DEBUG_STREAM << "[attrbind] subsys=[" << subsystem_name << "] attr=[" << attribute_name << "] -> ptr=" << attributePointer << " vtbl=" << (attributePointer ? *(void**)attributePointer : (void*)0) << "\n" << std::flush; } // BRING-UP GUARD [T3, temporary]: audio references attributes on subsystems that // are not fully reconstructed yet (GeneratorState/On, CondenserState, ReportLeak, // Torso SpeedOfTorsoHorizontal/MotionState, Reservoir/Avionics/ControlsMapper ...). // GetAttributePointer returns NULL for those, and the original engine Fail()s // (fatal) -- which would abort every audio-enabled run. Redirect NULL to a shared // inert zero pad so scalar/vector watchers read 0 (that sound stays silent) instead // of crashing; state watchers on it are skipped by the AudioStateWatcher guard. // Self-clearing: a registered attribute resolves to its real member. Remove once // the subsystem attribute tables are reconstructed (the audio subsystem wave). if (attributePointer == NULL) { static char s_missingAttrPad[64] = {0}; if (getenv("BT_AUDIO_LOG")) DEBUG_STREAM << "[attrnull] " << subsystem_name << "." << attribute_name << " not reconstructed -> inert pad\n" << std::flush; attributePointer = s_missingAttrPad; } Check_Pointer(attributePointer); #endif // // Get other fields // *stream >> sendNotificationOnChange; attributeChanged = False; } // //############################################################################# // BuildFromPage //############################################################################# // void AttributeWatcher::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { Component::BuildFromPage(stream, name_list, class_ID, object_ID); // // HACK - Store attribute pointer using names // MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, subsystem); MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, attribute); // // Store other fields // Logical send_notification_on_change = True; *stream << send_notification_on_change; } // //############################################################################# //############################################################################# // Logical AttributeWatcher::TestInstance() const { Component::TestInstance(); Check(simulation); Check_Pointer(attributePointer); return True; } // //############################################################################# //############################################################################# // Logical AttributeWatcher::DidAttributeChange() { if (attributeChanged) { attributeChanged = False; return True; } return False; } // //############################################################################# //############################################################################# // void AttributeWatcher::SendNotificationOfChange() { Fail("AttributeWatcher::SendNotificationOfChange - Should never reach here"); } #ifdef TEST_CLASS # include "watcher.tcp" #endif