Shot Manager's Kitsu creator now allows the choice of 2D/3D camera.
This commit is contained in:
1 parent
8dcd4daad1
commit
644aa32014
2 files changed
+58
-18
No files matched your search
+56
-16
@@ -12,7 +12,7 @@ import re
|
||||
|
||||
import bpy
|
||||
from bpy.app.handlers import persistent
|
||||
from bpy.props import BoolProperty, EnumProperty, IntProperty, PointerProperty, StringProperty
|
||||
from bpy.props import BoolProperty, CollectionProperty, EnumProperty, IntProperty, PointerProperty, StringProperty
|
||||
|
||||
from . import config
|
||||
from .scene_manager import ipc
|
||||
@@ -135,14 +135,14 @@ def camera_rig_available():
|
||||
return hasattr(bpy.types, "OBJECT_OT_build_camera_rig")
|
||||
|
||||
|
||||
def _new_camera_rig(context, shot, is_3d, sequence=None):
|
||||
def _new_camera_rig(context, shot, kind, sequence=None):
|
||||
"""Camera rig built by the Add Camera Rigs add-on at the 3D cursor, named for the shot.
|
||||
Returns the camera object."""
|
||||
kind is a key of config SHOT_CAMERA_RIG_MODES ("3D", "2D"). Returns the camera object."""
|
||||
scene = context.scene
|
||||
if context.mode != "OBJECT":
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
before = {ob.as_pointer() for ob in bpy.data.objects}
|
||||
bpy.ops.object.build_camera_rig(mode=config.SHOT_CAMERA_RIG_MODES["3D" if is_3d else "2D"])
|
||||
bpy.ops.object.build_camera_rig(mode=config.SHOT_CAMERA_RIG_MODES[kind])
|
||||
# Found by difference: the add-on may also add widget objects for the bone shapes.
|
||||
new = [ob for ob in bpy.data.objects if ob.as_pointer() not in before]
|
||||
camera = next((ob for ob in new if ob.type == "CAMERA"), None)
|
||||
@@ -225,9 +225,10 @@ def kitsu_shot_state(scene, shot, only_cast):
|
||||
return "NEW"
|
||||
|
||||
|
||||
def create_kitsu_shots(context, data, is_3d, only_cast, duration):
|
||||
def create_kitsu_shots(context, data, cameras, only_cast, duration, default_camera):
|
||||
"""A camera rig and a shot for every NEW shot of the sequence, in Kitsu order, after the
|
||||
shots of the scene. Kitsu's frame count is the shot length, else duration. Returns the markers."""
|
||||
shots of the scene. The rig is cameras[shot name], else default_camera (keys of config
|
||||
SHOT_CAMERA_RIG_MODES). Kitsu's frame count is the shot length, else duration. Returns the markers."""
|
||||
scene = context.scene
|
||||
number = sequence_number(data["sequence"])
|
||||
if number is not None:
|
||||
@@ -236,7 +237,8 @@ def create_kitsu_shots(context, data, is_3d, only_cast, duration):
|
||||
for shot in data["shots"]:
|
||||
if kitsu_shot_state(scene, shot, only_cast) != "NEW":
|
||||
continue
|
||||
camera = _new_camera_rig(context, shot["shot"], is_3d, data["sequence"])
|
||||
kind = cameras.get(shot["shot"], default_camera)
|
||||
camera = _new_camera_rig(context, shot["shot"], kind, data["sequence"])
|
||||
markers.append(append_shot(context, shot["shot"], camera, shot.get("nb_frames") or duration))
|
||||
return markers
|
||||
|
||||
@@ -381,7 +383,7 @@ class WTD_OT_shot_viewer_new_shot(bpy.types.Operator):
|
||||
if not camera_rig_available():
|
||||
self.report({"WARNING"}, "Enable the Add Camera Rigs add-on to build the shot camera")
|
||||
return {"CANCELLED"}
|
||||
camera = _new_camera_rig(context, name, self.camera_3d)
|
||||
camera = _new_camera_rig(context, name, "3D" if self.camera_3d else "2D")
|
||||
else:
|
||||
camera = scene.objects.get(self.camera_name)
|
||||
if camera is None or camera.type != "CAMERA":
|
||||
@@ -513,6 +515,22 @@ class WTD_OT_shot_viewer_kitsu_sequence(bpy.types.Operator):
|
||||
|
||||
|
||||
KITSU_STATE_ICONS = {"NEW": "CAMERA_DATA", "EXISTS": "CHECKMARK", "UNCAST": "BLANK1"}
|
||||
# Camera rig choices: the keys of config SHOT_CAMERA_RIG_MODES ("3D", "2D").
|
||||
CAMERA_KIND_ITEMS = [
|
||||
(kind, kind, f"{mode.title()} camera rig (Add Camera Rigs)") for kind, mode in config.SHOT_CAMERA_RIG_MODES.items()
|
||||
]
|
||||
DEFAULT_CAMERA_KIND = "2D" if "2D" in config.SHOT_CAMERA_RIG_MODES else CAMERA_KIND_ITEMS[0][0]
|
||||
|
||||
|
||||
class WTD_KitsuShotCamera(bpy.types.PropertyGroup):
|
||||
"""Camera rig of one Kitsu shot in Build Kitsu Shots (name: the shot)."""
|
||||
|
||||
camera: EnumProperty(name="Camera", items=CAMERA_KIND_ITEMS, default=DEFAULT_CAMERA_KIND)
|
||||
|
||||
|
||||
def _all_cameras_update(self, context):
|
||||
for item in self.cameras:
|
||||
item.camera = self.camera
|
||||
|
||||
|
||||
class WTD_OT_shot_viewer_kitsu_shots(bpy.types.Operator):
|
||||
@@ -526,7 +544,14 @@ class WTD_OT_shot_viewer_kitsu_shots(bpy.types.Operator):
|
||||
description="Leave out the shots with nothing cast in Kitsu",
|
||||
default=True,
|
||||
)
|
||||
camera_3d: BoolProperty(name="3D Cameras", description="Build 3D crane rigs. Otherwise 2D camera rigs")
|
||||
camera: EnumProperty(
|
||||
name="All Cameras",
|
||||
description="Camera rig of every shot. Each shot can then be changed in its line",
|
||||
items=CAMERA_KIND_ITEMS,
|
||||
default=DEFAULT_CAMERA_KIND,
|
||||
update=_all_cameras_update,
|
||||
)
|
||||
cameras: CollectionProperty(type=WTD_KitsuShotCamera)
|
||||
duration: IntProperty(
|
||||
name="Default Duration",
|
||||
description="Length of the shots without a frame count in Kitsu",
|
||||
@@ -540,7 +565,12 @@ class WTD_OT_shot_viewer_kitsu_shots(bpy.types.Operator):
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.duration = config.SHOT_DEFAULT_DURATION
|
||||
return context.window_manager.invoke_props_dialog(self, width=420)
|
||||
self.cameras.clear()
|
||||
for shot in KITSU["shots"]:
|
||||
item = self.cameras.add()
|
||||
item.name = shot["shot"]
|
||||
item.camera = self.camera
|
||||
return context.window_manager.invoke_props_dialog(self, width=560)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -550,16 +580,24 @@ class WTD_OT_shot_viewer_kitsu_shots(bpy.types.Operator):
|
||||
for shot in KITSU["shots"]:
|
||||
state = kitsu_shot_state(scene, shot, self.only_cast)
|
||||
row = col.row()
|
||||
row.active = state == "NEW"
|
||||
row.label(text=shot["shot"], icon=KITSU_STATE_ICONS[state])
|
||||
row.label(text=f"{shot['nb_frames']} fr" if shot.get("nb_frames") else "? fr")
|
||||
info = row.row()
|
||||
info.active = state == "NEW"
|
||||
info.label(text=shot["shot"], icon=KITSU_STATE_ICONS[state])
|
||||
info.label(text=f"{shot['nb_frames']} fr" if shot.get("nb_frames") else "? fr")
|
||||
names = ", ".join(c["name"] for c in shot["casting"])
|
||||
row.label(text=names or "nothing cast")
|
||||
info.label(text=names or "nothing cast")
|
||||
choice = row.row()
|
||||
choice.ui_units_x = 5
|
||||
item = self.cameras.get(shot["shot"])
|
||||
if state == "NEW" and item is not None:
|
||||
choice.prop(item, "camera", expand=True)
|
||||
else:
|
||||
choice.label(text="")
|
||||
layout.separator()
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
layout.prop(self, "camera", expand=True)
|
||||
layout.prop(self, "only_cast")
|
||||
layout.prop(self, "camera_3d")
|
||||
layout.prop(self, "duration")
|
||||
new = [s for s in KITSU["shots"] if kitsu_shot_state(scene, s, self.only_cast) == "NEW"]
|
||||
if not new:
|
||||
@@ -574,7 +612,8 @@ class WTD_OT_shot_viewer_kitsu_shots(bpy.types.Operator):
|
||||
if not camera_rig_available():
|
||||
self.report({"WARNING"}, "Enable the Add Camera Rigs add-on to build the shot cameras")
|
||||
return {"CANCELLED"}
|
||||
markers = create_kitsu_shots(context, KITSU, self.camera_3d, self.only_cast, self.duration)
|
||||
cameras = {item.name: item.camera for item in self.cameras}
|
||||
markers = create_kitsu_shots(context, KITSU, cameras, self.only_cast, self.duration, self.camera)
|
||||
if not markers:
|
||||
self.report({"INFO"}, "Every shot is in the scene already")
|
||||
return {"CANCELLED"}
|
||||
@@ -622,6 +661,7 @@ classes = (
|
||||
WTD_OT_shot_viewer_new_shot,
|
||||
WTD_OT_shot_viewer_delete_shot,
|
||||
WTD_OT_shot_viewer_kitsu_sequence,
|
||||
WTD_KitsuShotCamera,
|
||||
WTD_OT_shot_viewer_kitsu_shots,
|
||||
WTD_OT_shot_viewer_select_rig,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user