diff --git a/addon/flamenco/gui.py b/addon/flamenco/gui.py index d9697f75..fc913044 100644 --- a/addon/flamenco/gui.py +++ b/addon/flamenco/gui.py @@ -95,8 +95,12 @@ class FLAMENCO_PT_job_submission(bpy.types.Panel): return row = layout.row(align=True) + if setting.get("editable", True): - self.draw_setting_editable(row, propgroup, setting) + if job_types.setting_can_autoeval(setting): + self.draw_setting_autoeval(row, propgroup, setting) + else: + self.draw_setting_editable(row, propgroup, setting) else: self.draw_setting_readonly(context, row, propgroup, setting) @@ -132,6 +136,30 @@ class FLAMENCO_PT_job_submission(bpy.types.Panel): ) -> None: layout.prop(propgroup, setting.key) + def draw_setting_autoeval( + self, + layout: bpy.types.UILayout, + propgroup: JobTypePropertyGroup, + setting: _AvailableJobSetting, + ) -> None: + autoeval_enabled = job_types.setting_should_autoeval(propgroup, setting) + if autoeval_enabled: + label = propgroup.bl_rna.properties[setting.key].name + layout.prop( + propgroup, + job_types.setting_autoeval_propname(setting), + text=label, + icon="AUTO", + ) + else: + self.draw_setting_editable(layout, propgroup, setting) + layout.prop( + propgroup, + job_types.setting_autoeval_propname(setting), + text="", + icon="AUTO", + ) + def draw_flamenco_status( self, context: bpy.types.Context, layout: bpy.types.UILayout ) -> None: diff --git a/addon/flamenco/job_types.py b/addon/flamenco/job_types.py index db60e8a7..fe34411f 100644 --- a/addon/flamenco/job_types.py +++ b/addon/flamenco/job_types.py @@ -68,6 +68,30 @@ def setting_is_visible(setting: _AvailableJobSetting) -> bool: return str(visibility) in {"visible", "submission"} +def setting_should_autoeval( + propgroup: job_types_propgroup.JobTypePropertyGroup, + setting: _AvailableJobSetting, +) -> bool: + if not setting_is_visible(setting): + # Invisible settings are there purely to be auto-evaluated. + return True + + propname = setting_autoeval_propname(setting) + return getattr(propgroup, propname, False) + + +def setting_can_autoeval(setting: _AvailableJobSetting) -> bool: + # Note that this uses the Pythonified name; that's done by the OpenAPI code generator. + can: bool = setting.get("autoeval_lockable", False) + print(f"setting_can_autoeval({setting.key}: {can})") + return can + + +def setting_autoeval_propname(setting: _AvailableJobSetting) -> str: + """Return the property name of the 'auto-eval' state for this setting.""" + return f"autoeval_{setting.key}" + + def _store_available_job_types(available_job_types: _AvailableJobTypes) -> None: global _available_job_types global _job_type_enum_items diff --git a/addon/flamenco/job_types_propgroup.py b/addon/flamenco/job_types_propgroup.py index 348d71e6..84e42c36 100644 --- a/addon/flamenco/job_types_propgroup.py +++ b/addon/flamenco/job_types_propgroup.py @@ -131,8 +131,7 @@ class JobTypePropertyGroup: setting value. Otherwise the default is used. """ for setting in self.job_type.settings: - if job_types.setting_is_visible(setting): - # Skip those settings that will be visible in the GUI. + if not job_types.setting_should_autoeval(self, setting): continue setting_eval = setting.get("eval", "") @@ -253,10 +252,16 @@ def generate(job_type: _AvailableJobType) -> type[JobTypePropertyGroup]: ) pg_type.__annotations__ = {} + # Add RNA properties for the settings. for setting in job_type.settings: prop = _create_property(job_type, setting) pg_type.__annotations__[setting.key] = prop + if job_types.setting_can_autoeval(setting): + # Add RNA property for the 'auto-eval' toggle. + propname, prop = _create_autoeval_property(setting) + pg_type.__annotations__[propname] = prop + assert issubclass(pg_type, JobTypePropertyGroup), "did not expect type %r" % type( pg_type ) @@ -304,6 +309,29 @@ def _create_property(job_type: _AvailableJobType, setting: _AvailableJobSetting) return prop +def _create_autoeval_property( + setting: _AvailableJobSetting, +) -> tuple[str, Any]: + from flamenco.manager.model.available_job_setting import AvailableJobSetting + + assert isinstance(setting, AvailableJobSetting) + + setting_name = _job_setting_key_to_label(setting.key) + prop_descr = ( + "Automatically determine the value for %r when the job gets submitted" + % setting_name + ) + + prop = bpy.props.BoolProperty( + name="Auto Evaluate %s" % setting_name, + description=prop_descr, + default=True, + ) + + prop_name = job_types.setting_autoeval_propname(setting) + return prop_name, prop + + def _find_prop_type( job_type: _AvailableJobType, setting: _AvailableJobSetting ) -> tuple[Any, dict[str, Any]]: diff --git a/internal/manager/job_compilers/scripts/simple_blender_render.js b/internal/manager/job_compilers/scripts/simple_blender_render.js index d980991d..411477e4 100644 --- a/internal/manager/job_compilers/scripts/simple_blender_render.js +++ b/internal/manager/job_compilers/scripts/simple_blender_render.js @@ -5,6 +5,7 @@ const JOB_TYPE = { settings: [ // Settings for artists to determine: { key: "frames", type: "string", required: true, eval: "f'{C.scene.frame_start}-{C.scene.frame_end}'", + autoevalLockable: true, description: "Frame range to render. Examples: '47', '1-30', '3, 5-10, 47-327'" }, { key: "chunk_size", type: "int32", default: 1, description: "Number of frames to render in one Blender render task", visible: "submission" },