Code stuff

This commit is contained in:
Melody Becker 2025-01-26 20:23:56 +01:00
parent cf22890c16
commit e58093b5a5
Signed by: mstar
SSH key fingerprint: SHA256:vkXfS9FG2pVNVfvDrzd1VW9n8VJzqqdKQGljxxX8uK8
153 changed files with 11196 additions and 4 deletions

View file

@ -0,0 +1,185 @@
@tool
extends VBoxContainer
const Utils = preload("../../scripts/Utils.gd")
const ConditionEditor = preload("../condition_editors/ConditionEditor.tscn")
const BoolConditionEditor = preload("../condition_editors/BoolConditionEditor.tscn")
const IntegerConditionEditor = preload("../condition_editors/IntegerConditionEditor.tscn")
const FloatConditionEditor = preload("../condition_editors/FloatConditionEditor.tscn")
const StringConditionEditor = preload("../condition_editors/StringConditionEditor.tscn")
@onready var header = $HeaderContainer/Header
@onready var title = $HeaderContainer/Header/Title
@onready var title_icon = $HeaderContainer/Header/Title/Icon
@onready var from = $HeaderContainer/Header/Title/From
@onready var to = $HeaderContainer/Header/Title/To
@onready var condition_count_icon = $HeaderContainer/Header/ConditionCount/Icon
@onready var condition_count_label = $HeaderContainer/Header/ConditionCount/Label
@onready var priority_icon = $HeaderContainer/Header/Priority/Icon
@onready var priority_spinbox = $HeaderContainer/Header/Priority/SpinBox
@onready var add = $HeaderContainer/Header/HBoxContainer/Add
@onready var add_popup_menu = $HeaderContainer/Header/HBoxContainer/Add/PopupMenu
@onready var content_container = $MarginContainer
@onready var condition_list = $MarginContainer/Conditions
var undo_redo
var transition:
set = set_transition
var _to_free
func _init():
_to_free = []
func _ready():
header.gui_input.connect(_on_header_gui_input)
priority_spinbox.value_changed.connect(_on_priority_spinbox_value_changed)
add.pressed.connect(_on_add_pressed)
add_popup_menu.index_pressed.connect(_on_add_popup_menu_index_pressed)
condition_count_icon.texture = get_theme_icon("MirrorX", "EditorIcons")
priority_icon.texture = get_theme_icon("AnimationTrackGroup", "EditorIcons")
func _exit_tree():
free_node_from_undo_redo() # Managed by EditorInspector
func _on_header_gui_input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
toggle_conditions()
func _on_priority_spinbox_value_changed(val: int) -> void:
set_priority(val)
func _on_add_pressed():
Utils.popup_on_target(add_popup_menu, add)
func _on_add_popup_menu_index_pressed(index):
## Handle condition name duplication (4.x changed how duplicates are
## automatically handled and gave a random index instead of a progressive one)
var default_new_condition_name = "Param"
var condition_dup_index = 0
var new_name = default_new_condition_name
for condition_editor in condition_list.get_children():
var condition_name = condition_editor.condition.name
if (condition_name == new_name):
condition_dup_index += 1
new_name = "%s%s" % [default_new_condition_name, condition_dup_index]
var condition
match index:
0: # Trigger
condition = Condition.new(new_name)
1: # Boolean
condition = BooleanCondition.new(new_name)
2: # Integer
condition = IntegerCondition.new(new_name)
3: # Float
condition = FloatCondition.new(new_name)
4: # String
condition = StringCondition.new(new_name)
_:
push_error("Unexpected index(%d) from PopupMenu" % index)
var editor = create_condition_editor(condition)
add_condition_editor_action(editor, condition)
func _on_ConditionEditorRemove_pressed(editor):
remove_condition_editor_action(editor)
func _on_transition_changed(new_transition):
if not new_transition:
return
for condition in transition.conditions.values():
var editor = create_condition_editor(condition)
add_condition_editor(editor, condition)
update_title()
update_condition_count()
update_priority_spinbox_value()
func _on_condition_editor_added(editor):
editor.undo_redo = undo_redo
if not editor.remove.pressed.is_connected(_on_ConditionEditorRemove_pressed):
editor.remove.pressed.connect(_on_ConditionEditorRemove_pressed.bind(editor))
transition.add_condition(editor.condition)
update_condition_count()
func add_condition_editor(editor, condition):
condition_list.add_child(editor)
editor.condition = condition # Must be assigned after enter tree, as assignment would trigger ui code
_on_condition_editor_added(editor)
func remove_condition_editor(editor):
transition.remove_condition(editor.condition.name)
condition_list.remove_child(editor)
_to_free.append(editor) # Freeing immediately after removal will break undo/redo
update_condition_count()
func update_title():
from.text = transition.from
to.text = transition.to
func update_condition_count():
var count = transition.conditions.size()
condition_count_label.text = str(count)
if count == 0:
hide_conditions()
else:
show_conditions()
func update_priority_spinbox_value():
priority_spinbox.value = transition.priority
priority_spinbox.apply()
func set_priority(value):
transition.priority = value
func show_conditions():
content_container.visible = true
func hide_conditions():
content_container.visible = false
func toggle_conditions():
content_container.visible = !content_container.visible
func create_condition_editor(condition):
var editor
if condition is BooleanCondition:
editor = BoolConditionEditor.instantiate()
elif condition is IntegerCondition:
editor = IntegerConditionEditor.instantiate()
elif condition is FloatCondition:
editor = FloatConditionEditor.instantiate()
elif condition is StringCondition:
editor = StringConditionEditor.instantiate()
else:
editor = ConditionEditor.instantiate()
return editor
func add_condition_editor_action(editor, condition):
undo_redo.create_action("Add Transition Condition")
undo_redo.add_do_method(self, "add_condition_editor", editor, condition)
undo_redo.add_undo_method(self, "remove_condition_editor", editor)
undo_redo.commit_action()
func remove_condition_editor_action(editor):
undo_redo.create_action("Remove Transition Condition")
undo_redo.add_do_method(self, "remove_condition_editor", editor)
undo_redo.add_undo_method(self, "add_condition_editor", editor, editor.condition)
undo_redo.commit_action()
func set_transition(t):
if transition != t:
transition = t
_on_transition_changed(t)
# Free nodes cached in UndoRedo stack
func free_node_from_undo_redo():
for node in _to_free:
if is_instance_valid(node):
var history_id = undo_redo.get_object_history_id(node)
undo_redo.get_history_undo_redo(history_id).clear_history(false) # TODO: Should be handled by plugin.gd (Temporary solution as only TransitionEditor support undo/redo)
node.queue_free()
_to_free.clear()

View file

@ -0,0 +1,133 @@
[gd_scene load_steps=7 format=3 uid="uid://dw0ecw2wdeosi"]
[ext_resource type="Texture2D" uid="uid://dg8cmn5ubq6r5" path="res://addons/imjp94.yafsm/assets/icons/add-white-18dp.svg" id="1"]
[ext_resource type="Script" path="res://addons/imjp94.yafsm/scenes/transition_editors/TransitionEditor.gd" id="3"]
[sub_resource type="Gradient" id="Gradient_hw7k8"]
offsets = PackedFloat32Array(1)
colors = PackedColorArray(1, 1, 1, 1)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_ipxab"]
gradient = SubResource("Gradient_hw7k8")
width = 18
height = 18
[sub_resource type="Image" id="Image_o35y7"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 131, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 128, 128, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 93, 93, 55, 255, 97, 97, 58, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 98, 98, 47, 255, 97, 97, 42, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 94, 94, 46, 255, 93, 93, 236, 255, 93, 93, 233, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 93, 93, 252, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id="ImageTexture_v636r"]
image = SubResource("Image_o35y7")
[node name="TransitionEditor" type="VBoxContainer"]
script = ExtResource("3")
[node name="HeaderContainer" type="MarginContainer" parent="."]
layout_mode = 2
[node name="Panel" type="Panel" parent="HeaderContainer"]
layout_mode = 2
[node name="Header" type="HBoxContainer" parent="HeaderContainer"]
layout_mode = 2
[node name="Title" type="HBoxContainer" parent="HeaderContainer/Header"]
layout_mode = 2
tooltip_text = "Next State"
[node name="From" type="Label" parent="HeaderContainer/Header/Title"]
layout_mode = 2
size_flags_horizontal = 3
text = "From"
[node name="Icon" type="TextureRect" parent="HeaderContainer/Header/Title"]
texture_filter = 1
layout_mode = 2
texture = SubResource("GradientTexture2D_ipxab")
expand_mode = 3
stretch_mode = 3
[node name="To" type="Label" parent="HeaderContainer/Header/Title"]
layout_mode = 2
size_flags_horizontal = 3
text = "To"
[node name="VSeparator" type="VSeparator" parent="HeaderContainer/Header"]
layout_mode = 2
[node name="ConditionCount" type="HBoxContainer" parent="HeaderContainer/Header"]
layout_mode = 2
tooltip_text = "Number of Conditions"
[node name="Icon" type="TextureRect" parent="HeaderContainer/Header/ConditionCount"]
texture_filter = 1
layout_mode = 2
texture = SubResource("ImageTexture_v636r")
expand_mode = 3
stretch_mode = 3
[node name="Label" type="Label" parent="HeaderContainer/Header/ConditionCount"]
layout_mode = 2
text = "No."
[node name="VSeparator2" type="VSeparator" parent="HeaderContainer/Header"]
layout_mode = 2
[node name="Priority" type="HBoxContainer" parent="HeaderContainer/Header"]
layout_mode = 2
tooltip_text = "Priority"
[node name="Icon" type="TextureRect" parent="HeaderContainer/Header/Priority"]
texture_filter = 1
layout_mode = 2
texture = SubResource("ImageTexture_v636r")
expand_mode = 3
stretch_mode = 3
[node name="SpinBox" type="SpinBox" parent="HeaderContainer/Header/Priority"]
layout_mode = 2
max_value = 10.0
rounded = true
allow_greater = true
[node name="VSeparator3" type="VSeparator" parent="HeaderContainer/Header"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="HeaderContainer/Header"]
layout_mode = 2
size_flags_horizontal = 10
[node name="Add" type="Button" parent="HeaderContainer/Header/HBoxContainer"]
layout_mode = 2
tooltip_text = "Add Condition"
icon = ExtResource("1")
flat = true
[node name="PopupMenu" type="PopupMenu" parent="HeaderContainer/Header/HBoxContainer/Add"]
item_count = 5
item_0/text = "Trigger"
item_0/id = 0
item_1/text = "Boolean"
item_1/id = 1
item_2/text = "Integer"
item_2/id = 2
item_3/text = "Float"
item_3/id = 3
item_4/text = "String"
item_4/id = 4
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
[node name="Panel" type="Panel" parent="MarginContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="Conditions" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2

View file

@ -0,0 +1,33 @@
@tool
extends EditorInspectorPlugin
const Transition = preload("res://addons/imjp94.yafsm/src/transitions/Transition.gd")
const TransitionEditor = preload("res://addons/imjp94.yafsm/scenes/transition_editors/TransitionEditor.tscn")
var undo_redo
var transition_icon
func _can_handle(object):
return object is Transition
func _parse_property(object, type, path, hint, hint_text, usage, wide) -> bool:
match path:
"from":
return true
"to":
return true
"conditions":
var transition_editor = TransitionEditor.instantiate() # Will be freed by editor
transition_editor.undo_redo = undo_redo
add_custom_control(transition_editor)
transition_editor.ready.connect(_on_transition_editor_tree_entered.bind(transition_editor, object))
return true
"priority":
return true
return false
func _on_transition_editor_tree_entered(editor, transition):
editor.transition = transition
if transition_icon:
editor.title_icon.texture = transition_icon

View file

@ -0,0 +1,112 @@
@tool
extends "res://addons/imjp94.yafsm/scenes/flowchart/FlowChartLine.gd"
const Transition = preload("../../src/transitions/Transition.gd")
const ValueCondition = preload("../../src/conditions/ValueCondition.gd")
const hi_res_font: Font = preload("res://addons/imjp94.yafsm/assets/fonts/sans_serif.tres")
@export var upright_angle_range: = 5.0
@onready var label_margin = $MarginContainer
@onready var vbox = $MarginContainer/VBoxContainer
var undo_redo
var transition:
set = set_transition
var template = "{condition_name} {condition_comparation} {condition_value}"
var _template_var = {}
func _init():
super._init()
set_transition(Transition.new())
func _draw():
super._draw()
var abs_rotation = abs(rotation)
var is_flip = abs_rotation > deg_to_rad(90.0)
var is_upright = (abs_rotation > (deg_to_rad(90.0) - deg_to_rad(upright_angle_range))) and (abs_rotation < (deg_to_rad(90.0) + deg_to_rad(upright_angle_range)))
if is_upright:
var x_offset = label_margin.size.x / 2
var y_offset = -label_margin.size.y
label_margin.position = Vector2((size.x - x_offset) / 2, 0)
else:
var x_offset = label_margin.size.x
var y_offset = -label_margin.size.y
if is_flip:
label_margin.rotation = deg_to_rad(180)
label_margin.position = Vector2((size.x + x_offset) / 2, 0)
else:
label_margin.rotation = deg_to_rad(0)
label_margin.position = Vector2((size.x - x_offset) / 2, y_offset)
# Update overlay text
func update_label():
if transition:
var template_var = {"condition_name": "", "condition_comparation": "", "condition_value": null}
for label in vbox.get_children():
if not (str(label.name) in transition.conditions.keys()): # Names of nodes are now of type StringName, not simple strings!
vbox.remove_child(label)
label.queue_free()
for condition in transition.conditions.values():
var label = vbox.get_node_or_null(NodePath(condition.name))
if not label:
label = Label.new()
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.add_theme_font_override("font", hi_res_font)
label.name = condition.name
vbox.add_child(label)
if "value" in condition:
template_var["condition_name"] = condition.name
template_var["condition_comparation"] = ValueCondition.COMPARATION_SYMBOLS[condition.comparation]
template_var["condition_value"] = condition.get_value_string()
label.text = template.format(template_var)
var override_template_var = _template_var.get(condition.name)
if override_template_var:
label.text = label.text.format(override_template_var)
else:
label.text = condition.name
queue_redraw()
func _on_transition_changed(new_transition):
if not is_inside_tree():
return
if new_transition:
new_transition.condition_added.connect(_on_transition_condition_added)
new_transition.condition_removed.connect(_on_transition_condition_removed)
for condition in new_transition.conditions.values():
condition.name_changed.connect(_on_condition_name_changed)
condition.display_string_changed.connect(_on_condition_display_string_changed)
update_label()
func _on_transition_condition_added(condition):
condition.name_changed.connect(_on_condition_name_changed)
condition.display_string_changed.connect(_on_condition_display_string_changed)
update_label()
func _on_transition_condition_removed(condition):
condition.name_changed.disconnect(_on_condition_name_changed)
condition.display_string_changed.disconnect(_on_condition_display_string_changed)
update_label()
func _on_condition_name_changed(from, to):
var label = vbox.get_node_or_null(NodePath(from))
if label:
label.name = to
update_label()
func _on_condition_display_string_changed(display_string):
update_label()
func set_transition(t):
if transition != t:
if transition:
if transition.condition_added.is_connected(_on_transition_condition_added):
transition.condition_added.disconnect(_on_transition_condition_added)
transition = t
_on_transition_changed(transition)

View file

@ -0,0 +1,26 @@
[gd_scene load_steps=4 format=3 uid="uid://cwb2nrjai7fao"]
[ext_resource type="PackedScene" uid="uid://creoglbeckyhs" path="res://addons/imjp94.yafsm/scenes/flowchart/FlowChartLine.tscn" id="1"]
[ext_resource type="Script" path="res://addons/imjp94.yafsm/scenes/transition_editors/TransitionLine.gd" id="2"]
[ext_resource type="SystemFont" uid="uid://dmcxm8gxsonbq" path="res://addons/imjp94.yafsm/assets/fonts/sans_serif.tres" id="3_y6xyv"]
[node name="TransitionLine" instance=ExtResource("1")]
script = ExtResource("2")
upright_angle_range = 0.0
[node name="MarginContainer" type="MarginContainer" parent="." index="0"]
layout_mode = 2
mouse_filter = 2
[node name="Label" type="Label" parent="MarginContainer" index="0"]
visible = false
layout_mode = 2
size_flags_horizontal = 6
size_flags_vertical = 6
theme_override_fonts/font = ExtResource("3_y6xyv")
text = "Transition"
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer" index="1"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4