@tool class_name RoomSimulator extends Node signal device_state_changed( device_id: StringName, active: bool ) signal binding_activated( cabinet_id: StringName, action_id: StringName, device_id: StringName ) signal binding_deactivated( cabinet_id: StringName, action_id: StringName, device_id: StringName ) signal path_activated( path_id: StringName, cabinet_id: StringName, event_id: StringName, action_id: StringName, device_id: StringName ) signal path_deactivated( path_id: StringName, cabinet_id: StringName, event_id: StringName, action_id: StringName, device_id: StringName ) var room: RoomDefinition var device_states: Dictionary = {} func configure( room_definition: RoomDefinition ) -> void: room = room_definition device_states.clear() if room == null: push_error( "RoomSimulator received a null RoomDefinition." ) return for device in room.devices: if device == null: continue device_states[ device.device_id ] = device.initial_active if not Engine.is_editor_hint(): _connect_hardware_manager() print("") print("======= ROOM SIMULATOR =======") print("Room: ", room.display_name) print("Devices: ", room.devices.size()) print("==============================") print("") func _connect_hardware_manager() -> void: if not HardwareManager.action_activated.is_connected( _on_hardware_action_activated ): HardwareManager.action_activated.connect( _on_hardware_action_activated ) if not HardwareManager.action_deactivated.is_connected( _on_hardware_action_deactivated ): HardwareManager.action_deactivated.connect( _on_hardware_action_deactivated ) func reset() -> void: if room == null: return for device in room.devices: if device == null: continue _set_device_state( device.device_id, device.initial_active ) func get_device_state( device_id: StringName ) -> bool: return device_states.get( device_id, false ) # # Runtime HardwareManager entry points # func _on_hardware_action_activated( cabinet_id: StringName, action_id: StringName, context: Dictionary ) -> void: _process_action_activated( cabinet_id, action_id, context ) func _on_hardware_action_deactivated( cabinet_id: StringName, action_id: StringName, context: Dictionary ) -> void: _process_action_deactivated( cabinet_id, action_id, context ) # # Editor simulation entry points # func simulate_action_activated( cabinet_id: StringName, action_id: StringName, context: Dictionary = {} ) -> void: _process_action_activated( cabinet_id, action_id, context ) func simulate_action_deactivated( cabinet_id: StringName, action_id: StringName, context: Dictionary = {} ) -> void: _process_action_deactivated( cabinet_id, action_id, context ) # # Shared processing # func _process_action_activated( cabinet_id: StringName, action_id: StringName, context: Dictionary ) -> void: if room == null: return var device := room.get_device_for_action( cabinet_id, action_id ) if device == null: print( "[SIMULATION] No room device bound to %s:%s" % [ cabinet_id, action_id ] ) return var event_id := StringName( context.get( "game_event", "unknown_event" ) ) var path_id := LogicPathId.make( cabinet_id, event_id, action_id, device.device_id ) path_activated.emit( path_id, cabinet_id, event_id, action_id, device.device_id ) binding_activated.emit( cabinet_id, action_id, device.device_id ) _set_device_state( device.device_id, true ) func _process_action_deactivated( cabinet_id: StringName, action_id: StringName, context: Dictionary ) -> void: if room == null: return var device := room.get_device_for_action( cabinet_id, action_id ) if device == null: return var event_id := StringName( context.get( "game_event", "unknown_event" ) ) var path_id := LogicPathId.make( cabinet_id, event_id, action_id, device.device_id ) path_deactivated.emit( path_id, cabinet_id, event_id, action_id, device.device_id ) binding_deactivated.emit( cabinet_id, action_id, device.device_id ) if ( device.behavior == RoomDeviceDefinition.Behavior.MOMENTARY ): _set_device_state( device.device_id, false ) func _set_device_state( device_id: StringName, active: bool ) -> void: device_states[ device_id ] = active print( "[SIMULATION] Device '%s' -> %s" % [ device_id, "ACTIVE" if active else "INACTIVE" ] ) device_state_changed.emit( device_id, active )