261 lines
7.5 KiB
GDScript

extends Reference
class_name GDB_Entity
var _title := ""
var _title_property : Object = null
var _properties := [].duplicate()
var _property_ids := [].duplicate()
class _CommonWrapperProperty extends GDB_Property:
var object : WeakRef
func _init(object_ : Object, val, sig_name := "", flags := 0) -> void:
self.object = weakref(object_)
.set_type(typeof(val))
.set_value(val)
.set_flags(flags)
if sig_name != "":
object_.connect(sig_name, self, "_on_object_value_changed")
func _on_object_value_changed(p0 = null, p1 = null, p2 = null, p3 = null) -> void:
var obj : Object = self.object.get_ref()
if obj: # shouldn't actually be null, who called the handler then?
_value = obj.get(self.member)
emit_signal("value_changed")
class _WrapperProperty extends _CommonWrapperProperty:
var member : String
func _init(object_ : Object, member_ : String, sig_name : String, flags : int) \
.(object_, object_.get(member), sig_name, flags) -> void:
self.member = member_
.set_name(member_.capitalize())
func get_value():
var obj : Object = self.object.get_ref()
if obj:
return obj.get(self.member)
return .get_value()
func set_value(value) -> void:
var obj : Object = self.object.get_ref()
if obj:
obj.set(self.member, value)
.set_value(obj.get(self.member))
else:
.set_value(value)
class _ArrayWrapperProperty extends _WrapperProperty:
func _init(object_ : Object, member_ : String, sig_name_added : String, sig_name_removed : String, flags : int) \
.(object_, member_, "", flags) -> void:
if sig_name_added != "":
object_.connect(sig_name_added, self, "_on_object_value_added")
if sig_name_removed != "":
object_.connect(sig_name_added, self, "_on_object_value_removed")
func _on_object_value_added(value, p0 = null, p1 = null, p2 = null, p3 = null) -> void:
var obj : Object = self.object.get_ref()
if obj:
_value = obj.get(self.member)
emit_signal("value_changed")
emit_signal("value_added", value)
func _on_object_value_removed(value, p0 = null, p1 = null, p2 = null, p3 = null) -> void:
var obj : Object = self.object.get_ref()
if obj:
_value = obj.get(self.member)
emit_signal("value_changed")
emit_signal("value_removed", value)
class _GetSetWrapperProperty extends _CommonWrapperProperty:
var getter := ""
var setter := ""
func _init(object_ : Object, getter_ : String, setter_ := "", sig_name := "", flags := 0) \
.(object_, object.call(getter_), sig_name, flags) -> void:
self.getter = getter_
self.setter = setter_
func get_value():
var obj : Object = self.object.get_ref()
if obj:
return obj.call(self.getter)
return .get_value()
func set_value(value) -> void:
if !self.setter:
return
var obj : Object = self.object.get_ref()
if obj:
obj.call(self.setter, value)
.set_value(obj.call(self.getter))
else:
.set_value(value)
################
# public stuff #
################
func get_title() -> String:
return _title
func set_title(title : String) -> void:
if _title_property:
# title and title_property are mutually exclusive
GDBUtility.disconnect_all(_title_property, self)
_title_property = null
__set_title(title)
func set_title_property(property : Object) -> void:
if property.get_type() != TYPE_STRING:
printerr("Title property must be string.")
return
if _title_property == property:
return
if _title_property:
GDBUtility.disconnect_all(_title_property, self)
_title_property = property
var new_title := ""
if _title_property:
new_title = _title_property.get_value()
GDBUtility.try_connect(_title_property, "value_changed", self, "_on_title_property_value_changed")
__set_title(new_title)
func get_properties() -> Array:
return _properties
func get_property_ids() -> Array:
return _property_ids
func get_property(index : int) -> Object:
if index < 0 || index >= _properties.size():
return null
return _properties[index]
func get_property_id(index : int) -> String:
if index < 0 || index >= _property_ids.size():
return ""
return _property_ids[index]
func get_property_by_id(id : String) -> Object:
return get_property(find_property_by_id(id))
func add_property(id : String, property : Object, index := -1) -> void:
if !GDB_Property.is_valid_property(property):
printerr("GDB_Entity: attempted to add invalid property.")
return
if find_property(property) >= 0:
return
if find_property_by_id(id) >= 0:
printerr("GDB_Entity: duplicate property id")
return
if index < 0:
index = _properties.size()
index = min(index, _properties.size())
_properties.insert(index, property)
_property_ids.insert(index, id)
emit_signal("property_added", index)
func remove_property(property : Object) -> bool:
var index := find_property(property)
if index < 0:
return false
_properties.remove(index)
_property_ids.remove(index)
emit_signal("property_removed", index, property)
return true
func remove_property_at(index : int) -> bool:
if index < 0 || index >= _properties.size():
return false
return remove_property(_properties[index])
func find_property(property : Object) -> int:
return _properties.find(property)
func find_property_by_id(id : String) -> int:
return _property_ids.find(id)
#################
# private stuff #
#################
func __set_title(title : String) -> void:
if title != _title:
_title = title
emit_signal("entity_title_changed")
################
# static stuff #
################
static func is_valid_entity(object : Object) -> bool:
return object != null \
&& object.has_method("get_properties")
static func make_property(object : Object, member : String, sig_name := "", flags := 0) -> GDB_Property:
return _WrapperProperty.new(object, member, sig_name, flags)
static func make_getset_property(object : Object, getter : String, setter := "", sig_name := "", flags := 0) -> GDB_Property:
return _GetSetWrapperProperty.new(object, getter, setter, sig_name, flags)
static func make_array_property(object : Object, member : String, sig_name_added := "", sig_name_removed := "", array_type := TYPE_NIL, flags := 0) -> GDB_Property:
var prop := _ArrayWrapperProperty.new(object, member, sig_name_added, sig_name_removed, flags)
prop.set_content_type(array_type)
return prop
static func make_entity_title_property(entity : Object) -> Object:
var property : Object
if entity.has_method("get_title_property"):
property = entity.get_title_property()
if property:
return property
if entity.get("title") is String:
var sig_name := ""
if entity.has_signal("title_changed"):
sig_name = "title_changed"
return make_property(entity, "title", sig_name)
if entity.has_method("get_title"):
var setter := ""
var sig_name := ""
var flags := 0
if entity.has_method("set_title"):
setter = "set_title"
else:
flags |= GDB_Property.FLAG_READONLY
if entity.has_signal("title_changed"):
sig_name = "title_changed"
return make_getset_property(entity, "get_title", setter, sig_name, flags)
return null
static func get_entity_property_ids(entity : Object) -> Array:
return __get_entity_optional(entity, "property_ids", [])
#################
# private stuff #
#################
static func __get_entity_optional(entity : Object, name : String, default = null):
return GDB_Property.__get_prop_optional(entity, name, default) # why write this twice?
############
# handlers #
############
func _on_title_property_value_changed() -> void:
if !_title_property: # should exist
return
__set_title(_title_property.get_value())
###########
# signals #
###########
signal entity_title_changed()
signal property_added(index)
signal property_removed(index, property)