Asset Pipeline v2 #145

Closed
Nick Alberelli wants to merge 431 commits from (deleted):feature/asset-pipeline-v2 into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
3 changed files with 153 additions and 146 deletions
Showing only changes of commit 186d114a18 - Show all commits

View File

@ -3,6 +3,7 @@ from typing import Dict, Set
from . import asset_suffix from . import asset_suffix
from . import constants from . import constants
from .transfer_data import transfer_core
class AssetTransferMapping: class AssetTransferMapping:
@ -126,50 +127,43 @@ class AssetTransferMapping:
def _gen_transfer_data_map(self): def _gen_transfer_data_map(self):
transfer_data_map: Dict[bpy.types.Collection, bpy.types.Collection] = {} transfer_data_map: Dict[bpy.types.Collection, bpy.types.Collection] = {}
remove_transfer_data = [] temp_transfer_data = bpy.context.scene.temp_transfer_data_ownership
for obj in self._external_col.all_objects: for source_obj in self.object_map:
# TODO Remove any tansfer_info that is on an external obj but owned by the local TL target_obj = self.object_map[source_obj]
# TODO this works on pull not push FIX! objs = [source_obj, target_obj]
# TODO Just do the opposite of this in the local collection for obj in objs:
for transfer_info in obj.transfer_data_ownership: if obj.name.endswith(constants.LOCAL_SUFFIX):
if transfer_info.owner in self._local_tls: for transfer_info in obj.transfer_data_ownership:
remove_transfer_data.append(transfer_info.name) if transfer_info.owner in self._local_tls:
if ( temp_info = transfer_core.transfer_data_add_entry(
transfer_info.owner not in self._local_tls transfer_data=temp_transfer_data,
and transfer_info.owner != "NONE" name=transfer_info.name,
): td_type=transfer_info.type,
name = transfer_info.name + '_' + obj.name task_layer_name=transfer_info.owner,
target_obj_name = asset_suffix.get_target_name(obj.name) )
target_obj = self._local_col.all_objects.get(target_obj_name) name = transfer_info.name + '_' + obj.name
transfer_data_map[name] = (transfer_info, target_obj) transfer_data_map[name] = {
'transfer_info': temp_info,
for name in remove_transfer_data: 'source_obj': obj,
# TODO FIX THIS 'target_obj': target_obj,
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
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 return transfer_data_map

View File

@ -79,41 +79,61 @@ def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
context (bpy.types.Context): context of .blend file context (bpy.types.Context): context of .blend file
transfer_data_map: Map generated by class AssetTransferMapping 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: for name in transfer_data_map:
transfer_data = transfer_data_map[name] transfer_data = transfer_data_map[name]
transfer_info = transfer_data[0] transfer_info = transfer_data.get('transfer_info')
target_obj = transfer_data[1] target_obj = transfer_data.get('target_obj')
source_obj = transfer_data.get('source_obj')
if target_obj is None: if target_obj is None:
print(f"Failed to Transfer data for {transfer_info.id_data.name}") print(f"Failed to Transfer data for {transfer_info.id_data.name}")
continue continue
if transfer_info.type == constants.VERTEX_GROUP_KEY: if source_obj != target_obj:
print(f"Transfering Data {constants.VERTEX_GROUP_KEY}: {name}") if transfer_info.type == constants.VERTEX_GROUP_KEY:
transfer_functions.transfer_vertex_group( print(f"Transfering Data {constants.VERTEX_GROUP_KEY}: {name}")
context=context, transfer_functions.transfer_vertex_group(
vertex_group_name=transfer_info.name, context=context,
obj_target=target_obj, vertex_group_name=transfer_info.name,
obj_source=transfer_info.id_data, target_obj=target_obj,
) source_obj=source_obj,
if transfer_info.type == constants.VERTEX_COLOR_KEY: )
transfer_functions.transfer_vertex_color( if transfer_info.type == constants.VERTEX_COLOR_KEY:
vertex_color_name=transfer_info.name, transfer_functions.transfer_vertex_color(
obj_target=target_obj, vertex_color_name=transfer_info.name,
obj_source=transfer_info.id_data, target_obj=target_obj,
) source_obj=source_obj,
if transfer_info.type == constants.MODIFIER_KEY: )
print(f"Transfering Data {constants.MODIFIER_KEY}: {name}") if transfer_info.type == constants.MODIFIER_KEY:
transfer_functions.transfer_modifier(transfer_info, target_obj) print(f"Transfering Data {constants.MODIFIER_KEY}: {name}")
if transfer_info.type == constants.CONSTRAINT_KEY: transfer_functions.transfer_modifier(
transfer_functions.transfer_constraint(transfer_info, target_obj) transfer_info=transfer_info,
if transfer_info.type == constants.MATERIAL_SLOT_KEY: target_obj=target_obj,
print(f"Transfering Data {constants.MATERIAL_SLOT_KEY}: {name}") source_obj=source_obj,
transfer_functions.transfer_material_slot(transfer_info, target_obj) )
if transfer_info.type == constants.UV_LAYERS_KEY: if transfer_info.type == constants.CONSTRAINT_KEY:
transfer_functions.transfer_uv_layer( transfer_functions.transfer_constraint(
obj_target=target_obj, transfer_info=transfer_info,
obj_source=transfer_info.id_data, target_obj=target_obj,
uv_name=transfer_info.name, 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( copy_transfer_data_ownership(
transfer_data_item=transfer_info, transfer_data_item=transfer_info,
@ -160,6 +180,7 @@ def transfer_data_add_entry(
transfer_info.name = name transfer_info.name = name
transfer_info.owner = task_layer_name.upper() transfer_info.owner = task_layer_name.upper()
transfer_info.type = td_type transfer_info.type = td_type
return transfer_info
def copy_transfer_data(source_data, target_data): def copy_transfer_data(source_data, target_data):

View File

@ -5,6 +5,7 @@ from .. import asset_suffix, constants
## FUNCTIONS SPECFIC TO TRANSFER DATA TYPES ## FUNCTIONS SPECFIC TO TRANSFER DATA TYPES
# TODO Remove reliance on transfer_info for 'transfer' functions
def vertex_groups_clean(obj): def vertex_groups_clean(obj):
@ -41,20 +42,20 @@ def get_vertex_groups(obj, task_layer_name, new_transfer_data):
def transfer_vertex_group( def transfer_vertex_group(
context, context,
vertex_group_name: str, vertex_group_name: str,
obj_target: bpy.types.Object, target_obj: bpy.types.Object,
obj_source: bpy.types.Object, source_obj: bpy.types.Object,
): ):
if obj_target == obj_source: if target_obj == source_obj:
return return
if obj_target.vertex_groups.get(vertex_group_name): if target_obj.vertex_groups.get(vertex_group_name):
obj_target.vertex_groups.remove(obj_target.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 = context.copy()
override["selected_editable_objects"] = [obj_target, obj_source] override["selected_editable_objects"] = [target_obj, source_obj]
override["active_object"] = obj_source override["active_object"] = source_obj
override["object"] = obj_source override["object"] = source_obj
with context.temp_override(**override): with context.temp_override(**override):
bpy.ops.object.data_transfer( bpy.ops.object.data_transfer(
data_type="VGROUP_WEIGHTS", data_type="VGROUP_WEIGHTS",
@ -104,17 +105,17 @@ def get_vertex_colors(obj, task_layer_name, new_transfer_data):
def transfer_vertex_color( def transfer_vertex_color(
vertex_color_name: str, vertex_color_name: str,
obj_target: bpy.types.Object, target_obj: bpy.types.Object,
obj_source: 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: if old_color:
obj_target.data.vertex_colors.remove(old_color) target_obj.data.vertex_colors.remove(old_color)
transfer_color = obj_source.data.vertex_colors.get(vertex_color_name) transfer_color = source_obj.data.vertex_colors.get(vertex_color_name)
new_color = obj_target.data.vertex_colors.new( new_color = target_obj.data.vertex_colors.new(
name=transfer_color.name, do_init=False 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 new_color.data[loop.index].color = transfer_color.data[loop.index].color
# ABOVE FOR LOOP IS FOR TOPOLOGY THAT MATCHES # ABOVE FOR LOOP IS FOR TOPOLOGY THAT MATCHES
# BELOW COMMENTED OUT CODE IS FOR TOPOLOGY THAT DOESN'T MATCH # 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 transfer_info.obj = obj
def transfer_uv_layer(obj_source, obj_target, uv_name): def transfer_uv_layer(source_obj, target_obj, uv_name):
old_uv_layer = obj_target.data.uv_layers.get(uv_name) old_uv_layer = target_obj.data.uv_layers.get(uv_name)
if old_uv_layer: 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) transfer_uv = source_obj.data.uv_layers.get(uv_name)
new_uv = obj_target.data.uv_layers.new(name=uv_name, do_init=False) new_uv = target_obj.data.uv_layers.new(name=uv_name, do_init=False)
for loop in obj_target.data.loops: for loop in target_obj.data.loops:
new_uv.data[loop.index].uv = transfer_uv.data[loop.index].uv new_uv.data[loop.index].uv = transfer_uv.data[loop.index].uv
# BELOW CODE IS FOR NON MATCHING TOPOLOGY # BELOW CODE IS FOR NON MATCHING TOPOLOGY
# else: # 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') # transfer_corner_data(obj_source, obj_target, uv_from.data, uv_to.data, data_suffix = 'uv')
# Make sure correct layer is set to active # 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: 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 break
@ -211,43 +212,40 @@ def get_modifiers(obj, task_layer_name, new_transfer_data):
transfer_info.obj = obj 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 # remove old and sync existing modifiers
obj_source = transfer_info.id_data old_mod = target_obj.modifiers.get(transfer_info.name)
if obj_source == obj_target:
return
old_mod = obj_target.modifiers.get(transfer_info.name)
if old_mod: if old_mod:
obj_target.modifiers.remove(old_mod) target_obj.modifiers.remove(old_mod)
# transfer new modifiers # 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: 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) # sort new modifier at correct index (default to beginning of the stack)
idx = 0 idx = 0
if i > 0: if i > 0:
name_prev = obj_source.modifiers[i - 1].name name_prev = source_obj.modifiers[i - 1].name
for target_mod_i, target_mod in enumerate(obj_target.modifiers): for target_mod_i, target_mod in enumerate(target_obj.modifiers):
if target_mod.name == name_prev: if target_mod.name == name_prev:
idx = target_mod_i + 1 idx = target_mod_i + 1
bpy.ops.object.modifier_move_to_index( 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] props = [p.identifier for p in mod.bl_rna.properties if not p.is_readonly]
for prop in props: for prop in props:
value = getattr(mod, prop) value = getattr(mod, prop)
setattr(mod_target, prop, value) setattr(mod_target, prop, value)
# rebind modifiers (corr. smooth, surf. deform, mesh deform) # 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 mod.type == 'SURFACE_DEFORM':
if not mod.is_bound: if not mod.is_bound:
continue continue
for i in range(2): for i in range(2):
bpy.ops.object.surfacedeform_bind( bpy.ops.object.surfacedeform_bind(
{"object": obj_target, "active_object": obj_target}, {"object": target_obj, "active_object": target_obj},
modifier=mod.name, modifier=mod.name,
) )
elif mod.type == 'MESH_DEFORM': elif mod.type == 'MESH_DEFORM':
@ -255,7 +253,7 @@ def transfer_modifier(transfer_info, obj_target):
continue continue
for i in range(2): for i in range(2):
bpy.ops.object.meshdeform_bind( bpy.ops.object.meshdeform_bind(
{"object": obj_target, "active_object": obj_target}, {"object": target_obj, "active_object": target_obj},
modifier=mod.name, modifier=mod.name,
) )
elif mod.type == 'CORRECTIVE_SMOOTH': elif mod.type == 'CORRECTIVE_SMOOTH':
@ -263,7 +261,7 @@ def transfer_modifier(transfer_info, obj_target):
continue continue
for i in range(2): for i in range(2):
bpy.ops.object.correctivesmooth_bind( bpy.ops.object.correctivesmooth_bind(
{"object": obj_target, "active_object": obj_target}, {"object": target_obj, "active_object": target_obj},
modifier=mod.name, modifier=mod.name,
) )
@ -298,33 +296,30 @@ def get_constraints(obj, task_layer_name, new_transfer_data):
transfer_info.obj = obj 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 # remove old and sync existing modifiers
obj_source = transfer_info.id_data old_mod = target_obj.constraints.get(transfer_info.name)
if obj_source == obj_target:
return
old_mod = obj_target.constraints.get(transfer_info.name)
if old_mod: if old_mod:
obj_target.constraints.remove(old_mod) target_obj.constraints.remove(old_mod)
# transfer new modifiers # 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: 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 constraint_new.name = constraint.name
# sort new modifier at correct index (default to beginning of the stack) # sort new modifier at correct index (default to beginning of the stack)
idx = 0 idx = 0
if i > 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( for target_mod_i, target_constraint in enumerate(
obj_target.constraints target_obj.constraints
): ):
if target_constraint.name == name_prev: if target_constraint.name == name_prev:
idx = target_mod_i + 1 idx = target_mod_i + 1
bpy.ops.constraint.move_to_index( 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 = [ props = [
p.identifier for p in constraint.bl_rna.properties if not p.is_readonly 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 transfer_info.obj = obj
def transfer_material_slot(transfer_info, obj_target): def transfer_material_slot(transfer_info, target_obj, source_obj):
obj_source = transfer_info.id_data
if obj_source == obj_target:
return
# Delete existing material slot if exists # Delete existing material slot if exists
for idx in range(len(obj_source.material_slots)): for idx in range(len(source_obj.material_slots)):
slot = obj_source.material_slots[idx] slot = source_obj.material_slots[idx]
if asset_suffix.get_basename(slot.material.name) == transfer_info.name: if asset_suffix.get_basename(slot.material.name) == transfer_info.name:
obj_target.active_material_index = idx target_obj.active_material_index = idx
bpy.ops.object.material_slot_remove({"object": obj_target}) bpy.ops.object.material_slot_remove({"object": target_obj})
# Transfer material slots # Transfer material slots
for idx in range(len(obj_source.material_slots)): for idx in range(len(source_obj.material_slots)):
if idx >= len(obj_target.material_slots): if idx >= len(target_obj.material_slots):
slot = obj_source.material_slots[idx] slot = source_obj.material_slots[idx]
if asset_suffix.get_basename(slot.material.name) == transfer_info.name: if asset_suffix.get_basename(slot.material.name) == transfer_info.name:
bpy.ops.object.material_slot_add({"object": obj_target}) bpy.ops.object.material_slot_add({"object": target_obj})
obj_target.material_slots[idx].link = obj_source.material_slots[ target_obj.material_slots[idx].link = source_obj.material_slots[
idx idx
].link ].link
obj_target.material_slots[idx].material = obj_source.material_slots[ target_obj.material_slots[idx].material = source_obj.material_slots[
idx idx
].material ].material
# Transfer active material slot index # 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 # Transfer material slot assignments for curve
if obj_target.type == "CURVE": if target_obj.type == "CURVE":
for spl_to, spl_from in zip(obj_target.data.splines, obj_source.data.splines): for spl_to, spl_from in zip(target_obj.data.splines, source_obj.data.splines):
spl_to.material_index = spl_from.material_index spl_to.material_index = spl_from.material_index
# Rest of the loop applies only to meshes. # Rest of the loop applies only to meshes.
if obj_target.type == "MESH": if target_obj.type == "MESH":
# Transfer material slot assignments for 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.material_index = pol_from.material_index
pol_to.use_smooth = pol_from.use_smooth pol_to.use_smooth = pol_from.use_smooth