mirror of
https://github.com/Relintai/godot_data_editor.git
synced 2024-11-13 06:27:19 +01:00
286 lines
8.5 KiB
GDScript
286 lines
8.5 KiB
GDScript
# Item Tree
|
|
tool
|
|
extends Control
|
|
|
|
var dummy_root = null
|
|
|
|
|
|
onready var tree = get_node("Panel/VBox/Tree") # The item tree
|
|
onready var class_context_menu = get_node("ClassContextMenu") # Context menu when right clicking on a class
|
|
onready var instance_context_menu = get_node("InstanceContextMenu") # Context menu when right clicking on an instance
|
|
onready var filter_control = get_node("Panel/VBox/Margin/HBoxContainer/Filter")
|
|
|
|
var item_manager = null # Item Manager, used to load, modify and save items
|
|
|
|
var tree_roots = {} # Holds a copy of all tree roots, i.e. classes, accessible by class name
|
|
var tree_elements = {} # Reference to all tree elements, accessible by ["_roots"][item_class] (for the roots) and [item_class][id] for the items
|
|
|
|
signal on_delete_pressed # Emitted when item is deleted
|
|
signal on_rename_pressed # Emitted when item is renamed
|
|
signal on_duplicate_pressed # Emitted when item is duplicated
|
|
signal on_new_item_pressed # Emitted when new item is created
|
|
signal on_open # Emitted when item is opened in OS
|
|
signal on_item_selected(item, is_leaf) # Emitted when a tree item is selected, carries the item and wheter or not it is a leaf element
|
|
|
|
var last_selected = null # Reference to last selected item
|
|
var last_selected_id = "" # Name/id of last selected item
|
|
var last_selected_class = "" # Name/id of last selected class
|
|
|
|
var plugin_config
|
|
|
|
var filter = ""
|
|
|
|
# Load the tree when ready
|
|
func _ready():
|
|
# test = EditorPlugin.new()
|
|
tree.set_hide_root(true)
|
|
tree.set_select_mode(Tree.SELECT_SINGLE)
|
|
tree.set_allow_rmb_select(true)
|
|
load_tree()
|
|
|
|
|
|
func load_tree(is_reload = false):
|
|
plugin_config = ConfigFile.new()
|
|
plugin_config.load("res://addons/godot_data_editor/plugin.cfg")
|
|
|
|
|
|
self.item_manager = Globals.get("item_manager")
|
|
tree_elements = {}
|
|
tree_roots = {}
|
|
#filter_control.set_text("")
|
|
#filter = ""
|
|
last_selected_id = ""
|
|
last_selected_class = ""
|
|
last_selected = null
|
|
var tree_element_to_be_selected = null
|
|
|
|
|
|
# Store the class and name of the last selected item, in case the tree is reloaded
|
|
last_selected = tree.get_selected()
|
|
if last_selected:
|
|
if last_selected.has_meta("item"):
|
|
if last_selected.get_meta("item").get("_id"):
|
|
self.last_selected_id = last_selected.get_meta("item")._id
|
|
else:
|
|
self.last_selected_id = null
|
|
self.last_selected_class = last_selected.get_meta("class")
|
|
#print(last_selected_id)
|
|
#print(last_selected_class)
|
|
|
|
tree.clear()
|
|
|
|
|
|
# Create the roots for each item class, e.g. actors, monsters, crystals...
|
|
dummy_root = tree.create_item()
|
|
tree_elements["_roots"] = {}
|
|
var classes = item_manager.class_names
|
|
for item_class in classes:
|
|
var root = create_item_root(item_class)
|
|
tree_elements["_roots"][item_class] = root
|
|
pass
|
|
|
|
# Populate the list with items
|
|
classes.sort()
|
|
for item_class in classes:
|
|
tree_elements[item_class] = {}
|
|
|
|
var ids = item_manager.items[item_class].keys()
|
|
ids.sort()
|
|
for id in ids:
|
|
var item = item_manager.get_item(item_class, id)
|
|
if filter == "" or id.find(filter) != -1:
|
|
var tree_item = add_leaf(item, false)
|
|
pass
|
|
pass
|
|
|
|
if last_selected_id:
|
|
tree_element_to_be_selected = get_tree_item(last_selected_class, last_selected_id)
|
|
elif last_selected_class:
|
|
tree_element_to_be_selected = get_tree_item(last_selected_class)
|
|
elif tree.get_root().get_children():
|
|
tree_element_to_be_selected = tree.get_root().get_children()
|
|
else:
|
|
tree_element_to_be_selected = null # No elements to be selected
|
|
|
|
last_selected
|
|
|
|
# Handle filter
|
|
if tree_element_to_be_selected and not filter_control.has_focus():
|
|
tree.grab_focus()
|
|
tree_element_to_be_selected.select(0)
|
|
|
|
func create_item_root(item_class):
|
|
var tree_item = tree.create_item(dummy_root)
|
|
tree_item.set_selectable(0, true)
|
|
tree_item.set_icon(0, load(plugin_config.get_value("custom", "class_directory") + "/" + item_class + ".png"))
|
|
tree_item.set_text(0, item_class.capitalize())
|
|
tree_item.set_meta("class", item_class)
|
|
tree_roots[item_class] = tree_item
|
|
return tree_item
|
|
|
|
func select_first_element():
|
|
var first_element = tree.get_root().get_children()
|
|
if first_element:
|
|
first_element.select(0)
|
|
first_element = first_element.get_children()
|
|
last_selected = first_element.get_meta("item")
|
|
last_selected_id = last_selected._id
|
|
last_selected_class = last_selected._class
|
|
return last_selected
|
|
|
|
|
|
|
|
# Creates a new tree item, optionally with an existing item
|
|
func add_leaf(item, update_order):
|
|
var id = item._id
|
|
var item_class = item._class
|
|
var tree_item = tree.create_item(tree_roots[item_class])
|
|
set_tree_item_label_text(item, tree_item)
|
|
tree_item.set_selectable(0, true)
|
|
tree_item.set_meta("class", item_class)
|
|
tree_item.set_meta("item", item)
|
|
|
|
tree_elements[item_class][id] = tree_item
|
|
|
|
# Don't order the tree in the beginning as the ids will already be sorted
|
|
if update_order:
|
|
# Move the items which come before in the alphabet to the top
|
|
var elements_name_array = tree_elements[item_class].keys()
|
|
elements_name_array.sort()
|
|
tree_item.move_to_top()
|
|
var to_be_reordered = []
|
|
for element_name in elements_name_array:
|
|
if str(id) > str(element_name) or str(id) == str(element_name):
|
|
to_be_reordered.append(element_name)
|
|
else:
|
|
break
|
|
pass
|
|
to_be_reordered.invert()
|
|
for element_name in to_be_reordered:
|
|
tree_elements[item_class][element_name].move_to_top()
|
|
pass
|
|
tree_item.select(0)
|
|
return tree_item
|
|
|
|
|
|
func set_tree_item_label_text(item, tree_item = null):
|
|
if tree_item == null:
|
|
tree_item = get_tree_item(item._class, item._id)
|
|
|
|
if item._dirty or not item._persistent:
|
|
tree_item.set_text(0, " " + item._display_name + " (*)")
|
|
tree_item.set_custom_color(0, Color(1, 0.5, 0.5))
|
|
else:
|
|
tree_item.set_text(0, " " + item._display_name)
|
|
tree_item.set_custom_color(0, Color(0.7, 0.7, 0.7))
|
|
|
|
func get_selected_item_root():
|
|
var selected = tree.get_selected()
|
|
if selected.has_meta("item"):
|
|
return selected.get_parent()
|
|
else:
|
|
return selected
|
|
|
|
|
|
# A tree element in the tree was selected (either class or item)
|
|
func _on_Tree_cell_selected():
|
|
emit_signal("on_item_selected", get_selected_item(), get_selected_class())
|
|
|
|
func get_selected_item():
|
|
var selected = tree.get_selected()
|
|
if selected.has_meta("item"):
|
|
return selected.get_meta("item")
|
|
else:
|
|
return null
|
|
|
|
|
|
func get_selected_class():
|
|
return tree.get_selected().get_meta("class")
|
|
|
|
|
|
func get_tree_item(item_class, id = ""):
|
|
if id != "":
|
|
if tree_elements.has(item_class) and tree_elements[item_class].has(id):
|
|
return tree_elements[item_class][id]
|
|
else:
|
|
return null
|
|
else:
|
|
if tree_elements["_roots"].has(item_class):
|
|
return tree_elements["_roots"][item_class]
|
|
else:
|
|
return null
|
|
|
|
# Sets the selection to a specific tree item
|
|
func select_item(item):
|
|
if tree_elements.has(item._class) and tree_elements[item._class].has(item._id):
|
|
tree_elements[item._class][item._id].select(0)
|
|
|
|
# Sets the selection to a specific class
|
|
func select_class(item_class):
|
|
if tree_elements["_roots"].has(item_class):
|
|
tree_elements["_roots"][item_class].select(0)
|
|
|
|
|
|
func _on_Filter_text_changed( text ):
|
|
self.filter = text
|
|
load_tree()
|
|
|
|
|
|
|
|
# Right click context menu on leafs
|
|
# 0 = Add | 1 = Rename | 2 = Delete | 3 = Duplicate | 4 = Open
|
|
func _on_InstanceContextMenu_item_pressed(index):
|
|
if index == 0:
|
|
emit_signal("on_new_item_pressed")
|
|
elif index == 1:
|
|
emit_signal("on_rename_pressed")
|
|
elif index == 2:
|
|
emit_signal("on_delete_pressed")
|
|
elif index == 3:
|
|
emit_signal("on_duplicate_pressed")
|
|
elif index == 4:
|
|
emit_signal("on_open")
|
|
|
|
###########################################################
|
|
# CLASS CONTEXT MENU #
|
|
###########################################################
|
|
func _on_ClassContextMenu_about_to_show():
|
|
class_context_menu.set_item_text(0, tr("Add") + " " + get_selected_class().capitalize())
|
|
|
|
func _on_InstanceContextMenu_about_to_show():
|
|
pass
|
|
|
|
# Right click context menu on class branch
|
|
# 0 = Add | 1 = Delete Class
|
|
func _on_ClassContextMenu_item_pressed(index):
|
|
if index == 0:
|
|
emit_signal("on_new_item_pressed")
|
|
elif index == 1:
|
|
emit_signal("on_delete_pressed")
|
|
elif index == 2:
|
|
emit_signal("on_rename_pressed")
|
|
|
|
|
|
|
|
func _on_Tree_item_rmb_selected(pos):
|
|
var is_leaf = get_selected_item() != null
|
|
if is_leaf:
|
|
instance_context_menu.set_pos(get_global_mouse_pos())
|
|
instance_context_menu.popup()
|
|
else:
|
|
class_context_menu.set_pos(get_global_mouse_pos())
|
|
class_context_menu.popup()
|
|
|
|
|
|
func _on_DeleteItemDialog_confirmed():
|
|
var selected_item = get_selected_item()
|
|
if selected_item != null:
|
|
item_manager.delete_item(selected_item)
|
|
load_tree()
|
|
|
|
|
|
|
|
|
|
|
|
#TODO: Proper memory management?
|