Skip to content

Commit

Permalink
Remove bone_groups
Browse files Browse the repository at this point in the history
  • Loading branch information
UuuNyaa committed Apr 23, 2024
1 parent c2160f0 commit 6a44a5a
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 84 deletions.
61 changes: 54 additions & 7 deletions mmd_tools/core/bone.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
# This file is part of MMD Tools.

import math
from typing import Iterable, Optional
from typing import TYPE_CHECKING, Iterable, Optional, Set

import bpy
from mathutils import Vector

from mmd_tools import bpyutils
from mmd_tools.bpyutils import TransformConstraintOp
import mmd_tools.utils

if TYPE_CHECKING:
from mmd_tools.properties.root import MMDRoot, MMDDisplayItemFrame
from mmd_tools.properties.pose_bone import MMDBone


def remove_constraint(constraints, name):
Expand Down Expand Up @@ -74,7 +79,7 @@ def __get_selected_pose_bones(armature_object: bpy.types.Object) -> Iterable[bpy
@staticmethod
def load_bone_fixed_axis(armature_object: bpy.types.Object, enable=True):
for b in FnBone.__get_selected_pose_bones(armature_object):
mmd_bone = b.mmd_bone
mmd_bone: MMDBone = b.mmd_bone
mmd_bone.enabled_fixed_axis = enable
lock_rotation = b.lock_rotation[:]
if enable:
Expand Down Expand Up @@ -143,14 +148,14 @@ def __unassign_mmd_tools_bone_collections(edit_bone: bpy.types.EditBone) -> bpy.
return edit_bone

@staticmethod
def sync_bone_collections_from_armature(armature_object: bpy.types.Object):
def sync_bone_collections_from_display_item_frames(armature_object: bpy.types.Object):
armature: bpy.types.Armature = armature_object.data
bone_collections = armature.collections

from mmd_tools.core.model import FnModel

root_object: bpy.types.Object = FnModel.find_root_object(armature_object)
mmd_root = root_object.mmd_root
mmd_root: MMDRoot = root_object.mmd_root

bones = armature.bones
used_groups = set()
Expand Down Expand Up @@ -186,13 +191,55 @@ def sync_bone_collections_from_armature(armature_object: bpy.types.Object):
continue
bone_collections.remove(bone_collection)

@staticmethod
def sync_display_item_frames_from_bone_collections(armature_object: bpy.types.Object):
armature: bpy.types.Armature = armature_object.data
bone_collections: bpy.types.BoneCollections = armature.collections

from mmd_tools.core.model import FnModel

root_object: bpy.types.Object = FnModel.find_root_object(armature_object)
mmd_root: MMDRoot = root_object.mmd_root
display_item_frames = mmd_root.display_item_frames

used_frame_index: Set[int] = set()

bone_collection: bpy.types.BoneCollection
for bone_collection in bone_collections:
if len(bone_collection.bones) == 0 or FnBone.__is_special_bone_collection(bone_collection):
continue

bone_collection_name = bone_collection.name
display_item_frame: Optional[MMDDisplayItemFrame] = display_item_frames.get(bone_collection_name)
if display_item_frame is None:
display_item_frame = display_item_frames.add()
display_item_frame.name = bone_collection_name
display_item_frame.name_e = bone_collection_name
used_frame_index.add(display_item_frames.find(bone_collection_name))

mmd_tools.utils.ItemOp.resize(display_item_frame.data, len(bone_collection.bones))
for display_item, bone in zip(display_item_frame.data, bone_collection.bones):
display_item.type = "BONE"
display_item.name = bone.name

for i in reversed(range(len(display_item_frames))):
if i in used_frame_index:
continue
display_item_frame = display_item_frames[i]
if display_item_frame.is_special:
if display_item_frame.name != "表情":
display_item_frame.data.clear()
else:
display_item_frames.remove(i)
mmd_root.active_display_item_frame = 0

@staticmethod
def apply_bone_fixed_axis(armature_object: bpy.types.Object):
bone_map = {}
for b in armature_object.pose.bones:
if b.is_mmd_shadow_bone or not b.mmd_bone.enabled_fixed_axis:
continue
mmd_bone = b.mmd_bone
mmd_bone: MMDBone = b.mmd_bone
parent_tip = b.parent and not b.parent.is_mmd_shadow_bone and b.parent.mmd_bone.is_tip
bone_map[b.name] = (mmd_bone.fixed_axis.normalized(), mmd_bone.is_tip, parent_tip)

Expand Down Expand Up @@ -238,7 +285,7 @@ def apply_bone_fixed_axis(armature_object: bpy.types.Object):
@staticmethod
def load_bone_local_axes(armature_object: bpy.types.Object, enable=True):
for b in FnBone.__get_selected_pose_bones(armature_object):
mmd_bone = b.mmd_bone
mmd_bone: MMDBone = b.mmd_bone
mmd_bone.enabled_local_axes = enable
if enable:
axes = b.bone.matrix_local.to_3x3().transposed()
Expand All @@ -251,7 +298,7 @@ def apply_bone_local_axes(armature_object: bpy.types.Object):
for b in armature_object.pose.bones:
if b.is_mmd_shadow_bone or not b.mmd_bone.enabled_local_axes:
continue
mmd_bone = b.mmd_bone
mmd_bone: MMDBone = b.mmd_bone
bone_map[b.name] = (mmd_bone.local_axis_x, mmd_bone.local_axis_z)

with bpyutils.edit_object(armature_object) as data:
Expand Down
2 changes: 1 addition & 1 deletion mmd_tools/core/pmx/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ def __importDisplayFrames(self):
else:
raise Exception("Unknown display item type.")

DisplayItemQuickSetup.apply_bone_groups(root.mmd_root, self.__armObj)
FnBone.sync_bone_collections_from_display_item_frames(self.__armObj)

def __addArmatureModifier(self, meshObj, armObj):
# TODO: move to model.py
Expand Down
50 changes: 4 additions & 46 deletions mmd_tools/operators/display_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ class DisplayItemQuickSetup(Operator):
items=[
("RESET", "Reset", "Clear all items and frames, reset to default", "X", 0),
("FACIAL", "Load Facial Items", "Load all morphs to faical frame", "SHAPEKEY_DATA", 1),
("GROUP_LOAD", "Load Bone Groups", "Load armature's bone groups to display item frames", "GROUP_BONE", 2),
("GROUP_APPLY", "Apply Bone Groups", "Apply display item frames to armature's bone groups", "GROUP_BONE", 3),
("GROUP_LOAD", "Sync from Bone Collections", "Sync armature's bone collections to display item frames", "GROUP_BONE", 2),
("GROUP_APPLY", "Sync to Bone Collections", "Sync display item frames to armature's bone collections", "GROUP_BONE", 3),
],
default="FACIAL",
)
Expand All @@ -274,10 +274,10 @@ def execute(self, context):
rig.initialDisplayFrames(reset=False) # ensure default frames
self.load_facial_items(root.mmd_root)
elif self.type == "GROUP_LOAD":
self.load_bone_groups(root.mmd_root, rig.armature())
FnBone.sync_display_item_frames_from_bone_collections(rig.armature())
rig.initialDisplayFrames(reset=False) # ensure default frames
elif self.type == "GROUP_APPLY":
self.apply_bone_groups(root.mmd_root, rig.armature())
FnBone.sync_bone_collections_from_display_item_frames(rig.armature())
return {"FINISHED"}

@staticmethod
Expand All @@ -303,45 +303,3 @@ def load_facial_items(mmd_root):
item.type = "MORPH"
item.morph_type, item.name = data
frame.active_item = 0

@staticmethod
def load_bone_groups(mmd_root, armature):
bone_groups = OrderedDict((i.name, []) for i in armature.pose.bone_groups)
for b in armature.pose.bones:
if b.bone_group:
bone_groups[b.bone_group.name].append(b.name)

frames = mmd_root.display_item_frames
used_index = set()
for group_name, bone_names in bone_groups.items():
if len(bone_names) < 1: # skip empty group
continue

frame = frames.get(group_name)
if frame is None:
frame = frames.add()
frame.name = group_name
frame.name_e = group_name
used_index.add(frames.find(group_name))

items = frame.data
ItemOp.resize(items, len(bone_names))
for item, name in zip(items, bone_names):
item.type = "BONE"
item.name = name
frame.active_item = 0

# remove unused frames
for i in reversed(range(len(frames))):
if i not in used_index:
frame = frames[i]
if frame.is_special:
if frame.name != "表情":
frame.data.clear()
else:
frames.remove(i)
mmd_root.active_display_item_frame = 0

@staticmethod
def apply_bone_groups(mmd_root, armature):
FnBone.sync_bone_collections_from_armature(armature)
67 changes: 37 additions & 30 deletions mmd_tools/operators/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@
# Copyright 2014 MMD Tools authors
# This file is part of MMD Tools.

from typing import TYPE_CHECKING, cast

import bpy
from bpy.types import Operator

import mmd_tools.core.model as mmd_model
from mmd_tools.bpyutils import SceneOp, activate_layer_collection
from mmd_tools.core.bone import FnBone, MigrationFnBone
from mmd_tools.core.model import FnModel, Model

if TYPE_CHECKING:
from mmd_tools.properties.root import MMDRoot


class MorphSliderSetup(Operator):
Expand All @@ -29,10 +34,10 @@ class MorphSliderSetup(Operator):

def execute(self, context):
obj = context.active_object
root = mmd_model.Model.findRoot(context.active_object)
root = FnModel.find_root_object(context.active_object)

with activate_layer_collection(root):
rig = mmd_model.Model(root)
rig = Model(root)
if self.type == "BIND":
rig.morph_slider.bind()
elif self.type == "UNBIND":
Expand All @@ -51,8 +56,8 @@ class CleanRiggingObjects(Operator):
bl_options = {"REGISTER", "UNDO", "INTERNAL"}

def execute(self, context):
root = mmd_model.Model.findRoot(context.active_object)
rig = mmd_model.Model(root)
root = FnModel.find_root_object(context.active_object)
rig = Model(root)
rig.clean()
SceneOp(context).active_object = root
return {"FINISHED"}
Expand Down Expand Up @@ -82,10 +87,10 @@ class BuildRig(Operator):
)

def execute(self, context):
root = mmd_model.Model.findRoot(context.active_object)
root = FnModel.find_root_object(context.active_object)

with activate_layer_collection(root):
rig = mmd_model.Model(root)
rig = Model(root)
rig.build(self.non_collision_distance_scale, self.collision_margin)
SceneOp(context).active_object = root

Expand All @@ -100,8 +105,8 @@ class CleanAdditionalTransformConstraints(Operator):

def execute(self, context):
obj = context.active_object
root = mmd_model.Model.findRoot(obj)
rig = mmd_model.Model(root)
root = FnModel.find_root_object(obj)
rig = Model(root)
FnBone.clean_additional_transformation(rig.armature())
SceneOp(context).active_object = obj
return {"FINISHED"}
Expand All @@ -115,8 +120,8 @@ class ApplyAdditionalTransformConstraints(Operator):

def execute(self, context):
obj = context.active_object
root = mmd_model.Model.findRoot(obj)
rig = mmd_model.Model(root)
root = FnModel.find_root_object(obj)
rig = Model(root)
MigrationFnBone.fix_mmd_ik_limit_override(rig.armature())
FnBone.apply_additional_transformation(rig.armature())

Expand Down Expand Up @@ -200,17 +205,18 @@ class AddMissingVertexGroupsFromBones(Operator):

@classmethod
def poll(cls, context: bpy.types.Context):
return mmd_model.FnModel.find_root_object(context.active_object) is not None
return FnModel.find_root_object(context.active_object) is not None

def execute(self, context: bpy.types.Context):
active_object: bpy.types.Object = context.active_object
root_object = mmd_model.FnModel.find_root_object(active_object)
root_object = FnModel.find_root_object(active_object)
assert root_object is not None

bone_order_mesh_object = mmd_model.FnModel.find_bone_order_mesh_object(root_object)
bone_order_mesh_object = FnModel.find_bone_order_mesh_object(root_object)
if bone_order_mesh_object is None:
return {"CANCELLED"}

mmd_model.FnModel.add_missing_vertex_groups_from_bones(root_object, bone_order_mesh_object, self.search_in_all_meshes)
FnModel.add_missing_vertex_groups_from_bones(root_object, bone_order_mesh_object, self.search_in_all_meshes)

return {"FINISHED"}

Expand Down Expand Up @@ -238,7 +244,7 @@ class CreateMMDModelRoot(Operator):
)

def execute(self, context):
rig = mmd_model.Model.create(self.name_j, self.name_e, self.scale, add_root_bone=True)
rig = Model.create(self.name_j, self.name_e, self.scale, add_root_bone=True)
rig.initialDisplayFrames()
return {"FINISHED"}

Expand Down Expand Up @@ -310,12 +316,12 @@ def execute(self, context):
scale = self.scale
model_name = "New MMD Model"

root = mmd_model.Model.findRoot(armature)
root = FnModel.find_root_object(armature)
if root is None or root != armature.parent:
rig = mmd_model.Model.create(model_name, model_name, scale, armature=armature)
Model.create(model_name, model_name, scale, armature=armature)

self.__attach_meshes_to(armature, SceneOp(context).id_objects)
self.__configure_rig(context, mmd_model.Model(armature.parent))
self.__configure_rig(context, Model(armature.parent))
return {"FINISHED"}

def __attach_meshes_to(self, armature, objects):
Expand Down Expand Up @@ -379,7 +385,7 @@ def __configure_rig(self, context, rig):
FnMaterial.set_nodes_are_readonly(False)
from mmd_tools.operators.display_item import DisplayItemQuickSetup

DisplayItemQuickSetup.load_bone_groups(root.mmd_root, armature)
FnBone.sync_display_item_frames_from_bone_collections(armature)
rig.initialDisplayFrames(reset=False) # ensure default frames
DisplayItemQuickSetup.load_facial_items(root.mmd_root)
root.mmd_root.active_display_item_frame = 0
Expand All @@ -393,24 +399,25 @@ class ResetObjectVisibility(bpy.types.Operator):
@classmethod
def poll(cls, context: bpy.types.Context):
active_object: bpy.types.Object = context.active_object
return mmd_model.Model.findRoot(active_object) is not None
return FnModel.find_root_object(active_object) is not None

def execute(self, context: bpy.types.Context):
active_object: bpy.types.Object = context.active_object
mmd_root_object = mmd_model.Model.findRoot(active_object)
mmd_root = mmd_root_object.mmd_root
mmd_root_object = FnModel.find_root_object(active_object)
assert mmd_root_object is not None
mmd_root = cast(MMDRoot, mmd_root_object.mmd_root)

mmd_root_object.hide_set(False)

rigid_group_object = mmd_model.FnModel.find_rigid_group_object(mmd_root_object)
rigid_group_object = FnModel.find_rigid_group_object(mmd_root_object)
if rigid_group_object:
rigid_group_object.hide_set(True)

joint_group_object = mmd_model.FnModel.find_joint_group_object(mmd_root_object)
joint_group_object = FnModel.find_joint_group_object(mmd_root_object)
if joint_group_object:
joint_group_object.hide_set(True)

temporary_group_object = mmd_model.FnModel.find_temporary_group_object(mmd_root_object)
temporary_group_object = FnModel.find_temporary_group_object(mmd_root_object)
if temporary_group_object:
temporary_group_object.hide_set(True)

Expand All @@ -432,10 +439,10 @@ class AssembleAll(Operator):

def execute(self, context):
active_object = context.active_object
root_object = mmd_model.Model.findRoot(active_object)
root_object = FnModel.find_root_object(active_object)

with activate_layer_collection(root_object):
rig = mmd_model.Model(root_object)
rig = Model(root_object)

MigrationFnBone.fix_mmd_ik_limit_override(rig.armature())
FnBone.apply_additional_transformation(rig.armature())
Expand All @@ -458,10 +465,10 @@ class DisassembleAll(Operator):

def execute(self, context):
active_object = context.active_object
root_object = mmd_model.Model.findRoot(active_object)
root_object = FnModel.find_root_object(active_object)

with activate_layer_collection(root_object):
rig = mmd_model.Model(root_object)
rig = Model(root_object)

root_object.mmd_root.use_property_driver = False
with bpy.context.temp_override(selected_objects=[active_object]):
Expand Down

0 comments on commit 6a44a5a

Please sign in to comment.