Skip to content
Snippets Groups Projects
space_view3d_spacebar_menu.py 49.8 KiB
Newer Older

        layout.separator()

        layout.operator_menu_enum("pose.select_grouped", "type", text="Grouped")
        layout.operator("object.select_pattern", text="Select Pattern...")

class VIEW3D_MT_PoseCopy(bpy.types.Menu):
    bl_label = "Pose Copy"

    def draw(self, context):
        layout = self.layout
		 
        layout.operator("pose.copy")
        layout.operator("pose.paste")
        layout.operator("pose.paste",
           text="Paste X-Flipped Pose").flipped = True
        layout.separator()

class VIEW3D_MT_PoseNames(bpy.types.Menu):
    bl_label = "Pose Copy"

    def draw(self, context):
        layout = self.layout
		 
        layout.operator_context = 'EXEC_AREA'
        layout.operator("pose.autoside_names",
            text="AutoName Left/Right").axis = 'XAXIS'
        layout.operator("pose.autoside_names",
            text="AutoName Front/Back").axis = 'YAXIS'
        layout.operator("pose.autoside_names",
            text="AutoName Top/Bottom").axis = 'ZAXIS'

        layout.operator("pose.flip_names")


class VIEW3D_MT_SelectSurface(bpy.types.Menu):
    bl_label = "Select Menu"

    def draw(self, context):
        layout = self.layout

        layout.operator("view3d.select_border")
        layout.operator("view3d.select_circle")

        layout.separator()

        layout.operator("curve.select_all", text="Select/Deselect All")
        layout.operator("curve.select_inverse")
        layout.operator("curve.select_random")
        layout.operator("curve.select_every_nth")

        layout.separator()

        layout.operator("curve.select_row")

        layout.separator()

        layout.operator("curve.select_more")
        layout.operator("curve.select_less")

class VIEW3D_MT_SelectMetaball(bpy.types.Menu):
    bl_label = "Select Menu"

    def draw(self, context):
        layout = self.layout

        layout.operator("view3d.select_border")

        layout.separator()

        #layout.operator("mball.select_deselect_all_metaelems")
        layout.operator("mball.select_inverse_metaelems")

        layout.separator()

        layout.operator("mball.select_random_metaelems")

class VIEW3D_MT_edit_TK(bpy.types.Menu):
    bl_label = "Edit Mesh"

    def draw(self, context):
        layout = self.layout
        row = layout.row()

        layout.operator_context = 'INVOKE_REGION_WIN'

        prop = layout.operator("wm.context_set_value",
            text="Select By Vertex", icon='VERTEXSEL')
        prop.value = "(True, False, False)"
        prop.path = "tool_settings.mesh_selection_mode"
        layout.menu("VIEW3D_MT_edit_mesh_vertices", icon='VERTEXSEL')

        prop = layout.operator("wm.context_set_value",
            text="Select By Edge", icon='EDGESEL')
        prop.value = "(False, True, False)"
        prop.path = "tool_settings.mesh_selection_mode"
        layout.menu("VIEW3D_MT_edit_mesh_edges", icon='EDGESEL')

        prop = layout.operator("wm.context_set_value",
            text="Select By Face", icon='FACESEL')
        prop.value = "(False, False, True)"
        prop.path = "tool_settings.mesh_selection_mode"
        layout.menu("VIEW3D_MT_edit_mesh_faces", icon='FACESEL')
        layout.separator()

        layout.menu("VIEW3D_MT_edit_mesh_normals", icon='META_DATA')
        layout.operator("mesh.loopcut_slide",
            text="Loopcut", icon='EDIT_VEC')

class VIEW3D_MT_editM_Edge(bpy.types.Menu):
    bl_label = "Edges"

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_REGION_WIN'

        layout.operator("mesh.mark_seam")
        layout.operator("mesh.mark_seam", text="Clear Seam").clear = True
        layout.separator()

        layout.operator("mesh.mark_sharp")
        layout.operator("mesh.mark_sharp", text="Clear Sharp").clear = True
        layout.operator("mesh.extrude_move_along_normals", text="Extrude")
        layout.separator()

        layout.operator("mesh.edge_rotate",
            text="Rotate Edge CW").direction = 'CW'
        layout.operator("mesh.edge_rotate",
            text="Rotate Edge CCW").direction = 'CCW'
        layout.separator()

        layout.operator("TFM_OT_edge_slide", text="Edge Slide")
        layout.operator("mesh.loop_multi_select", text="Edge Loop")
        layout.operator("mesh.loop_multi_select", text="Edge Ring").ring = True
        layout.operator("mesh.loop_to_region")
        layout.operator("mesh.region_to_loop")


class VIEW3D_MT_EditCurveCtrlpoints(bpy.types.Menu):
    bl_label = "Control Points"

    def draw(self, context):
        layout = self.layout

        edit_object = context.edit_object

        if edit_object.type == 'CURVE':
            layout.operator("transform.transform").mode = 'TILT'
            layout.operator("curve.tilt_clear")
            layout.operator("curve.separate")

            layout.separator()

            layout.operator_menu_enum("curve.handle_type_set", "type")

            layout.separator()

            layout.menu("VIEW3D_MT_hook")


class VIEW3D_MT_EditCurveSegments(bpy.types.Menu):
    bl_label = "Curve Segments"

    def draw(self, context):
        layout = self.layout

        layout.operator("curve.subdivide")
        layout.operator("curve.switch_direction")

class VIEW3D_MT_EditCurveSpecials(bpy.types.Menu):
    bl_label = "Specials"

    def draw(self, context):
        layout = self.layout

        layout.operator("curve.subdivide")
        layout.operator("curve.switch_direction")
        layout.operator("curve.spline_weight_set")
        layout.operator("curve.radius_set")
        layout.operator("curve.smooth")
        layout.operator("curve.smooth_radius")

class VIEW3D_MT_EditArmatureTK(bpy.types.Menu):
    bl_label = "Armature Tools"

    def draw(self, context):
        layout = self.layout

        # Edit Armature

        layout.operator("transform.transform", text="Scale Envelope Distance").mode = 'BONESIZE'

        layout.operator("transform.transform", text="Scale B-Bone Width").mode = 'BONESIZE'

        layout.separator()

        layout.operator("armature.extrude_move")

        layout.operator("armature.extrude_forked")

        layout.operator("armature.duplicate_move")
        layout.operator("armature.merge")
        layout.operator("armature.fill")
        layout.operator("armature.delete")
        layout.operator("armature.separate")

        layout.separator()

        layout.operator("armature.subdivide_multi", text="Subdivide")
        layout.operator("armature.switch_direction", text="Switch Direction")

class VIEW3D_MT_ArmatureName(bpy.types.Menu):
    bl_label = "Armature Name"

    def draw(self, context):
        layout = self.layout

        layout.operator_context = 'EXEC_AREA'
        layout.operator("armature.autoside_names", text="AutoName Left/Right").type = 'XAXIS'
        layout.operator("armature.autoside_names", text="AutoName Front/Back").type = 'YAXIS'
        layout.operator("armature.autoside_names", text="AutoName Top/Bottom").type = 'ZAXIS'
        layout.operator("armature.flip_names")
        layout.separator()

class VIEW3D_MT_KeyframeMenu(bpy.types.Menu):
    bl_label = "Keyframe Menu"

    def draw(self, context):
        layout = self.layout

        # Keyframe Bleck
        layout.operator("anim.keyframe_insert_menu",
            text="Insert Keyframe...")
        layout.operator("anim.keyframe_delete_v3d",
            text="Delete Keyframe...")
        layout.operator("anim.keying_set_active_set",
            text="Change Keying Set...")
        layout.separator()

# Classes for VIEW3D_MT_CursorMenu()
class VIEW3D_OT_pivot_cursor(bpy.types.Operator):
    "Cursor as Pivot Point"
    bl_idname = "view3d.pivot_cursor"
    bl_label = "Cursor as Pivot Point"

    def poll(self, context):
        return bpy.context.space_data.pivot_point != 'CURSOR'

    def execute(self, context):
        bpy.context.space_data.pivot_point = 'CURSOR'
        return {'FINISHED'}

class VIEW3D_OT_revert_pivot(bpy.types.Operator):
    "Revert Pivot Point"
    bl_idname = "view3d.revert_pivot"
    bl_label = "Reverts Pivot Point to median"

    def poll(self, context):
        return bpy.context.space_data.pivot_point != 'MEDIAN_POINT'

    def execute(self, context):
        bpy.context.space_data.pivot_point = 'MEDIAN_POINT'
        # @todo Change this to 'BOUDNING_BOX_CENTER' if needed...
        return{'FINISHED'}

class VIEW3D_MT_CursorMenu(bpy.types.Menu):
    bl_label = "Snap Cursor Menu"

    def draw(self, context):

        layout = self.layout
        layout.operator_context = 'INVOKE_REGION_WIN'
        layout.operator("view3d.snap_cursor_to_selected",
            text="Cursor to Selected")
        layout.operator("view3d.snap_cursor_to_center",
            text="Cursor to Center")
        layout.operator("view3d.snap_cursor_to_grid",
        layout.operator("view3d.snap_cursor_to_active",
            text="Cursor to Active")
        layout.separator()
        layout.operator("view3d.snap_selected_to_cursor",
            text="Selection to Cursor")
        layout.operator("view3d.snap_selected_to_grid",
            text="Selection to Grid")
        layout.separator()
        layout.operator("view3d.pivot_cursor",
            text="Set Cursor as Pivot Point")
        layout.operator("view3d.revert_pivot",
            text="Revert Pivot Point")

class VIEW3D_MT_EditCursorMenu(bpy.types.Menu):
    bl_label = "Snap Cursor Menu"

    def draw(self, context):

        layout = self.layout
        layout.operator_context = 'INVOKE_REGION_WIN'
        layout.operator("view3d.snap_cursor_to_selected",
            text="Cursor to Selected")
        layout.operator("view3d.snap_cursor_to_center",
            text="Cursor to Center")
        layout.operator("view3d.snap_cursor_to_grid",
            text="Cursor to Grid")
        layout.operator("view3d.snap_cursor_to_active",
            text="Cursor to Active")
        layout.separator()
        layout.operator("view3d.snap_selected_to_cursor",
            text="Selection to Cursor")
        layout.operator("view3d.snap_selected_to_grid",
            text="Selection to Grid")
        layout.separator()
        layout.operator("view3d.pivot_cursor",
            text="Set Cursor as Pivot Point")
        layout.operator("view3d.revert_pivot",
            text="Revert Pivot Point")
        layout.operator("view3d.snap_cursor_to_edge_intersection",
            text="Cursor to Edge Intersection")
        layout.operator("transform.snap_type", text="Snap Tools",
            icon='SNAP_ON')

def abs(val):
    if val > 0:
        return val
    return -val

def LineLineIntersect (p1, p2, p3, p4):
    # based on Paul Bourke's Shortest Line Between 2 lines
    
    min = 0.0000001
    
    v1 = Vector((p1.x - p3.x, p1.y - p3.y, p1.z - p3.z))
    v2 = Vector((p4.x - p3.x, p4.y - p3.y, p4.z - p3.z))
    
    if abs(v2.x) < min and abs(v2.y) < min and abs(v2.z)  < min:
        return None
        
    v3 = Vector((p2.x - p1.x, p2.y - p1.y, p2.z - p1.z))
    
    if abs(v3.x) < min and abs(v3.y) < min and abs(v3.z) < min:
        return None

    d1 = v1.dot(v2)
    d2 = v2.dot(v3)
    d3 = v1.dot(v3)
    d4 = v2.dot(v2)
    d5 = v3.dot(v3)

    d = d5 * d4 - d2 * d2
    
    if abs(d) < min:
        return None
        
    n = d1 * d2 - d3 * d4

    mua = n / d
    mub = (d1 + d2 * (mua)) / d4

    return [Vector((p1.x + mua * v3.x, p1.y + mua * v3.y, p1.z + mua * v3.z)), 
        Vector((p3.x + mub * v2.x, p3.y + mub * v2.y, p3.z + mub * v2.z))]

def edgeIntersect(context, operator):
    
    obj = context.active_object
    
    if (obj.type != "MESH"):
        operator.report({'ERROR'}, "Object must be a mesh")
        return None
    
    edges = [];
    mesh = obj.data
    verts = mesh.verts

    is_editmode = (obj.mode == 'EDIT')
    if is_editmode:
        bpy.ops.object.mode_set(mode='OBJECT')
    
    for e in mesh.edges:
        if e.selected:
            edges.append(e)

    if is_editmode:
        bpy.ops.object.mode_set(mode='EDIT')
            
    if len(edges) != 2:
        operator.report({'ERROR'}, "Operator requires exactly 2 edges to be selected.")
        return
        
    line = LineLineIntersect(verts[edges[0].verts[0]].co, verts[edges[0].verts[1]].co, verts[edges[1].verts[0]].co, verts[edges[1].verts[1]].co)

    if (line == None):
        operator.report({'ERROR'}, "Selected edges are parallel.")
        return

    tm = obj.matrix.copy()
    point = ((line[0] + line[1]) / 2)
    point = tm * point

    context.scene.cursor_location = point
            
    return point
    
class VIEW3D_OT_CursorToEdgeIntersection(bpy.types.Operator):
    "Finds the mid-point of the shortest distance between two edges"
    
    bl_idname = "view3d.snap_cursor_to_edge_intersection"
    bl_label = "Cursor to Edge Intersection"

    def poll(self, context):
        obj = context.active_object
        return obj != None and obj.type == 'MESH'

    def execute(self, context):
        edgeIntersect(context, self)
        return {'FINISHED'}

class VIEW3D_MT_undoS(bpy.types.Menu):
    bl_label = "Undo/Redo"

    def draw(self, context):
        layout = self.layout
        layout.operator_context = 'INVOKE_REGION_WIN'
        layout.operator("ed.undo", icon='TRIA_LEFT')
        layout.operator("ed.redo", icon='TRIA_RIGHT')

def register():
    bpy.types.register(VIEW3D_MT_Space_Dynamic_Menu)
    bpy.types.register(VIEW3D_MT_AddMenu)
    bpy.types.register(VIEW3D_MT_TransformMenu)
    bpy.types.register(VIEW3D_MT_MirrorMenu)
    bpy.types.register(VIEW3D_MT_ParentMenu)
    bpy.types.register(VIEW3D_MT_GroupMenu)
    bpy.types.register(VIEW3D_MT_AlignMenu)
    bpy.types.register(VIEW3D_MT_SelectMenu)
    bpy.types.register(VIEW3D_MT_SelectEditMenu)
    bpy.types.register(VIEW3D_MT_SelectCurveMenu)
    bpy.types.register(VIEW3D_MT_SelectPoseMenu)
    bpy.types.register(VIEW3D_MT_PoseCopy)
    bpy.types.register(VIEW3D_MT_PoseNames)
    bpy.types.register(VIEW3D_MT_KeyframeMenu)
    bpy.types.register(VIEW3D_MT_SelectArmatureMenu)
    bpy.types.register(VIEW3D_MT_ArmatureName)
    bpy.types.register(VIEW3D_MT_SelectMetaball)
    bpy.types.register(VIEW3D_MT_SelectSurface)
    bpy.types.register(VIEW3D_MT_edit_TK)
    bpy.types.register(VIEW3D_MT_EditArmatureTK)
    bpy.types.register(VIEW3D_MT_editM_Edge)
    bpy.types.register(VIEW3D_MT_EditCurveCtrlpoints)
    bpy.types.register(VIEW3D_MT_EditCurveSegments)
    bpy.types.register(VIEW3D_MT_EditCurveSpecials)
    bpy.types.register(VIEW3D_OT_pivot_cursor)
    bpy.types.register(VIEW3D_OT_revert_pivot)
    bpy.types.register(VIEW3D_MT_CursorMenu)
    bpy.types.register(VIEW3D_MT_EditCursorMenu)
    bpy.types.register(VIEW3D_OT_CursorToEdgeIntersection)
    bpy.types.register(VIEW3D_MT_undoS)

    km = bpy.context.manager.active_keyconfig.keymaps['3D View']
    kmi = km.items.add('wm.call_menu', 'SPACE', 'PRESS')
    kmi.properties.name = "VIEW3D_MT_Space_Dynamic_Menu"


def unregister():
    bpy.types.unregister(VIEW3D_MT_Space_Dynamic_Menu)
    bpy.types.unregister(VIEW3D_MT_AddMenu)
    bpy.types.unregister(VIEW3D_MT_TransformMenu)
    bpy.types.unregister(VIEW3D_MT_MirrorMenu)
    bpy.types.unregister(VIEW3D_MT_ParentMenu)
    bpy.types.unregister(VIEW3D_MT_GroupMenu)
    bpy.types.unregister(VIEW3D_MT_AlignMenu)
    bpy.types.unregister(VIEW3D_MT_SelectMenu)
    bpy.types.unregister(VIEW3D_MT_SelectEditMenu)
    bpy.types.unregister(VIEW3D_MT_SelectCurveMenu)
    bpy.types.unregister(VIEW3D_MT_SelectPoseMenu)
    bpy.types.unregister(VIEW3D_MT_PoseCopy)
    bpy.types.unregister(VIEW3D_MT_PoseNames)
    bpy.types.unregister(VIEW3D_MT_KeyframeMenu)
    bpy.types.unregister(VIEW3D_MT_SelectArmatureMenu)
    bpy.types.unregister(VIEW3D_MT_ArmatureName)
    bpy.types.unregister(VIEW3D_MT_SelectMetaball)
    bpy.types.unregister(VIEW3D_MT_SelectSurface)
    bpy.types.unregister(VIEW3D_MT_edit_TK)
    bpy.types.unregister(VIEW3D_MT_EditArmatureTK)
    bpy.types.unregister(VIEW3D_MT_editM_Edge)
    bpy.types.unregister(VIEW3D_MT_EditCurveCtrlpoints)
    bpy.types.unregister(VIEW3D_MT_EditCurveSegments)
    bpy.types.unregister(VIEW3D_MT_EditCurveSpecials)
    bpy.types.unregister(VIEW3D_OT_pivot_cursor)
    bpy.types.unregister(VIEW3D_OT_revert_pivot)
    bpy.types.unregister(VIEW3D_MT_CursorMenu)
    bpy.types.unregister(VIEW3D_MT_EditCursorMenu)
    bpy.types.unregister(VIEW3D_OT_CursorToEdgeIntersection)
    bpy.types.unregister(VIEW3D_MT_undoS)

    km = bpy.context.manager.active_keyconfig.keymaps['3D View']
    for kmi in km.items:
        if kmi.idname == 'wm.call_menu':
Brendon Murphy's avatar
Brendon Murphy committed
            if kmi.properties.name == "VIEW3D_MT_Space_Dynamic_Menu":
                km.remove_item(kmi)
                break

if __name__ == "__main__":
    register()