Asset Pipeline v2 #145
@ -3,6 +3,7 @@ from typing import Dict, Set
|
||||
|
||||
from . import asset_suffix
|
||||
from . import constants
|
||||
from .transfer_data import transfer_core
|
||||
|
||||
|
||||
class AssetTransferMapping:
|
||||
@ -126,50 +127,43 @@ class AssetTransferMapping:
|
||||
|
||||
def _gen_transfer_data_map(self):
|
||||
transfer_data_map: Dict[bpy.types.Collection, bpy.types.Collection] = {}
|
||||
remove_transfer_data = []
|
||||
for obj in self._external_col.all_objects:
|
||||
# TODO Remove any tansfer_info that is on an external obj but owned by the local TL
|
||||
# TODO this works on pull not push FIX!
|
||||
# TODO Just do the opposite of this in the local collection
|
||||
for transfer_info in obj.transfer_data_ownership:
|
||||
if transfer_info.owner in self._local_tls:
|
||||
remove_transfer_data.append(transfer_info.name)
|
||||
if (
|
||||
transfer_info.owner not in self._local_tls
|
||||
and transfer_info.owner != "NONE"
|
||||
):
|
||||
name = transfer_info.name + '_' + obj.name
|
||||
target_obj_name = asset_suffix.get_target_name(obj.name)
|
||||
target_obj = self._local_col.all_objects.get(target_obj_name)
|
||||
transfer_data_map[name] = (transfer_info, target_obj)
|
||||
|
||||
for name in remove_transfer_data:
|
||||
# TODO FIX THIS
|
||||
try:
|
||||
index = obj.transfer_data_ownership.keys().index(name)
|
||||
obj.transfer_data_ownership.remove(index)
|
||||
print(f"Remvoing {name} from {obj.name}")
|
||||
except:
|
||||
continue
|
||||
|
||||
remove_transfer_data = []
|
||||
for obj in self._local_col.all_objects:
|
||||
for transfer_info in obj.transfer_data_ownership:
|
||||
# if transfer_info.owner not in self._local_tls:
|
||||
# remove_transfer_data.append(transfer_info.name)
|
||||
if transfer_info.owner in self._local_tls:
|
||||
name = transfer_info.name + '_' + obj.name
|
||||
target_obj_name = asset_suffix.get_target_name(obj.name)
|
||||
target_obj = self._external_col.all_objects.get(target_obj_name)
|
||||
transfer_data_map[name] = (transfer_info, target_obj)
|
||||
|
||||
# for name in remove_transfer_data:
|
||||
# # TODO FIX THIS
|
||||
# try:
|
||||
# index = obj.transfer_data_ownership.keys().index(name)
|
||||
# obj.transfer_data_ownership.remove(index)
|
||||
# print(f"Remvoing {name} from {obj.name}")
|
||||
# except:
|
||||
# continue
|
||||
temp_transfer_data = bpy.context.scene.temp_transfer_data_ownership
|
||||
for source_obj in self.object_map:
|
||||
target_obj = self.object_map[source_obj]
|
||||
objs = [source_obj, target_obj]
|
||||
for obj in objs:
|
||||
if obj.name.endswith(constants.LOCAL_SUFFIX):
|
||||
for transfer_info in obj.transfer_data_ownership:
|
||||
if transfer_info.owner in self._local_tls:
|
||||
temp_info = transfer_core.transfer_data_add_entry(
|
||||
transfer_data=temp_transfer_data,
|
||||
name=transfer_info.name,
|
||||
td_type=transfer_info.type,
|
||||
task_layer_name=transfer_info.owner,
|
||||
)
|
||||
name = transfer_info.name + '_' + obj.name
|
||||
transfer_data_map[name] = {
|
||||
'transfer_info': temp_info,
|
||||
'source_obj': obj,
|
||||
'target_obj': target_obj,
|
||||
}
|
||||
|
||||
if obj.name.endswith(constants.EXTERNAL_SUFFIX):
|
||||
for transfer_info in obj.transfer_data_ownership:
|
||||
if (
|
||||
transfer_info.owner not in self._local_tls
|
||||
and transfer_info.owner != "NONE"
|
||||
):
|
||||
temp_info = transfer_core.transfer_data_add_entry(
|
||||
transfer_data=temp_transfer_data,
|
||||
name=transfer_info.name,
|
||||
td_type=transfer_info.type,
|
||||
task_layer_name=transfer_info.owner,
|
||||
)
|
||||
name = transfer_info.name + '_' + obj.name
|
||||
transfer_data_map[name] = {
|
||||
'transfer_info': temp_info,
|
||||
'source_obj': obj,
|
||||
'target_obj': target_obj,
|
||||
}
|
||||
return transfer_data_map
|
||||
|
@ -79,41 +79,61 @@ def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
|
||||
context (bpy.types.Context): context of .blend file
|
||||
transfer_data_map: Map generated by class AssetTransferMapping
|
||||
"""
|
||||
target_objs = [
|
||||
transfer_data_map[name].get("target_obj") for name in transfer_data_map
|
||||
]
|
||||
for target_obj in set(target_objs):
|
||||
target_obj.transfer_data_ownership.clear()
|
||||
|
||||
for name in transfer_data_map:
|
||||
transfer_data = transfer_data_map[name]
|
||||
transfer_info = transfer_data[0]
|
||||
target_obj = transfer_data[1]
|
||||
transfer_info = transfer_data.get('transfer_info')
|
||||
target_obj = transfer_data.get('target_obj')
|
||||
source_obj = transfer_data.get('source_obj')
|
||||
if target_obj is None:
|
||||
print(f"Failed to Transfer data for {transfer_info.id_data.name}")
|
||||
continue
|
||||
if transfer_info.type == constants.VERTEX_GROUP_KEY:
|
||||
print(f"Transfering Data {constants.VERTEX_GROUP_KEY}: {name}")
|
||||
transfer_functions.transfer_vertex_group(
|
||||
context=context,
|
||||
vertex_group_name=transfer_info.name,
|
||||
obj_target=target_obj,
|
||||
obj_source=transfer_info.id_data,
|
||||
)
|
||||
if transfer_info.type == constants.VERTEX_COLOR_KEY:
|
||||
transfer_functions.transfer_vertex_color(
|
||||
vertex_color_name=transfer_info.name,
|
||||
obj_target=target_obj,
|
||||
obj_source=transfer_info.id_data,
|
||||
)
|
||||
if transfer_info.type == constants.MODIFIER_KEY:
|
||||
print(f"Transfering Data {constants.MODIFIER_KEY}: {name}")
|
||||
transfer_functions.transfer_modifier(transfer_info, target_obj)
|
||||
if transfer_info.type == constants.CONSTRAINT_KEY:
|
||||
transfer_functions.transfer_constraint(transfer_info, target_obj)
|
||||
if transfer_info.type == constants.MATERIAL_SLOT_KEY:
|
||||
print(f"Transfering Data {constants.MATERIAL_SLOT_KEY}: {name}")
|
||||
transfer_functions.transfer_material_slot(transfer_info, target_obj)
|
||||
if transfer_info.type == constants.UV_LAYERS_KEY:
|
||||
transfer_functions.transfer_uv_layer(
|
||||
obj_target=target_obj,
|
||||
obj_source=transfer_info.id_data,
|
||||
uv_name=transfer_info.name,
|
||||
)
|
||||
if source_obj != target_obj:
|
||||
if transfer_info.type == constants.VERTEX_GROUP_KEY:
|
||||
print(f"Transfering Data {constants.VERTEX_GROUP_KEY}: {name}")
|
||||
transfer_functions.transfer_vertex_group(
|
||||
context=context,
|
||||
vertex_group_name=transfer_info.name,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_info.type == constants.VERTEX_COLOR_KEY:
|
||||
transfer_functions.transfer_vertex_color(
|
||||
vertex_color_name=transfer_info.name,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_info.type == constants.MODIFIER_KEY:
|
||||
print(f"Transfering Data {constants.MODIFIER_KEY}: {name}")
|
||||
transfer_functions.transfer_modifier(
|
||||
transfer_info=transfer_info,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_info.type == constants.CONSTRAINT_KEY:
|
||||
transfer_functions.transfer_constraint(
|
||||
transfer_info=transfer_info,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_info.type == constants.MATERIAL_SLOT_KEY:
|
||||
print(f"Transfering Data {constants.MATERIAL_SLOT_KEY}: {name}")
|
||||
transfer_functions.transfer_material_slot(
|
||||
transfer_info=transfer_info,
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
)
|
||||
if transfer_info.type == constants.UV_LAYERS_KEY:
|
||||
transfer_functions.transfer_uv_layer(
|
||||
target_obj=target_obj,
|
||||
source_obj=source_obj,
|
||||
uv_name=transfer_info.name,
|
||||
)
|
||||
|
||||
copy_transfer_data_ownership(
|
||||
transfer_data_item=transfer_info,
|
||||
@ -160,6 +180,7 @@ def transfer_data_add_entry(
|
||||
transfer_info.name = name
|
||||
transfer_info.owner = task_layer_name.upper()
|
||||
transfer_info.type = td_type
|
||||
return transfer_info
|
||||
|
||||
|
||||
def copy_transfer_data(source_data, target_data):
|
||||
|
@ -5,6 +5,7 @@ from .. import asset_suffix, constants
|
||||
|
||||
|
||||
## FUNCTIONS SPECFIC TO TRANSFER DATA TYPES
|
||||
# TODO Remove reliance on transfer_info for 'transfer' functions
|
||||
|
||||
|
||||
def vertex_groups_clean(obj):
|
||||
@ -41,20 +42,20 @@ def get_vertex_groups(obj, task_layer_name, new_transfer_data):
|
||||
def transfer_vertex_group(
|
||||
context,
|
||||
vertex_group_name: str,
|
||||
obj_target: bpy.types.Object,
|
||||
obj_source: bpy.types.Object,
|
||||
target_obj: bpy.types.Object,
|
||||
source_obj: bpy.types.Object,
|
||||
):
|
||||
if obj_target == obj_source:
|
||||
if target_obj == source_obj:
|
||||
return
|
||||
|
||||
if obj_target.vertex_groups.get(vertex_group_name):
|
||||
obj_target.vertex_groups.remove(obj_target.vertex_groups.get(vertex_group_name))
|
||||
if target_obj.vertex_groups.get(vertex_group_name):
|
||||
target_obj.vertex_groups.remove(target_obj.vertex_groups.get(vertex_group_name))
|
||||
|
||||
obj_source.vertex_groups.active = obj_source.vertex_groups[vertex_group_name]
|
||||
source_obj.vertex_groups.active = source_obj.vertex_groups[vertex_group_name]
|
||||
override = context.copy()
|
||||
override["selected_editable_objects"] = [obj_target, obj_source]
|
||||
override["active_object"] = obj_source
|
||||
override["object"] = obj_source
|
||||
override["selected_editable_objects"] = [target_obj, source_obj]
|
||||
override["active_object"] = source_obj
|
||||
override["object"] = source_obj
|
||||
with context.temp_override(**override):
|
||||
bpy.ops.object.data_transfer(
|
||||
data_type="VGROUP_WEIGHTS",
|
||||
@ -104,17 +105,17 @@ def get_vertex_colors(obj, task_layer_name, new_transfer_data):
|
||||
|
||||
def transfer_vertex_color(
|
||||
vertex_color_name: str,
|
||||
obj_target: bpy.types.Object,
|
||||
obj_source: bpy.types.Object,
|
||||
target_obj: bpy.types.Object,
|
||||
source_obj: bpy.types.Object,
|
||||
):
|
||||
old_color = obj_target.data.vertex_colors.get(vertex_color_name)
|
||||
old_color = target_obj.data.vertex_colors.get(vertex_color_name)
|
||||
if old_color:
|
||||
obj_target.data.vertex_colors.remove(old_color)
|
||||
transfer_color = obj_source.data.vertex_colors.get(vertex_color_name)
|
||||
new_color = obj_target.data.vertex_colors.new(
|
||||
target_obj.data.vertex_colors.remove(old_color)
|
||||
transfer_color = source_obj.data.vertex_colors.get(vertex_color_name)
|
||||
new_color = target_obj.data.vertex_colors.new(
|
||||
name=transfer_color.name, do_init=False
|
||||
)
|
||||
for loop in obj_target.data.loops:
|
||||
for loop in target_obj.data.loops:
|
||||
new_color.data[loop.index].color = transfer_color.data[loop.index].color
|
||||
# ABOVE FOR LOOP IS FOR TOPOLOGY THAT MATCHES
|
||||
# BELOW COMMENTED OUT CODE IS FOR TOPOLOGY THAT DOESN'T MATCH
|
||||
@ -159,14 +160,14 @@ def get_uv_layers(obj, task_layer_name, new_transfer_data):
|
||||
transfer_info.obj = obj
|
||||
|
||||
|
||||
def transfer_uv_layer(obj_source, obj_target, uv_name):
|
||||
old_uv_layer = obj_target.data.uv_layers.get(uv_name)
|
||||
def transfer_uv_layer(source_obj, target_obj, uv_name):
|
||||
old_uv_layer = target_obj.data.uv_layers.get(uv_name)
|
||||
if old_uv_layer:
|
||||
obj_target.data.uv_layers.remove(old_uv_layer)
|
||||
target_obj.data.uv_layers.remove(old_uv_layer)
|
||||
|
||||
transfer_uv = obj_source.data.uv_layers.get(uv_name)
|
||||
new_uv = obj_target.data.uv_layers.new(name=uv_name, do_init=False)
|
||||
for loop in obj_target.data.loops:
|
||||
transfer_uv = source_obj.data.uv_layers.get(uv_name)
|
||||
new_uv = target_obj.data.uv_layers.new(name=uv_name, do_init=False)
|
||||
for loop in target_obj.data.loops:
|
||||
new_uv.data[loop.index].uv = transfer_uv.data[loop.index].uv
|
||||
# BELOW CODE IS FOR NON MATCHING TOPOLOGY
|
||||
# else:
|
||||
@ -175,9 +176,9 @@ def transfer_uv_layer(obj_source, obj_target, uv_name):
|
||||
# transfer_corner_data(obj_source, obj_target, uv_from.data, uv_to.data, data_suffix = 'uv')
|
||||
|
||||
# Make sure correct layer is set to active
|
||||
for uv_l in obj_source.data.uv_layers:
|
||||
for uv_l in source_obj.data.uv_layers:
|
||||
if uv_l.active_render:
|
||||
obj_target.data.uv_layers[uv_l.name].active_render = True
|
||||
target_obj.data.uv_layers[uv_l.name].active_render = True
|
||||
break
|
||||
|
||||
|
||||
@ -211,43 +212,40 @@ def get_modifiers(obj, task_layer_name, new_transfer_data):
|
||||
transfer_info.obj = obj
|
||||
|
||||
|
||||
def transfer_modifier(transfer_info, obj_target):
|
||||
def transfer_modifier(transfer_info, target_obj, source_obj):
|
||||
# remove old and sync existing modifiers
|
||||
obj_source = transfer_info.id_data
|
||||
if obj_source == obj_target:
|
||||
return
|
||||
old_mod = obj_target.modifiers.get(transfer_info.name)
|
||||
old_mod = target_obj.modifiers.get(transfer_info.name)
|
||||
if old_mod:
|
||||
obj_target.modifiers.remove(old_mod)
|
||||
target_obj.modifiers.remove(old_mod)
|
||||
|
||||
# transfer new modifiers
|
||||
for i, mod in enumerate(obj_source.modifiers):
|
||||
for i, mod in enumerate(source_obj.modifiers):
|
||||
if mod.name == transfer_info.name:
|
||||
mod_new = obj_target.modifiers.new(mod.name, mod.type)
|
||||
mod_new = target_obj.modifiers.new(mod.name, mod.type)
|
||||
# sort new modifier at correct index (default to beginning of the stack)
|
||||
idx = 0
|
||||
if i > 0:
|
||||
name_prev = obj_source.modifiers[i - 1].name
|
||||
for target_mod_i, target_mod in enumerate(obj_target.modifiers):
|
||||
name_prev = source_obj.modifiers[i - 1].name
|
||||
for target_mod_i, target_mod in enumerate(target_obj.modifiers):
|
||||
if target_mod.name == name_prev:
|
||||
idx = target_mod_i + 1
|
||||
bpy.ops.object.modifier_move_to_index(
|
||||
{'object': obj_target}, modifier=mod_new.name, index=idx
|
||||
{'object': target_obj}, modifier=mod_new.name, index=idx
|
||||
)
|
||||
mod_target = obj_target.modifiers.get(mod.name)
|
||||
mod_target = target_obj.modifiers.get(mod.name)
|
||||
props = [p.identifier for p in mod.bl_rna.properties if not p.is_readonly]
|
||||
for prop in props:
|
||||
value = getattr(mod, prop)
|
||||
setattr(mod_target, prop, value)
|
||||
|
||||
# rebind modifiers (corr. smooth, surf. deform, mesh deform)
|
||||
for mod in obj_target.modifiers:
|
||||
for mod in target_obj.modifiers:
|
||||
if mod.type == 'SURFACE_DEFORM':
|
||||
if not mod.is_bound:
|
||||
continue
|
||||
for i in range(2):
|
||||
bpy.ops.object.surfacedeform_bind(
|
||||
{"object": obj_target, "active_object": obj_target},
|
||||
{"object": target_obj, "active_object": target_obj},
|
||||
modifier=mod.name,
|
||||
)
|
||||
elif mod.type == 'MESH_DEFORM':
|
||||
@ -255,7 +253,7 @@ def transfer_modifier(transfer_info, obj_target):
|
||||
continue
|
||||
for i in range(2):
|
||||
bpy.ops.object.meshdeform_bind(
|
||||
{"object": obj_target, "active_object": obj_target},
|
||||
{"object": target_obj, "active_object": target_obj},
|
||||
modifier=mod.name,
|
||||
)
|
||||
elif mod.type == 'CORRECTIVE_SMOOTH':
|
||||
@ -263,7 +261,7 @@ def transfer_modifier(transfer_info, obj_target):
|
||||
continue
|
||||
for i in range(2):
|
||||
bpy.ops.object.correctivesmooth_bind(
|
||||
{"object": obj_target, "active_object": obj_target},
|
||||
{"object": target_obj, "active_object": target_obj},
|
||||
modifier=mod.name,
|
||||
)
|
||||
|
||||
@ -298,33 +296,30 @@ def get_constraints(obj, task_layer_name, new_transfer_data):
|
||||
transfer_info.obj = obj
|
||||
|
||||
|
||||
def transfer_constraint(transfer_info, obj_target):
|
||||
def transfer_constraint(transfer_info, target_obj, source_obj):
|
||||
# remove old and sync existing modifiers
|
||||
obj_source = transfer_info.id_data
|
||||
if obj_source == obj_target:
|
||||
return
|
||||
old_mod = obj_target.constraints.get(transfer_info.name)
|
||||
old_mod = target_obj.constraints.get(transfer_info.name)
|
||||
if old_mod:
|
||||
obj_target.constraints.remove(old_mod)
|
||||
target_obj.constraints.remove(old_mod)
|
||||
|
||||
# transfer new modifiers
|
||||
for i, constraint in enumerate(obj_source.constraints):
|
||||
for i, constraint in enumerate(source_obj.constraints):
|
||||
if constraint.name == transfer_info.name:
|
||||
constraint_new = obj_target.constraints.new(constraint.type)
|
||||
constraint_new = target_obj.constraints.new(constraint.type)
|
||||
constraint_new.name = constraint.name
|
||||
# sort new modifier at correct index (default to beginning of the stack)
|
||||
idx = 0
|
||||
if i > 0:
|
||||
name_prev = obj_source.constraints[i - 1].name
|
||||
name_prev = source_obj.constraints[i - 1].name
|
||||
for target_mod_i, target_constraint in enumerate(
|
||||
obj_target.constraints
|
||||
target_obj.constraints
|
||||
):
|
||||
if target_constraint.name == name_prev:
|
||||
idx = target_mod_i + 1
|
||||
bpy.ops.constraint.move_to_index(
|
||||
{'object': obj_target}, constraint=constraint_new.name, index=idx
|
||||
{'object': target_obj}, constraint=constraint_new.name, index=idx
|
||||
)
|
||||
constraint_target = obj_target.constraints.get(constraint.name)
|
||||
constraint_target = target_obj.constraints.get(constraint.name)
|
||||
props = [
|
||||
p.identifier for p in constraint.bl_rna.properties if not p.is_readonly
|
||||
]
|
||||
@ -366,42 +361,39 @@ def get_material_slots(obj, task_layer_name, new_transfer_data):
|
||||
transfer_info.obj = obj
|
||||
|
||||
|
||||
def transfer_material_slot(transfer_info, obj_target):
|
||||
obj_source = transfer_info.id_data
|
||||
if obj_source == obj_target:
|
||||
return
|
||||
def transfer_material_slot(transfer_info, target_obj, source_obj):
|
||||
# Delete existing material slot if exists
|
||||
for idx in range(len(obj_source.material_slots)):
|
||||
slot = obj_source.material_slots[idx]
|
||||
for idx in range(len(source_obj.material_slots)):
|
||||
slot = source_obj.material_slots[idx]
|
||||
if asset_suffix.get_basename(slot.material.name) == transfer_info.name:
|
||||
obj_target.active_material_index = idx
|
||||
bpy.ops.object.material_slot_remove({"object": obj_target})
|
||||
target_obj.active_material_index = idx
|
||||
bpy.ops.object.material_slot_remove({"object": target_obj})
|
||||
|
||||
# Transfer material slots
|
||||
|
||||
for idx in range(len(obj_source.material_slots)):
|
||||
if idx >= len(obj_target.material_slots):
|
||||
slot = obj_source.material_slots[idx]
|
||||
for idx in range(len(source_obj.material_slots)):
|
||||
if idx >= len(target_obj.material_slots):
|
||||
slot = source_obj.material_slots[idx]
|
||||
if asset_suffix.get_basename(slot.material.name) == transfer_info.name:
|
||||
bpy.ops.object.material_slot_add({"object": obj_target})
|
||||
obj_target.material_slots[idx].link = obj_source.material_slots[
|
||||
bpy.ops.object.material_slot_add({"object": target_obj})
|
||||
target_obj.material_slots[idx].link = source_obj.material_slots[
|
||||
idx
|
||||
].link
|
||||
obj_target.material_slots[idx].material = obj_source.material_slots[
|
||||
target_obj.material_slots[idx].material = source_obj.material_slots[
|
||||
idx
|
||||
].material
|
||||
|
||||
# Transfer active material slot index
|
||||
obj_target.active_material_index = obj_source.active_material_index
|
||||
target_obj.active_material_index = source_obj.active_material_index
|
||||
|
||||
# Transfer material slot assignments for curve
|
||||
if obj_target.type == "CURVE":
|
||||
for spl_to, spl_from in zip(obj_target.data.splines, obj_source.data.splines):
|
||||
if target_obj.type == "CURVE":
|
||||
for spl_to, spl_from in zip(target_obj.data.splines, source_obj.data.splines):
|
||||
spl_to.material_index = spl_from.material_index
|
||||
|
||||
# Rest of the loop applies only to meshes.
|
||||
if obj_target.type == "MESH":
|
||||
if target_obj.type == "MESH":
|
||||
# Transfer material slot assignments for mesh
|
||||
for pol_to, pol_from in zip(obj_target.data.polygons, obj_source.data.polygons):
|
||||
for pol_to, pol_from in zip(target_obj.data.polygons, source_obj.data.polygons):
|
||||
pol_to.material_index = pol_from.material_index
|
||||
pol_to.use_smooth = pol_from.use_smooth
|
||||
|
Loading…
Reference in New Issue
Block a user