feat(studio,stacking,animations,collections): M16 ModBison Studio, object stacking, model animations, and poly collections for MVP 2
checkpoint / checkpoint (push) Successful in 6m32s

This commit is contained in:
2026-09-22 18:30:57 +00:00
parent 654c1ec6bf
commit 721dbe5ae7
37 changed files with 5202 additions and 17 deletions
+69 -3
View File
@@ -36,6 +36,8 @@ var selection: SelectionManager
var tools: ToolRegistry
var catalog: EditorObjectCatalog = null
const PlacementStackManagerClass = preload("res://scripts/editor/placement_stack_manager.gd")
func _init(p_model: ChunkEditorModel, p_catalog: EditorObjectCatalog = null) -> void:
model = p_model
@@ -72,16 +74,80 @@ func erase_tile(layer_idx: int, x: int, y: int, z: int = 0) -> bool:
func place_object(catalog_id: String, position: Vector3,
rotation: Vector4 = Vector4(0, 0, 0, 1), scale: Vector3 = Vector3.ONE) -> String:
var result: Variant = use_tool("object_place", {
rotation: Vector4 = Vector4(0, 0, 0, 1), scale: Vector3 = Vector3.ONE,
properties: Dictionary = {}) -> String:
var args: Dictionary = {
"catalog_id": catalog_id,
"position": position,
"rotation": rotation,
"scale": scale,
})
}
if not properties.is_empty():
args["properties"] = properties
var result: Variant = use_tool("object_place", args)
return result if result is String else ""
func place_object_stacked(catalog_id: String, target_object_id: String = "",
hit_point: Vector3 = Vector3.ZERO, surface_normal: Vector3 = Vector3(0, 0, 1),
elevation_offset: float = 0.0, align_to_normal: bool = false) -> String:
var target_obj: ChunkDataDecoder.WorldObjectData = null
if target_object_id != "":
target_obj = model.find_object(target_object_id)
var stack_info: Dictionary = PlacementStackManagerClass.calculate_stack_transform(
catalog_id, target_obj, hit_point, surface_normal, elevation_offset, align_to_normal
)
var props: Dictionary = {}
if stack_info["parent_id"] != "":
props["parent_id"] = stack_info["parent_id"]
props["stacked_on"] = stack_info["parent_id"]
if elevation_offset != 0.0:
props["elevation_offset"] = elevation_offset
return place_object(catalog_id, stack_info["position"], stack_info["rotation"], Vector3.ONE, props)
func drop_object_to_surface(object_id: String) -> bool:
var obj := model.find_object(object_id)
if obj == null:
return false
var old_pos := obj.position
var old_props := obj.properties.duplicate(true)
if not PlacementStackManagerClass.drop_to_surface(model, object_id):
return false
var new_pos := obj.position
var new_props := obj.properties.duplicate(true)
undo_redo.begin("Drop '%s' to surface" % object_id)
undo_redo.add_do(func():
var target := model.find_object(object_id)
if target != null:
target.position = new_pos
target.properties = new_props
)
undo_redo.add_undo(func():
var target := model.find_object(object_id)
if target != null:
target.position = old_pos
target.properties = old_props
)
undo_redo.commit()
return true
func adjust_object_elevation(object_id: String, delta_z: float) -> bool:
var obj := model.find_object(object_id)
if obj == null:
return false
var target_pos := obj.position + Vector3(0, 0, delta_z)
target_pos.z = maxf(0.0, target_pos.z)
return move_object(object_id, target_pos)
func get_stacked_children(parent_id: String) -> Array[String]:
return PlacementStackManagerClass.get_all_children(model, parent_id)
func delete_object(object_id: String) -> bool:
return bool(use_tool("erase", {"object_id": object_id}))