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.
13 changed files with 75 additions and 73 deletions
Showing only changes of commit f433baa3fb - Show all commits

View File

@ -34,15 +34,15 @@ This Add-On was designed to allow multiple artists to collaborate while contribu
## Key Concepts
**Task Layers** Task Layers are defined in a JSON file that describes the number of layers used to manage the asset. Typically each task layer is given it's own file, artists can optionally house multiple task layers inside the same file if required. Each task layer is used to describe a step in the asset making process (e.g."Modeling", "Rigging", "Shading"). The number and content of a task layer is fully customizable by the artist.
**Ownership** Each piece of data in the Asset Pipeline is owned by a task layer, this includes Objects, Task Layer Collections and Transfer Data. The owner of data is the only person who can contribute to that piece of data, including modifying or removing that data. Objects implicitly will own the meshes and other types of object data, multiple objects referencing the same mesh is not supported.
**Ownership** Each piece of data in the Asset Pipeline is owned by a task layer, this includes Objects, Task Layer Collections and Transferable Data. The owner of data is the only person who can contribute to that piece of data, including modifying or removing that data. Objects implicitly will own the meshes and other types of object data, multiple objects referencing the same mesh is not supported.
**Asset Collection** Is the top-level collection for a given asset, all relevant objects/sub-collections for the asset are contained within this collection.
**Task Layer Collection** These collections are children of the asset collection, each Task Layer collection is owned by a specific task layer, they are all top-level child collections to the Asset Collection. Children of the Task Layer collections are owned by the Task Layer collection's owner.
**Transfer Data** Is data that a part or associated with an object or mesh, but can be explicitly owned and updated. This is the key concept that allows multiple artists to contribute to an asset. During the Push/Pull process transfer data is applied on top of each object, allowing artist A to own an object but artist B to own the vertex groups on that object for example.
**Transferable Data** Is data that a part or associated with an object or mesh, but can be explicitly owned and updated. This is the key concept that allows multiple artists to contribute to an asset. During the Push/Pull process Transferable Data is applied on top of each object, allowing artist A to own an object but artist B to own the vertex groups on that object for example.
Transfer Data Types:
Transferable Data Types:
- Vertex Groups
- Modifiers
- Constraints
@ -90,12 +90,12 @@ When you Push/Pull a file, you will be greeted with an operator dialogue. This d
The add-on will optionally save your current file plus any unsaved/unpacked images will be saved in a directory relative to your asset (configurable in the add-on preferences). It will always create a back-up of your current file, in the case where the merge process fails, you will be prompted to revert your file back to it's pre-merge status.
### 3. Merge with Published File
Push and Pull are merging operations done to/from the published file. When you want to share your updated work to the rest of the team select "Push to Publish" to update the published file with your changes. Push will update any Transfer data you edited, and update any objects/collections you own with the version in your current file. Transfer Data owned by other artists will be re-applied to your objects.
Push and Pull are merging operations done to/from the published file. When you want to share your updated work to the rest of the team select "Push to Publish" to update the published file with your changes. Push will update any Transferable Data you edited, and update any objects/collections you own with the version in your current file. Transferable Data owned by other artists will be re-applied to your objects.
If another artist then uses the "Pull to Publish" operator the same process will occur, keeping all objects, collections and transfer data that is local to their file, and importing any data that was owned externally by other task layers.
If another artist then uses the "Pull to Publish" operator the same process will occur, keeping all objects, collections and Transferable Data that is local to their file, and importing any data that was owned externally by other task layers.
## Surrendering Ownership
In the ownership inspector each Object/Transfer Data item has an option to "surrender" that piece of data. When surrendering this piece of data is now "up for grabs" to all other task layers. After surrendering artists will need to push this update to the published file. The surrendered item's ownership indicator will be replaced by an "Update Surrendered" operator, this operator is available to all task layers except the one that surrendered that data. When another task layer pulls in from the publish, they will be able to run the "Update Surrendered" operator to claim it assigning it to that task layer.
In the ownership inspector each Object/Transferable Data item has an option to "surrender" that piece of data. When surrendering this piece of data is now "up for grabs" to all other task layers. After surrendering artists will need to push this update to the published file. The surrendered item's ownership indicator will be replaced by an "Update Surrendered" operator, this operator is available to all task layers except the one that surrendered that data. When another task layer pulls in from the publish, they will be able to run the "Update Surrendered" operator to claim it assigning it to that task layer.
## Publish New Version
To Publish a new version of an asset select the "Publish New Version" operator. The operator dialogue will require an input on which publish type to create. Publish types are as follows.

View File

@ -214,7 +214,7 @@ class AssetTransferMapping:
# THIS IS FOR WHEN SURRENDERED DATA HAS BEEN REPLACED
obj = transfer_data_item.id_data
other_obj = bpy.data.objects.get(merge_get_target_name(obj.name))
# Find Related Transfer Data Item on Target/Source Object
# Find Related Transferable Data Item on Target/Source Object
for other_obj_transfer_data_item in other_obj.transfer_data_ownership:
if task_layer_prefix_basename_get(
other_obj_transfer_data_item.name

View File

@ -25,10 +25,10 @@ def ownership_transfer_data_cleanup(
asset_pipe: 'bpy.types.AssetPipeline',
obj: bpy.types.Object,
) -> None:
"""Remove Transfer Data ownership items if the corrisponding data is missing
"""Remove Transferable Data ownership items if the corrisponding data is missing
Args:
obj (bpy.types.Object): Object that contains the transfer data
obj (bpy.types.Object): Object that contains the Transferable Data
"""
local_task_layer_keys = asset_pipe.get_local_task_layers()
transfer_data = obj.transfer_data_ownership
@ -46,7 +46,7 @@ def ownership_get(
local_col: bpy.types.Collection,
scene: bpy.types.Scene,
) -> None:
"""Find new transfer data owned by the local task layer.
"""Find new Transferable Data owned by the local task layer.
Marks items as owned by the local task layer if they are in the
corrisponding task layer collection and have no owner.
@ -88,8 +88,8 @@ def ownership_get(
def ownership_set(temp_transfer_data: bpy.types.CollectionProperty) -> None:
"""Add new transfer data items on each object found in the
temp transfer data collection property
"""Add new Transferable Data items on each object found in the
temp Transferable Data collection property
Args:
temp_transfer_data (bpy.types.CollectionProperty): Collection property containing newly found
@ -152,11 +152,11 @@ def merge_task_layer(
) -> None:
"""Combines data from an external task layer collection in the local
task layer collection. By finding the owner of each collection,
object and transfer data item and keeping each layer of data via a copy
object and Transferable Data item and keeping each layer of data via a copy
from it's respective owners.
This ensures that objects owned by an external task layer will always be kept
linked into the scene, and any local transfer data like a modifier will be applied
linked into the scene, and any local Transferable Data like a modifier will be applied
ontop of that external object of vice versa. Ownership is stored in an objects properties,
and map is created to match each object to it's respective owner.
@ -183,7 +183,7 @@ def merge_task_layer(
error_msg = ''
if len(map.conflict_transfer_data) != 0:
for conflict in map.conflict_transfer_data:
error_msg += f"Transfer Data conflict found for '{conflict.name}' on obj '{conflict.id_data.name}'\n"
error_msg += f"Transferable Data conflict found for '{conflict.name}' on obj '{conflict.id_data.name}'\n"
return error_msg
if len(map.conflict_ids) != 0:
@ -194,7 +194,7 @@ def merge_task_layer(
)
return error_msg
# Remove all transfer data from target objects
# Remove all Transferable Data from target objects
for source_obj in map.object_map:
if source_obj.data and source_obj.data.users > 1:
error_msg += f"Object {source_obj.name} contains multi-user datablock'\n"

View File

@ -161,7 +161,7 @@ def task_layer_prefix_name_get(name: str, task_layer_owner: str) -> str:
def task_layer_prefix_basename_get(name: str) -> str:
"""Get the base of a name if it contains a task layer prefix.
This prefix is set on some transfer data items, this functions
This prefix is set on some Transferable Data items, this functions
removes the prefixes and returns the basename
Args:
@ -187,7 +187,7 @@ def task_layer_prefix_transfer_data_update(
name of the actual data the transfer_data_item is referring to.
Args:
transfer_data_item (bpy.types.CollectionProperty): Transfer Data Item that is named with prefix
transfer_data_item (bpy.types.CollectionProperty): Transferable Data Item that is named with prefix
Returns:
bool: Returns True if a change to the name was completed

View File

@ -49,7 +49,7 @@ def draw_task_layer_selection(
- When a user is overriding or the object is new (using default ownership): "Show All Task Layers"
Args:
layout (bpy.types.UILayout): Any UI Layout element like self.layout or row
data (bpy.types.CollectionProperty or bpy.types.ID): Object, Collection or Transfer Data Item
data (bpy.types.CollectionProperty or bpy.types.ID): Object, Collection or Transferable Data Item
show_all_task_layers (bool, optional): Used when user is overriding or default ownership is set. Defaults to False.
show_local_task_layers (bool, optional): Force Showing Local Task Layers Only. Defaults to False.
text (str, optional): Title of prop search. Defaults to "".
@ -65,7 +65,7 @@ def draw_task_layer_selection(
else:
data_owner_name = "asset_id_owner"
# Get the current data owner from OBJ/COL or Transfer Data Item if it hasn't been passed
# Get the current data owner from OBJ/COL or Transferable Data Item if it hasn't been passed
if current_data_owner is None:
current_data_owner = data.get(data_owner_name)

View File

@ -21,11 +21,11 @@ from .transfer_util import (
def copy_transfer_data_ownership(
transfer_data_item, target_obj: bpy.types.Object
) -> None:
"""Copy transfer data item to object if non entry exists
"""Copy Transferable Data item to object if non entry exists
Args:
transfer_data_item: Item of bpy.types.CollectionProperty from source object
target_obj (bpy.types.Object): Object to add transfer data item to
target_obj (bpy.types.Object): Object to add Transferable Data item to
"""
transfer_data = target_obj.transfer_data_ownership
matches = check_transfer_data_entry(
@ -53,7 +53,7 @@ def transfer_data_clean(obj):
def transfer_data_is_missing(transfer_data_item) -> bool:
"""Check if Transfer Data item is missing
"""Check if Transferable Data item is missing
Args:
transfer_data_item: Item of class ASSET_TRANSFER_DATA
@ -75,10 +75,10 @@ def init_transfer_data(
scene: bpy.types.Scene,
obj: bpy.types.Object,
):
"""Collect Transfer Data Items on a given object
"""Collect Transferable Data Items on a given object
Args:
obj (bpy.types.Object): Target object for transfer data
obj (bpy.types.Object): Target object for Transferable Data
task_layer_name (str): Name of task layer
temp_transfer_data: Item of class ASSET_TRANSFER_DATA_TEMP
"""
@ -92,9 +92,9 @@ def init_transfer_data(
def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
"""Apply all transfer data from transfer data map onto objects.
Copies any transfer data owned by local layer onto objects owned by external layers.
Applies transfer data from external layers onto objects owned by local layers
"""Apply all Transferable Data from Transferable Data map onto objects.
Copies any Transferable Data owned by local layer onto objects owned by external layers.
Applies Transferable Data from external layers onto objects owned by local layers
Transfer_data_map is generated by class 'AssetTransferMapping'
@ -112,7 +112,7 @@ def apply_transfer_data(context: bpy.types.Context, transfer_data_map) -> None:
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_data_item.id_data.name}")
print(f"Failed to Transferable Data for {transfer_data_item.id_data.name}")
continue
if transfer_data_item is None:
continue

View File

@ -14,7 +14,7 @@ def materials_clean(obj):
constants.MATERIAL_SLOT_KEY,
)
# Clear Materials if No Transfer Data is Found
# Clear Materials if No Transferable Data is Found
if len(matches) != 0:
return

View File

@ -6,7 +6,7 @@ from ..task_layer import draw_task_layer_selection
def draw_transfer_data_type(
layout: bpy.types.UILayout, transfer_data: bpy.types.CollectionProperty
) -> None:
"""Draw UI Element for items of a transfer data type"""
"""Draw UI Element for items of a Transferable Data type"""
asset_pipe = bpy.context.scene.asset_pipeline
if transfer_data == []:
return
@ -60,7 +60,7 @@ def draw_transfer_data_type(
def draw_transfer_data(
transfer_data: bpy.types.CollectionProperty, layout: bpy.types.UILayout
) -> None:
"""Draw UI List of Transfer Data"""
"""Draw UI List of Transferable Data"""
vertex_groups = []
# vertex_colors = []
material_slots = []

View File

@ -6,12 +6,12 @@ from ..task_layer import get_transfer_data_owner
def check_transfer_data_entry(
transfer_data: bpy.types.CollectionProperty, key: str, td_type_key: str
) -> set:
"""Verifies if transfer data entry exists
"""Verifies if Transferable Data entry exists
Args:
ownership (bpy.types.CollectionProperty): Transfer Data of an object
ownership (bpy.types.CollectionProperty): Transferable Data of an object
key (str): Name of item that is being verified
td_type_key (str): Type of transfer data
td_type_key (str): Type of Transferable Data
Returns:
set: Returns set of matches where name is found in ownership
@ -31,12 +31,12 @@ def transfer_data_add_entry(
task_layer_name: str,
surrender: bool,
):
"""Add entry to transfer data ownership
"""Add entry to Transferable Data ownership
Args:
ownership (bpy.types.CollectionProperty): Transfer Data of an object
name (str): Name of new transfer data item
td_type_key (str): Type of transfer data
ownership (bpy.types.CollectionProperty): Transferable Data of an object
name (str): Name of new Transferable Data item
td_type_key (str): Type of Transferable Data
task_layer_name (str): Name of current task layer
"""
transfer_data_item = transfer_data.add()
@ -52,9 +52,9 @@ def transfer_data_clean(
):
"""Removes data if a transfer_data_item doesn't exist but the data does exist
Args:
obj (bpy.types.Object): Object containing transfer data
data_list (bpy.types.CollectionProperty): Collection Property containing a type of possible transfer data e.g. obj.modifiers
td_type_key (str): Key for the transfer data type
obj (bpy.types.Object): Object containing Transferable Data
data_list (bpy.types.CollectionProperty): Collection Property containing a type of possible Transferable Data e.g. obj.modifiers
td_type_key (str): Key for the Transferable Data type
"""
for item in data_list:
matches = check_transfer_data_entry(
@ -72,9 +72,9 @@ def transfer_data_item_is_missing(
"""Returns true if a transfer_data_item exists the data doesn't exist
Args:
transfer_data_item (_type_): Item of Transfer Data
data_list (bpy.types.CollectionProperty): Collection Property containing a type of possible transfer data e.g. obj.modifiers
td_type_key (str): Key for the transfer data type
transfer_data_item (_type_): Item of Transferable Data
data_list (bpy.types.CollectionProperty): Collection Property containing a type of possible Transferable Data e.g. obj.modifiers
td_type_key (str): Key for the Transferable Data type
Returns:
bool: Returns True if transfer_data_item is missing
"""
@ -84,8 +84,8 @@ def transfer_data_item_is_missing(
return True
"""Intilize transfer data to a temporary collection property, used
to draw a display of new transfer data to the user before merge process.
"""Intilize Transferable Data to a temporary collection property, used
to draw a display of new Transferable Data to the user before merge process.
"""
@ -99,9 +99,9 @@ def transfer_data_item_init(
Args:
scene (bpy.types.Scene): Scene that contains a the file's asset
obj (bpy.types.Object): Object containing possible transfer data
data_list (bpy.types.CollectionProperty): Collection Property containing a type of possible transfer data e.g. obj.modifiers
td_type_key (str): Key for the transfer data type
obj (bpy.types.Object): Object containing possible Transferable Data
data_list (bpy.types.CollectionProperty): Collection Property containing a type of possible Transferable Data e.g. obj.modifiers
td_type_key (str): Key for the Transferable Data type
"""
asset_pipe = scene.asset_pipeline
transfer_data = obj.transfer_data_ownership

View File

@ -102,7 +102,7 @@ def traverse_collection_tree(
def data_type_from_transfer_data_key(obj: bpy.types.Object, td_type: str):
"""Returns the data on an object that is referred to by the transfer data type"""
"""Returns the data on an object that is referred to by the Transferable Data type"""
if td_type == constants.VERTEX_GROUP_KEY:
return obj.vertex_groups
if td_type == constants.MODIFIER_KEY:

View File

@ -235,16 +235,16 @@ class ASSETPIPE_OT_create_new_asset(bpy.types.Operator):
class ASSETPIPE_OT_update_ownership(bpy.types.Operator):
bl_idname = "assetpipe.update_ownership"
bl_label = "Update Ownership"
bl_description = """Update the Ownership of Objects and Transfer Data"""
bl_description = """Update the Ownership of Objects and Transferable Data"""
_temp_transfer_data = None
_invalid_objs = []
_other_ids = []
expand: bpy.props.BoolProperty(
name="Show New Transfer Data",
name="Show New Transferable Data",
default=False,
description="Show New Transfer Data",
description="Show New Transferable Data",
)
def invoke(self, context: bpy.types.Context, event: bpy.types.Event):
@ -273,9 +273,9 @@ class ASSETPIPE_OT_sync_pull(bpy.types.Operator):
_sync_target: Path = None
expand: bpy.props.BoolProperty(
name="Show New Transfer Data",
name="Show New Transferable Data",
default=False,
description="Show New Transfer Data",
description="Show New Transferable Data",
)
save: bpy.props.BoolProperty(
name="Save File & Images",
@ -316,9 +316,9 @@ class ASSETPIPE_OT_sync_push(bpy.types.Operator):
_sync_target: Path = None
expand: bpy.props.BoolProperty(
name="Show New Transfer Data",
name="Show New Transferable Data",
default=False,
description="Show New Transfer Data",
description="Show New Transferable Data",
)
pull: bpy.props.BoolProperty(
name="Pull before Pushing",
@ -416,7 +416,7 @@ class ASSETPIPE_OT_reset_ownership(bpy.types.Operator):
bl_idname = "assetpipe.reset_ownership"
bl_label = "Reset Ownership"
bl_description = (
"""Reset the Object owner and transfer data on selected object(s)"""
"""Reset the Object owner and Transferable Data on selected object(s)"""
)
@classmethod
@ -507,7 +507,7 @@ class ASSETPIPE_OT_revert_file(bpy.types.Operator):
class ASSETPIPE_OT_fix_prefixes(bpy.types.Operator):
bl_idname = "assetpipe.fix_prefixes"
bl_label = "Fix Prefixes"
bl_description = """Fix Prefixes for Modifiers and Constraints so they match Transfer Data Owner on selected object(s)"""
bl_description = """Fix Prefixes for Modifiers and Constraints so they match Transferable Data Owner on selected object(s)"""
_updated_prefix = False
@ -577,9 +577,11 @@ class ASSETPIPE_OT_update_surrendered_object(bpy.types.Operator):
class ASSETPIPE_OT_update_surrendered_transfer_data(bpy.types.Operator):
bl_idname = "assetpipe.update_surrendered_transfer_data"
bl_label = "Claim Surrendered"
bl_description = """Claim Surrended Transfer Data Owner"""
bl_description = """Claim Surrended Transferable Data Owner"""
transfer_data_item_name: bpy.props.StringProperty(name="Transfer Data Item Name")
transfer_data_item_name: bpy.props.StringProperty(
name="Transferable Data Item Name"
)
_surrendered_transfer_data = None
_old_onwer = ""
@ -607,7 +609,7 @@ class ASSETPIPE_OT_update_surrendered_transfer_data(bpy.types.Operator):
if self._surrendered_transfer_data.owner == self._old_onwer:
self.report(
{'ERROR'},
f"Transfer Data Owner was not updated",
f"Transferable Data Owner was not updated",
)
return {'CANCELLED'}
self._surrendered_transfer_data.surrender = False
@ -626,7 +628,7 @@ class ASSETPIPE_OT_batch_ownership_change(bpy.types.Operator):
name_filter: bpy.props.StringProperty(
name="Filter by Name",
description="Filter Object or Transfer Data items by name",
description="Filter Object or Transferable Data items by name",
default="",
)
@ -649,7 +651,7 @@ class ASSETPIPE_OT_batch_ownership_change(bpy.types.Operator):
(
'TRANSFER_DATA',
"Transferable Data",
"Update Owner of Transfer Data within Objects",
"Update Owner of Transferable Data within Objects",
),
),
)
@ -682,7 +684,7 @@ class ASSETPIPE_OT_batch_ownership_change(bpy.types.Operator):
surrender_selection: bpy.props.BoolProperty(
name="Set Surrender",
default=False,
description="Surrender can only be set on objects/transfer data that are locally owned. Ownership cannot be changed while surrendering",
description="Surrender can only be set on objects/Transferable Data that are locally owned. Ownership cannot be changed while surrendering",
)
def _filter_by_name(self, context, unfiltered_list: []):
@ -792,7 +794,7 @@ class ASSETPIPE_OT_batch_ownership_change(bpy.types.Operator):
length = len(objs) if objs else 0
else:
transfer_data_items_to_update = self._get_transfer_data_to_update(context)
data_type_name = "Transfer Data Item(s)"
data_type_name = "Transferable Data Item(s)"
length = (
len(transfer_data_items_to_update)
if transfer_data_items_to_update

View File

@ -30,7 +30,7 @@ class AssetTransferData(bpy.types.PropertyGroup):
owner: bpy.props.StringProperty(name="Owner", default="NONE")
type: bpy.props.EnumProperty(
name="Transfer Data Type",
name="Transferable Data Type",
items=constants.TRANSFER_DATA_TYPES_ENUM_ITEMS,
)
surrender: bpy.props.BoolProperty(name="Surrender Ownership", default=False)
@ -42,7 +42,7 @@ class AssetTransferDataTemp(bpy.types.PropertyGroup):
owner: bpy.props.StringProperty(name="OwneAr", default="NONE")
type: bpy.props.EnumProperty(
name="Transfer Data Type",
name="Transferable Data Type",
items=constants.TRANSFER_DATA_TYPES_ENUM_ITEMS,
)
surrender: bpy.props.BoolProperty(name="Surrender Ownership", default=False)
@ -127,7 +127,7 @@ class AssetPipeline(bpy.types.PropertyGroup):
def get_local_task_layers(self):
return [task_layer.name for task_layer in self.local_task_layers]
# UI BOOLS: used to show/hide transfer data elements
# UI BOOLS: used to show/hide Transferable Data elements
# The names are also hard coded in constants.py under TRANSFER_DATA_TYPES
# any changes will need to be reflected both here and in that enum
group_vertex_ui_bool: bpy.props.BoolProperty(

View File

@ -73,12 +73,12 @@ def sync_draw(self, context):
)
if len(self._temp_transfer_data) == 0:
layout.label(text="No new local Transfer Data found")
layout.label(text="No new local Transferable Data found")
else:
layout.label(text="New local Transfer Data will be Pushed to Publish")
layout.label(text="New local Transferable Data will be Pushed to Publish")
row = layout.row()
row.prop(self, "expand", text="", icon="COLLAPSEMENU", toggle=False)
row.label(text="Show New Transfer Data")
row.label(text="Show New Transferable Data")
objs = [transfer_data_item.obj for transfer_data_item in self._temp_transfer_data]
if not self.expand: