mirror of
https://github.com/tonytins/citylimits
synced 2025-06-26 09:44:44 -04: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
14
addons/simple-state/demo/demo.gd
Normal file
14
addons/simple-state/demo/demo.gd
Normal file
|
@ -0,0 +1,14 @@
|
|||
extends State
|
||||
|
||||
|
||||
const NEXT_STATE_ACTION = "demo_next_state"
|
||||
|
||||
|
||||
func _enter() -> void:
|
||||
if InputMap.has_action(NEXT_STATE_ACTION):
|
||||
return
|
||||
var input_event := InputEventKey.new()
|
||||
input_event.keycode = KEY_TAB
|
||||
|
||||
InputMap.add_action(NEXT_STATE_ACTION)
|
||||
InputMap.action_add_event(NEXT_STATE_ACTION, input_event)
|
218
addons/simple-state/demo/demo.tscn
Normal file
218
addons/simple-state/demo/demo.tscn
Normal file
|
@ -0,0 +1,218 @@
|
|||
[gd_scene load_steps=17 format=3 uid="uid://clnliyc6fmqy6"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/simple-state/classes/debugger.gd" id="1_rqf1w"]
|
||||
[ext_resource type="Script" path="res://addons/simple-state/demo/description_box.gd" id="2_gktik"]
|
||||
[ext_resource type="Script" path="res://addons/simple-state/classes/sequence_state.gd" id="3_4afa7"]
|
||||
[ext_resource type="Script" path="res://addons/simple-state/demo/demo.gd" id="3_x0hcs"]
|
||||
[ext_resource type="Script" path="res://addons/simple-state/classes/random_state.gd" id="4_wxjoe"]
|
||||
[ext_resource type="Script" path="res://addons/simple-state/demo/emit_next.gd" id="6_kxcgl"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ysqm7"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_wxupu"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7gdgn"]
|
||||
draw_center = false
|
||||
border_width_left = 1
|
||||
border_width_top = 1
|
||||
border_width_right = 1
|
||||
border_width_bottom = 1
|
||||
|
||||
[sub_resource type="Animation" id="Animation_5pgem"]
|
||||
resource_name = "RESET"
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ColorRect:color")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 1, 1, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_mwhj1"]
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ColorRect:color")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(0, 0, 0, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_yyph0"]
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ColorRect:color")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(0, 0, 1, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_xmkhy"]
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ColorRect:color")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(0, 1, 0, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_4pwkk"]
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ColorRect:color")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 0, 0, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_gt7hj"]
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("ColorRect:color")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 1, 0, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_01hf1"]
|
||||
_data = {
|
||||
"RESET": SubResource("Animation_5pgem"),
|
||||
"black": SubResource("Animation_mwhj1"),
|
||||
"blue": SubResource("Animation_yyph0"),
|
||||
"green": SubResource("Animation_xmkhy"),
|
||||
"red": SubResource("Animation_4pwkk"),
|
||||
"yellow": SubResource("Animation_gt7hj")
|
||||
}
|
||||
|
||||
[node name="SimpleStateDemo" type="Panel"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="StateMachineDebugger" type="Tree" parent="MarginContainer/HBoxContainer" node_paths=PackedStringArray("state_machine_root")]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/relationship_line_width = 2
|
||||
theme_override_constants/draw_guides = 0
|
||||
theme_override_styles/panel = SubResource("StyleBoxEmpty_ysqm7")
|
||||
theme_override_styles/focus = SubResource("StyleBoxEmpty_wxupu")
|
||||
theme_override_styles/selected = SubResource("StyleBoxFlat_7gdgn")
|
||||
theme_override_styles/selected_focus = SubResource("StyleBoxFlat_7gdgn")
|
||||
select_mode = 1
|
||||
script = ExtResource("1_rqf1w")
|
||||
state_machine_root = NodePath("../../Root")
|
||||
allow_state_switching = true
|
||||
signal_show = true
|
||||
|
||||
[node name="DescriptionBox" type="Label" parent="MarginContainer/HBoxContainer" node_paths=PackedStringArray("tree")]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 1
|
||||
autowrap_mode = 3
|
||||
script = ExtResource("2_gktik")
|
||||
tree = NodePath("../StateMachineDebugger")
|
||||
show_descriptions = 2
|
||||
|
||||
[node name="InputInfo" type="Label" parent="MarginContainer/HBoxContainer/DescriptionBox"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 3
|
||||
anchor_left = 1.0
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -349.0
|
||||
offset_top = -78.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 0
|
||||
text = "MOUSE CLICK on state: select
|
||||
DOUBLE MOUSE CLICK on state: start
|
||||
TAB: next substate (only has effect on leaves)"
|
||||
horizontal_alignment = 2
|
||||
vertical_alignment = 2
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="MarginContainer"]
|
||||
custom_minimum_size = Vector2(50, 50)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 8
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="MarginContainer"]
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_01hf1")
|
||||
}
|
||||
|
||||
[node name="Root" type="Node" parent="MarginContainer" node_paths=PackedStringArray("target", "animation_player")]
|
||||
script = ExtResource("3_x0hcs")
|
||||
target = NodePath("")
|
||||
animation_player = NodePath("../AnimationPlayer")
|
||||
|
||||
[node name="SequenceState" type="Node" parent="MarginContainer/Root"]
|
||||
script = ExtResource("3_4afa7")
|
||||
|
||||
[node name="RandomState" type="Node" parent="MarginContainer/Root/SequenceState"]
|
||||
script = ExtResource("4_wxjoe")
|
||||
defer_choice = true
|
||||
|
||||
[node name="red" type="Node" parent="MarginContainer/Root/SequenceState/RandomState"]
|
||||
script = ExtResource("6_kxcgl")
|
||||
|
||||
[node name="yellow" type="Node" parent="MarginContainer/Root/SequenceState/RandomState"]
|
||||
script = ExtResource("6_kxcgl")
|
||||
|
||||
[node name="green" type="Node" parent="MarginContainer/Root/SequenceState"]
|
||||
script = ExtResource("6_kxcgl")
|
||||
|
||||
[node name="blue" type="Node" parent="MarginContainer/Root/SequenceState"]
|
||||
script = ExtResource("6_kxcgl")
|
||||
|
||||
[node name="black" type="Node" parent="MarginContainer/Root"]
|
||||
script = ExtResource("6_kxcgl")
|
||||
timer = 1.0
|
||||
metadata/description = "Will never start automatically, due to its parent being only a normal state."
|
98
addons/simple-state/demo/description_box.gd
Normal file
98
addons/simple-state/demo/description_box.gd
Normal file
|
@ -0,0 +1,98 @@
|
|||
extends Label
|
||||
|
||||
|
||||
## Mode of description box rendering.
|
||||
enum DisplayModes {
|
||||
NONE, ## Description box completely hidden.
|
||||
ACTIVE, ## Show descriptions of all active states.
|
||||
SELECTION, ## Show description of last selected state (also includes manual switches).
|
||||
}
|
||||
|
||||
|
||||
@export
|
||||
## [StateMachineDebugger] to reference.
|
||||
var tree : StateMachineDebugger:
|
||||
set(value):
|
||||
tree = value
|
||||
if show_descriptions == DisplayModes.SELECTION and \
|
||||
not tree.item_selected.is_connected(_on_tree_item_selected):
|
||||
tree.item_selected.connect(_on_tree_item_selected)
|
||||
|
||||
|
||||
@export
|
||||
## Show a description of a state.
|
||||
## Looks for a string metadata value by the name of [code]description[/code] on each state.
|
||||
var show_descriptions := DisplayModes.NONE:
|
||||
set(value):
|
||||
show_descriptions = value
|
||||
|
||||
match show_descriptions:
|
||||
DisplayModes.NONE:
|
||||
visible = false
|
||||
DisplayModes.ACTIVE:
|
||||
visible = true
|
||||
if not is_instance_valid(tree):
|
||||
return
|
||||
if tree.item_selected.is_connected(_on_tree_item_selected):
|
||||
tree.item_selected.disconnect(_on_tree_item_selected)
|
||||
DisplayModes.SELECTION:
|
||||
visible = true
|
||||
if not is_instance_valid(tree):
|
||||
return
|
||||
if not tree.item_selected.is_connected(_on_tree_item_selected):
|
||||
tree.item_selected.connect(_on_tree_item_selected)
|
||||
|
||||
|
||||
var _active_states : Array[State] = []
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
visible = show_descriptions != DisplayModes.NONE
|
||||
connect_signals()
|
||||
|
||||
|
||||
func connect_signals(state := tree.state_machine_root) -> void:
|
||||
if not state.has_meta(&"tree_item"):
|
||||
return
|
||||
for signal_name in tree.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))
|
||||
for child in(state.get_children() as Array[State]):
|
||||
connect_signals(child)
|
||||
|
||||
|
||||
func disconnect_signals(state := tree.state_machine_root) -> void:
|
||||
for signal_name in tree.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 _set_description_from_active_states() -> void:
|
||||
text = ""
|
||||
for state in _active_states:
|
||||
text += ("" if state.is_root() else "\n\n") + \
|
||||
state.name as String + \
|
||||
": " + \
|
||||
state.get_meta(&"description", "") as String
|
||||
|
||||
|
||||
func _on_tree_item_selected() -> void:
|
||||
text = tree.get_selected() \
|
||||
.get_metadata(0).get_meta(&"description", "")
|
||||
|
||||
|
||||
func _on_state_signal(signal_name: StringName, state: State) -> void:
|
||||
match signal_name:
|
||||
&"entered":
|
||||
if show_descriptions == DisplayModes.ACTIVE:
|
||||
_active_states.push_back(state)
|
||||
_set_description_from_active_states()
|
||||
&"exited":
|
||||
if show_descriptions == DisplayModes.ACTIVE:
|
||||
_active_states.pop_back()
|
||||
_set_description_from_active_states()
|
6
addons/simple-state/demo/emit_next.gd
Normal file
6
addons/simple-state/demo/emit_next.gd
Normal file
|
@ -0,0 +1,6 @@
|
|||
extends AnimationState
|
||||
|
||||
|
||||
func _update(_delta: float) -> void:
|
||||
if Input.is_action_just_pressed(get_root().NEXT_STATE_ACTION):
|
||||
choose_new_substate_requested.emit()
|
Loading…
Add table
Add a link
Reference in a new issue