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)