Compute render output path when evaluating job settings
Compute render output path when evaluating job settings, which is done within the Flamenco add-on, instead of in the job compiler script. This allows the UI to show the render path, rather than it only being known after the job has been submitted.
This commit is contained in:
parent
7bfde1df0b
commit
09a476e11a
@ -1,8 +1,22 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# <pep8 compliant>
|
# <pep8 compliant>
|
||||||
|
|
||||||
|
from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
from flamenco import job_submission
|
||||||
|
from flamenco.job_types_propgroup import JobTypePropertyGroup
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from flamenco.manager.models import (
|
||||||
|
AvailableJobSetting as _AvailableJobSetting,
|
||||||
|
SubmittedJob as _SubmittedJob,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_AvailableJobSetting = object
|
||||||
|
_SubmittedJob = object
|
||||||
|
|
||||||
|
|
||||||
class FLAMENCO_PT_job_submission(bpy.types.Panel):
|
class FLAMENCO_PT_job_submission(bpy.types.Panel):
|
||||||
bl_space_type = "PROPERTIES"
|
bl_space_type = "PROPERTIES"
|
||||||
@ -10,6 +24,10 @@ class FLAMENCO_PT_job_submission(bpy.types.Panel):
|
|||||||
bl_context = "output"
|
bl_context = "output"
|
||||||
bl_label = "Flamenco 3"
|
bl_label = "Flamenco 3"
|
||||||
|
|
||||||
|
# A temporary job can be constructed so that dynamic, read-only properties can be evaluated.
|
||||||
|
# This is only scoped to a single draw() call.
|
||||||
|
job: Optional[_SubmittedJob] = None
|
||||||
|
|
||||||
def draw(self, context: bpy.types.Context) -> None:
|
def draw(self, context: bpy.types.Context) -> None:
|
||||||
from . import job_types
|
from . import job_types
|
||||||
|
|
||||||
@ -24,14 +42,20 @@ class FLAMENCO_PT_job_submission(bpy.types.Panel):
|
|||||||
row.prop(context.scene, "flamenco_job_type", text="")
|
row.prop(context.scene, "flamenco_job_type", text="")
|
||||||
row.operator("flamenco.fetch_job_types", text="", icon="FILE_REFRESH")
|
row.operator("flamenco.fetch_job_types", text="", icon="FILE_REFRESH")
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
col = layout.column(align=True)
|
||||||
|
col.prop(context.scene, "flamenco_job_name", text="Job Name")
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
self.draw_job_settings(context, layout.column(align=True))
|
self.draw_job_settings(context, layout.column(align=True))
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
col = layout.column(align=True)
|
|
||||||
col.prop(context.scene, "flamenco_job_name", text="Job Name")
|
|
||||||
|
|
||||||
self.draw_flamenco_status(context, layout)
|
self.draw_flamenco_status(context, layout)
|
||||||
|
|
||||||
|
self.job = None
|
||||||
|
|
||||||
def draw_job_settings(
|
def draw_job_settings(
|
||||||
self, context: bpy.types.Context, layout: bpy.types.UILayout
|
self, context: bpy.types.Context, layout: bpy.types.UILayout
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -48,17 +72,47 @@ class FLAMENCO_PT_job_submission(bpy.types.Panel):
|
|||||||
layout.label(text="Job Settings:")
|
layout.label(text="Job Settings:")
|
||||||
layout.use_property_split = True
|
layout.use_property_split = True
|
||||||
for setting in job_type.settings:
|
for setting in job_type.settings:
|
||||||
if not setting.get("visible", True):
|
self.draw_setting(context, layout, propgroup, setting)
|
||||||
continue
|
|
||||||
row = layout.row(align=True)
|
def draw_setting(
|
||||||
row.prop(propgroup, setting.key)
|
self,
|
||||||
setting_eval = setting.get("eval", "")
|
context: bpy.types.Context,
|
||||||
if setting_eval:
|
layout: bpy.types.UILayout,
|
||||||
props = row.operator(
|
propgroup: JobTypePropertyGroup,
|
||||||
"flamenco.eval_setting", text="", icon="SCRIPTPLUGINS"
|
setting: _AvailableJobSetting,
|
||||||
)
|
) -> None:
|
||||||
props.setting_key = setting.key
|
if not setting.get("visible", True):
|
||||||
props.setting_eval = setting_eval
|
return
|
||||||
|
|
||||||
|
if setting.get("editable", True):
|
||||||
|
self.draw_setting_editable(layout, propgroup, setting)
|
||||||
|
else:
|
||||||
|
self.draw_setting_readonly(context, layout, propgroup, setting)
|
||||||
|
|
||||||
|
def draw_setting_editable(
|
||||||
|
self,
|
||||||
|
layout: bpy.types.UILayout,
|
||||||
|
propgroup: JobTypePropertyGroup,
|
||||||
|
setting: _AvailableJobSetting,
|
||||||
|
) -> None:
|
||||||
|
row = layout.row(align=True)
|
||||||
|
row.prop(propgroup, setting.key)
|
||||||
|
setting_eval = setting.get("eval", "")
|
||||||
|
if not setting_eval:
|
||||||
|
return
|
||||||
|
|
||||||
|
props = row.operator("flamenco.eval_setting", text="", icon="SCRIPTPLUGINS")
|
||||||
|
props.setting_key = setting.key
|
||||||
|
props.setting_eval = setting_eval
|
||||||
|
|
||||||
|
def draw_setting_readonly(
|
||||||
|
self,
|
||||||
|
context: bpy.types.Context,
|
||||||
|
layout: bpy.types.UILayout,
|
||||||
|
propgroup: JobTypePropertyGroup,
|
||||||
|
setting: _AvailableJobSetting,
|
||||||
|
) -> None:
|
||||||
|
layout.prop(propgroup, setting.key)
|
||||||
|
|
||||||
def draw_flamenco_status(
|
def draw_flamenco_status(
|
||||||
self, context: bpy.types.Context, layout: bpy.types.UILayout
|
self, context: bpy.types.Context, layout: bpy.types.UILayout
|
||||||
|
@ -83,7 +83,9 @@ def eval_hidden_settings(
|
|||||||
|
|
||||||
setting_eval = setting.get("eval", "")
|
setting_eval = setting.get("eval", "")
|
||||||
if setting_eval:
|
if setting_eval:
|
||||||
value = JobTypePropertyGroup.eval_setting(context, setting_eval)
|
value = JobTypePropertyGroup.eval_setting(
|
||||||
|
context, job, setting.key, setting_eval
|
||||||
|
)
|
||||||
elif "default" in setting:
|
elif "default" in setting:
|
||||||
value = setting.default
|
value = setting.default
|
||||||
else:
|
else:
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Callable, Optional, Any
|
import pprint
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import TYPE_CHECKING, Callable, Optional, Any, Union
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
@ -14,11 +16,38 @@ if TYPE_CHECKING:
|
|||||||
AvailableJobType as _AvailableJobType,
|
AvailableJobType as _AvailableJobType,
|
||||||
AvailableJobSetting as _AvailableJobSetting,
|
AvailableJobSetting as _AvailableJobSetting,
|
||||||
JobSettings as _JobSettings,
|
JobSettings as _JobSettings,
|
||||||
|
SubmittedJob as _SubmittedJob,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
_AvailableJobType = object
|
_AvailableJobType = object
|
||||||
_AvailableJobSetting = object
|
_AvailableJobSetting = object
|
||||||
_JobSettings = object
|
_JobSettings = object
|
||||||
|
_SubmittedJob = object
|
||||||
|
|
||||||
|
|
||||||
|
class SettingEvalError(Exception):
|
||||||
|
"""Raised when the evaluation of a setting fails."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
setting_key: str,
|
||||||
|
setting_eval: str,
|
||||||
|
eval_locals: dict[str, Any],
|
||||||
|
exception: Exception,
|
||||||
|
) -> None:
|
||||||
|
self.setting_key = setting_key
|
||||||
|
self.setting_eval = setting_eval
|
||||||
|
self.locals = eval_locals.copy()
|
||||||
|
self.exception = exception
|
||||||
|
|
||||||
|
print("Evaluation error of setting %r:" % setting_key)
|
||||||
|
print("Expression: %s" % setting_eval)
|
||||||
|
print("Local variables:")
|
||||||
|
pprint.pprint(eval_locals)
|
||||||
|
print("Exception: %s" % exception)
|
||||||
|
|
||||||
|
msg = "Evaluation error of setting %r: %s" % (setting_key, exception)
|
||||||
|
super().__init__(msg)
|
||||||
|
|
||||||
|
|
||||||
class JobTypePropertyGroup:
|
class JobTypePropertyGroup:
|
||||||
@ -47,24 +76,74 @@ class JobTypePropertyGroup:
|
|||||||
|
|
||||||
return js
|
return js
|
||||||
|
|
||||||
|
def label(self, setting_key: str) -> str:
|
||||||
|
"""Return the UI label for this setting."""
|
||||||
|
return self.bl_rna.properties[setting_key].name
|
||||||
|
|
||||||
def eval_and_assign(
|
def eval_and_assign(
|
||||||
self, context: bpy.types.Context, setting_key: str, setting_eval: str
|
self,
|
||||||
|
context: bpy.types.Context,
|
||||||
|
job: _SubmittedJob,
|
||||||
|
setting_key: str,
|
||||||
|
setting_eval: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Evaluate `setting_eval` and assign the result to the job setting."""
|
"""Evaluate `setting_eval` and assign the result to the job setting."""
|
||||||
value = self.eval_setting(context, setting_eval)
|
value = self.eval_setting(context, setting_key, setting_eval)
|
||||||
setattr(self, setting_key, value)
|
setattr(self, setting_key, value)
|
||||||
|
|
||||||
@staticmethod
|
def eval_setting(
|
||||||
def eval_setting(context: bpy.types.Context, setting_eval: str) -> Any:
|
self,
|
||||||
|
context: bpy.types.Context,
|
||||||
|
setting_key: str,
|
||||||
|
setting_eval: str,
|
||||||
|
) -> Any:
|
||||||
"""Evaluate `setting_eval` and return the result."""
|
"""Evaluate `setting_eval` and return the result."""
|
||||||
|
|
||||||
eval_globals = {
|
eval_locals = {
|
||||||
"bpy": bpy,
|
"bpy": bpy,
|
||||||
"C": context,
|
"C": context,
|
||||||
|
"jobname": context.scene.flamenco_job_name,
|
||||||
|
"Path": Path,
|
||||||
|
"last_n_dir_parts": self.last_n_dir_parts,
|
||||||
|
"settings": self,
|
||||||
}
|
}
|
||||||
value = eval(setting_eval, eval_globals, {})
|
try:
|
||||||
|
value = eval(setting_eval, {}, eval_locals)
|
||||||
|
except Exception as ex:
|
||||||
|
raise SettingEvalError(setting_key, setting_eval, eval_locals, ex) from ex
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def last_n_dir_parts(n: int, filepath: Union[str, Path, None] = None) -> Path:
|
||||||
|
"""Return the last `n` parts of the directory of `filepath`.
|
||||||
|
|
||||||
|
If `n` is 0, returns an empty `Path()`.
|
||||||
|
If `filepath` is None, uses bpy.data.filepath instead.
|
||||||
|
|
||||||
|
>>> str(lastNDirParts(2, "/path/to/some/file.blend"))
|
||||||
|
"to/some"
|
||||||
|
|
||||||
|
Always returns a relative path:
|
||||||
|
>>> str(lastNDirParts(200, "C:\\path\\to\\some\\file.blend"))
|
||||||
|
"path\\to\\some"
|
||||||
|
"""
|
||||||
|
|
||||||
|
if n <= 0:
|
||||||
|
return Path()
|
||||||
|
|
||||||
|
if filepath is None:
|
||||||
|
filepath = Path(bpy.data.filepath)
|
||||||
|
elif isinstance(filepath, str):
|
||||||
|
filepath = Path(filepath)
|
||||||
|
|
||||||
|
dirpath = filepath.parent
|
||||||
|
if n >= len(dirpath.parts):
|
||||||
|
all_parts = dirpath.relative_to(dirpath.anchor)
|
||||||
|
return all_parts
|
||||||
|
|
||||||
|
subset = Path(*dirpath.parts[-n:])
|
||||||
|
return subset
|
||||||
|
|
||||||
|
|
||||||
# Mapping from AvailableJobType.setting.type to a callable that converts a value
|
# Mapping from AvailableJobType.setting.type to a callable that converts a value
|
||||||
# to the appropriate type. This is necessary due to the ambiguity between floats
|
# to the appropriate type. This is necessary due to the ambiguity between floats
|
||||||
@ -137,6 +216,19 @@ def _create_property(job_type: _AvailableJobType, setting: _AvailableJobSetting)
|
|||||||
# Remove the 'ANIMATABLE' option.
|
# Remove the 'ANIMATABLE' option.
|
||||||
prop_kwargs.setdefault("options", set())
|
prop_kwargs.setdefault("options", set())
|
||||||
|
|
||||||
|
# Add any extra arguments.
|
||||||
|
propargs = setting.get("propargs", {})
|
||||||
|
coerce_keys = {"min", "max"}
|
||||||
|
for key, value in propargs.items():
|
||||||
|
if key in coerce_keys:
|
||||||
|
propargs[key] = value_coerce(value)
|
||||||
|
prop_kwargs.update(propargs)
|
||||||
|
|
||||||
|
# Construct a getter if it's a non-editable property. By having a getter and
|
||||||
|
# not a setter, the property automatically becomes read-only in the UI.
|
||||||
|
if not setting.get("editable", True):
|
||||||
|
prop_kwargs["get"] = _create_prop_getter(job_type, setting)
|
||||||
|
|
||||||
prop_name = _job_setting_key_to_label(setting.key)
|
prop_name = _job_setting_key_to_label(setting.key)
|
||||||
prop = prop_type(name=prop_name, **prop_kwargs)
|
prop = prop_type(name=prop_name, **prop_kwargs)
|
||||||
return prop
|
return prop
|
||||||
@ -229,3 +321,22 @@ def _set_if_available(
|
|||||||
some_dict[key] = value
|
some_dict[key] = value
|
||||||
else:
|
else:
|
||||||
some_dict[key] = transform(value)
|
some_dict[key] = transform(value)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_prop_getter(
|
||||||
|
job_type: _AvailableJobType, setting: _AvailableJobSetting
|
||||||
|
) -> Callable[[JobTypePropertyGroup], Any]:
|
||||||
|
def evaluate_setting(propgroup: JobTypePropertyGroup) -> Any:
|
||||||
|
value = propgroup.eval_setting(
|
||||||
|
bpy.context,
|
||||||
|
setting.key,
|
||||||
|
setting.eval,
|
||||||
|
)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def default_value(propgroup: JobTypePropertyGroup) -> Any:
|
||||||
|
return setting.default
|
||||||
|
|
||||||
|
if setting.get("eval"):
|
||||||
|
return evaluate_setting
|
||||||
|
return default_value
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
__version__ = "4196460c-dirty"
|
__version__ = "7bfde1df-dirty"
|
||||||
|
|
||||||
# import ApiClient
|
# import ApiClient
|
||||||
from flamenco.manager.api_client import ApiClient
|
from flamenco.manager.api_client import ApiClient
|
||||||
|
@ -76,7 +76,7 @@ class ApiClient(object):
|
|||||||
self.default_headers[header_name] = header_value
|
self.default_headers[header_name] = header_value
|
||||||
self.cookie = cookie
|
self.cookie = cookie
|
||||||
# Set default User-Agent.
|
# Set default User-Agent.
|
||||||
self.user_agent = 'Flamenco/4196460c-dirty (Blender add-on)'
|
self.user_agent = 'Flamenco/7bfde1df-dirty (Blender add-on)'
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
@ -404,7 +404,7 @@ conf = flamenco.manager.Configuration(
|
|||||||
"OS: {env}\n"\
|
"OS: {env}\n"\
|
||||||
"Python Version: {pyversion}\n"\
|
"Python Version: {pyversion}\n"\
|
||||||
"Version of the API: 1.0.0\n"\
|
"Version of the API: 1.0.0\n"\
|
||||||
"SDK Package Version: 4196460c-dirty".\
|
"SDK Package Version: 7bfde1df-dirty".\
|
||||||
format(env=sys.platform, pyversion=sys.version)
|
format(env=sys.platform, pyversion=sys.version)
|
||||||
|
|
||||||
def get_host_settings(self):
|
def get_host_settings(self):
|
||||||
|
@ -9,6 +9,7 @@ Name | Type | Description | Notes
|
|||||||
**type** | [**AvailableJobSettingType**](AvailableJobSettingType.md) | |
|
**type** | [**AvailableJobSettingType**](AvailableJobSettingType.md) | |
|
||||||
**subtype** | [**AvailableJobSettingSubtype**](AvailableJobSettingSubtype.md) | | [optional]
|
**subtype** | [**AvailableJobSettingSubtype**](AvailableJobSettingSubtype.md) | | [optional]
|
||||||
**choices** | **[str]** | When given, limit the valid values to these choices. Only usable with string type. | [optional]
|
**choices** | **[str]** | When given, limit the valid values to these choices. Only usable with string type. | [optional]
|
||||||
|
**propargs** | **{str: (bool, date, datetime, dict, float, int, list, str, none_type)}** | Any extra arguments to the bpy.props.SomeProperty() call used to create this property. | [optional]
|
||||||
**description** | **bool, date, datetime, dict, float, int, list, str, none_type** | The description/tooltip shown in the user interface. | [optional]
|
**description** | **bool, date, datetime, dict, float, int, list, str, none_type** | The description/tooltip shown in the user interface. | [optional]
|
||||||
**default** | **bool, date, datetime, dict, float, int, list, str, none_type** | The default value shown to the user when determining this setting. | [optional]
|
**default** | **bool, date, datetime, dict, float, int, list, str, none_type** | The default value shown to the user when determining this setting. | [optional]
|
||||||
**eval** | **str** | Python expression to be evaluated in order to determine the default value for this setting. | [optional]
|
**eval** | **str** | Python expression to be evaluated in order to determine the default value for this setting. | [optional]
|
||||||
|
@ -93,6 +93,7 @@ class AvailableJobSetting(ModelNormal):
|
|||||||
'type': (AvailableJobSettingType,), # noqa: E501
|
'type': (AvailableJobSettingType,), # noqa: E501
|
||||||
'subtype': (AvailableJobSettingSubtype,), # noqa: E501
|
'subtype': (AvailableJobSettingSubtype,), # noqa: E501
|
||||||
'choices': ([str],), # noqa: E501
|
'choices': ([str],), # noqa: E501
|
||||||
|
'propargs': ({str: (bool, date, datetime, dict, float, int, list, str, none_type)},), # noqa: E501
|
||||||
'description': (bool, date, datetime, dict, float, int, list, str, none_type,), # noqa: E501
|
'description': (bool, date, datetime, dict, float, int, list, str, none_type,), # noqa: E501
|
||||||
'default': (bool, date, datetime, dict, float, int, list, str, none_type,), # noqa: E501
|
'default': (bool, date, datetime, dict, float, int, list, str, none_type,), # noqa: E501
|
||||||
'eval': (str,), # noqa: E501
|
'eval': (str,), # noqa: E501
|
||||||
@ -111,6 +112,7 @@ class AvailableJobSetting(ModelNormal):
|
|||||||
'type': 'type', # noqa: E501
|
'type': 'type', # noqa: E501
|
||||||
'subtype': 'subtype', # noqa: E501
|
'subtype': 'subtype', # noqa: E501
|
||||||
'choices': 'choices', # noqa: E501
|
'choices': 'choices', # noqa: E501
|
||||||
|
'propargs': 'propargs', # noqa: E501
|
||||||
'description': 'description', # noqa: E501
|
'description': 'description', # noqa: E501
|
||||||
'default': 'default', # noqa: E501
|
'default': 'default', # noqa: E501
|
||||||
'eval': 'eval', # noqa: E501
|
'eval': 'eval', # noqa: E501
|
||||||
@ -166,6 +168,7 @@ class AvailableJobSetting(ModelNormal):
|
|||||||
_visited_composed_classes = (Animal,)
|
_visited_composed_classes = (Animal,)
|
||||||
subtype (AvailableJobSettingSubtype): [optional] # noqa: E501
|
subtype (AvailableJobSettingSubtype): [optional] # noqa: E501
|
||||||
choices ([str]): When given, limit the valid values to these choices. Only usable with string type.. [optional] # noqa: E501
|
choices ([str]): When given, limit the valid values to these choices. Only usable with string type.. [optional] # noqa: E501
|
||||||
|
propargs ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): Any extra arguments to the bpy.props.SomeProperty() call used to create this property.. [optional] # noqa: E501
|
||||||
description (bool, date, datetime, dict, float, int, list, str, none_type): The description/tooltip shown in the user interface.. [optional] # noqa: E501
|
description (bool, date, datetime, dict, float, int, list, str, none_type): The description/tooltip shown in the user interface.. [optional] # noqa: E501
|
||||||
default (bool, date, datetime, dict, float, int, list, str, none_type): The default value shown to the user when determining this setting.. [optional] # noqa: E501
|
default (bool, date, datetime, dict, float, int, list, str, none_type): The default value shown to the user when determining this setting.. [optional] # noqa: E501
|
||||||
eval (str): Python expression to be evaluated in order to determine the default value for this setting.. [optional] # noqa: E501
|
eval (str): Python expression to be evaluated in order to determine the default value for this setting.. [optional] # noqa: E501
|
||||||
@ -261,6 +264,7 @@ class AvailableJobSetting(ModelNormal):
|
|||||||
_visited_composed_classes = (Animal,)
|
_visited_composed_classes = (Animal,)
|
||||||
subtype (AvailableJobSettingSubtype): [optional] # noqa: E501
|
subtype (AvailableJobSettingSubtype): [optional] # noqa: E501
|
||||||
choices ([str]): When given, limit the valid values to these choices. Only usable with string type.. [optional] # noqa: E501
|
choices ([str]): When given, limit the valid values to these choices. Only usable with string type.. [optional] # noqa: E501
|
||||||
|
propargs ({str: (bool, date, datetime, dict, float, int, list, str, none_type)}): Any extra arguments to the bpy.props.SomeProperty() call used to create this property.. [optional] # noqa: E501
|
||||||
description (bool, date, datetime, dict, float, int, list, str, none_type): The description/tooltip shown in the user interface.. [optional] # noqa: E501
|
description (bool, date, datetime, dict, float, int, list, str, none_type): The description/tooltip shown in the user interface.. [optional] # noqa: E501
|
||||||
default (bool, date, datetime, dict, float, int, list, str, none_type): The default value shown to the user when determining this setting.. [optional] # noqa: E501
|
default (bool, date, datetime, dict, float, int, list, str, none_type): The default value shown to the user when determining this setting.. [optional] # noqa: E501
|
||||||
eval (str): Python expression to be evaluated in order to determine the default value for this setting.. [optional] # noqa: E501
|
eval (str): Python expression to be evaluated in order to determine the default value for this setting.. [optional] # noqa: E501
|
||||||
|
@ -4,7 +4,7 @@ Render Farm manager API
|
|||||||
The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
The `flamenco.manager` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||||
|
|
||||||
- API version: 1.0.0
|
- API version: 1.0.0
|
||||||
- Package version: 4196460c-dirty
|
- Package version: 7bfde1df-dirty
|
||||||
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
||||||
For more information, please visit [https://flamenco.io/](https://flamenco.io/)
|
For more information, please visit [https://flamenco.io/](https://flamenco.io/)
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@ import logging
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional, TYPE_CHECKING
|
from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
|
from flamenco.job_types_propgroup import JobTypePropertyGroup
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from . import job_types, job_submission
|
from . import job_types, job_submission
|
||||||
@ -115,8 +117,13 @@ class FLAMENCO_OT_eval_setting(FlamencoOpMixin, bpy.types.Operator):
|
|||||||
setting_eval: bpy.props.StringProperty(name="Python Expression") # type: ignore
|
setting_eval: bpy.props.StringProperty(name="Python Expression") # type: ignore
|
||||||
|
|
||||||
def execute(self, context: bpy.types.Context) -> set[str]:
|
def execute(self, context: bpy.types.Context) -> set[str]:
|
||||||
propgroup = context.scene.flamenco_job_settings
|
job = job_submission.job_for_scene(context.scene)
|
||||||
propgroup.eval_and_assign(context, self.setting_key, self.setting_eval)
|
if job is None:
|
||||||
|
self.report({"ERROR"}, "This Scene has no Flamenco job")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
propgroup: JobTypePropertyGroup = context.scene.flamenco_job_settings
|
||||||
|
propgroup.eval_and_assign(context, job, self.setting_key, self.setting_eval)
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,7 +28,9 @@ func exampleSubmittedJob() api.SubmittedJob {
|
|||||||
"images_or_video": "images",
|
"images_or_video": "images",
|
||||||
"image_file_extension": ".png",
|
"image_file_extension": ".png",
|
||||||
"video_container_format": "",
|
"video_container_format": "",
|
||||||
"render_output": "/render/sprites/farm_output/promo/square_ellie/square_ellie.lighting_light_breakdown2/######",
|
"render_output_root": "/render/sprites/farm_output/promo/square_ellie",
|
||||||
|
"add_path_components": 1,
|
||||||
|
"render_output_path": "/render/sprites/farm_output/promo/square_ellie/square_ellie.lighting_light_breakdown2/######",
|
||||||
}}
|
}}
|
||||||
metadata := api.JobMetadata{
|
metadata := api.JobMetadata{
|
||||||
AdditionalProperties: map[string]string{
|
AdditionalProperties: map[string]string{
|
||||||
@ -144,7 +146,7 @@ func TestSimpleBlenderRenderWindowsPaths(t *testing.T) {
|
|||||||
|
|
||||||
// Adjust the job to get paths in Windows notation.
|
// Adjust the job to get paths in Windows notation.
|
||||||
sj.Settings.AdditionalProperties["blendfile"] = "R:\\sf\\jobs\\scene123.blend"
|
sj.Settings.AdditionalProperties["blendfile"] = "R:\\sf\\jobs\\scene123.blend"
|
||||||
sj.Settings.AdditionalProperties["render_output"] = "R:\\sprites\\farm_output\\promo\\square_ellie\\square_ellie.lighting_light_breakdown2\\######"
|
sj.Settings.AdditionalProperties["render_output_path"] = "R:\\sprites\\farm_output\\promo\\square_ellie\\square_ellie.lighting_light_breakdown2\\######"
|
||||||
|
|
||||||
aj, err := s.Compile(ctx, sj)
|
aj, err := s.Compile(ctx, sj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -7,14 +7,19 @@ const JOB_TYPE = {
|
|||||||
{ key: "chunk_size", type: "int32", default: 1, description: "Number of frames to render in one Blender render task" },
|
{ key: "chunk_size", type: "int32", default: 1, description: "Number of frames to render in one Blender render task" },
|
||||||
{ key: "frames", type: "string", required: true, eval: "f'{C.scene.frame_start}-{C.scene.frame_end}'",
|
{ key: "frames", type: "string", required: true, eval: "f'{C.scene.frame_start}-{C.scene.frame_end}'",
|
||||||
description: "Frame range to render. Examples: '47', '1-30', '3, 5-10, 47-327'" },
|
description: "Frame range to render. Examples: '47', '1-30', '3, 5-10, 47-327'" },
|
||||||
|
|
||||||
|
// render_output_root + add_path_components determine the value of render_output_path.
|
||||||
{ key: "render_output_root", type: "string", subtype: "dir_path", required: true,
|
{ key: "render_output_root", type: "string", subtype: "dir_path", required: true,
|
||||||
description: "Base directory of where render output is stored. Will have some job-specific parts appended to it"},
|
description: "Base directory of where render output is stored. Will have some job-specific parts appended to it"},
|
||||||
|
{ key: "add_path_components", type: "int32", required: true, default: 0, propargs: {min: 0, max: 32},
|
||||||
|
description: "Number of path components of the current blend file to use in the render output path"},
|
||||||
|
{ key: "render_output_path", type: "string", subtype: "file_path", editable: false,
|
||||||
|
eval: "str(Path(settings.render_output_root) / last_n_dir_parts(settings.add_path_components) / jobname / '{timestamp}' / '######.{ext}')",
|
||||||
|
description: "Final file path of where render output will be saved"},
|
||||||
|
|
||||||
// Automatically evaluated settings:
|
// Automatically evaluated settings:
|
||||||
{ key: "blender_cmd", type: "string", default: "{blender}", visible: false },
|
{ key: "blender_cmd", type: "string", default: "{blender}", visible: false },
|
||||||
{ key: "blendfile", type: "string", required: true, description: "Path of the Blend file to render", visible: false },
|
{ key: "blendfile", type: "string", required: true, description: "Path of the Blend file to render", visible: false },
|
||||||
{ key: "render_output_path", type: "string", subtype: "file_path", visible: false,
|
|
||||||
description: "Final file path of where render output is stored, set by the job compiler"},
|
|
||||||
{ key: "fps", type: "float", eval: "C.scene.render.fps / C.scene.render.fps_base", visible: false },
|
{ key: "fps", type: "float", eval: "C.scene.render.fps / C.scene.render.fps_base", visible: false },
|
||||||
{
|
{
|
||||||
key: "images_or_video",
|
key: "images_or_video",
|
||||||
@ -55,15 +60,14 @@ const videoContainerToExtension = {
|
|||||||
|
|
||||||
function compileJob(job) {
|
function compileJob(job) {
|
||||||
print("Blender Render job submitted");
|
print("Blender Render job submitted");
|
||||||
|
|
||||||
const renderOutput = renderOutputPath(job);
|
|
||||||
job.settings.render_output_path = renderOutput;
|
|
||||||
print("job: ", job);
|
print("job: ", job);
|
||||||
|
|
||||||
|
const settings = job.settings;
|
||||||
|
|
||||||
|
const renderOutput = settings.render_output_path;
|
||||||
const finalDir = path.dirname(renderOutput);
|
const finalDir = path.dirname(renderOutput);
|
||||||
const renderDir = intermediatePath(job, finalDir);
|
const renderDir = intermediatePath(job, finalDir);
|
||||||
|
|
||||||
const settings = job.settings;
|
|
||||||
const renderTasks = authorRenderTasks(settings, renderDir, renderOutput);
|
const renderTasks = authorRenderTasks(settings, renderDir, renderOutput);
|
||||||
const videoTask = authorCreateVideoTask(settings, renderDir);
|
const videoTask = authorCreateVideoTask(settings, renderDir);
|
||||||
|
|
||||||
@ -79,19 +83,6 @@ function compileJob(job) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the intended render output path.
|
|
||||||
function renderOutputPath(job) {
|
|
||||||
// {DIR}/{job name}/{date and time of job submission}/######.{extension}
|
|
||||||
const pathSafeJobName = job.name.replace(/[/\\:?*]/, "-");
|
|
||||||
const extension = guessOutputFileExtension(job.settings);
|
|
||||||
return path.join(
|
|
||||||
job.settings.render_output_root,
|
|
||||||
pathSafeJobName,
|
|
||||||
formatTimestampLocal(job.created),
|
|
||||||
`######${extension}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the intermediate render output path.
|
// Determine the intermediate render output path.
|
||||||
function intermediatePath(job, finalDir) {
|
function intermediatePath(job, finalDir) {
|
||||||
const basename = path.basename(finalDir);
|
const basename = path.basename(finalDir);
|
||||||
|
@ -403,6 +403,9 @@ components:
|
|||||||
description: When given, limit the valid values to these choices. Only usable with string type.
|
description: When given, limit the valid values to these choices. Only usable with string type.
|
||||||
type: array
|
type: array
|
||||||
items: {type: string}
|
items: {type: string}
|
||||||
|
"propargs":
|
||||||
|
description: Any extra arguments to the bpy.props.SomeProperty() call used to create this property.
|
||||||
|
type: object
|
||||||
"description":
|
"description":
|
||||||
description: The description/tooltip shown in the user interface.
|
description: The description/tooltip shown in the user interface.
|
||||||
"default":
|
"default":
|
||||||
|
@ -18,65 +18,66 @@ import (
|
|||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"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",
|
||||||
|
"+BN0ZoqB6J3hvW2vTq/+PwAA///UdlNGQjgAAA==",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
@ -135,6 +135,9 @@ type AvailableJobSetting struct {
|
|||||||
// Identifier for the setting, must be unique within the job type.
|
// Identifier for the setting, must be unique within the job type.
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
|
|
||||||
|
// Any extra arguments to the bpy.props.SomeProperty() call used to create this property.
|
||||||
|
Propargs *map[string]interface{} `json:"propargs,omitempty"`
|
||||||
|
|
||||||
// Whether to immediately reject a job definition, of this type, without this particular setting.
|
// Whether to immediately reject a job definition, of this type, without this particular setting.
|
||||||
Required *bool `json:"required,omitempty"`
|
Required *bool `json:"required,omitempty"`
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user