From b1d340d21ae01da26cec2c6bd99e253f790e44fe Mon Sep 17 00:00:00 2001 From: Cory Petkovsek <632766+TokisanGames@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:44:36 +0700 Subject: [PATCH] Redesign Asset dock, default dock to bottom, floating, always on top, saveable settings --- .../editor/components/asset_dock.gd | 506 ++++++++++++++++-- .../editor/components/asset_dock.tscn | 71 ++- project/addons/terrain_3d/editor/editor.gd | 126 +---- project/project.godot | 11 +- 4 files changed, 552 insertions(+), 162 deletions(-) diff --git a/project/addons/terrain_3d/editor/components/asset_dock.gd b/project/addons/terrain_3d/editor/components/asset_dock.gd index 6cbbb1b5..9c0b75a8 100644 --- a/project/addons/terrain_3d/editor/components/asset_dock.gd +++ b/project/addons/terrain_3d/editor/components/asset_dock.gd @@ -1,65 +1,494 @@ @tool extends PanelContainer +#class_name Terrain3DAssetDock -signal placement_changed(index: int) + +## TODO +# Clean up, Move things back to ready? +# grab focus too aggressive if not pinned and window in front, alt+tab +# pin and slider reverse position from bottom +# right-click edit material, then click terrain3d and it triggers double click (edit or focus) + + +# Replace these with function calls signal resource_changed(resource: Resource, index: int) signal resource_inspected(resource: Resource) signal resource_selected +const PS_DOCK_SLOT: String = "terrain3d/config/dock_slot" +const PS_DOCK_TILE_SIZE: String = "terrain3d/config/dock_tile_size" +const PS_DOCK_FLOATING: String = "terrain3d/config/dock_floating" +const PS_DOCK_PINNED: String = "terrain3d/config/dock_always_on_top" +const PS_DOCK_WINDOW_POSITION: String = "terrain3d/config/dock_window_position" +const PS_DOCK_WINDOW_SIZE: String = "terrain3d/config/dock_window_size" + var list: ListContainer var entries: Array[ListEntry] var selected_index: int = 0 var focus_style: StyleBox -@onready var placement_option: OptionButton = $VBox/PlacementHBox/Options -@onready var placement_pin: Button = $VBox/PlacementHBox/Pinned -@onready var size_slider: HSlider = $VBox/SizeSlider +var placement_opt: OptionButton +var floating_btn: Button +var pinned_btn: Button +var size_slider: HSlider +var box: BoxContainer +var buttons: BoxContainer +var textures_btn: Button +var meshes_btn: Button +var asset_container: ScrollContainer + +#@onready var placement_opt: OptionButton = $Box/Buttons/PlacementOpt +#@onready var pinned: Button = $Box/Pinned +#@onready var size_slider: HSlider = $Box/Buttons/SizeSlider +#@onready var box: BoxContainer = $Box +#@onready var buttons: BoxContainer = $Box/Buttons +#@onready var textures_btn: Button = $Box/Buttons/TexturesBtn +#@onready var meshes_btn: Button = $Box/Buttons/MeshesBtn +#@onready var asset_container: ScrollContainer = $Box/ScrollContainer + +# Used only for editor, so change to single visible/hiddden +enum { + HIDDEN = -1, + SIDEBAR = 0, + BOTTOM = 1, + WINDOWED = 2, +} +var state: int = HIDDEN +var window: Window +var plugin: EditorPlugin + +enum { + POS_LEFT_UL = 0, + POS_LEFT_BL = 1, + POS_LEFT_UR = 2, + POS_LEFT_BR = 3, + POS_RIGHT_UL = 4, + POS_RIGHT_BL = 5, + POS_RIGHT_UR = 6, + POS_RIGHT_BR = 7, + POS_BOTTOM = 8, + POS_MAX = 9, +} +var slot: int = POS_BOTTOM +var _initialized: bool = false +var _godot_editor_window: Window # The main Godot Editor window func _ready() -> void: - placement_option.item_selected.connect(_on_placement_selected) - size_slider.value_changed.connect(_on_slider_changed) + print(self, "_ready") + if not _initialized: + return - list = ListContainer.new() - list.set_v_size_flags(SIZE_EXPAND_FILL) - list.set_h_size_flags(SIZE_EXPAND_FILL) - $VBox/ScrollContainer.add_child(list) - - # Copy theme from the editor, but since its a tool script, avoid saving icon resources in tscn - if EditorScript.new().get_editor_interface().get_edited_scene_root() != self: - set("theme_override_styles/panel", get_theme_stylebox("panel", "Panel")) - $VBox/Label.set("theme_override_styles/normal", get_theme_stylebox("bg", "EditorInspectorCategory")) - $VBox/Label.set("theme_override_fonts/font", get_theme_font("bold", "EditorFonts")) - $VBox/Label.set("theme_override_font_sizes/font_size",get_theme_font_size("bold_size", "EditorFonts")) - placement_pin.icon = get_theme_icon("Pin", "EditorIcons") - placement_pin.text = "" - - # Setup style for selected assets + # Setup styles + set("theme_override_styles/panel", get_theme_stylebox("panel", "Panel")) focus_style = get_theme_stylebox("focus", "Button").duplicate() focus_style.set_border_width_all(2) focus_style.set_border_color(Color(1, 1, 1, .67)) + # Avoid saving icon resources in tscn when editing w/ a tool script + if plugin.get_editor_interface().get_edited_scene_root() != self: + pinned_btn.icon = get_theme_icon("Pin", "EditorIcons") + pinned_btn.text = "" + floating_btn.icon = get_theme_icon("MakeFloating", "EditorIcons") + floating_btn.text = "" + + + +func initialize(p_plugin: EditorPlugin) -> void: + if p_plugin: + plugin = p_plugin + print(self, "initialize, Plugin: ", plugin!=null, ", Parent: ", get_parent(), ", state: ", state) + + # Get editor window. Structure is root:Window/EditorNode/Base Control + _godot_editor_window = plugin.get_editor_interface().get_base_control().get_parent().get_parent() + + placement_opt = $Box/Buttons/PlacementOpt + pinned_btn = $Box/Buttons/Pinned + floating_btn = $Box/Buttons/Floating + size_slider = $Box/Buttons/SizeSlider + box = $Box + buttons = $Box/Buttons + textures_btn = $Box/Buttons/TexturesBtn + meshes_btn = $Box/Buttons/MeshesBtn + asset_container = $Box/ScrollContainer + + list = ListContainer.new() + asset_container.add_child(list) + + load_project_settings() + + # Connect signals + resized.connect(update_layout) + textures_btn.pressed.connect(_on_textures_pressed) + meshes_btn.pressed.connect(_on_meshes_pressed) + placement_opt.item_selected.connect(set_slot) + floating_btn.pressed.connect(make_dock_float) + pinned_btn.toggled.connect(_on_pin_changed) + pinned_btn.visible = false + size_slider.value_changed.connect(_on_slider_changed) + resource_changed.connect(_on_resource_changed) + resource_inspected.connect(_on_resource_inspected) + resource_selected.connect(_on_resource_selected) + + print("Ready 4 Parent: ", get_parent(), ", state: ", state, ", slot: ", slot) + _initialized = true + print("initizalized, showing dock: ", plugin.visible) + update_assets() + update_dock(plugin.visible) + update_layout() + print("Ready 5 Parent: ", get_parent(), ", state: ", state) + + + + +## Window Management + +func dump_window() -> void: + return + if window: + window.print_tree() + push_warning("Dumping window") + for prop in window.get_property_list(): + print(prop.name, " = ", window.get(prop.name)) + push_warning("Dumping MarginContainer") + var mc: MarginContainer = get_parent() + for prop in mc.get_property_list(): + print(prop.name, " = ", mc.get(prop.name)) + push_warning("Dumping Self") + for prop in get_property_list(): + print(prop.name, " = ", get(prop.name)) + push_warning("Dumping Box") + for prop in $Box.get_property_list(): + print(prop.name, " = ", $Box.get(prop.name)) + print("-----done-------") + +func make_dock_float() -> void: + print(self, "make_dock_float, prev_slot: ", slot, ", current state: ", state) + #dump_project_settings() + # If already created (eg editor Make Floating) + if window: + push_warning("Capturing Window already created from Editor/make_floating, slot: ", slot, ", state: ", state) + print("Parent is: ", get_parent().name, ", gp: ", get_parent().get_parent().name) + else: + remove_dock() + create_window() + + state = WINDOWED + pinned_btn.visible = true + floating_btn.visible = false + placement_opt.visible = false + window.title = "Terrain3D Asset Dock" + window.always_on_top = pinned_btn.button_pressed + window.close_requested.connect(remove_dock.bind(true)) + visible = true # Is hidden when pops off of bottom. ?? + + print(self, "make_dock_float done, slot: ", slot, ", state: ", state) + #dump_project_settings() + #dump_window() + #save_project_settings() + + +func create_window() -> void: + print(self, "create_window") + window = Window.new() + window.wrap_controls = true + var mc := MarginContainer.new() + mc.set_anchors_preset(PRESET_FULL_RECT, false) + mc.add_child(self) + window.add_child(mc) + window.set_transient(false) + window.set_size(ProjectSettings.get_setting(PS_DOCK_WINDOW_SIZE, Vector2i(512, 512))) + window.set_position(ProjectSettings.get_setting(PS_DOCK_WINDOW_POSITION, Vector2i(704, 284))) + plugin.add_child(window) + window.show() + window.window_input.connect(_on_window_input) + window.mouse_entered.connect(_on_window_mouse_entered) + #window.mouse_exited.connect(_on_window_mouse_exited) + _godot_editor_window.mouse_entered.connect(_on_godot_window_entered) + + +func _on_window_input(event: InputEvent) -> void: + if event is InputEventKey and event.keycode == KEY_S and event.pressed and event.is_command_or_control_pressed(): + print("CTRL+S Pressed, saving scene") + save_project_settings() + plugin.get_editor_interface().save_scene() + + +func _on_window_mouse_entered() -> void: + #print("Mouse entered asset dock") + window.grab_focus() + + +func _on_godot_window_entered() -> void: + #print("Mouse entered godot") + _godot_editor_window.grab_focus() + + +#func _on_window_mouse_exited() -> void: + #print("Mouse exited asset dock") + #_godot_editor_window.grab_focus() + #pass + +## Dock placement + +func set_slot(p_slot: int) -> void: + print("set_slot call: ", p_slot) + p_slot = clamp(p_slot, 0, POS_MAX-1) + + if slot != p_slot: + print("set_slot changing slot: ", p_slot) + slot = p_slot + placement_opt.selected = slot + save_project_settings() + + plugin.select_terrain() + + print("Setting slot: ", slot, ", showing dock: ", plugin.visible) + update_dock(plugin.visible) + + +func remove_dock(p_force: bool = false) -> void: + print(self, "remove_dock, force: ", p_force) + if state == SIDEBAR: + print(self, "Remove dock from sidebar") + plugin.remove_control_from_docks(self) + state = HIDDEN + + elif state == BOTTOM: + print(self, "Remove dock from bottom panel") + plugin.remove_control_from_bottom_panel(self) + state = HIDDEN + + # If windowed and destination is not window or final exit, otherwise leave + elif state == WINDOWED and p_force: #( slot != POS_WINDOW or p_force ): + print("Removing window") + if not window: + push_error("State is windowed, but no window to remove. Shouldn't happen. Returning") + return + var parent: Node = get_parent() + if parent: + parent.remove_child(self) + _godot_editor_window.mouse_entered.disconnect(_on_godot_window_entered) + window.hide() # Maybe even if not parent? + window.queue_free() + window = null + floating_btn.button_pressed = false + floating_btn.visible = true + pinned_btn.visible = false + placement_opt.visible = true + state = HIDDEN + update_dock(plugin.visible) # return window to side/bottom + + # Hide pin + # Show make floating + # show slot changer + print(self, "remove dock end, state: ", state, ", slot: ", slot, ", visible: ", plugin.visible) + #dump_project_settings() + + +func update_dock(p_visible: bool) -> void: + print(self, "Show dock: ", p_visible, ", initialized: ", _initialized) + if not _initialized: + print(self, "Show dock: not initiazlied, returning") + return + + if window: + print("already window, returning") + return + elif floating_btn.button_pressed: + # No window, but floating button pressed happens if loading while open. Create window + push_warning("Loading window that was saved open - should happen only once at startup") + make_dock_float() + return + + remove_dock() + # Add dock to new destination + # Sidebar + if slot < POS_BOTTOM: # and not pinned.button_pressed: + #print(self, "Adding dock to side slot: ", slot, ", old state: ", state) + state = SIDEBAR + plugin.add_control_to_dock(slot, self) + #print(self, "state: ", state) + elif slot == POS_BOTTOM: # and not pinned.button_pressed: + #print(self, "Adding dock to bottom: ", slot, ", old state: ", state) + state = BOTTOM + plugin.add_control_to_bottom_panel(self, "Terrain3D") + #print(self, "Making bottom visible") + if p_visible: + plugin.make_bottom_panel_item_visible(self) + #print(self, "state: ", state) + + #update_layout() + + + +func update_layout() -> void: + #print(self, "Updating layout. Slot: %d, State: %d, plugin: %s" % [ slot, state, plugin ]) + if not _initialized: + return + print("update_layout: State: %d, slot: %d, parent: %s" % [ state, slot, get_parent().name ]) + + + # Take care here to detect if we have a new window (from Make floating) + # and convert to our window so it can be freed properly + # If not set to windowed and suddenly is, user hit `Make Floating`, grab it + if not window and get_parent() and get_parent().get_parent() is Window: + push_warning("Editor/Make Floating - should happen only once") + window = get_parent().get_parent() + make_dock_float() + return # Will return here upon display + + + var size_parent: Control = size_slider.get_parent() + # Vertical layout + if window or slot < POS_BOTTOM: + box.vertical = true + buttons.vertical = false + + if size.x >= 500 and size_parent != buttons: + size_slider.reparent(buttons) + buttons.move_child(size_slider, 3) + elif size.x < 500 and size_parent != box: + size_slider.reparent(box) + box.move_child(size_slider, 1) + floating_btn.reparent(buttons) + buttons.move_child(floating_btn, 4) + + # Wide layout + else: + size_slider.reparent(buttons) + floating_btn.reparent(box) + box.vertical = false + buttons.vertical = true + + save_project_settings() + + +## Manage Project Settings + +func dump_project_settings() -> void: + print("PS floating button: ", ProjectSettings.get_setting(PS_DOCK_FLOATING, "")) + print("PS pinned button: ", ProjectSettings.get_setting(PS_DOCK_PINNED, "")) + print("PS tile size: ", ProjectSettings.get_setting(PS_DOCK_TILE_SIZE, "")) + print("PS slot: ", ProjectSettings.get_setting(PS_DOCK_SLOT, "")) + print("PS window pos: ", ProjectSettings.get_setting(PS_DOCK_WINDOW_POSITION, "")) + print("PS window size: ", ProjectSettings.get_setting(PS_DOCK_WINDOW_SIZE, "")) + + +func load_project_settings() -> void: + print("Loading project settings") + print("---- pre") + dump_project_settings() + floating_btn.button_pressed = ProjectSettings.get_setting(PS_DOCK_FLOATING, false) + pinned_btn.button_pressed = ProjectSettings.get_setting(PS_DOCK_PINNED, true) + size_slider.value = ProjectSettings.get_setting(PS_DOCK_TILE_SIZE, 83) + set_slot(ProjectSettings.get_setting(PS_DOCK_SLOT, POS_BOTTOM)) + _on_slider_changed(size_slider.value) + # Window pos/size set on window creation in update_dock + print("---- post") + dump_project_settings() + + update_dock(plugin.visible) + + +func save_project_settings() -> void: + if not _initialized: + return + #print("Saving project settings, previous:") + #dump_project_settings() + ProjectSettings.set_setting(PS_DOCK_SLOT, slot) + ProjectSettings.set_setting(PS_DOCK_TILE_SIZE, size_slider.value) + ProjectSettings.set_setting(PS_DOCK_FLOATING, floating_btn.button_pressed) + ProjectSettings.set_setting(PS_DOCK_PINNED, pinned_btn.button_pressed) + if window: + ProjectSettings.set_setting(PS_DOCK_WINDOW_SIZE, window.size) + ProjectSettings.set_setting(PS_DOCK_WINDOW_POSITION, window.position) + ProjectSettings.save() + print("Saved project settings:") + dump_project_settings() -func _on_placement_selected(index: int) -> void: - emit_signal("placement_changed", index) + +## Panel Button handlers + +func _on_pin_changed(toggled: bool) -> void: + print("Pin toggled: ", toggled) + if window: + window.always_on_top = pinned_btn.button_pressed + save_project_settings() func _on_slider_changed(value: float) -> void: + print("Slider changed: ", value) if list: - list.set_entry_size(value) + list.set_entry_width(value) + save_project_settings() + + +func _on_textures_pressed() -> void: + print("Textures pressed") + pass + + +func _on_meshes_pressed() -> void: + print("Meshes pressed") + pass + + +## Tile handlers + +func _on_resource_changed(p_texture: Resource, p_index: int) -> void: + print("Resource changed: ", p_texture, p_index) + if plugin.is_terrain_valid(): + # If removing last entry and its selected, clear inspector + if not p_texture and p_index == get_selected_index() and \ + get_selected_index() == entries.size() - 2: + plugin.get_editor_interface().inspect_object(null) + plugin.terrain.get_assets().set_texture(p_index, p_texture) + + +func _on_resource_selected() -> void: + print(plugin, ": Resource selected----------") + plugin.select_terrain() + + # If not on a texture painting tool, then switch to Paint + if plugin.editor.get_tool() != Terrain3DEditor.TEXTURE: + var paint_btn: Button = plugin.ui.toolbar.get_node_or_null("PaintBaseTexture") + if paint_btn: + paint_btn.set_pressed(true) + plugin.ui._on_tool_changed(Terrain3DEditor.TEXTURE, Terrain3DEditor.REPLACE) + plugin.ui._on_setting_changed() + print("Resource selected done") -func move_slider(to_side: bool) -> void: - if to_side and size_slider.get_parent() != $VBox: - size_slider.reparent($VBox) - $VBox.move_child(size_slider, 2) - size_slider.custom_minimum_size = Vector2(0, 0) - elif not to_side and size_slider.get_parent() == $VBox: - size_slider.reparent($VBox/PlacementHBox) - $VBox/PlacementHBox.move_child(size_slider, 2) - size_slider.custom_minimum_size = Vector2(300, 10) +func _on_resource_inspected(p_texture: Resource) -> void: + print(plugin, ": Resource inspected: ", p_texture) + plugin.get_editor_interface().inspect_object(p_texture, "", true) + print("Resource inspected done") +func update_assets(p_args: Array = Array()) -> void: + #print("update_assets, initizialized: ", _initialized, ", args: ", p_args) + + if not _initialized: + print(self, "update_assets, not initizialized, returning") + return + + if plugin.terrain and plugin.terrain.assets: + if not plugin.terrain.assets.textures_changed.is_connected(update_assets): + plugin.terrain.assets.textures_changed.connect(update_assets) + + clear() + + if plugin.is_terrain_valid() and plugin.terrain.assets: + var texture_count: int = plugin.terrain.assets.get_texture_count() + for i in texture_count: + var texture: Terrain3DTexture = plugin.terrain.assets.get_texture(i) + add_item(texture) + + if texture_count < Terrain3DAssets.MAX_TEXTURES: + add_item() + + func clear() -> void: for i in entries: i.get_parent().remove_child(i) @@ -124,9 +553,18 @@ func notify_resource_changed(p_resource: Resource, p_index: int) -> void: class ListContainer extends Container: var height: float = 0 var width: float = 83 + + func _ready() -> void: + set_v_size_flags(SIZE_EXPAND_FILL) + set_h_size_flags(SIZE_EXPAND_FILL) + + + func get_entry_width() -> float: + return width + - func set_entry_size(value: float) -> void: + func set_entry_width(value: float) -> void: width = clamp(value, 56, 256) redraw() diff --git a/project/addons/terrain_3d/editor/components/asset_dock.tscn b/project/addons/terrain_3d/editor/components/asset_dock.tscn index 811eeb8f..3748176c 100644 --- a/project/addons/terrain_3d/editor/components/asset_dock.tscn +++ b/project/addons/terrain_3d/editor/components/asset_dock.tscn @@ -3,26 +3,42 @@ [ext_resource type="Script" path="res://addons/terrain_3d/editor/components/asset_dock.gd" id="1_e23pg"] [node name="Terrain3D" type="PanelContainer"] -custom_minimum_size = Vector2(256, 136) -offset_right = 256.0 -offset_bottom = 128.0 +custom_minimum_size = Vector2(256, 95) +offset_right = 766.0 +offset_bottom = 100.0 script = ExtResource("1_e23pg") -[node name="VBox" type="VBoxContainer" parent="."] +[node name="Box" type="BoxContainer" parent="."] layout_mode = 2 +size_flags_vertical = 3 +vertical = true -[node name="PlacementHBox" type="HBoxContainer" parent="VBox"] +[node name="Buttons" type="BoxContainer" parent="Box"] layout_mode = 2 -[node name="Label" type="Label" parent="VBox/PlacementHBox"] +[node name="TexturesBtn" type="Button" parent="Box/Buttons"] +custom_minimum_size = Vector2(80, 30) layout_mode = 2 -text = "Dock Position: " +size_flags_horizontal = 3 +size_flags_vertical = 0 +theme_override_font_sizes/font_size = 16 +text = "Textures" -[node name="Options" type="OptionButton" parent="VBox/PlacementHBox"] +[node name="MeshesBtn" type="Button" parent="Box/Buttons"] +custom_minimum_size = Vector2(80, 30) layout_mode = 2 size_flags_horizontal = 3 +size_flags_vertical = 0 +theme_override_font_sizes/font_size = 16 +text = "Meshes" + +[node name="PlacementOpt" type="OptionButton" parent="Box/Buttons"] +custom_minimum_size = Vector2(80, 30) +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 0 item_count = 9 -selected = 5 +selected = 8 popup/item_0/text = "Left_UL" popup/item_0/id = 0 popup/item_1/text = "Left_BL" @@ -42,28 +58,33 @@ popup/item_7/id = 7 popup/item_8/text = "Bottom" popup/item_8/id = 8 -[node name="Pinned" type="Button" parent="VBox/PlacementHBox"] +[node name="SizeSlider" type="HSlider" parent="Box/Buttons"] +custom_minimum_size = Vector2(80, 10) layout_mode = 2 -tooltip_text = "Keep panel visible even if Terrain3D is not selected. Useful for keeping dock floating." -toggle_mode = true -text = "P" -flat = true +size_flags_horizontal = 3 +min_value = 56.0 +max_value = 256.0 +value = 83.0 -[node name="Label" type="Label" parent="VBox"] +[node name="Floating" type="Button" parent="Box/Buttons"] layout_mode = 2 -theme_override_font_sizes/font_size = 16 -text = "Textures" -horizontal_alignment = 1 -vertical_alignment = 1 +size_flags_horizontal = 0 +size_flags_vertical = 0 +tooltip_text = "Pop this dock out to a floating window." +toggle_mode = true +text = "F" +flat = true -[node name="SizeSlider" type="HSlider" parent="VBox"] -custom_minimum_size = Vector2(100, 10) +[node name="Pinned" type="Button" parent="Box/Buttons"] layout_mode = 2 -min_value = 56.0 -max_value = 256.0 -value = 83.0 +size_flags_horizontal = 0 +size_flags_vertical = 0 +tooltip_text = "Make this window \"Always on top\"." +toggle_mode = true +text = "P" +flat = true -[node name="ScrollContainer" type="ScrollContainer" parent="VBox"] +[node name="ScrollContainer" type="ScrollContainer" parent="Box"] layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 diff --git a/project/addons/terrain_3d/editor/editor.gd b/project/addons/terrain_3d/editor/editor.gd index 67b34e1c..0d45f4ff 100644 --- a/project/addons/terrain_3d/editor/editor.gd +++ b/project/addons/terrain_3d/editor/editor.gd @@ -7,28 +7,19 @@ extends EditorPlugin const UI: Script = preload("res://addons/terrain_3d/editor/components/ui.gd") const RegionGizmo: Script = preload("res://addons/terrain_3d/editor/components/region_gizmo.gd") const ASSET_DOCK: String = "res://addons/terrain_3d/editor/components/asset_dock.tscn" -const PS_DOCK_POSITION: String = "terrain3d/config/dock_position" -const PS_DOCK_PINNED: String = "terrain3d/config/dock_pinned" var terrain: Terrain3D +var _last_terrain: Terrain3D var nav_region: NavigationRegion3D var editor: Terrain3DEditor var ui: Node # Terrain3DUI see Godot #75388 +var asset_dock: PanelContainer var region_gizmo: RegionGizmo var visible: bool var current_region_position: Vector2 var mouse_global_position: Vector3 = Vector3.ZERO -enum DOCK_STATE { - HIDDEN = -1, - SIDEBAR = 0, - BOTTOM = 1, -} -var asset_dock: Control -var dock_state: DOCK_STATE = -1 -var dock_position: DockSlot = DOCK_SLOT_RIGHT_BL - # Track negative input (CTRL) var _negative_input: bool = false # Track state prior to pressing CTRL: -1 not tracked, 0 false, 1 true @@ -43,26 +34,19 @@ func _enter_tree() -> void: region_gizmo = RegionGizmo.new() - if ProjectSettings.has_setting(PS_DOCK_POSITION): - dock_position = ProjectSettings.get_setting(PS_DOCK_POSITION) + print("Loading asset dock") asset_dock = load(ASSET_DOCK).instantiate() - await asset_dock.ready - if ProjectSettings.has_setting(PS_DOCK_PINNED): - asset_dock.placement_pin.button_pressed = ProjectSettings.get_setting(PS_DOCK_PINNED) - asset_dock.placement_pin.toggled.connect(_on_asset_dock_pin_changed) - asset_dock.placement_option.selected = dock_position - asset_dock.placement_changed.connect(_on_asset_dock_placement_changed) - asset_dock.resource_changed.connect(_on_asset_dock_resource_changed) - asset_dock.resource_inspected.connect(_on_asset_dock_resource_inspected) - asset_dock.resource_selected.connect(_on_asset_dock_resource_selected) - + asset_dock.initialize(self) + func _exit_tree() -> void: + push_warning("T3D Editor exit_tree") + asset_dock.remove_dock(true) asset_dock.queue_free() ui.queue_free() editor.free() - + func _handles(p_object: Object) -> bool: return p_object is Terrain3D or p_object is NavigationRegion3D @@ -75,14 +59,15 @@ func _edit(p_object: Object) -> void: if p_object == terrain: return terrain = p_object + _last_terrain = terrain editor.set_terrain(terrain) region_gizmo.set_node_3d(terrain) terrain.add_gizmo(region_gizmo) terrain.set_plugin(self) - if not terrain.assets_changed.is_connected(_load_assets): - terrain.assets_changed.connect(_load_assets) - _load_assets() + if not terrain.assets_changed.is_connected(asset_dock.update_assets): + terrain.assets_changed.connect(asset_dock.update_assets) + asset_dock.update_assets() if not terrain.storage_changed.is_connected(_load_storage): terrain.storage_changed.connect(_load_storage) _load_storage() @@ -101,26 +86,7 @@ func _make_visible(p_visible: bool, p_redraw: bool = false) -> void: if terrain: update_region_grid() region_gizmo.set_hidden(not visible or not terrain) - - # Manage Asset Dock position and visibility - if visible and dock_state == DOCK_STATE.HIDDEN: - if dock_position < DOCK_SLOT_MAX: - add_control_to_dock(dock_position, asset_dock) - dock_state = DOCK_STATE.SIDEBAR - asset_dock.move_slider(true) - else: - add_control_to_bottom_panel(asset_dock, "Terrain3D") - make_bottom_panel_item_visible(asset_dock) - dock_state = DOCK_STATE.BOTTOM - asset_dock.move_slider(false) - elif not visible and dock_state != DOCK_STATE.HIDDEN: - var pinned: bool = false - if p_redraw or ( asset_dock.placement_pin and not asset_dock.placement_pin.button_pressed): - if dock_state == DOCK_STATE.SIDEBAR: - remove_control_from_docks(asset_dock) - else: - remove_control_from_bottom_panel(asset_dock) - dock_state = DOCK_STATE.HIDDEN + asset_dock.update_dock(visible) func _clear() -> void: @@ -280,58 +246,18 @@ func update_region_grid() -> void: region_gizmo.grid = [Vector2i.ZERO] -func _load_assets() -> void: - if terrain and terrain.assets: - if not terrain.assets.textures_changed.is_connected(update_asset_dock): - terrain.assets.textures_changed.connect(update_asset_dock) - update_asset_dock(Array()) - - -func update_asset_dock(p_args: Array) -> void: - asset_dock.clear() - - if is_terrain_valid() and terrain.assets: - var texture_count: int = terrain.assets.get_texture_count() - for i in texture_count: - var texture: Terrain3DTexture = terrain.assets.get_texture(i) - asset_dock.add_item(texture) - - if texture_count < Terrain3DAssets.MAX_TEXTURES: - asset_dock.add_item() +#func is_selected() -> bool: + #print("Is_selected. Terrain: ", _last_terrain) + #if _last_terrain: + #var selected: Array[Node] = get_editor_interface().get_selection().get_selected_nodes() + #print(selected) + #return _last_terrain in selected + #return false -func _on_asset_dock_pin_changed(toggled: bool) -> void: - ProjectSettings.set_setting(PS_DOCK_PINNED, toggled) - ProjectSettings.save() - - -func _on_asset_dock_placement_changed(index: int) -> void: - dock_position = clamp(index, 0, DOCK_SLOT_MAX) - ProjectSettings.set_setting(PS_DOCK_POSITION, dock_position) - ProjectSettings.save() - _make_visible(false, true) # Hide to redraw - _make_visible(true) - - -func _on_asset_dock_resource_changed(p_texture: Resource, p_index: int) -> void: - if is_terrain_valid(): - # If removing last entry and its selected, clear inspector - if not p_texture and p_index == asset_dock.get_selected_index() and \ - asset_dock.get_selected_index() == asset_dock.entries.size() - 2: - get_editor_interface().inspect_object(null) - terrain.get_assets().set_texture(p_index, p_texture) - - -func _on_asset_dock_resource_selected() -> void: - # If not on a texture painting tool, then switch to Paint - if editor.get_tool() != Terrain3DEditor.TEXTURE: - var paint_btn: Button = ui.toolbar.get_node_or_null("PaintBaseTexture") - if paint_btn: - paint_btn.set_pressed(true) - ui._on_tool_changed(Terrain3DEditor.TEXTURE, Terrain3DEditor.REPLACE) - ui._on_setting_changed() - - -func _on_asset_dock_resource_inspected(texture: Resource) -> void: - get_editor_interface().inspect_object(texture, "", true) - +func select_terrain() -> void: + if _last_terrain: + #var es: EditorSelection = get_editor_interface().get_selection() + #es.clear() + #es.add_node(_last_terrain) + get_editor_interface().edit_node(_last_terrain) diff --git a/project/project.godot b/project/project.godot index 7e1642e5..b4a29ba7 100644 --- a/project/project.godot +++ b/project/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="Terrain3D" run/main_scene="res://demo/Demo.tscn" -config/features=PackedStringArray("4.1") +config/features=PackedStringArray("4.2") config/icon="res://icon.svg" [display] @@ -78,5 +78,10 @@ occlusion_culling/use_occlusion_culling=true [terrain3d] -config/dock_position=5 -config/dock_pinned=false +config/dock_always_on_top=false +config/dock_slot=8 +config/dock_tile_size=83.0 +config/dock_floating=false +config/dock_always_on_top=true +config/dock_window_size=Vector2i(512, 512) +config/dock_window_position=Vector2i(704, 284)