Skip to content

Commit

Permalink
fix: vrm 0.0 bone child object translation importing
Browse files Browse the repository at this point in the history
  • Loading branch information
saturday06 committed Jun 6, 2024
1 parent eb9ffc5 commit a0317af
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 76 deletions.
92 changes: 31 additions & 61 deletions src/io_scene_vrm/importer/abstract_base_vrm_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,29 +122,6 @@ def armature_data(self) -> Armature:
raise TypeError(message)
return armature_data

def save_bone_child_object_world_matrices(self, armature: Object) -> None:
for obj in self.context.blend_data.objects:
if (
obj.parent_type == "BONE"
and obj.parent == armature
and obj.parent_bone in self.armature_data.bones
):
self.bone_child_object_world_matrices[obj.name] = (
obj.matrix_world.copy()
)

def load_bone_child_object_world_matrices(self, armature: Object) -> None:
for obj in self.context.blend_data.objects:
if (
obj.parent_type == "BONE"
and obj.parent == armature
and obj.parent_bone in self.armature_data.bones
and obj.name in self.bone_child_object_world_matrices
):
obj.matrix_world = self.bone_child_object_world_matrices[
obj.name
].copy()

@staticmethod
@contextlib.contextmanager
def save_bone_child_object_transforms(
Expand Down Expand Up @@ -180,6 +157,7 @@ def save_bone_child_object_transforms(
and restore_obj.parent_bone in armature.data.bones
):
restore_obj.matrix_world = matrix_world.copy()
context.view_layer.update()

def use_fake_user_for_thumbnail(self) -> None:
# サムネイルはVRMの仕様ではimageのインデックスとあるが、UniVRMの実装ではtexture
Expand Down Expand Up @@ -982,48 +960,40 @@ def import_gltf2_with_indices(self) -> None:
vrm1_humanoid.human_bones.initial_automatic_bone_assignment = False
self.armature = obj

if self.armature is not None and self.parse_result.spec_version_number < (1, 0):
obj = self.armature
if obj.rotation_mode != "QUATERNION":
obj.rotation_mode = "QUATERNION"
obj.rotation_quaternion.rotate(mathutils.Euler((0.0, 0.0, math.pi), "XYZ"))
if self.context.object is not None:
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.select_all(action="DESELECT")
obj.select_set(True)
previous_active = self.context.view_layer.objects.active
try:
self.context.view_layer.objects.active = obj

bone_name_to_roll = {}
bpy.ops.object.mode_set(mode="EDIT")
if isinstance(obj.data, Armature):
for edit_bone in obj.data.edit_bones:
bone_name_to_roll[edit_bone.name] = edit_bone.roll
bpy.ops.object.mode_set(mode="OBJECT")

if (
(armature := self.armature) is not None
and isinstance(armature.data, Armature)
and self.parse_result.spec_version_number < (1, 0)
):
bone_name_to_roll = {}
with save_workspace(self.context, armature, mode="EDIT"):
for edit_bone in armature.data.edit_bones:
bone_name_to_roll[edit_bone.name] = edit_bone.roll

with save_workspace(self.context, armature):
if armature.rotation_mode != "QUATERNION":
armature.rotation_mode = "QUATERNION"
armature.rotation_quaternion.rotate(
mathutils.Euler((0.0, 0.0, math.pi), "XYZ")
)
bpy.ops.object.select_all(action="DESELECT")
armature.select_set(True)
bpy.ops.object.transform_apply(
location=False, rotation=True, scale=False, properties=False
)

self.save_bone_child_object_world_matrices(obj)

bpy.ops.object.mode_set(mode="EDIT")
if isinstance(obj.data, Armature):
edit_bones = [
edit_bone
for edit_bone in obj.data.edit_bones
if not edit_bone.parent
]
while edit_bones:
edit_bone = edit_bones.pop(0)
roll = bone_name_to_roll.get(edit_bone.name)
if roll is not None:
edit_bone.roll = roll
edit_bones.extend(edit_bone.children)
bpy.ops.object.mode_set(mode="OBJECT")
finally:
self.context.view_layer.objects.active = previous_active
with self.save_bone_child_object_transforms(self.context, armature):
edit_bones = [
edit_bone
for edit_bone in armature.data.edit_bones
if not edit_bone.parent
]
while edit_bones:
edit_bone = edit_bones.pop(0)
roll = bone_name_to_roll.get(edit_bone.name)
if roll is not None:
edit_bone.roll = roll
edit_bones.extend(edit_bone.children)

extras_mesh_index_key = self.import_id + "Meshes"
for obj in self.context.selectable_objects:
Expand Down
16 changes: 1 addition & 15 deletions src/io_scene_vrm/importer/vrm0/vrm_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import uuid
from typing import Optional, Union

import bpy
from bpy.types import (
Material,
Mesh,
Expand Down Expand Up @@ -1022,10 +1021,7 @@ def setup_vrm0_humanoid_bones(self) -> None:
# has error
return

previous_active = self.context.view_layer.objects.active
try:
self.context.view_layer.objects.active = armature

with self.save_bone_child_object_transforms(self.context, armature):
bone_name_to_human_bone_name: dict[str, HumanBoneName] = {}
for human_bone in human_bones:
if not human_bone.node.bone_name:
Expand All @@ -1035,8 +1031,6 @@ def setup_vrm0_humanoid_bones(self) -> None:
continue
bone_name_to_human_bone_name[human_bone.node.bone_name] = name

bpy.ops.object.mode_set(mode="EDIT")

for bone_name in bone_name_to_human_bone_name:
bone = self.armature_data.edit_bones.get(bone_name)
while bone:
Expand Down Expand Up @@ -1150,14 +1144,6 @@ def setup_vrm0_humanoid_bones(self) -> None:
connect_parent_tail_and_child_head_if_very_close_position(
self.armature_data
)
bpy.ops.object.mode_set(mode="OBJECT")
finally:
active = self.context.view_layer.objects.active
if active and active.mode != "OBJECT":
bpy.ops.object.mode_set(mode="OBJECT")
self.context.view_layer.objects.active = previous_active

self.load_bone_child_object_world_matrices(armature)

def find_vrm0_bone_node_indices(self) -> list[int]:
result: list[int] = []
Expand Down

0 comments on commit a0317af

Please sign in to comment.