145 lines
3.7 KiB
GDScript3
145 lines
3.7 KiB
GDScript3
|
tool
|
||
|
extends WindowDialog
|
||
|
|
||
|
|
||
|
onready var body : VBoxContainer = $MarginContainer/Body
|
||
|
|
||
|
onready var edited_scene_view : Container = body.get_node('EditedSceneView')
|
||
|
onready var scene_tree : Tree = edited_scene_view.get_node('SceneTree')
|
||
|
|
||
|
onready var footer : HBoxContainer = body.get_node('Footer')
|
||
|
onready var confirm_button : Button = footer.get_node('ConfirmButton')
|
||
|
onready var cancel_button : Button = footer.get_node('CancelButton')
|
||
|
|
||
|
onready var alert_dialog : AcceptDialog = $AlertDialog
|
||
|
|
||
|
|
||
|
enum Columns {
|
||
|
NAME,
|
||
|
PATH,
|
||
|
}
|
||
|
|
||
|
|
||
|
const MSG_EMPTY_SCENE = 'The current scene is empty!'
|
||
|
const MSG_UNSAVED_SCENE = 'The current scene is still not saved!'
|
||
|
const MSG_NO_FILTERED_NODES_IN_SCENE = "There aren't any %s nodes in the current scene"
|
||
|
|
||
|
const WINDOW_TITLE_DEFAULT = 'Select a Node'
|
||
|
const WINDOW_TITLE_WITH_FILTER = "Select the %s Node"
|
||
|
|
||
|
const DISABLED_ICON_MODULATE := Color(1, 1, 1, .5)
|
||
|
|
||
|
|
||
|
var class_filters : Array setget set_class_filters
|
||
|
var edited_scene_root : Node
|
||
|
|
||
|
|
||
|
var _editor_theme : EditorTheme
|
||
|
|
||
|
|
||
|
signal node_selected(selected_node)
|
||
|
|
||
|
|
||
|
func _ready():
|
||
|
self.class_filters = class_filters
|
||
|
|
||
|
scene_tree.columns = Columns.size()
|
||
|
scene_tree.set_column_expand(Columns.PATH, false)
|
||
|
|
||
|
alert_dialog.set_as_toplevel(true)
|
||
|
|
||
|
scene_tree.connect('item_activated', self, '_on_node_selected')
|
||
|
confirm_button.connect('pressed', self, '_on_node_selected')
|
||
|
cancel_button.connect('pressed', self, 'hide')
|
||
|
|
||
|
|
||
|
func initialize() -> bool:
|
||
|
edited_scene_root = get_tree().get_edited_scene_root()
|
||
|
if edited_scene_root == null:
|
||
|
_show_alert(MSG_EMPTY_SCENE)
|
||
|
return false
|
||
|
|
||
|
var scene_filename := edited_scene_root.filename
|
||
|
if not scene_filename:
|
||
|
_show_alert(MSG_UNSAVED_SCENE)
|
||
|
return false
|
||
|
|
||
|
scene_tree.clear()
|
||
|
|
||
|
var filtered_node_count := _add_node_to_scene_tree(edited_scene_root)
|
||
|
|
||
|
if class_filters and filtered_node_count == 0:
|
||
|
var filters_str := PoolStringArray(class_filters).join(" / ")
|
||
|
_show_alert(MSG_NO_FILTERED_NODES_IN_SCENE % filters_str)
|
||
|
return false
|
||
|
|
||
|
return true
|
||
|
|
||
|
|
||
|
func _add_node_to_scene_tree(node : Node, parent : TreeItem = null) -> int:
|
||
|
var tree_item := scene_tree.create_item(parent)
|
||
|
|
||
|
var node_class := node.get_class()
|
||
|
|
||
|
tree_item.set_icon(Columns.NAME, _editor_theme.get_icon(node_class))
|
||
|
tree_item.set_text(Columns.NAME, node.name)
|
||
|
|
||
|
tree_item.set_text(Columns.PATH, edited_scene_root.get_path_to(node))
|
||
|
|
||
|
var disabled_font_color := _editor_theme.get_color("disabled_font_color")
|
||
|
|
||
|
var filtered_node_count := 0
|
||
|
if class_filters:
|
||
|
var is_valid := false
|
||
|
|
||
|
for filter in class_filters:
|
||
|
if node.is_class(filter):
|
||
|
is_valid = true
|
||
|
filtered_node_count += 1
|
||
|
break
|
||
|
|
||
|
if not is_valid:
|
||
|
tree_item.set_selectable(Columns.NAME, false)
|
||
|
tree_item.set_icon_modulate(Columns.NAME, DISABLED_ICON_MODULATE)
|
||
|
tree_item.set_custom_color(Columns.NAME, disabled_font_color)
|
||
|
|
||
|
|
||
|
for child in node.get_children():
|
||
|
if child.owner == edited_scene_root:
|
||
|
filtered_node_count += _add_node_to_scene_tree(child, tree_item)
|
||
|
|
||
|
return filtered_node_count
|
||
|
|
||
|
|
||
|
func _show_alert(message : String) -> void:
|
||
|
alert_dialog.dialog_text = message
|
||
|
alert_dialog.popup_centered()
|
||
|
|
||
|
|
||
|
func _update_theme(editor_theme : EditorTheme) -> void:
|
||
|
_editor_theme = editor_theme
|
||
|
|
||
|
|
||
|
# Setters and Getters
|
||
|
func set_class_filters(filters : Array) -> void:
|
||
|
class_filters = filters
|
||
|
|
||
|
if class_filters != []:
|
||
|
var filters_str := PoolStringArray(class_filters).join(" / ")
|
||
|
window_title = WINDOW_TITLE_WITH_FILTER % filters_str
|
||
|
else:
|
||
|
window_title = WINDOW_TITLE_DEFAULT
|
||
|
|
||
|
|
||
|
# Signal Callbacks
|
||
|
func _on_node_selected() -> void:
|
||
|
var selected_item := scene_tree.get_selected()
|
||
|
|
||
|
if selected_item:
|
||
|
var node_path := selected_item.get_text(Columns.PATH)
|
||
|
var selected_node := edited_scene_root.get_node(node_path)
|
||
|
|
||
|
emit_signal('node_selected', selected_node)
|
||
|
|
||
|
hide()
|