import Mathutils import bpy class Error(Exception): pass class NoStartEndTime(Error): pass def lazy_deselect_objects(): if bpy.context.selected_objects: for obj in bpy.context.selected_objects: obj.selected = False def nukify_curve(curve): # The curve we're nukifying MUST have a start and end time set! try: start_frame = curve['start_frame'] end_frame = curve['end_frame'] except KeyError: raise NoStartEndTime( 'Both start_frame and end_frame must be set on a nukified curve') # We need to make sure that we have only the first layer visible # for this... that's how we work orig_visible_layers = list(bpy.context.scene.visible_layers) orig_cursor_location = bpy.context.scene.cursor_location bpy.context.scene.visible_layers = [True] + [False] * 19 bpy.context.scene.cursor_location = [0, 0, 0] # Delete old instances of curve stuff def possibly_delete_obj_by_prop(propname): if curve.get(propname): bpy.context.scene.objects.unlink( bpy.data.objects[curve[propname]]) del curve[propname] possibly_delete_obj_by_prop('rocket_bevel') possibly_delete_obj_by_prop('rocket_taper') possibly_delete_obj_by_prop('rocket_hook') possibly_delete_obj_by_prop('explosion_circle') # Set the bevel object to a cloned curvecircle, animate it lazy_deselect_objects() base_bevel = bpy.data.objects['nuke_curvecircle'] bpy.context.scene.objects.active = base_bevel base_bevel.selected = True bpy.ops.object.duplicate() new_bevel = bpy.context.scene.objects.active curve.data.bevel_object = new_bevel curve['rocket_bevel'] = new_bevel.name bpy.ops.anim.change_frame(frame=start_frame) bpy.ops.anim.keyframe_insert(type=-3, confirm_success=False) bpy.ops.anim.change_frame(frame=start_frame - 1) bpy.ops.transform.resize(value=(0.0, 0.0, 0.0)) bpy.ops.anim.keyframe_insert(type=-3, confirm_success=False) # Duplicate/create taper object lazy_deselect_objects() base_ctrlcurve = bpy.data.objects['base_ctrlcurve'] bpy.context.scene.objects.active = base_ctrlcurve base_ctrlcurve.selected = True bpy.ops.object.duplicate() new_taper_curve = bpy.context.scene.objects.active new_taper_curve.location = [0, 0, 0] curve.data.taper_object = new_taper_curve curve['rocket_taper'] = new_taper_curve.name # # Hook setup ## Enter edit mode ## Add hook to the taper object bpy.ops.object.mode_set(mode='EDIT', toggle=False) bpy.ops.object.hook_add_newob() bpy.ops.object.mode_set(mode='OBJECT', toggle=False) control_hook = bpy.context.selected_objects[0] bpy.context.scene.objects.active = control_hook curve['rocket_hook'] = control_hook.name ## Animate the hook bpy.ops.anim.change_frame(frame=start_frame) control_hook.location = [0.0, 1.0, 0.0] bpy.ops.anim.keyframe_insert(type=-1, confirm_success=False) bpy.ops.anim.change_frame(frame=end_frame) control_hook.location = [3.0, 1.0, 0.0] bpy.ops.anim.keyframe_insert(type=-1, confirm_success=False) # Figure out which point we want our "explosion" on ## We'll want to base the explosion coordinates on the explosion_coord = ( curve.data.splines[0].bezier_points[-1].co + curve.location) explosion_coord = explosion_coord + Mathutils.Vector([0, 0, 1]) ## Create a circle and attach at that point bpy.ops.mesh.primitive_circle_add( vertices=32, fill=True, radius=curve.get('explosion_radius', 1), layer=[True] + [False] * 31, location=explosion_coord) explosion = bpy.context.scene.objects.active curve['explosion_circle'] = explosion.name explosion.data.add_material(curve.data.materials[0]) ## Animate that circle. The order is: ## - Scaled down point ## - Squashed point ## - Final point ## ... but for laziness sake we will do it in reverse :) bpy.ops.anim.change_frame(frame=end_frame + 5) bpy.ops.anim.keyframe_insert(type=-3, confirm_success=False) bpy.ops.anim.change_frame(frame=end_frame + 4) bpy.ops.transform.resize(value=(1.1, 0.9, 1.1)) bpy.ops.anim.keyframe_insert(type=-3, confirm_success=False) bpy.ops.anim.change_frame(frame=end_frame) bpy.ops.transform.resize(value=(0.0, 0.0, 0.0)) bpy.ops.anim.keyframe_insert(type=-3, confirm_success=False) # set back the visible layers bpy.context.scene.visible_layers = orig_visible_layers bpy.context.scene.cursor_location = orig_cursor_location def nukify_selected_curves(): curves = [ obj for obj in bpy.context.selected_objects if obj.type == 'CURVE'] for curve in curves: nukify_curve(curve)