Added scene palette addon

This commit is contained in:
Marco 2025-02-24 11:57:09 +01:00
commit 687d3f7803
43 changed files with 1471 additions and 0 deletions

View file

@ -0,0 +1,9 @@
@tool
extends Button
func _on_mouse_entered():
scale = Vector2(1.05, 1.05)
func _on_mouse_exited():
scale = Vector2.ONE

View file

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

View file

@ -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)

View file

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

View file

@ -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"]

View file

@ -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

View file

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

View file

@ -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"]

View file

@ -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)

View file

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

View file

@ -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)

View file

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

View file

@ -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"]