diff --git a/addons/scene_palette/LICENSE b/addons/scene_palette/LICENSE new file mode 100644 index 00000000..fdddb29a --- /dev/null +++ b/addons/scene_palette/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/addons/scene_palette/components/favorite_button/Button.gd b/addons/scene_palette/components/favorite_button/Button.gd new file mode 100644 index 00000000..d469ca12 --- /dev/null +++ b/addons/scene_palette/components/favorite_button/Button.gd @@ -0,0 +1,9 @@ +@tool +extends Button + + +func _on_mouse_entered(): + scale = Vector2(1.05, 1.05) + +func _on_mouse_exited(): + scale = Vector2.ONE diff --git a/addons/scene_palette/components/favorite_button/Button.gd.uid b/addons/scene_palette/components/favorite_button/Button.gd.uid new file mode 100644 index 00000000..d1d49513 --- /dev/null +++ b/addons/scene_palette/components/favorite_button/Button.gd.uid @@ -0,0 +1 @@ +uid://d3wtnpc6vtyba diff --git a/addons/scene_palette/components/favorite_button/FavoriteButton.gd b/addons/scene_palette/components/favorite_button/FavoriteButton.gd new file mode 100644 index 00000000..49d073e2 --- /dev/null +++ b/addons/scene_palette/components/favorite_button/FavoriteButton.gd @@ -0,0 +1,53 @@ +@tool +extends HBoxContainer +class_name PalettePluginFavoriteButton +@onready var button:Button = %Button +@onready var delete_button = %DeleteButton +@onready var color_picker_button = %ColorPickerButton +const PALETTE_NAME_MAX_LEN = 17 + +var directory:String: + set(value): + directory = value + button.text = _create_button_label(directory) + +signal favorite_selected(dir) +signal favorite_color_changed(dir, color) +signal favorite_removed(dir) + +func _create_button_label(directory) -> String: + var dir_name:String = directory.split('/')[-1] + # remove -,_ so that the names look neater + var btn_name:String = dir_name.replace('-', ' ').replace('_', ' ') + button.tooltip_text = "Open palette for " + btn_name + + # If button names are too long, the behavior of the controls will wrap in + # a weird way when the panel width is resized in the editor. + # There's probably a better way to deal with this, but this works for now. + if len(btn_name) > PALETTE_NAME_MAX_LEN: + btn_name = btn_name.left(PALETTE_NAME_MAX_LEN) + return btn_name + + +func _on_favorite_button_pressed(): + favorite_selected.emit(directory) + +func _on_delete_button_pressed(): + favorite_removed.emit(directory) + queue_free() + +func set_settings_visibility(is_visible:bool): + delete_button.visible = is_visible + color_picker_button.visible = is_visible + +func _on_color_picker_button_color_changed(color): + set_color(color) + favorite_color_changed.emit(directory, color) + #delete_button.add_theme_stylebox_override('normal', stylebox) + +func set_color(color:Color): + var stylebox:StyleBoxFlat = StyleBoxFlat.new() + stylebox.bg_color = color + stylebox.set_content_margin_all(7) + button.add_theme_stylebox_override('normal', stylebox) + button.add_theme_stylebox_override('hover', stylebox) diff --git a/addons/scene_palette/components/favorite_button/FavoriteButton.gd.uid b/addons/scene_palette/components/favorite_button/FavoriteButton.gd.uid new file mode 100644 index 00000000..35425ef7 --- /dev/null +++ b/addons/scene_palette/components/favorite_button/FavoriteButton.gd.uid @@ -0,0 +1 @@ +uid://drl5v6d85cn8i diff --git a/addons/scene_palette/components/favorite_button/FavoriteButton.tscn b/addons/scene_palette/components/favorite_button/FavoriteButton.tscn new file mode 100644 index 00000000..317801d1 --- /dev/null +++ b/addons/scene_palette/components/favorite_button/FavoriteButton.tscn @@ -0,0 +1,67 @@ +[gd_scene load_steps=5 format=3 uid="uid://wfk2vnuru8d"] + +[ext_resource type="Script" path="res://addons/scene_palette/components/favorite_button/FavoriteButton.gd" id="1_vdv7t"] +[ext_resource type="Script" path="res://addons/scene_palette/components/favorite_button/Button.gd" id="2_8ifhe"] +[ext_resource type="Texture2D" uid="uid://ckxydxkbv6ecc" path="res://addons/scene_palette/icons/palette.png" id="2_hpqcp"] +[ext_resource type="Texture2D" uid="uid://ittulgc4utna" path="res://addons/scene_palette/icons/eye_dropper.png" id="4_0krmm"] + +[node name="FavoriteButton" type="HBoxContainer"] +offset_right = 40.0 +offset_bottom = 40.0 +size_flags_horizontal = 0 +theme_override_constants/separation = 0 +script = ExtResource("1_vdv7t") + +[node name="Button" type="Button" parent="."] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 0 +theme_override_font_sizes/font_size = 14 +text = "text" +icon = ExtResource("2_hpqcp") +script = ExtResource("2_8ifhe") + +[node name="VBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 +size_flags_horizontal = 2 +theme_override_constants/separation = -1 + +[node name="ColorPickerButton" type="ColorPickerButton" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +tooltip_text = "change color" +icon = ExtResource("4_0krmm") +edit_alpha = false + +[node name="TextureRect" type="TextureRect" parent="VBoxContainer/ColorPickerButton"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -5.0 +offset_top = -6.0 +offset_right = 5.0 +offset_bottom = 6.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("4_0krmm") +stretch_mode = 2 + +[node name="DeleteButton" type="Button" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +tooltip_text = "Remove from favorites." +text = " x " + +[connection signal="mouse_entered" from="Button" to="Button" method="_on_mouse_entered"] +[connection signal="mouse_exited" from="Button" to="Button" method="_on_mouse_exited"] +[connection signal="pressed" from="Button" to="." method="_on_favorite_button_pressed"] +[connection signal="color_changed" from="VBoxContainer/ColorPickerButton" to="." method="_on_color_picker_button_color_changed"] +[connection signal="pressed" from="VBoxContainer/DeleteButton" to="." method="_on_delete_button_pressed"] diff --git a/addons/scene_palette/components/scene_thumbnail/scene_drop.gd b/addons/scene_palette/components/scene_thumbnail/scene_drop.gd new file mode 100644 index 00000000..2a794e8c --- /dev/null +++ b/addons/scene_palette/components/scene_thumbnail/scene_drop.gd @@ -0,0 +1,116 @@ +@tool +extends Control + +const pp = 'ScenePalettePlugin: ' # prepended to printed messages +const MOUSE_HOVER_SCALE_ADJUST = 0.05 + +@onready var picture_point = %PicturePoint +@onready var name_label = %NameLabel +@onready var texture_rect: TextureRect = %TextureRect + +var _scene_path:String +var instantiate_scene_preview: + set(value): + instantiate_scene_preview = value + # refresh the preview + if _scene_path: + set_scene(_scene_path) + +func adjust_scale(amt:float): + picture_point.scale = Vector2(amt, amt) + +func show_file_label(show:bool): + # setting text here instead of in set_scene seems to work better + name_label.text = _create_display_label(_scene_path) + name_label.visible = show + +func _create_display_label(path:String) -> String: + var display_label = path.split('.tscn')[0].split('/')[-1] + display_label = display_label.replace('_', ' ').replace('-', ' ') + return display_label + +func set_scene(path:String): + tooltip_text = path + _scene_path = path + var file_extension = path.split('.')[-1] + + for node in picture_point.get_children(): + node.queue_free() + + match file_extension: + 'png': + texture_rect.texture = load(_scene_path) + 'tscn': + if instantiate_scene_preview: + var node:Node = load(_scene_path).instantiate() + if _scene_is_safe(node): + picture_point.add_child(node) + return + # if scene is not safe to instantiate, just keep a preview + _make_preview() + 'obj': + _make_preview() + +func _make_preview(): + var resource_previewer = EditorInterface.get_resource_previewer() + resource_previewer.queue_resource_preview(_scene_path, self, '_on_resource_preview', null) + +func _on_resource_preview(path:String, preview:Texture2D, thumbnail_preview:Texture2D, _user_data): + var texture_rect = TextureRect.new() + add_child(texture_rect) + texture_rect.texture = preview + hide() + show() + +## determine if scene is safe to instantiate as a preview +func _scene_is_safe(scene:Node) -> bool: + # if scene is a Node then it can't be positioned within the panel and + # clip_contents does not work. + if not scene is Node2D: + print("%Not instantiating preview for %s because it is not a Node2D" % + [pp, scene.scene_file_path] + ) + return false + # if scene contains a camera, the entire editor is repositioned + if _scene_contains_camera(scene): + print("%Not instantiating preview for %s because it contains a camera." % + [pp, scene.scene_file_path] + ) + return false + return true + +func _scene_contains_camera(scene:Node) -> bool: + if scene is Camera2D: + return true + for node in scene.get_children(): + var result:bool = _scene_contains_camera(node) + if result: + return result + return false + +## Mimics the data that would be provided if a file were dragged from the +## FileSystem browser +func _make_file_data() -> Dictionary: + return { + 'type': 'files', + 'files': [_scene_path], + 'from': '' + } + +func _make_drag_preview() -> Control: + var control:Control = Control.new() + if instantiate_scene_preview: + var scene = load(_scene_path).instantiate() + control.add_child(scene) + # TODO add an alternate image here + return control + +func _get_drag_data(at_position): + set_drag_preview(_make_drag_preview()) + return _make_file_data() + +func _on_mouse_entered(): + scale = Vector2.ONE + Vector2(MOUSE_HOVER_SCALE_ADJUST, MOUSE_HOVER_SCALE_ADJUST) + +func _on_mouse_exited(): + scale = Vector2.ONE diff --git a/addons/scene_palette/components/scene_thumbnail/scene_drop.gd.uid b/addons/scene_palette/components/scene_thumbnail/scene_drop.gd.uid new file mode 100644 index 00000000..4426d251 --- /dev/null +++ b/addons/scene_palette/components/scene_thumbnail/scene_drop.gd.uid @@ -0,0 +1 @@ +uid://ddmp30k7qqcrm diff --git a/addons/scene_palette/components/scene_thumbnail/scene_drop.tscn b/addons/scene_palette/components/scene_thumbnail/scene_drop.tscn new file mode 100644 index 00000000..b9c9ee03 --- /dev/null +++ b/addons/scene_palette/components/scene_thumbnail/scene_drop.tscn @@ -0,0 +1,77 @@ +[gd_scene load_steps=6 format=3 uid="uid://cypob1bi5kovv"] + +[ext_resource type="Script" path="res://addons/scene_palette/components/scene_thumbnail/scene_drop_holder.gd" id="1_1tb3w"] +[ext_resource type="Script" path="res://addons/scene_palette/components/scene_thumbnail/scene_drop.gd" id="2_7tuog"] +[ext_resource type="Texture2D" uid="uid://cgrtskqrq8iqy" path="res://addons/scene_palette/icons/open_scene.png" id="3_iydoq"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0w221"] +bg_color = Color(0.2484, 0.2484, 0.2484, 1) +corner_radius_top_left = 5 +corner_radius_top_right = 5 +corner_radius_bottom_right = 5 +corner_radius_bottom_left = 5 + +[sub_resource type="LabelSettings" id="LabelSettings_txl6c"] +font_size = 12 +font_color = Color(0.838897, 0.838897, 0.838897, 1) + +[node name="SceneDropHolder" type="MarginContainer"] +clip_contents = true +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("1_1tb3w") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="SceneDrop" type="Panel" parent="VBoxContainer"] +unique_name_in_owner = true +clip_contents = true +custom_minimum_size = Vector2(65, 65) +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_0w221") +script = ExtResource("2_7tuog") + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/SceneDrop"] +clip_contents = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 20 + +[node name="PicturePoint" type="Control" parent="VBoxContainer/SceneDrop/MarginContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 8 + +[node name="TextureRect" type="TextureRect" parent="VBoxContainer/SceneDrop/MarginContainer"] +unique_name_in_owner = true +texture_filter = 1 +clip_contents = true +layout_mode = 2 +expand_mode = 5 + +[node name="NameLabel" type="Label" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "name" +label_settings = SubResource("LabelSettings_txl6c") +autowrap_mode = 3 + +[node name="OpenSceneButton" type="Button" parent="."] +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 0 +tooltip_text = "Open Scene in Editor" +icon = ExtResource("3_iydoq") + +[connection signal="mouse_entered" from="VBoxContainer/SceneDrop" to="VBoxContainer/SceneDrop" method="_on_mouse_entered"] +[connection signal="mouse_exited" from="VBoxContainer/SceneDrop" to="VBoxContainer/SceneDrop" method="_on_mouse_exited"] +[connection signal="pressed" from="OpenSceneButton" to="." method="_on_open_scene_button_pressed"] diff --git a/addons/scene_palette/components/scene_thumbnail/scene_drop_holder.gd b/addons/scene_palette/components/scene_thumbnail/scene_drop_holder.gd new file mode 100644 index 00000000..17990129 --- /dev/null +++ b/addons/scene_palette/components/scene_thumbnail/scene_drop_holder.gd @@ -0,0 +1,36 @@ +@tool +extends MarginContainer +class_name PalettePluginSceneDrop +@onready var scene_drop = %SceneDrop +@onready var name_label = %NameLabel +@onready var open_scene_button: Button = $OpenSceneButton + +# Note most of the code is in scene_drop.gd attached to SceneDrop, this is a wrapper. +# A wrapper is used because it made implementing the drag and drop code easier + + +var instantiate_scene_preview: + set(value): + scene_drop.instantiate_scene_preview = value + +var _scene_path:String + +func set_scene(path:String): + _scene_path = path + scene_drop.set_scene(path) + var scene_name = _scene_path.split('.')[0].split('/')[-1] + name_label.text = scene_name + name_label.tooltip_text = scene_name + + var file_extension = path.split('.')[-1] + if file_extension != 'tscn': + open_scene_button.hide() + +func _on_open_scene_button_pressed(): + EditorInterface.open_scene_from_path(_scene_path) + +func adjust_scale(amt:float): + scene_drop.adjust_scale(amt) + +func show_file_label(show:bool): + scene_drop.show_file_label(show) diff --git a/addons/scene_palette/components/scene_thumbnail/scene_drop_holder.gd.uid b/addons/scene_palette/components/scene_thumbnail/scene_drop_holder.gd.uid new file mode 100644 index 00000000..a4857a95 --- /dev/null +++ b/addons/scene_palette/components/scene_thumbnail/scene_drop_holder.gd.uid @@ -0,0 +1 @@ +uid://ho726nh4p5h5 diff --git a/addons/scene_palette/components/sub_palette.gd b/addons/scene_palette/components/sub_palette.gd new file mode 100644 index 00000000..c7372a69 --- /dev/null +++ b/addons/scene_palette/components/sub_palette.gd @@ -0,0 +1,76 @@ +@tool +extends Control +class_name PalettePluginSubPalette + +@export var arrow_closed:Texture2D +@export var arrow_open:Texture2D + +@onready var scene_drop_grid_container = %SceneDropGridContainer +@onready var title_minimize_button = %TitleMinimizeButton +@onready var sub_palette_container = %SubPaletteContainer +@onready var content_container = %ContentContainer +@onready var panel = %Panel + +## multiply the title color by this much for the background panel +const PANEL_COLOR_AMT = 0.8 +var directory:String + +# only set to false by the top level palette +var expandable:bool = true: + set(value): + expandable = value + if not expandable: + title_minimize_button.icon = null + title_minimize_button.disabled = true + +func set_title(title:String): + title_minimize_button.text = title.replace('-', ' ').replace('_', ' ') + +func add_item(item:PalettePluginSceneDrop): + scene_drop_grid_container.add_child(item) + +func instantiate_previews(value:bool): + for node in scene_drop_grid_container.get_children(): + if node is PalettePluginSceneDrop: + node.instantiate_scene_preview = value + for node in sub_palette_container.get_children(): + if node is PalettePluginSubPalette: + node.instantiate_previews(value) + +# only used by top level palette +#func clear_items(): + #for node in scene_drop_grid_container.get_children(): + #node.queue_free() + #for node in sub_palette_container.get_children(): + #node.queue_free() + +# only used by top level palette +func set_color(color:Color): + var stylebox:StyleBoxFlat = StyleBoxFlat.new() + stylebox.bg_color = color + stylebox.set_content_margin_all(7) + title_minimize_button.add_theme_stylebox_override('normal', stylebox) + title_minimize_button.add_theme_stylebox_override('disabled', stylebox) + + var panel_stylebox:StyleBoxFlat = panel.get_theme_stylebox('panel') + var new_stylebox = panel_stylebox.duplicate() + new_stylebox.bg_color = _get_multiplied_color(color, PANEL_COLOR_AMT) + panel.add_theme_stylebox_override('panel', new_stylebox) + +func _get_multiplied_color(color:Color, amt:float) -> Color: + return Color(color.r * amt, color.g * amt, color.b * amt) + +func add_subpalette(palette:PalettePluginSubPalette): + sub_palette_container.add_child(palette) + +func _on_title_minimize_button_toggled(toggled_on): + if expandable: + if toggled_on: + title_minimize_button.icon = arrow_closed + content_container.hide() + else: + title_minimize_button.icon = arrow_open + content_container.show() + +func _on_showin_file_system_button_pressed(): + EditorInterface.get_file_system_dock().navigate_to_path(directory) diff --git a/addons/scene_palette/components/sub_palette.gd.uid b/addons/scene_palette/components/sub_palette.gd.uid new file mode 100644 index 00000000..31c4b3b5 --- /dev/null +++ b/addons/scene_palette/components/sub_palette.gd.uid @@ -0,0 +1 @@ +uid://ci2mreqtoawtg diff --git a/addons/scene_palette/components/sub_palette.tscn b/addons/scene_palette/components/sub_palette.tscn new file mode 100644 index 00000000..a6c9a0fc --- /dev/null +++ b/addons/scene_palette/components/sub_palette.tscn @@ -0,0 +1,102 @@ +[gd_scene load_steps=9 format=3 uid="uid://bvpntidioecs2"] + +[ext_resource type="Script" path="res://addons/scene_palette/components/sub_palette.gd" id="1_refpc"] +[ext_resource type="Texture2D" uid="uid://bfg208jggp5oq" path="res://addons/scene_palette/icons/arrow-side.png" id="2_k85x0"] +[ext_resource type="Texture2D" uid="uid://d2kroa0x3fffu" path="res://addons/scene_palette/icons/arrow-down.png" id="3_vnqya"] +[ext_resource type="Texture2D" uid="uid://cvdxqb0025g6i" path="res://addons/scene_palette/icons/file-folder.png" id="4_he5ce"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_65kn4"] +bg_color = Color(0.333333, 0.368627, 0.431373, 0.243137) +border_width_left = 2 +border_width_top = 1 +border_width_right = 2 +border_width_bottom = 2 +border_color = Color(0.0588235, 0.0705882, 0.0901961, 0.203922) +shadow_color = Color(0.0563122, 0.080628, 0.128452, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ow4wf"] +bg_color = Color(0.784314, 0.784314, 0.784314, 0.14902) +corner_radius_top_left = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_phfrh"] +bg_color = Color(0.775733, 0.789583, 0.777343, 0.254902) +corner_radius_top_left = 5 + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_3q58g"] +content_margin_left = 6.0 +content_margin_top = 1.0 +content_margin_right = 6.0 +content_margin_bottom = 1.0 +bg_color = Color(0.6, 0.6, 0.6, 0.203922) +corner_radius_top_right = 6 + +[node name="SubPalette" type="MarginContainer"] +anchors_preset = 10 +anchor_right = 1.0 +offset_bottom = 26.0 +grow_horizontal = 2 +size_flags_horizontal = 3 +size_flags_vertical = 0 +theme_override_constants/margin_left = 2 +theme_override_constants/margin_top = 2 +theme_override_constants/margin_right = 2 +theme_override_constants/margin_bottom = 2 +script = ExtResource("1_refpc") +arrow_closed = ExtResource("2_k85x0") +arrow_open = ExtResource("3_vnqya") + +[node name="Panel" type="Panel" parent="."] +unique_name_in_owner = true +layout_mode = 2 +theme_override_styles/panel = SubResource("StyleBoxFlat_65kn4") + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_left = 4 +theme_override_constants/margin_top = 2 +theme_override_constants/margin_right = 4 +theme_override_constants/margin_bottom = 2 + +[node name="SubPalette" type="VBoxContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/SubPalette"] +layout_mode = 2 +theme_override_constants/separation = 0 + +[node name="TitleMinimizeButton" type="Button" parent="MarginContainer/SubPalette/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_colors/font_disabled_color = Color(0.764706, 0.741176, 0.776471, 1) +theme_override_styles/focus = SubResource("StyleBoxFlat_ow4wf") +theme_override_styles/hover = SubResource("StyleBoxFlat_ow4wf") +theme_override_styles/pressed = SubResource("StyleBoxFlat_phfrh") +theme_override_styles/normal = SubResource("StyleBoxFlat_ow4wf") +toggle_mode = true +text = "Subfolder name" +icon = ExtResource("3_vnqya") + +[node name="ShowinFileSystemButton" type="Button" parent="MarginContainer/SubPalette/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Show in FileSystem browser" +theme_override_styles/normal = SubResource("StyleBoxFlat_3q58g") +icon = ExtResource("4_he5ce") + +[node name="ContentContainer" type="VBoxContainer" parent="MarginContainer/SubPalette"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="SceneDropGridContainer" type="HFlowContainer" parent="MarginContainer/SubPalette/ContentContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="SubPaletteContainerContainer" type="MarginContainer" parent="MarginContainer/SubPalette/ContentContainer"] +layout_mode = 2 + +[node name="SubPaletteContainer" type="VBoxContainer" parent="MarginContainer/SubPalette/ContentContainer/SubPaletteContainerContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[connection signal="toggled" from="MarginContainer/SubPalette/HBoxContainer/TitleMinimizeButton" to="." method="_on_title_minimize_button_toggled"] +[connection signal="pressed" from="MarginContainer/SubPalette/HBoxContainer/ShowinFileSystemButton" to="." method="_on_showin_file_system_button_pressed"] diff --git a/addons/scene_palette/icons/arrow-down.png b/addons/scene_palette/icons/arrow-down.png new file mode 100644 index 00000000..df7a67c3 --- /dev/null +++ b/addons/scene_palette/icons/arrow-down.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8903d25e50cddffd3af622fcbfea232124a6213a2aba728a164fadec65a1efd0 +size 125 diff --git a/addons/scene_palette/icons/arrow-down.png.import b/addons/scene_palette/icons/arrow-down.png.import new file mode 100644 index 00000000..19fe6172 --- /dev/null +++ b/addons/scene_palette/icons/arrow-down.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cxbllpqxt36ya" +path="res://.godot/imported/arrow-down.png-b712fff108a92e79656dd6b4b969bf5f.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/arrow-down.png" +dest_files=["res://.godot/imported/arrow-down.png-b712fff108a92e79656dd6b4b969bf5f.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 diff --git a/addons/scene_palette/icons/arrow-side.png b/addons/scene_palette/icons/arrow-side.png new file mode 100644 index 00000000..d976f5a0 --- /dev/null +++ b/addons/scene_palette/icons/arrow-side.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bd2f3fe32603cf8c4779e074f81aaf4106e939b281ce957f9a68cf17bf7f961 +size 99 diff --git a/addons/scene_palette/icons/arrow-side.png.import b/addons/scene_palette/icons/arrow-side.png.import new file mode 100644 index 00000000..c18f95a0 --- /dev/null +++ b/addons/scene_palette/icons/arrow-side.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b7l05l6ghxx5j" +path="res://.godot/imported/arrow-side.png-185c3df7ddcc19c4d0a04506730ba56b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/arrow-side.png" +dest_files=["res://.godot/imported/arrow-side.png-185c3df7ddcc19c4d0a04506730ba56b.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 diff --git a/addons/scene_palette/icons/eye_dropper-sheet.png b/addons/scene_palette/icons/eye_dropper-sheet.png new file mode 100644 index 00000000..1d238b5b --- /dev/null +++ b/addons/scene_palette/icons/eye_dropper-sheet.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc93b53806bc9e88d90683a1eaa416ddc07ea9c0c42d1fc20054bdd569164405 +size 163 diff --git a/addons/scene_palette/icons/eye_dropper-sheet.png.import b/addons/scene_palette/icons/eye_dropper-sheet.png.import new file mode 100644 index 00000000..ff713569 --- /dev/null +++ b/addons/scene_palette/icons/eye_dropper-sheet.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://jb3bt4obaych" +path="res://.godot/imported/eye_dropper-sheet.png-759375e46347743a68a9433610fbea65.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/eye_dropper-sheet.png" +dest_files=["res://.godot/imported/eye_dropper-sheet.png-759375e46347743a68a9433610fbea65.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 diff --git a/addons/scene_palette/icons/eye_dropper.png b/addons/scene_palette/icons/eye_dropper.png new file mode 100644 index 00000000..63ba4962 --- /dev/null +++ b/addons/scene_palette/icons/eye_dropper.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ae0b08e872004fbefdd461403962c01aee36176d8da5486acba79a95b643cda +size 180 diff --git a/addons/scene_palette/icons/eye_dropper.png.import b/addons/scene_palette/icons/eye_dropper.png.import new file mode 100644 index 00000000..0e008dc7 --- /dev/null +++ b/addons/scene_palette/icons/eye_dropper.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d0030kelua55d" +path="res://.godot/imported/eye_dropper.png-e8e8534c81034d4b80b1d0d50f045035.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/eye_dropper.png" +dest_files=["res://.godot/imported/eye_dropper.png-e8e8534c81034d4b80b1d0d50f045035.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 diff --git a/addons/scene_palette/icons/file-folder.png b/addons/scene_palette/icons/file-folder.png new file mode 100644 index 00000000..25a3c356 --- /dev/null +++ b/addons/scene_palette/icons/file-folder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af97ba2499b8d939523ae49662bad32bdb5731cd28ca1d60862103acfa818d9b +size 114 diff --git a/addons/scene_palette/icons/file-folder.png.import b/addons/scene_palette/icons/file-folder.png.import new file mode 100644 index 00000000..84c8cf1d --- /dev/null +++ b/addons/scene_palette/icons/file-folder.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://baysps7t1gju6" +path="res://.godot/imported/file-folder.png-4eb362a491ca7af3427122ea9b56a25a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/file-folder.png" +dest_files=["res://.godot/imported/file-folder.png-4eb362a491ca7af3427122ea9b56a25a.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 diff --git a/addons/scene_palette/icons/heart.png b/addons/scene_palette/icons/heart.png new file mode 100644 index 00000000..2782fe6f --- /dev/null +++ b/addons/scene_palette/icons/heart.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:464061d008c18939c6daafcf51be9dd67008a4779637e522124a165ec7634b60 +size 165 diff --git a/addons/scene_palette/icons/heart.png.import b/addons/scene_palette/icons/heart.png.import new file mode 100644 index 00000000..4668ca09 --- /dev/null +++ b/addons/scene_palette/icons/heart.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dxeflkjub2wbe" +path="res://.godot/imported/heart.png-375be3a5833724da84df4916df475344.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/heart.png" +dest_files=["res://.godot/imported/heart.png-375be3a5833724da84df4916df475344.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 diff --git a/addons/scene_palette/icons/open_scene.png b/addons/scene_palette/icons/open_scene.png new file mode 100644 index 00000000..6c765256 --- /dev/null +++ b/addons/scene_palette/icons/open_scene.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5aba0485cefc56f09a7283ab5744547ea75395e961e28d5a72d881ebee071ba +size 153 diff --git a/addons/scene_palette/icons/open_scene.png.import b/addons/scene_palette/icons/open_scene.png.import new file mode 100644 index 00000000..4675f8d6 --- /dev/null +++ b/addons/scene_palette/icons/open_scene.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cw2ivvqkvuqyt" +path="res://.godot/imported/open_scene.png-b01f4c77cb3dbeea3fa4aba31365eb29.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/open_scene.png" +dest_files=["res://.godot/imported/open_scene.png-b01f4c77cb3dbeea3fa4aba31365eb29.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 diff --git a/addons/scene_palette/icons/palette.png b/addons/scene_palette/icons/palette.png new file mode 100644 index 00000000..1e06be5a --- /dev/null +++ b/addons/scene_palette/icons/palette.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f855296f759d36ce57b03d8600d7c08957de11a88118a670e99ac4249127b85f +size 195 diff --git a/addons/scene_palette/icons/palette.png.import b/addons/scene_palette/icons/palette.png.import new file mode 100644 index 00000000..4bfbb6ff --- /dev/null +++ b/addons/scene_palette/icons/palette.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cduf71uf0kltn" +path="res://.godot/imported/palette.png-30929a9d0642f2cfc79eb57d3c5d6d9e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/palette.png" +dest_files=["res://.godot/imported/palette.png-30929a9d0642f2cfc79eb57d3c5d6d9e.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 diff --git a/addons/scene_palette/icons/wrench.png b/addons/scene_palette/icons/wrench.png new file mode 100644 index 00000000..ada62b89 --- /dev/null +++ b/addons/scene_palette/icons/wrench.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb4b1fa6cb7184c2fa79a6fc204edb3d2157a578db82dfc71027eeab5afa91c6 +size 153 diff --git a/addons/scene_palette/icons/wrench.png.import b/addons/scene_palette/icons/wrench.png.import new file mode 100644 index 00000000..dbb9af1c --- /dev/null +++ b/addons/scene_palette/icons/wrench.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bkg2osrael3pk" +path="res://.godot/imported/wrench.png-c288a337b937f77b2e3ed006855511ec.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/scene_palette/icons/wrench.png" +dest_files=["res://.godot/imported/wrench.png-c288a337b937f77b2e3ed006855511ec.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 diff --git a/addons/scene_palette/palette.gd b/addons/scene_palette/palette.gd new file mode 100644 index 00000000..9f87a27c --- /dev/null +++ b/addons/scene_palette/palette.gd @@ -0,0 +1,254 @@ +@tool +extends Control + +# TODO: Remember which folders are minimized/expanded for favorites +# TODO: when settings are expanded, and plugin dock width is short, wrapping is weird. fix +# TODO: Add expand all/minimize all buttons +# TODO: Add default texture/tooltip for preview not found +# TODO: If a subpalette has no scenes, don't show it + +# TODO: supress warnings +# TODO: Some 2D scenes are not being instantiated for some reason +# TODO: Add favorite groupings +# TODO: Add ability to rearrange favorites +# TODO: Shrink font size on buttons with long names to show more of the name + +@export_category("Sub Scenes") +@export var subpalette_scene:PackedScene +@export var scene_drop_scene:PackedScene +@export var fav_button_scene:PackedScene + +var top_level_sub_palette:PalettePluginSubPalette + +# containers +@onready var favorites_bar = %FavoritesBar +@onready var favorites_settings = %FavoritesSettings +@onready var scroll_container = %ScrollContainer +@onready var settings_container = %SettingsContainer + +# buttons, etc +@onready var file_dialog = %FileDialog +@onready var choose_directory_button = %ChooseDirectoryButton +@onready var save_dir_to_favorites = %SaveDirToFavorites +@onready var instantiate_for_preview_button = %UsePreviewCheckButton +@onready var icon_scene_scale_slider = %IconSceneScaleSlider +@onready var show_scene_label_button = %ShowSceneLabelButton +@onready var supported_file_type_label: Label = %SupportedFileTypeLabel +@onready var allow_file_types_button: CheckButton = %AllowFileTypesButton + +# have save data to remember favorite palettes +const save_data_dir = "res://addons/scene_palette/save_data/" +const save_data_path = save_data_dir + "save_data.tres" +const pp = 'ScenePalettePlugin: ' # prepended to any printed messages +const allowed_file_types = ['tscn', 'png', 'gltf', 'glb', 'fbx', 'obj'] + +# signals to scene drops to indicate setting changes +signal scene_scale_changed(amt:float) +signal show_scene_label_toggled(toggled_on:bool) + +var _current_dir: + set(value): + _current_dir = value + + # remove top level palette + for child in scroll_container.get_children(): + child.queue_free() + + # create new top level palette + top_level_sub_palette = subpalette_scene.instantiate() + top_level_sub_palette.directory = _current_dir + scroll_container.add_child(top_level_sub_palette) + var palette_title = _current_dir.split('/')[-1] + top_level_sub_palette.set_title(palette_title) + top_level_sub_palette.expandable = false # all subpalettes can be minimized, but not the top level + + # default settings for a new directory + var toggle_on:bool = false + var scene_scale:float = 1 + + # if we are navigating to a favorite, load saved settings for it + if _current_dir_in_favorites(): + var save_data:PalettePluginSaveData = _get_save_data() + var favorite = save_data.favorites[_current_dir] + top_level_sub_palette.set_color(favorite.color) + toggle_on = favorite.instantiate_scenes_for_previews + scene_scale = favorite.get('scene_preview_scale', scene_scale) + show_scene_label_button.button_pressed = favorite.get('show_labels', false) + allow_file_types_button.button_pressed = favorite.get('allow_nonscene_files', false) + else: + icon_scene_scale_slider.value = 1 + + instantiate_for_preview_button.button_pressed = toggle_on + _populate_scenes(top_level_sub_palette, _current_dir) + show_scene_label_toggled.emit(show_scene_label_button.button_pressed) + + await get_tree().create_timer(0.05).timeout # ¯\_(ツ)_/¯ don't work without it + icon_scene_scale_slider.value = scene_scale + +func _reload_palette(): + _current_dir = _current_dir + +## Recursively create subpalettes for the specified directory +func _populate_scenes(sub_palette:PalettePluginSubPalette, dir_path:String): + var dir = DirAccess.open(dir_path) + if dir: + for dir_name in dir.get_directories(): + var new_sub_palette:PalettePluginSubPalette = subpalette_scene.instantiate() + var path = dir_path + '/' + dir_name + sub_palette.add_subpalette(new_sub_palette) + new_sub_palette.directory = path + new_sub_palette.set_title(dir_name) + _populate_scenes(new_sub_palette, path) + for file_name in dir.get_files(): + var file_extension:String = file_name.split('.')[-1] + var all_file_types_allowed:bool = allow_file_types_button.button_pressed + if file_extension == 'tscn' or (all_file_types_allowed and file_extension in allowed_file_types): + var scene_drop:PalettePluginSceneDrop = scene_drop_scene.instantiate() + sub_palette.add_item(scene_drop) + scene_drop.instantiate_scene_preview = instantiate_for_preview_button.button_pressed + scene_scale_changed.connect(scene_drop.adjust_scale) + show_scene_label_toggled.connect(scene_drop.show_file_label) + scene_drop.set_scene(dir_path +'/' + file_name) + + else: + print(pp, 'No directory found for ', dir_path) + + +func _ready(): + save_dir_to_favorites.hide() + settings_container.hide() + _populate_favorites_tab_bar() + if not FileAccess.file_exists(save_data_path): + _create_new_save_data() + + var types_string:String = 'Supported file types: ' + for type in allowed_file_types: + types_string += type + ', ' + types_string = types_string.left(types_string.length() - 2) # remove last comma + + supported_file_type_label.text = types_string + +func _create_new_save_data(): + var data = PalettePluginSaveData.new() + ResourceSaver.save(data, save_data_path) + +func _get_save_data() -> PalettePluginSaveData: + if not FileAccess.file_exists(save_data_path): + # This only happens if a user manually deletes the save_data while the plugin is enabled + print(pp, 'favorites data was removed. Creating new save data.') + _create_new_save_data() + _populate_favorites_tab_bar() + return ResourceLoader.load(save_data_path) + +func _save_data(data:PalettePluginSaveData): + ResourceSaver.save(data, save_data_path) + +func _on_choose_directory_button_pressed(): + file_dialog.show() + +func _on_file_dialog_dir_selected(dir): + _current_dir = dir + choose_directory_button.text = dir #.split('/')[-1] + # set the tooltip in case some of the text is clipped + choose_directory_button.tooltip_text = dir + if not _current_dir_in_favorites(): + save_dir_to_favorites.show() + else: + save_dir_to_favorites.hide() + +func _on_use_preview_check_button_toggled(toggled_on): + top_level_sub_palette.instantiate_previews(toggled_on) + if _current_dir_in_favorites(): + var save_data = _get_save_data() + save_data.favorites[_current_dir].instantiate_scenes_for_previews = toggled_on + _save_data(save_data) + +## Load favorites buttons +func _populate_favorites_tab_bar(): + var data:PalettePluginSaveData = _get_save_data() + + # clear existing buttons + for child in favorites_bar.get_children(): + # Don't remove the favorites bar header and settings button: + if child is PalettePluginFavoriteButton: + child.queue_free() + + # add new buttons + for dir in data.favorites: + var btn:PalettePluginFavoriteButton = fav_button_scene.instantiate() + btn.favorite_selected.connect(_on_new_favorite_selected) + btn.favorite_removed.connect(_on_favorite_removed) + btn.favorite_color_changed.connect(_on_favorite_color_changed) + favorites_bar.add_child(btn) + btn.directory = dir + btn.set_color(data.favorites[dir].color) + btn.set_settings_visibility(favorites_settings.button_pressed) + +func _on_new_favorite_selected(dir:String): + _on_file_dialog_dir_selected(dir) + +func _on_favorite_removed(dir:String): + var save_data:PalettePluginSaveData = _get_save_data() + save_data.favorites.erase(dir) + _save_data(save_data) + _populate_favorites_tab_bar() + + # show button to add to favorite again if we removed the current dir + if dir == _current_dir: + save_dir_to_favorites.show() + +func _on_favorite_color_changed(dir:String, color:Color): + var save_data:PalettePluginSaveData = _get_save_data() + save_data.favorites[dir].color = color + _save_data(save_data) + + # show real time updates if we're looking at this directory! + if _current_dir == dir: + top_level_sub_palette.set_color(color) + +func _on_save_dir_to_favorites_pressed(): + var save_data:PalettePluginSaveData = _get_save_data() + + if _current_dir_in_favorites(): + print(pp, _current_dir, ' is already in favorites') + else: + save_data.add_favorite(_current_dir, instantiate_for_preview_button.button_pressed) + _save_data(save_data) + _populate_favorites_tab_bar() + save_dir_to_favorites.hide() + +func _current_dir_in_favorites() -> bool: + var save_data:PalettePluginSaveData = _get_save_data() + return _current_dir in save_data.favorites + + +## toggle visibility of configuration options +func _on_favorites_settings_toggled(toggled_on): + for btn in favorites_bar.get_children(): + if btn is PalettePluginFavoriteButton: + btn.set_settings_visibility(toggled_on) + settings_container.visible = toggled_on + +func _on_show_scene_label_button_toggled(toggled_on): + show_scene_label_toggled.emit(toggled_on) + var save_data:PalettePluginSaveData = _get_save_data() + if _current_dir in save_data.favorites: + save_data.favorites[_current_dir].show_labels = toggled_on + _save_data(save_data) + +func _on_icon_scene_scale_slider_value_changed(value:float): + scene_scale_changed.emit(value) + var save_data:PalettePluginSaveData = _get_save_data() + if _current_dir in save_data.favorites: + save_data.favorites[_current_dir].scene_preview_scale = value + _save_data(save_data) + +func _on_reset_scale_button_pressed(): + icon_scene_scale_slider.value = 1 + +func _on_allow_file_types_button_toggled(toggled_on: bool) -> void: + var save_data:PalettePluginSaveData = _get_save_data() + if _current_dir in save_data.favorites: + save_data.favorites[_current_dir].allow_nonscene_files = toggled_on + _save_data(save_data) + _reload_palette() diff --git a/addons/scene_palette/palette.gd.uid b/addons/scene_palette/palette.gd.uid new file mode 100644 index 00000000..69aef69a --- /dev/null +++ b/addons/scene_palette/palette.gd.uid @@ -0,0 +1 @@ +uid://b1w21qpmp3ksw diff --git a/addons/scene_palette/palette.tscn b/addons/scene_palette/palette.tscn new file mode 100644 index 00000000..544b2794 --- /dev/null +++ b/addons/scene_palette/palette.tscn @@ -0,0 +1,268 @@ +[gd_scene load_steps=8 format=3 uid="uid://blawi4i3chdo3"] + +[ext_resource type="Script" path="res://addons/scene_palette/palette.gd" id="1_wgshj"] +[ext_resource type="PackedScene" uid="uid://bvpntidioecs2" path="res://addons/scene_palette/components/sub_palette.tscn" id="2_tthq0"] +[ext_resource type="PackedScene" uid="uid://cypob1bi5kovv" path="res://addons/scene_palette/components/scene_thumbnail/scene_drop.tscn" id="3_wqrsw"] +[ext_resource type="PackedScene" uid="uid://wfk2vnuru8d" path="res://addons/scene_palette/components/favorite_button/FavoriteButton.tscn" id="4_ynrw4"] +[ext_resource type="Texture2D" uid="uid://bf5ltt1pu5oc0" path="res://addons/scene_palette/icons/heart.png" id="5_fqbaj"] +[ext_resource type="Texture2D" uid="uid://brn8ob85ane7i" path="res://addons/scene_palette/icons/wrench.png" id="6_q5myn"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_yf8ba"] + +[node name="Palette" type="Control"] +clip_contents = true +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +size_flags_horizontal = 2 +size_flags_vertical = 2 +mouse_filter = 2 +script = ExtResource("1_wgshj") +subpalette_scene = ExtResource("2_tthq0") +scene_drop_scene = ExtResource("3_wqrsw") +fav_button_scene = ExtResource("4_ynrw4") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="DirectoryPicker" type="HFlowContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/DirectoryPicker"] +layout_mode = 2 +text = "Current Directory: " + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/DirectoryPicker"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ChooseDirectoryButton" type="Button" parent="VBoxContainer/DirectoryPicker/HBoxContainer"] +unique_name_in_owner = true +clip_contents = true +layout_mode = 2 +size_flags_horizontal = 3 +text = "Choose A Directory" +text_overrun_behavior = 1 + +[node name="SaveDirToFavorites" type="Button" parent="VBoxContainer/DirectoryPicker/HBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +tooltip_text = "Add to favorites." +icon = ExtResource("5_fqbaj") + +[node name="HSeparator" type="HSeparator" parent="VBoxContainer"] +layout_mode = 2 + +[node name="FavoritesBar" type="HFlowContainer" parent="VBoxContainer"] +unique_name_in_owner = true +clip_contents = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Favebar header" type="HBoxContainer" parent="VBoxContainer/FavoritesBar"] +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +alignment = 1 + +[node name="FavoritesSettings" type="Button" parent="VBoxContainer/FavoritesBar/Favebar header"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 2 +size_flags_vertical = 0 +tooltip_text = "Show additional settings options." +toggle_mode = true +icon = ExtResource("6_q5myn") + +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/FavoritesBar/Favebar header"] +layout_mode = 2 + +[node name="HeartIcon" type="TextureRect" parent="VBoxContainer/FavoritesBar/Favebar header"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +texture = ExtResource("5_fqbaj") +stretch_mode = 4 + +[node name="Label" type="Label" parent="VBoxContainer/FavoritesBar/Favebar header"] +layout_mode = 2 +size_flags_horizontal = 2 +text = "Favorites: " + +[node name="HSeparator2" type="HSeparator" parent="VBoxContainer"] +layout_mode = 2 + +[node name="SettingsContainer" type="VBoxContainer" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="SettingsHeader" type="HBoxContainer" parent="VBoxContainer/SettingsContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +tooltip_text = "Palette Display Settings. + +If currently viewing a favorite palette, settings will be saved for this palette." + +[node name="TextureRect2" type="TextureRect" parent="VBoxContainer/SettingsContainer/SettingsHeader"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +texture = ExtResource("6_q5myn") +stretch_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/SettingsContainer/SettingsHeader"] +layout_mode = 2 +text = "Palette Settings" + +[node name="TextureRect" type="TextureRect" parent="VBoxContainer/SettingsContainer/SettingsHeader"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +texture = ExtResource("6_q5myn") +stretch_mode = 2 + +[node name="UseOtherFileTypes" type="HFlowContainer" parent="VBoxContainer/SettingsContainer"] +layout_mode = 2 +tooltip_text = "If enabled, show all supported file types (png, glb, etc), not just \".tscn\" files." + +[node name="Label" type="Label" parent="VBoxContainer/SettingsContainer/UseOtherFileTypes"] +layout_mode = 2 +text = "Allow non-scene file types:" + +[node name="AllowFileTypesButton" type="CheckButton" parent="VBoxContainer/SettingsContainer/UseOtherFileTypes"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 10 + +[node name="ShowLabels" type="HFlowContainer" parent="VBoxContainer/SettingsContainer"] +layout_mode = 2 +tooltip_text = "Show scene labels: + +Show filenames under thumbnails." + +[node name="Label" type="Label" parent="VBoxContainer/SettingsContainer/ShowLabels"] +layout_mode = 2 +text = "Show scene labels: " + +[node name="ShowSceneLabelButton" type="CheckButton" parent="VBoxContainer/SettingsContainer/ShowLabels"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 10 + +[node name="UsePreview" type="HFlowContainer" parent="VBoxContainer/SettingsContainer"] +layout_mode = 2 +tooltip_text = "Instantiate Scene for Previews: + +Turned on: +Instantiates the scene and centers it in the preview window. +Suitable for small 2D scenes, provides a better thumbnail than +the editor preview. Ignores scenes that are not 2D or that +contain a camera. +CAUTION: This will actually load and instantiate the scene, +it is great for small assets, but may not be suitable for large +scenes or a directory that contains a lot of files. + +Turned off: +Uses the editor preview. This is generated from the visible +window when you last saved scene. If the thumbnail is blank, +open the scene, center it and save it. This should update +the thumbnail. + +If working on a favorite palette, preference is saved per palette." + +[node name="UsePreviewLabel" type="Label" parent="VBoxContainer/SettingsContainer/UsePreview"] +custom_minimum_size = Vector2(40, 0) +layout_mode = 2 +size_flags_horizontal = 3 +text = "Instantiate Scenes for Previews: " +autowrap_mode = 3 + +[node name="UsePreviewCheckButton" type="CheckButton" parent="VBoxContainer/SettingsContainer/UsePreview"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="HFlowContainer2" type="HFlowContainer" parent="VBoxContainer/SettingsContainer"] +layout_mode = 2 +tooltip_text = "Scene Preview Scale: + +Adjust size of scene previews. Only works if \"Instantiate scene for previews is turned on\"." + +[node name="Label" type="Label" parent="VBoxContainer/SettingsContainer/HFlowContainer2"] +layout_mode = 2 +text = "Scene Preview Scale" + +[node name="IconSceneScaleSlider" type="HSlider" parent="VBoxContainer/SettingsContainer/HFlowContainer2"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +min_value = 0.01 +max_value = 5.0 +step = 0.01 +value = 1.0 +tick_count = 6 + +[node name="ResetScaleButton" type="Button" parent="VBoxContainer/SettingsContainer/HFlowContainer2"] +layout_mode = 2 +tooltip_text = "reset scale to 1" +text = "reset" + +[node name="EmptyHSeparator" type="HSeparator" parent="VBoxContainer/SettingsContainer"] +layout_mode = 2 +theme_override_styles/separator = SubResource("StyleBoxEmpty_yf8ba") + +[node name="SupportedFileTypeLabel" type="Label" parent="VBoxContainer/SettingsContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Supported file types: tscn, png, gltf, glb, fbx, obj" +autowrap_mode = 3 + +[node name="LinkButton" type="LinkButton" parent="VBoxContainer/SettingsContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +tooltip_text = "Open repository on Github." +text = "A plugin by cixil" +uri = "https://github.com/cixil/godot-scene-palette" + +[node name="HSeparator3" type="HSeparator" parent="VBoxContainer"] +layout_mode = 2 + +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="VBoxContainer/ScrollContainer"] +custom_minimum_size = Vector2(30, 0) +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 0 +text = "Choose a directory to get started." +horizontal_alignment = 1 +autowrap_mode = 3 + +[node name="FileDialog" type="FileDialog" parent="VBoxContainer"] +unique_name_in_owner = true +title = "Open a Directory" +initial_position = 2 +size = Vector2i(478, 500) +ok_button_text = "Select Current Folder" +file_mode = 2 + +[connection signal="pressed" from="VBoxContainer/DirectoryPicker/HBoxContainer/ChooseDirectoryButton" to="." method="_on_choose_directory_button_pressed"] +[connection signal="pressed" from="VBoxContainer/DirectoryPicker/HBoxContainer/SaveDirToFavorites" to="." method="_on_save_dir_to_favorites_pressed"] +[connection signal="toggled" from="VBoxContainer/FavoritesBar/Favebar header/FavoritesSettings" to="." method="_on_favorites_settings_toggled"] +[connection signal="toggled" from="VBoxContainer/SettingsContainer/UseOtherFileTypes/AllowFileTypesButton" to="." method="_on_allow_file_types_button_toggled"] +[connection signal="toggled" from="VBoxContainer/SettingsContainer/ShowLabels/ShowSceneLabelButton" to="." method="_on_show_scene_label_button_toggled"] +[connection signal="toggled" from="VBoxContainer/SettingsContainer/UsePreview/UsePreviewCheckButton" to="." method="_on_use_preview_check_button_toggled"] +[connection signal="value_changed" from="VBoxContainer/SettingsContainer/HFlowContainer2/IconSceneScaleSlider" to="." method="_on_icon_scene_scale_slider_value_changed"] +[connection signal="pressed" from="VBoxContainer/SettingsContainer/HFlowContainer2/ResetScaleButton" to="." method="_on_reset_scale_button_pressed"] +[connection signal="dir_selected" from="VBoxContainer/FileDialog" to="." method="_on_file_dialog_dir_selected"] diff --git a/addons/scene_palette/plugin.cfg b/addons/scene_palette/plugin.cfg new file mode 100644 index 00000000..f6b23630 --- /dev/null +++ b/addons/scene_palette/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Scene Palette" +description="Drag and Drop scenes onto your scene" +author="ccpixel" +version="1.0.2" +script="scene_palette.gd" diff --git a/addons/scene_palette/resources/rsc_favorite.gd b/addons/scene_palette/resources/rsc_favorite.gd new file mode 100644 index 00000000..cf4dceb7 --- /dev/null +++ b/addons/scene_palette/resources/rsc_favorite.gd @@ -0,0 +1,11 @@ +# Can't use this because Godot can't save nested custom resources +# Leaving here in case this is fixed in the future + +#extends Resource +#class_name PalettePluginFavorite +# +#var _default_button_color = '#21262e' +# +#var directory:String +#var color:Color = Color(_default_button_color) +#var instantiate_scenes_for_previews:bool = false diff --git a/addons/scene_palette/resources/rsc_favorite.gd.uid b/addons/scene_palette/resources/rsc_favorite.gd.uid new file mode 100644 index 00000000..9c5ed444 --- /dev/null +++ b/addons/scene_palette/resources/rsc_favorite.gd.uid @@ -0,0 +1 @@ +uid://dbbhixj1ht5n2 diff --git a/addons/scene_palette/resources/rsc_pallete_plugin_save_data.gd b/addons/scene_palette/resources/rsc_pallete_plugin_save_data.gd new file mode 100644 index 00000000..504692b7 --- /dev/null +++ b/addons/scene_palette/resources/rsc_pallete_plugin_save_data.gd @@ -0,0 +1,16 @@ +@tool +extends Resource +class_name PalettePluginSaveData +const DEFAULT_BUTTON_COLOR = '#0e1521' + +# can't use this because Godot doesn't support saving nested custom resources yet +#@export var favorites:Array[PalettePluginFavorite] = [] +@export var favorites:Dictionary + +func add_favorite(directory, instantiate_scenes, color=DEFAULT_BUTTON_COLOR): + favorites[directory] = { + instantiate_scenes_for_previews = instantiate_scenes, + color = color, + scene_preview_scale = 1, + show_labels = true + } diff --git a/addons/scene_palette/resources/rsc_pallete_plugin_save_data.gd.uid b/addons/scene_palette/resources/rsc_pallete_plugin_save_data.gd.uid new file mode 100644 index 00000000..6f62b661 --- /dev/null +++ b/addons/scene_palette/resources/rsc_pallete_plugin_save_data.gd.uid @@ -0,0 +1 @@ +uid://d2vskl7301jhr diff --git a/addons/scene_palette/save_data/empty_file b/addons/scene_palette/save_data/empty_file new file mode 100644 index 00000000..e69de29b diff --git a/addons/scene_palette/scene_palette.gd b/addons/scene_palette/scene_palette.gd new file mode 100644 index 00000000..d63b2797 --- /dev/null +++ b/addons/scene_palette/scene_palette.gd @@ -0,0 +1,13 @@ +@tool +extends EditorPlugin + +var dock + +func _enter_tree(): + dock = preload("res://addons/scene_palette/palette.tscn").instantiate() + add_control_to_dock(DOCK_SLOT_LEFT_UL, dock) + + +func _exit_tree(): + remove_control_from_docks(dock) + dock.free() diff --git a/addons/scene_palette/scene_palette.gd.uid b/addons/scene_palette/scene_palette.gd.uid new file mode 100644 index 00000000..9a7f31fe --- /dev/null +++ b/addons/scene_palette/scene_palette.gd.uid @@ -0,0 +1 @@ +uid://bspbautrwdydf