Skip to content

Commit

Permalink
Merge pull request #73 from UuuNyaa/70-fixed-bone-morph-exception-_ge…
Browse files Browse the repository at this point in the history
…tvisibilityofmmdrigarmature-exception-and-rigidbody-data-loss-and-regeneration

Fix 3 problems
  • Loading branch information
UuuNyaa authored Oct 7, 2022
2 parents 69fa072 + 740b8a9 commit 97861e3
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 38 deletions.
2 changes: 1 addition & 1 deletion mmd_tools/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ def renameBone(self, old_bone_name, new_bone_name):
if old_bone_name in mesh.vertex_groups:
mesh.vertex_groups[old_bone_name].name = new_bone_name

def build(self, non_collision_distance_scale, collision_margin):
def build(self, non_collision_distance_scale = 1.5, collision_margin = 1e-06):
rigidbody_world_enabled = rigid_body.setRigidBodyWorldEnabled(False)
if self.__root.mmd_root.is_built:
self.clean()
Expand Down
2 changes: 1 addition & 1 deletion mmd_tools/operators/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ def execute(self, context):
rig = mmd_model.Model(root_object)

rig.applyAdditionalTransformConstraints()
rig.build(1.5, 1e-06)
rig.build()
rig.morph_slider.bind()

bpy.ops.mmd_tools.sdef_bind({'selected_objects': [active_object]})
Expand Down
84 changes: 49 additions & 35 deletions mmd_tools/operators/rigid_body.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@

import bpy
import mmd_tools.core.model as mmd_model
from bpy.types import Operator
from mmd_tools import utils
from mmd_tools.bpyutils import Props
from mmd_tools.bpyutils import Props, activate_layer_collection
from mmd_tools.core import rigid_body


class SelectRigidBody(Operator):
class SelectRigidBody(bpy.types.Operator):
bl_idname = 'mmd_tools.rigid_body_select'
bl_label = 'Select Rigid Body'
bl_description = 'Select similar rigidbody objects which have the same property values with active rigidbody object'
Expand Down Expand Up @@ -78,7 +77,7 @@ def execute(self, context):

return { 'FINISHED' }

class AddRigidBody(Operator):
class AddRigidBody(bpy.types.Operator):
bl_idname = 'mmd_tools.rigid_body_add'
bl_label = 'Add Rigid Body'
bl_description = 'Add Rigid Bodies to selected bones'
Expand Down Expand Up @@ -263,7 +262,7 @@ def invoke(self, context, event):
vm = context.window_manager
return vm.invoke_props_dialog(self)

class RemoveRigidBody(Operator):
class RemoveRigidBody(bpy.types.Operator):
bl_idname = 'mmd_tools.rigid_body_remove'
bl_label = 'Remove Rigid Body'
bl_description = 'Deletes the currently selected Rigid Body'
Expand Down Expand Up @@ -312,7 +311,7 @@ def execute(self, context: bpy.types.Context):

return {'FINISHED'}

class AddJoint(Operator):
class AddJoint(bpy.types.Operator):
bl_idname = 'mmd_tools.joint_add'
bl_label = 'Add Joint'
bl_description = 'Add Joint(s) to selected rigidbody objects'
Expand Down Expand Up @@ -445,7 +444,7 @@ def invoke(self, context, event):
vm = context.window_manager
return vm.invoke_props_dialog(self)

class RemoveJoint(Operator):
class RemoveJoint(bpy.types.Operator):
bl_idname = 'mmd_tools.joint_remove'
bl_label = 'Remove Joint'
bl_description = 'Deletes the currently selected Joint'
Expand All @@ -464,7 +463,7 @@ def execute(self, context):
utils.selectAObject(root)
return { 'FINISHED' }

class UpdateRigidBodyWorld(Operator):
class UpdateRigidBodyWorld(bpy.types.Operator):
bl_idname = 'mmd_tools.rigid_body_world_update'
bl_label = 'Update Rigid Body World'
bl_description = 'Update rigid body world and references of rigid body constraint according to current scene objects (experimental)'
Expand All @@ -474,15 +473,6 @@ class UpdateRigidBodyWorld(Operator):
def __get_rigid_body_world_objects():
rigid_body.setRigidBodyWorldEnabled(True)
rbw = bpy.context.scene.rigidbody_world
if bpy.app.version < (2, 80, 0):
if not rbw.group:
rbw.group = bpy.data.groups.new('RigidBodyWorld')
rbw.group.use_fake_user = True
if not rbw.constraints:
rbw.constraints = bpy.data.groups.new('RigidBodyConstraints')
rbw.constraints.use_fake_user = True
return rbw.group.objects, rbw.constraints.objects

if not rbw.collection:
rbw.collection = bpy.data.collections.new('RigidBodyWorld')
rbw.collection.use_fake_user = True
Expand All @@ -497,12 +487,12 @@ def __get_rigid_body_world_objects():
return rbw.collection.objects, rbw.constraints.objects

def execute(self, context):
scene_objs = (bpy.context.scene.objects,)
scene_objs += tuple({x.dupli_group.objects for x in scene_objs[0] if x.dupli_type == 'GROUP' and x.dupli_group}) if bpy.app.version < (2, 80, 0)\
else tuple({x.instance_collection.objects for x in scene_objs[0] if x.instance_type == 'COLLECTION' and x.instance_collection})
scene = context.scene
scene_objs = set(scene.objects)
scene_objs.union(o for x in scene.objects if x.instance_type == 'COLLECTION' and x.instance_collection for o in x.instance_collection.objects)

def _update_group(obj, group):
if any((obj in x.values()) for x in scene_objs):
if obj in scene_objs:
if obj not in group.values():
group.link(obj)
return True
Expand All @@ -517,25 +507,49 @@ def _references(obj):
if getattr(obj, 'override_library', None):
yield from _references(obj.override_library.reference)

_find_root = mmd_model.Model.findRoot
_find_root = mmd_model.FnModel.find_root
need_rebuild_physics = scene.rigidbody_world is None or scene.rigidbody_world.collection is None or scene.rigidbody_world.constraints is None
rb_objs, rbc_objs = self.__get_rigid_body_world_objects()
objects = bpy.data.objects
table = {}

for i in (x for x in objects if x.rigid_body):
if _update_group(i, rb_objs):
rb_map = table.setdefault(_find_root(i), {})
if i in rb_map: # means rb_map[i] will replace i
rb_objs.unlink(i)
continue
for r in _references(i):
rb_map[r] = i
# Perhaps due to a bug in Blender,
# when bpy.ops.rigidbody.world_remove(),
# Object.rigid_body are removed,
# but Object.rigid_body_constraint are retained.
# Therefore, it must be checked with Object.mmd_type.
for i in (x for x in objects if x.mmd_type == 'RIGID_BODY'):
if not _update_group(i, rb_objs):
continue

rb_map = table.setdefault(_find_root(i), {})
if i in rb_map: # means rb_map[i] will replace i
rb_objs.unlink(i)
continue
for r in _references(i):
rb_map[r] = i

# TODO Modify mmd_rigid to allow recovery of the remaining rigidbody parameters.
# mass, friction, restitution, linear_dumping, angular_dumping

for i in (x for x in objects if x.rigid_body_constraint):
if _update_group(i, rbc_objs):
rbc, root = i.rigid_body_constraint, _find_root(i)
rb_map = table.get(root, {})
rbc.object1 = rb_map.get(rbc.object1, rbc.object1)
rbc.object2 = rb_map.get(rbc.object2, rbc.object2)
if not _update_group(i, rbc_objs):
continue

rbc, root = i.rigid_body_constraint, _find_root(i)
rb_map = table.get(root, {})
rbc.object1 = rb_map.get(rbc.object1, rbc.object1)
rbc.object2 = rb_map.get(rbc.object2, rbc.object2)

if need_rebuild_physics:
for root in scene.objects:
if root.mmd_type != 'ROOT':
continue
if not root.mmd_root.is_built:
continue
with activate_layer_collection(root):
mmd_model.Model(root).build()
# After rebuild. First play. Will be crash!
# But saved it before. Reload after crash. The play can be work.

return { 'FINISHED' }
8 changes: 8 additions & 0 deletions mmd_tools/properties/morph.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ def _get_bone(prop):
root = prop.id_data
fnModel = FnModel(root)
arm = fnModel.armature()
if arm is None:
return ''
fnBone = FnBone.from_bone_id(arm, bone_id)
if not fnBone:
return ''
Expand All @@ -112,6 +114,12 @@ def _set_bone(prop, value):
root = prop.id_data
fnModel = FnModel(root)
arm = fnModel.armature()

# Load the library_override file. This function is triggered when loading, but the arm obj cannot be found.
# The arm obj is exist, but the relative relationship has not yet been established.
if arm is None:
return

if value not in arm.pose.bones.keys():
prop['bone_id'] = -1
return
Expand Down
4 changes: 3 additions & 1 deletion mmd_tools/properties/root.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ def _getVisibilityOfMMDRigArmature(prop):
if prop.id_data.mmd_type != 'ROOT':
return False
arm = mmd_model.FnModel.find_armature(prop.id_data)
return (arm and not arm.hide)
r = arm and not arm.hide
# Returning the non-BOOL type will raise a exception in the library override mode.
return bool(r)


def _setActiveRigidbodyObject(prop, v):
Expand Down

0 comments on commit 97861e3

Please sign in to comment.