diff --git a/RenderWorker/VFXReviewWorker/Dtos.cs b/RenderWorker/VFXReviewWorker/Dtos.cs index 04d9337..cb60bdf 100644 --- a/RenderWorker/VFXReviewWorker/Dtos.cs +++ b/RenderWorker/VFXReviewWorker/Dtos.cs @@ -134,6 +134,8 @@ public sealed class SlateInfo public string? Description { get; set; } public string? Notes { get; set; } public string ShotCode { get; set; } = ""; + /// Production name, burned into the slate and the overlay. + public string? Show { get; set; } public string? Episode { get; set; } public string? Scene { get; set; } public string? VfxScope { get; set; } diff --git a/RenderWorker/VFXReviewWorker/VFXReviewWorker.csproj b/RenderWorker/VFXReviewWorker/VFXReviewWorker.csproj index 22db3e5..8bb313f 100644 --- a/RenderWorker/VFXReviewWorker/VFXReviewWorker.csproj +++ b/RenderWorker/VFXReviewWorker/VFXReviewWorker.csproj @@ -15,7 +15,7 @@ every change that gets published. publish.ps1 appends the git SHA via SourceRevisionId, giving "1.1.0+feb1c7b". --> - 1.1.0 + 1.2.0 diff --git a/RenderWorker/scripts/vfxr_build_preview.jsx b/RenderWorker/scripts/vfxr_build_preview.jsx index 15ce765..81c8b13 100644 --- a/RenderWorker/scripts/vfxr_build_preview.jsx +++ b/RenderWorker/scripts/vfxr_build_preview.jsx @@ -266,6 +266,27 @@ } } + // The production name, burned into both the slate and the overlay. The + // slate's other fields are title case ("Date", "Scene") while the overlay's + // are upper ("DATE", "SHOT NAME"), so both spellings are attempted rather + // than assuming which template uses which — and a template that exposes + // neither reports its actual property names instead of failing silently. + function setShowField(layer, value, label) { + var candidates = ["SHOW", "Show"]; + var i; + + if (value === null || value === undefined || value === "") { + return; + } + for (i = 0; i < candidates.length; i += 1) { + if (setEssentialProperty(layer, candidates[i], value)) { + return; + } + } + warn(label + ": no Essential Property named " + candidates.join(" or ") + + ". Available: " + listEssentialPropertyNames(layer).join(", ")); + } + function setCompStartFrame(comp, frameNumber) { try { comp.displayStartFrame = frameNumber; @@ -437,6 +458,7 @@ overlayLayer.enabled = true; setEssentialProperty(overlayLayer, "DATE", ctx.slate.date); setEssentialProperty(overlayLayer, "SHOT NAME", ctx.slate.versionName); + setShowField(overlayLayer, ctx.slate.show, "Overlay SHOW"); } else { warn("Overlay comp \"" + ctx.overlayComp + "\" not found — rendering without burn-ins"); } @@ -471,6 +493,7 @@ setEssentialProperty(slateLayer, "Episode", ctx.slate.episode); setEssentialProperty(slateLayer, "Scene", ctx.slate.scene); setEssentialProperty(slateLayer, "Frames", result.frameCount); + setShowField(slateLayer, ctx.slate.show, "Slate SHOW"); setSlateField(slateLayer, ctx.slateScopeProp, ctx.slate.vfxScope, "VFX Scope"); // The slate's Notes field carries this submission's note; when the diff --git a/VFXReviewConnector.jsx b/VFXReviewConnector.jsx index 31392fb..03d98bc 100644 --- a/VFXReviewConnector.jsx +++ b/VFXReviewConnector.jsx @@ -32,7 +32,7 @@ var SETTINGS_KEY = "cfg"; // Bump on every change deployed to a workstation. The panel reports this to // the server on load, so Pipeline → Machines shows which version each machine // is actually running and flags the ones left behind. -var PANEL_VERSION = "2.1.2"; +var PANEL_VERSION = "2.2.0"; (function VFXReviewConnector(thisObj) { var uiState = { @@ -1331,6 +1331,36 @@ var PANEL_VERSION = "2.1.2"; return null; } + // The production name, burned into both the slate and the overlay. The + // slate's fields are title case ("Date", "Scene") and the overlay's are + // upper ("DATE", "SHOT NAME"), so both spellings are attempted rather than + // assuming which template uses which. Mirrors setShowField in the worker's + // vfxr_build_preview.jsx so panel- and farm-built previews match. + function setShowProperty(layer, label) { + var value = getShowName(); + var candidates = ["SHOW", "Show"]; + var i; + + if (!value) { + return false; + } + for (i = 0; i < candidates.length; i += 1) { + if (setEssentialProperty(layer, candidates[i], value)) { + return true; + } + } + diagLog(label + ": no Essential Property named SHOW or Show on this layer"); + return false; + } + + // The production's own name, not its code: this is read off a slate. + function getShowName() { + if (!CURRENT_PROJECT) { + return ""; + } + return trimText(CURRENT_PROJECT.name || CURRENT_PROJECT.code || ""); + } + function setEssentialProperty(layer, propName, value) { try { layer.property("Essential Properties").property(propName).setValue(String(value)); @@ -1480,6 +1510,7 @@ var PANEL_VERSION = "2.1.2"; essentialProperties = overlayLayer.property("Essential Properties"); essentialProperties.property("DATE").setValue(getDateString()); essentialProperties.property("SHOT NAME").setValue(overlayShotCode + "_cmp_TT_" + (apiData.shot.shotVersion || "v001")); + setShowProperty(overlayLayer, "Overlay SHOW"); return true; } catch (overlayError) { return false; @@ -1620,6 +1651,7 @@ var PANEL_VERSION = "2.1.2"; essentialProperties = overlayLayer.property("Essential Properties"); essentialProperties.property("DATE").setValue(dateString); essentialProperties.property("SHOT NAME").setValue(shotCode + "_cmp_TT_" + (data.shot.shotVersion || "v001")); + setShowProperty(overlayLayer, "Overlay SHOW"); updated += 1; } catch (overlayError) { skipped += 1; @@ -1670,6 +1702,7 @@ var PANEL_VERSION = "2.1.2"; setEssentialProperty(slateLayer, "Episode", shot.episode); setEssentialProperty(slateLayer, "Scene", shot.scene); setEssentialProperty(slateLayer, "Frames", frameCount); + setShowProperty(slateLayer, "Slate SHOW"); shotLayer = previewComp.layer("SHOT"); var targetOutPoint = shotLayer.inPoint + shotComp.duration; diff --git a/lib/render-pipeline/preview.ts b/lib/render-pipeline/preview.ts index 0069354..07ca98f 100644 --- a/lib/render-pipeline/preview.ts +++ b/lib/render-pipeline/preview.ts @@ -37,6 +37,8 @@ export interface PreviewManifest { description: string | null; notes: string | null; shotCode: string; + /** Production name, burned into the slate and the overlay. */ + show: string | null; episode: string | null; scene: string | null; vfxScope: string | null; @@ -75,6 +77,7 @@ export async function buildPreviewManifest(exportRow: ExportForPreview): Promise description: true, notes: true, slateDescription: true, + project: { select: { name: true, code: true } }, }, }); if (!shot) throw new PipelineError(404, "Shot not found for export"); @@ -111,6 +114,8 @@ export async function buildPreviewManifest(exportRow: ExportForPreview): Promise description: shot.slateDescription ?? shot.description, notes: shot.notes, shotCode: shot.shotCode, + // The production's own name, not its code: this is read off a slate. + show: shot.project?.name ?? shot.project?.code ?? null, episode: shot.episode, scene: shot.scene, vfxScope: exportRow.vfxScope,