diff --git a/scripts/world_object.gd b/scripts/world_object.gd new file mode 100644 index 0000000..4e7dd8e --- /dev/null +++ b/scripts/world_object.gd @@ -0,0 +1,93 @@ +class_name WorldObject +extends RefCounted +## A world object (prop, interactable, spawn point, etc.) within a chunk. +## +## This is the runtime representation used by [ChunkScene] to hold object +## metadata. It mirrors [ChunkDataDecoder.WorldObjectData] but is a standalone +## class so it can be referenced by scene nodes. + +## Stable object ID, unique within the chunk. +var id: String = "" + +## Object type: "prop", "interactable", "spawn_point", "door", etc. +var type: String = "" + +## Reference to the object's mesh/glTF asset. +var asset_id: String = "" + +## World-space position. +var position: Vector3 = Vector3.ZERO + +## World-space rotation as a quaternion (x, y, z, w). +var rotation: Vector4 = Vector4(0, 0, 0, 1) + +## World-space scale. +var scale: Vector3 = Vector3.ONE + +## Type-specific key/value properties. +var properties: Dictionary = {} + +## Whether this is a spawnable dynamic entity template. +var is_dynamic: bool = false + +## Per-object content moderation flags. +var flags: ChunkDataDecoder.ContentFlags = ChunkDataDecoder.ContentFlags.new() + +## Whether this object has been modified locally. +var is_dirty: bool = false + + +func _init( + p_id: String = "", + p_type: String = "", + p_asset_id: String = "", + p_position: Vector3 = Vector3.ZERO, + p_rotation: Vector4 = Vector4(0, 0, 0, 1), + p_scale: Vector3 = Vector3.ONE, + p_properties: Dictionary = {}, + p_dynamic: bool = false, + p_flags: ChunkDataDecoder.ContentFlags = null +) -> void: + id = p_id + type = p_type + asset_id = p_asset_id + position = p_position + rotation = p_rotation + scale = p_scale + properties = p_properties + is_dynamic = p_dynamic + if p_flags != null: + flags = p_flags + + +## Convert to a dictionary representation. +func to_dict() -> Dictionary: + return { + "id": id, + "type": type, + "asset_id": asset_id, + "position": position, + "rotation": rotation, + "scale": scale, + "properties": properties, + "dynamic": is_dynamic, + "flags": flags.to_dict(), + } + + +## Create a WorldObject from a dictionary. +static func from_dict(d: Dictionary) -> WorldObject: + var flags := ChunkDataDecoder.ContentFlags.new() + if d.has("flags"): + flags.from_dict(d["flags"]) + return WorldObject.new( + d.get("id", ""), + d.get("type", ""), + d.get("asset_id", ""), + d.get("position", Vector3.ZERO), + d.get("rotation", Vector4(0, 0, 0, 1)), + d.get("scale", Vector3.ONE), + d.get("properties", {}), + d.get("dynamic", false), + flags, + )