#include #include "munga.h" #pragma hdrstop #include "audwthr.h" #include "objstrm.h" #include "namelist.h" //############################################################################# //########################### AudioIdleWatcher ########################## //############################################################################# // //############################################################################# //############################################################################# // AudioIdleWatcher::AudioIdleWatcher( PlugStream *stream, Entity *entity ): Component(stream), audioComponentSocket(this) { AudioComponent *audio_component; PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); AudioIdleWatcherX(audio_component, entity); } // //############################################################################# //############################################################################# // void AudioIdleWatcher::AudioIdleWatcherX( AudioComponent *audio_component, Entity *entity ) { Check(audio_component); Check(entity); audioComponentSocket.Add(audio_component); entity->AddAudioWatcher(this); } // //############################################################################# //############################################################################# // AudioIdleWatcher::~AudioIdleWatcher() { } // //############################################################################# //############################################################################# // void AudioIdleWatcher::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { Component::BuildFromPage(stream, name_list, class_ID, object_ID); CString audio_component_name("audio_component"); PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); } // //############################################################################# //############################################################################# // Logical AudioIdleWatcher::TestInstance() const { Component::TestInstance(); Check(&audioComponentSocket); return True; } // //############################################################################# //############################################################################# // void AudioIdleWatcher::ReleaseLinkHandler( Socket *socket, Plug *plug ) { if (socket == &audioComponentSocket) { Check(&audioComponentSocket); Check(socket); Unregister_Object(this); delete this; } else { Component::ReleaseLinkHandler(socket, plug); } } // //############################################################################# //############################################################################# // void AudioIdleWatcher::Execute() { Check(this); Check(audioComponentSocket.GetCurrent()); audioComponentSocket.GetCurrent()->ReceiveControl( IdleAudioControlID, 0.0f ); } //############################################################################# //############################## AudioMotionTrigger ##################### //############################################################################# // //############################################################################# //############################################################################# // AudioMotionTrigger::AudioMotionTrigger( PlugStream *stream, Entity *entity ): AudioTriggerOf(stream, entity) { MemoryStream_Read(stream, &motionType); MemoryStream_Read(stream, &motionValue); PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioMotionTrigger::~AudioMotionTrigger() { } // //############################################################################# //############################################################################# // void AudioMotionTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); // // Store fields // MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_type); MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_value); } // //############################################################################# //############################################################################# // AudioControlValue AudioMotionTrigger::ExtractInterestingValue(const Motion *attribute_ptr) { Check(this); Check(attribute_ptr); switch (motionType) { case LinearMotionType: switch (motionValue) { case XMotionValue: return attribute_ptr->linearMotion.x; case YMotionValue: return attribute_ptr->linearMotion.y; case ZMotionValue: return attribute_ptr->linearMotion.z; case LengthMotionValue: return attribute_ptr->linearMotion.Length(); } break; case AngularMotionType: switch (motionValue) { case XMotionValue: return attribute_ptr->angularMotion.x; case YMotionValue: return attribute_ptr->angularMotion.y; case ZMotionValue: return attribute_ptr->angularMotion.z; case LengthMotionValue: return attribute_ptr->angularMotion.Length(); } break; } Fail("AudioMotionTrigger::ExtractInterestingValue - Should never reach here"); return 0.0f; } // //############################################################################# //############################################################################# // #if DEBUG_LEVEL>0 void AudioMotionTrigger::DumpValue(const Motion *attribute_ptr) #else void AudioMotionTrigger::DumpValue(const Motion*) #endif { Check(this); Check(attribute_ptr); switch (motionType) { case LinearMotionType: switch (motionValue) { case XMotionValue: Dump(attribute_ptr->linearMotion.x); break; case YMotionValue: Dump(attribute_ptr->linearMotion.y); break; case ZMotionValue: Dump(attribute_ptr->linearMotion.z); break; case LengthMotionValue: Dump(attribute_ptr->linearMotion.Length()); break; } break; case AngularMotionType: switch (motionValue) { case XMotionValue: Dump(attribute_ptr->angularMotion.x); break; case YMotionValue: Dump(attribute_ptr->angularMotion.y); break; case ZMotionValue: Dump(attribute_ptr->angularMotion.z); break; case LengthMotionValue: Dump(attribute_ptr->angularMotion.Length()); break; } break; } } //############################################################################# //############################## AudioMotionScale ####################### //############################################################################# // //############################################################################# //############################################################################# // AudioMotionScale::AudioMotionScale( PlugStream *stream, Entity *entity ): AudioScaleOf(stream, entity) { MemoryStream_Read(stream, &motionType); MemoryStream_Read(stream, &motionValue); PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioMotionScale::~AudioMotionScale() { } // //############################################################################# //############################################################################# // void AudioMotionScale::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioScaleOf::BuildFromPage(stream, name_list, class_ID, object_ID); // // Store fields // MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_type); MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_value); } // //############################################################################# //############################################################################# // AudioControlValue AudioMotionScale::ExtractInterestingValue(const Motion *attribute_ptr) { Check(this); Check(attribute_ptr); switch (motionType) { case LinearMotionType: switch (motionValue) { case XMotionValue: return attribute_ptr->linearMotion.x; case YMotionValue: return attribute_ptr->linearMotion.y; case ZMotionValue: return attribute_ptr->linearMotion.z; case LengthMotionValue: return attribute_ptr->linearMotion.Length(); } break; case AngularMotionType: switch (motionValue) { case XMotionValue: return attribute_ptr->angularMotion.x; case YMotionValue: return attribute_ptr->angularMotion.y; case ZMotionValue: return attribute_ptr->angularMotion.z; case LengthMotionValue: return attribute_ptr->angularMotion.Length(); } break; } Fail("AudioMotionScale::ExtractInterestingValue - Should never reach here"); return 0.0f; } // //############################################################################# //############################################################################# // #if DEBUG_LEVEL>0 void AudioMotionScale::DumpValue(const Motion *attribute_ptr) #else void AudioMotionScale::DumpValue(const Motion*) #endif { Check(this); Check(attribute_ptr); switch (motionType) { case LinearMotionType: switch (motionValue) { case XMotionValue: Dump(attribute_ptr->linearMotion.x); break; case YMotionValue: Dump(attribute_ptr->linearMotion.y); break; case ZMotionValue: Dump(attribute_ptr->linearMotion.z); break; case LengthMotionValue: Dump(attribute_ptr->linearMotion.Length()); break; } break; case AngularMotionType: switch (motionValue) { case XMotionValue: Dump(attribute_ptr->angularMotion.x); break; case YMotionValue: Dump(attribute_ptr->angularMotion.y); break; case ZMotionValue: Dump(attribute_ptr->angularMotion.z); break; case LengthMotionValue: Dump(attribute_ptr->angularMotion.Length()); break; } break; } } //############################################################################# //############################## AudioHingeScale ######################## //############################################################################# // //############################################################################# //############################################################################# // AudioHingeScale::AudioHingeScale( PlugStream *stream, Entity *entity ): AudioScaleOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioHingeScale::~AudioHingeScale() { } // //############################################################################# //############################################################################# // AudioControlValue AudioHingeScale::ExtractInterestingValue(const Hinge *attribute_ptr) { Check(this); Check(attribute_ptr); return attribute_ptr->rotationAmount; } // //############################################################################# //############################################################################# // #if DEBUG_LEVEL>0 void AudioHingeScale::DumpValue(const Hinge *attribute_ptr) #else void AudioHingeScale::DumpValue(const Hinge*) #endif { Check(this); Check(attribute_ptr); Dump(attribute_ptr->rotationAmount); } //############################################################################# //############################## AudioScalarTrigger ##################### //############################################################################# // //############################################################################# //############################################################################# // AudioScalarTrigger::AudioScalarTrigger( PlugStream *stream, Entity *entity ): AudioTriggerOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioScalarTrigger::~AudioScalarTrigger() { } // //############################################################################# //############################################################################# // void AudioScalarTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); } // //############################################################################# //############################################################################# // AudioControlValue AudioScalarTrigger::ExtractInterestingValue(const Scalar *attribute_ptr) { Check(this); Check_Pointer(attribute_ptr); return *attribute_ptr; } //############################################################################# //####################### AudioScalarDeltaTrigger ####################### //############################################################################# // //############################################################################# //############################################################################# // AudioScalarDeltaTrigger::AudioScalarDeltaTrigger( PlugStream *stream, Entity *entity ): AudioDeltaOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioScalarDeltaTrigger::~AudioScalarDeltaTrigger() { } // //############################################################################# //############################################################################# // void AudioScalarDeltaTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioDeltaOf::BuildFromPage(stream, name_list, class_ID, object_ID); } //############################################################################# //############################## AudioScalarScale ####################### //############################################################################# // //############################################################################# //############################################################################# // AudioScalarScale::AudioScalarScale( PlugStream *stream, Entity *entity ): AudioScaleOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioScalarScale::~AudioScalarScale() { } // //############################################################################# //############################################################################# // AudioControlValue AudioScalarScale::ExtractInterestingValue(const Scalar *attribute_ptr) { Check(this); Check_Pointer(attribute_ptr); return *attribute_ptr; } //############################################################################# //######################### AudioLogicalTrigger ######################### //############################################################################# // //############################################################################# //############################################################################# // AudioLogicalTrigger::AudioLogicalTrigger( PlugStream *stream, Entity *entity ): AudioMatchOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioLogicalTrigger::~AudioLogicalTrigger() { } // //############################################################################# //############################################################################# // void AudioLogicalTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioMatchOf::BuildFromPage(stream, name_list, class_ID, object_ID); } // //############################################################################# //############################################################################# // int AudioLogicalTrigger::ExtractInterestingValue(const Logical *attribute_ptr) { Check(this); Check_Pointer(attribute_ptr); return *attribute_ptr; } //############################################################################# //######################### AudioEnumerationTrigger ##################### //############################################################################# // //############################################################################# //############################################################################# // AudioEnumerationTrigger::AudioEnumerationTrigger( PlugStream *stream, Entity *entity ): AudioMatchOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioEnumerationTrigger::~AudioEnumerationTrigger() { } // //############################################################################# //############################################################################# // void AudioEnumerationTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioMatchOf::BuildFromPage(stream, name_list, class_ID, object_ID); } // //############################################################################# //############################################################################# // int AudioEnumerationTrigger::ExtractInterestingValue(const Enumeration *attribute_ptr) { Check(this); Check_Pointer(attribute_ptr); return *attribute_ptr; } //############################################################################# //###################### AudioEnumerationDeltaTrigger ################### //############################################################################# // //############################################################################# //############################################################################# // AudioEnumerationDeltaTrigger::AudioEnumerationDeltaTrigger( PlugStream *stream, Entity *entity ): AudioDeltaOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioEnumerationDeltaTrigger::~AudioEnumerationDeltaTrigger() { } // //############################################################################# //############################################################################# // void AudioEnumerationDeltaTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioDeltaOf::BuildFromPage( stream, name_list, class_ID, object_ID ); } //############################################################################# //############################# AudioIntegerTrigger ##################### //############################################################################# // //############################################################################# //############################################################################# // AudioIntegerTrigger::AudioIntegerTrigger( PlugStream *stream, Entity *entity ): AudioTriggerOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioIntegerTrigger::~AudioIntegerTrigger() { } // //############################################################################# //############################################################################# // void AudioIntegerTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); } // //############################################################################# //############################################################################# // AudioControlValue AudioIntegerTrigger::ExtractInterestingValue(const int *attribute_ptr) { Check(this); Check_Pointer(attribute_ptr); return *attribute_ptr; } //############################################################################# //###################### AudioControlsButtonTrigger ##################### //############################################################################# // //############################################################################# //############################################################################# // AudioControlsButtonTrigger::AudioControlsButtonTrigger( PlugStream *stream, Entity *entity ): AudioTriggerOf(stream, entity) { PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioControlsButtonTrigger::~AudioControlsButtonTrigger() { } // //############################################################################# //############################################################################# // void AudioControlsButtonTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioTriggerOf::BuildFromPage( stream, name_list, class_ID, object_ID ); } // //############################################################################# //############################################################################# // AudioControlValue AudioControlsButtonTrigger::ExtractInterestingValue( const ControlsButton *attribute_ptr ) { Check(this); Check_Pointer(attribute_ptr); return *attribute_ptr; } //############################################################################# //########################### AudioStateWatcher ######################### //############################################################################# // //############################################################################# //############################################################################# // AudioStateWatcher::AudioStateWatcher( PlugStream *stream, Entity *entity ): AudioWatcherOf(stream, entity) { Check_Pointer(attributePointer); // BRING-UP GUARD [T3, temporary]: an AudioStateWatcher binds to a StateIndicator // attribute BY NAME. The Mech's own state indicators (SimulationState, Animation/ // ReplicantAnimationState, CollisionState) are real; but audio also binds state // attrs on subsystems that are not fully reconstructed yet (GeneratorState, // CondenserState, Torso MotionState, ...). Those resolve to an unconstructed // object -- a null/garbage vtable at +0 or a debug-fill (0xCDCDCDCD) watcher chain // at +0x18 -- and AddAudioWatcher would AV in SChainOf::Add. Skip the register // (that subsystem's state audio stays silent) until the subsystem is built; this // is SELF-CLEARING (a real StateIndicator passes). See docs: audio subsystem wave. // Validate the AUDIO SOCKET at +0x18 (what AddAudioWatcher touches), NOT the // object's +0 vtable: a real StateIndicator has a vtable at +0, but the binary's // 0x54 subsystem alarm (GaugeAlarm54) is non-polymorphic there (a raw header) yet // has a real, constructed SChainOf socket at +0x18. A skip means the socket is // unconstructed (null / debug-fill 0xCDCDCDCD) -- the inert pad or a subsystem not // yet reconstructed. Registering there would AV in SChainOf::Add. { unsigned chain = *(unsigned*)((char*)attributePointer + 0x18); if (chain == 0 || chain == 0xCDCDCDCD) { if (getenv("BT_AUDIO_LOG")) DEBUG_STREAM << "[audiostate] skip watcher on unbuilt StateIndicator " << attributePointer << " (chain=" << (void*)chain << ")\n" << std::flush; return; } } Cast_Object(StateIndicator*, attributePointer)->AddAudioWatcher(this); } // //############################################################################# //############################################################################# // AudioStateWatcher::~AudioStateWatcher() { } // //############################################################################# //############################################################################# // void AudioStateWatcher::SendNotificationOfChange() { Check(this); StateIndicator *state_indicator = GetCurrentPointer(); Check(state_indicator); StateChanged( state_indicator->GetOldState(), state_indicator->GetState() ); } // //############################################################################# //############################################################################# // void AudioStateWatcher::StateChanged( Enumeration, Enumeration ) { Fail("AudioStateWatcher::StateChanged - Should never reach here"); } //############################################################################# //############################## AudioStateTrigger ###################### //############################################################################# // //############################################################################# //############################################################################# // AudioStateTrigger::AudioStateTrigger( PlugStream *stream, Entity *entity ): AudioStateWatcher(stream, entity) { MemoryStream_Read(stream, &triggerState); MemoryStream_Read(stream, &inverseTrigger); MemoryStream_Read(stream, &controlID); MemoryStream_Read(stream, &controlValue); MemoryStream_Read(stream, &excludeTransition); MemoryStream_Read(stream, &excludeState); if (getenv("BT_ATTRBIND_LOG")) { static int s_stc=0; if (s_stc++<120) DEBUG_STREAM << "[statecfg] attrPtr=" << (void*)attributePointer << " comp=" << (void*)audioComponentSocket.GetCurrent() << " trigState=" << triggerState << " inv=" << (int)inverseTrigger << " ctl=" << (int)controlID << "/" << controlValue << " excl=" << (int)excludeTransition << "/" << excludeState << "\n" << std::flush; } PrimeWatcher(); } // //############################################################################# //############################################################################# // AudioStateTrigger::~AudioStateTrigger() { } // //############################################################################# //############################################################################# // void AudioStateTrigger::BuildFromPage( PlugStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID ) { AudioStateWatcher::BuildFromPage(stream, name_list, class_ID, object_ID); // // Write standard fields // MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, trigger_state); MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, inverse_trigger); MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value); // // Write optional fields // Logical exclude_transition = False; Enumeration exclude_state = 0; if ((name_list)->FindData("exclude_state") != NULL) { exclude_transition = True; Check_Pointer((name_list)->FindData("exclude_state")); Convert_From_Ascii( (const char *)(name_list)->FindData("exclude_state"), &exclude_state ); } MemoryStream_Write(stream, &exclude_transition); MemoryStream_Write(stream, &exclude_state); } // //############################################################################# //############################################################################# // void AudioStateTrigger::StateChanged( Enumeration old_state, Enumeration new_state ) { Check(this); // // If the exclude switch is on then check for the transition // if (excludeTransition) { if ( !inverseTrigger && new_state == triggerState && old_state == excludeState ) { return; } if ( inverseTrigger && old_state == triggerState && new_state == excludeState ) { return; } } // // Check for the trigger state // if ( (!inverseTrigger && new_state == triggerState) || (inverseTrigger && old_state == triggerState) ) { Check(&audioComponentSocket); Check(audioComponentSocket.GetCurrent()); #if 1 audioComponentSocket.GetCurrent()->ReceiveControl( controlID, controlValue ); #else audioComponentSocket.GetCurrent()->PostReceiveControl( controlID, controlValue ); #endif } }