Asset Pipeline: Add Support for Asset Catalogs #185

Merged
Nick Alberelli merged 7 commits from TinyNick/blender-studio-pipeline:feature/asset-pipeline-set-catalog into main 2024-01-09 23:28:34 +01:00
6 changed files with 114 additions and 7 deletions

View File

@ -0,0 +1,43 @@
import os
from pathlib import Path
import bpy
asset_file_cache = None
cat_data_cache = None
# TODO add refresh operator
def find_asset_cat_file(directory):
global asset_file_cache
if asset_file_cache is not None:
return asset_file_cache
asset_file = os.path.join(directory, "blender_assets.cats.txt")
if os.path.exists(asset_file):
return asset_file
parent_dir = os.path.dirname(directory)
if parent_dir == directory:
raise FileNotFoundError("blender_assets.cats.txt not found")
return find_asset_cat_file(parent_dir)
def get_asset_cat_enum_items(reload: bool = False):
global cat_data_cache
if cat_data_cache is not None and not reload:
return cat_data_cache
items = []
items.append(('NONE', 'None', ''))
asset_cat_file = find_asset_cat_file(Path(bpy.data.filepath).parent.__str__())
with (Path(asset_cat_file)).open() as file:
for line in file.readlines():
if line.startswith(("#", "VERSION", "\n")):
continue
# Each line contains : 'uuid:catalog_tree:catalog_name' + eol ('\n')
name = line.split(':', 1)[1].split(":")[-1].strip("\n")
uuid = line.split(':', 1)[0]
items.append((uuid, name, ''))
return items

View File

@ -49,8 +49,25 @@ def get_next_published_file(
) )
def get_asset_catalogues():
folder = Path(bpy.data.filepath).parent
target_catalog = "Catalog"
with (folder / "blender_assets.cats.txt").open() as f:
for line in f.readlines():
if line.startswith(("#", "VERSION", "\n")):
continue
# Each line contains : 'uuid:catalog_tree:catalog_name' + eol ('\n')
name = line.split(":")[2].split("\n")[0]
if name == target_catalog:
uuid = line.split(":")[0]
obj = bpy.data.objects["Suzanne"] # Object name, case-sensitive !
asset_data = obj.asset_data
asset_data.catalog_id = uuid
def create_next_published_file( def create_next_published_file(
current_file: Path, publish_type=constants.ACTIVE_PUBLISH_KEY current_file: Path, publish_type=constants.ACTIVE_PUBLISH_KEY, catalog_id: str = ''
) -> None: ) -> None:
"""Creates new Published version of a given Publish Type """Creates new Published version of a given Publish Type
@ -58,11 +75,16 @@ def create_next_published_file(
current_file (Path): Current file, which must be a task file at root of asset directory current_file (Path): Current file, which must be a task file at root of asset directory
publish_type (_type_, optional): Publish type, 'publish', 'staged', 'review'. Defaults to 'publish'. publish_type (_type_, optional): Publish type, 'publish', 'staged', 'review'. Defaults to 'publish'.
""" """
# TODO Set Catalogue here
new_file_path = get_next_published_file(current_file, publish_type) new_file_path = get_next_published_file(current_file, publish_type)
asset_col = bpy.context.scene.asset_pipeline.asset_collection
if publish_type == constants.ACTIVE_PUBLISH_KEY: if publish_type == constants.ACTIVE_PUBLISH_KEY:
bpy.context.scene.asset_pipeline.asset_collection.asset_mark() asset_col.asset_mark()
if catalog_id != '' or catalog_id != 'NONE':
asset_col.asset_data.catalog_id = catalog_id
bpy.ops.wm.save_as_mainfile(filepath=new_file_path.__str__(), copy=True) bpy.ops.wm.save_as_mainfile(filepath=new_file_path.__str__(), copy=True)
bpy.context.scene.asset_pipeline.asset_collection.asset_clear() asset_col.asset_clear()
def find_all_published(current_file: Path, publish_type: str) -> list[Path]: def find_all_published(current_file: Path, publish_type: str) -> list[Path]:

View File

@ -1,6 +1,8 @@
from typing import Set
import bpy import bpy
import os import os
from pathlib import Path from pathlib import Path
from . import constants from . import constants
from . import config from . import config
from .prefs import get_addon_prefs from .prefs import get_addon_prefs
@ -25,6 +27,8 @@ from .sync import (
sync_execute_push, sync_execute_push,
) )
from .asset_catalog import get_asset_cat_enum_items
class ASSETPIPE_OT_create_new_asset(bpy.types.Operator): class ASSETPIPE_OT_create_new_asset(bpy.types.Operator):
bl_idname = "assetpipe.create_new_asset" bl_idname = "assetpipe.create_new_asset"
@ -425,8 +429,12 @@ class ASSETPIPE_OT_publish_new_version(bpy.types.Operator):
f"Only '{constants.REVIEW_PUBLISH_KEY}' Publish is supported when a version is staged", f"Only '{constants.REVIEW_PUBLISH_KEY}' Publish is supported when a version is staged",
) )
return {'CANCELLED'} return {'CANCELLED'}
catalog_id = context.scene.asset_pipeline.asset_catalog_id
create_next_published_file(Path(bpy.data.filepath), self.publish_types) create_next_published_file(
current_file=Path(bpy.data.filepath),
publish_type=self.publish_types,
catalog_id=catalog_id,
)
return {'FINISHED'} return {'FINISHED'}
@ -465,7 +473,8 @@ class ASSETPIPE_OT_publish_staged_as_active(bpy.types.Operator):
) )
# Delete Staged File # Delete Staged File
staged_file.unlink() staged_file.unlink()
create_next_published_file(current_file) catalog_id = context.scene.asset_pipeline.asset_catalog_id
create_next_published_file(current_file=current_file, catalog_id=catalog_id)
return {'FINISHED'} return {'FINISHED'}
@ -861,7 +870,6 @@ class ASSETPIPE_OT_batch_ownership_change(bpy.types.Operator):
layout.row(align=True).prop(self, "data_source", expand=True) layout.row(align=True).prop(self, "data_source", expand=True)
layout.prop(self, "data_type", expand=True) layout.prop(self, "data_type", expand=True)
filter_owner_row = layout.row() filter_owner_row = layout.row()
filter_owner_row.enabled = grey_out filter_owner_row.enabled = grey_out
if advanced_mode: if advanced_mode:
@ -940,6 +948,17 @@ class ASSETPIPE_OT_batch_ownership_change(bpy.types.Operator):
return {'FINISHED'} return {'FINISHED'}
class ASSETPIPE_OT_refresh_asset_cat(bpy.types.Operator):
bl_idname = "assetpipe.refresh_asset_cat"
bl_label = "Refresh Asset Catalogs"
bl_description = """Refresh Asset Catalogs"""
def execute(self, context: bpy.types.Context):
get_asset_cat_enum_items()
self.report({'INFO'}, "Asset Catalogs Refreshed!")
return {'FINISHED'}
classes = ( classes = (
ASSETPIPE_OT_update_ownership, ASSETPIPE_OT_update_ownership,
ASSETPIPE_OT_sync_push, ASSETPIPE_OT_sync_push,
@ -954,6 +973,7 @@ classes = (
ASSETPIPE_OT_update_surrendered_object, ASSETPIPE_OT_update_surrendered_object,
ASSETPIPE_OT_update_surrendered_transfer_data, ASSETPIPE_OT_update_surrendered_transfer_data,
ASSETPIPE_OT_batch_ownership_change, ASSETPIPE_OT_batch_ownership_change,
ASSETPIPE_OT_refresh_asset_cat,
) )

View File

@ -1,9 +1,11 @@
import bpy import bpy
import os
from typing import List from typing import List
from . import constants from . import constants
from .config import get_task_layer_presets_path from .config import get_task_layer_presets_path
from pathlib import Path from pathlib import Path
from .prefs import get_addon_prefs from .prefs import get_addon_prefs
from .asset_catalog import get_asset_cat_enum_items
""" NOTE Items in these properties groups should be generated by a function that finds the """ NOTE Items in these properties groups should be generated by a function that finds the
avaliable task layers from the task_layer.json file that needs to be created. avaliable task layers from the task_layer.json file that needs to be created.
@ -144,6 +146,15 @@ class AssetPipeline(bpy.types.PropertyGroup):
) )
file_parent_ui_bool: bpy.props.BoolProperty(name="Show/Hide Parent", default=False) file_parent_ui_bool: bpy.props.BoolProperty(name="Show/Hide Parent", default=False)
def get_asset_catalogs(self, context):
return get_asset_cat_enum_items()
asset_catalog_id: bpy.props.EnumProperty(
name="Catalog",
items=get_asset_catalogs,
description="Select Asset Library Catalog for the current Asset, this value will be updated each time you Push to an 'Active' Publish",
)
classes = ( classes = (
AssetTransferData, AssetTransferData,

View File

@ -151,8 +151,11 @@ def sync_execute_pull(self, context):
def sync_execute_push(self, context): def sync_execute_push(self, context):
_catalog_id = None
temp_file_path = create_temp_file_backup(self, context) temp_file_path = create_temp_file_backup(self, context)
_catalog_id = context.scene.asset_pipeline.asset_catalog_id
file_path = self._sync_target.__str__() file_path = self._sync_target.__str__()
bpy.ops.wm.open_mainfile(filepath=file_path) bpy.ops.wm.open_mainfile(filepath=file_path)
@ -174,5 +177,10 @@ def sync_execute_push(self, context):
self.report({'ERROR'}, error_msg) self.report({'ERROR'}, error_msg)
return {'CANCELLED'} return {'CANCELLED'}
asset_pipe = context.scene.asset_pipeline
asset_col = asset_pipe.asset_collection
if _catalog_id != '' or _catalog_id != 'NONE':
asset_col.asset_data.catalog_id = _catalog_id
bpy.ops.wm.save_as_mainfile(filepath=file_path) bpy.ops.wm.save_as_mainfile(filepath=file_path)
bpy.ops.wm.open_mainfile(filepath=self._current_file.__str__()) bpy.ops.wm.open_mainfile(filepath=self._current_file.__str__())

View File

@ -89,6 +89,9 @@ class ASSETPIPE_PT_sync_tools(bpy.types.Panel):
def draw(self, context: bpy.types.Context) -> None: def draw(self, context: bpy.types.Context) -> None:
layout = self.layout layout = self.layout
cat_row = layout.row(align=True)
cat_row.prop(context.scene.asset_pipeline, 'asset_catalog_id')
cat_row.operator("assetpipe.refresh_asset_cat", icon='FILE_REFRESH', text="")
layout.operator("assetpipe.batch_ownership_change") layout.operator("assetpipe.batch_ownership_change")
layout.operator("assetpipe.revert_file", icon="FILE_TICK") layout.operator("assetpipe.revert_file", icon="FILE_TICK")