diff --git a/add_camera_rigs/__init__.py b/add_camera_rigs/__init__.py index 9d296e6ceee5dffa71c48b279c9e611181e93fed..9c742e6ab81f37fa46ecfebb0107b58937d58c4e 100644 --- a/add_camera_rigs/__init__.py +++ b/add_camera_rigs/__init__.py @@ -16,11 +16,10 @@ # # ##### END GPL LICENSE BLOCK ##### - bl_info = { "name": "Add Camera Rigs", - "author": "Wayne Dixon, Brian Raschko, Kris Wittig", - "version": (1, 4, 1), + "author": "Wayne Dixon, Brian Raschko, Kris Wittig, Damien Picard", + "version": (1, 4, 2), "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 c73031983dd8729a182dd51559aee6b3d3dbb1d1..1a37bc6e530a0956212727d69fe601db2c6415e0 100644 --- a/add_camera_rigs/build_rigs.py +++ b/add_camera_rigs/build_rigs.py @@ -1,6 +1,25 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + import bpy +from bpy_extras import object_utils from bpy.types import Operator -from math import radians +from math import radians, pi from rna_prop_ui import rna_idprop_ui_prop_get from .create_widgets import (create_root_widget, create_widget, @@ -9,518 +28,254 @@ from .create_widgets import (create_root_widget, ) -def build_dolly_rig(context): - """Operator to build the dolly rig""" - # Set the bone layers - boneLayer = (False, True, False, False, False, False, False, False, - False, False, False, False, False, False, False, False, - False, False, False, False, False, False, False, False, - False, False, False, False, False, False, False, False) - - # Add the new armature object: - bpy.ops.object.armature_add() - rig = context.active_object - - # it will try to name the rig "Dolly_rig" but if that name exists it will - # add 000 to the name - if "Dolly_rig" not in context.scene.objects: - rig.name = "Dolly_rig" - else: - rig.name = "Dolly_rig.000" - rig["rig_id"] = "Dolly_rig" - - bpy.ops.object.mode_set(mode='EDIT') - - # Remove default bone: +def create_dolly_bones(rig, bone_layers): bones = rig.data.edit_bones - bones.remove(bones[0]) - # Add new bones: + # Add new bones root = bones.new("Root") - root.tail = (0.0, 3.0, 0.0) + root.tail = (0.0, 1.0, 0.0) + root.show_wire = True - bpy.ops.object.mode_set(mode='EDIT') - ctrlAimChild = bones.new("aim_MCH") - ctrlAimChild.head = (0.0, 5.0, 3.0) - ctrlAimChild.tail = (0.0, 7.0, 3.0) - ctrlAimChild.layers = boneLayer + 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 - ctrlAim = bones.new("Aim") - ctrlAim.head = (0.0, 5.0, 3.0) - ctrlAim.tail = (0.0, 7.0, 3.0) + ctrl_aim = bones.new("Aim") + ctrl_aim.head = (0.0, 10.0, 1.7) + ctrl_aim.tail = (0.0, 11.0, 1.7) + ctrl_aim.show_wire = True ctrl = bones.new("Camera") - ctrl.head = (0.0, 0.0, 3.0) - ctrl.tail = (0.0, 2.0, 3.0) + ctrl.head = (0.0, 0.0, 1.7) + ctrl.tail = (0.0, 1.0, 1.7) + ctrl.show_wire = True - # Setup hierarchy: + # Setup hierarchy ctrl.parent = root - ctrlAim.parent = root - ctrlAimChild.parent = ctrlAim - - # jump into pose mode and change bones to euler - bpy.ops.object.mode_set(mode='POSE') - for x in bpy.context.object.pose.bones: - x.rotation_mode = 'XYZ' - - # jump into pose mode and add the custom bone shapes - bpy.ops.object.mode_set(mode='POSE') - bpy.context.object.pose.bones["Root"].custom_shape = bpy.data.objects[ - "WDGT_Camera_root"] # add the widget as custom shape - # set the wireframe checkbox to true - bpy.context.object.data.bones["Root"].show_wire = True - bpy.context.object.pose.bones[ - "Aim"].custom_shape = bpy.data.objects["WDGT_Aim"] - bpy.context.object.data.bones["Aim"].show_wire = True - bpy.context.object.pose.bones["Aim"].custom_shape_transform = bpy.data.objects[ - rig.name].pose.bones["aim_MCH"] # sets the "At" field to the child - bpy.context.object.pose.bones[ - "Camera"].custom_shape = bpy.data.objects["WDGT_Camera"] - bpy.context.object.data.bones["Camera"].show_wire = True - - # jump into object mode - bpy.ops.object.mode_set(mode='OBJECT') - - # Add constraints to bones: - con = rig.pose.bones['aim_MCH'].constraints.new('COPY_ROTATION') - con.target = rig - con.subtarget = "Camera" - - con = rig.pose.bones['Camera'].constraints.new('TRACK_TO') - con.target = rig - con.subtarget = "Aim" - con.use_target_z = True - - # Add custom Bone property to Camera bone - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "lock", create=True) - ob["lock"] = 1.0 - prop["soft_min"] = prop["min"] = 0.0 - prop["soft_max"] = prop["max"] = 1.0 - - # Add Driver to Lock/Unlock Camera from Aim Target - rig = bpy.context.view_layer.objects.active - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - - constraint = pose_bone.constraints["Track To"] - inf_driver = constraint.driver_add('influence') - inf_driver.driver.type = 'SCRIPTED' - var = inf_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["lock"]' - inf_driver.driver.expression = 'var' - - # Add custom property for the lens / add the driver after the camera is created - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "focal_length", create=True) - ob["focal_length"] = 50.0 - prop["soft_min"] = prop["min"] = 1.0 - prop["default"] = 50.0 - prop["soft_max"] = prop["max"] = 5000.0 - - # Add custom property for the focus distance / add the driver after the camera is created - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "focus_distance", create=True) - ob["focus_distance"] = 10.00 - prop["soft_min"] = prop["min"] = 0.0 - prop["soft_max"] = prop["max"] = 1000.0 - - # Add custom property for the f-stop / add the driver after the camera is created - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "f-stop", create=True) - ob["f-stop"] = 2.8 - prop["soft_min"] = prop["min"] = 0.1 - prop["soft_max"] = prop["max"] = 128.00 - - # Add the camera object: - bpy.ops.object.mode_set(mode='OBJECT') - - bpy.ops.object.camera_add() - cam = bpy.context.active_object - - # Name the Camera Object - if 'Dolly_camera' not in context.scene.objects: - cam.name = "Dolly_camera" - else: - cam.name = "Dolly_camera.000" - - # this will name the camera data - cam.data.name = cam.name - - cam_data_name = bpy.context.object.data.name - bpy.data.cameras[cam_data_name].display_size = 1.0 - cam.rotation_euler = [radians(90), 0, 0] # rotate the camera 90 degrees in x - - cam.location = (0.0, -2.0, 0.0) # move the camera to the correct postion - cam.parent = rig - cam.parent_type = "BONE" - cam.parent_bone = "Camera" - - # Add Driver to link the camera lens to the custom property on the armature - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - lens_driver = cam.data.driver_add("lens") - lens_driver.driver.type = 'SCRIPTED' - var = lens_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["focal_length"]' - lens_driver.driver.expression = 'var' - - # Add Driver to link the camera focus distance to the custom property on the armature - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - lens_driver = cam.data.driver_add("dof.focus_distance") - lens_driver.driver.type = 'SCRIPTED' - var = lens_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["focus_distance"]' - lens_driver.driver.expression = 'var' - - # Add Driver to link the camera f-stop to the custom property on the armature - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - lens_driver = cam.data.driver_add("dof.aperture_fstop") - lens_driver.driver.type = 'SCRIPTED' - var = lens_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["f-stop"]' - lens_driver.driver.expression = 'var' - - # lock the location/rotation/scale of the camera - cam.lock_location = [True, True, True] - cam.lock_rotation = [True, True, True] - cam.lock_scale = [True, True, True] - - # Set new camera as active camera - bpy.context.scene.camera = cam - - # make sure the camera is selectable by default (this can be locked in the UI) - bpy.context.object.hide_select = False - - # make the rig the active object before finishing - bpy.context.view_layer.objects.active = rig - bpy.data.objects[cam.name].select_set(False) - bpy.data.objects[rig.name].select_set(True) - - return rig - + ctrl_aim.parent = root + ctrl_aim_child.parent = ctrl_aim -class ADD_CAMERA_RIGS_OT_build_dolly_rig(Operator): - bl_idname = "add_camera_rigs.build_dolly_rig" - bl_label = "Build Dolly Camera Rig" - bl_description = "Build a Camera Dolly Rig" - bl_options = {'REGISTER', 'UNDO'} - def execute(self, context): - # build the Widgets - if not "WDGT_Camera_root" in bpy.context.scene.objects: - create_root_widget(self, "Camera_root") - if not "WDGT_Camera" in bpy.context.scene.objects: - create_camera_widget(self, "Camera") - if not "WDGT_Aim" in bpy.context.scene.objects: - create_aim_widget(self, "Aim") - - # call the function to build the rig - build_dolly_rig(context) - - return {'FINISHED'} - - -def build_crane_rig(context): - # Define some useful variables: - boneLayer = (False, True, False, False, False, False, False, False, - False, False, False, False, False, False, False, False, - False, False, False, False, False, False, False, False, - False, False, False, False, False, False, False, False) - - # Add the new armature object: - bpy.ops.object.armature_add() - rig = context.active_object - - # it will try to name the rig "Crane_rig" but if that name exists it will - # add .000 to the name - if "Crane_rig" not in context.scene.objects: - rig.name = "Crane_rig" - else: - rig.name = "Crane_rig.000" - rig["rig_id"] = "Crane_rig" - - bpy.ops.object.mode_set(mode='EDIT') - - # Remove default bone: +def create_crane_bones(rig, bone_layers): bones = rig.data.edit_bones - bones.remove(bones[0]) - # Add new bones: + # Add new bones root = bones.new("Root") - root.tail = (0.0, 3.0, 0.0) + root.tail = (0.0, 1.0, 0.0) + root.show_wire = True - ctrlAimChild = bones.new("aim_MCH") - ctrlAimChild.head = (0.0, 10.0, 1.0) - ctrlAimChild.tail = (0.0, 12.0, 1.0) - ctrlAimChild.layers = boneLayer + 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 - ctrlAim = bones.new("Aim") - ctrlAim.head = (0.0, 10.0, 1.0) - ctrlAim.tail = (0.0, 12.0, 1.0) + ctrl_aim = bones.new("Aim") + ctrl_aim.head = (0.0, 10.0, 1.7) + ctrl_aim.tail = (0.0, 11.0, 1.7) + ctrl_aim.show_wire = True ctrl = bones.new("Camera") - ctrl.head = (0.0, 1.0, 1.0) - ctrl.tail = (0.0, 3.0, 1.0) + ctrl.head = (0.0, 1.0, 1.7) + ctrl.tail = (0.0, 2.0, 1.7) arm = bones.new("Crane_arm") - arm.head = (0.0, 0.0, 1.0) - arm.tail = (0.0, 1.0, 1.0) + arm.head = (0.0, 0.0, 1.7) + arm.tail = (0.0, 1.0, 1.7) height = bones.new("Crane_height") height.head = (0.0, 0.0, 0.0) - height.tail = (0.0, 0.0, 1.0) + height.tail = (0.0, 0.0, 1.7) - # Setup hierarchy: + # Setup hierarchy ctrl.parent = arm ctrl.use_inherit_rotation = False ctrl.use_inherit_scale = False + ctrl.show_wire = True arm.parent = height arm.use_inherit_scale = False height.parent = root - ctrlAim.parent = root - ctrlAimChild.parent = ctrlAim - - # 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' + ctrl_aim.parent = root + ctrl_aim_child.parent = ctrl_aim - # jump into pose mode and change bones to euler - bpy.ops.object.mode_set(mode='POSE') - for x in bpy.context.object.pose.bones: - x.rotation_mode = 'XYZ' - - # lock the relevant loc, rot and scale - bpy.context.object.pose.bones[ - "Crane_arm"].lock_rotation = [False, True, False] - bpy.context.object.pose.bones["Crane_arm"].lock_scale = [True, False, True] - bpy.context.object.pose.bones["Crane_height"].lock_location = [True, True, True] - bpy.context.object.pose.bones["Crane_height"].lock_rotation = [True, True, True] - bpy.context.object.pose.bones["Crane_height"].lock_scale = [True, False, True] - - # add the custom bone shapes - bpy.context.object.pose.bones["Root"].custom_shape = bpy.data.objects[ - "WDGT_Camera_root"] # add the widget as custom shape - # set the wireframe checkbox to true - bpy.context.object.data.bones["Root"].show_wire = True - bpy.context.object.pose.bones[ - "Aim"].custom_shape = bpy.data.objects["WDGT_Aim"] - bpy.context.object.data.bones["Aim"].show_wire = True - bpy.context.object.pose.bones["Aim"].custom_shape_transform = bpy.data.objects[ - rig.name].pose.bones["aim_MCH"] # sets the "At" field to the child - bpy.context.object.pose.bones[ - "Camera"].custom_shape = bpy.data.objects["WDGT_Camera"] - bpy.context.object.data.bones["Camera"].show_wire = True - - # jump into object mode + # Jump into object mode bpy.ops.object.mode_set(mode='OBJECT') + pose_bones = rig.pose.bones + + # Lock the relevant loc, rot and scale + pose_bones["Crane_arm"].lock_rotation = (False, True, False) + pose_bones["Crane_arm"].lock_scale = (True, False, True) + pose_bones["Crane_height"].lock_location = (True, True, True) + pose_bones["Crane_height"].lock_rotation = (True, True, True) + 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 - # Add constraints to bones: - con = rig.pose.bones['aim_MCH'].constraints.new('COPY_ROTATION') + 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) + + # 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 + + # Lens property + pb = pose_bones['Camera'] + pb["lens"] = 50.0 + prop = rna_idprop_ui_prop_get(pb, "lens", create=True) + prop["default"] = 50.0 + prop["min"] = 1.0 + 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") + aim_widget = create_aim_widget("Aim") + + # Add the custom bone shapes + pose_bones["Root"].custom_shape = root_widget + pose_bones["Aim"].custom_shape = aim_widget + pose_bones["Camera"].custom_shape = camera_widget + + # Set the "At" field to the child + pose_bones["Aim"].custom_shape_transform = pose_bones["Aim_shape_rotation-MCH"] + + # Add constraints to bones + con = pose_bones['Aim_shape_rotation-MCH'].constraints.new('COPY_ROTATION') con.target = rig con.subtarget = "Camera" - con = rig.pose.bones['Camera'].constraints.new('TRACK_TO') + con = pose_bones['Camera'].constraints.new('TRACK_TO') con.target = rig con.subtarget = "Aim" con.use_target_z = True - # Add custom Bone property to Camera bone - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "lock", create=True) - ob["lock"] = 1.0 - prop["soft_min"] = prop["min"] = 0.0 - prop["soft_max"] = prop["max"] = 1.0 - - # Add Driver to Lock/Unlock Camera from Aim Target - rig = bpy.context.view_layer.objects.active - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - - constraint = pose_bone.constraints["Track To"] - inf_driver = constraint.driver_add('influence') - inf_driver.driver.type = 'SCRIPTED' - var = inf_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["lock"]' - inf_driver.driver.expression = 'var' - - # Add custom property for the lens / add the driver after the camera is created - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "focal_length", create=True) - ob["focal_length"] = 50.0 - prop["soft_min"] = prop["min"] = 1.0 - prop["default"] = 50.0 - prop["soft_max"] = prop["max"] = 5000.0 - - # Add custom property for the focus distance / add the driver after the camera is created - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "focus_distance", create=True) - ob["focus_distance"] = 10.00 - prop["soft_min"] = prop["min"] = 0.0 - prop["soft_max"] = prop["max"] = 1000.0 - - # Add custom property for the focus distance / add the driver after the camera is created - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "focus_distance", create=True) - ob["focus_distance"] = 10.00 - prop["soft_min"] = prop["min"] = 0.0 - prop["soft_max"] = prop["max"] = 1000.0 - - # Add custom property for the f-stop / add the driver after the camera is created - ob = bpy.context.object.pose.bones['Camera'] - prop = rna_idprop_ui_prop_get(ob, "f-stop", create=True) - ob["f-stop"] = 2.8 - prop["soft_min"] = prop["min"] = 0.1 - prop["soft_max"] = prop["max"] = 128.00 - - # Add the camera object: - bpy.ops.object.mode_set(mode='OBJECT') + # 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' + + # Add the camera object + cam_name = "%s_Camera" % mode.capitalize() + cam_data = bpy.data.cameras.new(cam_name) + cam = object_utils.object_data_add(context, cam_data, name=cam_name) + view_layer.objects.active = cam + context.scene.camera = cam + + cam.data.display_size = 1.0 + cam.rotation_euler[0] = pi / 2.0 # Rotate the camera 90 degrees in x - bpy.ops.object.camera_add() - cam = bpy.context.active_object - - # this will name the Camera Object - if 'Crane_camera' not in context.scene.objects: - cam.name = "Crane_camera" - else: - cam.name = "Crane_camera.000" - - # this will name the camera Data Object - if "Crane_camera" not in bpy.context.scene.objects.data.camera: - cam.data.name = "Crane_camera" - else: - cam.data.name = "Crane_camera.000" - - cam_data_name = bpy.context.object.data.name - bpy.data.cameras[cam_data_name].display_size = 1.0 - cam.rotation_euler = [radians(90), 0, 0] # rotate the camera 90 degrees in x - cam.location = (0.0, -2.0, 0.0) # move the camera to the correct postion + cam.location = (0.0, -1.0, 0.0) # Move the camera to the correct position cam.parent = rig cam.parent_type = "BONE" cam.parent_bone = "Camera" - # Add Driver to link the camera lens to the custom property on the armature - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - lens_driver = cam.data.driver_add("lens") - lens_driver.driver.type = 'SCRIPTED' - var = lens_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["focal_length"]' - lens_driver.driver.expression = 'var' - - # Add Driver to link the camera focus distance to the custom property on the armature - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - lens_driver = cam.data.driver_add("dof.focus_distance") - lens_driver.driver.type = 'SCRIPTED' - var = lens_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["focus_distance"]' - lens_driver.driver.expression = 'var' - - # Add Driver to link the camera f-stop to the custom property on the armature - pose_bone = bpy.data.objects[rig.name].pose.bones['Camera'] - lens_driver = cam.data.driver_add("dof.aperture_fstop") - lens_driver.driver.type = 'SCRIPTED' - var = lens_driver.driver.variables.new() - var.name = 'var' - var.type = 'SINGLE_PROP' - - # Target the Custom bone property - var.targets[0].id = bpy.data.objects[rig.name] - var.targets[0].data_path = 'pose.bones["Camera"]["f-stop"]' - lens_driver.driver.expression = 'var' - - # the location/rotation/scale of the camera - cam.lock_location = [True, True, True] - cam.lock_rotation = [True, True, True] - cam.lock_scale = [True, True, True] - - # Set new camera as active camera - bpy.context.scene.camera = cam - - # make sure the camera is selectable by default (this can be locked in the UI) - bpy.context.object.hide_select = False - - # make the rig the active object before finishing - bpy.context.view_layer.objects.active = rig - bpy.data.objects[cam.name].select_set(False) - bpy.data.objects[rig.name].select_set(True) + # Lock camera transforms + cam.lock_location = (True,) * 3 + cam.lock_rotation = (True,) * 3 + cam.lock_scale = (True,) * 3 + + # Add drivers to link the camera properties to the custom props + # on the armature + for prop_from, prop_to in (("lens", "lens"), + ("focus_distance", "dof.focus_distance"), + ("aperture_fstop", "dof.aperture_fstop")): + 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' + + # Make the rig the active object + for ob in view_layer.objects: + ob.select_set(False) + rig.select_set(True) + view_layer.objects.active = rig return rig -class ADD_CAMERA_RIGS_OT_build_crane_rig(Operator): - bl_idname = "add_camera_rigs.build_crane_rig" - bl_label = "Build Crane Camera Rig" - bl_description = "Build a Camera Crane Rig" +class OBJECT_OT_build_camera_rig(Operator): + bl_idname = "object.build_camera_rig" + bl_label = "Build Camera Rig" + bl_description = "Build a Camera Rig" bl_options = {'REGISTER', 'UNDO'} - def execute(self, context): - # build the Widgets - if not "WDGT_Camera_root" in bpy.context.scene.objects: - create_root_widget(self, "Camera_root") - if not "WDGT_Camera" in bpy.context.scene.objects: - create_camera_widget(self, "Camera") - if not "WDGT_Aim" in bpy.context.scene.objects: - create_aim_widget(self, "Aim") - - # call the function to build the rig - build_crane_rig(context) + mode: bpy.props.EnumProperty(items= + (('DOLLY',) * 3, + ('CRANE',) * 3,), + name="mode", + description="", default="DOLLY") + def execute(self, context): + # Build the rig + build_camera_rig(context, self.mode) return {'FINISHED'} -# dolly and crane entries in the Add Object > Camera Menu def add_dolly_crane_buttons(self, context): + """Dolly and crane entries in the Add Object > Camera Menu""" if context.mode == 'OBJECT': - self.layout.operator( - ADD_CAMERA_RIGS_OT_build_dolly_rig.bl_idname, + op = self.layout.operator( + OBJECT_OT_build_camera_rig.bl_idname, text="Dolly Camera Rig", icon='CAMERA_DATA' ) - self.layout.operator( - ADD_CAMERA_RIGS_OT_build_crane_rig.bl_idname, + op.mode = "DOLLY" + op = self.layout.operator( + OBJECT_OT_build_camera_rig.bl_idname, text="Crane Camera Rig", icon='CAMERA_DATA' ) + op.mode = "CRANE" classes = ( - ADD_CAMERA_RIGS_OT_build_dolly_rig, - ADD_CAMERA_RIGS_OT_build_crane_rig, + OBJECT_OT_build_camera_rig, ) diff --git a/add_camera_rigs/composition_guides_menu.py b/add_camera_rigs/composition_guides_menu.py index 7ce8dc272c5411f42bdc279378fbb4917b4e00a3..c3ff43e5a12cfdfac3a0facb8ef7e1411fd09814 100644 --- a/add_camera_rigs/composition_guides_menu.py +++ b/add_camera_rigs/composition_guides_menu.py @@ -1,16 +1,36 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + import bpy -from bpy.types import Menu +from bpy.types import Panel +from .operators import get_arm_and_cam -class ADD_CAMERA_RIGS_MT_composition_guides_menu(Menu): +class ADD_CAMERA_RIGS_PT_composition_guides(Panel): bl_label = "Composition Guides" - bl_idname = "ADD_CAMERA_RIGS_MT_composition_guides_menu" + bl_space_type = 'VIEW_3D' + bl_region_type = 'HEADER' def draw(self, context): layout = self.layout - activeCameraName = bpy.context.active_object.children[0].name - cam = bpy.data.cameras[bpy.data.objects[activeCameraName].data.name] + arm, cam = get_arm_and_cam(context.active_object) + cam = cam.data layout.prop(cam, "show_safe_areas") layout.row().separator() @@ -24,17 +44,12 @@ class ADD_CAMERA_RIGS_MT_composition_guides_menu(Menu): layout.prop(cam, "show_composition_thirds") -def draw_item(self, context): - layout = self.layout - layout.menu(CustomMenu.bl_idname) - - def register(): - bpy.utils.register_class(ADD_CAMERA_RIGS_MT_composition_guides_menu) + bpy.utils.register_class(ADD_CAMERA_RIGS_PT_composition_guides) def unregister(): - bpy.utils.unregister_class(ADD_CAMERA_RIGS_MT_composition_guides_menu) + bpy.utils.unregister_class(ADD_CAMERA_RIGS_PT_composition_guides) if __name__ == "__main__": diff --git a/add_camera_rigs/create_widgets.py b/add_camera_rigs/create_widgets.py index 788a868d007a1d65ca83c0e10923b2ff034f11be..f19fc206e9b0e744a37163e1ba55563b8bd5f4b2 100644 --- a/add_camera_rigs/create_widgets.py +++ b/add_camera_rigs/create_widgets.py @@ -1,241 +1,258 @@ import bpy -def create_widget(self, name): - """ Creates an empty widget object and returns the object.""" - widget_prefix = bpy.context.preferences.addons["add_camera_rigs"].preferences.widget_prefix +def create_widget(name): + """Create an empty widget object and return the object""" + prefs = bpy.context.preferences.addons["add_camera_rigs"].preferences + widget_prefix = prefs.widget_prefix obj_name = widget_prefix + name scene = bpy.context.scene - mesh = bpy.data.meshes.new(obj_name) - obj = bpy.data.objects.new(obj_name, mesh) + obj = bpy.data.objects.get(obj_name) - # create a new collection for the wigets - collection_name = bpy.context.preferences.addons["add_camera_rigs"].preferences.camera_widget_collection_name - c = bpy.data.collections.get(collection_name) - if c is not None: - c.objects.link(obj) - else: - c = bpy.data.collections.new(collection_name) - c.hide_viewport = True - c.hide_render = True + if obj is None: + mesh = bpy.data.meshes.new(obj_name) + obj = bpy.data.objects.new(obj_name, mesh) - # link the collection - scene.collection.children.link(c) - c.objects.link(obj) + # Create a new collection for the widgets + collection_name = prefs.camera_widget_collection_name + coll = bpy.data.collections.get(collection_name) + if coll is None: + coll = bpy.data.collections.new(collection_name) + scene.collection.children.link(coll) + coll.hide_viewport = True + coll.hide_render = True + + # Link the collection + coll.objects.link(obj) return obj -def create_root_widget(self, name): - # Creates a compass-shaped widget - obj = create_widget(self, name) - if obj is not None: - verts = [(0.210255, 0.209045, 0), (0.113789, 0.273501, -2.98023e-08), - (-3.07015e-08, 0.296135, 0), (-0.113789, 0.273501, 0), - (-0.210255, 0.209045, 0), (-0.274712, 0.112579, 7.45058e-09), - (-0.297346, -0.00121052, 1.48165e-08), (0.297346, -0.00121046, -1.49858e-08), - (0.274711, 0.112579, 7.45058e-09), (0.071529, 0.505864, 0), - (-0.0715289, 0.505864, 0), (-0.071529, 0.379091, 2.98023e-08), - (0.071529, 0.379091, 0), (-0.132587, 0.505864, 0), - (0.132587, 0.505864, 0), (-3.07015e-08, 0.667601, 1.19209e-07), - (-0.274712, -0.115, 2.23517e-08), (0.274712, -0.115, -7.45058e-09), - (0.210255, -0.211466, 0), (0.113789, -0.275922, 0), - (-9.03062e-08, -0.298556, 0), (-0.113789, -0.275922, 2.98023e-08), - (-0.210255, -0.211466, 0), (-0.668811, -0.00121029, 4.46188e-08), - (-0.507075, 0.131377, 4.47035e-08), (-0.507075, -0.133798, -1.49012e-08), - (-0.380301, 0.0703187, 1.49012e-08), (-0.380301, -0.0727393, 1.49012e-08), - (-0.507075, -0.0727393, -1.49012e-08), (-0.507075, 0.0703187, 4.47035e-08), - (0.507075, -0.0727393, -1.49012e-08), (0.507075, 0.0703187, -1.49012e-08), - (0.380301, 0.0703187, 1.49012e-08), (0.380301, -0.0727393, -1.49012e-08), - (0.507075, 0.131377, -1.49012e-08), (0.507075, -0.133798, -1.49012e-08), - (0.668811, -0.0012103, -1.49858e-08), (1.48112e-07, -0.670021, 0), - (-0.132587, -0.508285, 0), (0.132587, -0.508285, 0), - (-0.0715289, -0.381512, 2.98023e-08), (0.0715291, -0.381512, -2.98023e-08), - (0.0715291, -0.508285, 0), (-0.0715289, -0.508285, 0), - ] - - edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8), (10, 11), (9, 12), - (11, 12), (10, 13), (9, 14), (13, 15), (14, 15), (16, - 22), (17, 18), (18, 19), (19, 20), (20, 21), - (21, 22), (7, 17), (6, 16), (23, 24), (23, 25), (24, - 29), (25, 28), (26, 27), (26, 29), (27, 28), - (31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, - 36), (35, 36), (37, 38), (37, 39), (38, 43), - (39, 42), (40, 41), (40, 43), (41, 42), ] - - faces = [] +def create_root_widget(name): + """Create a compass-shaped widget""" + obj = create_widget(name) + if not obj.data.vertices: + verts = [(0.6307649612426758, 0.6271349787712097, 0.0), + (0.3413670063018799, 0.8205029964447021, 0.0), + (0.0, 0.8884050250053406, 0.0), + (-0.3413670063018799, 0.8205029964447021, 0.0), + (-0.6307649612426758, 0.6271349787712097, 0.0), + (-0.8241360187530518, 0.3377370238304138, 0.0), + (-0.8920379877090454, -0.003631560131907463, 0.0), + (0.8920379877090454, -0.003631379920989275, 0.0), + (0.824133038520813, 0.3377370238304138, 0.0), + (0.21458700299263, 1.5175920724868774, 0.0), + (-0.21458669006824493, 1.5175920724868774, 0.0), + (-0.21458700299263, 1.1372729539871216, 0.0), + (0.21458700299263, 1.1372729539871216, 0.0), + (-0.3977609872817993, 1.5175920724868774, 0.0), + (0.3977609872817993, 1.5175920724868774, 0.0), + (0.0, 2.002802848815918, 0.0), + (-0.8241360187530518, -0.3449999988079071, 0.0), + (0.8241360187530518, -0.3449999988079071, 0.0), + (0.6307649612426758, -0.6343979835510254, 0.0), + (0.3413670063018799, -0.8277660012245178, 0.0), + (0.0, -0.8956680297851562, 0.0), + (-0.3413670063018799, -0.8277660012245178, 0.0), + (-0.6307649612426758, -0.6343979835510254, 0.0), + (-2.0064330101013184, -0.003630870021879673, 0.0), + (-1.5212249755859375, 0.39413100481033325, 0.0), + (-1.5212249755859375, -0.4013940095901489, 0.0), + (-1.1409029960632324, 0.21095609664916992, 0.0), + (-1.1409029960632324, -0.2182179093360901, 0.0), + (-1.5212249755859375, -0.2182179093360901, 0.0), + (-1.5212249755859375, 0.21095609664916992, 0.0), + (1.5212249755859375, -0.2182179093360901, 0.0), + (1.5212249755859375, 0.21095609664916992, 0.0), + (1.1409029960632324, 0.21095609664916992, 0.0), + (1.1409029960632324, -0.2182179093360901, 0.0), + (1.5212249755859375, 0.39413100481033325, 0.0), + (1.5212249755859375, -0.4013940095901489, 0.0), + (2.0064330101013184, -0.0036309000570327044, 0.0), + (0.0, -2.0100629329681396, 0.0), + (-0.3977609872817993, -1.5248548984527588, 0.0), + (0.3977609872817993, -1.5248548984527588, 0.0), + (-0.21458669006824493, -1.144536018371582, 0.0), + (0.21458730101585388, -1.144536018371582, 0.0), + (0.21458730101585388, -1.5248548984527588, 0.0), + (-0.21458669006824493, -1.5248548984527588, 0.0)] + + edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8), + (10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15), + (16, 22), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17), + (6, 16), (23, 24), (23, 25), (24, 29), (25, 28), (26, 27), (26, 29), + (27, 28), (31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, 36), + (35, 36), (37, 38), (37, 39), (38, 43), (39, 42), (40, 41), (40, 43), + (41, 42)] mesh = obj.data mesh.from_pydata(verts, edges, []) mesh.update() + return obj -def create_camera_widget(self, name): - # Creates a camera ctrl widget - - obj = create_widget(self, name) - if obj != None: - verts = [(0.13756819069385529, 1.0706068032106941e-08, -0.13756819069385529), - (0.1797415018081665, 5.353034016053471e-09, -0.07445136457681656), - (0.19455081224441528, -6.381313819948996e-16, 8.504085435845354e-09), - (0.1797415018081665, -5.353034016053471e-09, 0.07445138692855835), - (0.13756819069385529, -1.0706068032106941e-08, 0.13756819069385529), - (0.07445137947797775, -2.1412136064213882e-08, 0.1797415018081665), - (-9.740904971522468e-08, -2.1412136064213882e-08, 0.19455081224441528), - (-5.87527146933553e-08, 2.1412136064213882e-08, -0.19455081224441528), - (0.0744515135884285, 2.1412136064213882e-08, -0.17974145710468292), - (0.3317747414112091, 5.353034016053471e-09, -0.04680081456899643), - (0.3317747414112091, -5.353034016053471e-09, 0.04680081456899643), - (0.24882805347442627, -5.353034016053471e-09, 0.04680081456899643), - (0.24882805347442627, 5.353034016053471e-09, -0.04680084437131882), - (0.3317747414112091, -5.353034016053471e-09, 0.08675074577331543), - (0.3317747414112091, 5.353034016053471e-09, -0.08675074577331543), - (0.43759751319885254, 0.0, 0.0), (-0.07445148378610611, - - 2.1412136064213882e-08, 0.17974145710468292), - (-0.07445141673088074, 2.1412136064213882e-08, -0.1797415018081665), - (-0.13756820559501648, 1.0706068032106941e-08, -0.1375681608915329), - (-0.1797415018081665, 5.353034016053471e-09, -0.07445136457681656), - (-0.19455081224441528, -1.2762627639897992e-15, 2.0872269246297037e-08), - (-0.1797415018081665, -5.353034016053471e-09, 0.07445140182971954), - (-0.1375681608915329, -1.0706068032106941e-08, 0.13756820559501648), - (5.1712785165136665e-08, -4.2824272128427765e-08, 0.43759751319885254), - (0.08675077557563782, -2.1412136064213882e-08, 0.3317747414112091), - (-0.08675073087215424, -2.1412136064213882e-08, 0.3317747414112091), - (0.046800870448350906, -2.1412136064213882e-08, 0.24882805347442627), - (-0.04680079594254494, -2.1412136064213882e-08, 0.24882805347442627), - (-0.04680079594254494, -2.1412136064213882e-08, 0.3317747414112091), - (0.04680084437131882, -2.1412136064213882e-08, 0.3317747414112091), - (-0.04680076241493225, 2.1412136064213882e-08, -0.3317747414112091), - (0.046800874173641205, 2.1412136064213882e-08, -0.3317747414112091), - (0.04680086299777031, 2.1412136064213882e-08, -0.24882805347442627), - (-0.046800799667835236, 2.1412136064213882e-08, -0.24882805347442627), - (0.0867508053779602, 2.1412136064213882e-08, -0.3317747414112091), - (-0.08675070106983185, 2.1412136064213882e-08, -0.3317747414112091), - (4.711345980012993e-08, 4.2824272128427765e-08, -0.43759751319885254), - (-0.43759751319885254, 1.0210102111918393e-14, -9.882624141255292e-08), - (-0.3317747414112091, -5.353034016053471e-09, 0.08675065636634827), - (-0.3317747414112091, 5.353034016053471e-09, -0.08675083518028259), - (-0.24882805347442627, -5.353034016053471e-09, 0.04680076986551285), - (-0.24882805347442627, 5.353034016053471e-09, -0.0468008853495121), - (-0.3317747414112091, 5.353034016053471e-09, -0.046800896525382996), - (-0.3317747414112091, -5.353034016053471e-09, 0.04680073633790016), - (-0.08263588696718216, -7.0564780685344886e-09, 0.08263592422008514), - (-0.10796899348497391, -3.5282390342672443e-09, 0.04472224414348602), - (-0.11686481535434723, -8.411977372806655e-16, 1.2537773486087644e-08), - (-0.10796899348497391, 3.5282390342672443e-09, -0.04472222551703453), - (-0.08263592422008514, 7.0564780685344886e-09, -0.08263588696718216), - (-0.04472225159406662, 7.0564780685344886e-09, -0.10796899348497391), - (-0.0447222925722599, -7.0564780685344886e-09, 0.10796897858381271), - (0.0447223074734211, 7.0564780685344886e-09, -0.10796897858381271), - (-3.529219583242593e-08, 7.0564780685344886e-09, -0.11686481535434723), - (-5.8512675593647145e-08, -7.0564780685344886e-09, 0.11686481535434723), - (0.04472222924232483, -7.0564780685344886e-09, 0.10796899348497391), - (0.08263590186834335, -7.0564780685344886e-09, 0.08263590186834335), - (0.10796899348497391, -3.5282390342672443e-09, 0.04472223296761513), - (0.11686481535434723, -4.2059886864033273e-16, 5.108323541946902e-09), - (0.10796899348497391, 3.5282390342672443e-09, -0.04472222924232483), - (0.08263590186834335, 7.0564780685344886e-09, -0.08263590186834335), - (3.725290298461914e-08, -2.1412136064213882e-08, 0.24882805347442627)] +def create_camera_widget(name): + """Create a camera control widget""" + obj = create_widget(name) + if not obj.data.vertices: + verts = [(0.27513638138771057, 0.0, -0.27513638138771057), + (0.359483003616333, 0.0, -0.14890272915363312), + (0.38910162448883057, 0.0, 0.0), + (0.359483003616333, 0.0, 0.1489027738571167), + (0.27513638138771057, 0.0, 0.27513638138771057), + (0.1489027589559555, 0.0, 0.359483003616333), + (-1.9481809943044937e-07, 0.0, 0.38910162448883057), + (-1.175054293867106e-07, 0.0, -0.38910162448883057), + (0.148903027176857, 0.0, -0.35948291420936584), + (0.6635494828224182, 0.0, -0.09360162913799286), + (0.6635494828224182, 0.0, 0.09360162913799286), + (0.49765610694885254, 0.0, 0.09360162913799286), + (0.49765610694885254, 0.0, -0.09360168874263763), + (0.6635494828224182, 0.0, 0.17350149154663086), + (0.6635494828224182, 0.0, -0.17350149154663086), + (0.8751950263977051, 0.0, 0.0), + (-0.14890296757221222, 0.0, 0.35948291420936584), + (-0.14890283346176147, 0.0, -0.359483003616333), + (-0.27513641119003296, 0.0, -0.2751363217830658), + (-0.359483003616333, 0.0, -0.14890272915363312), + (-0.38910162448883057, 0.0, 0.0), + (-0.359483003616333, 0.0, 0.1489028036594391), + (-0.2751363217830658, 0.0, 0.27513641119003296), + (1.0342557033027333e-07, 0.0, 0.8751950263977051), + (0.17350155115127563, 0.0, 0.6635494828224182), + (-0.17350146174430847, 0.0, 0.6635494828224182), + (0.09360174089670181, 0.0, 0.49765610694885254), + (-0.09360159188508987, 0.0, 0.49765610694885254), + (-0.09360159188508987, 0.0, 0.6635494828224182), + (0.09360168874263763, 0.0, 0.6635494828224182), + (-0.0936015248298645, 0.0, -0.6635494828224182), + (0.09360174834728241, 0.0, -0.6635494828224182), + (0.09360172599554062, 0.0, -0.49765610694885254), + (-0.09360159933567047, 0.0, -0.49765610694885254), + (0.1735016107559204, 0.0, -0.6635494828224182), + (-0.1735014021396637, 0.0, -0.6635494828224182), + (9.422691960025986e-08, 0.0, -0.8751950263977051), + (-0.8751950263977051, 0.0, 0.0), + (-0.6635494828224182, 0.0, 0.17350131273269653), + (-0.6635494828224182, 0.0, -0.17350167036056519), + (-0.49765610694885254, 0.0, 0.0936015397310257), + (-0.49765610694885254, 0.0, -0.0936017706990242), + (-0.6635494828224182, 0.0, -0.09360179305076599), + (-0.6635494828224182, 0.0, 0.09360147267580032), + (-0.16527177393436432, 0.0, 0.1652718484401703), + (-0.21593798696994781, 0.0, 0.08944448828697205), + (-0.23372963070869446, 0.0, 0.0), + (-0.21593798696994781, 0.0, -0.08944445103406906), + (-0.1652718484401703, 0.0, -0.16527177393436432), + (-0.08944450318813324, 0.0, -0.21593798696994781), + (-0.0894445851445198, 0.0, 0.21593795716762543), + (0.0894446149468422, 0.0, -0.21593795716762543), + (-7.058439166485186e-08, 0.0, -0.23372963070869446), + (-1.1702535118729429e-07, 0.0, 0.23372963070869446), + (0.08944445848464966, 0.0, 0.21593798696994781), + (0.1652718037366867, 0.0, 0.1652718037366867), + (0.21593798696994781, 0.0, 0.08944446593523026), + (0.23372963070869446, 0.0, 0.0), + (0.21593798696994781, 0.0, -0.08944445848464966), + (0.1652718037366867, 0.0, -0.1652718037366867)] edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8), - (10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15), (16, 22), - (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17), (6, 16), (23, 24), - (23, 25), (24, 29), (25, 28), (26, 29), (27, 28), (31, 32), (30, 33), (32, 33), - (31, 34), (30, 35), (34, 36), (35, 36), (37, 38), (37, 39), (38, 43), (39, 42), - (40, 41), (40, 43), (41, 42), (50, 53), (49, 52), (44, 45), (45, 46), (46, 47), - (47, 48), (48, 49), (44, 50), (51, 59), (51, 52), (53, 54), (54, 55), (55, 56), - (56, 57), (57, 58), (58, 59), (26, 60), (27, 60), (23, 60)] - - faces = [] + (10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15), + (16, 22), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17), + (6, 16), (23, 24), (23, 25), (24, 29), (25, 28), (26, 29), (27, 28), + (31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, 36), (35, 36), + (37, 38), (37, 39), (38, 43), (39, 42), (40, 41), (40, 43), (41, 42), + (50, 53), (49, 52), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49), + (44, 50), (51, 59), (51, 52), (53, 54), (54, 55), (55, 56), (56, 57), + (57, 58), (58, 59), (27, 26)] mesh = obj.data mesh.from_pydata(verts, edges, []) mesh.update() + return obj -def create_aim_widget(self, name): - # Creates a camera aim widget - - obj = create_widget(self, name) - if obj != None: - verts = [(0.15504144132137299, 1.4901161193847656e-08, 0.15504144132137299), - (0.20257140696048737, 7.450580596923828e-09, 0.0839078277349472), - (0.21926172077655792, -8.881784197001252e-16, -9.584233851001045e-09), - (0.20257140696048737, -7.450580596923828e-09, -0.0839078426361084), - (0.15504144132137299, -1.4901161193847656e-08, -0.15504144132137299), - (0.0839078351855278, -1.4901161193847656e-08, -0.20257140696048737), - (-1.0978147457763043e-07, -1.4901161193847656e-08, -0.21926172077655792), - (-6.621520043381679e-08, 1.4901161193847656e-08, 0.21926172077655792), - (0.08390798419713974, 1.4901161193847656e-08, 0.2025713473558426), - (0.39969685673713684, 3.725290298461914e-09, 0.05274524539709091), - (0.39969685673713684, -3.725290298461914e-09, -0.05274524167180061), - (0.4931790232658386, -3.725290298461914e-09, -0.05274524167180061), - (0.4931790232658386, 3.725290298461914e-09, 0.052745271474123), - (0.39969685673713684, -7.450580596923828e-09, -0.09776943176984787), - (0.39969685673713684, 7.450580596923828e-09, 0.09776943176984787), - (0.28043296933174133, 6.226862126577502e-17, -6.226862788321993e-17), - (-0.08390796184539795, -1.4901161193847656e-08, -0.2025713473558426), - (-0.08390787988901138, 1.4901161193847656e-08, 0.20257140696048737), - (-0.15504147112369537, 1.4901161193847656e-08, 0.1550414115190506), - (-0.20257140696048737, 7.450580596923828e-09, 0.08390782028436661), - (-0.21926172077655792, -1.7763568394002505e-15, -2.352336458955051e-08), - (-0.20257140696048737, -7.450580596923828e-09, -0.08390786498785019), - (-0.1550414115190506, -1.4901161193847656e-08, -0.15504147112369537), - (2.9140544199890428e-08, 2.9802322387695312e-08, 0.2804329991340637), - (-0.09776944667100906, 2.9802322387695312e-08, 0.3996969163417816), - (0.09776947647333145, 2.9802322387695312e-08, 0.3996969163417816), - (-0.052745264023542404, 2.9802322387695312e-08, 0.4931790828704834), - (0.05274529010057449, 2.9802322387695312e-08, 0.4931790828704834), - (0.052745264023542404, 2.9802322387695312e-08, 0.3996969163417816), - (-0.052745234221220016, 2.9802322387695312e-08, 0.3996969163417816), - (0.05274517461657524, -2.9802322387695312e-08, -0.3996969759464264), - (-0.052745334804058075, -2.9802322387695312e-08, -0.3996969759464264), - (-0.05274537205696106, -2.9802322387695312e-08, -0.49317920207977295), - (0.05274519696831703, -2.9802322387695312e-08, -0.49317920207977295), - (-0.09776955097913742, -2.9802322387695312e-08, -0.3996969163417816), - (0.09776940196752548, -2.9802322387695312e-08, -0.39969703555107117), - (-7.148475589247028e-08, -2.9802322387695312e-08, -0.2804329991340637), - (-0.2804330289363861, 3.552713678800501e-15, 4.234420103443881e-08), - (-0.3996969759464264, -7.450580596923828e-09, -0.09776938706636429), - (-0.39969685673713684, 7.450580596923828e-09, 0.09776950627565384), - (-0.4931790232658386, -3.725290298461914e-09, -0.05274520441889763), - (-0.4931790232658386, 3.725290298461914e-09, 0.05274531990289688), - (-0.3996969163417816, 3.725290298461914e-09, 0.052745312452316284), - (-0.3996969163417816, -3.725290298461914e-09, -0.05274519324302673), - (-0.06401804089546204, -7.450580596923828e-09, -0.06401806324720383), - (-0.0836436077952385, -3.725290298461914e-09, -0.03464633598923683), - (-0.09053517132997513, -8.881784197001252e-16, -9.713016169143884e-09), - (-0.0836436077952385, 3.725290298461914e-09, 0.03464631363749504), - (-0.06401806324720383, 7.450580596923828e-09, 0.06401804089546204), - (-0.03464633598923683, 7.450580596923828e-09, 0.0836436077952385), - (-0.034646373242139816, -7.450580596923828e-09, -0.0836435854434967), - (0.03464638441801071, 7.450580596923828e-09, 0.0836435854434967), - (-2.734086912425937e-08, 7.450580596923828e-09, 0.09053517132997513), - (-4.532979147597871e-08, -7.450580596923828e-09, -0.09053517132997513), - (0.034646324813365936, -7.450580596923828e-09, -0.0836436077952385), - (0.06401804834604263, -7.450580596923828e-09, -0.06401804834604263), - (0.0836436077952385, -3.725290298461914e-09, -0.034646324813365936), - (0.09053517132997513, -4.440892098500626e-16, -3.957419281164221e-09), - (0.0836436077952385, 3.725290298461914e-09, 0.03464632108807564), - (0.06401804834604263, 7.450580596923828e-09, 0.06401804834604263), - (1.1175870895385742e-08, 2.9802322387695312e-08, 0.4931790828704834), - (-3.3337176574832483e-08, 2.4835267176115394e-09, 0.030178390443325043), - (-3.9333485801762436e-08, -2.4835271617007493e-09, -0.030178390443325043), - (-0.030178390443325043, -7.40148665436918e-16, -7.794483281031717e-09), - (0.030178390443325043, -5.921189111737107e-16, -5.875951281097969e-09)] +def create_aim_widget(name): + """Create a camera aim widget""" + obj = create_widget(name) + if not obj.data.vertices: + verts = [(0.31008288264274597, 0.0, 0.31008288264274597), + (0.40514281392097473, 0.0, 0.1678156554698944), + (0.43852344155311584, 0.0, 0.0), + (0.40514281392097473, 0.0, -0.1678156852722168), + (0.31008288264274597, 0.0, -0.31008288264274597), + (0.1678156703710556, 0.0, -0.40514281392097473), + (-2.1956294915526087e-07, 0.0, -0.43852344155311584), + (-1.3243040086763358e-07, 0.0, 0.43852344155311584), + (0.16781596839427948, 0.0, 0.4051426947116852), + (0.7993937134742737, 0.0, 0.10549049079418182), + (0.7993937134742737, 0.0, -0.10549048334360123), + (0.9863580465316772, 0.0, -0.10549048334360123), + (0.9863580465316772, 0.0, 0.105490542948246), + (0.7993937134742737, 0.0, -0.19553886353969574), + (0.7993937134742737, 0.0, 0.19553886353969574), + (0.5608659386634827, 0.0, 0.0), + (-0.1678159236907959, 0.0, -0.4051426947116852), + (-0.16781575977802277, 0.0, 0.40514281392097473), + (-0.31008294224739075, 0.0, 0.3100828230381012), + (-0.40514281392097473, 0.0, 0.16781564056873322), + (-0.43852344155311584, 0.0, 0.0), + (-0.40514281392097473, 0.0, -0.16781572997570038), + (-0.3100828230381012, 0.0, -0.31008294224739075), + (5.8281088399780856e-08, 0.0, 0.5608659982681274), + (-0.19553889334201813, 0.0, 0.7993938326835632), + (0.1955389529466629, 0.0, 0.7993938326835632), + (-0.10549052804708481, 0.0, 0.9863581657409668), + (0.10549058020114899, 0.0, 0.9863581657409668), + (0.10549052804708481, 0.0, 0.7993938326835632), + (-0.10549046844244003, 0.0, 0.7993938326835632), + (0.10549034923315048, 0.0, -0.7993939518928528), + (-0.10549066960811615, 0.0, -0.7993939518928528), + (-0.10549074411392212, 0.0, -0.9863584041595459), + (0.10549039393663406, 0.0, -0.9863584041595459), + (-0.19553910195827484, 0.0, -0.7993938326835632), + (0.19553880393505096, 0.0, -0.7993940711021423), + (-1.4296951178494055e-07, 0.0, -0.5608659982681274), + (-0.5608660578727722, 0.0, 0.0), + (-0.7993939518928528, 0.0, -0.19553877413272858), + (-0.7993937134742737, 0.0, 0.19553901255130768), + (-0.9863580465316772, 0.0, -0.10549040883779526), + (-0.9863580465316772, 0.0, 0.10549063980579376), + (-0.7993938326835632, 0.0, 0.10549062490463257), + (-0.7993938326835632, 0.0, -0.10549038648605347), + (-0.12803608179092407, 0.0, -0.12803612649440765), + (-0.167287215590477, 0.0, -0.06929267197847366), + (-0.18107034265995026, 0.0, 0.0), + (-0.167287215590477, 0.0, 0.06929262727499008), + (-0.12803612649440765, 0.0, 0.12803608179092407), + (-0.06929267197847366, 0.0, 0.167287215590477), + (-0.06929274648427963, 0.0, -0.1672871708869934), + (0.06929276883602142, 0.0, 0.1672871708869934), + (-5.468173824851874e-08, 0.0, 0.18107034265995026), + (-9.065958295195742e-08, 0.0, -0.18107034265995026), + (0.06929264962673187, 0.0, -0.167287215590477), + (0.12803609669208527, 0.0, -0.12803609669208527), + (0.167287215590477, 0.0, -0.06929264962673187), + (0.18107034265995026, 0.0, 0.0), + (0.167287215590477, 0.0, 0.06929264217615128), + (0.12803609669208527, 0.0, 0.12803609669208527), + (-6.667435314966497e-08, 0.0, 0.060356780886650085), + (-7.866697160352487e-08, 0.0, -0.060356780886650085), + (-0.060356780886650085, 0.0, 0.0), + (0.060356780886650085, 0.0, 0.0)] edges = [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (7, 8), (0, 8), - (10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15), (16, 22), - (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17), (6, 16), (23, 24), - (23, 25), (24, 29), (25, 28), (26, 29), (27, 28), (31, 32), (30, 33), (32, 33), - (31, 34), (30, 35), (34, 36), (35, 36), (37, 38), (37, 39), (38, 43), (39, 42), - (40, 41), (40, 43), (41, 42), (50, 53), (49, 52), (44, 45), (45, 46), (46, 47), - (47, 48), (48, 49), (44, 50), (51, 59), (51, 52), (53, 54), (54, 55), (55, 56), - (56, 57), (57, 58), (58, 59), (26, 60), (27, 60), (23, 60), (61, 62), (63, 64)] - - faces = [] + (10, 11), (9, 12), (11, 12), (10, 13), (9, 14), (13, 15), (14, 15), + (16, 22), (17, 18), (18, 19), (19, 20), (20, 21), (21, 22), (7, 17), + (6, 16), (23, 24), (23, 25), (24, 29), (25, 28), (26, 29), (27, 28), + (31, 32), (30, 33), (32, 33), (31, 34), (30, 35), (34, 36), (35, 36), + (37, 38), (37, 39), (38, 43), (39, 42), (40, 41), (40, 43), (41, 42), + (50, 53), (49, 52), (44, 45), (45, 46), (46, 47), (47, 48), (48, 49), + (44, 50), (51, 59), (51, 52), (53, 54), (54, 55), (55, 56), (56, 57), + (57, 58), (58, 59), (27, 26), (60, 61), (62, 63)] mesh = obj.data mesh.from_pydata(verts, edges, []) mesh.update() + return obj diff --git a/add_camera_rigs/operators.py b/add_camera_rigs/operators.py index fe93041d0871ed19f207dc03f7205a4841f4e87b..7468007e5de6db641d70fca0a161763fb351ca80 100644 --- a/add_camera_rigs/operators.py +++ b/add_camera_rigs/operators.py @@ -1,118 +1,108 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + import bpy from bpy.types import Operator -def set_scene_camera(): - '''Makes the camera the active and sets it to the scene camera''' - ob = bpy.context.active_object - # find the children on the rig (the camera name) - active_cam = ob.children[0].name - # cam = bpy.data.cameras[bpy.data.objects[active_cam]] - scene_cam = bpy.context.scene.camera +def get_arm_and_cam(obj): + if obj.type == 'ARMATURE': + cam = None + for child in obj.children: + if child.type == 'CAMERA': + cam = child + break + if cam is not None: + return obj, cam + elif (obj.type == 'CAMERA' + and obj.parent is not None + and "rig_id" in obj.parent + and obj.parent["rig_id"].lower() in {"dolly_rig", "crane_rig"}): + return obj.parent, obj + return None, None + + +class CameraRigMixin(): + @classmethod + def poll(cls, context): + if context.active_object is not None: + return get_arm_and_cam(context.active_object) != (None, None) - if active_cam != scene_cam.name: - bpy.context.scene.camera = bpy.data.objects[active_cam] - else: - return None + return False -class ADD_CAMERA_RIGS_OT_set_scene_camera(Operator): +class ADD_CAMERA_RIGS_OT_set_scene_camera(Operator, CameraRigMixin): bl_idname = "add_camera_rigs.set_scene_camera" bl_label = "Make Camera Active" bl_description = "Makes the camera parented to this rig the active scene camera" - @classmethod - def poll(cls, context): - return context.active_object is not None - def execute(self, context): - set_scene_camera() + arm, cam = get_arm_and_cam(context.active_object) + scene_cam = context.scene.camera - return {'FINISHED'} + if cam is not None and cam is not scene_cam: + context.scene.camera = cam + return {'FINISHED'} + return {'CANCELLED'} -def markerBind(): - '''Defines the function to add a marker to timeling and bind camera''' - rig = bpy.context.active_object # rig object - active_cam = rig.children[0] # camera object - - # switch area to DOPESHEET to add marker - bpy.context.area.type = 'DOPESHEET_EDITOR' - # add marker - bpy.ops.marker.add() # it will automatiically have the name of the camera - # select rig camera - bpy.context.view_layer.objects.active = active_cam - # bind marker to selected camera - bpy.ops.marker.camera_bind() - # make the rig the active object before finishing - bpy.context.view_layer.objects.active = rig - bpy.data.objects[active_cam.name].select_set(False) - bpy.data.objects[rig.name].select_set(True) - # switch back to 3d view - bpy.context.area.type = 'VIEW_3D' - - -class ADD_CAMERA_RIGS_OT_add_marker_bind(Operator): + +class ADD_CAMERA_RIGS_OT_add_marker_bind(Operator, CameraRigMixin): bl_idname = "add_camera_rigs.add_marker_bind" bl_label = "Add Marker and Bind Camera" bl_description = "Add marker to current frame then bind rig camera to it (for camera switching)" - @classmethod - def poll(cls, context): - return context.active_object is not None - def execute(self, context): - markerBind() - - return {'FINISHED'} + arm, cam = get_arm_and_cam(context.active_object) + marker = context.scene.timeline_markers.new( + "cam_" + str(context.scene.frame_current), + frame=context.scene.frame_current + ) + marker.camera = cam -def add_DOF_object(): - """Define the function to add an Empty as DOF object """ - smode = bpy.context.mode - rig = bpy.context.active_object - bone = rig.data.bones['aim_MCH'] - active_cam = rig.children[0].name - cam = bpy.data.cameras[bpy.data.objects[active_cam].data.name] - - bpy.ops.object.mode_set(mode='OBJECT', toggle=False) - # Add Empty - bpy.ops.object.empty_add() - obj = bpy.context.active_object - - obj.name = "Empty_DOF" - # parent to aim_MCH - obj.parent = rig - obj.parent_type = "BONE" - obj.parent_bone = "aim_MCH" - # clear loc and rot - bpy.ops.object.location_clear() - bpy.ops.object.rotation_clear() - # move to bone head - obj.location = bone.head - - # make this new empty the dof_object - cam.dof.focus_object = obj - - # make the rig the active object before finishing - bpy.context.view_layer.objects.active = rig - bpy.data.objects[obj.name].select_set(False) - bpy.data.objects[rig.name].select_set(True) - - bpy.ops.object.mode_set(mode=smode, toggle=False) + return {'FINISHED'} -class ADD_CAMERA_RIGS_OT_add_dof_object(Operator): +class ADD_CAMERA_RIGS_OT_add_dof_object(Operator, CameraRigMixin): bl_idname = "add_camera_rigs.add_dof_object" bl_label = "Add DOF Object" bl_description = "Create Empty and add as DOF Object" - @classmethod - def poll(cls, context): - return context.active_object is not None - def execute(self, context): - add_DOF_object() + arm, cam = get_arm_and_cam(context.active_object) + bone = arm.data.bones['Aim_shape_rotation-MCH'] + + # Add Empty + empty_obj = bpy.data.objects.new("EmptyDOF", None) + context.scene.collection.objects.link(empty_obj) + + # Parent to Aim Child bone + empty_obj.parent = arm + empty_obj.parent_type = "BONE" + empty_obj.parent_bone = "Aim_shape_rotation-MCH" + + # Move to bone head + empty_obj.location = bone.head + + # Make this new empty the dof_object + cam.data.dof.use_dof = True + cam.data.dof.focus_object = empty_obj return {'FINISHED'} diff --git a/add_camera_rigs/prefs.py b/add_camera_rigs/prefs.py index 18c75bc4e96c17b38b0ea7396222c525d0169127..465c42a669389ea0e309f704448c8c326ba8f92b 100644 --- a/add_camera_rigs/prefs.py +++ b/add_camera_rigs/prefs.py @@ -1,23 +1,40 @@ -import bpy +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + from bpy.types import AddonPreferences from bpy.props import StringProperty -class Add_Camera_Rigs_Preferences(AddonPreferences): +class AddCameraRigsPreferences(AddonPreferences): bl_idname = 'add_camera_rigs' - # widget prefix + # Widget prefix widget_prefix: StringProperty( name="Camera Widget prefix", - description="Choose a prefix for the widget objects", - default="WDGT_", + description="Prefix for the widget objects", + default="WGT-", ) - # collection name + # Collection name camera_widget_collection_name: StringProperty( name="Bone Widget collection name", - description="Choose a name for the collection the widgets will appear", - default="WDGTS_camera", + description="Name for the collection the widgets will appear", + default="Widgets", ) def draw(self, context): @@ -30,7 +47,7 @@ class Add_Camera_Rigs_Preferences(AddonPreferences): classes = ( - Add_Camera_Rigs_Preferences, + AddCameraRigsPreferences, ) diff --git a/add_camera_rigs/ui_panels.py b/add_camera_rigs/ui_panels.py index 3356d3898fcf834819189d21860d9935a4098671..63fe158a6b0e9e7281a0f81d1d3f235cd87c5dbb 100644 --- a/add_camera_rigs/ui_panels.py +++ b/add_camera_rigs/ui_panels.py @@ -1,84 +1,95 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + import bpy from bpy.types import Panel +from .operators import get_arm_and_cam, CameraRigMixin + -class ADD_CAMERA_RIGS_PT_camera_rig_ui(Panel): - bl_category = 'Create' - bl_label = "Camera Rig UI" +class ADD_CAMERA_RIGS_PT_camera_rig_ui(Panel, CameraRigMixin): + bl_label = "Camera Rig" bl_space_type = 'VIEW_3D' bl_region_type = 'UI' - - _ACTIVE_OBJECT: object = None - - _ACTIVE_RIG_TYPE: str = None - - @classmethod - def poll(self, context): - self._ACTIVE_OBJECT = bpy.context.active_object - - if self._ACTIVE_OBJECT != None and "rig_id" in self._ACTIVE_OBJECT: - rigType = self._ACTIVE_OBJECT["rig_id"] - - if rigType == "Dolly_rig" or rigType == "Crane_rig": - self._ACTIVE_RIG_TYPE = rigType - return True - - return False + bl_category = 'Item' def draw(self, context): - arm = self._ACTIVE_OBJECT.data - poseBones = self._ACTIVE_OBJECT.pose.bones - activeCameraName = self._ACTIVE_OBJECT.children[0].name - - cam = bpy.data.cameras[bpy.data.objects[activeCameraName].data.name] + active_object = context.active_object + arm, cam = get_arm_and_cam(context.active_object) + pose_bones = arm.pose.bones + cam_data = cam.data layout = self.layout.box().column() layout.label(text="Clipping:") - layout.prop(cam, "clip_start", text="Start") - layout.prop(cam, "clip_end", text="End") - layout.prop(cam, "type") - layout.prop(cam.dof, "use_dof") - if cam.dof.use_dof: - if cam.dof.focus_object is None: - layout.operator("add_camera_rigs.add_dof_object", text="Add DOF Empty") - layout.prop(poseBones["Camera"], '["focus_distance"]', text="Focus Distance") - layout.prop(poseBones["Camera"], '["f-stop"]', text="F-Stop") - - layout.prop(self._ACTIVE_OBJECT, 'show_in_front', toggle=False, text='Show in front') - layout.prop(cam, "show_limits") - layout.prop(cam, "show_passepartout") - if cam.show_passepartout: - layout.prop(cam, "passepartout_alpha") + layout.prop(cam_data, "clip_start", text="Start") + layout.prop(cam_data, "clip_end", text="End") + layout.prop(cam_data, "type") + layout.prop(cam_data.dof, "use_dof") + if cam_data.dof.use_dof: + if cam_data.dof.focus_object is None: + layout.operator("add_camera_rigs.add_dof_object", + text="Add DOF Empty", icon="OUTLINER_OB_EMPTY") + layout.prop(pose_bones["Camera"], + '["focus_distance"]', text="Focus Distance") + layout.prop(pose_bones["Camera"], + '["aperture_fstop"]', text="F-Stop") + + layout.prop(active_object, 'show_in_front', + toggle=False, text='Show in Front') + layout.prop(cam_data, "show_limits") + layout.prop(cam_data, "show_passepartout") + if cam_data.show_passepartout: + layout.prop(cam_data, "passepartout_alpha") layout.row().separator() - # added the comp guides here - layout.operator( - "wm.call_menu", text="Composition Guides").name = "ADD_CAMERA_RIGS_MT_composition_guides_menu" + # Added the comp guides here + layout.popover( + panel="ADD_CAMERA_RIGS_PT_composition_guides", + text="Composition Guides",) layout.row().separator() - layout.prop(bpy.data.objects[activeCameraName], + layout.prop(cam, "hide_select", text="Make Camera Unselectable") layout.operator("add_camera_rigs.add_marker_bind", - text="Add Marker and Bind") - if bpy.context.scene.camera.name != activeCameraName: + text="Add Marker and Bind", icon="MARKER_HLT") + if context.scene.camera is not cam: layout.operator("add_camera_rigs.set_scene_camera", text="Make Camera Active", icon='CAMERA_DATA') - # Camera Lens - layout.label(text="Focal Length:") - layout.prop(poseBones["Camera"], '["focal_length"]', text="Focal Length (mm)") - if self._ACTIVE_RIG_TYPE == "Crane_rig": - layout = layout.box().column() - - # Crane arm stuff - layout.label(text="Crane Arm:") - layout.prop(poseBones["Crane_height"], 'scale', index=1, text="Arm Height") - layout.prop(poseBones["Crane_arm"], 'scale', index=1, text="Arm Length") + # Camera lens + layout.separator() + layout.prop(pose_bones["Camera"], '["lens"]', text="Focal Length (mm)") # Track to Constraint layout.label(text="Tracking:") - layout.prop(poseBones["Camera"], '["lock"]', text="Aim Lock", slider=True) + layout.prop(pose_bones["Camera"].constraints["Track To"], + 'influence', text="Aim Lock", slider=True) + + if arm["rig_id"].lower() == "crane_rig": + col = layout.box().column() + + # Crane arm stuff + col.label(text="Crane Arm:") + col.prop(pose_bones["Crane_height"], + 'scale', index=1, text="Arm Height") + col.prop(pose_bones["Crane_arm"], + 'scale', index=1, text="Arm Length") def register():