Added spoilers and entity/entity-array properties to property grid.
This commit is contained in:
parent
c961dff76a
commit
eab4f1fa08
7
scenes/property_list/entity_spoiler.tscn
Normal file
7
scenes/property_list/entity_spoiler.tscn
Normal file
@ -0,0 +1,7 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/spoiler.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/property_list/scripts/entity_spoiler.gd" type="Script" id=2]
|
||||
|
||||
[node name="spoiler" instance=ExtResource( 1 )]
|
||||
script = ExtResource( 2 )
|
7
scenes/property_list/entity_tree_spoiler.tscn
Normal file
7
scenes/property_list/entity_tree_spoiler.tscn
Normal file
@ -0,0 +1,7 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/spoiler.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/property_list/scripts/entity_tree_spoiler.gd" type="Script" id=2]
|
||||
|
||||
[node name="spoiler" instance=ExtResource( 1 )]
|
||||
script = ExtResource( 2 )
|
22
scenes/property_list/scripts/entity_spoiler.gd
Normal file
22
scenes/property_list/scripts/entity_spoiler.gd
Normal file
@ -0,0 +1,22 @@
|
||||
extends "res://addons/de.mewin.gduibasics/scenes/scripts/spoiler.gd"
|
||||
|
||||
var entity : Object setget _set_entity
|
||||
|
||||
#############
|
||||
# overrides #
|
||||
#############
|
||||
func _lazy_load_child() -> Control:
|
||||
var prop_list : Control = load("res://addons/de.mewin.gduibasics/scripts/types/controls/property_list.gd").new()
|
||||
prop_list.size_flags_horizontal |= SIZE_EXPAND
|
||||
prop_list.entity = entity
|
||||
return prop_list
|
||||
|
||||
###########
|
||||
# setters #
|
||||
###########
|
||||
func _set_entity(val : Object) -> void:
|
||||
if val != entity:
|
||||
entity = val
|
||||
var prop_list := _get_child()
|
||||
if prop_list:
|
||||
prop_list.entity = entity
|
26
scenes/property_list/scripts/entity_tree_spoiler.gd
Normal file
26
scenes/property_list/scripts/entity_tree_spoiler.gd
Normal file
@ -0,0 +1,26 @@
|
||||
extends "res://addons/de.mewin.gduibasics/scenes/scripts/spoiler.gd"
|
||||
|
||||
# only used to store the entities before the tree is created
|
||||
var __entities := [].duplicate()
|
||||
|
||||
#############
|
||||
# overrides #
|
||||
#############
|
||||
func _lazy_load_child() -> Control:
|
||||
var tree : Control = load("res://addons/de.mewin.gduibasics/scripts/types/controls/entity_tree.gd").new()
|
||||
tree.size_flags_horizontal |= SIZE_EXPAND
|
||||
tree.rect_min_size.y = 300 # ?
|
||||
for entity in __entities:
|
||||
tree.add_entity(entity)
|
||||
__entities.clear()
|
||||
return tree
|
||||
|
||||
################
|
||||
# public stuff #
|
||||
################
|
||||
func add_entity(entity : Object) -> void:
|
||||
var tree := _get_child()
|
||||
if tree:
|
||||
tree.add_entity(entity)
|
||||
else:
|
||||
__entities.append(entity)
|
115
scenes/scripts/spoiler.gd
Normal file
115
scenes/scripts/spoiler.gd
Normal file
@ -0,0 +1,115 @@
|
||||
extends VBoxContainer
|
||||
|
||||
export(Texture) var icon_shown : Texture = preload("res://addons/de.mewin.gduibasics/images/arrow_down.svg")
|
||||
export(Texture) var icon_hidden : Texture = preload("res://addons/de.mewin.gduibasics/images/arrow_right.svg")
|
||||
var child_visible : bool setget _set_child_visible, _get_child_visible
|
||||
var label := "" setget _set_label
|
||||
|
||||
onready var _header : Control = GDBUtility.find_node_by_name(self, "header")
|
||||
onready var _tex_arrow : TextureRect = GDBUtility.find_node_by_name(self, "tex_arrow")
|
||||
|
||||
var __last_child : Control = null
|
||||
|
||||
#############
|
||||
# overrides #
|
||||
#############
|
||||
func _ready() -> void:
|
||||
__update_child()
|
||||
_header.label = label
|
||||
|
||||
func add_child(child : Node, legible_unique_name := false):
|
||||
.add_child(child, legible_unique_name)
|
||||
__update_child()
|
||||
|
||||
################
|
||||
# overridables #
|
||||
################
|
||||
func _lazy_load_child() -> Control:
|
||||
return null
|
||||
|
||||
################
|
||||
# public stuff #
|
||||
################
|
||||
func toggle() -> void:
|
||||
_set_child_visible(!_get_child_visible())
|
||||
|
||||
#################
|
||||
# private stuff #
|
||||
#################
|
||||
func _get_child() -> Control:
|
||||
if get_child_count() < 2:
|
||||
return null
|
||||
return get_child(1) as Control
|
||||
|
||||
func __update_child() -> void:
|
||||
var the_child := _get_child()
|
||||
if the_child == __last_child:
|
||||
return
|
||||
|
||||
if __last_child:
|
||||
GDBUtility.disconnect_all(__last_child, self)
|
||||
if the_child:
|
||||
the_child.connect("visibility_changed", self, "_on_child_visibility_changed")
|
||||
the_child.connect("tree_exiting", self, "_on_child_tree_exiting")
|
||||
if the_child.visible != _get_child_visible():
|
||||
emit_signal("child_visibility_changed")
|
||||
__last_child = the_child
|
||||
__update_icon()
|
||||
|
||||
func __update_icon() -> void:
|
||||
if _get_child_visible():
|
||||
_tex_arrow.texture = icon_shown
|
||||
else:
|
||||
_tex_arrow.texture = icon_hidden
|
||||
|
||||
#####################
|
||||
# setters & getters #
|
||||
#####################
|
||||
func _set_label(val : String) -> void:
|
||||
label = val
|
||||
if _header:
|
||||
_header.label = val
|
||||
|
||||
func _set_child_visible(val : bool) -> void:
|
||||
var child := _get_child()
|
||||
if val && !child:
|
||||
child = yield(GDBCoroutine.await(_lazy_load_child()), "completed")
|
||||
if child:
|
||||
emit_signal("child_created", child)
|
||||
child.visible = true
|
||||
add_child(child)
|
||||
return
|
||||
|
||||
if child && child.visible != val:
|
||||
child.visible = val
|
||||
emit_signal("on_child_visibility_changed")
|
||||
|
||||
func _get_child_visible() -> bool:
|
||||
var child := _get_child()
|
||||
if child:
|
||||
return child.visible
|
||||
return false
|
||||
|
||||
############
|
||||
# handlers #
|
||||
############
|
||||
func _on_header_gui_input(event : InputEvent) -> void:
|
||||
if event is InputEventMouseButton && event.button_index == BUTTON_LEFT && event.pressed:
|
||||
toggle()
|
||||
|
||||
func _on_child_visibility_changed() -> void:
|
||||
__update_icon()
|
||||
emit_signal("child_visibility_changed")
|
||||
|
||||
func _on_child_tree_exiting() -> void:
|
||||
var tree := get_tree()
|
||||
if !tree:
|
||||
return
|
||||
yield(tree, "idle_frame")
|
||||
__update_child()
|
||||
|
||||
###########
|
||||
# signals #
|
||||
###########
|
||||
signal child_created(child)
|
||||
signal child_visibility_changed()
|
31
scenes/spoiler.tscn
Normal file
31
scenes/spoiler.tscn
Normal file
@ -0,0 +1,31 @@
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/scripts/spoiler.gd" type="Script" id=1]
|
||||
[ext_resource path="res://addons/de.mewin.gduibasics/scenes/property_list/header.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://addons/de.mewin.gduibasics/images/arrow_right.svg" type="Texture" id=3]
|
||||
|
||||
[node name="spoiler" type="VBoxContainer"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="header" parent="." instance=ExtResource( 2 )]
|
||||
margin_right = 1024.0
|
||||
|
||||
[node name="margin_container" type="MarginContainer" parent="header"]
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 22.0
|
||||
mouse_filter = 2
|
||||
custom_constants/margin_left = 5
|
||||
|
||||
[node name="tex_arrow" type="TextureRect" parent="header/margin_container"]
|
||||
margin_left = 5.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 22.0
|
||||
mouse_filter = 2
|
||||
texture = ExtResource( 3 )
|
||||
|
||||
[connection signal="gui_input" from="header" to="." method="_on_header_gui_input"]
|
@ -74,11 +74,14 @@ func __sort_children():
|
||||
rows[rows.size() - 1].append(child)
|
||||
|
||||
child.rect_size = child.get_combined_minimum_size()
|
||||
column_widths[col] = max(column_widths[col], child.rect_size.x)
|
||||
|
||||
var full_size : Vector2 = child.rect_size + Vector2(constraints.padding_left + constraints.padding_right, \
|
||||
constraints.padding_top + constraints.padding_bottom)
|
||||
column_widths[col] = max(column_widths[col], full_size.x)
|
||||
|
||||
if child.size_flags_horizontal & Control.SIZE_EXPAND:
|
||||
column_expand[col] = max(column_expand[col], child.size_flags_stretch_ratio)
|
||||
row_width += child.rect_size.x
|
||||
row_width += full_size.x
|
||||
|
||||
col = col + constraints.colspan
|
||||
|
||||
@ -100,22 +103,24 @@ func __sort_children():
|
||||
col = 0
|
||||
for child in row:
|
||||
var constraints := _get_constraints(child)
|
||||
child.rect_position = pos
|
||||
child.rect_position = pos + Vector2(constraints.padding_left, constraints.padding_top)
|
||||
|
||||
var width := 0.0
|
||||
for i in range(min(constraints.colspan, columns - col)):
|
||||
width += column_widths[col + i]
|
||||
|
||||
if child.size_flags_horizontal & Control.SIZE_FILL:
|
||||
child.rect_size.x = width
|
||||
child.rect_size.x = width - (constraints.padding_left + constraints.padding_right)
|
||||
pos.x += width
|
||||
|
||||
row_height = max(row_height, child.rect_size.y)
|
||||
var full_height : float = child.rect_size.y + constraints.padding_top + constraints.padding_bottom
|
||||
row_height = max(row_height, full_height)
|
||||
col = col + constraints.colspan
|
||||
|
||||
for child in row:
|
||||
if child.size_flags_vertical & Control.SIZE_FILL:
|
||||
child.rect_size.y = row_height
|
||||
var constraints := _get_constraints(child)
|
||||
child.rect_size.y = row_height - (constraints.padding_top + constraints.padding_bottom)
|
||||
|
||||
pos.y += row_height
|
||||
pos.x = 0.0
|
||||
|
@ -14,12 +14,10 @@ onready var __selected_entity_adapter := get_node_or_null(selected_entity_adapte
|
||||
func _ready():
|
||||
create_item() # invisible root
|
||||
hide_root = true
|
||||
columns = column_ids.size()
|
||||
select_mode = SELECT_ROW
|
||||
set_column_titles_visible(true)
|
||||
|
||||
for col in range(min(columns, column_titles.size())):
|
||||
set_column_title(col, column_titles[col])
|
||||
__update_columns()
|
||||
|
||||
connect("item_selected", self, "_on_item_selected")
|
||||
if __selected_entity_adapter != null:
|
||||
@ -33,6 +31,9 @@ func add_entity(entity : Object) -> void:
|
||||
printerr("UIB_EntityTree: attempted to add invalid entity")
|
||||
return
|
||||
|
||||
if !column_ids:
|
||||
__columns_from_entity(entity)
|
||||
|
||||
var itm := create_item()
|
||||
itm.set_metadata(0, entity)
|
||||
var col := 0
|
||||
@ -101,6 +102,24 @@ func __update_row(entity : Object, column := ""):
|
||||
|
||||
itm.set_text(col_idx, GDB_Property.get_prop_value_as_string(prop))
|
||||
|
||||
func __columns_from_entity(entity : Object) -> void:
|
||||
column_ids = []
|
||||
column_titles = []
|
||||
|
||||
for prop_id in GDB_Entity.get_entity_property_ids(entity):
|
||||
var prop : Object = entity.get_property_by_id(prop_id)
|
||||
if prop && prop.get_type() in [TYPE_STRING, TYPE_INT, TYPE_REAL, TYPE_BOOL] \
|
||||
&& !(GDB_Property.get_prop_flags(prop) & GDB_Property.FLAG_HIDDEN):
|
||||
column_ids.append(prop_id)
|
||||
column_titles.append(prop.get_name())
|
||||
|
||||
__update_columns()
|
||||
|
||||
func __update_columns() -> void:
|
||||
columns = max(1, column_ids.size())
|
||||
for col in range(min(columns, column_titles.size())):
|
||||
set_column_title(col, column_titles[col])
|
||||
|
||||
############
|
||||
# handlers #
|
||||
############
|
||||
|
@ -2,6 +2,8 @@ extends UIB_DynamicGridContainer
|
||||
|
||||
class_name UIB_PropertyList
|
||||
|
||||
const COLUMNS = 2
|
||||
|
||||
export(NodePath) var entity_adapter := ""
|
||||
|
||||
var entity : Object = null setget _set_entity
|
||||
@ -13,7 +15,7 @@ onready var __entity_adapter := get_node_or_null(entity_adapter) as GDB_DataAdap
|
||||
# overrides #
|
||||
#############
|
||||
func _ready() -> void:
|
||||
self.columns = 2
|
||||
self.columns = COLUMNS
|
||||
|
||||
if __entity_adapter != null:
|
||||
__entity_adapter.connect("data_changed", self, "_on_entity_adapter_data_changed")
|
||||
@ -22,13 +24,20 @@ func _ready() -> void:
|
||||
# overridables #
|
||||
################
|
||||
func _make_controls(property : Object) -> Array:
|
||||
if GDB_Property.get_prop_flags(property) & GDB_Property.FLAG_HIDDEN:
|
||||
return []
|
||||
|
||||
match property.get_type():
|
||||
GDB_Property.TYPE_HEADER:
|
||||
return _make_header(property)
|
||||
GDB_Property.TYPE_ENTITY:
|
||||
return _make_controls_entity(property)
|
||||
TYPE_INT, TYPE_REAL, TYPE_STRING:
|
||||
return _make_controls_simple(property)
|
||||
TYPE_BOOL:
|
||||
return _make_controls_bool(property)
|
||||
TYPE_ARRAY:
|
||||
return _make_controls_array(property)
|
||||
_:
|
||||
return []
|
||||
|
||||
@ -37,9 +46,17 @@ func _make_header(property : Object) -> Array:
|
||||
var header := preload("res://addons/de.mewin.gduibasics/scenes/property_list/header.tscn").instance()
|
||||
header.label = property.get_name()
|
||||
header.texture = GDB_Property.get_prop_icon(property)
|
||||
get_constraints(header).colspan = self.columns
|
||||
get_constraints(header).colspan = COLUMNS
|
||||
return [header]
|
||||
|
||||
func _make_controls_entity(property : Object) -> Array:
|
||||
var spoiler := preload("res://addons/de.mewin.gduibasics/scenes/property_list/entity_spoiler.tscn").instance()
|
||||
spoiler.label = property.get_name()
|
||||
spoiler.entity = property.get_value()
|
||||
get_constraints(spoiler).colspan = COLUMNS
|
||||
get_constraints(spoiler).padding_left = 5
|
||||
return [spoiler]
|
||||
|
||||
func _make_controls_simple(property : Object) -> Array:
|
||||
var label := preload("res://addons/de.mewin.gduibasics/scenes/property_list/property_label.tscn").instance()
|
||||
label.label = property.get_name()
|
||||
@ -57,11 +74,29 @@ func _make_controls_bool(property : Object) -> Array:
|
||||
var checkbox := UIB_PropertyCheckBox.new()
|
||||
checkbox.property = property
|
||||
checkbox.size_flags_horizontal |= SIZE_EXPAND
|
||||
checkbox.disabled = !(GDB_Property.get_prop_flags(property) & GDB_Property.FLAG_READONLY)
|
||||
get_constraints(checkbox).colspan = self.columns
|
||||
return [
|
||||
checkbox
|
||||
]
|
||||
|
||||
func _make_controls_array(property : Object) -> Array:
|
||||
match GDB_Property.get_prop_content_type(property):
|
||||
GDB_Property.TYPE_ENTITY:
|
||||
return _make_controls_entity_array(property)
|
||||
_:
|
||||
return []
|
||||
|
||||
func _make_controls_entity_array(property : Object) -> Array:
|
||||
var spoiler := preload("res://addons/de.mewin.gduibasics/scenes/property_list/entity_tree_spoiler.tscn").instance()
|
||||
spoiler.label = property.get_name()
|
||||
for entity in property.get_value():
|
||||
spoiler.add_entity(entity)
|
||||
spoiler.connect("child_created", self, "_on_entity_array_tree_created")
|
||||
get_constraints(spoiler).colspan = COLUMNS
|
||||
get_constraints(spoiler).padding_left = 5
|
||||
return [spoiler]
|
||||
|
||||
################
|
||||
# public stuff #
|
||||
################
|
||||
@ -139,6 +174,9 @@ func __init_entity() -> void:
|
||||
if entity == null:
|
||||
return
|
||||
|
||||
var title_property := GDB_Entity.make_entity_title_property(entity)
|
||||
if title_property:
|
||||
pass
|
||||
for property in entity.get_properties():
|
||||
add_property(property)
|
||||
|
||||
@ -162,6 +200,14 @@ func _set_entity(entity_ : Object) -> void:
|
||||
func _on_entity_adapter_data_changed() -> void:
|
||||
_set_entity(__entity_adapter.data)
|
||||
|
||||
func _on_entity_array_tree_created(tree : UIB_EntityTree) -> void:
|
||||
tree.connect("item_activated", self, "_on_entity_array_tree_item_activated", [tree])
|
||||
|
||||
func _on_entity_array_tree_item_activated(tree : UIB_EntityTree) -> void:
|
||||
var entity : Object = tree.get_selected_entity()
|
||||
if entity:
|
||||
_set_entity(entity)
|
||||
|
||||
###########
|
||||
# signals #
|
||||
###########
|
||||
|
@ -21,7 +21,7 @@ func _gui_input(event : InputEvent) -> void:
|
||||
#################
|
||||
func __init_property() -> void:
|
||||
text = __text_from_property()
|
||||
editable = (property != null)
|
||||
editable = (property != null && !(GDB_Property.get_prop_flags(property) & GDB_Property.FLAG_READONLY))
|
||||
__validate_text()
|
||||
|
||||
if property != null:
|
||||
|
@ -5,21 +5,54 @@ class_name UIB_DynamicGridConstraints
|
||||
|
||||
export(int, 1, 100) var colspan := 1 setget _set_colspan
|
||||
export(int, 1, 100) var rowspan := 1 setget _set_rowspan
|
||||
export(int) var padding_top := 0 setget _set_padding_top
|
||||
export(int) var padding_bottom := 0 setget _set_padding_bottom
|
||||
export(int) var padding_left := 0 setget _set_padding_left
|
||||
export(int) var padding_right := 0 setget _set_padding_right
|
||||
|
||||
func _ready():
|
||||
#############
|
||||
# overrides #
|
||||
#############
|
||||
func _ready() -> void:
|
||||
__trigger_update()
|
||||
|
||||
func __trigger_update():
|
||||
#################
|
||||
# private stuff #
|
||||
#################
|
||||
func __trigger_update() -> void:
|
||||
var container := get_node_or_null("../..") as Container # cyclic inclusion, cannot use UIB_DynamicGridContainer
|
||||
if container != null:
|
||||
container.notification(Container.NOTIFICATION_SORT_CHILDREN)
|
||||
|
||||
func _set_colspan(value : int):
|
||||
###########
|
||||
# setters #
|
||||
###########
|
||||
func _set_colspan(value : int) -> void:
|
||||
if value != colspan:
|
||||
colspan = value
|
||||
__trigger_update()
|
||||
|
||||
func _set_rowspan(value : int):
|
||||
func _set_rowspan(value : int) -> void:
|
||||
if value != rowspan:
|
||||
rowspan = value
|
||||
__trigger_update()
|
||||
|
||||
func _set_padding_top(value : int) -> void:
|
||||
if value != padding_top:
|
||||
padding_top = value
|
||||
__trigger_update()
|
||||
|
||||
func _set_padding_bottom(value : int) -> void:
|
||||
if value != padding_bottom:
|
||||
padding_bottom = value
|
||||
__trigger_update()
|
||||
|
||||
func _set_padding_left(value : int) -> void:
|
||||
if value != padding_left:
|
||||
padding_left = value
|
||||
__trigger_update()
|
||||
|
||||
func _set_padding_right(value : int) -> void:
|
||||
if value != padding_right:
|
||||
padding_right = value
|
||||
__trigger_update()
|
||||
|
Loading…
x
Reference in New Issue
Block a user