diff --git a/abx/abx_context.py b/abx/abx_context.py index ccb1f53..2fa0258 100644 --- a/abx/abx_context.py +++ b/abx/abx_context.py @@ -17,6 +17,7 @@ with open(os.path.join(os.path.dirname(__file__), 'abx.yaml')) as def_yaml_file: from . import accumulate from .accumulate import RecursiveDict +from .render_profile import RenderProfileMap class ABX_Context(object): @@ -90,7 +91,7 @@ class ABX_Context(object): self.abx_fields = abx_data - self.render_profiles = self.abx_fields['render_profiles'] + self.render_profiles = RenderProfileMap(self.abx_fields['render_profiles']) try: self.render_root = os.path.join(self.root, diff --git a/abx/abx_ui.py b/abx/abx_ui.py index 8ee8827..f8aae8a 100644 --- a/abx/abx_ui.py +++ b/abx/abx_ui.py @@ -98,29 +98,29 @@ seq_id_table = { } -def get_seq_ids(self, context): - """ - Specific function to retrieve enumerated values for sequence units. - - NOTE: due to be replaced by file_context features. - """ - # - # Note: To avoid the reference bug mentioned in the Blender documentation, - # we only return values held in the global seq_id_table, which - # should remain defined and therefore hold a reference to the strings. - # - if not context: - seq_ids = seq_id_table[None] - else: - scene = context.scene - series = scene.lunaprops.series_id - episode = scene.lunaprops.episode_id - if (series, episode) in seq_id_table: - seq_ids = seq_id_table[(series, episode)] - else: - seq_ids = seq_id_table[None] - seq_enum_items = [(s, s, seq_id_table[series,episode][s]) for s in seq_ids] - return seq_enum_items +# def get_seq_ids(self, context): +# """ +# Specific function to retrieve enumerated values for sequence units. +# +# NOTE: due to be replaced by file_context features. +# """ +# # +# # Note: To avoid the reference bug mentioned in the Blender documentation, +# # we only return values held in the global seq_id_table, which +# # should remain defined and therefore hold a reference to the strings. +# # +# if not context: +# seq_ids = seq_id_table[None] +# else: +# scene = context.scene +# series = scene.lunaprops.series_id +# episode = scene.lunaprops.episode_id +# if (series, episode) in seq_id_table: +# seq_ids = seq_id_table[(series, episode)] +# else: +# seq_ids = seq_id_table[None] +# seq_enum_items = [(s, s, seq_id_table[series,episode][s]) for s in seq_ids] +# return seq_enum_items class ProjectProperties(bpy.types.PropertyGroup): """ @@ -136,11 +136,15 @@ class ProjectProperties(bpy.types.PropertyGroup): # name_context = BlendFile.new_name_context() # self.name_context_id = str(id(name_context)) # return name_context - + render_root = bpy.props.StringProperty( + name = 'Render Root', + description = 'Path to where renders should be stored', + subtype = 'FILE_PATH') + render_folder = bpy.props.StringProperty( name = 'Render Folder', - description = 'Path to the render folder (without filename)', - subtype = 'FILE_PATH') + description = 'Relative path from Render Root (without filename)', + subtype = 'FILE_NAME') render_prefix = bpy.props.StringProperty( name = 'Render Prefix', @@ -152,6 +156,11 @@ class ProjectProperties(bpy.types.PropertyGroup): description = 'Short code for this Blender scene only', maxlen=16) + scene_suffix = bpy.props.StringProperty( + name = 'Scene Suffix', + description = 'Short descriptive annotation for this scene (used only in scene name)', + maxlen=16) + role = bpy.props.EnumProperty( name = 'Role', description = 'Role of this scene in project', @@ -192,6 +201,31 @@ class ProjectProperties(bpy.types.PropertyGroup): name = 'Ink Type', description = "Determines how ink will be handled in final shot render") + @property + def scene_name(self): + if self.scene_suffix: + return self.designation + ' ' + self.scene_suffix + else: + return self.designation + + @property + def render_stem(self): + if self.render_prefix: + return self.render_prefix + '-' + self.designation + else: + return self.designation + + def render_path(self, suffix='', framedigits=5, ext='png', rdr_fmt='PNG'): + if suffix: + suffix = '-' + suffix + if rdr_fmt in ('AVI', 'MKV'): + path = os.path.join(self.render_root, self.render_folder, suffix, + self.render_prefix + self.designation + suffix + '.' + ext) + else: + path = os.path.join(self.render_root, self.render_folder, suffix, self.designation, + self.render_prefix + self.designation + suffix + '-f' + '#'*framedigits + '.' + ext) + return path + class ProjectPanel(bpy.types.Panel): """ Add a panel to the Properties-Scene screen with Project Settings. @@ -206,10 +240,13 @@ class ProjectPanel(bpy.types.Panel): pp = bpy.context.scene.project_properties self.layout.label(text='Project Properties') row = self.layout.row() + row.prop(pp, 'render_root') + row = self.layout.row() row.prop(pp, 'render_folder') row = self.layout.row() row.prop(pp, 'render_prefix') row.prop(pp, 'designation') + row.prop(pp, 'scene_suffix') self.layout.label(text='Render Range') row = self.layout.row() row.prop(pp, 'frame_start') @@ -224,109 +261,109 @@ class ProjectPanel(bpy.types.Panel): -class LunaticsSceneProperties(bpy.types.PropertyGroup): - """ - Properties of the current scene. - - NOTE: due to be replaced by 'ProjectProperties', using the schema data - retrieved by file_context. - """ - - series_id = bpy.props.EnumProperty( - items=[ - ('S1', 'S1', 'Series One'), - ('S2', 'S2', 'Series Two'), - ('S3', 'S3', 'Series Three'), - ('A1', 'Aud','Audiodrama'), - ('L', 'Lib','Library') - ], - name="Series", - default='S1', - description="Series/Season of Animated Series, Audiodrama, or Library" - ) - - episode_id = bpy.props.IntProperty( - name="Episode", - default=0, - description="Episode number (0 means multi-use), ignored for Library", - min=0, - max=1000, - soft_max=18 - ) - - seq_id = bpy.props.EnumProperty( - name='', - items=get_seq_ids, - description="Sequence ID" - ) - - block_id = bpy.props.IntProperty( - name='', - default=1, - min=0, - max=20, - soft_max=10, - description="Block number" - ) - - use_multicam = bpy.props.BoolProperty( - name="Multicam", - default=False, - description="Use multicam camera/shot numbering?" - ) - - cam_id = bpy.props.IntProperty( - name="Cam", - default=0, - min=0, - max=20, - soft_max=10, - description="Camera number" - ) - - shot_id = bpy.props.EnumProperty( - name='Shot', - #items=[('NONE', '', 'Single')]+[(c,c,'Shot '+c) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], - items=[(c,c,'Shot '+c) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], - default='A', - description="Shot ID, normally a single capital letter, can be empty, two letters for transitions" - ) - - shot_name = bpy.props.StringProperty( - name='Name', - description='Short descriptive codename', - maxlen=0 - ) - - - -class LunaticsScenePanel(bpy.types.Panel): - """ - Add a panel to the Properties-Scene screen - - NOTE: To be replaced by 'ProjectPropertiesPanel'. - """ - bl_idname = 'SCENE_PT_lunatics' - bl_label = 'Lunatics Project' - bl_space_type = 'PROPERTIES' - bl_region_type = 'WINDOW' - bl_context = 'scene' - - def draw(self, context): - lunaprops = bpy.context.scene.lunaprops - self.layout.label(text='Lunatics! Project Properties') - row = self.layout.row() - row.prop(lunaprops, 'series_id') - row.prop(lunaprops, 'episode_id') - row = self.layout.row() - row.prop(lunaprops, 'use_multicam') - row = self.layout.row() - row.prop(lunaprops, 'seq_id') - row.prop(lunaprops, 'block_id') - if lunaprops.use_multicam: - row.prop(lunaprops, 'cam_id') - row.prop(lunaprops, 'shot_id') - row.prop(lunaprops, 'shot_name') +# class LunaticsSceneProperties(bpy.types.PropertyGroup): +# """ +# Properties of the current scene. +# +# NOTE: due to be replaced by 'ProjectProperties', using the schema data +# retrieved by file_context. +# """ +# +# series_id = bpy.props.EnumProperty( +# items=[ +# ('S1', 'S1', 'Series One'), +# ('S2', 'S2', 'Series Two'), +# ('S3', 'S3', 'Series Three'), +# ('A1', 'Aud','Audiodrama'), +# ('L', 'Lib','Library') +# ], +# name="Series", +# default='S1', +# description="Series/Season of Animated Series, Audiodrama, or Library" +# ) +# +# episode_id = bpy.props.IntProperty( +# name="Episode", +# default=0, +# description="Episode number (0 means multi-use), ignored for Library", +# min=0, +# max=1000, +# soft_max=18 +# ) +# +# seq_id = bpy.props.EnumProperty( +# name='', +# items=get_seq_ids, +# description="Sequence ID" +# ) +# +# block_id = bpy.props.IntProperty( +# name='', +# default=1, +# min=0, +# max=20, +# soft_max=10, +# description="Block number" +# ) +# +# use_multicam = bpy.props.BoolProperty( +# name="Multicam", +# default=False, +# description="Use multicam camera/shot numbering?" +# ) +# +# cam_id = bpy.props.IntProperty( +# name="Cam", +# default=0, +# min=0, +# max=20, +# soft_max=10, +# description="Camera number" +# ) +# +# shot_id = bpy.props.EnumProperty( +# name='Shot', +# #items=[('NONE', '', 'Single')]+[(c,c,'Shot '+c) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], +# items=[(c,c,'Shot '+c) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'], +# default='A', +# description="Shot ID, normally a single capital letter, can be empty, two letters for transitions" +# ) +# +# shot_name = bpy.props.StringProperty( +# name='Name', +# description='Short descriptive codename', +# maxlen=0 +# ) +# +# +# +# class LunaticsScenePanel(bpy.types.Panel): +# """ +# Add a panel to the Properties-Scene screen +# +# NOTE: To be replaced by 'ProjectPropertiesPanel'. +# """ +# bl_idname = 'SCENE_PT_lunatics' +# bl_label = 'Lunatics Project' +# bl_space_type = 'PROPERTIES' +# bl_region_type = 'WINDOW' +# bl_context = 'scene' +# +# def draw(self, context): +# lunaprops = bpy.context.scene.lunaprops +# self.layout.label(text='Lunatics! Project Properties') +# row = self.layout.row() +# row.prop(lunaprops, 'series_id') +# row.prop(lunaprops, 'episode_id') +# row = self.layout.row() +# row.prop(lunaprops, 'use_multicam') +# row = self.layout.row() +# row.prop(lunaprops, 'seq_id') +# row.prop(lunaprops, 'block_id') +# if lunaprops.use_multicam: +# row.prop(lunaprops, 'cam_id') +# row.prop(lunaprops, 'shot_id') +# row.prop(lunaprops, 'shot_name') # Buttons @@ -480,7 +517,7 @@ class CharacterPanel(bpy.types.Panel): -class lunatics_compositing_settings(bpy.types.PropertyGroup): +class InkPaintProps(bpy.types.PropertyGroup): """ Settings for Ink/Paint Config. """ @@ -500,7 +537,7 @@ class lunatics_compositing_settings(bpy.types.PropertyGroup): default = True) -class lunatics_compositing(bpy.types.Operator): +class InkPaintOp(bpy.types.Operator): """ Ink/Paint Config Operator. """ @@ -515,7 +552,7 @@ class lunatics_compositing(bpy.types.Operator): """ scene = context.scene - shot = ink_paint.LunaticsShot(scene, + shot = ink_paint.InkPaintShot(scene, inkthru=context.scene.lx_compos_settings.inkthru, billboards=context.scene.lx_compos_settings.billboards, sepsky=context.scene.lx_compos_settings.sepsky ) @@ -526,7 +563,7 @@ class lunatics_compositing(bpy.types.Operator): -class LunaticsPanel(bpy.types.Panel): +class InkPaintPanel(bpy.types.Panel): """ Ink/Paint Configuration panel. """ @@ -567,9 +604,9 @@ def update_handler(ctxt): def register(): - bpy.utils.register_class(LunaticsSceneProperties) - bpy.types.Scene.lunaprops = bpy.props.PointerProperty(type=LunaticsSceneProperties) - bpy.utils.register_class(LunaticsScenePanel) + # bpy.utils.register_class(LunaticsSceneProperties) + # bpy.types.Scene.lunaprops = bpy.props.PointerProperty(type=LunaticsSceneProperties) + # bpy.utils.register_class(LunaticsScenePanel) bpy.utils.register_class(ProjectProperties) bpy.types.Scene.project_properties = bpy.props.PointerProperty(type=ProjectProperties) @@ -588,10 +625,10 @@ def register(): bpy.types.Scene.copy_anim_settings = bpy.props.PointerProperty(type=copy_animation_settings) bpy.utils.register_class(CharacterPanel) - bpy.utils.register_class(lunatics_compositing_settings) - bpy.types.Scene.lx_compos_settings = bpy.props.PointerProperty(type=lunatics_compositing_settings) - bpy.utils.register_class(lunatics_compositing) - bpy.utils.register_class(LunaticsPanel) + bpy.utils.register_class(InkPaintProps) + bpy.types.Scene.lx_compos_settings = bpy.props.PointerProperty(type=InkPaintProps) + bpy.utils.register_class(InkPaintOp) + bpy.utils.register_class(InkPaintPanel) bpy.app.handlers.save_post.append(update_handler) bpy.app.handlers.load_post.append(update_handler) @@ -602,8 +639,8 @@ def unregister(): bpy.app.handlers.load_post.remove(update_handler) bpy.app.handlers.scene_update_post.remove(update_handler) - bpy.utils.unregister_class(LunaticsSceneProperties) - bpy.utils.unregister_class(LunaticsScenePanel) + # bpy.utils.unregister_class(LunaticsSceneProperties) + # bpy.utils.unregister_class(LunaticsScenePanel) bpy.utils.unregister_class(ProjectProperties) @@ -617,8 +654,8 @@ def unregister(): bpy.utils.unregister_class(copy_animation_settings) bpy.utils.unregister_class(CharacterPanel) - bpy.utils.unregister_class(lunatics_compositing_settings) - bpy.utils.unregister_class(lunatics_compositing) - bpy.utils.unregister_class(LunaticsPanel) + bpy.utils.unregister_class(InkPaintProps) + bpy.utils.unregister_class(InkPaintOp) + bpy.utils.unregister_class(InkPaintPanel) diff --git a/abx/ink_paint.py b/abx/ink_paint.py index 27c96c5..b6b975f 100644 --- a/abx/ink_paint.py +++ b/abx/ink_paint.py @@ -48,7 +48,7 @@ THRU_INK_COLOR = (20,100,50) # TODO: probably should have a dialog somewhere that can change these through the UI? -class LunaticsShot(object): +class InkPaintShot(object): """ General class for Lunatics Blender Scene data. @@ -72,52 +72,38 @@ class LunaticsShot(object): self.inkthru = bool(inkthru) self.billboards = bool(billboards) self.sepsky = bool(sepsky) - - self.series_id = scene.lunaprops.series_id - self.episode_id = scene.lunaprops.episode_id - self.seq_id = scene.lunaprops.seq_id - self.block_id = scene.lunaprops.block_id - self.shot_id = scene.lunaprops.shot_id - self.cam_id = scene.lunaprops.cam_id - self.shot_name = scene.lunaprops.shot_name - self.render_root = '//../../Renders/' - - @property - def fullname(self): - return self.designation + '-' + self.name + self.pp = scene.project_properties - @property - def designation(self): - episode_code = "%2.2sE%2.2d" % (self.series_id, self.episode_id) - return episode_code + '-' + self.shortname + # self.series_id = scene.lunaprops.series_id + # self.episode_id = scene.lunaprops.episode_id + # self.seq_id = scene.lunaprops.seq_id + # self.block_id = scene.lunaprops.block_id + # self.shot_id = scene.lunaprops.shot_id + # self.cam_id = scene.lunaprops.cam_id + # self.shot_name = scene.lunaprops.shot_name + # + # self.render_root = '//../../Renders/' - @property - def shortname(self): - desig = str(self.seq_id) + '-' + str(self.block_id) - if self.cam_id: - desig = desig + '-Cam' + str(self.cam_id) - if self.shot_id: - desig = desig + '-' + str(self.shot_id) - return desig + # @property + # def fullname(self): + # return self.designation + '-' + self.name + + # @property + # def designation(self): + # episode_code = "%2.2sE%2.2d" % (self.series_id, self.episode_id) + # return episode_code + '-' + self.shortname + + # @property + # def shortname(self): + # desig = str(self.seq_id) + '-' + str(self.block_id) + # if self.cam_id: + # desig = desig + '-Cam' + str(self.cam_id) + # if self.shot_id: + # desig = desig + '-' + str(self.shot_id) + # return desig - @property - def scene_name(self): - if self.shot_name: - return self.shortname + ' ' + self.shot_name - else: - return self.shortname - - def render_path(self, suffix='', framedigits=5, ext='png', rdr_fmt='PNG'): - if suffix: - suffix = '-' + suffix - if rdr_fmt in ('AVI', 'MKV'): - path = os.path.join(self.render_root, suffix, - self.designation + suffix + '.' + ext) - else: - path = os.path.join(self.render_root, suffix, self.designation, - self.designation + suffix + '-f' + '#'*framedigits + '.' + ext) - return path + def cfg_scene(self, scene=None, thru=True, exr=True, multicam=False, role='shot'): """ @@ -126,9 +112,11 @@ class LunaticsShot(object): if not scene: scene = self.scene - scene.name = self.scene_name - scene.render.filepath = self.render_path() - #os.path.join(self.render_root, 'PNG', self.designation, self.designation + '-f#####.png') + scene.name = self.pp.scene_name + + + scene.render.filepath = self.pp.render_path() # TODO - NO PARAMS - this really should + # be integrated w/ render_profiles scene.render.image_settings.file_format='PNG' scene.render.image_settings.compression = 50 scene.render.image_settings.color_mode = 'RGB' @@ -211,8 +199,9 @@ class LunaticsShot(object): exr_paint.format.color_mode = 'RGBA' exr_paint.format.color_depth = '16' exr_paint.format.exr_codec = 'ZIP' - exr_paint.base_path = os.path.join(self.render_root, 'EXR', - self.designation, self.designation + '-Paint-f#####' + '.exr') + exr_paint.base_path = os.path.join( + self.pp.render_root, self.pp.render_folder, 'EXR', + self.pp.render_stem, self.pp.render_stem + '-Paint-f#####' + '.exr') if 'Image' in exr_paint.layer_slots: exr_paint.layer_slots.remove(exr_paint.inputs['Image']) @@ -257,8 +246,9 @@ class LunaticsShot(object): exr_ink.format.color_mode = 'RGBA' exr_ink.format.color_depth = '16' exr_ink.format.exr_codec = 'ZIP' - exr_ink.base_path = os.path.join(self.render_root, 'EXR', - self.designation, self.designation + '-Ink-f#####' + '.exr') + exr_ink.base_path = os.path.join( + self.pp.render_root, self.pp.render_folder, 'EXR', + self.pp.render_stem, self.pp.render_stem + '-Ink-f#####' + '.exr') # Create EXR Ink layers and connect if 'Image' in exr_ink.layer_slots: diff --git a/abx/render_profile.py b/abx/render_profile.py index 8ac4b76..b931e0d 100644 --- a/abx/render_profile.py +++ b/abx/render_profile.py @@ -52,7 +52,7 @@ class RenderProfileMap(dict): def blender_enum_lookup(self, context): from abx import BlendFile - return RenderProfileMap(BlendFile.render_profiles).blender_enum() + return BlendFile.render_profiles.blender_enum() class RenderProfile(object): """ @@ -284,19 +284,26 @@ class RenderProfile(object): scene.render.motion_blur_samples = self.motion_blur_samples if self.format: + scene.render.filepath = scene.project_properties.render_path( + suffix = self.suffix, + framedigits = self.framedigits, + ext = self.render_formats[self.format][1], + rdr_fmt = self.render_formats[self.format][0] + ) + # prefix = scene.name_context.render_path # prefix = BlendfileContext.name_contexts[scene.name_context].render_path - - prefix = os.path.join( - scene.project_properties.render_folder, - scene.project_properties.render_prefix) - if self.suffix: - scene.render.filepath = (prefix + '-' + self.suffix + '-' + - 'f'+('#'*self.framedigits) + '.' + - self.render_formats[self.format][1]) - else: - scene.render.filepath = (prefix + '-f'+('#'*self.framedigits) + '.' + - self.render_formats[self.format][1]) + # + # prefix = os.path.join( + # scene.project_properties.render_folder, + # scene.project_properties.render_prefix) + # if self.suffix: + # scene.render.filepath = (prefix + '-' + self.suffix + '-' + + # 'f'+('#'*self.framedigits) + '.' + + # self.render_formats[self.format][1]) + # else: + # scene.render.filepath = (prefix + '-f'+('#'*self.framedigits) + '.' + + # self.render_formats[self.format][1]) \ No newline at end of file diff --git a/testdata/blendfiles/testing_project_properties.blend b/testdata/blendfiles/testing_project_properties.blend new file mode 100644 index 0000000..3ae05cb Binary files /dev/null and b/testdata/blendfiles/testing_project_properties.blend differ