From d4cf1d91e83c3593a45922cd232121ef59b9ec9b Mon Sep 17 00:00:00 2001 From: Lexi Quinn Date: Mon, 20 Oct 2025 18:30:21 +1100 Subject: [PATCH] added new track editor ui --- Locales/en.mo | Bin 9222 -> 9436 bytes Locales/en.po | 12 +++ Locales/translation_template.pot | 12 +++ Scenes/TowerBase/dissolve.tres | 4 +- Towers/Assault/tower_stats.tres | 1 - feature_ui.gd | 5 +- feature_ui.tscn | 2 + project.godot | 4 +- remix_menu.gd | 28 ++---- track_editor.gd | 124 +++++++++++++++++++++++++ track_editor.gd.uid | 1 + track_editor.tscn | 154 +++++++++++++++++++++++++++++++ 12 files changed, 319 insertions(+), 28 deletions(-) create mode 100644 track_editor.gd create mode 100644 track_editor.gd.uid create mode 100644 track_editor.tscn diff --git a/Locales/en.mo b/Locales/en.mo index 29a2f0b14f11f508527df14b150523ba82865664..92c333f2aad1704d46ba213050e73cd0c7694121 100644 GIT binary patch delta 3109 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 void: + +func set_feature(new_feature: Feature) -> void: + feature = new_feature icon.texture = feature.icon name_label.text = tr(feature.display_name) diff --git a/feature_ui.tscn b/feature_ui.tscn index 9ac4a36..6272c09 100644 --- a/feature_ui.tscn +++ b/feature_ui.tscn @@ -9,12 +9,14 @@ anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +alignment = 1 script = ExtResource("1_tms0v") icon = NodePath("TextureRect") name_label = NodePath("Label") [node name="TextureRect" type="TextureRect" parent="."] layout_mode = 2 +mouse_filter = 2 texture = ExtResource("2_w6jf0") stretch_mode = 5 diff --git a/project.godot b/project.godot index b0f30ae..c76451a 100644 --- a/project.godot +++ b/project.godot @@ -13,7 +13,7 @@ config_version=5 config/name="Decked Out Defense" config/version="0.3.0" run/main_scene="uid://d2k8y13qfvch0" -config/features=PackedStringArray("4.4", "Forward Plus") +config/features=PackedStringArray("4.5", "Forward Plus") boot_splash/show_image=false config/icon="res://Assets/Textures/icon.svg" @@ -56,8 +56,8 @@ import/blender/enabled=false [gui] -theme/custom="uid://b6a0ip4p72tgx" theme/default_font_antialiasing=0 +theme/custom="uid://b6a0ip4p72tgx" [input] diff --git a/remix_menu.gd b/remix_menu.gd index abbb029..32c88e9 100644 --- a/remix_menu.gd +++ b/remix_menu.gd @@ -44,33 +44,17 @@ func set_card_two(option: int) -> void: func remix() -> void: - temp_card_one = Card.new() - temp_card_one.cost = card_one.cost - temp_card_one.faction = card_one.faction - temp_card_one.rarity = card_one.rarity - temp_card_one.tags = card_one.tags - temp_card_one.icon = card_one.icon - temp_card_one.display_name = card_one.display_name - temp_card_one.turret_scene = card_one.turret_scene - temp_card_one.weapon_scene = card_one.weapon_scene - temp_card_one.tower_stats = card_one.tower_stats.duplicate() - temp_card_one.weapon_stats = card_one.weapon_stats.duplicate() + temp_card_one = card_one.duplicate(true) + temp_card_one.tower_stats = temp_card_one.tower_stats.duplicate_deep() + temp_card_one.weapon_stats = temp_card_one.weapon_stats.duplicate_deep() for feature: Feature in card_two.tower_stats.features: temp_card_one.tower_stats.features.append(feature) for feature: Feature in card_two.weapon_stats.features: temp_card_one.weapon_stats.features.append(feature) - temp_card_two = Card.new() - temp_card_two.cost = card_two.cost - temp_card_two.faction = card_two.faction - temp_card_two.rarity = card_two.rarity - temp_card_two.tags = card_two.tags - temp_card_two.icon = card_two.icon - temp_card_two.display_name = card_two.display_name - temp_card_two.turret_scene = card_two.turret_scene - temp_card_two.weapon_scene = card_two.weapon_scene - temp_card_two.tower_stats = card_two.tower_stats.duplicate() - temp_card_two.weapon_stats = card_two.weapon_stats.duplicate() + temp_card_two = card_two.duplicate(true) + temp_card_two.tower_stats = temp_card_two.tower_stats.duplicate_deep() + temp_card_two.weapon_stats = temp_card_two.weapon_stats.duplicate_deep() for feature: Feature in card_one.tower_stats.features: temp_card_two.tower_stats.features.append(feature) for feature: Feature in card_one.weapon_stats.features: diff --git a/track_editor.gd b/track_editor.gd new file mode 100644 index 0000000..aced394 --- /dev/null +++ b/track_editor.gd @@ -0,0 +1,124 @@ +class_name TrackEditor +extends Control + +@export var drag_feature: FeatureUI +@export var sample_library: VBoxContainer +@export var feature_scene: PackedScene +@export var features_list: Array[Feature] +@export var parts: HBoxContainer + +var dragging: bool = false +var hovered_feature: Feature +var hovered_drop_slot: int = -2 +var feature_uis: Array[FeatureUI] +var slots: Array[VBoxContainer] + +const FEATURE_SLOTS: int = 6 + + +func _ready() -> void: + populate_sample_library() + populate_feature_slots() + parts.mouse_entered.connect(set_hovered_drop_slot.bind(-1)) + parts.mouse_exited.connect(unset_hovered_drop_slot) + + +func _process(_delta: float) -> void: + drag_feature.position = get_viewport().get_mouse_position() + + +func _input(event: InputEvent) -> void: + if event is InputEventMouseButton: + if event.pressed == true and event.button_index == 1: + if hovered_feature != null: + attach_feat_to_mouse(hovered_feature) + if event.pressed == false and event.button_index == 1: + detach_feat_from_mouse() + + +func populate_sample_library() -> void: + for x: int in 3: + var hbox: HBoxContainer = HBoxContainer.new() + hbox.size_flags_vertical = Control.SIZE_EXPAND_FILL + for y: int in 3: + var feat: FeatureUI = feature_scene.instantiate() as FeatureUI + feat.set_feature(features_list[x]) + feat.mouse_filter = Control.MOUSE_FILTER_PASS + feat.size_flags_horizontal = Control.SIZE_EXPAND_FILL + feat.mouse_entered.connect(set_hovered_feature.bind(feat.feature)) + hbox.add_child(feat) + sample_library.add_child(hbox) + sample_library.mouse_exited.connect(unset_hovered_feature) + + +func populate_feature_slots() -> void: + for x: int in FEATURE_SLOTS: + var vbox: VBoxContainer = VBoxContainer.new() + var label: Label = Label.new() + match slots.size(): + 0: label.text = tr("SLOT_FIRST") + 1: label.text = tr("SLOT_SECOND") + 2: label.text = tr("SLOT_THIRD") + 3: label.text = tr("SLOT_FOURTH") + 4: label.text = tr("SLOT_FIFTH") + 5: label.text = tr("SLOT_SIXTH") + label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + vbox.add_child(label) + vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL + vbox.mouse_filter = Control.MOUSE_FILTER_STOP + vbox.mouse_entered.connect(set_hovered_drop_slot.bind(slots.size())) + vbox.mouse_exited.connect(unset_hovered_drop_slot) + parts.add_child(vbox) + slots.append(vbox) + + +func add_feature(feature: Feature) -> void: + if hovered_drop_slot >= 0 and hovered_drop_slot < feature_uis.size(): + change_feature(feature_uis[hovered_drop_slot], feature) + elif feature_uis.size() < FEATURE_SLOTS: + var feature_visual: FeatureUI = feature_scene.instantiate() + feature_visual.set_feature(feature) + slots[feature_uis.size()].add_child(feature_visual) + feature_uis.append(feature_visual) + + +func change_feature(existing_feature: FeatureUI, new_feature: Feature) -> void: + existing_feature.set_feature(new_feature) + + +func attach_feat_to_mouse(feature: Feature) -> void: + drag_feature.set_feature(feature) + drag_feature.visible = true + dragging = true + + +func detach_feat_from_mouse() -> void: + drag_feature.visible = false + if hovered_drop_slot >= -1 and dragging == true: + add_feature(drag_feature.feature) + dragging = false + + +func set_hovered_feature(feature: Feature) -> void: + hovered_feature = feature + + +func unset_hovered_feature() -> void: + hovered_feature = null + + +func set_hovered_drop_slot(slot: int = -2) -> void: + hovered_drop_slot = slot + + +func unset_hovered_drop_slot() -> void: + hovered_drop_slot = -2 + + +func _on_cancel_button_pressed() -> void: + queue_free() + + +func _on_confirm_button_pressed() -> void: + pass # Replace with function body. diff --git a/track_editor.gd.uid b/track_editor.gd.uid new file mode 100644 index 0000000..89e2908 --- /dev/null +++ b/track_editor.gd.uid @@ -0,0 +1 @@ +uid://mrv5vrlxfc13 diff --git a/track_editor.tscn b/track_editor.tscn new file mode 100644 index 0000000..f5634ad --- /dev/null +++ b/track_editor.tscn @@ -0,0 +1,154 @@ +[gd_scene load_steps=7 format=3 uid="uid://bajli4d3nqwll"] + +[ext_resource type="PackedScene" uid="uid://c8xdsg6gtwvh3" path="res://feature_ui.tscn" id="1_y6tpq"] +[ext_resource type="Script" uid="uid://mrv5vrlxfc13" path="res://track_editor.gd" id="1_yrnbk"] +[ext_resource type="Script" uid="uid://bsuinotkvh7eu" path="res://Scripts/Resources/feature.gd" id="3_dya4i"] +[ext_resource type="Resource" uid="uid://nh7g23b3rnvr" path="res://Scripts/Features/Radar/radar_feature.tres" id="4_4gmyw"] +[ext_resource type="Resource" uid="uid://dfup264h2pun7" path="res://Scripts/Features/HeavyRounds/heavy_rounds_feature.tres" id="5_dxngn"] +[ext_resource type="Resource" uid="uid://bij61ul87ka0r" path="res://Scripts/Features/ExtendedBarrel/extended_barrel_feature.tres" id="6_1rakx"] + +[node name="Control" type="Control" node_paths=PackedStringArray("drag_feature", "sample_library", "parts")] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_yrnbk") +drag_feature = NodePath("FeatureUI") +sample_library = NodePath("PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2/SamplePanel/SampleLibrary") +feature_scene = ExtResource("1_y6tpq") +features_list = Array[ExtResource("3_dya4i")]([ExtResource("4_4gmyw"), ExtResource("5_dxngn"), ExtResource("6_1rakx")]) +parts = NodePath("PanelContainer/VBoxContainer/VBoxContainer/SourceCartridge/Parts") + +[node name="PanelContainer" type="PanelContainer" parent="."] +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.175 +anchor_top = 0.05 +anchor_right = 0.825 +anchor_bottom = 0.95 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +text = "TITLE_REMIX" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="SourceCartridge" type="HBoxContainer" parent="PanelContainer/VBoxContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="CassetteSelector" type="VBoxContainer" parent="PanelContainer/VBoxContainer/VBoxContainer/SourceCartridge"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/VBoxContainer/SourceCartridge/CassetteSelector"] +layout_mode = 2 +text = "LABEL_CASSETTE_SELECTOR" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="OptionButton" type="OptionButton" parent="PanelContainer/VBoxContainer/VBoxContainer/SourceCartridge/CassetteSelector"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Parts" type="HBoxContainer" parent="PanelContainer/VBoxContainer/VBoxContainer/SourceCartridge"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 3.0 + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +size_flags_stretch_ratio = 0.1 + +[node name="InfoPanel" type="HBoxContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +size_flags_stretch_ratio = 5.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/InfoPanel"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer"] +layout_mode = 2 +text = "LABEL_CARD_DESCRIPTION" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="RichTextLabel" type="RichTextLabel" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +bbcode_enabled = true +text = "a long ass example description of a card that goes into honestly way too much detail but at least if we can support a lot of text at a good size then we dont have to worry about really complicated cards fucking up our UI later in developement if we end up needing to explain a lot" + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer"] +layout_mode = 2 +text = "LABEL_TARGET_LIST" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer/InfoPanel"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 0.1 + +[node name="VBoxContainer2" type="VBoxContainer" parent="PanelContainer/VBoxContainer/InfoPanel"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="SamplePanel" type="VBoxContainer" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2/SamplePanel"] +layout_mode = 2 +text = "TITLE_SAMPLES" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="SampleLibrary" type="VBoxContainer" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2/SamplePanel"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Controls" type="HBoxContainer" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2"] +layout_mode = 2 +alignment = 2 + +[node name="CancelButton" type="Button" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2/Controls"] +layout_mode = 2 +text = "BUTTON_CANCEL" + +[node name="ConfirmButton" type="Button" parent="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2/Controls"] +layout_mode = 2 +text = "BUTTON_CONFIRM_REMIX" + +[node name="FeatureUI" parent="." instance=ExtResource("1_y6tpq")] +visible = false +layout_mode = 0 +anchors_preset = 0 +anchor_right = 0.0 +anchor_bottom = 0.0 +grow_horizontal = 1 +grow_vertical = 1 +mouse_filter = 2 + +[connection signal="pressed" from="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2/Controls/CancelButton" to="." method="_on_cancel_button_pressed"] +[connection signal="pressed" from="PanelContainer/VBoxContainer/InfoPanel/VBoxContainer2/Controls/ConfirmButton" to="." method="_on_confirm_button_pressed"]