import bpy import os from bpy.types import PropertyGroup from bpy.props import (BoolProperty, EnumProperty, PointerProperty, CollectionProperty, StringProperty) # region template props class RT_PG_render_toolbox_props(PropertyGroup): default_base_path : StringProperty( name="Base Path Template", description="Template for file output base path\ \nFolder containing subsequent filepath", default="//render/{node_label}/", # options={'SKIP_SAVE'} ) ## Multilayer base path : output on file instead of folder default_multilayer_base_path : StringProperty( name="Base Path Template", description="Template for multilayer file output base paths\ \nOutput of the file sequence", default="//render/{node_label}/{node_label}_", # options={'SKIP_SAVE'} ) ### file slots (not used currently) default_file_slot : StringProperty( name="File Slot Template", description="Template for file output file slots\ \nSubpath added to base path for file sequence", default="{socket_name}/{socket_name}_", # options={'SKIP_SAVE'} ) ## Multilayer's layer: layer name in EXR instead of subpath to file default_multilayer_name : StringProperty( name="Layer Name Template", description="Template for multilayer file output layer names\ \nLayer name in EXR multilayer file", default="{socket_name}", # options={'SKIP_SAVE'} ) # default_tech_pass_name : StringProperty( # name="Tech Pass Name Template", # description="Template for tech pass file output layer names\ # \nLayer name in EXR multilayer file", # default="tech", # # options={'SKIP_SAVE'} # ) # default_crypto_name : StringProperty( # name="Crypto Pass Name Template", # description="Template for crypto pass file output layer names\ # \nLayer name in EXR multilayer file", # default="crypto", # # options={'SKIP_SAVE'} # ) # endregion # region visibility states def name_search_callback(self, context, edit_text): """Search callback for collection names""" ## second arg is not displayed, can be and empty string... if self.hierarchy_type == 'COLLECTION': return [(c.name, '') for c in bpy.context.scene.collection.children_recursive if edit_text.lower() in c.name.lower()] else: return [(o.name, '') for o in bpy.context.scene.collection.all_objects if edit_text.lower() in o.name.lower()] class RT_PG_render_toolbox_conform_props(PropertyGroup): hierarchy_type: EnumProperty( name="Hierarchy Type", description="Choose whether to conform object hierarchy or collection hierarchy", items=( ('COLLECTION', "Collection Hierarchy", "Conform collection hierarchy"), ('OBJECT', "Object Hierarchy", "Conform object hierarchy"), ), default='COLLECTION' ) ## Utility prop : expose and control view layer hide state for active object ## just used for the update (actual bool value means nothing) ## can also use RT_PG_object_visibility from vis_conflict ops ## TODO: make an ops for this instead ? # active_object_viewlayer_hide : BoolProperty( # name="Active Object View Layer Hide", # description="show / hide active object in current viewlayer", # default=True, # update=toggle_viewlayer_hide_state # ) target_name: StringProperty( name="Root Item", description="Collection or object to target", # or object name # (useful for excluded collections) default="", search=name_search_callback ## basic collection fetch: # search=lambda self, context, edit_text: [(c.name, '') for c in bpy.context.scene.collection.children_recursive if edit_text.lower() in c.name.lower()] ) affect_target: EnumProperty( name="Affect Target", description="Choose whether to affect collections, objects, or both", items=[ ('COLLECTION', "Collection", "Affect collections only"), ('OBJECT', "Object", "Affect objects only"), ('ALL', "All", "Affect both collections and objects") ], default='ALL' ) ## Common object and collection conform_selectability: BoolProperty( name="Hide Select State", description="Conform hide select select", default=False ) conform_viewlayer: BoolProperty( name="Hide in Viewlayer State", description="Conform viewlayer temporary hide", default=True ) conform_viewport: BoolProperty( name="Disable in Viewports State", description="Conform the monitor icon (global viewport disable)", default=False ) conform_render: BoolProperty( name="Disable in Renders State", description="Conform the camera icon (render visibility)", default=False ) ## Specific to collections conform_exclude: BoolProperty( name="Exclude View Layer State", description="Conform the exclude from view layer", default=True ) conform_holdout: BoolProperty( name="Holdout State", description="Conform Collection Holdout State", default=True ) conform_use_indirect: BoolProperty( name="Indirect Only State", description="Conform Collection Indirect Only", default=True ) # endregion # region reset template functions def reset_scene_path_templates(): ## set default template from environment variable if available, or fallback to preferences defaults prefs = bpy.context.preferences.addons[__package__].preferences if not prefs.use_env_base_path_templates: # set from preferences bpy.context.scene.render_toolbox.default_base_path = prefs.base_path_template bpy.context.scene.render_toolbox.default_multilayer_base_path = prefs.base_path_multilayer_template return # set from environment variables (fallback to preferences if not set) exr_base_path_template = os.getenv('RENDERTOOLBOX_EXR_PATH_TEMPLATE') if exr_base_path_template: bpy.context.scene.render_toolbox.default_base_path = exr_base_path_template else: bpy.context.scene.render_toolbox.default_base_path = prefs.base_path_template multilayer_base_path_template = os.getenv('RENDERTOOLBOX_MULTILAYER_PATH_TEMPLATE') if multilayer_base_path_template: bpy.context.scene.render_toolbox.default_multilayer_base_path = multilayer_base_path_template else: bpy.context.scene.render_toolbox.default_multilayer_base_path = prefs.base_path_multilayer_template # endregion # region register classes = ( RT_PG_render_toolbox_props, RT_PG_render_toolbox_conform_props, ) def register(): for cls in classes: bpy.utils.register_class(cls) bpy.types.Scene.render_toolbox = bpy.props.PointerProperty(type=RT_PG_render_toolbox_props) bpy.types.ViewLayer.render_toolbox_conform = bpy.props.PointerProperty(type=RT_PG_render_toolbox_conform_props) # not stored, no need to unregister def unregister(): del bpy.types.Scene.render_toolbox for cls in reversed(classes): bpy.utils.unregister_class(cls)