diff --git a/blender/arm/props.py b/blender/arm/props.py index af222807..0cdb249d 100755 --- a/blender/arm/props.py +++ b/blender/arm/props.py @@ -124,6 +124,7 @@ def init_properties(): bpy.types.Object.arm_proxy_sync_materials = BoolProperty(name="Materials", description="Keep materials synchronized with proxy object", default=True, update=arm.proxy.proxy_sync_materials) bpy.types.Object.arm_proxy_sync_modifiers = BoolProperty(name="Modifiers", description="Keep modifiers synchronized with proxy object", default=True, update=arm.proxy.proxy_sync_modifiers) bpy.types.Object.arm_proxy_sync_traits = BoolProperty(name="Traits", description="Keep traits synchronized with proxy object", default=True, update=arm.proxy.proxy_sync_traits) + bpy.types.Object.arm_proxy_sync_trait_props = BoolProperty(name="Trait Property Values", description="Keep trait property values synchronized with proxy object", default=False, update=arm.proxy.proxy_sync_traits) # For speakers bpy.types.Speaker.arm_play_on_start = BoolProperty(name="Play on Start", description="Play this sound automatically", default=False) bpy.types.Speaker.arm_loop = BoolProperty(name="Loop", description="Loop this sound", default=False) diff --git a/blender/arm/props_ui.py b/blender/arm/props_ui.py index 65b6c313..bea19b16 100644 --- a/blender/arm/props_ui.py +++ b/blender/arm/props_ui.py @@ -1320,6 +1320,9 @@ class ARM_PT_ProxyPanel(bpy.types.Panel): layout.prop(obj, "arm_proxy_sync_materials") layout.prop(obj, "arm_proxy_sync_modifiers") layout.prop(obj, "arm_proxy_sync_traits") + row = layout.row() + row.enabled = obj.arm_proxy_sync_traits + row.prop(obj, "arm_proxy_sync_trait_props") layout.operator("arm.proxy_toggle_all") layout.operator("arm.proxy_apply_all") @@ -1349,6 +1352,7 @@ class ArmProxyToggleAllButton(bpy.types.Operator): obj.arm_proxy_sync_materials = b obj.arm_proxy_sync_modifiers = b obj.arm_proxy_sync_traits = b + obj.arm_proxy_sync_trait_props = b return{'FINISHED'} class ArmProxyApplyAllButton(bpy.types.Operator): @@ -1365,6 +1369,7 @@ class ArmProxyApplyAllButton(bpy.types.Operator): obj.arm_proxy_sync_materials = context.object.arm_proxy_sync_materials obj.arm_proxy_sync_modifiers = context.object.arm_proxy_sync_modifiers obj.arm_proxy_sync_traits = context.object.arm_proxy_sync_traits + obj.arm_proxy_sync_trait_props = context.object.arm_proxy_sync_trait_props return{'FINISHED'} class ArmSyncProxyButton(bpy.types.Operator): diff --git a/blender/arm/proxy.py b/blender/arm/proxy.py index 558bd68f..fab18aed 100644 --- a/blender/arm/proxy.py +++ b/blender/arm/proxy.py @@ -1,3 +1,5 @@ +from typing import Any, Dict + import bpy def proxy_sync_loc(self, context): @@ -107,11 +109,40 @@ def sync_collection(cSrc, cDst): for prop in properties: setattr(mDst, prop, getattr(mSrc, prop)) -def sync_traits(obj): +def sync_traits(obj: bpy.types.Object): + """Synchronizes the traits of the given object with the traits of + its proxy. + If `arm.proxy_sync_trait_props` is `False`, the values of the trait + properties are kept where possible. + """ + # (Optionally) keep the old property values + values: Dict[bpy.types.Object, Dict[str, Dict[str, Any]]] = {} + for i in range(len(obj.arm_traitlist)): + if not obj.arm_proxy_sync_trait_props: + for prop in obj.arm_traitlist[i].arm_traitpropslist: + values[obj][obj.arm_traitlist[i].name][prop.name] = prop.get_value() + sync_collection(obj.proxy.arm_traitlist, obj.arm_traitlist) - for i in range(0, len(obj.arm_traitlist)): + + for i in range(len(obj.arm_traitlist)): sync_collection(obj.proxy.arm_traitlist[i].arm_traitpropslist, obj.arm_traitlist[i].arm_traitpropslist) + # Set stored property values + if not obj.arm_proxy_sync_trait_props: + if values.get(obj) is None: + continue + + value = values[obj].get(obj.arm_traitlist[i].name) + if value is None: + continue + + for prop in obj.arm_traitlist[i].arm_traitpropslist: + + value = values[obj].get(prop.name) + if value is not None: + prop.set_value(value) + + def sync_materials(obj): # Blender likes to crash here:( pass