69 lines
1.7 KiB
GDScript
69 lines
1.7 KiB
GDScript
class_name DynamicObjectNode
|
|
extends Node3D
|
|
## A visual representation of a dynamic (spawnable) world object template.
|
|
##
|
|
## This node is instantiated by [ChunkScene] for each dynamic [WorldObject].
|
|
## Dynamic objects are stored as *templates* in the chunk; their runtime state
|
|
## (position, health, inventory) is managed by the entity system, not by this
|
|
## node. This node renders the template's visual representation so the object
|
|
## is visible in the world.
|
|
##
|
|
## ## Structure
|
|
##
|
|
## ```
|
|
## DynamicObjectNode (Node3D)
|
|
## └── MeshInstance3D # the object's visual mesh
|
|
## ```
|
|
|
|
## The world object data this node represents.
|
|
var world_object: WorldObject = null
|
|
|
|
## The loaded mesh instance (or placeholder).
|
|
var _mesh_instance: MeshInstance3D = null
|
|
|
|
|
|
func _ready() -> void:
|
|
if world_object == null:
|
|
return
|
|
_load_mesh()
|
|
|
|
|
|
## Load and attach the object's mesh.
|
|
func _load_mesh() -> void:
|
|
_mesh_instance = MeshInstance3D.new()
|
|
_mesh_instance.name = "mesh"
|
|
|
|
var mesh := _load_asset_mesh(world_object.asset_id)
|
|
if mesh == null:
|
|
mesh = _make_placeholder_mesh()
|
|
|
|
_mesh_instance.mesh = mesh
|
|
add_child(_mesh_instance)
|
|
|
|
|
|
## Attempt to load a mesh from the asset path.
|
|
func _load_asset_mesh(asset_id: String) -> Mesh:
|
|
if asset_id.is_empty():
|
|
return null
|
|
var path := "res://assets/%s" % asset_id
|
|
if ResourceLoader.exists(path):
|
|
var res := load(path)
|
|
if res is Mesh:
|
|
return res
|
|
return null
|
|
|
|
|
|
## Create a simple placeholder sphere mesh when the real asset is unavailable.
|
|
func _make_placeholder_mesh() -> Mesh:
|
|
var mesh := SphereMesh.new()
|
|
mesh.radius = 0.5
|
|
mesh.height = 1.0
|
|
return mesh
|
|
|
|
|
|
## Get the world object's display name.
|
|
func get_display_name() -> String:
|
|
if world_object == null:
|
|
return ""
|
|
return world_object.get_display_name()
|