#include "munga.h" #pragma hdrstop #include "simulate.h" #include "update.h" #include "app.h" #if defined(TRACE_EXECUTE_WATCHERS) static BitTrace Execute_Watchers("Execute Watchers"); #define SET_EXECUTE_WATCHERS() Execute_Watchers.Set() #define CLEAR_EXECUTE_WATCHERS() Execute_Watchers.Clear() #else #define SET_EXECUTE_WATCHERS() #define CLEAR_EXECUTE_WATCHERS() #endif //############################################################################# //######################## StateIndicator ############################### //############################################################################# //############################################################################# // Construction and Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // StateIndicator::StateIndicator(): audioWatcherSocket(NULL), videoWatcherSocket(NULL), gaugeWatcherSocket(NULL) { Check_Pointer(this); stateCount = 0; oldState = 0; currentState = 0; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // StateIndicator::StateIndicator(unsigned max_states): audioWatcherSocket(NULL), videoWatcherSocket(NULL), gaugeWatcherSocket(NULL) { Check_Pointer(this); stateCount = max_states; oldState = max_states; currentState = max_states; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // StateIndicator::StateIndicator(const StateIndicator &state_indicator): audioWatcherSocket(NULL), videoWatcherSocket(NULL), gaugeWatcherSocket(NULL) { Check_Pointer(this); // Do not perform deep copy of watchers stateCount = state_indicator.stateCount; oldState = state_indicator.oldState; currentState = state_indicator.currentState; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // StateIndicator::~StateIndicator() { Check(this); // // Manual deletion of existing watchers // { SChainIteratorOf iterator(&audioWatcherSocket); #if DEBUG_LEVEL>2 Component *component; while ((component = iterator.ReadAndNext()) != NULL) { Check(component); Dump(component->GetClassID()); } Warn(iterator.GetSize() != 0); #endif iterator.DeletePlugs(); } { SChainIteratorOf iterator(&videoWatcherSocket); #if DEBUG_LEVEL>2 Component *component; while ((component = iterator.ReadAndNext()) != NULL) { Check(component); Dump(component->GetClassID()); } Warn(iterator.GetSize() != 0); #endif iterator.DeletePlugs(); } { SChainIteratorOf iterator(&gaugeWatcherSocket); #if DEBUG_LEVEL>2 Component *component; while ((component = iterator.ReadAndNext()) != NULL) { Check(component); Dump(component->GetClassID()); } Warn(iterator.GetSize() != 0); #endif iterator.DeletePlugs(); } Check_Fpu(); } //############################################################################# // State stuff // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // StateIndicator& StateIndicator::operator=(const StateIndicator &state_indicator) { // Do not perform assignment of watchers stateCount = state_indicator.stateCount; oldState = state_indicator.oldState; currentState = state_indicator.currentState; Check_Fpu(); return *this; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical StateIndicator::operator==(const StateIndicator &state_indicator) const { Check_Fpu(); return ( stateCount == state_indicator.stateCount && oldState == state_indicator.oldState && currentState == state_indicator.currentState ); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void StateIndicator::SetState(unsigned new_state) { Check(this); Verify(new_state < stateCount); // //-------------------------------------------------------------------------- // See if the state really changes // // NOTE - the old state does change to the current state, simulating a loop // in the state engine. If it turns out that someone is watching the // level of the state indicator and doing their own edge detection, // this might possibly maybe screw something up //-------------------------------------------------------------------------- // oldState = currentState; if (new_state == currentState) { return; } // //------------------------------------------------------------------- // If the state has changed, update the state values and then run any // watchers //------------------------------------------------------------------- // currentState = new_state; Component *watcher; SET_EXECUTE_WATCHERS(); // Audio { SChainIteratorOf iterator(audioWatcherSocket); Check(&iterator); while ((watcher = iterator.ReadAndNext()) != NULL) { watcher->Execute(); } } // Video { SChainIteratorOf iterator(videoWatcherSocket); Check(&iterator); while ((watcher = iterator.ReadAndNext()) != NULL) { watcher->Execute(); } } // Gauge { SChainIteratorOf iterator(gaugeWatcherSocket); Check(&iterator); while ((watcher = iterator.ReadAndNext()) != NULL) { watcher->Execute(); } } CLEAR_EXECUTE_WATCHERS(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // std::ostream& operator << (std::ostream &strm, const StateIndicator &state_indicator) { Check(&state_indicator); strm << "[" << state_indicator.stateCount << ","; strm << state_indicator.oldState << ","; strm << state_indicator.currentState << "]"; return strm; } //############################################################################# // Test Support // Logical StateIndicator::TestInstance() const { return True; } //############################################################################# //########################## Simulation ################################# //############################################################################# //############################################################################# // Virtual Data support // Derivation* Simulation::GetClassDerivations() { static Derivation classDerivations(Receiver::GetClassDerivations(), "Simulation"); return &classDerivations; } Simulation::SharedData Simulation::DefaultData( Simulation::GetClassDerivations(), Simulation::GetMessageHandlers(), Simulation::GetAttributeIndex(), Simulation::StateCount ); //############################################################################# // Model support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Simulation::ReadUpdateRecord(UpdateRecord *message) { Check(this); Check_Pointer(message); lastUpdate = Now(); // HACK - should be based upon message->timeStamp SetSimulationState(message->simulationState); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Simulation::WriteUpdateRecord( UpdateRecord *message, int update_model ) { Check(this); Check_Pointer(message); message->timeStamp = lastPerformance; message->simulationState = GetSimulationState(); message->recordLength = sizeof(*message); message->recordID = (Word)update_model; lastUpdate = lastPerformance; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Simulation::WriteSimulationUpdate(MemoryStream *update_stream) { Check(this); Check(update_stream); // //----------------- // Write the update //----------------- // int bit=0; int update_model = updateModel; updateModel = 0; while (update_model) { if (update_model & 1) { UpdateRecord* update = (UpdateRecord*)update_stream->GetPointer(); WriteUpdateRecord(update, bit); update_stream->AdvancePointer(update->recordLength); } update_model >>= 1; ++bit; } Check_Fpu(); } //############################################################################# // Construction and Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Simulation::Simulation( Simulation::ClassID class_ID, Simulation::SharedData &virtual_data ): Receiver(class_ID, virtual_data), simulationState(GetSharedData()->stateCount), audioWatcherSocket(NULL), videoWatcherSocket(NULL), gaugeWatcherSocket(NULL), effectWatcherSocket(NULL) { Check_Pointer(this); SetSimulationState(DefaultState); lastPerformance = Now(); lastUpdate = lastPerformance; activePerformance = &Simulation::DoNothingOnce; updateModel = 0; simulationFlags = 0; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Simulation::~Simulation() { Check(this); // // Watchers should be deleted by renderers by now // #if DEBUG_LEVEL>0 { SChainIteratorOf iterator(&audioWatcherSocket); Verify(iterator.GetSize() == 0); } { SChainIteratorOf iterator(&videoWatcherSocket); Verify(iterator.GetSize() == 0); } { SChainIteratorOf iterator(&gaugeWatcherSocket); Verify(iterator.GetSize() == 0); } #endif Check_Fpu(); } //############################################################################# // Attribute Support // const Simulation::AttributePointer Simulation::NullAttribute = NULL; const Simulation::IndexEntry Simulation::AttributePointers[]= { { Simulation::SimulationStateAttributeID, "SimulationState", (Simulation::AttributePointer)&Simulation::simulationState } }; Simulation::AttributeIndexSet& Simulation::GetAttributeIndex() { static Simulation::AttributeIndexSet attributeIndex(ELEMENTS(Simulation::AttributePointers), Simulation::AttributePointers ); return attributeIndex; } void* Simulation::GetAttributePointer(Simulation::AttributeID attribute) { Check(this); AttributePointer attr = GetSharedData()->activeAttributeIndex->Find(attribute); Check_Fpu(); if (attr == NullAttribute) { return NULL; } else { return &(this->*attr); } } void* Simulation::GetAttributePointer(const char* attribute_name) { Check(this); AttributePointer attr = GetSharedData()->activeAttributeIndex->Find(attribute_name); Check_Fpu(); if (attr == NullAttribute) { return NULL; } else { return &(this->*attr); } } //############################################################################# // Simulation Support // void Simulation::PerformAndWatch( const Time& till, MemoryStream *update_stream ) { Check(this); Check(&till); Scalar slice = till - lastPerformance; lastPerformance = till; Perform(slice); if (!AreWatchersDelayed()) { ExecuteWatchers(); } WriteSimulationUpdate(update_stream); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Simulation::DoNothingOnce(Scalar) { NeverExecute(); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Simulation::DoNothing(Scalar) { Check_Fpu(); } //############################################################################# // Watcher Support // void Simulation::ExecuteWatchers() { SET_EXECUTE_WATCHERS(); Component *watcher; // Audio { SChainIteratorOf iterator(audioWatcherSocket); while ((watcher = iterator.ReadAndNext()) != NULL) { watcher->Execute(); } } // Video { SChainIteratorOf iterator(videoWatcherSocket); while ((watcher = iterator.ReadAndNext()) != NULL) { watcher->Execute(); } } // Gauge { SChainIteratorOf iterator(gaugeWatcherSocket); while ((watcher = iterator.ReadAndNext()) != NULL) { watcher->Execute(); } } // Effect { SChainIteratorOf iterator(effectWatcherSocket); while ((watcher = iterator.ReadAndNext()) != NULL) { watcher->Execute(); } } CLEAR_EXECUTE_WATCHERS(); } //############################################################################# // Test Support // Logical Simulation::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); } //############################################################################# //################### Simulation::AttributeIndexSet ##################### //############################################################################# const Simulation::AttributeIndexSet Simulation::AttributeIndexSet::NullSet; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Simulation__AttributeIndexSet::~Simulation__AttributeIndexSet() { if (attributeIndex) { Unregister_Pointer(attributeIndex); delete[] attributeIndex; } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void Simulation::AttributeIndexSet::Build( Simulation::AttributeID count, const Simulation::IndexEntry index_table[], const Simulation::AttributeIndexSet *inheritance ) { // //------------------------------------------------------- // Find out the highest message type we have to deal with //------------------------------------------------------- // Check(this); Check_Pointer(index_table); entryCount = 0; Simulation::AttributeID i; for (i=0; i entryCount) { entryCount = index_table[i].entryID; } } if (inheritance) { Check(inheritance); if (entryCountentryCount) { entryCount = inheritance->entryCount; } #if DEBUG_LEVEL>0 else if (entryCount > inheritance->entryCount) { i = inheritance->entryCount+1; goto Check_Table; } #endif } else { Verify(entryCount == count); #if DEBUG_LEVEL>0 i = 1; Check_Table: while (i <= entryCount) { int j; for (j=0; j count); #endif } // //----------------------------------------------------------------------- // Allocate the memory for the new handler set, and copy the inherited // handlers to the new table. We are guaranteed to have enough space for // the inherited table //----------------------------------------------------------------------- // attributeIndex = new Simulation::IndexEntry[entryCount]; Check_Pointer(attributeIndex); Register_Pointer(attributeIndex); i = 0; if (inheritance) { for (; ientryCount; ++i) { attributeIndex[i] = inheritance->attributeIndex[i]; } } // //---------------------------------------------------------------------- // Step through the new table supplied, placing each handler in the slot // determined by the message type //---------------------------------------------------------------------- // for (i=0; i inheritance->entryCount); attributeIndex[index_table[i].entryID-1] = index_table[i]; } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Simulation::AttributePointer Simulation::AttributeIndexSet::Find(const char* attribute_name) const { Check(this); Check_Pointer(attribute_name); for (int attribute=0; attributeGetUpdateManager(); Check(updater); updater->RequestEncore(this, encore); } #if defined(TEST_CLASS) && 0 #include "model.tcp" #endif