Pipeline update

This commit is contained in:
2026-05-10 14:43:57 +03:00
parent 333a0b9938
commit ce888bc5bb
9 changed files with 552 additions and 23 deletions
@@ -354,7 +354,11 @@ class OgreMaterialGenerator(object):
else:
image_filepath = bpy.path.abspath(image.filepath, library=image.library)
image_filepath = os.path.normpath(image_filepath)
if not os.path.isfile(image_filepath):
logger.warning("Skipping texture copy: source path is not a file (%s)", image_filepath)
return
# Should we update the file
update = False
if os.path.isfile(target_filepath):
+78 -13
View File
@@ -186,26 +186,32 @@ def extra_linear(angle, offset):
mapping_blend_path = argv[0]
mapping_gltf_path = argv[1]
mapping_objects = argv[2]
mapping_armature_name = argv[3]
mapping_outfile = argv[4]
# Backward compat: support both 4-arg (blend, gltf, armature, outfile) and 5-arg (blend, gltf, objects, armature, outfile)
if len(argv) >= 5:
mapping_objects = argv[2]
mapping_armature_name = argv[3]
mapping_outfile = argv[4]
else:
mapping_objects = "AUTO"
mapping_armature_name = argv[2]
mapping_outfile = argv[3]
#for mapping in [ExportMappingFemale(), ExportMappingMale(), ExportMappingMaleBabyShape(), ExportMappingMaleEdited(), ExportMappingFemaleEdited(), ExportMappingMaleTestShapeEdited(), ExportMappingMaleBaseShapeEdited()]:
class CommandLineMapping:
blend_path = mapping_blend_path
gltf_path = mapping_gltf_path
# ogre_scene = "characters/female/vroid-normal-female.scene"
inner_path = "Object"
# objs = ["male", "Body", "Hair", "Face", "BackHair", "Tops", "Bottoms", "Shoes", "Accessory"]
# objs = ["female", "Body", "Hair", "Face", "BackHair", "Tops", "Bottoms", "Shoes", "Accessory"]
objs = []
armature_name = mapping_armature_name
outfile = mapping_outfile
default_action = 'default'
auto_discover = False
def __init__(self):
self.objs = [mapping_armature_name]
if len(mapping_objects) > 0:
if len(mapping_objects) > 0 and mapping_objects != "AUTO":
self.objs += [o.strip() for o in mapping_objects.split(";")]
else:
self.auto_discover = True
self.files = []
for fobj in self.objs:
self.files.append({"name": fobj})
@@ -224,11 +230,30 @@ for mapping in[CommandLineMapping()]:
bpy.app.driver_namespace["angle_to_linear_x"] = angle_to_linear_x
print("Driver setup done...")
bpy.ops.wm.append(
filepath=os.path.join(mapping.blend_path, mapping.inner_path),
directory=os.path.join(mapping.blend_path, mapping.inner_path),
files=mapping.files)
print("Append done...")
if mapping.auto_discover:
# Load all objects from the blend file so we can discover meshes by custom props
with bpy.data.libraries.load(mapping.blend_path) as (data_from, data_to):
data_to.objects = data_from.objects
for obj in data_to.objects:
if obj is not None:
try:
bpy.context.collection.objects.link(obj)
except RuntimeError:
pass # Already linked
print("Library load done...")
discovered = []
for ob in bpy.data.objects:
if ob.type == 'MESH' and all(p in ob.keys() for p in ["age", "sex", "slot"]):
discovered.append(ob.name)
mapping.objs += discovered
print(f"Auto-discovered {len(discovered)} body part objects: {discovered}")
else:
bpy.ops.wm.append(
filepath=os.path.join(mapping.blend_path, mapping.inner_path),
directory=os.path.join(mapping.blend_path, mapping.inner_path),
files=mapping.files)
print("Append done...")
prepare_armature(mapping)
print("Armature done...")
@@ -239,6 +264,10 @@ for mapping in[CommandLineMapping()]:
bpy.data.objects.remove(ob)
elif ob.name.startswith("Face") and ob.name != "Face":
bpy.data.objects.remove(ob)
# Remove auto-discovered objects that weren't meant for export
elif mapping.auto_discover and ob.type == 'MESH' and ob.name not in mapping.objs:
if not ob.name.endswith("-noimp"):
ob.name = ob.name + "-noimp"
print("Removing original armature and actions...")
orig_arm = bpy.data.objects[mapping.armature_name + '_orig']
@@ -317,12 +346,48 @@ for mapping in[CommandLineMapping()]:
save_data[key] = obj[key]
if key.startswith("body_"):
save_data[key.replace("body_", "", 1)] = obj[key]
# Export aggregated clothing metadata
if "layer" in obj:
save_data["layer"] = int(obj["layer"])
else:
save_data["layer"] = 0
tags = []
if "garments" in obj and obj["garments"]:
garments = [g.strip() for g in str(obj["garments"]).split(";") if g.strip()]
save_data["garments"] = garments
tags.extend(garments)
else:
save_data["garments"] = []
if "clothing_tags" in obj and obj["clothing_tags"]:
clothing_tags = [t.strip() for t in str(obj["clothing_tags"]).split(";") if t.strip()]
tags.extend(clothing_tags)
# Deduplicate and sort
seen = set()
unique_tags = []
for t in tags:
t_lower = t.lower()
if t_lower not in seen:
seen.add(t_lower)
unique_tags.append(t)
save_data["tags"] = unique_tags
# Export shape keys if present
shape_keys = []
if obj.data.shape_keys and obj.data.shape_keys.key_blocks:
for sk in obj.data.shape_keys.key_blocks:
shape_keys.append(sk.name)
save_data["shape_keys"] = shape_keys
save_data["mesh"] = obj.data.name + ".mesh"
json_dir = os.path.dirname(mapping.gltf_path)
save_file = json_dir + "/body_part_" + obj.data.name + ".json"
json_filepath = os.path.join(json_dir, save_file)
with open(json_filepath, 'w') as f:
json.dump(save_data, f)
json.dump(save_data, f, indent=2)
armobj = bpy.data.objects.get(mapping.armature_name)
armobj.data.name = armobj.name