Add bison model to default editor palette and object catalog
checkpoint / checkpoint (push) Successful in 6m10s

This commit is contained in:
2026-09-21 18:11:06 +00:00
parent ddcc0866b8
commit 509e85b53e
10 changed files with 251 additions and 2 deletions
+6
View File
@@ -36,6 +36,12 @@
"display_name": "Buffalo Chip Coin", "display_name": "Buffalo Chip Coin",
"category": "props" "category": "props"
}, },
"bison": {
"asset_id": "props/bison.glb",
"type": "prop",
"display_name": "Bison",
"category": "nature"
},
"spawn_point": { "spawn_point": {
"asset_id": "", "asset_id": "",
"type": "spawn_point", "type": "spawn_point",
Binary file not shown.
+42
View File
@@ -0,0 +1,42 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://wa7kf5fvrdh1"
path="res://.godot/imported/bison.glb-caef5252d8e08046747c7628b6609f07.scn"
[deps]
source_file="res://assets/props/bison.glb"
dest_files=["res://.godot/imported/bison.glb-caef5252d8e08046747c7628b6609f07.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/root_script=null
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_name_suffixes=true
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
materials/extract=0
materials/extract_format=0
materials/extract_path=""
_subresources={}
gltf/naming_version=2
gltf/embedded_image_handling=1
Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

@@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://oemjaiyc1jor"
path="res://.godot/imported/bison_04bizontexture.jpg-ee62bcbf71190dd9c3260c488d0f5226.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "62ac14285e2f49777af903582f16d021"
}
[deps]
source_file="res://assets/props/bison_04bizontexture.jpg"
dest_files=["res://.godot/imported/bison_04bizontexture.jpg-ee62bcbf71190dd9c3260c488d0f5226.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
+12 -2
View File
@@ -48,11 +48,21 @@ func is_loaded() -> bool:
func resolve(id: String) -> Dictionary: func resolve(id: String) -> Dictionary:
if not _loaded: if not _loaded:
return {} return {}
return _catalog.get(id, {}) if _catalog.has(id):
return _catalog[id]
if (id.contains("bizon") or id.contains("bison")) and _catalog.has("bison"):
return _catalog["bison"]
return {}
func has_object(id: String) -> bool: func has_object(id: String) -> bool:
return _loaded and _catalog.has(id) if not _loaded:
return false
if _catalog.has(id):
return true
if (id.contains("bizon") or id.contains("bison")) and _catalog.has("bison"):
return true
return false
func get_all_ids() -> Array[String]: func get_all_ids() -> Array[String]:
+2
View File
@@ -115,6 +115,8 @@ func _setup_import_ui() -> void:
sample_option.set_item_metadata(4, {"path": "res://assets/props/buffalo_chip_coin.glb", "name": "Buffalo Chip Coin"}) sample_option.set_item_metadata(4, {"path": "res://assets/props/buffalo_chip_coin.glb", "name": "Buffalo Chip Coin"})
sample_option.add_item("Small Crate", 5) sample_option.add_item("Small Crate", 5)
sample_option.set_item_metadata(5, {"path": "res://assets/props/crate_small.glb", "name": "Small Crate"}) sample_option.set_item_metadata(5, {"path": "res://assets/props/crate_small.glb", "name": "Small Crate"})
sample_option.add_item("Bison", 6)
sample_option.set_item_metadata(6, {"path": "res://assets/props/bison.glb", "name": "Bison"})
sample_option.size_flags_horizontal = Control.SIZE_EXPAND_FILL sample_option.size_flags_horizontal = Control.SIZE_EXPAND_FILL
sample_option.item_selected.connect(func(idx: int): sample_option.item_selected.connect(func(idx: int):
if idx > 0: if idx > 0:
+37
View File
@@ -0,0 +1,37 @@
extends SceneTree
## Test loading and instantiating bison.glb prop
func _init() -> void:
print("=== Smoke Test: Bison Model ===")
var path := "res://assets/props/bison.glb"
if not FileAccess.file_exists(path):
printerr("FAIL: bison.glb does not exist on disk at ", path)
quit(1)
return
var res := load(path)
if res == null:
printerr("FAIL: Could not load ", path)
quit(1)
return
print("PASS: Loaded PackedScene: ", res)
if res is PackedScene:
var inst = (res as PackedScene).instantiate()
if inst == null:
printerr("FAIL: Could not instantiate bison scene")
quit(1)
return
print("PASS: Instantiated bison: ", inst.name, " (", inst.get_class(), ")")
_print_node(inst, 0)
inst.queue_free()
print("=== Bison Model Smoke Test Passed ===")
quit(0)
func _print_node(n: Node, depth: int) -> void:
print(" ".repeat(depth), "- ", n.name, " [", n.get_class(), "]")
for c in n.get_children():
_print_node(c, depth + 1)
+103
View File
@@ -0,0 +1,103 @@
extends SceneTree
## Headless smoke test verifying Bison model is present in the editor palette
## and loads properly via StaticObjectNode and EditorCore.
const ChunkEditorModelClass := preload("res://scripts/editor/chunk_editor_model.gd")
const EditorObjectCatalogClass := preload("res://scripts/editor/object_catalog.gd")
const EditorCoreClass := preload("res://scripts/editor/editor_core.gd")
const PalettePanelClass := preload("res://scripts/editor/ui/palette_panel.gd")
const StaticObjectNodeClass := preload("res://scripts/static_object_node.gd")
const WorldObjectClass := preload("res://scripts/world_object.gd")
var passed := 0
var failed := 0
func _check(label: String, cond: bool) -> void:
if cond:
passed += 1
print(" PASS: ", label)
else:
failed += 1
printerr(" FAIL: ", label)
func _initialize() -> void:
await _run()
func _run() -> void:
print("=== Running Bison Model in Editor Palette Smoke Test ===")
var root := Node.new()
root.name = "TestRoot"
get_root().add_child(root)
# 1. Check catalog loading
var catalog := EditorObjectCatalogClass.new()
var err := catalog.load_catalog()
_check("Loaded EditorObjectCatalog from JSON", err == OK)
# 2. Check bison in default ids
var all_ids := catalog.get_all_ids()
_check("Catalog contains 'bison'", all_ids.has("bison"))
var bison_entry := catalog.resolve("bison")
_check("Bison entry has asset_id props/bison.glb", bison_entry.get("asset_id") == "props/bison.glb")
_check("Bison entry display_name is Bison", bison_entry.get("display_name") == "Bison")
_check("Bison asset file exists in project", FileAccess.file_exists("res://assets/props/bison.glb"))
# 3. Check alias resolution for legacy custom import id
var alias_entry := catalog.resolve("custom_bizon_by_madtrollstudio_rqk_lny_pnfx")
_check("Legacy custom id resolves to bison", alias_entry.get("asset_id") == "props/bison.glb")
# 4. Check PalettePanel populates bison in list
var palette := PalettePanelClass.new()
root.add_child(palette)
await process_frame
palette.set_catalog(catalog)
var found_in_palette := false
for i in range(palette._list.item_count):
var item_text := palette._list.get_item_text(i)
if item_text == "Bison":
found_in_palette = true
break
_check("PalettePanel list contains 'Bison'", found_in_palette)
# 5. Place bison in a chunk model
var model := ChunkEditorModelClass.new()
var core := EditorCoreClass.new(model, catalog)
var obj_id := core.place_object("bison", Vector3(10.0, 0.0, 15.0))
_check("Placed bison via EditorCore", not obj_id.is_empty())
var placed_obj := model.find_object(obj_id)
_check("Placed object has props/bison.glb", placed_obj != null and placed_obj.asset_id == "props/bison.glb")
# 6. StaticObjectNode with default props/bison.glb
var wo1 := WorldObjectClass.new()
wo1.id = "test_bison_1"
wo1.type = "prop"
wo1.asset_id = "props/bison.glb"
wo1.position = Vector3(10.0, 0.0, 15.0)
var node1 := StaticObjectNodeClass.new()
node1.world_object = wo1
root.add_child(node1)
await process_frame
_check("StaticObjectNode loaded visuals for props/bison.glb", node1.get_child_count() > 0)
# 7. StaticObjectNode with legacy user:// path as saved in World 6
var wo2 := WorldObjectClass.new()
wo2.id = "test_bison_legacy"
wo2.type = "prop"
wo2.asset_id = "user://custom_assets/Bizon by madtrollstudio - RqkLNYPnfx.glb"
wo2.properties = {"catalog_id": "custom_bizon_by_madtrollstudio_rqk_lny_pnfx"}
var node2 := StaticObjectNodeClass.new()
node2.world_object = wo2
root.add_child(node2)
await process_frame
_check("StaticObjectNode loaded visuals for legacy world chunk bison", node2.get_child_count() > 0)
print("Bison Palette Smoke Test complete. Passed: %d, Failed: %d" % [passed, failed])
if failed > 0:
quit(1)
else:
quit(0)
+6
View File
@@ -61,6 +61,8 @@ func _load_mesh() -> void:
add_child(asset_node) add_child(asset_node)
if asset_node is MeshInstance3D: if asset_node is MeshInstance3D:
_mesh_instance = asset_node as MeshInstance3D _mesh_instance = asset_node as MeshInstance3D
else:
_mesh_instance = asset_node.find_child("*", true, false) as MeshInstance3D
return return
# 2. Build a stylized, recognizable 3D representation based on catalog ID / asset ID # 2. Build a stylized, recognizable 3D representation based on catalog ID / asset ID
@@ -96,9 +98,13 @@ func _try_load_asset(asset_id: String) -> Node:
var candidate_paths: Array[String] = [ var candidate_paths: Array[String] = [
asset_id, asset_id,
"res://assets/%s" % asset_id, "res://assets/%s" % asset_id,
"res://assets/props/%s" % asset_id.get_file(),
"user://custom_assets/%s" % asset_id, "user://custom_assets/%s" % asset_id,
"user://custom_assets/%s" % asset_id.get_file() "user://custom_assets/%s" % asset_id.get_file()
] ]
var lower_id := asset_id.to_lower()
if lower_id.contains("bizon") or lower_id.contains("bison") or lower_id.contains("madtrollstudio"):
candidate_paths.append("res://assets/props/bison.glb")
for cpath in candidate_paths: for cpath in candidate_paths:
if FileAccess.file_exists(cpath): if FileAccess.file_exists(cpath):