class_name WorldTargetDescriptor extends RefCounted var _target_id: StringName var _target_kind: StringName var _display_name: String var _local_position: Vector3 var _metadata: Dictionary var _capabilities_by_id: Dictionary = {} var _capability_ids: Array[StringName] = [] var _is_valid := false func _init( target_id: StringName = &"", target_kind: StringName = &"", capabilities: Array = [], local_position: Vector3 = Vector3.ZERO, display_name: String = "", metadata: Dictionary = {} ) -> void: _target_id = target_id _target_kind = target_kind _display_name = display_name _local_position = local_position _metadata = metadata.duplicate(true) _is_valid = ( not _target_id.is_empty() and not _target_kind.is_empty() and _local_position.is_finite() and not WorldTargetCapability._contains_object(_metadata) ) for value in capabilities: var capability := value as WorldTargetCapability if ( capability == null or not capability.is_valid() or _capabilities_by_id.has(capability.get_capability_id()) ): _is_valid = false continue var isolated_capability := capability.copy() _capabilities_by_id[isolated_capability.get_capability_id()] = isolated_capability _capability_ids.append(isolated_capability.get_capability_id()) _capability_ids.sort_custom(_id_less) func is_valid() -> bool: return _is_valid func get_target_id() -> StringName: return _target_id func get_target_kind() -> StringName: return _target_kind func get_display_name() -> String: return _display_name func get_local_position() -> Vector3: return _local_position func get_metadata() -> Dictionary: return _metadata.duplicate(true) func get_metadata_value(metadata_id: StringName, default_value: Variant = null) -> Variant: var value: Variant = _metadata.get(String(metadata_id), default_value) return value.duplicate(true) if value is Array or value is Dictionary else value func has_capability(capability_id: StringName) -> bool: return _capabilities_by_id.has(capability_id) func get_capability(capability_id: StringName) -> WorldTargetCapability: var capability := _capabilities_by_id.get(capability_id) as WorldTargetCapability return capability.copy() if capability != null else null func get_capability_ids() -> Array[StringName]: return _capability_ids.duplicate() func get_capabilities() -> Array[WorldTargetCapability]: var capabilities: Array[WorldTargetCapability] = [] for capability_id in _capability_ids: capabilities.append((_capabilities_by_id[capability_id] as WorldTargetCapability).copy()) return capabilities func copy() -> WorldTargetDescriptor: return WorldTargetDescriptor.new( _target_id, _target_kind, get_capabilities(), _local_position, _display_name, _metadata ) func with_local_position(next_position: Vector3) -> WorldTargetDescriptor: return WorldTargetDescriptor.new( _target_id, _target_kind, get_capabilities(), next_position, _display_name, _metadata ) func to_dictionary() -> Dictionary: var capabilities: Array[Dictionary] = [] for capability_id in _capability_ids: capabilities.append( (_capabilities_by_id[capability_id] as WorldTargetCapability).to_dictionary() ) return { "target_id": String(_target_id), "target_kind": String(_target_kind), "display_name": _display_name, "local_position": [_local_position.x, _local_position.y, _local_position.z], "metadata": _metadata.duplicate(true), "capabilities": capabilities, } static func _id_less(first: StringName, second: StringName) -> bool: return String(first) < String(second)