diff options
author | meta-androcto <meta.androcto1@gmail.com> | 2019-12-02 02:54:05 +0300 |
---|---|---|
committer | meta-androcto <meta.androcto1@gmail.com> | 2019-12-02 02:54:05 +0300 |
commit | 7cfd041403732d6913415eeda89769ea7d424cfe (patch) | |
tree | e9d22bb3991f096dbf395c5734b38585ddbe0df9 /add_camera_rigs/build_rigs.py | |
parent | 44680646e7111881f723729637e617ad35d63b1a (diff) |
add camera rigs: update, move to folder structure: T71763
Diffstat (limited to 'add_camera_rigs/build_rigs.py')
-rw-r--r-- | add_camera_rigs/build_rigs.py | 544 |
1 files changed, 544 insertions, 0 deletions
diff --git a/add_camera_rigs/build_rigs.py b/add_camera_rigs/build_rigs.py new file mode 100644 index 00000000..c7303198 --- /dev/null +++ b/add_camera_rigs/build_rigs.py @@ -0,0 +1,544 @@ +import bpy +from bpy.types import Operator +from math import radians +from rna_prop_ui import rna_idprop_ui_prop_get +from .create_widgets import (create_root_widget, + create_widget, + create_camera_widget, + create_aim_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: + bones = rig.data.edit_bones + bones.remove(bones[0]) + + # Add new bones: + root = bones.new("Root") + root.tail = (0.0, 3.0, 0.0) + + 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 + + ctrlAim = bones.new("Aim") + ctrlAim.head = (0.0, 5.0, 3.0) + ctrlAim.tail = (0.0, 7.0, 3.0) + + ctrl = bones.new("Camera") + ctrl.head = (0.0, 0.0, 3.0) + ctrl.tail = (0.0, 2.0, 3.0) + + # 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 + + +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: + bones = rig.data.edit_bones + bones.remove(bones[0]) + + # Add new bones: + root = bones.new("Root") + root.tail = (0.0, 3.0, 0.0) + + ctrlAimChild = bones.new("aim_MCH") + ctrlAimChild.head = (0.0, 10.0, 1.0) + ctrlAimChild.tail = (0.0, 12.0, 1.0) + ctrlAimChild.layers = boneLayer + + ctrlAim = bones.new("Aim") + ctrlAim.head = (0.0, 10.0, 1.0) + ctrlAim.tail = (0.0, 12.0, 1.0) + + ctrl = bones.new("Camera") + ctrl.head = (0.0, 1.0, 1.0) + ctrl.tail = (0.0, 3.0, 1.0) + + arm = bones.new("Crane_arm") + arm.head = (0.0, 0.0, 1.0) + arm.tail = (0.0, 1.0, 1.0) + + height = bones.new("Crane_height") + height.head = (0.0, 0.0, 0.0) + height.tail = (0.0, 0.0, 1.0) + + # Setup hierarchy: + ctrl.parent = arm + ctrl.use_inherit_rotation = False + ctrl.use_inherit_scale = False + + 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' + + # 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 + 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 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 + + # 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.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) + + 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" + 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) + + return {'FINISHED'} + + +# dolly and crane entries in the Add Object > Camera Menu +def add_dolly_crane_buttons(self, context): + if context.mode == 'OBJECT': + self.layout.operator( + ADD_CAMERA_RIGS_OT_build_dolly_rig.bl_idname, + text="Dolly Camera Rig", + icon='CAMERA_DATA' + ) + self.layout.operator( + ADD_CAMERA_RIGS_OT_build_crane_rig.bl_idname, + text="Crane Camera Rig", + icon='CAMERA_DATA' + ) + + +classes = ( + ADD_CAMERA_RIGS_OT_build_dolly_rig, + ADD_CAMERA_RIGS_OT_build_crane_rig, +) + + +def register(): + from bpy.utils import register_class + for cls in classes: + register_class(cls) + + bpy.types.VIEW3D_MT_camera_add.append(add_dolly_crane_buttons) + + +def unregister(): + from bpy.utils import unregister_class + for cls in classes: + unregister_class(cls) + + bpy.types.VIEW3D_MT_camera_add.remove(add_dolly_crane_buttons) + + +if __name__ == "__main__": + register() |