Shot Viewer: sequence field, cameras named CAM_sq0000_sh0000
The Shot Viewer panel gets a Sequence number, saved with the scene. New
shot cameras are named from it with SHOT_CAMERA_NAME_FORMAT
("{prefix}{sequence}_{shot}") and SEQUENCE_NAME_FORMAT ("sq{:04d}"),
both overridable in the config JSON.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c376a92591
commit
00788bb3bf
4 files changed
+44
-8
No files matched your search
@@ -254,6 +254,10 @@ Choosing a shot in the panel moves the playhead to it and puts **the 3D view you
|
||||
|
||||
The list always highlights the shot under the playhead. The file does not need any shots yet: add the first one with **+**.
|
||||
|
||||
### Sequence
|
||||
|
||||
Set the sequence number in the **Sequence** field at the top of the panel. It is saved with the scene, and the formatted name is shown next to it (`10` → `sq0010`). It is used to name the cameras of new shots: `CAM_sq0010_sh0030`. Both formats can be changed in the [Configuration](#configuration) (`SEQUENCE_NAME_FORMAT`, `SHOT_CAMERA_NAME_FORMAT`).
|
||||
|
||||
### Moving through the sequence
|
||||
|
||||
| To… | Do… |
|
||||
@@ -275,7 +279,7 @@ Click **+** next to the shot list:
|
||||
|---|---|
|
||||
| **Name** | Pre-filled with the next free shot number (`sh0010`, `sh0020`…). This is the marker name. |
|
||||
| **Duration** | Length of the shot in frames. |
|
||||
| **New Camera** | On: creates the camera `CAM_<shot name>`, copying the lens and position of the current camera, so you start from the current framing. Off: pick an existing camera of the scene. |
|
||||
| **New Camera** | On: creates the camera `CAM_<sequence>_<shot>` (its name is shown in the dialog), copying the lens and position of the current camera, so you start from the current framing. Off: pick an existing camera of the scene. |
|
||||
|
||||
The shot is added at the end of the sequence and the scene's **End** frame grows to include it. The first shot starts at frame 1001, and the scene **Start** moves there too. The playhead and the 3D view then jump to the new shot.
|
||||
|
||||
@@ -316,6 +320,7 @@ To change them **without editing the code**, write a JSON file with the keys to
|
||||
"RESOLUTION": [1920, 1080],
|
||||
"RENAME_SIDES": ["center", "left", "right"],
|
||||
"SHOT_FRAME_START": 1001,
|
||||
"SEQUENCE_NAME_FORMAT": "sq{:03d}",
|
||||
"SHOT_VIEWER_RIG_GROUPS": {
|
||||
"Characters": "(?i)^(?:chr|ch)[_-]"
|
||||
}
|
||||
@@ -324,6 +329,8 @@ To change them **without editing the code**, write a JSON file with the keys to
|
||||
|
||||
Unknown keys are ignored and reported in the system console.
|
||||
|
||||
Name formats use Python's `str.format`: `"sq{:04d}"` turns `10` into `sq0010`. `SHOT_CAMERA_NAME_FORMAT` takes the named tokens `{prefix}` (the camera prefix of `OBJECT_PREFIXES`, `CAM_`), `{sequence}` and `{shot}`. The default `"{prefix}{sequence}_{shot}"` gives `CAM_sq0010_sh0030`.
|
||||
|
||||
### Keys by tool
|
||||
|
||||
| Tool | Keys |
|
||||
@@ -336,7 +343,7 @@ Unknown keys are ignored and reported in the system console.
|
||||
| Sanity Check: layout | `SET_COLLECTION_PATTERN` |
|
||||
| Sanity Check: panel | `CATEGORY_ORDER`, `MAX_ISSUES_DRAWN` |
|
||||
| Rename | `RENAME_SEPARATOR`, `RENAME_PADDING`, `RENAME_SIDES`, `RENAME_TYPE_SUFFIXES` (plus `OBJECT_PREFIXES` / `DATABLOCK_PREFIXES` for *By Type* prefixes) |
|
||||
| Shot Viewer | `SHOT_VIEWER_RIG_GROUPS`, `SHOT_NAME_FORMAT`, `SHOT_NUMBER_STEP`, `SHOT_FRAME_START`, `SHOT_DEFAULT_DURATION` |
|
||||
| Shot Viewer | `SHOT_VIEWER_RIG_GROUPS`, `SHOT_NAME_FORMAT`, `SHOT_NUMBER_STEP`, `SHOT_FRAME_START`, `SHOT_DEFAULT_DURATION`, `SEQUENCE_NAME_FORMAT`, `SHOT_CAMERA_NAME_FORMAT` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -246,6 +246,11 @@ SHOT_VIEWER_RIG_GROUPS = {
|
||||
|
||||
# Shots added by the shot viewer. TODO: confirm with production.
|
||||
SHOT_NAME_FORMAT = "sh{:04d}"
|
||||
# Sequence of the scene (number set in the Shot Viewer panel): SEQUENCE_NAME_FORMAT.format(number).
|
||||
SEQUENCE_NAME_FORMAT = "sq{:04d}"
|
||||
# Cameras added by the shot viewer. Tokens: {prefix} (OBJECT_PREFIXES["CAMERA"]),
|
||||
# {sequence} (SEQUENCE_NAME_FORMAT) and {shot} (the shot name).
|
||||
SHOT_CAMERA_NAME_FORMAT = "{prefix}{sequence}_{shot}"
|
||||
SHOT_NUMBER_STEP = 10
|
||||
SHOT_FRAME_START = 1001
|
||||
SHOT_DEFAULT_DURATION = 48
|
||||
|
||||
+26
-6
@@ -110,16 +110,27 @@ def next_shot_name(scene):
|
||||
return config.SHOT_NAME_FORMAT.format((max(numbers, default=0) // step + 1) * step)
|
||||
|
||||
|
||||
def _new_camera(scene, name, source=None):
|
||||
def sequence_name(scene):
|
||||
return config.SEQUENCE_NAME_FORMAT.format(scene.wtd_sequence)
|
||||
|
||||
|
||||
def camera_name(scene, shot):
|
||||
"""Name of a new shot camera (config SHOT_CAMERA_NAME_FORMAT)."""
|
||||
return config.SHOT_CAMERA_NAME_FORMAT.format(
|
||||
prefix=config.OBJECT_PREFIXES.get("CAMERA", ""), sequence=sequence_name(scene), shot=shot
|
||||
)
|
||||
|
||||
|
||||
def _new_camera(scene, shot, source=None):
|
||||
"""New camera in the scene collection, copying ``source`` (lens and placement) when given."""
|
||||
camera_name = config.OBJECT_PREFIXES.get("CAMERA", "") + name
|
||||
name = camera_name(scene, shot)
|
||||
if source is not None and source.type == "CAMERA":
|
||||
data = source.data.copy()
|
||||
data.name = camera_name
|
||||
data.name = name
|
||||
else:
|
||||
source = None
|
||||
data = bpy.data.cameras.new(camera_name)
|
||||
camera = bpy.data.objects.new(camera_name, data)
|
||||
data = bpy.data.cameras.new(name)
|
||||
camera = bpy.data.objects.new(name, data)
|
||||
if source is not None:
|
||||
camera.matrix_world = source.matrix_world.copy()
|
||||
else:
|
||||
@@ -231,7 +242,10 @@ class WTD_OT_shot_viewer_new_shot(bpy.types.Operator):
|
||||
layout.prop(self, "name")
|
||||
layout.prop(self, "duration")
|
||||
layout.prop(self, "new_camera")
|
||||
if not self.new_camera:
|
||||
if self.new_camera:
|
||||
name = self.name.strip() or next_shot_name(context.scene)
|
||||
layout.label(text=camera_name(context.scene, name), icon="CAMERA_DATA")
|
||||
else:
|
||||
layout.prop_search(self, "camera_name", context.scene, "objects", icon="CAMERA_DATA")
|
||||
|
||||
def execute(self, context):
|
||||
@@ -358,12 +372,18 @@ def register():
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
bpy.types.WindowManager.wtd_shot_viewer = PointerProperty(type=WTD_ShotViewerSettings)
|
||||
bpy.types.Scene.wtd_sequence = IntProperty(
|
||||
name="Sequence",
|
||||
description="Sequence number of the scene, used in the names of new cameras (config SEQUENCE_NAME_FORMAT)",
|
||||
min=0,
|
||||
)
|
||||
bpy.app.handlers.frame_change_post.append(_on_frame_change)
|
||||
|
||||
|
||||
def unregister():
|
||||
if _on_frame_change in bpy.app.handlers.frame_change_post:
|
||||
bpy.app.handlers.frame_change_post.remove(_on_frame_change)
|
||||
del bpy.types.Scene.wtd_sequence
|
||||
del bpy.types.WindowManager.wtd_shot_viewer
|
||||
for cls in reversed(classes):
|
||||
bpy.utils.unregister_class(cls)
|
||||
@@ -283,6 +283,10 @@ class _ShotViewerPanel:
|
||||
scene = context.scene
|
||||
has_shots = bool(shot_viewer.shots(scene))
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(scene, "wtd_sequence")
|
||||
row.label(text=shot_viewer.sequence_name(scene))
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.scale_y = 1.4
|
||||
row.enabled = has_shots
|
||||
|
||||
Reference in new issue
Block a user