Added Glitch Room Source code to Gitty
This commit is contained in:
commit
1ac9eb5644
505 files changed
+28504
No files matched your search
@@ -0,0 +1,983 @@
|
||||
@tool
|
||||
class_name EditorSimulationDriver
|
||||
extends RefCounted
|
||||
|
||||
|
||||
signal action_activated(
|
||||
cabinet_id: StringName,
|
||||
action_id: StringName,
|
||||
context: Dictionary
|
||||
)
|
||||
|
||||
signal action_deactivated(
|
||||
cabinet_id: StringName,
|
||||
action_id: StringName,
|
||||
context: Dictionary
|
||||
)
|
||||
|
||||
signal device_state_changed(
|
||||
device_id: StringName,
|
||||
active: bool
|
||||
)
|
||||
|
||||
signal trace_entry_created(
|
||||
entry: Dictionary
|
||||
)
|
||||
|
||||
signal sequence_started(
|
||||
sequence: TestSequence
|
||||
)
|
||||
|
||||
signal sequence_finished(
|
||||
sequence: TestSequence
|
||||
)
|
||||
|
||||
signal sequence_stopped
|
||||
|
||||
var sequence_settling: bool = false
|
||||
var room: RoomDefinition
|
||||
var scenario: ScenarioDefinition
|
||||
var logic_engine: RoomLogicEngine
|
||||
var simulated_device_states: Dictionary = {}
|
||||
var hardware_backend: SimulatedHardwareBackend
|
||||
|
||||
var pending_hardware_deactivations: Array[Dictionary] = []
|
||||
|
||||
var paused: bool = false
|
||||
|
||||
var active_sequence: TestSequence = null
|
||||
|
||||
var sequence_start_time: float = 0.0
|
||||
|
||||
var pending_sequence_steps: Array[Dictionary] = []
|
||||
|
||||
var sequence_running: bool = false
|
||||
|
||||
func start_sequence(
|
||||
sequence: TestSequence
|
||||
) -> void:
|
||||
|
||||
if sequence == null:
|
||||
return
|
||||
|
||||
#
|
||||
# Starting a rehearsal means starting from
|
||||
# a clean simulated-room state.
|
||||
#
|
||||
reset_simulation()
|
||||
|
||||
active_sequence = sequence
|
||||
|
||||
sequence_start_time = (
|
||||
_get_simulation_time()
|
||||
)
|
||||
|
||||
pending_sequence_steps.clear()
|
||||
|
||||
for step in sequence.get_sorted_steps():
|
||||
|
||||
pending_sequence_steps.append(
|
||||
{
|
||||
"execute_at": (
|
||||
sequence_start_time
|
||||
+ step.time_offset_seconds
|
||||
),
|
||||
|
||||
"step": step,
|
||||
}
|
||||
)
|
||||
|
||||
sequence_running = true
|
||||
sequence_settling = false
|
||||
|
||||
trace_entry_created.emit(
|
||||
{
|
||||
"type": &"sequence",
|
||||
"time": _get_simulation_time(),
|
||||
"sequence_id": sequence.sequence_id,
|
||||
"display_name": sequence.display_name,
|
||||
"state": &"started",
|
||||
}
|
||||
)
|
||||
|
||||
sequence_started.emit(
|
||||
sequence
|
||||
)
|
||||
|
||||
#
|
||||
# Execute all steps authored at 0.0 immediately.
|
||||
#
|
||||
_process_pending_sequence_steps()
|
||||
|
||||
|
||||
func advance(
|
||||
delta_seconds: float
|
||||
) -> void:
|
||||
|
||||
if paused:
|
||||
return
|
||||
|
||||
_advance_internal(
|
||||
delta_seconds
|
||||
)
|
||||
|
||||
func configure(
|
||||
room_definition: RoomDefinition,
|
||||
scenario_definition: ScenarioDefinition
|
||||
) -> void:
|
||||
|
||||
room = room_definition
|
||||
scenario = scenario_definition
|
||||
|
||||
pending_hardware_deactivations.clear()
|
||||
simulated_device_states.clear()
|
||||
|
||||
logic_engine = RoomLogicEngine.new()
|
||||
|
||||
logic_engine.configure(
|
||||
room_definition
|
||||
)
|
||||
|
||||
logic_engine.action_requested.connect(
|
||||
_on_logic_action_requested
|
||||
)
|
||||
|
||||
logic_engine.trace_entry_created.connect(
|
||||
_on_logic_trace_entry_created
|
||||
)
|
||||
|
||||
hardware_backend = SimulatedHardwareBackend.new()
|
||||
|
||||
hardware_backend.pin_state_changed.connect(
|
||||
_on_simulated_pin_state_changed
|
||||
)
|
||||
|
||||
hardware_backend.trace_entry_created.connect(
|
||||
_on_hardware_trace_entry_created
|
||||
)
|
||||
|
||||
func simulate_game_event(
|
||||
cabinet_id: StringName,
|
||||
event_id: StringName
|
||||
) -> void:
|
||||
|
||||
if scenario == null:
|
||||
push_error(
|
||||
"EditorSimulationDriver has no scenario."
|
||||
)
|
||||
return
|
||||
|
||||
var assignment := (
|
||||
scenario.get_assignment_for_cabinet(
|
||||
cabinet_id
|
||||
)
|
||||
)
|
||||
|
||||
if assignment == null:
|
||||
push_error(
|
||||
"No scenario assignment exists for cabinet '%s'."
|
||||
% cabinet_id
|
||||
)
|
||||
return
|
||||
|
||||
#
|
||||
# Feed the event into the room-level logic engine.
|
||||
#
|
||||
emit_room_event(
|
||||
cabinet_id,
|
||||
event_id
|
||||
)
|
||||
|
||||
#
|
||||
# Preserve the existing scenario mapping:
|
||||
#
|
||||
# game event
|
||||
# -> cabinet hardware action
|
||||
#
|
||||
var actions := (
|
||||
assignment.get_actions_for_event(
|
||||
event_id
|
||||
)
|
||||
)
|
||||
|
||||
for action_id in actions:
|
||||
|
||||
_activate_action(
|
||||
cabinet_id,
|
||||
action_id,
|
||||
{
|
||||
"game_event": event_id
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
func _activate_action(
|
||||
cabinet_id: StringName,
|
||||
action_id: StringName,
|
||||
context: Dictionary
|
||||
) -> void:
|
||||
|
||||
if room == null:
|
||||
return
|
||||
|
||||
var assignment := (
|
||||
scenario.get_assignment_for_cabinet(
|
||||
cabinet_id
|
||||
)
|
||||
)
|
||||
|
||||
if assignment == null:
|
||||
return
|
||||
|
||||
if assignment.cabinet == null:
|
||||
return
|
||||
|
||||
if assignment.cabinet.hardware_config == null:
|
||||
return
|
||||
|
||||
var action := (
|
||||
assignment.cabinet.hardware_config.get_action(
|
||||
action_id
|
||||
)
|
||||
)
|
||||
|
||||
if action == null:
|
||||
push_error(
|
||||
"Editor simulation could not find hardware action '%s' on cabinet '%s'."
|
||||
% [
|
||||
action_id,
|
||||
cabinet_id
|
||||
]
|
||||
)
|
||||
return
|
||||
|
||||
action_activated.emit(
|
||||
cabinet_id,
|
||||
action_id,
|
||||
context
|
||||
)
|
||||
|
||||
hardware_backend.activate_action(
|
||||
cabinet_id,
|
||||
action,
|
||||
context
|
||||
)
|
||||
|
||||
match action.action_type:
|
||||
HardwareAction.ActionType.PULSE_OUTPUT:
|
||||
_schedule_deactivation(
|
||||
cabinet_id,
|
||||
action_id,
|
||||
context,
|
||||
action.pulse_duration_ms
|
||||
)
|
||||
|
||||
HardwareAction.ActionType.DIGITAL_OUTPUT:
|
||||
#
|
||||
# For now, treat a digital output as latched.
|
||||
# We'll add explicit ON/OFF editing later.
|
||||
#
|
||||
pass
|
||||
|
||||
|
||||
func _schedule_deactivation(
|
||||
cabinet_id: StringName,
|
||||
action_id: StringName,
|
||||
context: Dictionary,
|
||||
duration_ms: int
|
||||
) -> void:
|
||||
|
||||
var duration_seconds := (
|
||||
float(duration_ms)
|
||||
/ 1000.0
|
||||
)
|
||||
|
||||
pending_hardware_deactivations.append(
|
||||
{
|
||||
"execute_at": (
|
||||
_get_simulation_time()
|
||||
+ duration_seconds
|
||||
),
|
||||
|
||||
"cabinet_id": cabinet_id,
|
||||
"action_id": action_id,
|
||||
"context": context.duplicate(),
|
||||
}
|
||||
)
|
||||
|
||||
func _get_simulation_time() -> float:
|
||||
|
||||
if logic_engine == null:
|
||||
return 0.0
|
||||
|
||||
return logic_engine.get_simulation_time()
|
||||
|
||||
func emit_room_event(
|
||||
source_id: StringName,
|
||||
event_id: StringName
|
||||
) -> void:
|
||||
|
||||
if logic_engine == null:
|
||||
return
|
||||
|
||||
logic_engine.emit_event(
|
||||
source_id,
|
||||
event_id
|
||||
)
|
||||
|
||||
func _on_logic_action_requested(
|
||||
target_id: StringName,
|
||||
action_id: StringName,
|
||||
rule_id: StringName
|
||||
) -> void:
|
||||
|
||||
if room == null:
|
||||
return
|
||||
|
||||
#
|
||||
# First: direct room-device action.
|
||||
#
|
||||
var device := room.get_device(
|
||||
target_id
|
||||
)
|
||||
|
||||
if device != null:
|
||||
|
||||
_apply_device_action(
|
||||
device,
|
||||
action_id,
|
||||
rule_id
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
#
|
||||
# Second: cabinet hardware action.
|
||||
#
|
||||
var assignment := (
|
||||
scenario.get_assignment_for_cabinet(
|
||||
target_id
|
||||
)
|
||||
)
|
||||
|
||||
if assignment != null:
|
||||
|
||||
_activate_action(
|
||||
target_id,
|
||||
action_id,
|
||||
{
|
||||
"logic_rule": rule_id
|
||||
}
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
print(
|
||||
"[SIM] Unhandled logic action: ",
|
||||
target_id,
|
||||
".",
|
||||
action_id
|
||||
)
|
||||
|
||||
func _apply_device_action(
|
||||
device: RoomDeviceDefinition,
|
||||
action_id: StringName,
|
||||
_rule_id: StringName
|
||||
) -> void:
|
||||
|
||||
match action_id:
|
||||
|
||||
&"activate":
|
||||
_set_device_active(
|
||||
device.device_id,
|
||||
true
|
||||
)
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"activated"
|
||||
)
|
||||
|
||||
&"deactivate":
|
||||
_set_device_active(
|
||||
device.device_id,
|
||||
false
|
||||
)
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"deactivated"
|
||||
)
|
||||
|
||||
&"turn_on":
|
||||
_set_device_active(
|
||||
device.device_id,
|
||||
true
|
||||
)
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"turned_on"
|
||||
)
|
||||
|
||||
&"turn_off":
|
||||
_set_device_active(
|
||||
device.device_id,
|
||||
false
|
||||
)
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"turned_off"
|
||||
)
|
||||
|
||||
&"unlock":
|
||||
_set_device_active(
|
||||
device.device_id,
|
||||
true
|
||||
)
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"unlocked"
|
||||
)
|
||||
|
||||
&"lock":
|
||||
_set_device_active(
|
||||
device.device_id,
|
||||
false
|
||||
)
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"locked"
|
||||
)
|
||||
|
||||
_:
|
||||
print(
|
||||
"[SIM] Unsupported device action: ",
|
||||
device.device_id,
|
||||
".",
|
||||
action_id
|
||||
)
|
||||
|
||||
func _set_device_active(
|
||||
device_id: StringName,
|
||||
active: bool
|
||||
) -> void:
|
||||
|
||||
var previous_active := bool(
|
||||
simulated_device_states.get(
|
||||
device_id,
|
||||
false
|
||||
)
|
||||
)
|
||||
|
||||
simulated_device_states[
|
||||
device_id
|
||||
] = active
|
||||
|
||||
device_state_changed.emit(
|
||||
device_id,
|
||||
active
|
||||
)
|
||||
|
||||
#
|
||||
# Record the simulated physical-state transition.
|
||||
#
|
||||
if previous_active != active:
|
||||
|
||||
trace_entry_created.emit(
|
||||
{
|
||||
"type": &"device",
|
||||
"time": _get_simulation_time(),
|
||||
"device_id": device_id,
|
||||
"active": active,
|
||||
}
|
||||
)
|
||||
|
||||
func _emit_device_event(
|
||||
device_id: StringName,
|
||||
event_id: StringName
|
||||
) -> void:
|
||||
|
||||
if logic_engine == null:
|
||||
return
|
||||
|
||||
logic_engine.emit_event(
|
||||
device_id,
|
||||
event_id
|
||||
)
|
||||
|
||||
func _on_logic_trace_entry_created(
|
||||
entry: Dictionary
|
||||
) -> void:
|
||||
|
||||
var timed_entry := (
|
||||
entry.duplicate(true)
|
||||
)
|
||||
|
||||
timed_entry["time"] = (
|
||||
_get_simulation_time()
|
||||
)
|
||||
|
||||
print(
|
||||
"[SIM TRACE] ",
|
||||
timed_entry
|
||||
)
|
||||
|
||||
trace_entry_created.emit(
|
||||
timed_entry
|
||||
)
|
||||
|
||||
func _propagate_hardware_action_to_devices(
|
||||
cabinet_id: StringName,
|
||||
action_id: StringName,
|
||||
active: bool,
|
||||
context: Dictionary
|
||||
) -> void:
|
||||
|
||||
if room == null:
|
||||
return
|
||||
|
||||
for binding in room.bindings:
|
||||
|
||||
if binding == null:
|
||||
continue
|
||||
|
||||
if binding.cabinet_id != cabinet_id:
|
||||
continue
|
||||
|
||||
if binding.hardware_action_id != action_id:
|
||||
continue
|
||||
|
||||
var device := room.get_device(
|
||||
binding.device_id
|
||||
)
|
||||
|
||||
if device == null:
|
||||
continue
|
||||
|
||||
_set_device_active(
|
||||
device.device_id,
|
||||
active
|
||||
)
|
||||
|
||||
print(
|
||||
"[SIM DEVICE PATH] ",
|
||||
cabinet_id,
|
||||
".",
|
||||
action_id,
|
||||
" -> ",
|
||||
device.device_id,
|
||||
" active=",
|
||||
active,
|
||||
" context=",
|
||||
context
|
||||
)
|
||||
|
||||
if active:
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"activated"
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
_emit_device_event(
|
||||
device.device_id,
|
||||
&"deactivated"
|
||||
)
|
||||
|
||||
func _on_simulated_pin_state_changed(
|
||||
cabinet_id: StringName,
|
||||
_gpio_pin: int,
|
||||
active: bool,
|
||||
action_id: StringName,
|
||||
context: Dictionary
|
||||
) -> void:
|
||||
|
||||
_propagate_hardware_action_to_devices(
|
||||
cabinet_id,
|
||||
action_id,
|
||||
active,
|
||||
context
|
||||
)
|
||||
|
||||
func _on_hardware_trace_entry_created(
|
||||
entry: Dictionary
|
||||
) -> void:
|
||||
|
||||
var timed_entry := (
|
||||
entry.duplicate(true)
|
||||
)
|
||||
|
||||
timed_entry["time"] = (
|
||||
_get_simulation_time()
|
||||
)
|
||||
|
||||
print(
|
||||
"[GPIO SIM] ",
|
||||
timed_entry
|
||||
)
|
||||
|
||||
trace_entry_created.emit(
|
||||
timed_entry
|
||||
)
|
||||
|
||||
func _process_pending_hardware_deactivations() -> void:
|
||||
|
||||
if pending_hardware_deactivations.is_empty():
|
||||
return
|
||||
|
||||
var ready: Array[Dictionary] = []
|
||||
var remaining: Array[Dictionary] = []
|
||||
|
||||
for pending in pending_hardware_deactivations:
|
||||
|
||||
var execute_at: float = (
|
||||
pending.get(
|
||||
"execute_at",
|
||||
0.0
|
||||
)
|
||||
)
|
||||
|
||||
if execute_at <= _get_simulation_time():
|
||||
ready.append(
|
||||
pending
|
||||
)
|
||||
else:
|
||||
remaining.append(
|
||||
pending
|
||||
)
|
||||
|
||||
pending_hardware_deactivations = remaining
|
||||
|
||||
for pending in ready:
|
||||
|
||||
_deactivate_hardware_action(
|
||||
pending.get(
|
||||
"cabinet_id",
|
||||
&""
|
||||
),
|
||||
|
||||
pending.get(
|
||||
"action_id",
|
||||
&""
|
||||
),
|
||||
|
||||
pending.get(
|
||||
"context",
|
||||
{}
|
||||
)
|
||||
)
|
||||
|
||||
func _deactivate_hardware_action(
|
||||
cabinet_id: StringName,
|
||||
action_id: StringName,
|
||||
context: Dictionary
|
||||
) -> void:
|
||||
|
||||
if scenario == null:
|
||||
return
|
||||
|
||||
var assignment := (
|
||||
scenario.get_assignment_for_cabinet(
|
||||
cabinet_id
|
||||
)
|
||||
)
|
||||
|
||||
if assignment == null:
|
||||
return
|
||||
|
||||
if assignment.cabinet == null:
|
||||
return
|
||||
|
||||
if assignment.cabinet.hardware_config == null:
|
||||
return
|
||||
|
||||
var action := (
|
||||
assignment.cabinet.hardware_config.get_action(
|
||||
action_id
|
||||
)
|
||||
)
|
||||
|
||||
if action == null:
|
||||
return
|
||||
|
||||
action_deactivated.emit(
|
||||
cabinet_id,
|
||||
action_id,
|
||||
context
|
||||
)
|
||||
|
||||
if hardware_backend != null:
|
||||
|
||||
hardware_backend.deactivate_action(
|
||||
cabinet_id,
|
||||
action,
|
||||
context
|
||||
)
|
||||
|
||||
func set_paused(
|
||||
value: bool
|
||||
) -> void:
|
||||
|
||||
paused = value
|
||||
|
||||
|
||||
func is_paused() -> bool:
|
||||
|
||||
return paused
|
||||
|
||||
|
||||
func step(
|
||||
delta_seconds: float
|
||||
) -> void:
|
||||
|
||||
if delta_seconds <= 0.0:
|
||||
return
|
||||
|
||||
_advance_internal(
|
||||
delta_seconds
|
||||
)
|
||||
|
||||
|
||||
func reset_simulation() -> void:
|
||||
|
||||
pending_sequence_steps.clear()
|
||||
|
||||
active_sequence = null
|
||||
sequence_running = false
|
||||
sequence_start_time = 0.0
|
||||
sequence_settling = false
|
||||
|
||||
pending_hardware_deactivations.clear()
|
||||
simulated_device_states.clear()
|
||||
|
||||
if logic_engine != null:
|
||||
logic_engine.reset()
|
||||
|
||||
if hardware_backend != null:
|
||||
hardware_backend.reset()
|
||||
|
||||
paused = false
|
||||
|
||||
func _advance_internal(
|
||||
delta_seconds: float
|
||||
) -> void:
|
||||
|
||||
if delta_seconds <= 0.0:
|
||||
return
|
||||
|
||||
if logic_engine == null:
|
||||
return
|
||||
|
||||
logic_engine.advance(
|
||||
delta_seconds
|
||||
)
|
||||
|
||||
_process_pending_sequence_steps()
|
||||
|
||||
_process_pending_hardware_deactivations()
|
||||
|
||||
_finish_sequence_if_ready()
|
||||
|
||||
func _process_pending_sequence_steps() -> void:
|
||||
|
||||
if not sequence_running:
|
||||
return
|
||||
|
||||
if pending_sequence_steps.is_empty():
|
||||
|
||||
_finish_sequence_if_ready()
|
||||
|
||||
return
|
||||
|
||||
_finish_sequence_if_ready()
|
||||
|
||||
var current_time := (
|
||||
_get_simulation_time()
|
||||
)
|
||||
|
||||
var ready: Array[Dictionary] = []
|
||||
var remaining: Array[Dictionary] = []
|
||||
|
||||
for pending in pending_sequence_steps:
|
||||
|
||||
var execute_at := float(
|
||||
pending.get(
|
||||
"execute_at",
|
||||
0.0
|
||||
)
|
||||
)
|
||||
|
||||
if execute_at <= current_time:
|
||||
|
||||
ready.append(
|
||||
pending
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
remaining.append(
|
||||
pending
|
||||
)
|
||||
|
||||
pending_sequence_steps = remaining
|
||||
|
||||
for pending in ready:
|
||||
|
||||
var step := (
|
||||
pending.get(
|
||||
"step"
|
||||
)
|
||||
as TestSequenceStep
|
||||
)
|
||||
|
||||
if step == null:
|
||||
continue
|
||||
|
||||
_execute_sequence_step(
|
||||
step
|
||||
)
|
||||
|
||||
_finish_sequence_if_ready()
|
||||
|
||||
func _execute_sequence_step(
|
||||
step: TestSequenceStep
|
||||
) -> void:
|
||||
|
||||
trace_entry_created.emit(
|
||||
{
|
||||
"type": &"input",
|
||||
"time": _get_simulation_time(),
|
||||
"source_id": step.source_id,
|
||||
"event_id": step.event_id,
|
||||
"note": step.note,
|
||||
}
|
||||
)
|
||||
|
||||
#
|
||||
# If the source is a scenario cabinet, this is a
|
||||
# game/cabinet event and must travel through the
|
||||
# existing scenario mapping as well as room logic.
|
||||
#
|
||||
if scenario != null:
|
||||
|
||||
var assignment := (
|
||||
scenario.get_assignment_for_cabinet(
|
||||
step.source_id
|
||||
)
|
||||
)
|
||||
|
||||
if assignment != null:
|
||||
|
||||
simulate_game_event(
|
||||
step.source_id,
|
||||
step.event_id
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
#
|
||||
# Otherwise this is a generic room/world input.
|
||||
#
|
||||
emit_room_event(
|
||||
step.source_id,
|
||||
step.event_id
|
||||
)
|
||||
|
||||
func _finish_sequence_if_ready() -> void:
|
||||
|
||||
if not sequence_running:
|
||||
return
|
||||
|
||||
#
|
||||
# Still waiting to inject authored inputs.
|
||||
#
|
||||
if not pending_sequence_steps.is_empty():
|
||||
return
|
||||
|
||||
#
|
||||
# All authored inputs have been injected.
|
||||
# Enter settling state once.
|
||||
#
|
||||
if not sequence_settling:
|
||||
|
||||
sequence_settling = true
|
||||
|
||||
if active_sequence != null:
|
||||
|
||||
trace_entry_created.emit(
|
||||
{
|
||||
"type": &"sequence",
|
||||
"time": _get_simulation_time(),
|
||||
"sequence_id": active_sequence.sequence_id,
|
||||
"display_name": active_sequence.display_name,
|
||||
"state": &"settling",
|
||||
}
|
||||
)
|
||||
|
||||
#
|
||||
# Room logic still has delayed work.
|
||||
#
|
||||
if (
|
||||
logic_engine != null
|
||||
and logic_engine.has_pending_actions()
|
||||
):
|
||||
return
|
||||
|
||||
#
|
||||
# Hardware pulses are still active.
|
||||
#
|
||||
if not pending_hardware_deactivations.is_empty():
|
||||
return
|
||||
|
||||
#
|
||||
# Everything has settled.
|
||||
#
|
||||
var completed_sequence := active_sequence
|
||||
|
||||
sequence_running = false
|
||||
sequence_settling = false
|
||||
active_sequence = null
|
||||
|
||||
if completed_sequence == null:
|
||||
return
|
||||
|
||||
trace_entry_created.emit(
|
||||
{
|
||||
"type": &"sequence",
|
||||
"time": _get_simulation_time(),
|
||||
"sequence_id": completed_sequence.sequence_id,
|
||||
"display_name": completed_sequence.display_name,
|
||||
"state": &"finished",
|
||||
}
|
||||
)
|
||||
|
||||
sequence_finished.emit(
|
||||
completed_sequence
|
||||
)
|
||||
|
||||
func stop_sequence() -> void:
|
||||
|
||||
if not sequence_running:
|
||||
return
|
||||
|
||||
pending_sequence_steps.clear()
|
||||
|
||||
sequence_running = false
|
||||
sequence_settling = false
|
||||
active_sequence = null
|
||||
|
||||
trace_entry_created.emit(
|
||||
{
|
||||
"type": &"sequence",
|
||||
"time": _get_simulation_time(),
|
||||
"state": &"stopped",
|
||||
}
|
||||
)
|
||||
|
||||
sequence_stopped.emit()
|
||||
Reference in new issue
Block a user