From ef00f4c50dfab6358fa938c9467dd225e0911163 Mon Sep 17 00:00:00 2001 From: edintomato2 <156262199+edintomato2@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:43:56 -0500 Subject: [PATCH] Gomez Placer, Trileset loader Add the ability to place Gomez as the starting point for a level, improved object detection for the cursor, and implemented a palette picker. We have the bare minimum! --- Defaults/default.tres | 12 ++- Scenes/UI.tscn | 184 +++++++++++++++++++++++++------- Scripts/Cursor.gd | 5 + Scripts/Exporter/Exporter.gd | 2 +- Scripts/Importer/Importer.gd | 29 +++-- Scripts/Settings.gd | 2 +- Scripts/UI/Titlebar/menuFile.gd | 24 ++++- Scripts/UI/Toolbar/NPCs.gd | 11 ++ Scripts/UI/Toolbar/Palette.gd | 30 ------ Scripts/UI/Toolbar/Triles.gd | 50 +++++++++ Scripts/UI/UI.gd | 110 +++++++++++++------ export_presets.cfg | 40 ------- 12 files changed, 340 insertions(+), 159 deletions(-) create mode 100644 Scripts/UI/Toolbar/NPCs.gd delete mode 100644 Scripts/UI/Toolbar/Palette.gd create mode 100644 Scripts/UI/Toolbar/Triles.gd diff --git a/Defaults/default.tres b/Defaults/default.tres index 438497a..74ba54e 100644 --- a/Defaults/default.tres +++ b/Defaults/default.tres @@ -1,4 +1,4 @@ -[gd_resource type="Theme" load_steps=4 format=3 uid="uid://5wxvr808qkyw"] +[gd_resource type="Theme" load_steps=5 format=3 uid="uid://5wxvr808qkyw"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jyao1"] bg_color = Color(0, 0, 0, 0.196078) @@ -6,6 +6,11 @@ border_width_top = 2 border_color = Color(0, 0, 0, 1) border_blend = true +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rx68y"] +bg_color = Color(0, 0, 0, 0.196078) +border_width_left = 2 +border_color = Color(0, 0, 0, 1) + [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mceqj"] content_margin_left = 6.0 content_margin_right = 6.0 @@ -14,13 +19,12 @@ bg_color = Color(0, 0, 0, 1) [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7tf7i"] bg_color = Color(0, 0, 0, 0.196078) border_width_left = 2 -border_width_top = 2 -border_width_bottom = 2 border_color = Color(0, 0, 0, 1) -border_blend = true [resource] HBoxContainer/constants/separation = 0 ItemList/styles/panel = SubResource("StyleBoxFlat_jyao1") +Label/styles/normal = SubResource("StyleBoxFlat_rx68y") MenuButton/styles/normal = SubResource("StyleBoxFlat_mceqj") RichTextLabel/styles/normal = SubResource("StyleBoxFlat_7tf7i") +VSplitContainer/constants/separation = 0 diff --git a/Scenes/UI.tscn b/Scenes/UI.tscn index 6745382..fe2cab6 100644 --- a/Scenes/UI.tscn +++ b/Scenes/UI.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=24 format=3 uid="uid://cdwpy8hm6qseq"] +[gd_scene load_steps=29 format=3 uid="uid://cdwpy8hm6qseq"] [ext_resource type="Script" path="res://Scripts/UI/UI.gd" id="1_yufu8"] [ext_resource type="Theme" uid="uid://5wxvr808qkyw" path="res://Defaults/default.tres" id="2_pfeim"] @@ -8,7 +8,8 @@ [ext_resource type="PackedScene" uid="uid://baepcmjcgsbk0" path="res://Objects/Compass.glb" id="6_exilt"] [ext_resource type="Script" path="res://Scripts/UI/Sidebar/EditorInfo.gd" id="7_jfdyk"] [ext_resource type="Script" path="res://Scripts/UI/Compass.gd" id="7_lgwbb"] -[ext_resource type="Script" path="res://Scripts/UI/Toolbar/Palette.gd" id="10_yvdlw"] +[ext_resource type="Script" path="res://Scripts/UI/Toolbar/Triles.gd" id="9_4swbr"] +[ext_resource type="Script" path="res://Scripts/UI/Toolbar/NPCs.gd" id="10_2driq"] [ext_resource type="Script" path="res://Scripts/Importer/Importer.gd" id="11_b3xhm"] [ext_resource type="Script" path="res://Scripts/Exporter/Exporter.gd" id="12_4xdn3"] @@ -36,6 +37,14 @@ keycode = 83 [sub_resource type="Shortcut" id="Shortcut_c4g0v"] events = [SubResource("InputEventKey_txw7b")] +[sub_resource type="InputEventKey" id="InputEventKey_pptsy"] +device = -1 +ctrl_pressed = true +keycode = 78 + +[sub_resource type="Shortcut" id="Shortcut_o221s"] +events = [SubResource("InputEventKey_pptsy")] + [sub_resource type="InputEventKey" id="InputEventKey_slhck"] device = -1 ctrl_pressed = true @@ -60,6 +69,14 @@ keycode = 72 [sub_resource type="Shortcut" id="Shortcut_efjk7"] events = [SubResource("InputEventKey_oq4ek")] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mn0ei"] +bg_color = Color(0, 0, 0, 0.196078) +border_width_left = 2 +border_color = Color(0, 0, 0, 1) + +[sub_resource type="Theme" id="Theme_328gk"] +Label/styles/normal = SubResource("StyleBoxFlat_mn0ei") + [node name="UI" type="VBoxContainer"] anchors_preset = 15 anchor_right = 1.0 @@ -68,6 +85,7 @@ grow_horizontal = 2 grow_vertical = 2 size_flags_horizontal = 3 size_flags_vertical = 3 +theme_override_constants/separation = 0 script = ExtResource("1_yufu8") [node name="Titlebar" type="HBoxContainer" parent="."] @@ -80,22 +98,25 @@ shortcut = SubResource("Shortcut_aqtus") text = "File" flat = false switch_on_hover = true -item_count = 5 +item_count = 6 popup/item_0/text = "Load Level" popup/item_0/id = 0 popup/item_1/text = "Save Level" popup/item_1/id = 1 popup/item_1/disabled = true -popup/item_2/text = "Options" -popup/item_2/id = 2 -popup/item_3/text = "" -popup/item_3/id = 3 -popup/item_3/separator = true -popup/item_4/text = "Quit" -popup/item_4/id = 4 +popup/item_2/text = "New Level" +popup/item_2/id = 5 +popup/item_3/text = "Options" +popup/item_3/id = 2 +popup/item_4/text = "" +popup/item_4/id = 3 +popup/item_4/separator = true +popup/item_5/text = "Quit" +popup/item_5/id = 4 script = ExtResource("3_mnd5b") loadShortcut = SubResource("Shortcut_8hi2n") saveShortcut = SubResource("Shortcut_c4g0v") +newShortcut = SubResource("Shortcut_o221s") quitShortcut = SubResource("Shortcut_x4u3j") [node name="Load" type="FileDialog" parent="Titlebar/File"] @@ -103,6 +124,7 @@ title = "Open a File" initial_position = 1 size = Vector2i(454, 400) ok_button_text = "Open" +dialog_hide_on_ok = true file_mode = 0 access = 2 filters = PackedStringArray("*.fezlvl.json ; FEZ Levels") @@ -111,11 +133,22 @@ use_native_dialog = true [node name="Save" type="FileDialog" parent="Titlebar/File"] title = "Save FEZLVL as" initial_position = 2 +ok_button_text = "Save" dialog_hide_on_ok = true access = 2 filters = PackedStringArray("*.fezlvl.json ; FEZ Levels") use_native_dialog = true +[node name="New" type="FileDialog" parent="Titlebar/File"] +title = "Open a File" +initial_position = 2 +ok_button_text = "Open" +dialog_hide_on_ok = true +file_mode = 0 +access = 2 +filters = PackedStringArray("*.fezts.json ; FEZ Trileset") +use_native_dialog = true + [node name="Edit" type="MenuButton" parent="Titlebar"] layout_mode = 2 text = "Edit" @@ -128,18 +161,16 @@ shortcut = SubResource("Shortcut_5p5ho") text = "View" flat = false switch_on_hover = true -item_count = 5 -popup/item_0/text = "Palette" -popup/item_0/id = 0 -popup/item_1/text = "Hide layers..." -popup/item_1/id = 1 -popup/item_2/text = "" -popup/item_2/id = 10 -popup/item_2/separator = true -popup/item_3/text = "Debug terminal" -popup/item_3/id = 2 -popup/item_4/text = "Raw FEZLVL.JSON" -popup/item_4/id = 3 +item_count = 4 +popup/item_0/text = "Hide layers..." +popup/item_0/id = 1 +popup/item_1/text = "" +popup/item_1/id = 10 +popup/item_1/separator = true +popup/item_2/text = "Debug terminal" +popup/item_2/id = 2 +popup/item_3/text = "Raw FEZLVL.JSON" +popup/item_3/id = 3 [node name="Help" type="MenuButton" parent="Titlebar"] layout_mode = 2 @@ -195,34 +226,44 @@ size_flags_horizontal = 3 mouse_filter = 1 color = Color(0, 0, 0, 1) -[node name="Sidebar" type="HBoxContainer" parent="."] +[node name="VSplitContainer" type="VSplitContainer" parent="."] +clip_contents = true +layout_mode = 2 +size_flags_vertical = 3 +theme = ExtResource("2_pfeim") + +[node name="Sidebar" type="HBoxContainer" parent="VSplitContainer"] layout_mode = 2 size_flags_vertical = 3 size_flags_stretch_ratio = 15.0 -[node name="Spacer" type="Container" parent="Sidebar"] +[node name="Spacer" type="Control" parent="VSplitContainer/Sidebar"] layout_mode = 2 size_flags_horizontal = 3 size_flags_stretch_ratio = 5.3 +mouse_filter = 1 -[node name="SidebarVertical" type="VBoxContainer" parent="Sidebar"] +[node name="SidebarVertical" type="VBoxContainer" parent="VSplitContainer/Sidebar"] layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 +theme_override_constants/separation = 0 -[node name="Position" type="Label" parent="Sidebar/SidebarVertical"] +[node name="Position" type="Label" parent="VSplitContainer/Sidebar/SidebarVertical"] layout_mode = 2 mouse_filter = 1 +theme = SubResource("Theme_328gk") text = "[0, 0, 0]" horizontal_alignment = 1 -[node name="Object" type="Label" parent="Sidebar/SidebarVertical"] +[node name="Object" type="Label" parent="VSplitContainer/Sidebar/SidebarVertical"] layout_mode = 2 mouse_filter = 1 +theme = ExtResource("2_pfeim") text = "None" horizontal_alignment = 1 -[node name="EditorLog" type="RichTextLabel" parent="Sidebar/SidebarVertical"] +[node name="EditorLog" type="RichTextLabel" parent="VSplitContainer/Sidebar/SidebarVertical"] layout_mode = 2 size_flags_vertical = 3 theme = ExtResource("2_pfeim") @@ -232,51 +273,114 @@ scroll_following = true threaded = true script = ExtResource("7_jfdyk") -[node name="CompassView" type="SubViewportContainer" parent="Sidebar/SidebarVertical"] +[node name="CompassView" type="SubViewportContainer" parent="VSplitContainer/Sidebar/SidebarVertical"] visible = false layout_mode = 2 size_flags_vertical = 3 size_flags_stretch_ratio = 0.5 stretch = true -[node name="Compass" type="SubViewport" parent="Sidebar/SidebarVertical/CompassView"] +[node name="Compass" type="SubViewport" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView"] transparent_bg = true handle_input_locally = false size = Vector2i(2, 2) render_target_update_mode = 0 -[node name="Compass" parent="Sidebar/SidebarVertical/CompassView/Compass" instance=ExtResource("6_exilt")] +[node name="Compass" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView/Compass" instance=ExtResource("6_exilt")] transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0, 0, 0) visible = false script = ExtResource("7_lgwbb") -[node name="CompPivot" type="Node3D" parent="Sidebar/SidebarVertical/CompassView/Compass"] +[node name="CompPivot" type="Node3D" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView/Compass"] transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0, 0, 0) -[node name="CompassCam" type="Camera3D" parent="Sidebar/SidebarVertical/CompassView/Compass/CompPivot"] +[node name="CompassCam" type="Camera3D" parent="VSplitContainer/Sidebar/SidebarVertical/CompassView/Compass/CompPivot"] transform = Transform3D(0.707107, -0.380969, 0.595704, 0, 0.842453, 0.538771, -0.707107, -0.380969, 0.595704, 6.79999, 6.79999, 6.79999) cull_mask = 1 projection = 1 size = 10.0 far = 20.0 -[node name="Toolbar" type="HBoxContainer" parent="."] +[node name="Toolbar" type="HBoxContainer" parent="VSplitContainer"] +clip_contents = true +custom_minimum_size = Vector2(0, 1) layout_mode = 2 size_flags_vertical = 3 +theme_override_constants/separation = 0 -[node name="TextureButton" type="TextureButton" parent="Toolbar"] +[node name="ChoosePalette" type="OptionButton" parent="VSplitContainer/Toolbar"] layout_mode = 2 +alignment = 1 +item_count = 3 +selected = 0 +fit_to_longest_item = false +popup/item_0/text = "Triles" +popup/item_0/id = 0 +popup/item_0/disabled = true +popup/item_1/text = "Art Objects" +popup/item_1/id = 1 +popup/item_1/disabled = true +popup/item_2/text = "NPCs" +popup/item_2/id = 2 +popup/item_2/disabled = true -[node name="Palette" type="ItemList" parent="Toolbar"] +[node name="Palettes" type="Control" parent="VSplitContainer/Toolbar"] layout_mode = 2 size_flags_horizontal = 3 +mouse_filter = 2 + +[node name="Triles" type="ItemList" parent="VSplitContainer/Toolbar/Palettes"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +mouse_force_pass_scroll_events = false +theme = ExtResource("2_pfeim") +allow_search = false +max_columns = 0 +same_column_width = true +icon_mode = 0 +icon_scale = 2.0 +script = ExtResource("9_4swbr") + +[node name="AOs" type="ItemList" parent="VSplitContainer/Toolbar/Palettes"] +visible = false +clip_contents = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 +mouse_force_pass_scroll_events = false +theme = ExtResource("2_pfeim") +allow_search = false +max_columns = 0 +same_column_width = true +icon_mode = 0 +icon_scale = 2.0 + +[node name="NPCs" type="ItemList" parent="VSplitContainer/Toolbar/Palettes"] +visible = false +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 3 mouse_force_pass_scroll_events = false theme = ExtResource("2_pfeim") allow_search = false max_columns = 0 same_column_width = true +icon_mode = 0 icon_scale = 2.0 -script = ExtResource("10_yvdlw") +script = ExtResource("10_2driq") [node name="SFX" type="AudioStreamPlayer" parent="."] @@ -296,9 +400,11 @@ script = ExtResource("12_4xdn3") [connection signal="confirmed" from="Titlebar/File/Load" to="." method="_on_load_dialog_confirmed"] [connection signal="file_selected" from="Titlebar/File/Load" to="Loader" method="_on_load_dialog_file_selected"] [connection signal="file_selected" from="Titlebar/File/Save" to="Exporter" method="_on_save_file_selected"] +[connection signal="file_selected" from="Titlebar/File/New" to="Titlebar/File" method="_on_new_file_selected"] [connection signal="close_requested" from="Titlebar/Help/About" to="Titlebar/Help" method="_on_about_close_requested"] +[connection signal="item_selected" from="VSplitContainer/Toolbar/ChoosePalette" to="VSplitContainer/Toolbar/Palettes/Triles" method="_on_choose_palette_item_selected"] [connection signal="levelJSON" from="Loader" to="Titlebar/File" method="_on_loader_level_json"] [connection signal="levelJSON" from="Loader" to="Titlebar/View" method="_on_loader_level_json"] -[connection signal="levelJSON" from="Loader" to="Sidebar/SidebarVertical/EditorLog" method="_on_loader_level_json"] -[connection signal="loadedTS" from="Loader" to="Toolbar/Palette" method="_on_loader_loaded_ts"] +[connection signal="levelJSON" from="Loader" to="VSplitContainer/Sidebar/SidebarVertical/EditorLog" method="_on_loader_level_json"] +[connection signal="loadedTS" from="Loader" to="VSplitContainer/Toolbar/Palettes/Triles" method="_on_loader_loaded_ts"] [connection signal="newCurPor" from="Loader" to="." method="_on_loader_new_cur_por"] diff --git a/Scripts/Cursor.gd b/Scripts/Cursor.gd index 710a771..c360028 100644 --- a/Scripts/Cursor.gd +++ b/Scripts/Cursor.gd @@ -16,6 +16,10 @@ func tweenToPos(obj: Object, property: NodePath, direction: Variant, action, spe allowMove = false var tween = create_tween().set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_CIRC) + + if typeof(direction) == TYPE_VECTOR3: # Round position down. + direction = round(direction) + tween.tween_property(obj, property, direction, speed) emit_signal("hasMoved", action) @@ -40,6 +44,7 @@ func _process(_delta): func _unhandled_input(_event): if allowMove: # Movement control. Why does this have to be a bunch of if statements? + # Yes, this is reversed, but that's because of the position of the camera. var forward = transform.basis.z; var right = -transform.basis.x var _moveTo = Vector3.ZERO # Prevent cursor from going below (0, 0, 0) diff --git a/Scripts/Exporter/Exporter.gd b/Scripts/Exporter/Exporter.gd index b1229ba..5ca4e1b 100644 --- a/Scripts/Exporter/Exporter.gd +++ b/Scripts/Exporter/Exporter.gd @@ -67,7 +67,7 @@ func _saveFEZLVL(path, filename): "StartingPoint": var id = obj.get_meta("Id") var face = obj.get_meta("Face") - var spDict = { "Id": id, "Face": face} + var spDict = { "Id": [id[0], id[1], id[2] - 1], "Face": face} template["StartingPosition"] = spDict pass diff --git a/Scripts/Importer/Importer.gd b/Scripts/Importer/Importer.gd index 62ad868..66f83ae 100644 --- a/Scripts/Importer/Importer.gd +++ b/Scripts/Importer/Importer.gd @@ -30,13 +30,17 @@ func _ready(): pass func _on_load_dialog_file_selected(path): - for n in get_child_count(): # Clear out all objects. - get_child(n).queue_free() + killChildren() _mutex.lock(); _path = path; _mutex.unlock(); # Send file path to thread. _sema.post() # Tell thread to start processing. pass +func killChildren(): # Please do not judge my function names. + for n in get_child_count(): # Clear out all objects. + get_child(n).queue_free() + pass + func _loadFEZLVL(): while true: _sema.wait() # Wait for signal from main thread to start processing. @@ -57,7 +61,7 @@ func _loadFEZLVL(): if err == OK: var lvlData = readLvl.data # Load trileset. - trileset = await _loadObj(Settings.TSDir + lvlData["TrileSetName"].to_lower() + ".fezts.json", 2) + trileset = await loadObj(Settings.TSDir + lvlData["TrileSetName"].to_lower() + ".fezts.json", 2) # Place fezlvl triles into scene. var trilePlacements = lvlData["Triles"] # Extract emplacements, phi, and trile ID. @@ -87,7 +91,7 @@ func _loadFEZLVL(): else: print("Error reading .fezlvl.") -func _loadObj(filepath: String, type: int = 4): +func loadObj(filepath: String, type: int = 4): var cleanPath = filepath.get_basename() match type: 2: # Load trileset as ArrayMesh, and trile names as Dictionary. @@ -183,7 +187,7 @@ func placeAO(dir, ao): var rot = ao["Rotation"] var scale = ao["Scale"] - var obj = await _loadObj(dir + objName + ".fezao.json") + var obj = await loadObj(dir + objName + ".fezao.json") obj.quaternion = Quaternion(rot[0], rot[1], rot[2], rot[3]) obj.scale = Vector3(scale[0], scale[1], scale[2]) @@ -210,6 +214,15 @@ func placeStart(dir, posArray): gomez.texture_filter = BaseMaterial3D.TEXTURE_FILTER_NEAREST gomez.scale = Vector3(5, 5, 5) + var statBod = StaticBody3D.new() # Set up collisions for Cursor + var colBod = CollisionShape3D.new() + var colShape = SphereShape3D.new() + + colShape.radius = 0.05 + colBod.shape = colShape + statBod.add_child(colBod) + gomez.add_child(statBod) + # Figuring out where to place him var posStr = posArray["Id"] var face = posArray["Face"] @@ -217,19 +230,21 @@ func placeStart(dir, posArray): match face: # Test with levels to find out where we should place Gomez! "Front": adjust = Vector3.FORWARD - "Back": adjust = Vector3.DOWN + "Back": adjust = Vector3.BACK "Left": adjust = Vector3.LEFT "Right": adjust = Vector3.RIGHT "Top": adjust = Vector3.UP "Down": adjust = Vector3.DOWN - var pos = Vector3(posStr[0], posStr[1], posStr[2]) - adjust + var pos = Vector3(posStr[0], posStr[1], posStr[2]) + adjust gomez.position = pos gomez.layers = 8 gomez.set_meta("Type", "StartingPoint") gomez.set_meta("Id", posStr) gomez.set_meta("Face", face) + gomez.set_meta("Name", "Gomez") + gomez.play("gif") call_deferred("add_child", gomez) return pos diff --git a/Scripts/Settings.gd b/Scripts/Settings.gd index 2a287d6..8556128 100644 --- a/Scripts/Settings.gd +++ b/Scripts/Settings.gd @@ -12,7 +12,7 @@ var NPCDir var TSDir func _ready(): # Load saved data, if available. - var err = config.load("user://HARDHAT.cfg") + var err = config.load("user://Beret.cfg") if err != OK: # If not, have the user set up save data. var s = preload("res://Scenes/NoDirs.tscn") get_tree().change_scene_to_packed(s) diff --git a/Scripts/UI/Titlebar/menuFile.gd b/Scripts/UI/Titlebar/menuFile.gd index 2ef2656..c8cce7d 100644 --- a/Scripts/UI/Titlebar/menuFile.gd +++ b/Scripts/UI/Titlebar/menuFile.gd @@ -2,16 +2,24 @@ extends MenuButton @onready var _fdLoad = $Load @onready var _svFile = $Save +@onready var _nwFile = $New + +@onready var _ldr = $"../../Loader" @export var loadShortcut: Shortcut @export var saveShortcut: Shortcut +@export var newShortcut: Shortcut @export var quitShortcut: Shortcut func _ready(): self.get_popup().id_pressed.connect(_on_file_menu_pressed) get_popup().set_item_shortcut(0, loadShortcut, true) get_popup().set_item_shortcut(1, saveShortcut, true) - get_popup().set_item_shortcut(4, quitShortcut, true) + get_popup().set_item_shortcut(5, quitShortcut, true) + get_popup().set_item_shortcut(2, newShortcut, true) + + _fdLoad.root_subfolder = Settings.LVLDir + _nwFile.root_subfolder = Settings.TSDir func _on_file_menu_pressed(id: int): match id: @@ -23,9 +31,21 @@ func _on_file_menu_pressed(id: int): print("To do!") 4: get_tree().root.propagate_notification(NOTIFICATION_WM_CLOSE_REQUEST) + 5: + _nwFile.visible = true func _on_loader_level_json(_lvlJSON, _trileNum, _aoNum, _npcNum): # Once a level is loaded, let the user save. get_popup().set_item_disabled(1, false) - pass # Replace with function body. + pass + +func _on_new_file_selected(path: String): + var cleanPath = path.get_basename() + ".json" + # Have the user choose a trileset, and let the user save. + get_popup().set_item_disabled(1, false) + _ldr.killChildren() # Clear out all objects + var trileset = await _ldr.loadObj(cleanPath, 2) + _ldr.trileset = trileset # Let the importer know we have loaded a new TS + _ldr.loadedTS.emit(trileset) + pass diff --git a/Scripts/UI/Toolbar/NPCs.gd b/Scripts/UI/Toolbar/NPCs.gd new file mode 100644 index 0000000..a210eb6 --- /dev/null +++ b/Scripts/UI/Toolbar/NPCs.gd @@ -0,0 +1,11 @@ +extends ItemList + +# Called when the node enters the scene tree for the first time. +func _ready(): + # For now, we'll only let the user place Gomez as the starting point. + var gif = GifManager.sprite_frames_from_file(Settings.NPCDir + "gomez/idlewink.gif") + var tex = gif.get_frame_texture("gif", 0) + + var idx = add_icon_item(tex, true) + set_item_metadata(idx, "StartingPoint") # Set type of NPC as metadata. + set_item_tooltip(idx, "Gomez (StartingPoint)") # Set name as tooltip. diff --git a/Scripts/UI/Toolbar/Palette.gd b/Scripts/UI/Toolbar/Palette.gd deleted file mode 100644 index 1638c5a..0000000 --- a/Scripts/UI/Toolbar/Palette.gd +++ /dev/null @@ -1,30 +0,0 @@ -extends ItemList - -const TRILE_SIZE = 18 # Width and height of trile textures, in pixels. - -func _on_loader_loaded_ts(trileset): - clear() # Empty out list, in case it's full from another level. - - var tex: Texture2D = trileset[1].albedo_texture # Get texture - var info: Dictionary = trileset[2] # Extract atlas offset and trile name from here! - - var w = tex.get_width() - var h = tex.get_height() - - # Trixel Engine defines the positions of textures as an "Atlas Offset" multiplied by image - # width and height. We'll implement the same thing here to find both the trile texture and its - # representative name. - - for trile in info: - var offsetX = floor(info[trile]["AtlasOffset"][0] * w) - var offsetY = floor(info[trile]["AtlasOffset"][1] * h) - var atl = AtlasTexture.new() - - atl.atlas = tex - atl.region = Rect2(offsetX, offsetY, TRILE_SIZE, TRILE_SIZE) - atl.filter_clip = true - - var idx = add_item(info[trile]["Name"], atl, true) - set_item_metadata(idx, trile) # Set trile ID as metadata. - pass - pass diff --git a/Scripts/UI/Toolbar/Triles.gd b/Scripts/UI/Toolbar/Triles.gd new file mode 100644 index 0000000..1844342 --- /dev/null +++ b/Scripts/UI/Toolbar/Triles.gd @@ -0,0 +1,50 @@ +extends ItemList + +const TRILE_SIZE = 18 # Width and height of trile textures, in pixels. +@onready var _Colors: OptionButton = $"../../ChoosePalette" # "Colors", because this is a palette! + +var curTS = null + +func _on_loader_loaded_ts(trileset): + curTS = trileset + # Enable all "colors"; default to "Triles". + for i in _Colors.item_count: + _Colors.set_item_disabled(i, false) + reloadTS(trileset) + +func _on_choose_palette_item_selected(index): # Hide palettes except for the one we chose. + var showPalette = index + var numChild = get_parent().get_child_count() + for palette in range(0, numChild): + if palette == showPalette: + get_parent().get_child(palette).visible = true + else: + get_parent().get_child(palette).visible = false + +func reloadTS(trileset): # (Re)load trileset. + clear() # Empty out list, in case it's full. + + var tex: Texture2D = trileset[1].albedo_texture # Get texture + var info: Dictionary = trileset[2] # Extract atlas offset and trile name from here! + + var w = tex.get_width() + var h = tex.get_height() + + # Trixel Engine defines the positions of textures as an "Atlas Offset" multiplied by image + # width and height. We'll implement the same thing here to find both the trile texture and its + # representative name. + + for trile in info: + var offsetX = floor(info[trile]["AtlasOffset"][0] * w) + var offsetY = floor(info[trile]["AtlasOffset"][1] * h) + var atl = AtlasTexture.new() + + atl.atlas = tex + atl.region = Rect2(offsetX, offsetY, TRILE_SIZE, TRILE_SIZE) # Get the texture at position x and y + atl.filter_clip = true # Don't let the textures bleed into each other! + + var idx = add_icon_item(atl, true) + set_item_metadata(idx, trile) # Set trile ID as metadata. + set_item_tooltip(idx, info[trile]["Name"]) # Set trile name as tooltip. + pass + pass diff --git a/Scripts/UI/UI.gd b/Scripts/UI/UI.gd index 11c1700..8c39aff 100644 --- a/Scripts/UI/UI.gd +++ b/Scripts/UI/UI.gd @@ -10,26 +10,21 @@ var soundRight = preload("res://Sounds/rotateright.wav") var posFormat = "[%d, %d, %d]" # Position formatting. var movement = false -var tID: String = "" # Trile ID. -var onTrile = null +var onObj = null -@onready var _infoLabel: Label = $"Sidebar/SidebarVertical/Position" -@onready var _objLabel: Label = $"Sidebar/SidebarVertical/Object" +@onready var _infoLabel: Label = $"VSplitContainer/Sidebar/SidebarVertical/Position" +@onready var _objLabel: Label = $"VSplitContainer/Sidebar/SidebarVertical/Object" + +@onready var _palettes: Control = $"VSplitContainer/Toolbar/Palettes" -@onready var _palette: ItemList = $"Toolbar/Palette" @onready var _loader: Node3D = $"Loader" @onready var _cursor: Node3D = $"../Cursor" +@onready var _curArea: Area3D = $"../Cursor/Area3D" @onready var _sfx: AudioStreamPlayer = $"SFX" signal cursorPos(newPos: Vector3) # A relay from Loader. -func _ready(): - var curArea = $"../Cursor/Area3D" - curArea.body_entered.connect(_on_body_entered) - _palette.item_selected.connect(_on_object_clicked) - pass - func _notification(what): if what == NOTIFICATION_WM_CLOSE_REQUEST: # Handle closing the window. _sfx.stream = soundCancel; _sfx.play() @@ -38,9 +33,23 @@ func _notification(what): get_tree().quit() func _process(_delta): - var pos = _cursor.get_child(1).global_position + var pos = _cursor.global_position # Update Position label var posStr = posFormat % [pos.x, pos.y, pos.z] _infoLabel.set_text(posStr) + +func _physics_process(_delta): + # Update Object label + if _curArea.has_overlapping_bodies(): + var bodies = _curArea.get_overlapping_bodies() + if !(bodies.size() == 0): # Prevent trying to get a nil value + onObj = bodies[0].get_parent() # Maybe we should list all objects? AOs could inhabit the same space... + + var objName = onObj.get_meta("Name") + _objLabel.set_text(str(objName)) + else: + onObj = null + _objLabel.set_text("None") + func _on_cursor_has_moved(keyPress): # Sounds for movement. match keyPress: @@ -61,29 +70,60 @@ func _on_loader_new_cur_por(newPos): emit_signal("cursorPos", newPos) pass -# Check collisions (with triles, AOs) -func _on_body_entered(body): - onTrile = body.get_parent() - var objName = onTrile.get_meta("Name") - if body != null: - _objLabel.set_text(str(objName)) - else: - _objLabel.set_text("None") - pass - -# Get trile ID/name of selected object -func _on_object_clicked(idx): - tID = _palette.get_item_metadata(idx) - print(tID) - pass - # Allow placing/removing of objects func _unhandled_input(event): - if event.is_action_pressed("place_object", true) and !tID.is_empty(): - var info: Dictionary = {"Id" : tID, "Position" : _cursor.global_position, "Phi" : 0} - _loader.placeTrile(_loader.trileset, info) - pass + # First, let's see what the active (visible) palette is + var active: ItemList = getActivePalette(_palettes) + var selected = active.get_selected_items() + var objID = null + var objType = active.get_name() # The name of the palette will decide what we're placing. + + if !(selected.size() == 0): # If something is selected, + objID = active.get_item_metadata(selected[0]) + + if event.is_action_pressed("place_object", true): + match objType: + "Triles": + if !objID.is_empty() and (onObj == null): # and if nothing's there + await plObj(objID, "Trile") + elif !objID.is_empty() and !(onObj == null): # or if a trile is already occupying that spot + await rmObj(onObj) # Delete it, and change it to the new trile. + await plObj(objID, "Trile") + "AOs": + pass + "NPCs": + await plObj(objID, "NPC") + pass + + _curArea.monitoring = false; _curArea.monitoring = true # Force the area to update + + if event.is_action_pressed("remove_object", true) and !(onObj == null): # Remove valid objects + await rmObj(onObj) - if event.is_action_pressed("remove_object", true) and !(onTrile == null): - onTrile.queue_free() - pass +func rmObj(obj): + obj.queue_free() + onObj = null + return OK + +func plObj(obj, type: String): + match type: + "Trile": + # We should probably factor in camera rotation as the Phi value. + var info: Dictionary = {"Id" : obj, "Position" : _cursor.global_position, "Phi" : 0} + _loader.placeTrile(_loader.trileset, info) + "AO": + pass + "NPC": + if obj == "StartingPoint": + # It looks like the Trixel engine only has sepcific positions for Gomez to spawn at. + var info: Dictionary = {"Id": _cursor.global_position, "Face": "Back"} + _loader.placeStart(Settings.NPCDir, info) + return OK + +func getActivePalette(parent: Node): + var children = parent.get_child_count() + for idx in children: + var child = parent.get_child(idx) + if child.visible == true: + return child + return 1 diff --git a/export_presets.cfg b/export_presets.cfg index 1e79336..2c30b68 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -60,43 +60,3 @@ Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorActi ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue Remove-Item -Recurse -Force '{temp_dir}'" - -[preset.1] - -name="Linux/X11" -platform="Linux/X11" -runnable=true -dedicated_server=false -custom_features="" -export_filter="all_resources" -include_filter="" -exclude_filter="test/*" -export_path="../BeretExports/Beret_Linux.x86_64" -encryption_include_filters="" -encryption_exclude_filters="" -encrypt_pck=false -encrypt_directory=false - -[preset.1.options] - -custom_template/debug="" -custom_template/release="" -debug/export_console_wrapper=1 -binary_format/embed_pck=true -texture_format/bptc=true -texture_format/s3tc=true -texture_format/etc=false -texture_format/etc2=false -binary_format/architecture="x86_64" -ssh_remote_deploy/enabled=false -ssh_remote_deploy/host="user@host_ip" -ssh_remote_deploy/port="22" -ssh_remote_deploy/extra_args_ssh="" -ssh_remote_deploy/extra_args_scp="" -ssh_remote_deploy/run_script="#!/usr/bin/env bash -export DISPLAY=:0 -unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" -\"{temp_dir}/{exe_name}\" {cmd_args}" -ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash -kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") -rm -rf \"{temp_dir}\""