122 lines
4.9 KiB
Python
122 lines
4.9 KiB
Python
# SPDX-FileCopyrightText: 2025 Blender Studio Tools Authors
|
|
#
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import bpy
|
|
from bpy.types import Collection
|
|
from .transfer_data.transfer_functions.shape_keys import shape_key_set_active
|
|
from .. import prefs
|
|
|
|
class Perserve:
|
|
def __init__(self, local_col: Collection) -> None:
|
|
self._local_col = local_col
|
|
self._action_dict: dict = {}
|
|
self.generate_preserve_maps()
|
|
|
|
def generate_preserve_maps(self) -> None:
|
|
addon_prefs = prefs.get_addon_prefs()
|
|
if addon_prefs.preserve_action:
|
|
self._action_dict = self._get_action_map()
|
|
if addon_prefs.preserve_indexes:
|
|
self._active_index_dict = self._get_active_index_map()
|
|
|
|
def _get_action_map(self):
|
|
action_dict = {}
|
|
for obj in self._local_col.all_objects:
|
|
# Set action map for armatures only
|
|
if obj.type != "ARMATURE":
|
|
continue
|
|
# Only set action map if obj has action assignment
|
|
if not obj.animation_data or not obj.animation_data.action:
|
|
continue
|
|
|
|
# Store obj name as obj may removed during merge
|
|
action = obj.animation_data.action
|
|
action_dict[obj.name] = (action, obj.animation_data.action_slot, action.use_fake_user)
|
|
action.use_fake_user = True
|
|
return action_dict
|
|
|
|
def set_action_map(self):
|
|
for obj_name, action_info in self._action_dict.items():
|
|
action, slot, fake_user = action_info
|
|
obj = bpy.data.objects.get(obj_name)
|
|
if not obj:
|
|
continue
|
|
if not obj.animation_data:
|
|
obj.animation_data_create()
|
|
obj.animation_data.action = action
|
|
obj.animation_data.action_slot = slot
|
|
action.use_fake_user = fake_user
|
|
|
|
def unassign_actions(self):
|
|
for obj_name, action_info in self._action_dict.items():
|
|
action, slot, fake_user = action_info
|
|
obj = bpy.data.objects.get(obj_name)
|
|
if not obj:
|
|
continue
|
|
if obj.animation_data:
|
|
obj.animation_data.action = None
|
|
action.use_fake_user = fake_user
|
|
|
|
def _get_active_index_map(self):
|
|
active_index = {}
|
|
for obj in self._local_col.all_objects:
|
|
indexes = {}
|
|
|
|
if getattr(obj.data, "uv_layers", None) and getattr(obj.data.uv_layers, "active", None):
|
|
indexes['uv_layer'] = obj.data.uv_layers.active.name
|
|
|
|
if getattr(obj.vertex_groups, "active", None):
|
|
indexes['vertex_group'] = obj.vertex_groups.active.name
|
|
|
|
if (
|
|
getattr(obj.data, "color_attributes", None) and
|
|
getattr(obj.data.color_attributes, "active_color", None) and
|
|
len(obj.data.color_attributes) > 0
|
|
):
|
|
indexes['color_attribute'] = obj.data.color_attributes.active_color_name
|
|
|
|
if getattr(obj.data, "attributes", None) and getattr(
|
|
obj.data.attributes, "active", None
|
|
):
|
|
indexes['attribute'] = obj.data.attributes.active.name
|
|
|
|
if getattr(obj.data, "shape_keys", None) and getattr(obj, "active_shape_key", None):
|
|
indexes['shape_key'] = obj.active_shape_key.name
|
|
|
|
active_index[obj.name] = indexes
|
|
return active_index
|
|
|
|
def set_active_index_map(self):
|
|
for obj_name, indexes in self._active_index_dict.items():
|
|
obj = bpy.data.objects.get(obj_name)
|
|
if not obj:
|
|
continue
|
|
|
|
if indexes.get('uv_layer'):
|
|
uv_layer = obj.data.uv_layers[indexes.get('uv_layer')]
|
|
if uv_layer:
|
|
obj.data.uv_layers.active = uv_layer
|
|
|
|
if indexes.get('vertex_group'):
|
|
vertex_group = obj.vertex_groups.get(indexes.get('vertex_group'))
|
|
if vertex_group:
|
|
obj.vertex_groups.active = vertex_group
|
|
|
|
# Setting color_attribute active also sets attribute active, so attribute must always follow color_attribute
|
|
if indexes.get('color_attribute'):
|
|
color_attribute = obj.data.color_attributes.get(indexes.get('color_attribute'))
|
|
for index, color_attribute in enumerate(obj.data.color_attributes):
|
|
if color_attribute.name == indexes.get('color_attribute'):
|
|
obj.data.color_attributes.active_color_index = index
|
|
|
|
if indexes.get('attribute'):
|
|
attribute = obj.data.attributes.get(indexes.get('attribute'))
|
|
if attribute:
|
|
obj.data.attributes.active = attribute
|
|
|
|
if indexes.get('shape_key'):
|
|
shape_key = obj.data.shape_keys.key_blocks.get(indexes.get('shape_key'))
|
|
if shape_key:
|
|
shape_key_set_active(obj, indexes.get('shape_key'))
|