diff --git a/multi_user/bl_types/bl_armature.py b/multi_user/bl_types/bl_armature.py index 8de002f..f106c5b 100644 --- a/multi_user/bl_types/bl_armature.py +++ b/multi_user/bl_types/bl_armature.py @@ -25,6 +25,16 @@ from .. import presence, operators, utils from .bl_datablock import BlDatablock +def get_roll(bone: bpy.types.Bone) -> float: + """ Compute the actuall roll of a pose bone + + :arg pose_bone: target pose bone + :type pose_bone: bpy.types.PoseBone + :return: float + """ + return bone.AxisRollFromMatrix(bone.matrix_local.to_3x3())[1] + + class BlArmature(BlDatablock): bl_id = "armatures" bl_class = bpy.types.Armature @@ -34,7 +44,7 @@ class BlArmature(BlDatablock): bl_check_common = False bl_icon = 'ARMATURE_DATA' bl_reload_parent = False - + def _construct(self, data): return bpy.data.armatures.new(data["name"]) @@ -44,8 +54,8 @@ class BlArmature(BlDatablock): 'uuid', data['user'], bpy.data.objects - ) - + ) + if parent_object is None: parent_object = bpy.data.objects.new( data['user_name'], target) @@ -94,16 +104,16 @@ class BlArmature(BlDatablock): new_bone.head = bone_data['head_local'] new_bone.tail_radius = bone_data['tail_radius'] new_bone.head_radius = bone_data['head_radius'] - # new_bone.roll = bone_data['roll'] - + new_bone.roll = bone_data['roll'] + if 'parent' in bone_data: new_bone.parent = target.edit_bones[data['bones'] - [bone]['parent']] + [bone]['parent']] new_bone.use_connect = bone_data['use_connect'] loader = Loader() loader.load(new_bone, bone_data) - + if bpy.context.mode != 'OBJECT': bpy.ops.object.mode_set(mode='OBJECT') bpy.context.view_layer.objects.active = current_active_object @@ -127,8 +137,6 @@ class BlArmature(BlDatablock): 'parent', 'name', 'layers', - # 'roll', - ] data = dumper.dump(instance) @@ -136,6 +144,7 @@ class BlArmature(BlDatablock): if bone.parent: data['bones'][bone.name]['parent'] = bone.parent.name # get the parent Object + # TODO: Use id_data instead object_users = utils.get_datablock_users(instance)[0] data['user'] = object_users.uuid data['user_name'] = object_users.name @@ -146,6 +155,8 @@ class BlArmature(BlDatablock): item.name for item in container_users if isinstance(item, bpy.types.Collection)] data['user_scene'] = [ item.name for item in container_users if isinstance(item, bpy.types.Scene)] + + for bone in instance.bones: + data['bones'][bone.name]['roll'] = get_roll(bone) + return data - - diff --git a/multi_user/bl_types/bl_datablock.py b/multi_user/bl_types/bl_datablock.py index d10cbe4..c016b4f 100644 --- a/multi_user/bl_types/bl_datablock.py +++ b/multi_user/bl_types/bl_datablock.py @@ -56,7 +56,7 @@ def load_driver(target_datablock, src_driver): loader = Loader() drivers = target_datablock.animation_data.drivers src_driver_data = src_driver['driver'] - new_driver = drivers.new(src_driver['data_path']) + new_driver = drivers.new(src_driver['data_path'], index=src_driver['array_index']) # Settings new_driver.driver.type = src_driver_data['type'] diff --git a/multi_user/bl_types/bl_object.py b/multi_user/bl_types/bl_object.py index 9091ff4..2aa21e6 100644 --- a/multi_user/bl_types/bl_object.py +++ b/multi_user/bl_types/bl_object.py @@ -23,9 +23,19 @@ import mathutils from replication.exception import ContextError from .bl_datablock import BlDatablock, get_datablock_from_uuid -from .dump_anything import Dumper, Loader +from .dump_anything import ( + Dumper, + Loader, + np_load_collection, + np_dump_collection) +SKIN_DATA = [ + 'radius', + 'use_loose', + 'use_root' +] + def load_pose(target_bone, data): target_bone.rotation_mode = data['rotation_mode'] loader = Loader() @@ -64,7 +74,7 @@ def find_data_from_name(name=None): logging.warning( "Lightprobe replication only supported since 2.83. See https://developer.blender.org/D6396") elif bpy.app.version[1] >= 91 and name in bpy.data.volumes.keys(): - # Only supported since 2.91 + # Only supported since 2.91 instance = bpy.data.volumes[name] return instance @@ -150,12 +160,12 @@ class BlObject(BlDatablock): vertex_group.add( [vert['index']], vert['weight'], 'REPLACE') + object_data = target.data + # SHAPE KEYS if 'shape_keys' in data: target.shape_key_clear() - object_data = target.data - # Create keys and load vertices coords for key_block in data['shape_keys']['key_blocks']: key_data = data['shape_keys']['key_blocks'][key_block] @@ -212,6 +222,15 @@ class BlObject(BlDatablock): if target.data is None and img_uuid: target.data = get_datablock_from_uuid(img_uuid, None) + if hasattr(object_data, 'skin_vertices') \ + and object_data.skin_vertices\ + and 'skin_vertices' in data: + for index, skin_data in enumerate(object_data.skin_vertices): + np_load_collection( + data['skin_vertices'][index], + skin_data.data, + SKIN_DATA) + def _dump_implementation(self, data, instance=None): assert(instance) @@ -273,14 +292,14 @@ class BlObject(BlDatablock): return data # MODIFIERS - modifiers = getattr(instance,'modifiers', None ) - data["modifiers"] = {} - if modifiers: - dumper.include_filter = None - dumper.depth = 1 - - for index, modifier in enumerate(modifiers): - data["modifiers"][modifier.name] = dumper.dump(modifier) + if hasattr(instance, 'modifiers'): + data["modifiers"] = {} + modifiers = getattr(instance, 'modifiers', None) + if modifiers: + dumper.include_filter = None + dumper.depth = 1 + for index, modifier in enumerate(modifiers): + data["modifiers"][modifier.name] = dumper.dump(modifier) gp_modifiers = getattr(instance, 'grease_pencil_modifiers', None) @@ -305,6 +324,7 @@ class BlObject(BlDatablock): # CONSTRAINTS if hasattr(instance, 'constraints'): + dumper.include_filter = None dumper.depth = 3 data["constraints"] = dumper.dump(instance.constraints) @@ -408,6 +428,12 @@ class BlObject(BlDatablock): key_blocks[key.name]['relative_key'] = key.relative_key.name data['shape_keys']['key_blocks'] = key_blocks + if hasattr(object_data, 'skin_vertices') and object_data.skin_vertices: + skin_vertices = list() + for skin_data in object_data.skin_vertices: + skin_vertices.append(np_dump_collection(skin_data.data, SKIN_DATA)) + data['skin_vertices'] = skin_vertices + return data def _resolve_deps_implementation(self): diff --git a/multi_user/bl_types/dump_anything.py b/multi_user/bl_types/dump_anything.py index 50b7022..4d43180 100644 --- a/multi_user/bl_types/dump_anything.py +++ b/multi_user/bl_types/dump_anything.py @@ -514,7 +514,7 @@ class Loader: T.ColorRampElement: DESTRUCTOR_REMOVE, T.Modifier: DESTRUCTOR_CLEAR, T.GpencilModifier: DESTRUCTOR_CLEAR, - T.Constraint: CONSTRUCTOR_NEW, + T.Constraint: DESTRUCTOR_REMOVE, } element_type = element.bl_rna_property.fixed_type @@ -529,7 +529,13 @@ class Loader: if destructor: if destructor == DESTRUCTOR_REMOVE: collection = element.read() - for i in range(len(collection)-1): + elems_to_remove = len(collection) + + # Color ramp doesn't allow to remove all elements + if type(element_type) == T.ColorRampElement: + elems_to_remove -= 1 + + for i in range(elems_to_remove): collection.remove(collection[0]) else: getattr(element.read(), DESTRUCTOR_CLEAR)()