Allow the render output path to have a {timestamp}
field
This commit is contained in:
parent
09a476e11a
commit
2187464d5e
@ -196,3 +196,51 @@ func TestSimpleBlenderRenderWindowsPaths(t *testing.T) {
|
|||||||
"fps": int64(24),
|
"fps": int64(24),
|
||||||
}, tVideo.Commands[0].Parameters)
|
}, tVideo.Commands[0].Parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSimpleBlenderRenderOutputPathFieldReplacement(t *testing.T) {
|
||||||
|
c := mockedClock(t)
|
||||||
|
|
||||||
|
s, err := Load(c)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Compiling a job should be really fast.
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
sj := exampleSubmittedJob()
|
||||||
|
sj.Settings.AdditionalProperties["render_output_path"] = "/root/{timestamp}/jobname/######"
|
||||||
|
|
||||||
|
aj, err := s.Compile(ctx, sj)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("job compiler failed: %v", err)
|
||||||
|
}
|
||||||
|
if aj == nil {
|
||||||
|
t.Fatalf("job compiler returned nil but no error")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The job compiler should have replaced the {timestamp} and {ext} fields.
|
||||||
|
assert.Equal(t, "/root/2006-01-02_090405/jobname/######", aj.Settings["render_output_path"])
|
||||||
|
|
||||||
|
// Tasks should have been created to render the frames: 1-3, 4-6, 7-9, 10, video-encoding
|
||||||
|
assert.Equal(t, 5, len(aj.Tasks))
|
||||||
|
t0 := aj.Tasks[0]
|
||||||
|
expectCliArgs := []interface{}{ // They are strings, but Goja doesn't know that and will produce an []interface{}.
|
||||||
|
"--render-output", "/root/2006-01-02_090405/jobname__intermediate-2006-01-02_090405/######",
|
||||||
|
"--render-format", sj.Settings.AdditionalProperties["format"].(string),
|
||||||
|
"--render-frame", "1-3",
|
||||||
|
}
|
||||||
|
assert.EqualValues(t, AuthoredCommandParameters{
|
||||||
|
"exe": "{blender}",
|
||||||
|
"blendfile": sj.Settings.AdditionalProperties["blendfile"].(string),
|
||||||
|
"args": expectCliArgs,
|
||||||
|
"argsBefore": make([]interface{}, 0),
|
||||||
|
}, t0.Commands[0].Parameters)
|
||||||
|
|
||||||
|
tVideo := aj.Tasks[4] // This should be a video encoding task
|
||||||
|
assert.EqualValues(t, AuthoredCommandParameters{
|
||||||
|
"input_files": "/root/2006-01-02_090405/jobname__intermediate-2006-01-02_090405/*.png",
|
||||||
|
"output_file": "/root/2006-01-02_090405/jobname__intermediate-2006-01-02_090405/scene123-1-10.mp4",
|
||||||
|
"fps": int64(24),
|
||||||
|
}, tVideo.Commands[0].Parameters)
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@ const JOB_TYPE = {
|
|||||||
{ key: "add_path_components", type: "int32", required: true, default: 0, propargs: {min: 0, max: 32},
|
{ 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"},
|
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,
|
{ 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}')",
|
eval: "str(Path(settings.render_output_root) / last_n_dir_parts(settings.add_path_components) / jobname / '{timestamp}' / '######')",
|
||||||
description: "Final file path of where render output will be saved"},
|
description: "Final file path of where render output will be saved"},
|
||||||
|
|
||||||
// Automatically evaluated settings:
|
// Automatically evaluated settings:
|
||||||
@ -62,12 +62,14 @@ function compileJob(job) {
|
|||||||
print("Blender Render job submitted");
|
print("Blender Render job submitted");
|
||||||
print("job: ", job);
|
print("job: ", job);
|
||||||
|
|
||||||
const settings = job.settings;
|
|
||||||
|
|
||||||
const renderOutput = settings.render_output_path;
|
const renderOutput = renderOutputPath(job);
|
||||||
|
job.settings.render_output_path = renderOutput;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -83,6 +85,19 @@ function compileJob(job) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do field replacement on the render output path.
|
||||||
|
function renderOutputPath(job) {
|
||||||
|
let path = job.settings.render_output_path;
|
||||||
|
return path.replace(/{([^}]+)}/g, (match, group0) => {
|
||||||
|
switch (group0) {
|
||||||
|
case "timestamp":
|
||||||
|
return formatTimestampLocal(job.created);
|
||||||
|
default:
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user