[Bf-extensions-cvs] [f4cf9b00] master: Add camera rigs: add 2D camera rig

Damien Picard noreply at git.blender.org
Mon Mar 9 12:09:33 CET 2020


Commit: f4cf9b00db36bf096e1cf5ad50127ade8b985dd2
Author: Damien Picard
Date:   Fri Jan 24 10:30:51 2020 +0100
Branches: master
https://developer.blender.org/rBAf4cf9b00db36bf096e1cf5ad50127ade8b985dd2

Add camera rigs: add 2D camera rig

This rig is mostly useful for 2D shots, when the camera is static and
the action happens in front of it (like a theatre stage).

In a 2D production (and some shots in 3D as well), you sometimes need
to rotate the camera while zooming, effectively "cropping" the field,
just as you would using a rostrum camera. This is tedious and
error-prone if animating built-in basic transforms, so this rig
implements a more intuitive way to do that, by just animating the two
lower corners of the camera's field.

Also improved other stuff in the add-on:
- add the GPL license block to create_widgets.py;
- rename "arm[ature]" to "rig" in some functions, for consistency and
  to avoid confusion with the crane's arm;
- changes to the UI panel:
  - remove the boxes,
  - put focal length at the top of the panel,
  - group related properties using aligned columns,
  - change the Make Camera Active operator's poll method, so that it
    is always visible in the UI, but greyed out when the camera is
    already active.

===================================================================

M	add_camera_rigs/__init__.py
M	add_camera_rigs/build_rigs.py
M	add_camera_rigs/composition_guides_menu.py
M	add_camera_rigs/create_widgets.py
M	add_camera_rigs/operators.py
M	add_camera_rigs/ui_panels.py

===================================================================

diff --git a/add_camera_rigs/__init__.py b/add_camera_rigs/__init__.py
index 6b577199..6f9f9eeb 100644
--- a/add_camera_rigs/__init__.py
+++ b/add_camera_rigs/__init__.py
@@ -18,8 +18,8 @@
 
 bl_info = {
     "name": "Add Camera Rigs",
-    "author": "Wayne Dixon, Brian Raschko, Kris Wittig, Damien Picard",
-    "version": (1, 4, 2),
+    "author": "Wayne Dixon, Brian Raschko, Kris Wittig, Damien Picard, Flavio Perez",
+    "version": (1, 4, 3),
     "blender": (2, 80, 0),
     "location": "View3D > Add > Camera > Dolly or Crane Rig",
     "description": "Adds a Camera Rig with UI",
diff --git a/add_camera_rigs/build_rigs.py b/add_camera_rigs/build_rigs.py
index 1a37bc6e..57cadc0e 100644
--- a/add_camera_rigs/build_rigs.py
+++ b/add_camera_rigs/build_rigs.py
@@ -17,18 +17,33 @@
 # ##### END GPL LICENSE BLOCK #####
 
 import bpy
-from bpy_extras import object_utils
 from bpy.types import Operator
-from math import radians, pi
+from bpy_extras import object_utils
+from mathutils import Vector
 from rna_prop_ui import rna_idprop_ui_prop_get
+from math import pi
+
 from .create_widgets import (create_root_widget,
-                             create_widget,
-                             create_camera_widget,
-                             create_aim_widget,
-                             )
+                             create_camera_widget, create_aim_widget,
+                             create_circle_widget, create_corner_widget)
+
+
+def create_prop_driver(rig, cam, prop_from, prop_to):
+    """Create driver to a property on the rig"""
+    driver = cam.data.driver_add(prop_to)
+    driver.driver.type = 'SCRIPTED'
+    var = driver.driver.variables.new()
+    var.name = 'var'
+    var.type = 'SINGLE_PROP'
 
+    # Target the custom bone property
+    var.targets[0].id = rig
+    var.targets[0].data_path = 'pose.bones["Camera"]["%s"]' % prop_from
+    driver.driver.expression = 'var'
 
-def create_dolly_bones(rig, bone_layers):
+
+def create_dolly_bones(rig):
+    """Create bones for the dolly camera rig"""
     bones = rig.data.edit_bones
 
     # Add new bones
@@ -39,7 +54,7 @@ def create_dolly_bones(rig, bone_layers):
     ctrl_aim_child = bones.new("Aim_shape_rotation-MCH")
     ctrl_aim_child.head = (0.0, 10.0, 1.7)
     ctrl_aim_child.tail = (0.0, 11.0, 1.7)
-    ctrl_aim_child.layers = bone_layers
+    ctrl_aim_child.layers = tuple(i == 1 for i in range(32))
 
     ctrl_aim = bones.new("Aim")
     ctrl_aim.head = (0.0, 10.0, 1.7)
@@ -57,7 +72,8 @@ def create_dolly_bones(rig, bone_layers):
     ctrl_aim_child.parent = ctrl_aim
 
 
-def create_crane_bones(rig, bone_layers):
+def create_crane_bones(rig):
+    """Create bones for the crane camera rig"""
     bones = rig.data.edit_bones
 
     # Add new bones
@@ -68,7 +84,7 @@ def create_crane_bones(rig, bone_layers):
     ctrl_aim_child = bones.new("Aim_shape_rotation-MCH")
     ctrl_aim_child.head = (0.0, 10.0, 1.7)
     ctrl_aim_child.tail = (0.0, 11.0, 1.7)
-    ctrl_aim_child.layers = bone_layers
+    ctrl_aim_child.layers = tuple(i == 1 for i in range(32))
 
     ctrl_aim = bones.new("Aim")
     ctrl_aim.head = (0.0, 10.0, 1.7)
@@ -112,34 +128,13 @@ def create_crane_bones(rig, bone_layers):
     pose_bones["Crane_height"].lock_scale = (True, False, True)
 
 
-def build_camera_rig(context, mode):
-    bone_layers = tuple(i == 1 for i in range(32))
-    view_layer = bpy.context.view_layer
-
-    rig_name = mode.capitalize() + "_Rig"
-    rig_data = bpy.data.armatures.new(rig_name)
-    rig = object_utils.object_data_add(context, rig_data, name=rig_name)
-    rig["rig_id"] = "%s" % rig_name
-    view_layer.objects.active = rig
-    rig.location = context.scene.cursor.location
-
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    # Add new bones
-    if mode == "DOLLY":
-        create_dolly_bones(rig, bone_layers)
-    elif mode == "CRANE":
-        create_crane_bones(rig, bone_layers)
-
+def setup_3d_rig(rig, cam):
+    """Finish setting up Dolly and Crane rigs"""
     # Jump into object mode and change bones to euler
     bpy.ops.object.mode_set(mode='OBJECT')
     pose_bones = rig.pose.bones
-    for b in pose_bones:
-        b.rotation_mode = 'XYZ'
-
-    # Add custom properties to the armature’s Camera bone,
-    # so that all properties may be animated in a single action
-    # Add driver after the camera is created
+    for bone in pose_bones:
+        bone.rotation_mode = 'XYZ'
 
     # Lens property
     pb = pose_bones['Camera']
@@ -150,22 +145,6 @@ def build_camera_rig(context, mode):
     prop["max"] = 1000000.0
     prop["soft_max"] = 5000.0
 
-    # DOF Focus Distance property
-    pb = pose_bones['Camera']
-    pb["focus_distance"] = 10.0
-    prop = rna_idprop_ui_prop_get(pb, "focus_distance", create=True)
-    prop["default"] = 10.0
-    prop["min"] = 0.0
-
-    # DOF F-Stop property
-    pb = pose_bones['Camera']
-    pb["aperture_fstop"] = 2.8
-    prop = rna_idprop_ui_prop_get(pb, "aperture_fstop", create=True)
-    prop["default"] = 2.8
-    prop["min"] = 0.0
-    prop["soft_min"] = 0.1
-    prop["soft_max"] = 128.0
-
     # Build the widgets
     root_widget = create_root_widget("Camera_Root")
     camera_widget = create_camera_widget("Camera")
@@ -176,7 +155,7 @@ def build_camera_rig(context, mode):
     pose_bones["Aim"].custom_shape = aim_widget
     pose_bones["Camera"].custom_shape = camera_widget
 
-    # Set the "At" field to the child
+    # Set the "At" field to the shape mecanism
     pose_bones["Aim"].custom_shape_transform = pose_bones["Aim_shape_rotation-MCH"]
 
     # Add constraints to bones
@@ -189,55 +168,359 @@ def build_camera_rig(context, mode):
     con.subtarget = "Aim"
     con.use_target_z = True
 
-    # Change display to BBone: it just looks nicer
-    bpy.context.object.data.display_type = 'BBONE'
-    # Change display to wire for object
-    bpy.context.object.display_type = 'WIRE'
+    cam.data.display_size = 1.0
+    cam.rotation_euler[0] = pi / 2.0  # Rotate the camera 90 degrees in x
+
+    create_prop_driver(rig, cam, "lens", "lens")
+
+
+def create_2d_bones(context, rig, cam):
+    """Create bones for the 2D camera rig"""
+    scene = context.scene
+    bones = rig.data.edit_bones
+
+    # Add new bones
+    bones = rig.data.edit_bones
+    root = bones.new("Root")
+    root.tail = Vector((0.0, 0.0, 1.0))
+    root.show_wire = True
+
+    ctrl = bones.new('Camera')
+    ctrl.tail = Vector((0.0, 0.0, 1.0))
+    ctrl.show_wire = True
+
+    left_corner = bones.new("Left_corner")
+    left_corner.head = (-3, 10, -2)
+    left_corner.tail = left_corner.head + Vector((0.0, 0.0, 1.0))
+    left_corner.show_wire = True
+
+    right_corner = bones.new("Right_corner")
+    right_corner.head = (3, 10, -2)
+    right_corner.tail = right_corner.head + Vector((0.0, 0.0, 1.0))
+    right_corner.show_wire = True
 
+    corner_distance_x = (left_corner.head - right_corner.head).length
+    corner_distance_y = -left_corner.head.z
+    corner_distance_z = left_corner.head.y
+
+    center = bones.new("Center-MCH")
+    center.head = ((right_corner.head + left_corner.head) / 2.0)
+    center.tail = center.head + Vector((0.0, 0.0, 1.0))
+    center.layers = tuple(i == 1 for i in range(32))
+    center.show_wire = True
+
+    # Setup hierarchy
+    ctrl.parent = root
+    left_corner.parent = root
+    right_corner.parent = root
+    center.parent = root
+
+    # Jump into object mode and change bones to euler
+    bpy.ops.object.mode_set(mode='OBJECT')
+    pose_bones = rig.pose.bones
+    for bone in pose_bones:
+        bone.rotation_mode = 'XYZ'
+
+    # Bone drivers
+    center_drivers = pose_bones["Center-MCH"].driver_add("location")
+
+    # Center X driver
+    driver = center_drivers[0].driver
+    driver.type = 'AVERAGE'
+
+    for corner in ('left', 'right'):
+        var = driver.variables.new()
+        var.name = corner
+        var.type = 'TRANSFORMS'
+        var.targets[0].id = rig
+        var.targets[0].bone_target = corner.capitalize() + '_corner'
+        var.targets[0].transform_type = 'LOC_X'
+        var.targets[0].transform_space = 'TRANSFORM_SPACE'
+
+    # Center Y driver
+    driver = center_drivers[1].driver
+    driver.type = 'SCRIPTED'
+
+    driver.expression = '({distance_x} - (left_x-right_x))*(res_y/res_x)/2 + (left_y + right_y)/2'.format(distance_x=corner_distance_x)
+
+    for direction in ('x', 'y'):
+        for corner in ('left', 'right'):
+            var = driver.variables.new()
+            var.name = '%s_%s' % (corner, direction)
+            var.type = 'TRANSFORMS'
+            var.targets[0].id = rig
+            var.targets[0].bone_target = corner.capitalize() + '_corner'
+            var.targets[0].transform_type = 'LOC_' + direction.upper()
+            var.targets[0].transform_space = 'TRANSFORM_SPACE'
+
+        var = driver.variables.new()
+        var.name = 'res_' + direction
+        var.type = 'SINGLE_PROP'
+        var.targets[0].id_type = 'SCENE'
+        var.targets[0].id = scene
+        var.targets[0].data_path = 'render.resolution_' + direction
+
+    # Center Z driver
+    driver = center_drivers[2].driver
+    driver.type = 'AVERAGE'
+
+    for corner in ('left', 'right'):
+        var = driver.variables.new()
+        var.name = corner
+        var.type = 'TRANSFORMS'
+        var.targets[0].id = rig
+        var.targets[0].bone_target = corner.capitalize() + '_corner'
+        var.targets[0].transform_type = 'LOC_Z'
+        var.targets[0].transform_space = 'TRANSFORM_SPACE'
+
+    # Bone constraints
+    con = pose_bones["Camera"].constraints.new('DAMPED_TRACK')
+    con.target = rig
+    con.subtarget = "Center-MCH"
+    con.track_axis = 'TRACK_NEGATIVE_Z'
+
+    # Build the widgets
+    left_widget = create_corner_widget("Left_corner", reverse=True)
+    right_widget = create_corner_widget("Right_corner")
+    parent_widget = create_circle_widget("Root", radius=0.5)
+    camera_widget = create_circle_widget("Camera_2D", radius=0.3)
+
+    # Add the custom bone shapes
+    pose_bones["Left_corner"].custom_shape = left_widget
+    pose_bones["Right_corner"].custom_shape = right_widget
+    pose_bones["Root"].custom_shape = parent_widget
+    pose_bones["Camera"].custom_shape = camera_widget
+
+ 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list