gd: added input addon

This commit is contained in:
2025-05-27 19:20:46 +02:00
parent d8a1604af9
commit c8d8c7ec25
683 changed files with 21608 additions and 2 deletions

View File

@ -0,0 +1,140 @@
@tool
extends MarginContainer
const ActionSlot = preload("../action_slot/action_slot.gd")
const Utils = preload("../utils.gd")
const ArrayEdit = preload("../array_edit/array_edit.gd")
signal delete_requested()
signal duplicate_requested()
@export var input_mapping_editor_scene:PackedScene
@onready var _action_slot:ActionSlot = %ActionSlot
@onready var _input_mappings:ArrayEdit = %InputMappings
const ClassScanner = preload("../class_scanner.gd")
var _plugin:EditorPlugin
var _scanner:ClassScanner
var _undo_redo:EditorUndoRedoManager
var _mapping:GUIDEActionMapping
func _ready():
_action_slot.action_changed.connect(_on_action_changed)
_input_mappings.delete_requested.connect(_on_input_mapping_delete_requested)
_input_mappings.add_requested.connect(_on_input_mappings_add_requested)
_input_mappings.move_requested.connect(_on_input_mappings_move_requested)
_input_mappings.clear_requested.connect(_on_input_mappings_clear_requested)
_input_mappings.duplicate_requested.connect(_on_input_mappings_duplicate_requested)
_input_mappings.collapse_state_changed.connect(_on_input_mappings_collapse_state_changed)
func initialize(plugin:EditorPlugin, scanner:ClassScanner):
_plugin = plugin
_scanner = scanner
_undo_redo = _plugin.get_undo_redo()
func edit(mapping:GUIDEActionMapping):
assert(_mapping == null)
_mapping = mapping
_mapping.changed.connect(_update)
_update()
func _update():
_input_mappings.clear()
_action_slot.action = _mapping.action
for i in _mapping.input_mappings.size():
var input_mapping = _mapping.input_mappings[i]
var input_mapping_editor = input_mapping_editor_scene.instantiate()
_input_mappings.add_item(input_mapping_editor)
input_mapping_editor.initialize(_plugin, _scanner)
input_mapping_editor.edit(input_mapping)
_input_mappings.collapsed = _mapping.get_meta("_guide_input_mappings_collapsed", false)
func _on_action_changed():
_undo_redo.create_action("Change action")
_undo_redo.add_do_property(_mapping, "action", _action_slot.action)
_undo_redo.add_undo_property(_mapping, "action", _mapping.action)
_undo_redo.commit_action()
func _on_input_mappings_add_requested():
var values = _mapping.input_mappings.duplicate()
var new_mapping = GUIDEInputMapping.new()
values.append(new_mapping)
_undo_redo.create_action("Add input mapping")
_undo_redo.add_do_property(_mapping, "input_mappings", values)
_undo_redo.add_undo_property(_mapping, "input_mappings", _mapping.input_mappings)
_undo_redo.commit_action()
func _on_input_mapping_delete_requested(index:int):
var values = _mapping.input_mappings.duplicate()
values.remove_at(index)
_undo_redo.create_action("Delete input mapping")
_undo_redo.add_do_property(_mapping, "input_mappings", values)
_undo_redo.add_undo_property(_mapping, "input_mappings", _mapping.input_mappings)
_undo_redo.commit_action()
func _on_input_mappings_move_requested(from:int, to:int):
var values = _mapping.input_mappings.duplicate()
var mapping = values[from]
values.remove_at(from)
if from < to:
to -= 1
values.insert(to, mapping)
_undo_redo.create_action("Move input mapping")
_undo_redo.add_do_property(_mapping, "input_mappings", values)
_undo_redo.add_undo_property(_mapping, "input_mappings", _mapping.input_mappings)
_undo_redo.commit_action()
func _on_input_mappings_clear_requested():
var values:Array[GUIDEInputMapping] = []
_undo_redo.create_action("Clear input mappings")
_undo_redo.add_do_property(_mapping, "input_mappings", values)
_undo_redo.add_undo_property(_mapping, "input_mappings", _mapping.input_mappings)
_undo_redo.commit_action()
func _on_input_mappings_duplicate_requested(index:int):
var values = _mapping.input_mappings.duplicate()
var copy:GUIDEInputMapping = values[index].duplicate()
copy.input = Utils.duplicate_if_inline(copy.input)
for i in copy.modifiers.size():
copy.modifiers[i] = Utils.duplicate_if_inline(copy.modifiers[i])
for i in copy.triggers.size():
copy.triggers[i] = Utils.duplicate_if_inline(copy.triggers[i])
# insert copy after original
values.insert(index+1, copy)
_undo_redo.create_action("Duplicate input mapping")
_undo_redo.add_do_property(_mapping, "input_mappings", values)
_undo_redo.add_undo_property(_mapping, "input_mappings", _mapping.input_mappings)
_undo_redo.commit_action()
func _on_input_mappings_collapse_state_changed(new_state:bool):
_mapping.set_meta("_guide_input_mappings_collapsed", new_state)

View File

@ -0,0 +1 @@
uid://dp8xv83uhxpjo

View File

@ -0,0 +1,43 @@
[gd_scene load_steps=5 format=3 uid="uid://361aipcef24h"]
[ext_resource type="Script" path="res://addons/guide/editor/action_mapping_editor/action_mapping_editor.gd" id="1_2k0pi"]
[ext_resource type="PackedScene" uid="uid://du4x7ng6ntuk4" path="res://addons/guide/editor/action_slot/action_slot.tscn" id="1_hguf2"]
[ext_resource type="PackedScene" uid="uid://c323mdijdhktg" path="res://addons/guide/editor/input_mapping_editor/input_mapping_editor.tscn" id="2_a8nbp"]
[ext_resource type="PackedScene" uid="uid://cly0ff32fvpb2" path="res://addons/guide/editor/array_edit/array_edit.tscn" id="4_ehr5j"]
[node name="ActionMappingEditor" type="MarginContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_vertical = 0
theme_override_constants/margin_bottom = 5
script = ExtResource("1_2k0pi")
input_mapping_editor_scene = ExtResource("2_a8nbp")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_vertical = 0
[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
[node name="ActionSlot" parent="HBoxContainer/HBoxContainer" instance=ExtResource("1_hguf2")]
unique_name_in_owner = true
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
size_flags_stretch_ratio = 4.0
[node name="InputMappings" parent="HBoxContainer/VBoxContainer" instance=ExtResource("4_ehr5j")]
unique_name_in_owner = true
layout_mode = 2
title = "Input mappings"
add_tooltip = "Add input mapping"
clear_tooltip = "Clear input mappings"

View File

@ -0,0 +1,70 @@
@tool
extends Control
signal action_changed()
@onready var _line_edit:LineEdit = %LineEdit
@onready var _type_icon:TextureRect = %TypeIcon
var index:int
var action:GUIDEAction:
set(value):
if is_instance_valid(action):
action.changed.disconnect(_refresh)
action = value
if is_instance_valid(action):
action.changed.connect(_refresh)
# action_changed can only be emitted by
# dragging an action into this, not when setting
# the property
_refresh()
func _refresh():
if not is_instance_valid(action):
_line_edit.text = "<none>"
_line_edit.tooltip_text = ""
_type_icon.texture = preload("missing_action.svg")
_type_icon.tooltip_text = "Missing action"
else:
_line_edit.text = action._editor_name()
_line_edit.tooltip_text = action.resource_path
## Update the icon to reflect the given value type.
match action.action_value_type:
GUIDEAction.GUIDEActionValueType.AXIS_1D:
_type_icon.texture = preload("action_value_type_axis1d.svg")
_type_icon.tooltip_text = "Axis1D"
GUIDEAction.GUIDEActionValueType.AXIS_2D:
_type_icon.texture = preload("action_value_type_axis2d.svg")
_type_icon.tooltip_text = "Axis2D"
GUIDEAction.GUIDEActionValueType.AXIS_3D:
_type_icon.texture = preload("action_value_type_axis3d.svg")
_type_icon.tooltip_text = "Axis3D"
_:
# fallback is bool
_type_icon.texture = preload("action_value_type_bool.svg")
_type_icon.tooltip_text = "Boolean"
func _gui_input(event):
if event is InputEventMouseButton:
if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
if is_instance_valid(action):
EditorInterface.edit_resource(action)
func _on_line_edit_action_dropped(new_action:GUIDEAction):
action = new_action
action_changed.emit()
func _on_line_edit_focus_entered():
if is_instance_valid(action):
EditorInterface.edit_resource(action)

View File

@ -0,0 +1 @@
uid://ysrbdsqui5cn

View File

@ -0,0 +1,29 @@
[gd_scene load_steps=3 format=3 uid="uid://du4x7ng6ntuk4"]
[ext_resource type="Script" path="res://addons/guide/editor/action_slot/action_slot.gd" id="1_w5nxd"]
[ext_resource type="Script" path="res://addons/guide/editor/action_slot/action_slot_line_edit.gd" id="2_ram7b"]
[node name="ActionSlot" type="HBoxContainer"]
offset_right = 40.0
offset_bottom = 40.0
size_flags_horizontal = 3
script = ExtResource("1_w5nxd")
[node name="TypeIcon" type="TextureRect" parent="."]
unique_name_in_owner = true
layout_mode = 2
expand_mode = 3
stretch_mode = 4
[node name="LineEdit" type="LineEdit" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
text = "Name"
editable = false
selecting_enabled = false
script = ExtResource("2_ram7b")
[connection signal="action_dropped" from="LineEdit" to="." method="_on_line_edit_action_dropped"]
[connection signal="focus_entered" from="LineEdit" to="." method="_on_line_edit_focus_entered"]

View File

@ -0,0 +1,24 @@
@tool
extends LineEdit
signal action_dropped(action:GUIDEAction)
func _can_drop_data(at_position, data) -> bool:
if not data is Dictionary:
return false
if data.has("files"):
for file in data["files"]:
if ResourceLoader.load(file) is GUIDEAction:
return true
return false
func _drop_data(at_position, data) -> void:
for file in data["files"]:
var item = ResourceLoader.load(file)
if item is GUIDEAction:
action_dropped.emit(item)

View File

@ -0,0 +1 @@
uid://b12uq0dpsgj7u

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-105.29,-40.0231)">
<g id="vt_axis1d" transform="matrix(2.99151,0,0,2.8775,150.452,37.7582)">
<rect x="-15.097" y="0.787" width="10.697" height="11.121" style="fill:none;"/>
<clipPath id="_clip1">
<rect x="-15.097" y="0.787" width="10.697" height="11.121"/>
</clipPath>
<g clip-path="url(#_clip1)">
<g transform="matrix(0.391767,0,0,0.416391,-43.1614,-16.5941)">
<path d="M98.94,48.419L98.94,61.773C98.94,65.458 95.882,68.45 92.114,68.45L78.462,68.45C74.695,68.45 71.636,65.458 71.636,61.773L71.636,48.419C71.636,44.734 74.695,41.743 78.462,41.743L92.114,41.743C95.882,41.743 98.94,44.734 98.94,48.419ZM96.466,48.419C96.466,46.07 94.516,44.163 92.114,44.163L78.462,44.163C76.06,44.163 74.11,46.07 74.11,48.419L74.11,61.773C74.11,64.122 76.06,66.03 78.462,66.03L92.114,66.03C94.516,66.03 96.466,64.122 96.466,61.773L96.466,48.419Z" style="fill:rgb(253,150,0);"/>
</g>
<g transform="matrix(0.334279,0,0,0.347524,-18.3085,-0.144498)">
<g transform="matrix(20.88,0,0,24,11.6286,27.2968)">
<path d="M0.144,-0.068L0.298,-0.068L0.298,-0.557C0.298,-0.571 0.298,-0.586 0.299,-0.601L0.171,-0.492C0.168,-0.489 0.164,-0.487 0.161,-0.486C0.158,-0.485 0.155,-0.484 0.152,-0.484C0.147,-0.484 0.142,-0.485 0.138,-0.487C0.134,-0.489 0.131,-0.492 0.129,-0.495L0.101,-0.534L0.314,-0.718L0.387,-0.718L0.387,-0.068L0.528,-0.068L0.528,-0L0.144,-0L0.144,-0.068Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
<g transform="matrix(20.88,0,0,24,22.695,27.2968)">
<path d="M0.708,-0.358C0.708,-0.304 0.7,-0.256 0.683,-0.212C0.666,-0.167 0.642,-0.13 0.611,-0.099C0.58,-0.067 0.542,-0.043 0.499,-0.026C0.456,-0.009 0.408,-0 0.355,-0L0.087,-0L0.087,-0.717L0.355,-0.717C0.408,-0.717 0.456,-0.708 0.499,-0.691C0.542,-0.674 0.58,-0.649 0.611,-0.618C0.642,-0.586 0.666,-0.549 0.683,-0.505C0.7,-0.46 0.708,-0.412 0.708,-0.358ZM0.609,-0.358C0.609,-0.402 0.603,-0.441 0.591,-0.476C0.579,-0.511 0.562,-0.54 0.54,-0.564C0.518,-0.588 0.491,-0.606 0.46,-0.619C0.428,-0.632 0.393,-0.638 0.355,-0.638L0.185,-0.638L0.185,-0.079L0.355,-0.079C0.393,-0.079 0.428,-0.085 0.46,-0.098C0.491,-0.11 0.518,-0.128 0.54,-0.152C0.562,-0.176 0.579,-0.205 0.591,-0.24C0.603,-0.275 0.609,-0.314 0.609,-0.358Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://du55fdegui0t0"
path="res://.godot/imported/action_value_type_axis1d.svg-47cde6e873b547282e811542e4ee320d.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/guide/editor/action_slot/action_value_type_axis1d.svg"
dest_files=["res://.godot/imported/action_value_type_axis1d.svg-47cde6e873b547282e811542e4ee320d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=true
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,0,-77.6972)">
<g id="vt_axis2d" transform="matrix(2.99151,0,0,2.8775,45.1623,75.4322)">
<rect x="-15.097" y="0.787" width="10.697" height="11.121" style="fill:none;"/>
<clipPath id="_clip1">
<rect x="-15.097" y="0.787" width="10.697" height="11.121"/>
</clipPath>
<g clip-path="url(#_clip1)">
<g transform="matrix(0.391767,0,0,0.416391,-43.1614,-16.5941)">
<path d="M98.94,48.419L98.94,61.773C98.94,65.458 95.882,68.45 92.114,68.45L78.462,68.45C74.695,68.45 71.636,65.458 71.636,61.773L71.636,48.419C71.636,44.734 74.695,41.743 78.462,41.743L92.114,41.743C95.882,41.743 98.94,44.734 98.94,48.419ZM96.466,48.419C96.466,46.07 94.516,44.163 92.114,44.163L78.462,44.163C76.06,44.163 74.11,46.07 74.11,48.419L74.11,61.773C74.11,64.122 76.06,66.03 78.462,66.03L92.114,66.03C94.516,66.03 96.466,64.122 96.466,61.773L96.466,48.419Z" style="fill:rgb(253,150,0);"/>
</g>
<g transform="matrix(0.334279,0,0,0.347524,-18.1375,-0.117391)">
<g transform="matrix(20.88,0,0,24,11.6286,27.2968)">
<path d="M0.301,-0.725C0.331,-0.725 0.359,-0.72 0.386,-0.711C0.412,-0.702 0.435,-0.689 0.454,-0.672C0.473,-0.655 0.488,-0.634 0.499,-0.609C0.51,-0.584 0.516,-0.556 0.516,-0.525C0.516,-0.498 0.511,-0.474 0.504,-0.451C0.496,-0.428 0.485,-0.407 0.471,-0.386C0.457,-0.365 0.442,-0.345 0.424,-0.325C0.406,-0.306 0.387,-0.286 0.367,-0.266L0.179,-0.073C0.192,-0.076 0.205,-0.079 0.219,-0.081C0.233,-0.083 0.246,-0.085 0.259,-0.085L0.499,-0.085C0.508,-0.085 0.516,-0.082 0.522,-0.076C0.527,-0.07 0.53,-0.063 0.53,-0.054L0.53,-0L0.052,-0L0.052,-0.031C0.052,-0.037 0.053,-0.043 0.056,-0.05C0.058,-0.057 0.062,-0.063 0.068,-0.069L0.298,-0.299C0.317,-0.318 0.334,-0.337 0.35,-0.355C0.365,-0.373 0.379,-0.391 0.39,-0.409C0.401,-0.427 0.41,-0.445 0.416,-0.463C0.422,-0.482 0.424,-0.501 0.425,-0.523C0.424,-0.544 0.421,-0.562 0.415,-0.578C0.408,-0.594 0.399,-0.607 0.387,-0.617C0.375,-0.627 0.362,-0.635 0.346,-0.64C0.33,-0.645 0.314,-0.648 0.296,-0.648C0.278,-0.648 0.261,-0.645 0.246,-0.64C0.23,-0.635 0.217,-0.627 0.205,-0.618C0.193,-0.608 0.183,-0.597 0.175,-0.584C0.167,-0.571 0.161,-0.557 0.158,-0.541C0.155,-0.531 0.151,-0.524 0.146,-0.52C0.14,-0.516 0.133,-0.514 0.125,-0.514C0.123,-0.514 0.121,-0.514 0.119,-0.514C0.117,-0.514 0.115,-0.514 0.113,-0.515L0.067,-0.523C0.071,-0.555 0.08,-0.584 0.094,-0.609C0.107,-0.634 0.124,-0.656 0.144,-0.673C0.165,-0.69 0.188,-0.702 0.215,-0.711C0.241,-0.72 0.27,-0.725 0.301,-0.725Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
<g transform="matrix(20.88,0,0,24,22.695,27.2968)">
<path d="M0.708,-0.358C0.708,-0.304 0.7,-0.256 0.683,-0.212C0.666,-0.167 0.642,-0.13 0.611,-0.099C0.58,-0.067 0.542,-0.043 0.499,-0.026C0.456,-0.009 0.408,-0 0.355,-0L0.087,-0L0.087,-0.717L0.355,-0.717C0.408,-0.717 0.456,-0.708 0.499,-0.691C0.542,-0.674 0.58,-0.649 0.611,-0.618C0.642,-0.586 0.666,-0.549 0.683,-0.505C0.7,-0.46 0.708,-0.412 0.708,-0.358ZM0.609,-0.358C0.609,-0.402 0.603,-0.441 0.591,-0.476C0.579,-0.511 0.562,-0.54 0.54,-0.564C0.518,-0.588 0.491,-0.606 0.46,-0.619C0.428,-0.632 0.393,-0.638 0.355,-0.638L0.185,-0.638L0.185,-0.079L0.355,-0.079C0.393,-0.079 0.428,-0.085 0.46,-0.098C0.491,-0.11 0.518,-0.128 0.54,-0.152C0.562,-0.176 0.579,-0.205 0.591,-0.24C0.603,-0.275 0.609,-0.314 0.609,-0.358Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bw3r81rgkbeic"
path="res://.godot/imported/action_value_type_axis2d.svg-82a12ec01234cc4464e5fb9b94ba28f0.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/guide/editor/action_slot/action_value_type_axis2d.svg"
dest_files=["res://.godot/imported/action_value_type_axis2d.svg-82a12ec01234cc4464e5fb9b94ba28f0.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=true
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-34.1415,-77.6972)">
<g id="vt_axis3d" transform="matrix(2.99151,0,0,2.8775,79.3037,75.4322)">
<rect x="-15.097" y="0.787" width="10.697" height="11.121" style="fill:none;"/>
<clipPath id="_clip1">
<rect x="-15.097" y="0.787" width="10.697" height="11.121"/>
</clipPath>
<g clip-path="url(#_clip1)">
<g transform="matrix(0.391767,0,0,0.416391,-43.1614,-16.5941)">
<path d="M98.94,48.419L98.94,61.773C98.94,65.458 95.882,68.45 92.114,68.45L78.462,68.45C74.695,68.45 71.636,65.458 71.636,61.773L71.636,48.419C71.636,44.734 74.695,41.743 78.462,41.743L92.114,41.743C95.882,41.743 98.94,44.734 98.94,48.419ZM96.466,48.419C96.466,46.07 94.516,44.163 92.114,44.163L78.462,44.163C76.06,44.163 74.11,46.07 74.11,48.419L74.11,61.773C74.11,64.122 76.06,66.03 78.462,66.03L92.114,66.03C94.516,66.03 96.466,64.122 96.466,61.773L96.466,48.419Z" style="fill:rgb(253,150,0);"/>
</g>
<g transform="matrix(0.334279,0,0,0.347524,-18.1375,-0.117391)">
<g transform="matrix(20.88,0,0,24,11.6286,27.2968)">
<path d="M0.31,-0.725C0.34,-0.725 0.368,-0.72 0.394,-0.712C0.42,-0.703 0.442,-0.691 0.46,-0.675C0.479,-0.659 0.493,-0.639 0.504,-0.617C0.514,-0.594 0.519,-0.569 0.519,-0.541C0.519,-0.518 0.516,-0.498 0.51,-0.48C0.504,-0.462 0.496,-0.447 0.485,-0.433C0.474,-0.42 0.461,-0.408 0.446,-0.399C0.431,-0.39 0.413,-0.382 0.395,-0.377C0.441,-0.364 0.476,-0.343 0.5,-0.315C0.523,-0.286 0.535,-0.249 0.535,-0.206C0.535,-0.173 0.529,-0.143 0.516,-0.117C0.504,-0.09 0.487,-0.068 0.465,-0.049C0.443,-0.031 0.418,-0.017 0.389,-0.007C0.36,0.003 0.33,0.008 0.297,0.008C0.259,0.008 0.226,0.003 0.199,-0.006C0.172,-0.016 0.149,-0.029 0.131,-0.046C0.112,-0.062 0.097,-0.082 0.085,-0.105C0.073,-0.128 0.062,-0.152 0.054,-0.179L0.092,-0.195C0.099,-0.198 0.106,-0.2 0.113,-0.2C0.12,-0.2 0.126,-0.198 0.131,-0.195C0.136,-0.192 0.14,-0.188 0.143,-0.182C0.143,-0.181 0.146,-0.175 0.147,-0.173C0.151,-0.163 0.157,-0.152 0.164,-0.14C0.17,-0.128 0.179,-0.117 0.191,-0.106C0.202,-0.095 0.216,-0.086 0.233,-0.079C0.25,-0.072 0.271,-0.068 0.296,-0.068C0.321,-0.068 0.342,-0.072 0.361,-0.08C0.38,-0.088 0.396,-0.099 0.408,-0.112C0.421,-0.125 0.43,-0.139 0.437,-0.156C0.443,-0.171 0.446,-0.187 0.446,-0.203C0.446,-0.222 0.443,-0.24 0.438,-0.256C0.433,-0.272 0.424,-0.286 0.41,-0.298C0.397,-0.309 0.378,-0.318 0.354,-0.325C0.33,-0.332 0.3,-0.335 0.263,-0.335L0.263,-0.4C0.293,-0.4 0.319,-0.403 0.34,-0.41C0.362,-0.416 0.379,-0.424 0.393,-0.436C0.407,-0.447 0.417,-0.46 0.423,-0.475C0.429,-0.49 0.432,-0.507 0.432,-0.526C0.432,-0.547 0.429,-0.565 0.422,-0.58C0.416,-0.595 0.407,-0.608 0.396,-0.618C0.384,-0.628 0.371,-0.635 0.355,-0.641C0.34,-0.646 0.323,-0.648 0.305,-0.648C0.287,-0.648 0.27,-0.645 0.255,-0.64C0.24,-0.635 0.226,-0.627 0.214,-0.618C0.202,-0.608 0.193,-0.597 0.185,-0.584C0.177,-0.571 0.171,-0.556 0.167,-0.541C0.164,-0.531 0.16,-0.524 0.155,-0.52C0.149,-0.516 0.142,-0.514 0.134,-0.514C0.132,-0.514 0.131,-0.514 0.129,-0.514C0.127,-0.514 0.125,-0.514 0.123,-0.515L0.076,-0.523C0.081,-0.555 0.09,-0.584 0.103,-0.609C0.116,-0.634 0.133,-0.656 0.154,-0.673C0.174,-0.69 0.198,-0.702 0.224,-0.711C0.251,-0.72 0.279,-0.725 0.31,-0.725Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
<g transform="matrix(20.88,0,0,24,22.695,27.2968)">
<path d="M0.708,-0.358C0.708,-0.304 0.7,-0.256 0.683,-0.212C0.666,-0.167 0.642,-0.13 0.611,-0.099C0.58,-0.067 0.542,-0.043 0.499,-0.026C0.456,-0.009 0.408,-0 0.355,-0L0.087,-0L0.087,-0.717L0.355,-0.717C0.408,-0.717 0.456,-0.708 0.499,-0.691C0.542,-0.674 0.58,-0.649 0.611,-0.618C0.642,-0.586 0.666,-0.549 0.683,-0.505C0.7,-0.46 0.708,-0.412 0.708,-0.358ZM0.609,-0.358C0.609,-0.402 0.603,-0.441 0.591,-0.476C0.579,-0.511 0.562,-0.54 0.54,-0.564C0.518,-0.588 0.491,-0.606 0.46,-0.619C0.428,-0.632 0.393,-0.638 0.355,-0.638L0.185,-0.638L0.185,-0.079L0.355,-0.079C0.393,-0.079 0.428,-0.085 0.46,-0.098C0.491,-0.11 0.518,-0.128 0.54,-0.152C0.562,-0.176 0.579,-0.205 0.591,-0.24C0.603,-0.275 0.609,-0.314 0.609,-0.358Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dcsfko8g6vjor"
path="res://.godot/imported/action_value_type_axis3d.svg-6c96e9bad6748ae9f491c37a99292ee2.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/guide/editor/action_slot/action_value_type_axis3d.svg"
dest_files=["res://.godot/imported/action_value_type_axis3d.svg-6c96e9bad6748ae9f491c37a99292ee2.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=true
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-70.3759,-40.0231)">
<g id="vt_bool" transform="matrix(2.99151,0,0,2.8775,115.538,37.7582)">
<rect x="-15.097" y="0.787" width="10.697" height="11.121" style="fill:none;"/>
<clipPath id="_clip1">
<rect x="-15.097" y="0.787" width="10.697" height="11.121"/>
</clipPath>
<g clip-path="url(#_clip1)">
<g transform="matrix(0.391767,0,0,0.416391,-43.1614,-16.5941)">
<path d="M98.94,48.419L98.94,61.773C98.94,65.458 95.882,68.45 92.114,68.45L78.462,68.45C74.695,68.45 71.636,65.458 71.636,61.773L71.636,48.419C71.636,44.734 74.695,41.743 78.462,41.743L92.114,41.743C95.882,41.743 98.94,44.734 98.94,48.419ZM96.466,48.419C96.466,46.07 94.516,44.163 92.114,44.163L78.462,44.163C76.06,44.163 74.11,46.07 74.11,48.419L74.11,61.773C74.11,64.122 76.06,66.03 78.462,66.03L92.114,66.03C94.516,66.03 96.466,64.122 96.466,61.773L96.466,48.419Z" style="fill:rgb(253,150,0);"/>
</g>
<g transform="matrix(0.334279,0,0,0.347524,-16.1271,-0.158791)">
<g transform="matrix(24,0,0,24,11.6286,27.2968)">
<path d="M0.087,-0L0.087,-0.717L0.316,-0.717C0.36,-0.717 0.397,-0.712 0.429,-0.704C0.461,-0.695 0.487,-0.683 0.508,-0.667C0.528,-0.651 0.543,-0.631 0.553,-0.608C0.563,-0.585 0.568,-0.559 0.568,-0.53C0.568,-0.512 0.565,-0.495 0.56,-0.479C0.554,-0.462 0.546,-0.447 0.535,-0.433C0.524,-0.419 0.51,-0.407 0.493,-0.396C0.476,-0.385 0.456,-0.376 0.434,-0.369C0.486,-0.358 0.525,-0.339 0.552,-0.312C0.579,-0.285 0.592,-0.249 0.592,-0.204C0.592,-0.174 0.586,-0.146 0.575,-0.121C0.564,-0.096 0.548,-0.075 0.526,-0.057C0.505,-0.039 0.478,-0.025 0.447,-0.015C0.416,-0.005 0.381,-0 0.341,-0L0.087,-0ZM0.184,-0.327L0.184,-0.077L0.339,-0.077C0.367,-0.077 0.39,-0.08 0.41,-0.087C0.43,-0.093 0.446,-0.102 0.459,-0.113C0.472,-0.125 0.482,-0.138 0.488,-0.154C0.494,-0.17 0.497,-0.188 0.497,-0.207C0.497,-0.244 0.483,-0.273 0.457,-0.294C0.431,-0.316 0.392,-0.327 0.339,-0.327L0.184,-0.327ZM0.184,-0.396L0.312,-0.396C0.339,-0.396 0.363,-0.399 0.383,-0.405C0.403,-0.411 0.42,-0.419 0.433,-0.43C0.446,-0.44 0.456,-0.453 0.462,-0.468C0.468,-0.483 0.472,-0.5 0.472,-0.518C0.472,-0.56 0.459,-0.591 0.434,-0.611C0.408,-0.63 0.369,-0.64 0.316,-0.64L0.184,-0.64L0.184,-0.396Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bla3yu6pdqyt5"
path="res://.godot/imported/action_value_type_bool.svg-552c954344c23690bcca901351d04f59.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/guide/editor/action_slot/action_value_type_bool.svg"
dest_files=["res://.godot/imported/action_value_type_bool.svg-552c954344c23690bcca901351d04f59.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=true
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-70.6587,-77.6972)">
<g id="action_warning" transform="matrix(2.99151,0,0,2.8775,115.821,75.4322)">
<rect x="-15.097" y="0.787" width="10.697" height="11.121" style="fill:none;"/>
<g transform="matrix(0.334279,0,0,0.347524,-14.8308,0.994936)">
<g transform="matrix(20.88,0,0,24,11.6286,27.2968)">
<path d="M0.215,-0.717L0.215,-0.431C0.215,-0.416 0.215,-0.401 0.214,-0.387C0.214,-0.372 0.213,-0.358 0.212,-0.343C0.211,-0.329 0.21,-0.314 0.208,-0.299C0.207,-0.284 0.205,-0.267 0.203,-0.25L0.143,-0.25C0.141,-0.267 0.139,-0.284 0.137,-0.299C0.136,-0.314 0.135,-0.329 0.134,-0.343C0.133,-0.358 0.132,-0.372 0.131,-0.387C0.131,-0.401 0.131,-0.416 0.131,-0.431L0.131,-0.717L0.215,-0.717ZM0.109,-0.055C0.109,-0.064 0.111,-0.072 0.114,-0.08C0.117,-0.087 0.121,-0.094 0.127,-0.1C0.132,-0.105 0.139,-0.11 0.147,-0.113C0.154,-0.116 0.162,-0.118 0.171,-0.118C0.18,-0.118 0.188,-0.116 0.196,-0.113C0.203,-0.11 0.21,-0.105 0.216,-0.1C0.221,-0.094 0.226,-0.087 0.229,-0.08C0.232,-0.072 0.234,-0.064 0.234,-0.055C0.234,-0.046 0.232,-0.038 0.229,-0.03C0.226,-0.023 0.221,-0.016 0.216,-0.011C0.21,-0.005 0.203,-0 0.196,0.003C0.188,0.006 0.18,0.008 0.171,0.008C0.162,0.008 0.154,0.006 0.147,0.003C0.139,-0 0.132,-0.005 0.127,-0.011C0.121,-0.016 0.117,-0.023 0.114,-0.03C0.111,-0.038 0.109,-0.046 0.109,-0.055Z" style="fill:rgb(253,150,0);fill-rule:nonzero;"/>
</g>
</g>
<g transform="matrix(0.604147,0,0,0.347524,-66.4208,-26.2145)">
<path d="M93.806,77.697L102.659,109.697L84.953,109.697L93.806,77.697ZM93.806,83.533L87.289,107.087L100.322,107.087L93.806,83.533Z" style="fill:rgb(253,150,0);"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,37 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cdi5eoc1e8ha0"
path="res://.godot/imported/missing_action.svg-31774fd8d1b787aab90de376faa436ea.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://addons/guide/editor/action_slot/missing_action.svg"
dest_files=["res://.godot/imported/missing_action.svg-31774fd8d1b787aab90de376faa436ea.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,113 @@
@tool
extends Container
const Utils = preload("../utils.gd")
@export var item_scene:PackedScene
@export var title:String = "":
set(value):
title = value
_refresh()
@export var add_tooltip:String:
set(value):
add_tooltip = value
_refresh()
@export var clear_tooltip:String:
set(value):
clear_tooltip = value
_refresh()
@export var item_separation:int = 8:
set(value):
item_separation = value
_refresh()
@export var collapsed:bool = false:
set(value):
collapsed = value
_refresh()
signal add_requested()
signal delete_requested(index:int)
signal move_requested(from:int, to:int)
signal insert_requested(index:int)
signal duplicate_requested(index:int)
signal clear_requested()
signal collapse_state_changed(collapsed:bool)
@onready var _add_button:Button = %AddButton
@onready var _clear_button:Button = %ClearButton
@onready var _contents:Container = %Contents
@onready var _title_label:Label = %TitleLabel
@onready var _collapse_button:Button = %CollapseButton
@onready var _expand_button:Button = %ExpandButton
@onready var _count_label:Label = %CountLabel
func _ready():
_add_button.icon = get_theme_icon("Add", "EditorIcons")
_add_button.pressed.connect(func(): add_requested.emit())
_clear_button.icon = get_theme_icon("Clear", "EditorIcons")
_clear_button.pressed.connect(func(): clear_requested.emit())
_collapse_button.icon = get_theme_icon("Collapse", "EditorIcons")
_collapse_button.pressed.connect(_on_collapse_pressed)
_expand_button.icon = get_theme_icon("Forward", "EditorIcons")
_expand_button.pressed.connect(_on_expand_pressed)
_refresh()
func _refresh():
if is_instance_valid(_add_button):
_add_button.tooltip_text = add_tooltip
if is_instance_valid(_clear_button):
_clear_button.tooltip_text = clear_tooltip
_clear_button.visible = _contents.get_child_count() > 0
if is_instance_valid(_contents):
_contents.add_theme_constant_override("separation", item_separation)
_contents.visible = not collapsed
if is_instance_valid(_collapse_button):
_collapse_button.visible = not collapsed
if is_instance_valid(_expand_button):
_expand_button.visible = collapsed
if is_instance_valid(_title_label):
_title_label.text = title
if is_instance_valid(_count_label):
_count_label.text = "(%s)" % [_contents.get_child_count()]
func clear():
Utils.clear(_contents)
_refresh()
func add_item(new_item:Control):
var item_wrapper = item_scene.instantiate()
_contents.add_child(item_wrapper)
item_wrapper.initialize(new_item)
item_wrapper.move_requested.connect(func(from:int, to:int): move_requested.emit(from, to))
item_wrapper.delete_requested.connect(func(idx:int): delete_requested.emit(idx) )
item_wrapper.duplicate_requested.connect(func(idx:int): duplicate_requested.emit(idx) )
_refresh()
func _on_collapse_pressed():
collapsed = true
collapse_state_changed.emit(true)
func _on_expand_pressed():
collapsed = false
collapse_state_changed.emit(false)

View File

@ -0,0 +1 @@
uid://whm2ksw6nc4h

View File

@ -0,0 +1,88 @@
[gd_scene load_steps=5 format=3 uid="uid://cly0ff32fvpb2"]
[ext_resource type="Script" path="res://addons/guide/editor/array_edit/array_edit.gd" id="1_y3qyt"]
[ext_resource type="PackedScene" uid="uid://cjabwsa4gmlpp" path="res://addons/guide/editor/array_edit/array_edit_item.tscn" id="2_n3ncl"]
[sub_resource type="Image" id="Image_efj5n"]
data = {
"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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_uapko"]
image = SubResource("Image_efj5n")
[node name="Array" type="MarginContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_y3qyt")
item_scene = ExtResource("2_n3ncl")
item_separation = 10
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"]
layout_mode = 2
[node name="Panel" type="Panel" parent="VBoxContainer/MarginContainer"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/MarginContainer"]
layout_mode = 2
[node name="CollapseButton" type="Button" parent="VBoxContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(32, 0)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Collapse"
icon = SubResource("ImageTexture_uapko")
[node name="ExpandButton" type="Button" parent="VBoxContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(48, 0)
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Expand"
icon = SubResource("ImageTexture_uapko")
[node name="AddButton" type="Button" parent="VBoxContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 0
icon = SubResource("ImageTexture_uapko")
[node name="ClearButton" type="Button" parent="VBoxContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
size_flags_horizontal = 0
icon = SubResource("ImageTexture_uapko")
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/MarginContainer/HBoxContainer"]
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/MarginContainer/HBoxContainer/MarginContainer"]
layout_mode = 2
[node name="TitleLabel" type="Label" parent="VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
[node name="CountLabel" type="Label" parent="VBoxContainer/MarginContainer/HBoxContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "(0)"
[node name="Contents" type="VBoxContainer" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_constants/separation = 10

View File

@ -0,0 +1,84 @@
@tool
extends Container
const Utils = preload("../utils.gd")
const Dragger = preload("dragger.gd")
signal move_requested(from:int, to:int)
signal delete_requested(index:int)
signal duplicate_requested(index:int)
@onready var _dragger:Dragger = %Dragger
@onready var _content:Container = %Content
@onready var _before_indicator:ColorRect = %BeforeIndicator
@onready var _after_indicator:ColorRect = %AfterIndicator
@onready var _popup_menu:PopupMenu = %PopupMenu
const ID_DELETE = 2
const ID_DUPLICATE = 3
func _ready():
_dragger.icon = get_theme_icon("GuiSpinboxUpdown", "EditorIcons")
_before_indicator.color = get_theme_color("box_selection_stroke_color", "Editor")
_after_indicator.color = get_theme_color("box_selection_stroke_color", "Editor")
_before_indicator.visible = false
_after_indicator.visible = false
_dragger._parent_array = get_parent()
_dragger._index = get_index()
_dragger.pressed.connect(_show_popup_menu)
_popup_menu.clear()
_popup_menu.add_icon_item(get_theme_icon("Duplicate", "EditorIcons"), "Duplicate", ID_DUPLICATE)
_popup_menu.add_icon_item(get_theme_icon("Remove", "EditorIcons"), "Delete", ID_DELETE)
_popup_menu.id_pressed.connect(_on_popup_menu_id_pressed)
func initialize(content:Control):
Utils.clear(_content)
_content.add_child(content)
func _can_drop_data(at_position:Vector2, data) -> bool:
if data is Dictionary and data.has("parent_array") and data.parent_array == get_parent() and data.index != get_index():
var height = size.y
var is_before = not _is_last_child() or (at_position.y < height/2.0)
if is_before and data.index == get_index() - 1:
# don't allow the previous child to be inserted at its
# own position
return false
_before_indicator.visible = is_before
_after_indicator.visible = not is_before
return true
return false
func _drop_data(at_position, data):
var height = size.y
var is_before = not _is_last_child() or (at_position.y < height/2.0)
var from = data.index
var to = get_index() if is_before else get_index() + 1
move_requested.emit(data.index, to)
_before_indicator.visible = false
_after_indicator.visible = false
func _is_last_child() -> bool:
return get_index() == get_parent().get_child_count() - 1
func _on_mouse_exited():
_before_indicator.visible = false
_after_indicator.visible = false
func _show_popup_menu():
_popup_menu.popup(Rect2(get_global_mouse_position(), Vector2.ZERO))
func _on_popup_menu_id_pressed(id:int):
match id:
ID_DELETE:
delete_requested.emit(get_index())
ID_DUPLICATE:
duplicate_requested.emit(get_index())

View File

@ -0,0 +1 @@
uid://dhqhut5enoj43

View File

@ -0,0 +1,83 @@
[gd_scene load_steps=5 format=3 uid="uid://cjabwsa4gmlpp"]
[ext_resource type="Script" path="res://addons/guide/editor/array_edit/array_edit_item.gd" id="1_ujx05"]
[ext_resource type="Script" path="res://addons/guide/editor/array_edit/dragger.gd" id="2_53e2r"]
[sub_resource type="Image" id="Image_efj5n"]
data = {
"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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_uapko"]
image = SubResource("Image_efj5n")
[node name="ArrayEditItem" type="MarginContainer"]
anchors_preset = 10
anchor_right = 1.0
offset_bottom = 8.0
grow_horizontal = 2
script = ExtResource("1_ujx05")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 2
theme_override_constants/margin_top = 2
theme_override_constants/margin_bottom = 2
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
layout_mode = 2
[node name="Dragger" type="Button" parent="MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 0
tooltip_text = "Drag to reorder, click for options."
focus_mode = 0
mouse_filter = 1
icon = SubResource("ImageTexture_uapko")
script = ExtResource("2_53e2r")
[node name="Content" type="MarginContainer" parent="MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 2
mouse_filter = 2
[node name="BeforeIndicator" type="ColorRect" parent="VBoxContainer"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
mouse_filter = 2
color = Color(0, 0, 0, 1)
[node name="Control" type="Control" parent="VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
mouse_filter = 2
[node name="AfterIndicator" type="ColorRect" parent="VBoxContainer"]
unique_name_in_owner = true
visible = false
custom_minimum_size = Vector2(0, 2)
layout_mode = 2
mouse_filter = 2
color = Color(0, 0, 0, 1)
[node name="PopupMenu" type="PopupMenu" parent="."]
unique_name_in_owner = true
item_count = 2
item_0/text = "Duplicate"
item_0/icon = SubResource("ImageTexture_uapko")
item_0/id = 3
item_1/text = "Delete"
item_1/icon = SubResource("ImageTexture_uapko")
item_1/id = 2
[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"]

View File

@ -0,0 +1,8 @@
@tool
extends Button
var _parent_array:Variant
var _index:int
func _get_drag_data(at_position):
return { "parent_array" : _parent_array, "index" : _index }

View File

@ -0,0 +1 @@
uid://d3cob8fbf0xk8

View File

@ -0,0 +1,148 @@
@tool
extends Window
const ClassScanner = preload("../class_scanner.gd")
const Utils = preload("../utils.gd")
signal input_selected(input:GUIDEInput)
@onready var _input_display = %InputDisplay
@onready var _available_types:Container = %AvailableTypes
@onready var _none_available:Control = %NoneAvailable
@onready var _some_available:Control = %SomeAvailable
@onready var _select_bool_button:Button = %SelectBoolButton
@onready var _select_1d_button:Button = %Select1DButton
@onready var _select_2d_button:Button = %Select2DButton
@onready var _select_3d_button:Button = %Select3DButton
@onready var _instructions_label:Label = %InstructionsLabel
@onready var _accept_detection_button:Button = %AcceptDetectionButton
@onready var _input_detector:GUIDEInputDetector = %InputDetector
@onready var _detect_bool_button:Button = %DetectBoolButton
@onready var _detect_1d_button:Button = %Detect1DButton
@onready var _detect_2d_button:Button = %Detect2DButton
@onready var _detect_3d_button:Button = %Detect3DButton
var _scanner:ClassScanner
var _last_detected_input:GUIDEInput
func initialize(scanner:ClassScanner):
_scanner = scanner
_setup_dialog()
func _setup_dialog():
# we need to bind this here. if we bind it in the editor, the editor
# will crash when opening the scene because it will delete the node it
# just tries to edit.
focus_exited.connect(_on_close_requested)
_show_inputs_of_value_type(GUIDEAction.GUIDEActionValueType.BOOL)
_instructions_label.text = tr("Press one of the buttons above to detect an input.")
_accept_detection_button.visible = false
func _on_close_requested():
hide()
queue_free()
func _show_inputs_of_value_type(type:GUIDEAction.GUIDEActionValueType) -> void:
var items:Array[GUIDEInput] = []
_select_bool_button.set_pressed_no_signal(type == GUIDEAction.GUIDEActionValueType.BOOL)
_select_1d_button.set_pressed_no_signal(type == GUIDEAction.GUIDEActionValueType.AXIS_1D)
_select_2d_button.set_pressed_no_signal(type == GUIDEAction.GUIDEActionValueType.AXIS_2D)
_select_3d_button.set_pressed_no_signal(type == GUIDEAction.GUIDEActionValueType.AXIS_3D)
var all_inputs = _scanner.find_inheritors("GUIDEInput")
for script in all_inputs.values():
var dummy:GUIDEInput = script.new()
if dummy._native_value_type() == type:
items.append(dummy)
_some_available.visible = not items.is_empty()
_none_available.visible = items.is_empty()
if items.is_empty():
return
items.sort_custom(func(a,b): return a._editor_name().nocasecmp_to(b._editor_name()) < 0)
Utils.clear(_available_types)
for item in items:
var button = Button.new()
button.text = item._editor_name()
button.tooltip_text = item._editor_description()
button.pressed.connect(_deliver.bind(item))
button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
_available_types.add_child(button)
func _deliver(input:GUIDEInput):
input_selected.emit(input)
hide()
queue_free()
func _on_select_bool_button_pressed():
_show_inputs_of_value_type(GUIDEAction.GUIDEActionValueType.BOOL)
func _on_select_1d_button_pressed():
_show_inputs_of_value_type(GUIDEAction.GUIDEActionValueType.AXIS_1D)
func _on_select_2d_button_pressed():
_show_inputs_of_value_type(GUIDEAction.GUIDEActionValueType.AXIS_2D)
func _on_select_3d_button_pressed():
_show_inputs_of_value_type(GUIDEAction.GUIDEActionValueType.AXIS_3D)
func _on_input_detector_detection_started():
_instructions_label.text = tr("Actuate the input now...")
func _on_input_detector_input_detected(input:GUIDEInput):
_instructions_label.visible = false
_input_display.visible = true
_input_display.input = input
_accept_detection_button.visible = true
_last_detected_input = input
func _begin_detect_input(type:GUIDEAction.GUIDEActionValueType):
_last_detected_input = null
_instructions_label.visible = true
_instructions_label.text = tr("Get ready...")
_accept_detection_button.visible = false
_input_display.visible = false
_input_detector.detect(type)
func _on_detect_bool_button_pressed():
_detect_bool_button.release_focus()
_begin_detect_input(GUIDEAction.GUIDEActionValueType.BOOL)
func _on_detect_1d_button_pressed():
_detect_1d_button.release_focus()
_begin_detect_input(GUIDEAction.GUIDEActionValueType.AXIS_1D)
func _on_detect_2d_button_pressed():
_detect_2d_button.release_focus()
_begin_detect_input(GUIDEAction.GUIDEActionValueType.AXIS_2D)
func _on_detect_3d_button_pressed():
_detect_3d_button.release_focus()
_begin_detect_input(GUIDEAction.GUIDEActionValueType.AXIS_3D)
func _on_accept_detection_button_pressed():
input_selected.emit(_last_detected_input)
hide()
queue_free

View File

@ -0,0 +1 @@
uid://dfuj0dl8ob6r6

View File

@ -0,0 +1,216 @@
[gd_scene load_steps=5 format=3 uid="uid://dic27bm4pfw3q"]
[ext_resource type="Script" path="res://addons/guide/editor/binding_dialog/binding_dialog.gd" id="1_tknjd"]
[ext_resource type="PackedScene" uid="uid://dsv7s6tfmnsrs" path="res://addons/guide/editor/input_display/input_display.tscn" id="2_83ieu"]
[ext_resource type="Script" path="res://addons/guide/remapping/guide_input_detector.gd" id="3_c6q6r"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3e874"]
content_margin_left = 4.0
content_margin_top = 4.0
content_margin_right = 4.0
content_margin_bottom = 4.0
bg_color = Color(1, 0.365, 0.365, 1)
draw_center = false
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
corner_detail = 1
[node name="BindingDialog" type="Window"]
title = "Input Configuration"
initial_position = 4
size = Vector2i(1200, 600)
popup_window = true
min_size = Vector2i(1200, 600)
script = ExtResource("1_tknjd")
[node name="MarginContainer" type="MarginContainer" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_bottom = 5
[node name="BGPanel" type="Panel" parent="MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_3e874")
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer"]
layout_mode = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/MarginContainer"]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="LeftPanel" type="Panel" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer"]
layout_mode = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 10
[node name="Label" type="Label" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Detect Input"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="DetectBoolButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "Boolean"
[node name="Detect1DButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "1D"
[node name="Detect2DButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "2D"
[node name="Detect3DButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(80, 0)
layout_mode = 2
size_flags_horizontal = 3
text = "3D"
[node name="InstructionsLabel" type="Label" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 6
text = "3..2..1.."
horizontal_alignment = 1
vertical_alignment = 1
autowrap_mode = 2
[node name="InputDisplay" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer" instance=ExtResource("2_83ieu")]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 6
[node name="AcceptDetectionButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 4
text = "Accept"
[node name="MarginContainer2" type="MarginContainer" parent="MarginContainer/MarginContainer/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="RightPanel" type="Panel" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2"]
unique_name_in_owner = true
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2"]
layout_mode = 2
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer"]
layout_mode = 2
size_flags_horizontal = 3
theme_override_constants/separation = 10
[node name="Label" type="Label" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer"]
layout_mode = 2
text = "Select Input"
horizontal_alignment = 1
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer"]
layout_mode = 2
[node name="SelectBoolButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(80, 0)
layout_mode = 2
size_flags_horizontal = 3
toggle_mode = true
text = "Boolean"
[node name="Select1DButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(80, 0)
layout_mode = 2
size_flags_horizontal = 3
toggle_mode = true
text = "1D"
[node name="Select2DButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(80, 0)
layout_mode = 2
size_flags_horizontal = 3
toggle_mode = true
text = "2D"
[node name="Select3DButton" type="Button" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
custom_minimum_size = Vector2(80, 0)
layout_mode = 2
size_flags_horizontal = 3
toggle_mode = true
text = "3D"
[node name="NoneAvailable" type="Label" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 6
size_flags_vertical = 6
text = "No matching inputs available."
[node name="SomeAvailable" type="ScrollContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
[node name="AvailableTypes" type="VBoxContainer" parent="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/SomeAvailable"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
[node name="InputDetector" type="Node" parent="."]
unique_name_in_owner = true
script = ExtResource("3_c6q6r")
[connection signal="close_requested" from="." to="." method="_on_close_requested"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/DetectBoolButton" to="." method="_on_detect_bool_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/Detect1DButton" to="." method="_on_detect_1d_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/Detect2DButton" to="." method="_on_detect_2d_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/HBoxContainer/Detect3DButton" to="." method="_on_detect_3d_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer/MarginContainer/VBoxContainer/AcceptDetectionButton" to="." method="_on_accept_detection_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer/SelectBoolButton" to="." method="_on_select_bool_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer/Select1DButton" to="." method="_on_select_1d_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer/Select2DButton" to="." method="_on_select_2d_button_pressed"]
[connection signal="pressed" from="MarginContainer/MarginContainer/HBoxContainer/MarginContainer2/MarginContainer/VBoxContainer/HBoxContainer/Select3DButton" to="." method="_on_select_3d_button_pressed"]
[connection signal="detection_started" from="InputDetector" to="." method="_on_input_detector_detection_started"]
[connection signal="input_detected" from="InputDetector" to="." method="_on_input_detector_input_detected"]

View File

@ -0,0 +1,91 @@
## Scanner to find inheriting classes. Used to detect inheritors of
## modifiers and triggers. Ideally this would be built into the editor
## but sometimes one has to hack their way around the limitations.
## This only scans to the extent needed to drive the UI, it's not a general
## purpose implementation.
@tool
const GUIDESet = preload("../guide_set.gd")
var _dirty:bool = true
# looks like we only get very limited access to the script's inheritance tree,
# so we need to do a little caching ourselves
var _script_lut:Dictionary = {}
func _init():
EditorInterface.get_resource_filesystem().script_classes_updated.connect(_mark_dirty)
func _mark_dirty():
_dirty = true
## Returns all classes that directly or indirectly inherit from the
## given class. Only works for scripts in the project, e.g. doesn't
## scan the whole class_db. Key is class name, value is the Script instance
func find_inheritors(clazz_name:StringName) -> Dictionary:
var result:Dictionary = {}
var root := EditorInterface.get_resource_filesystem().get_filesystem()
# rebuild the LUT when needed
if _dirty:
_script_lut.clear()
_scan(root)
_dirty = false
var open_set:GUIDESet = GUIDESet.new()
# a closed set just to avoid infinite loops, we'll never
# look at the same class more than once.
var closed_set:GUIDESet = GUIDESet.new()
open_set.add(clazz_name)
while not open_set.is_empty():
var next = open_set.pull()
closed_set.add(next)
if not _script_lut.has(next):
# we don't know this script, ignore, move on
continue
# now find all scripts that extend the one we
# are looking at
for item:ScriptInfo in _script_lut.values():
if item.extendz == next:
# put them into the result
result[item.clazz_name] = item.clazz_script
# and put their class in the open set
# unless we already looked at it.
if not closed_set.has(item.clazz_name):
open_set.add(item.clazz_name)
return result
func _scan(folder:EditorFileSystemDirectory):
for i in folder.get_file_count():
var script_clazz = folder.get_file_script_class_name(i)
if script_clazz != "":
var info := _script_lut.get(script_clazz)
if info == null:
info = ScriptInfo.new()
info.clazz_name = script_clazz
info.clazz_script = ResourceLoader.load(folder.get_file_path(i))
_script_lut[script_clazz] = info
var script_extendz = folder.get_file_script_class_extends(i)
info.extendz = script_extendz
for i in folder.get_subdir_count():
_scan(folder.get_subdir(i))
class ScriptInfo:
var clazz_name:StringName
var extendz:StringName
var clazz_script:Script
func _to_string() -> String:
return clazz_name + ":" + extendz

View File

@ -0,0 +1 @@
uid://b1trdjs8ofe7c

View File

@ -0,0 +1,39 @@
@tool
extends RichTextLabel
signal clicked()
var _formatter:GUIDEInputFormatter = GUIDEInputFormatter.new(64)
var input:GUIDEInput:
set(value):
if value == input:
return
if is_instance_valid(input):
input.changed.disconnect(_refresh)
input = value
if is_instance_valid(input):
input.changed.connect(_refresh)
_refresh()
func _refresh():
if not is_instance_valid(input):
parse_bbcode("[center][i]<not bound>[/i][/center]")
tooltip_text = ""
return
var text := await _formatter.input_as_richtext_async(input, false)
parse_bbcode("[center]" + text + "[/center]")
tooltip_text = _formatter.input_as_text(input)
func _gui_input(event):
if event is InputEventMouseButton:
if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
clicked.emit()

View File

@ -0,0 +1 @@
uid://cgf2qrodwja32

View File

@ -0,0 +1,18 @@
[gd_scene load_steps=3 format=3 uid="uid://dsv7s6tfmnsrs"]
[ext_resource type="Script" path="res://addons/guide/editor/input_display/input_display.gd" id="1_ne6sd"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0bp65"]
[node name="InputDisplay" type="RichTextLabel"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_styles/normal = SubResource("StyleBoxEmpty_0bp65")
bbcode_enabled = true
fit_content = true
script = ExtResource("1_ne6sd")

View File

@ -0,0 +1,299 @@
@tool
extends MarginContainer
const ArrayEdit = preload("../array_edit/array_edit.gd")
const ClassScanner = preload("../class_scanner.gd")
const Utils = preload("../utils.gd")
@export var modifier_slot_scene:PackedScene
@export var trigger_slot_scene:PackedScene
@export var binding_dialog_scene:PackedScene
@onready var _edit_input_mapping_button:Button = %EditInputMappingButton
@onready var _input_display = %InputDisplay
@onready var _edit_input_button:Button = %EditInputButton
@onready var _clear_input_button:Button = %ClearInputButton
@onready var _modifiers:ArrayEdit = %Modifiers
@onready var _add_modifier_popup:PopupMenu = %AddModifierPopup
@onready var _triggers:ArrayEdit = %Triggers
@onready var _add_trigger_popup:PopupMenu = %AddTriggerPopup
var _plugin:EditorPlugin
var _scanner:ClassScanner
var _undo_redo:EditorUndoRedoManager
var _mapping:GUIDEInputMapping
func _ready():
_edit_input_button.icon = get_theme_icon("Edit", "EditorIcons")
_clear_input_button.icon = get_theme_icon("Remove", "EditorIcons")
_edit_input_mapping_button.icon = get_theme_icon("Tools", "EditorIcons")
_modifiers.add_requested.connect(_on_modifiers_add_requested)
_modifiers.delete_requested.connect(_on_modifier_delete_requested)
_modifiers.duplicate_requested.connect(_on_modifier_duplicate_requested)
_modifiers.move_requested.connect(_on_modifier_move_requested)
_modifiers.clear_requested.connect(_on_modifiers_clear_requested)
_modifiers.collapse_state_changed.connect(_on_modifiers_collapse_state_changed)
_triggers.add_requested.connect(_on_triggers_add_requested)
_triggers.delete_requested.connect(_on_trigger_delete_requested)
_triggers.duplicate_requested.connect(_on_trigger_duplicate_requested)
_triggers.move_requested.connect(_on_trigger_move_requested)
_triggers.clear_requested.connect(_on_triggers_clear_requested)
_triggers.collapse_state_changed.connect(_on_triggers_collapse_state_changed)
func initialize(plugin:EditorPlugin, scanner:ClassScanner) -> void:
_plugin = plugin
_scanner = scanner
_undo_redo = plugin.get_undo_redo()
_input_display.clicked.connect(_on_input_display_clicked)
func edit(mapping:GUIDEInputMapping) -> void:
assert(_mapping == null)
_mapping = mapping
_mapping.changed.connect(_update)
_update()
func _update():
_modifiers.clear()
_triggers.clear()
_input_display.input = _mapping.input
for i in _mapping.modifiers.size():
var modifier_slot = modifier_slot_scene.instantiate()
_modifiers.add_item(modifier_slot)
modifier_slot.modifier = _mapping.modifiers[i]
modifier_slot.changed.connect(_on_modifier_changed.bind(i, modifier_slot))
for i in _mapping.triggers.size():
var trigger_slot = trigger_slot_scene.instantiate()
_triggers.add_item(trigger_slot)
trigger_slot.trigger = _mapping.triggers[i]
trigger_slot.changed.connect(_on_trigger_changed.bind(i, trigger_slot))
_modifiers.collapsed = _mapping.get_meta("_guide_modifiers_collapsed", false)
_triggers.collapsed = _mapping.get_meta("_guide_triggers_collapsed", false)
func _on_modifiers_add_requested():
_fill_popup(_add_modifier_popup, "GUIDEModifier")
_add_modifier_popup.popup(Rect2(get_global_mouse_position(), Vector2.ZERO))
func _on_triggers_add_requested():
_fill_popup(_add_trigger_popup, "GUIDETrigger")
_add_trigger_popup.popup(Rect2(get_global_mouse_position(), Vector2.ZERO))
func _fill_popup(popup:PopupMenu, base_clazz:StringName):
popup.clear(true)
var inheritors := _scanner.find_inheritors(base_clazz)
for type in inheritors.keys():
var class_script:Script = inheritors[type]
var dummy = class_script.new()
popup.add_item(dummy._editor_name())
popup.set_item_tooltip(popup.item_count -1, dummy._editor_description())
popup.set_item_metadata(popup.item_count - 1, class_script)
func _on_input_display_clicked():
if is_instance_valid(_mapping.input):
EditorInterface.edit_resource(_mapping.input)
func _on_input_changed(input:GUIDEInput):
_undo_redo.create_action("Change input")
_undo_redo.add_do_property(_mapping, "input", input)
_undo_redo.add_undo_property(_mapping, "input", _mapping.input)
_undo_redo.commit_action()
if is_instance_valid(input):
EditorInterface.edit_resource(input)
func _on_edit_input_button_pressed():
var dialog:Window = binding_dialog_scene.instantiate()
EditorInterface.popup_dialog_centered(dialog)
dialog.initialize(_scanner)
dialog.input_selected.connect(_on_input_changed)
func _on_clear_input_button_pressed():
_undo_redo.create_action("Delete bound input")
_undo_redo.add_do_property(_mapping, "input", null)
_undo_redo.add_undo_property(_mapping, "triggers", _mapping.input)
_undo_redo.commit_action()
func _on_add_modifier_popup_index_pressed(index:int) -> void:
var script = _add_modifier_popup.get_item_metadata(index)
var new_modifier = script.new()
_undo_redo.create_action("Add " + new_modifier._editor_name() + " modifier")
var modifiers = _mapping.modifiers.duplicate()
modifiers.append(new_modifier)
_undo_redo.add_do_property(_mapping, "modifiers", modifiers)
_undo_redo.add_undo_property(_mapping, "modifiers", _mapping.modifiers)
_undo_redo.commit_action()
func _on_add_trigger_popup_index_pressed(index):
var script = _add_trigger_popup.get_item_metadata(index)
var new_trigger = script.new()
_undo_redo.create_action("Add " + new_trigger._editor_name() + " trigger")
var triggers = _mapping.triggers.duplicate()
triggers.append(new_trigger)
_undo_redo.add_do_property(_mapping, "triggers", triggers)
_undo_redo.add_undo_property(_mapping, "triggers", _mapping.triggers)
_undo_redo.commit_action()
func _on_modifier_changed(index:int, slot) -> void:
var new_modifier = slot.modifier
_undo_redo.create_action("Replace modifier")
var modifiers = _mapping.modifiers.duplicate()
modifiers[index] = new_modifier
_undo_redo.add_do_property(_mapping, "modifiers", modifiers)
_undo_redo.add_undo_property(_mapping, "modifiers", _mapping.modifiers)
_undo_redo.commit_action()
func _on_trigger_changed(index:int, slot) -> void:
var new_trigger = slot.trigger
_undo_redo.create_action("Replace trigger")
var triggers = _mapping.triggers.duplicate()
triggers[index] = new_trigger
_undo_redo.add_do_property(_mapping, "triggers", triggers)
_undo_redo.add_undo_property(_mapping, "triggers", _mapping.triggers)
_undo_redo.commit_action()
func _on_modifier_move_requested(from:int, to:int) -> void:
_undo_redo.create_action("Move modifier")
var modifiers = _mapping.modifiers.duplicate()
var modifier = modifiers[from]
modifiers.remove_at(from)
if from < to:
to -= 1
modifiers.insert(to, modifier)
_undo_redo.add_do_property(_mapping, "modifiers", modifiers)
_undo_redo.add_undo_property(_mapping, "modifiers", _mapping.modifiers)
_undo_redo.commit_action()
func _on_trigger_move_requested(from:int, to:int) -> void:
_undo_redo.create_action("Move trigger")
var triggers = _mapping.triggers.duplicate()
var trigger = triggers[from]
triggers.remove_at(from)
if from < to:
to -= 1
triggers.insert(to, trigger)
_undo_redo.add_do_property(_mapping, "triggers", triggers)
_undo_redo.add_undo_property(_mapping, "triggers", _mapping.triggers)
_undo_redo.commit_action()
func _on_modifier_duplicate_requested(index:int) -> void:
_undo_redo.create_action("Duplicate modifier")
var modifiers = _mapping.modifiers.duplicate()
var copy = Utils.duplicate_if_inline(modifiers[index])
modifiers.insert(index+1, copy)
_undo_redo.add_do_property(_mapping, "modifiers", modifiers)
_undo_redo.add_undo_property(_mapping, "modifiers", _mapping.modifiers)
_undo_redo.commit_action()
func _on_trigger_duplicate_requested(index:int) -> void:
_undo_redo.create_action("Duplicate trigger")
var triggers = _mapping.triggers.duplicate()
var copy = Utils.duplicate_if_inline(triggers[index])
triggers.insert(index+1, copy)
_undo_redo.add_do_property(_mapping, "triggers", triggers)
_undo_redo.add_undo_property(_mapping, "triggers", _mapping.triggers)
_undo_redo.commit_action()
func _on_modifier_delete_requested(index:int) -> void:
_undo_redo.create_action("Delete modifier")
var modifiers = _mapping.modifiers.duplicate()
modifiers.remove_at(index)
_undo_redo.add_do_property(_mapping, "modifiers", modifiers)
_undo_redo.add_undo_property(_mapping, "modifiers", _mapping.modifiers)
_undo_redo.commit_action()
func _on_trigger_delete_requested(index:int) -> void:
_undo_redo.create_action("Delete trigger")
var triggers = _mapping.triggers.duplicate()
triggers.remove_at(index)
_undo_redo.add_do_property(_mapping, "triggers", triggers)
_undo_redo.add_undo_property(_mapping, "triggers", _mapping.triggers)
_undo_redo.commit_action()
func _on_modifiers_clear_requested() -> void:
_undo_redo.create_action("Clear modifiers")
# if this is inlined into the do_property, then it doesn't work
# so lets keep it a local variable
var value:Array[GUIDEModifier] = []
_undo_redo.add_do_property(_mapping, "modifiers", value)
_undo_redo.add_undo_property(_mapping, "modifiers", _mapping.modifiers)
_undo_redo.commit_action()
func _on_triggers_clear_requested() -> void:
_undo_redo.create_action("Clear triggers")
# if this is inlined into the do_property, then it doesn't work
# so lets keep it a local variable
var value:Array[GUIDETrigger] = []
_undo_redo.add_do_property(_mapping, "triggers", value)
_undo_redo.add_undo_property(_mapping, "triggers", _mapping.triggers)
_undo_redo.commit_action()
func _on_modifiers_collapse_state_changed(new_state:bool):
_mapping.set_meta("_guide_modifiers_collapsed", new_state)
func _on_triggers_collapse_state_changed(new_state:bool):
_mapping.set_meta("_guide_triggers_collapsed", new_state)
func _on_edit_input_mapping_button_pressed():
EditorInterface.edit_resource(_mapping)

View File

@ -0,0 +1 @@
uid://dsw33iehbw8q6

View File

@ -0,0 +1,140 @@
[gd_scene load_steps=9 format=3 uid="uid://c323mdijdhktg"]
[ext_resource type="PackedScene" uid="uid://dsv7s6tfmnsrs" path="res://addons/guide/editor/input_display/input_display.tscn" id="1_pg8n3"]
[ext_resource type="Script" path="res://addons/guide/editor/input_mapping_editor/input_mapping_editor.gd" id="1_xsluc"]
[ext_resource type="PackedScene" uid="uid://ck5a30syo6bpo" path="res://addons/guide/editor/modifier_slot/modifier_slot.tscn" id="2_uhbrq"]
[ext_resource type="PackedScene" uid="uid://tk30wnstb0ku" path="res://addons/guide/editor/trigger_slot/trigger_slot.tscn" id="3_e0jys"]
[ext_resource type="PackedScene" uid="uid://dic27bm4pfw3q" path="res://addons/guide/editor/binding_dialog/binding_dialog.tscn" id="4_oepf3"]
[ext_resource type="PackedScene" uid="uid://cly0ff32fvpb2" path="res://addons/guide/editor/array_edit/array_edit.tscn" id="6_jekhk"]
[sub_resource type="Image" id="Image_m1w1j"]
data = {
"data": PackedByteArray(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, 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, 94, 94, 127, 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, 94, 94, 127, 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, 94, 94, 127, 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, 255, 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, 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, 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, 94, 94, 54, 255, 94, 94, 57, 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, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 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, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 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, 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, 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_y0eyy"]
image = SubResource("Image_m1w1j")
[node name="InputMappingEditor" type="MarginContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_vertical = 0
script = ExtResource("1_xsluc")
modifier_slot_scene = ExtResource("2_uhbrq")
trigger_slot_scene = ExtResource("3_e0jys")
binding_dialog_scene = ExtResource("4_oepf3")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 2
size_flags_vertical = 0
theme_override_constants/separation = 8
[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_vertical = 0
[node name="Panel" type="Panel" parent="HBoxContainer/MarginContainer"]
visible = false
layout_mode = 2
[node name="EditInputMappingButton" type="Button" parent="HBoxContainer/MarginContainer"]
unique_name_in_owner = true
layout_mode = 2
tooltip_text = "Open input mapping in inspector"
icon = SubResource("ImageTexture_y0eyy")
flat = true
[node name="MarginContainer1" type="MarginContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="Panel" type="Panel" parent="HBoxContainer/MarginContainer1"]
visible = false
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="HBoxContainer/MarginContainer1"]
layout_mode = 2
[node name="InputDisplay" parent="HBoxContainer/MarginContainer1/HBoxContainer" instance=ExtResource("1_pg8n3")]
unique_name_in_owner = true
layout_mode = 2
scroll_active = false
[node name="EditInputButton" type="Button" parent="HBoxContainer/MarginContainer1/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 0
tooltip_text = "Edit bound input..."
icon = SubResource("ImageTexture_y0eyy")
flat = true
[node name="ClearInputButton" type="Button" parent="HBoxContainer/MarginContainer1/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 0
tooltip_text = "Delete bound input"
icon = SubResource("ImageTexture_y0eyy")
flat = true
[node name="MarginContainer2" type="MarginContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 2.0
[node name="Panel" type="Panel" parent="HBoxContainer/MarginContainer2"]
visible = false
layout_mode = 2
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/MarginContainer2"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
size_flags_stretch_ratio = 2.0
[node name="Modifiers" parent="HBoxContainer/MarginContainer2/VBoxContainer" instance=ExtResource("6_jekhk")]
unique_name_in_owner = true
layout_mode = 2
title = "Modifiers"
add_tooltip = "Add modifier..."
clear_tooltip = "Clear modifiers"
[node name="AddModifierPopup" type="PopupMenu" parent="HBoxContainer/MarginContainer2/VBoxContainer"]
unique_name_in_owner = true
[node name="MarginContainer3" type="MarginContainer" parent="HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 2.0
[node name="Panel" type="Panel" parent="HBoxContainer/MarginContainer3"]
visible = false
layout_mode = 2
[node name="VBoxContainer2" type="VBoxContainer" parent="HBoxContainer/MarginContainer3"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
size_flags_stretch_ratio = 2.0
[node name="Triggers" parent="HBoxContainer/MarginContainer3/VBoxContainer2" instance=ExtResource("6_jekhk")]
unique_name_in_owner = true
layout_mode = 2
title = "Triggers"
add_tooltip = "Add trigger..."
clear_tooltip = "Clear triggers"
[node name="AddTriggerPopup" type="PopupMenu" parent="HBoxContainer/MarginContainer3/VBoxContainer2"]
unique_name_in_owner = true
[connection signal="pressed" from="HBoxContainer/MarginContainer/EditInputMappingButton" to="." method="_on_edit_input_mapping_button_pressed"]
[connection signal="pressed" from="HBoxContainer/MarginContainer1/HBoxContainer/EditInputButton" to="." method="_on_edit_input_button_pressed"]
[connection signal="pressed" from="HBoxContainer/MarginContainer1/HBoxContainer/ClearInputButton" to="." method="_on_clear_input_button_pressed"]
[connection signal="index_pressed" from="HBoxContainer/MarginContainer2/VBoxContainer/AddModifierPopup" to="." method="_on_add_modifier_popup_index_pressed"]
[connection signal="index_pressed" from="HBoxContainer/MarginContainer3/VBoxContainer2/AddTriggerPopup" to="." method="_on_add_trigger_popup_index_pressed"]

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1.16508,0,-1.89607)">
<path d="M11.289,19.641L0.424,19.641L0.424,11.08L11.289,11.08L11.289,1.973L21.263,1.973L21.263,11.08L31.576,11.08L31.576,19.641L21.263,19.641L21.263,28.711L11.289,28.711L11.289,19.641Z" style="fill:rgb(235,235,235);"/>
<path d="M11.289,19.641L0.424,19.641L0.424,11.08L11.289,11.08L11.289,1.973L21.263,1.973L21.263,11.08L31.576,11.08L31.576,19.641L21.263,19.641L21.263,28.711L11.289,28.711L11.289,19.641ZM11.567,19.641L11.567,28.473L20.985,28.473L20.985,19.641C20.985,19.509 21.109,19.402 21.263,19.402L31.298,19.402L31.298,11.318L21.263,11.318C21.109,11.318 20.985,11.212 20.985,11.08L20.985,2.212L11.567,2.212L11.567,11.08C11.567,11.212 11.442,11.318 11.289,11.318L0.702,11.318L0.702,19.402L11.289,19.402C11.442,19.402 11.567,19.509 11.567,19.641Z" style="fill:rgb(102,102,102);"/>
</g>
<g transform="matrix(1,0,0,1,-1.63395,-1.35279)">
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353Z" style="fill:rgb(102,102,102);"/>
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353ZM17.634,3.973C17.634,3.973 14.433,10.375 14.433,10.375L20.835,10.375L17.634,3.973Z" style="fill:rgb(102,102,102);"/>
</g>
<g transform="matrix(6.12323e-17,1,-1,6.12323e-17,33.3528,-1.63395)">
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353Z" style="fill:rgb(102,102,102);"/>
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353ZM17.634,3.973C17.634,3.973 14.433,10.375 14.433,10.375L20.835,10.375L17.634,3.973Z" style="fill:rgb(102,102,102);"/>
</g>
<g transform="matrix(-1,1.22465e-16,-1.22465e-16,-1,33.634,33.3528)">
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353Z" style="fill:rgb(102,102,102);"/>
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353ZM17.634,3.973C17.634,3.973 14.433,10.375 14.433,10.375L20.835,10.375L17.634,3.973Z" style="fill:rgb(102,102,102);"/>
</g>
<g transform="matrix(-1.83697e-16,-1,1,-1.83697e-16,-1.33687,33.6127)">
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353Z" style="fill:rgb(102,102,102);"/>
<path d="M17.634,3.353L21.284,10.653L13.984,10.653L17.634,3.353ZM17.634,3.973C17.634,3.973 14.433,10.375 14.433,10.375L20.835,10.375L17.634,3.973Z" style="fill:rgb(102,102,102);"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cap7e0f05pj8j"
path="res://.godot/imported/logo_editor_small.svg-a18f1eaff840dcdf5215ef26c289caf9.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/guide/editor/logo_editor_small.svg"
dest_files=["res://.godot/imported/logo_editor_small.svg-a18f1eaff840dcdf5215ef26c289caf9.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=0.5
editor/scale_with_editor_scale=true
editor/convert_colors_with_editor_theme=false

View File

@ -0,0 +1,159 @@
@tool
extends MarginContainer
const ClassScanner = preload("../class_scanner.gd")
const Utils = preload("../utils.gd")
const ArrayEdit = preload("../array_edit/array_edit.gd")
@export var action_mapping_editor_scene:PackedScene
@onready var _title_label:Label = %TitleLabel
@onready var _action_mappings:ArrayEdit = %ActionMappings
@onready var _editing_view:Control = %EditingView
@onready var _empty_view = %EmptyView
var _plugin:EditorPlugin
var _current_context:GUIDEMappingContext
var _undo_redo:EditorUndoRedoManager
var _scanner:ClassScanner
func _ready():
_title_label.add_theme_font_override("font", get_theme_font("title", "EditorFonts"))
_scanner = ClassScanner.new()
_editing_view.visible = false
_empty_view.visible = true
_action_mappings.add_requested.connect(_on_action_mappings_add_requested)
_action_mappings.move_requested.connect(_on_action_mappings_move_requested)
_action_mappings.delete_requested.connect(_on_action_mapping_delete_requested)
_action_mappings.clear_requested.connect(_on_action_mappings_clear_requested)
_action_mappings.duplicate_requested.connect(_on_action_mapping_duplicate_requested)
_action_mappings.collapse_state_changed.connect(_on_action_mappings_collapse_state_changed)
func initialize(plugin:EditorPlugin) -> void:
_plugin = plugin
_undo_redo = plugin.get_undo_redo()
func edit(context:GUIDEMappingContext) -> void:
if is_instance_valid(_current_context):
_current_context.changed.disconnect(_refresh)
_current_context = context
if is_instance_valid(_current_context):
_current_context.changed.connect(_refresh)
_refresh()
func _refresh():
_editing_view.visible = is_instance_valid(_current_context)
_empty_view.visible = not is_instance_valid(_current_context)
if not is_instance_valid(_current_context):
return
_title_label.text = _current_context._editor_name()
_title_label.tooltip_text = _current_context.resource_path
_action_mappings.clear()
for i in _current_context.mappings.size():
var mapping = _current_context.mappings[i]
var mapping_editor = action_mapping_editor_scene.instantiate()
mapping_editor.initialize(_plugin, _scanner)
_action_mappings.add_item(mapping_editor)
mapping_editor.edit(mapping)
_action_mappings.collapsed = _current_context.get_meta("_guide_action_mappings_collapsed", false)
func _on_action_mappings_add_requested():
var mappings = _current_context.mappings.duplicate()
var new_mapping := GUIDEActionMapping.new()
# don't set an action because they should come from the file system
mappings.append(new_mapping)
_undo_redo.create_action("Add action mapping")
_undo_redo.add_do_property(_current_context, "mappings", mappings)
_undo_redo.add_undo_property(_current_context, "mappings", _current_context.mappings)
_undo_redo.commit_action()
func _on_action_mappings_move_requested(from:int, to:int):
var mappings = _current_context.mappings.duplicate()
var mapping = mappings[from]
mappings.remove_at(from)
if from < to:
to -= 1
mappings.insert(to, mapping)
_undo_redo.create_action("Move action mapping")
_undo_redo.add_do_property(_current_context, "mappings", mappings)
_undo_redo.add_undo_property(_current_context, "mappings", _current_context.mappings)
_undo_redo.commit_action()
func _on_action_mapping_delete_requested(index:int):
var mappings = _current_context.mappings.duplicate()
mappings.remove_at(index)
_undo_redo.create_action("Delete action mapping")
_undo_redo.add_do_property(_current_context, "mappings", mappings)
_undo_redo.add_undo_property(_current_context, "mappings", _current_context.mappings)
_undo_redo.commit_action()
func _on_action_mappings_clear_requested():
var mappings:Array[GUIDEActionMapping] = []
_undo_redo.create_action("Clear action mappings")
_undo_redo.add_do_property(_current_context, "mappings", mappings)
_undo_redo.add_undo_property(_current_context, "mappings", _current_context.mappings)
_undo_redo.commit_action()
func _on_action_mapping_duplicate_requested(index:int):
var mappings = _current_context.mappings.duplicate()
var to_duplicate:GUIDEActionMapping = mappings[index]
var copy = GUIDEActionMapping.new()
# don't set the action, because each mapping should have a unique mapping
for input_mapping:GUIDEInputMapping in to_duplicate.input_mappings:
var copied_input_mapping := GUIDEInputMapping.new()
copied_input_mapping.input = Utils.duplicate_if_inline(input_mapping.input)
for modifier in input_mapping.modifiers:
copied_input_mapping.modifiers.append(Utils.duplicate_if_inline(modifier))
for trigger in input_mapping.triggers:
copied_input_mapping.triggers.append(Utils.duplicate_if_inline(trigger))
copy.input_mappings.append(copied_input_mapping)
# insert the copy after the copied mapping
mappings.insert(index+1, copy)
_undo_redo.create_action("Duplicate action mapping")
_undo_redo.add_do_property(_current_context, "mappings", mappings)
_undo_redo.add_undo_property(_current_context, "mappings", _current_context.mappings)
_undo_redo.commit_action()
func _on_action_mappings_collapse_state_changed(new_state:bool):
_current_context.set_meta("_guide_action_mappings_collapsed", new_state)

View File

@ -0,0 +1 @@
uid://bpemf1ch2011g

View File

@ -0,0 +1,58 @@
[gd_scene load_steps=4 format=3 uid="uid://dm3hott3tfvwe"]
[ext_resource type="Script" path="res://addons/guide/editor/mapping_context_editor/mapping_context_editor.gd" id="1_vytdu"]
[ext_resource type="PackedScene" uid="uid://361aipcef24h" path="res://addons/guide/editor/action_mapping_editor/action_mapping_editor.tscn" id="2_qb3p8"]
[ext_resource type="PackedScene" uid="uid://cly0ff32fvpb2" path="res://addons/guide/editor/array_edit/array_edit.tscn" id="3_x7h5x"]
[node name="MappingContextEditor" type="MarginContainer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
script = ExtResource("1_vytdu")
action_mapping_editor_scene = ExtResource("2_qb3p8")
[node name="EditingView" type="VBoxContainer" parent="."]
unique_name_in_owner = true
layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="EditingView"]
layout_mode = 2
[node name="TitleLabel" type="Label" parent="EditingView/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 6
text = "narf.tres"
horizontal_alignment = 1
[node name="MarginContainer" type="MarginContainer" parent="EditingView"]
layout_mode = 2
theme_override_constants/margin_bottom = 5
[node name="ScrollContainer" type="ScrollContainer" parent="EditingView"]
layout_mode = 2
size_flags_vertical = 3
[node name="ActionMappings" parent="EditingView/ScrollContainer" instance=ExtResource("3_x7h5x")]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
title = "Action mappings"
add_tooltip = "Add action mapping"
clear_tooltip = "Clear action mappings"
[node name="EmptyView" type="CenterContainer" parent="."]
unique_name_in_owner = true
layout_mode = 2
[node name="Label" type="Label" parent="EmptyView"]
layout_mode = 2
text = "Create and open a GUIDEMappingContext to get started."

View File

@ -0,0 +1,14 @@
@tool
extends "../resource_slot/resource_slot.gd"
var modifier:GUIDEModifier:
set(value):
_value = value
get:
return _value
func _accepts_drop_data(data:Resource) -> bool:
return data is GUIDEModifier

View File

@ -0,0 +1 @@
uid://cmvfuu8u5ubkk

View File

@ -0,0 +1,18 @@
[gd_scene load_steps=2 format=3 uid="uid://ck5a30syo6bpo"]
[ext_resource type="Script" path="res://addons/guide/editor/modifier_slot/modifier_slot.gd" id="1_273m5"]
[node name="LineEdit" type="LineEdit"]
offset_right = 1920.0
offset_bottom = 31.0
size_flags_horizontal = 3
size_flags_vertical = 0
text = "Name"
editable = false
context_menu_enabled = false
virtual_keyboard_enabled = false
shortcut_keys_enabled = false
middle_mouse_paste_enabled = false
selecting_enabled = false
drag_and_drop_selection_enabled = false
script = ExtResource("1_273m5")

View File

@ -0,0 +1,106 @@
@tool
extends LineEdit
signal changed()
const Utils = preload("../utils.gd")
func _ready():
editable = false
context_menu_enabled = false
virtual_keyboard_enabled = false
shortcut_keys_enabled = false
selecting_enabled = false
drag_and_drop_selection_enabled = false
middle_mouse_paste_enabled = false
## The underlying resource. This is opened for editing when the user clicks on the control. Its also
## used when dragging from the control.
var _value:Resource = null:
set(value):
if _value == value:
return
# stop tracking changes to the old resource (if any)
if is_instance_valid(_value):
_value.changed.disconnect(_update_from_value)
_value = value
# track changes to the resource itself
if is_instance_valid(_value):
_value.changed.connect(_update_from_value)
_update_from_value()
changed.emit()
func _update_from_value():
if not is_instance_valid(_value):
text = "<none>"
tooltip_text = ""
remove_theme_color_override("font_uneditable_color")
else:
text = _value._editor_name()
tooltip_text = _value.resource_path
# if the value is shared, we override the font color to indicate that
if not Utils.is_inline(_value):
add_theme_color_override("font_uneditable_color", get_theme_color("accent_color", "Editor"))
queue_redraw()
else:
remove_theme_color_override("font_uneditable_color")
## Can be overridden to handle the drop data. This method is called when the user drops something on the control.
## If the value should be updated ,this method should set the _value property.
func _do_drop_data(data:Resource):
_value = data
## Whether this control can accept drop data. This method is called when the user drags something over the control.
func _accepts_drop_data(data:Resource) -> bool:
return false
func _can_drop_data(at_position, data) -> bool:
if data is Resource:
return _accepts_drop_data(data)
if not data is Dictionary:
return false
if data.has("files"):
for file in data["files"]:
if _accepts_drop_data(ResourceLoader.load(file)):
return true
return false
func _drop_data(at_position, data) -> void:
if data is Resource:
_do_drop_data(data)
return
for file in data["files"]:
var item := ResourceLoader.load(file)
_do_drop_data(item)
func _get_drag_data(at_position: Vector2) -> Variant:
if is_instance_valid(_value):
var _preview := TextureRect.new()
_preview.texture = get_theme_icon("File", "EditorIcons")
set_drag_preview(_preview)
# if the value is shared, we just hand out the resource path
if not Utils.is_inline(_value):
return {"files": [_value.resource_path]}
else:
# otherwise we hand out a shallow copy
return _value.duplicate()
else:
return null
func _gui_input(event):
if event is InputEventMouseButton:
if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
if is_instance_valid(_value):
EditorInterface.edit_resource(_value)

View File

@ -0,0 +1 @@
uid://b7cctlhen71jw

View File

@ -0,0 +1,14 @@
@tool
extends "../resource_slot/resource_slot.gd"
var trigger:GUIDETrigger:
set(value):
_value = value
get:
return _value
func _accepts_drop_data(data:Resource) -> bool:
return data is GUIDETrigger

View File

@ -0,0 +1 @@
uid://dk2lv53ohhes2

View File

@ -0,0 +1,20 @@
[gd_scene load_steps=2 format=3 uid="uid://tk30wnstb0ku"]
[ext_resource type="Script" path="res://addons/guide/editor/trigger_slot/trigger_slot.gd" id="1_wxafc"]
[node name="LineEdit" type="LineEdit"]
unique_name_in_owner = true
offset_right = 1920.0
offset_bottom = 31.0
size_flags_horizontal = 3
size_flags_vertical = 0
tooltip_text = "Delete trigger"
text = "Name"
editable = false
context_menu_enabled = false
virtual_keyboard_enabled = false
shortcut_keys_enabled = false
middle_mouse_paste_enabled = false
selecting_enabled = false
drag_and_drop_selection_enabled = false
script = ExtResource("1_wxafc")

View File

@ -0,0 +1,22 @@
## Removes and frees all children of a node.
static func clear(node:Node):
if not is_instance_valid(node):
return
for child in node.get_children():
node.remove_child(child)
child.queue_free()
## Checks if the given resource is an inline resource. If so, returns a shallow copy,
## otherwise returns the resource. If the resource is null, returns null.
static func duplicate_if_inline(resource:Resource) -> Resource:
if is_inline(resource):
return resource.duplicate()
return resource
## Checks if the given resource is an inline resource.
static func is_inline(resource:Resource) -> bool:
if resource == null:
return false
return resource.resource_path.contains("::") or resource.resource_path == ""

View File

@ -0,0 +1 @@
uid://c2jwjge0gqr1l