LODs are child collections of the asset collection (COL_{asset}_LOD{n}).
Overrides hide the other LOD collections (viewport and render), keeping
the rig, pose and animation; collection instances instance the LOD
collection. Each instance has its own LOD, set per instance or for the
selection in the Loaded panel, kept through save, reload and updates.
Loading shows SCENE_MANAGER_DEFAULT_LOD (0).
The Shot Viewer panel is now "Shot Manager" and starts closed. Code
names and SHOT_VIEWER_* config keys are unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
3.2 KiB
Python
71 lines
3.2 KiB
Python
"""Write the asset files used by fake_libreflow.py into <workdir>/lib.
|
|
|
|
blender -b --factory-startup --python dev/make_test_assets.py -- <workdir>
|
|
|
|
bob: a rig (COL_bob: armature + meshes), v001 has 1 mesh, v002 has 2.
|
|
tree: COL_tree holding only LOD collections (COL_tree_LOD0, COL_tree_LOD1), plus an
|
|
unrelated top-level collection. v002 adds a mesh outside the LODs, v003 has no LOD.
|
|
car: a rig, COL_car: armature + COL_car_LOD0..2.
|
|
rock: a single top-level collection not named after the asset (fallback case), its mesh
|
|
using a node group linked from Blender's essentials (an indirect library).
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
|
|
import bpy
|
|
|
|
WORKDIR = sys.argv[sys.argv.index("--") + 1]
|
|
|
|
|
|
def mesh_object(name):
|
|
mesh = bpy.data.meshes.new(name)
|
|
mesh.from_pydata([(0, 0, 0), (1, 0, 0), (0, 1, 0)], [], [(0, 1, 2)])
|
|
return bpy.data.objects.new(name, mesh)
|
|
|
|
|
|
def write(path, collection_name, meshes=1, rig=False, extra=False, node_group=False, lods=0):
|
|
bpy.ops.wm.read_homefile(use_empty=True)
|
|
scene = bpy.context.scene
|
|
collection = bpy.data.collections.new(collection_name)
|
|
scene.collection.children.link(collection)
|
|
parent = None
|
|
if rig:
|
|
parent = bpy.data.objects.new("RIG_" + collection_name, bpy.data.armatures.new("RIG_" + collection_name))
|
|
collection.objects.link(parent)
|
|
bpy.context.view_layer.objects.active = parent
|
|
bpy.ops.object.mode_set(mode="EDIT")
|
|
bone = parent.data.edit_bones.new("root")
|
|
bone.tail = (0, 0, 1)
|
|
bpy.ops.object.mode_set(mode="OBJECT")
|
|
for index in range(meshes):
|
|
ob = mesh_object(f"GEO_{collection_name}_{index}")
|
|
ob.parent = parent
|
|
collection.objects.link(ob)
|
|
for lod in range(lods):
|
|
lod_collection = bpy.data.collections.new(f"{collection_name}_LOD{lod}")
|
|
collection.children.link(lod_collection)
|
|
ob = mesh_object(f"GEO_{collection_name}_LOD{lod}")
|
|
ob.parent = parent
|
|
lod_collection.objects.link(ob)
|
|
if node_group:
|
|
essentials = os.path.join(bpy.utils.system_resource("DATAFILES"), "assets", "nodes", "geometry_nodes_essentials.blend")
|
|
with bpy.data.libraries.load(essentials, link=True) as (_data_from, data_to):
|
|
data_to.node_groups = ["Smooth by Angle"]
|
|
ob.modifiers.new("Smooth", "NODES").node_group = data_to.node_groups[0]
|
|
if extra:
|
|
scene.collection.children.link(bpy.data.collections.new("WIP_other"))
|
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
bpy.ops.wm.save_as_mainfile(filepath=path)
|
|
|
|
|
|
lib = os.path.join(WORKDIR, "lib")
|
|
write(os.path.join(lib, "bob", "v001", "rig.blend"), "COL_bob", meshes=1, rig=True, extra=True)
|
|
write(os.path.join(lib, "bob", "v002", "rig.blend"), "COL_bob", meshes=2, rig=True, extra=True)
|
|
write(os.path.join(lib, "tree", "v001", "model.blend"), "COL_tree", meshes=0, extra=True, lods=2)
|
|
write(os.path.join(lib, "tree", "v002", "model.blend"), "COL_tree", meshes=1, extra=True, lods=2)
|
|
write(os.path.join(lib, "tree", "v003", "model.blend"), "COL_tree", meshes=1, extra=True)
|
|
write(os.path.join(lib, "rock", "v001", "rock.blend"), "rock_geo", node_group=True)
|
|
write(os.path.join(lib, "car", "v001", "car.blend"), "COL_car", meshes=0, rig=True, lods=3)
|
|
print("Test assets written in", lib)
|