mirror of
https://github.com/tonytins/citylimits
synced 2025-12-17 13:34:43 -05:00
Major clean up and reorganization
- Upgraded to Godot 4 - Just remembered the basic principles are based on a tile editor, and dramatically simplified from there. Derp. - New state machine and license display add-ons. - Re-licensed under the GPL because Micropolis' assets aren't under a separate one.
This commit is contained in:
parent
55ed76c914
commit
c980445340
337 changed files with 5129 additions and 7661 deletions
139
addons/simple-state/classes/debugger.gd
Normal file
139
addons/simple-state/classes/debugger.gd
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
@icon("../icons/state_machine_debugger.png")
|
||||
class_name StateMachineDebugger
|
||||
extends Tree
|
||||
|
||||
|
||||
## Displays an interactive state tree.
|
||||
# This source code is a mess, I'm trying to make it less so.
|
||||
|
||||
|
||||
@export
|
||||
## Root state machine to reference.
|
||||
var state_machine_root : State:
|
||||
set(value):
|
||||
state_machine_root = value
|
||||
_setup_tree()
|
||||
|
||||
@export
|
||||
## What color to make the item when a state is active.
|
||||
var active_color := Color.FOREST_GREEN
|
||||
|
||||
@export
|
||||
## Forcefully switch states by double-clicking them.
|
||||
## Due to its nature, it has the potential to be destructive
|
||||
## and/ or not behave completely how one might expect.
|
||||
var allow_state_switching := false:
|
||||
set(value):
|
||||
allow_state_switching = value
|
||||
if allow_state_switching:
|
||||
item_activated.connect(_on_item_activated)
|
||||
else:
|
||||
item_activated.disconnect(_on_item_activated)
|
||||
|
||||
|
||||
@export_group("Signals", "signal_")
|
||||
@export
|
||||
## Show when a state emits a relevant signal.
|
||||
var signal_show := false:
|
||||
set(value):
|
||||
signal_show = value
|
||||
|
||||
if state_machine_root == null:
|
||||
return
|
||||
|
||||
if signal_show:
|
||||
connect_signals()
|
||||
else:
|
||||
disconnect_signals()
|
||||
|
||||
@export
|
||||
## Which signals to connect to on each state, as long as they exist.
|
||||
var signal_connections : Array[StringName] = [
|
||||
&"entered",
|
||||
&"exited",
|
||||
&"choose_new_substate_requested",
|
||||
&"animation_finished",
|
||||
]
|
||||
|
||||
@export
|
||||
## Delay before hiding signal.
|
||||
var signal_hide_delay := 1.0
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
columns = 2
|
||||
|
||||
|
||||
func change_state_by_path(path: NodePath) -> void:
|
||||
if not state_machine_root.has_node(path):
|
||||
return
|
||||
var state := state_machine_root
|
||||
for i in path.get_name_count():
|
||||
var part := path.get_name(i)
|
||||
state = await state.change_state_name(part)
|
||||
|
||||
|
||||
func connect_signals(state := state_machine_root) -> void:
|
||||
if not state.has_meta(&"tree_item"):
|
||||
return
|
||||
for signal_name in signal_connections:
|
||||
if state.has_signal(signal_name) and not \
|
||||
state.is_connected(signal_name, _on_state_signal):
|
||||
state.connect(signal_name, _on_state_signal.bind(signal_name, state.get_meta(&"tree_item")))
|
||||
for child in(state.get_children() as Array[State]):
|
||||
connect_signals(child)
|
||||
|
||||
|
||||
func disconnect_signals(state := state_machine_root) -> void:
|
||||
for signal_name in signal_connections:
|
||||
if state.has_signal(signal_name) and \
|
||||
state.is_connected(signal_name, _on_state_signal):
|
||||
state.disconnect(signal_name, _on_state_signal)
|
||||
for child in (state.get_children() as Array[State]):
|
||||
disconnect_signals(child)
|
||||
|
||||
|
||||
func _setup_tree(state := state_machine_root, parent_item: TreeItem = null) -> void:
|
||||
if state == state_machine_root:
|
||||
if get_root() != null:
|
||||
disconnect_signals()
|
||||
clear()
|
||||
if state_machine_root == null:
|
||||
return
|
||||
# state.print_tree_pretty()
|
||||
|
||||
# TODO: add icons
|
||||
var item := create_item(parent_item)
|
||||
item.set_text(0, state.name)
|
||||
item.set_metadata(0, state)
|
||||
state.set_meta(&"tree_item", item)
|
||||
connect_signals(state)
|
||||
|
||||
for child in (state.get_children() as Array[State]):
|
||||
_setup_tree(child, item)
|
||||
|
||||
|
||||
func _on_item_activated() -> void:
|
||||
change_state_by_path(state_machine_root.get_path_to(
|
||||
get_selected().get_metadata(0) as State))
|
||||
|
||||
|
||||
func _on_state_signal(signal_name: StringName, state_item: TreeItem) -> void:
|
||||
match signal_name:
|
||||
&"entered":
|
||||
for i in columns:
|
||||
state_item.set_custom_color(i, active_color)
|
||||
&"exited":
|
||||
for i in columns:
|
||||
state_item.clear_custom_color(i)
|
||||
|
||||
if not signal_show:
|
||||
return
|
||||
|
||||
state_item.set_text(1, signal_name)
|
||||
var timer := state_item.get_metadata(1) as SceneTreeTimer
|
||||
if timer != null:
|
||||
timer.timeout.disconnect(state_item.set_text)
|
||||
timer = get_tree().create_timer(signal_hide_delay)
|
||||
timer.timeout.connect(state_item.set_text.bind(1, ""))
|
||||
state_item.set_metadata(1, timer)
|
||||
Loading…
Add table
Add a link
Reference in a new issue