Asset Pipeline v2 #145
@ -3,20 +3,21 @@ import bpy
|
||||
import os
|
||||
from pathlib import Path
|
||||
from .merge.publish import (
|
||||
find_sync_target,
|
||||
find_all_published,
|
||||
get_next_published_file,
|
||||
)
|
||||
from .merge.naming import get_task_layer_col_name
|
||||
from .merge.other_ids import init_other_ids
|
||||
from .merge.core import (
|
||||
ownership_get,
|
||||
ownership_set,
|
||||
get_invalid_objects,
|
||||
merge_task_layer,
|
||||
)
|
||||
|
||||
from .merge.transfer_data.transfer_ui import draw_transfer_data
|
||||
from . import constants
|
||||
from .sync import (
|
||||
sync_poll,
|
||||
sync_invoke,
|
||||
sync_draw,
|
||||
sync_execute_update_ownership,
|
||||
sync_execute_prepare_sync,
|
||||
sync_execute_pull,
|
||||
sync_execute_push,
|
||||
)
|
||||
|
||||
|
||||
class ASSETPIPE_OT_create_new_asset(bpy.types.Operator):
|
||||
@ -107,11 +108,10 @@ class ASSETPIPE_OT_create_new_asset(bpy.types.Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class ASSETPIPE_OT_sync_with_publish(bpy.types.Operator):
|
||||
bl_idname = "assetpipe.sync_with_publish"
|
||||
bl_label = "Sync with Publish"
|
||||
bl_description = """'Push'band or 'Pull' data from Published file. Will prompt with a list of new data found before pushing
|
||||
During 'Push' current blender session will revert to the last saved file and clear the current undo history"""
|
||||
class ASSETPIPE_OT_update_ownership(bpy.types.Operator):
|
||||
bl_idname = "assetpipe.update_ownership"
|
||||
bl_label = "Update Onwership"
|
||||
bl_description = """""" # TODO Add description
|
||||
|
||||
_temp_transfer_data = None
|
||||
_invalid_objs = []
|
||||
@ -123,161 +123,114 @@ class ASSETPIPE_OT_sync_with_publish(bpy.types.Operator):
|
||||
description="Show New Transfer Data",
|
||||
)
|
||||
|
||||
save: bpy.props.BoolProperty(
|
||||
name="Save Current File",
|
||||
default=True,
|
||||
description="Save the Current File (after pulling if enabled) before Pushing to Publish",
|
||||
)
|
||||
|
||||
pull: bpy.props.BoolProperty(
|
||||
name="Pull before Pushing",
|
||||
default=False,
|
||||
description="Pull in any new data from the Published file before Pushing",
|
||||
)
|
||||
|
||||
push: bpy.props.BoolProperty(
|
||||
name="Push", default=False, description="Push any new data to Published file"
|
||||
)
|
||||
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event):
|
||||
self._temp_transfer_data = context.scene.asset_pipeline.temp_transfer_data
|
||||
self._temp_transfer_data.clear()
|
||||
self._invalid_objs.clear()
|
||||
|
||||
local_col = context.scene.asset_pipeline.asset_collection
|
||||
if not local_col:
|
||||
self.report({'ERROR'}, "Top level collection could not be found")
|
||||
return {'CANCELLED'}
|
||||
task_layer_key = context.scene.asset_pipeline.task_layer_name
|
||||
if task_layer_key == "NONE":
|
||||
self.report({'ERROR'}, "Current File Name doesn't contain valid task layer")
|
||||
return {'CANCELLED'}
|
||||
|
||||
ownership_get(local_col, context.scene)
|
||||
|
||||
# TODO Remove Invalid Objs Explicitly, some will be auto removed but not all
|
||||
self._invalid_objs = get_invalid_objects(local_col, context.scene)
|
||||
self._other_ids = init_other_ids(context.scene)
|
||||
|
||||
# Default behaviour is to pull before pushing
|
||||
if self.push:
|
||||
self.pull = True
|
||||
sync_invoke(self, context)
|
||||
return context.window_manager.invoke_props_dialog(self, width=400)
|
||||
|
||||
def draw(self, context: bpy.types.Context):
|
||||
layout = self.layout
|
||||
sync_draw(self, context)
|
||||
|
||||
row = layout.row()
|
||||
if self.push:
|
||||
row.prop(self, "pull")
|
||||
row.prop(self, "save")
|
||||
def execute(self, context: bpy.types.Context):
|
||||
sync_execute_update_ownership(self, context)
|
||||
return {'FINISHED'}
|
||||
|
||||
if len(self._invalid_objs) != 0:
|
||||
box = layout.box()
|
||||
box.alert = True
|
||||
box.label(text="Sync will clear Invalid Objects:", icon="ERROR")
|
||||
for obj in self._invalid_objs:
|
||||
box.label(text=obj.name, icon="OBJECT_DATA")
|
||||
|
||||
if len(self._other_ids) != 0:
|
||||
box = layout.box()
|
||||
box.label(text="New 'Other IDs' found")
|
||||
for id in self._other_ids:
|
||||
box.label(text=id.name)
|
||||
class ASSETPIPE_OT_sync_pull(bpy.types.Operator):
|
||||
bl_idname = "assetpipe.sync_pull"
|
||||
bl_label = "Pull from Publish"
|
||||
bl_description = """""" # TODO Add description
|
||||
|
||||
if len(self._temp_transfer_data) == 0:
|
||||
layout.label(text="No New Transfer Data found")
|
||||
else:
|
||||
layout.label(text="New Transfer 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")
|
||||
objs = [
|
||||
transfer_data_item.obj for transfer_data_item in self._temp_transfer_data
|
||||
]
|
||||
_temp_transfer_data = None
|
||||
_invalid_objs = []
|
||||
_other_ids = []
|
||||
_temp_dir: Path = None
|
||||
_current_file: Path = None
|
||||
_task_layer_key: str = ""
|
||||
_sync_target: Path = None
|
||||
|
||||
if not self.expand:
|
||||
return
|
||||
expand: bpy.props.BoolProperty(
|
||||
name="Show New Transfer Data",
|
||||
default=False,
|
||||
description="Show New Transfer Data",
|
||||
)
|
||||
|
||||
for obj in set(objs):
|
||||
obj_ownership = [
|
||||
transfer_data_item
|
||||
for transfer_data_item in self._temp_transfer_data
|
||||
if transfer_data_item.obj == obj
|
||||
]
|
||||
box = layout.box()
|
||||
box.label(text=obj.name, icon="OBJECT_DATA")
|
||||
draw_transfer_data(obj_ownership, box)
|
||||
@classmethod
|
||||
def poll(cls, context: bpy.types.Context) -> bool:
|
||||
if any([img.is_dirty for img in bpy.data.images]):
|
||||
cls.poll_message_set("Please save unsaved Images")
|
||||
return False
|
||||
if bpy.data.is_dirty:
|
||||
cls.poll_message_set("Please save current .blend file")
|
||||
return False
|
||||
return True
|
||||
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event):
|
||||
sync_invoke(self, context)
|
||||
return context.window_manager.invoke_props_dialog(self, width=400)
|
||||
|
||||
def draw(self, context: bpy.types.Context):
|
||||
sync_draw(self, context)
|
||||
|
||||
def execute(self, context: bpy.types.Context):
|
||||
# Find current task Layer
|
||||
temp_transfer_data = context.scene.asset_pipeline.temp_transfer_data
|
||||
ownership_set(temp_transfer_data)
|
||||
current_file = Path(bpy.data.filepath)
|
||||
temp_dir = Path(bpy.app.tempdir).parent
|
||||
task_layer_key = context.scene.asset_pipeline.task_layer_name
|
||||
if task_layer_key == "NONE":
|
||||
self.report({'ERROR'}, "Current File Name doesn't contain valid task layer")
|
||||
return {'CANCELLED'}
|
||||
sync_execute_update_ownership(self, context)
|
||||
sync_execute_prepare_sync(self, context)
|
||||
sync_execute_pull(self, context)
|
||||
return {'FINISHED'}
|
||||
|
||||
sync_target = find_sync_target(current_file)
|
||||
if not sync_target.exists():
|
||||
self.report({'ERROR'}, "Sync Target could not be determined")
|
||||
return {'CANCELLED'}
|
||||
|
||||
class ASSETPIPE_OT_sync_push(bpy.types.Operator):
|
||||
bl_idname = "assetpipe.sync_push"
|
||||
bl_label = "Push from Publish"
|
||||
bl_description = """""" # TODO Add description
|
||||
|
||||
_temp_transfer_data = None
|
||||
_invalid_objs = []
|
||||
_other_ids = []
|
||||
_temp_dir: Path = None
|
||||
_current_file: Path = None
|
||||
_task_layer_key: str = ""
|
||||
_sync_target: Path = None
|
||||
|
||||
expand: bpy.props.BoolProperty(
|
||||
name="Show New Transfer Data",
|
||||
default=False,
|
||||
description="Show New Transfer Data",
|
||||
)
|
||||
pull: bpy.props.BoolProperty(
|
||||
name="Pull before Pushing",
|
||||
default=True,
|
||||
description="Pull in any new data from the Published file before Pushing",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context: bpy.types.Context) -> bool:
|
||||
if any([img.is_dirty for img in bpy.data.images]):
|
||||
cls.poll_message_set("Please save unsaved Images")
|
||||
return False
|
||||
if bpy.data.is_dirty:
|
||||
cls.poll_message_set("Please save current .blend file")
|
||||
return False
|
||||
return True
|
||||
|
||||
def invoke(self, context: bpy.types.Context, event: bpy.types.Event):
|
||||
sync_invoke(self, context)
|
||||
return context.window_manager.invoke_props_dialog(self, width=400)
|
||||
|
||||
def draw(self, context: bpy.types.Context):
|
||||
self.layout.prop(self, "pull")
|
||||
sync_draw(self, context)
|
||||
|
||||
def execute(self, context: bpy.types.Context):
|
||||
# Find current task Layer
|
||||
sync_execute_update_ownership(self, context)
|
||||
sync_execute_prepare_sync(self, context)
|
||||
|
||||
if self.pull:
|
||||
temp_file = temp_dir.joinpath(
|
||||
current_file.name.replace(".blend", "") + "_Asset_Pipe_Backup.blend"
|
||||
)
|
||||
bpy.ops.wm.save_as_mainfile(filepath=temp_file.__str__(), copy=True)
|
||||
error_msg = merge_task_layer(
|
||||
context,
|
||||
local_tls=[task_layer_key],
|
||||
external_file=sync_target,
|
||||
)
|
||||
sync_execute_pull(self, context)
|
||||
bpy.ops.wm.save_mainfile(filepath=self._current_file.__str__())
|
||||
|
||||
if error_msg:
|
||||
bpy.ops.wm.open_mainfile(filepath=temp_file.__str__())
|
||||
bpy.ops.wm.save_as_mainfile(filepath=current_file.__str__())
|
||||
self.report({'ERROR'}, error_msg)
|
||||
return {'CANCELLED'}
|
||||
|
||||
if self.save:
|
||||
bpy.ops.wm.save_as_mainfile(filepath=current_file.__str__())
|
||||
|
||||
if not self.push:
|
||||
return {'FINISHED'}
|
||||
|
||||
push_targets = find_all_published(current_file, constants.ACTIVE_PUBLISH_KEY)
|
||||
if sync_target not in push_targets:
|
||||
push_targets.append(sync_target)
|
||||
|
||||
for file in push_targets:
|
||||
file_path = file.__str__()
|
||||
bpy.ops.wm.open_mainfile(filepath=file_path)
|
||||
|
||||
# SKIP DEPRECIATED FILES
|
||||
if context.scene.asset_pipeline.is_depreciated:
|
||||
continue
|
||||
|
||||
local_tls = [
|
||||
task_layer
|
||||
for task_layer in constants.TASK_LAYER_TYPES.keys()
|
||||
if task_layer != task_layer_key
|
||||
]
|
||||
|
||||
error_msg = merge_task_layer(
|
||||
context,
|
||||
local_tls=local_tls,
|
||||
external_file=current_file,
|
||||
)
|
||||
if error_msg:
|
||||
bpy.ops.wm.open_mainfile(filepath=current_file.__str__())
|
||||
self.report({'ERROR'}, error_msg)
|
||||
return {'CANCELLED'}
|
||||
|
||||
bpy.ops.wm.save_as_mainfile(filepath=file_path)
|
||||
bpy.ops.wm.open_mainfile(filepath=current_file.__str__())
|
||||
sync_execute_push(self, context)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
@ -312,7 +265,9 @@ class ASSETPIPE_OT_publish_new_version(bpy.types.Operator):
|
||||
|
||||
|
||||
classes = (
|
||||
ASSETPIPE_OT_sync_with_publish,
|
||||
ASSETPIPE_OT_update_ownership,
|
||||
ASSETPIPE_OT_sync_push,
|
||||
ASSETPIPE_OT_sync_pull,
|
||||
ASSETPIPE_OT_publish_new_version,
|
||||
ASSETPIPE_OT_create_new_asset,
|
||||
)
|
||||
|
156
scripts-blender/addons/asset_pipeline_2/sync.py
Normal file
156
scripts-blender/addons/asset_pipeline_2/sync.py
Normal file
@ -0,0 +1,156 @@
|
||||
import bpy
|
||||
from pathlib import Path
|
||||
from .merge.publish import (
|
||||
find_sync_target,
|
||||
find_all_published,
|
||||
)
|
||||
from .merge.other_ids import init_other_ids
|
||||
from .merge.core import (
|
||||
ownership_get,
|
||||
ownership_set,
|
||||
get_invalid_objects,
|
||||
merge_task_layer,
|
||||
)
|
||||
from .merge.transfer_data.transfer_ui import draw_transfer_data
|
||||
from . import constants
|
||||
|
||||
|
||||
def sync_poll(cls, context):
|
||||
if any([img.is_dirty for img in bpy.data.images]):
|
||||
cls.poll_message_set("Please save unsaved Images")
|
||||
return False
|
||||
if bpy.data.is_dirty:
|
||||
cls.poll_message_set("Please save current .blend file")
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def sync_invoke(self, context):
|
||||
self._temp_transfer_data = context.scene.asset_pipeline.temp_transfer_data
|
||||
self._temp_transfer_data.clear()
|
||||
self._invalid_objs.clear()
|
||||
|
||||
local_col = context.scene.asset_pipeline.asset_collection
|
||||
if not local_col:
|
||||
self.report({'ERROR'}, "Top level collection could not be found")
|
||||
return {'CANCELLED'}
|
||||
task_layer_key = context.scene.asset_pipeline.task_layer_name
|
||||
if task_layer_key == "NONE":
|
||||
self.report({'ERROR'}, "Current File Name doesn't contain valid task layer")
|
||||
return {'CANCELLED'}
|
||||
|
||||
ownership_get(local_col, context.scene)
|
||||
|
||||
# TODO Remove Invalid Objs Explicitly, some will be auto removed but not all
|
||||
self._invalid_objs = get_invalid_objects(local_col, context.scene)
|
||||
self._other_ids = init_other_ids(context.scene)
|
||||
|
||||
|
||||
def sync_draw(self, context):
|
||||
layout = self.layout
|
||||
row = layout.row()
|
||||
|
||||
if len(self._invalid_objs) != 0:
|
||||
box = layout.box()
|
||||
box.alert = True
|
||||
box.label(text="Sync will clear Invalid Objects:", icon="ERROR")
|
||||
for obj in self._invalid_objs:
|
||||
box.label(text=obj.name, icon="OBJECT_DATA")
|
||||
|
||||
if len(self._other_ids) != 0:
|
||||
box = layout.box()
|
||||
box.label(text="New 'Other IDs' found")
|
||||
for id in self._other_ids:
|
||||
box.label(text=id.name)
|
||||
|
||||
if len(self._temp_transfer_data) == 0:
|
||||
layout.label(text="No New Transfer Data found")
|
||||
else:
|
||||
layout.label(text="New Transfer 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")
|
||||
objs = [transfer_data_item.obj for transfer_data_item in self._temp_transfer_data]
|
||||
|
||||
if not self.expand:
|
||||
return
|
||||
|
||||
for obj in set(objs):
|
||||
obj_ownership = [
|
||||
transfer_data_item
|
||||
for transfer_data_item in self._temp_transfer_data
|
||||
if transfer_data_item.obj == obj
|
||||
]
|
||||
box = layout.box()
|
||||
box.label(text=obj.name, icon="OBJECT_DATA")
|
||||
draw_transfer_data(obj_ownership, box)
|
||||
|
||||
|
||||
def sync_execute_update_ownership(self, context):
|
||||
temp_transfer_data = context.scene.asset_pipeline.temp_transfer_data
|
||||
ownership_set(temp_transfer_data)
|
||||
|
||||
|
||||
def sync_execute_prepare_sync(self, context):
|
||||
self._current_file = Path(bpy.data.filepath)
|
||||
self._temp_dir = Path(bpy.app.tempdir).parent
|
||||
self._task_layer_key = context.scene.asset_pipeline.task_layer_name
|
||||
if self._task_layer_key == "NONE":
|
||||
self.report({'ERROR'}, "Current File Name doesn't contain valid task layer")
|
||||
return {'CANCELLED'}
|
||||
|
||||
self._sync_target = find_sync_target(self._current_file)
|
||||
if not self._sync_target.exists():
|
||||
self.report({'ERROR'}, "Sync Target could not be determined")
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
||||
def sync_execute_pull(self, context):
|
||||
temp_file = self._temp_dir.joinpath(
|
||||
self._current_file.name.replace(".blend", "") + "_Asset_Pipe_Backup.blend"
|
||||
)
|
||||
bpy.ops.wm.save_as_mainfile(filepath=temp_file.__str__(), copy=True)
|
||||
error_msg = merge_task_layer(
|
||||
context,
|
||||
local_tls=[self._task_layer_key],
|
||||
external_file=self._sync_target,
|
||||
)
|
||||
|
||||
if error_msg:
|
||||
bpy.ops.wm.open_mainfile(filepath=temp_file.__str__())
|
||||
bpy.ops.wm.save_as_mainfile(filepath=self._current_file.__str__())
|
||||
self.report({'ERROR'}, error_msg)
|
||||
return {'CANCELLED'}
|
||||
|
||||
|
||||
def sync_execute_push(self, context):
|
||||
push_targets = find_all_published(self._current_file, constants.ACTIVE_PUBLISH_KEY)
|
||||
if self._sync_target not in push_targets:
|
||||
push_targets.append(self._sync_target)
|
||||
|
||||
for file in push_targets:
|
||||
file_path = file.__str__()
|
||||
bpy.ops.wm.open_mainfile(filepath=file_path)
|
||||
|
||||
# SKIP DEPRECIATED FILES
|
||||
if context.scene.asset_pipeline.is_depreciated:
|
||||
continue
|
||||
|
||||
local_tls = [
|
||||
task_layer
|
||||
for task_layer in constants.TASK_LAYER_TYPES.keys()
|
||||
if task_layer != self._task_layer_key
|
||||
]
|
||||
|
||||
error_msg = merge_task_layer(
|
||||
context,
|
||||
local_tls=local_tls,
|
||||
external_file=self._current_file,
|
||||
)
|
||||
if error_msg:
|
||||
bpy.ops.wm.open_mainfile(filepath=self._current_file.__str__())
|
||||
self.report({'ERROR'}, error_msg)
|
||||
return {'CANCELLED'}
|
||||
|
||||
bpy.ops.wm.save_as_mainfile(filepath=file_path)
|
||||
bpy.ops.wm.open_mainfile(filepath=self._current_file.__str__())
|
@ -29,15 +29,11 @@ class ASSETPIPE_sync(bpy.types.Panel):
|
||||
layout.prop(asset_pipe, "asset_collection", text="Asset")
|
||||
layout.label(text="Test UI")
|
||||
|
||||
# layout.operator(
|
||||
# "assetpipe.sync_with_publish", text="Update Ownership"
|
||||
# ).pull = False
|
||||
layout.operator("assetpipe.update_ownership", text="Update Ownership")
|
||||
layout.operator("assetpipe.sync_push", text="Push to Publish", icon="TRIA_UP")
|
||||
layout.operator(
|
||||
"assetpipe.sync_with_publish", text="Push to Publish", icon="TRIA_UP"
|
||||
).push = True
|
||||
layout.operator(
|
||||
"assetpipe.sync_with_publish", text="Pull from Publish", icon="TRIA_DOWN"
|
||||
).pull = True
|
||||
"assetpipe.sync_pull", text="Pull from Publish", icon="TRIA_DOWN"
|
||||
)
|
||||
layout.operator("assetpipe.publish_new_version", icon="PLUS")
|
||||
|
||||
if asset_pipe.is_asset_pipeline_file and asset_pipe.task_layer_name == "NONE":
|
||||
|
Loading…
Reference in New Issue
Block a user