Pie Menus (2.66) - Update 01/28/13

Have you tried right clicking and choosing save as? I think mac OS is recognizing the zip file and allowing you to go directly into it. If that does not work set it up like this:
A folder called piemenus with all .py files in it including the init.py placed in your addons directory. The individual pies are meant to work solo if you want, but it’s a pain and you will miss out on a lot of options next release (they might not even work individually next release)

Updated with new version and lots of customization features. Check the first post. Enjoy.

that worked to get as a zip but it still won’t let me check the add-on.

edit: still won’t let me check/uncheck the addon but it’s working

I just installed the update - I like the new hotkeys, but for some reason switching the view to FRONT is not working. Is it only issue on my machine or is it bug?

Just thought of two new pies:
Delete menu (hotkey X)
Proportional edit falloff (hotkey O) (screenshot if you don’t know what i’m talking about)

For the proportional edit pie, there’s 7 falloff options. For the 8th space in the pie, make it an on/off button.
But, if you can squeeze 10 slices into the pie, have the 8th be ON, 9th OFF and 10th be Connected (I use connected mode most often) - though with sub-pies you would only need 8 :wink:

EDIT: Oh and a neat little spin+scale animation would be cool as the pie opens :wink: don’t know if anything like that is at all possible though.

It’s a bug, fixed in my working copy - I’ll update later today and see if I can get this X menu in.

Thanks LApe, let me please know when is the script updated.
-D

p.s. I love your Modo theme :slight_smile:

Updated! Added a delete menu too in edit mode.

Works great!!! thank you

:slight_smile: thanks sir!
I know you’re planning to allow custom pies sometime, but could you quickly explain a little about how I’d go about adding my own pie? I’ve done a little coding, but nothing fancy, so it’s a little daunting to give a crack at it just yet.

Sure, I’ll write a tutorial!:

All relevent files are in the piemenus folder:

  1. Start by copying one of the other menu files. I suggest pie_greybrushes.py since it will require the least modification. Rename your copy to whatever you new menu is, like pie_mynewmenu.py. Open it up for modification!

  2. Start by modifying the bl_info part - especially the name and description:


bl_info = {
    "name": "Pie: GreyBrushesMenu",
    "author": "Dan Eicher, Sean Olson",
    "version": (0, 1, 0),
    "blender": (2, 6, 4),
    "location": "View3D",
    "description": "3d View greybrushes sculpting pie menu",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "3D View"
}

Now, the first class in the file looks like this:


class VIEW3D_MT_greybrushes_Menu(bpy.types.Operator):
    '''Grey Brushes Menu'''
    bl_idname = "view3d.greybrushes_menu"
    bl_label = "Pie Grey Brushes Menu"
 
    @classmethod
    def poll(cls, context):
        return context.area.type == 'VIEW_3D'
        
    def modal(self, context, event):
        context.area.tag_redraw()
 
        if event.type == 'MOUSEMOVE':
            # mouse-over highlight
            self.current = self.menu.calc(event.mouse_region_x, event.mouse_region_y)
                        
            # pointer of center circle points at the mouse
            self.menu.pointerangle=math.degrees(math.atan2(event.mouse_region_y-self.menu.menu_y, event.mouse_region_x-self.menu.menu_x))-90     
            


        elif event.type == 'LEFTMOUSE':
            # get menu item clicked
            self.current = self.menu.calc(event.mouse_region_x,
                                          event.mouse_region_y)
 
            do_exec = self.current and self.current.poll(context)
            if do_exec:
                self.current.op(self, context)
 
            if self.current is None or do_exec:
                context.region.callback_remove(self._handle)
                return {'FINISHED'}
 
        if self.current == -1 or event.type in ('RIGHTMOUSE', 'ESC'):
            context.region.callback_remove(self._handle)
            return {'CANCELLED'}
 
        return {'RUNNING_MODAL'}
 
    def invoke(self, context, event):
        self.current = None


        # generate menu content
        self.menu = menu_init(PieMenu(x=event.mouse_region_x,
                                      y=event.mouse_region_y,
                                      layout_radius=80,
                                      text_size=11,
                                      text_dpi=72,
                                      center_radius_squared=225,
                                      max_radius_squared=62500#22500
                                      ))
 
        context.window_manager.modal_handler_add(self)
        self._handle = context.region.callback_add(self.menu.draw,
                                                   (self, context),
                                                   'POST_PIXEL')
        return {'RUNNING_MODAL'}

Change anything here that say’s “greybrushes” to “mynewmenu”. Also change the ‘’‘Grey Brushes Menu’‘’ …note that the bl_idname = “view3d.greybrushes_menu” has to be all lower case. This cause me trouble.

Moving on…


def menu_init(menu):
    menu.menu_items.append(up("Inflate/Deflate", 0, 55, 0))
    menu.menu_items.append(upright("Layer", 65, 30, 45))
    menu.menu_items.append(right("Clay Strips", 80, 0, 90))
    menu.menu_items.append(downright("Draw", 65, -30, 135))
    menu.menu_items.append(down("Crease", 0, -55, 180))
    menu.menu_items.append(downleft("Brush", -65, -30, 225))
    menu.menu_items.append(left("Clay", -80, 0, 270))
    menu.menu_items.append(upleft("Blob", -65, 30, 315))
 
    menu.item_offset = 22.5
 
    return menu

This chunk of code defines your labels that are going to be on the pies if you are going to have 8 directions. The parameters are (“Name”, X Position of Pie label, Y position of Pie Label, Angle that the label sits at.). So

menu.menu_items.append(up("Inflate/Deflate", 0, 55, 0))

is the inflate/deflate brush, straight up, 0 pixels on X axis, 55 up on Y axis, at 0 degrees.

Moving on we define the classes called from the function above:


class up(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Inflate/Deflate']
 
 
class upright(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Layer']
 
 
class right(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Clay Strips']
 
 
class downright(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Draw']
 
 
class down(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Crease']
 
 
class downleft(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Brush']
 
 
class left(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Clay']
       


class upleft(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Blob']

I would just leave the class names the same and fill in what the buttons are doing. so in the case of the up class


class up(MenuItem):
    def op(self, parent, context):
        bpy.context.tool_settings.sculpt.brush=bpy.data.brushes['Inflate/Deflate']
 

you don’t have to change any line except the bpy line. This tends to be the most time consuming part of this whole process, finding out the bpy code for what you are trying to do…

Note: if you are going to crash blender - it’s probably happening here. For instance, if you try to do a cycles command while not in cycles, you’ll crash blender. If you try to go to a mode not supported by an object - ie. Sculpt Mode while on an armature - You guessed it…crash blender.

Next we have the setBind() and removeBind() functions


def setBind():
    #enable the addon keybinding
    km = bpy.context.window_manager.keyconfigs.active.keymaps['Sculpt']
    for kmi in km.keymap_items:
        if kmi.idname == 'view3d.greybrushes_menu':
            if kmi.type == 'ONE' and kmi.ctrl==False and kmi.alt==False and kmi.shift==False and kmi.oskey==False and kmi.any==False and kmi.key_modifier=='NONE':
                kmi.active=True
                break


    #disable the default keybinding
    km = bpy.context.window_manager.keyconfigs.active.keymaps['Sculpt']
    for kmi in km.keymap_items:
        if kmi.idname == 'brush.active_index_set':
            if kmi.type == 'ONE' and kmi.ctrl==False and kmi.alt==False and kmi.shift==False and kmi.oskey==False and kmi.any==False and kmi.key_modifier=='NONE':
                kmi.active=False
                break

These basically just enable/disable keybindings and are just opposites of each other find anything that say’s view3d.greybrushes_menu and change to view3d.mynewmenu
the brush.active_index_set is the old keybinding. If you have a key conflict you want to change, you will need to find the original keybinding in the userprefs. Put the replace the brush.active_index_set with the identifier of the function you are trying to replace. Also replate the ‘ONE’ with the key you are trying to put the pie menu on. Also be sure to define the mode you want the keybinds to show up in. ‘SCULPT’ for sculpt mode, ‘MESH’ for edit mode of meshes, ‘VIEW3D’ to show up in all 3d windows, etc etc etc.

Home stretch for this file:


def register():
    bpy.utils.register_class(VIEW3D_MT_greybrushes_Menu)


    #add the keybinding   
    km = bpy.context.window_manager.keyconfigs.active.keymaps['Sculpt']
    km.keymap_items.new('view3d.greybrushes_menu', 'ONE', 'PRESS')


    #disable the default keybinding
    km = bpy.context.window_manager.keyconfigs.active.keymaps['Sculpt']
    for kmi in km.keymap_items:
        if kmi.idname == 'brush.active_index_set':
            if kmi.type == 'ONE' and kmi.ctrl==False and kmi.alt==False and kmi.shift==False and kmi.oskey==False and kmi.any==False and kmi.key_modifier=='NONE':
                kmi.active=False
                break

The register and unregister functions are basically opposites of each other also. These are basically the same as above, changing view3d.greybrushes to view3d.mynewmenu but you also need to change the lines that say


bpy.utils.register_class(VIEW3D_MT_greybrushes_Menu)

to bpy.utils.register_class(VIEW3D_MT_mynewmenu_Menu)

All done with this file! Now we have to modify init.py to take advantage of it! Open init.py.

Now open init.py

  1. Add an import line with the other imports.
    import pie_mynewmenu

  2. In def initSceneProperties(scn): add an your menu. it should look like this


pie_item = pie_set.add()
pie_item.name = "[ON] 3DView - My New Menu Menu"

This adds your menu to the menu activation list in the default on position

  1. Now jump all the way down to the updateBinds() function.

Add an if statement for your new file that would look like this:


if not name.find(My New Menu')==-1:
     if bpy.context.scene.pie_settings[i].activate:               
          pie_myNewMenu.setBind()
     else:               
          pie_myNewMenu.removeBind()

This chunk of code basically searches the string for your menu name and if it finds it sets up the keybindings

  1. In register add a line like this:
    pie_myNewMenu.register()

and in unregister a line like this:
pie_myNewMenu.unregister()

All done! Your new pie menu should now work!

front view still not working for me.

Are you using 1.0.1b? Open the file pie_viewMenu.py with a text editor and do a search for this class:


class ViewFront(MenuItem):
     def op(self, parent, context):
     bpy.ops.view3d.viewnumpad(type='FRONT', align_active=False)

Is there more than one bpy line after def op(self, parent, context): ? Perhaps the line above has a # in front of it? If so, you are using an old version. You can download the new one or just remove the # sign and delete the other line so it looks like the code above.

On second thought…an easier way to tell would be to check if you have a delete menu in edit mode. With the addon on, go to edit mode and delete something with X. Does a pie menu show up? If not, update. If so, tell me and I’ll take another look at the view menu thing.

I am using the correct version. I will check the code and post my results this evening sometime.
Thank you for taking the time to respond.

Working now.
The strange thing is I did not do anything really.
I went in and checked the code and it matched up fine.
First I opened the .py in note pad, i could not read it because of structure. So I opened it in word pad, used the find function and found the proper lines and it read as it should. When I closed word pad it ask me if I wanted to save the changes, even though I did not make any, I saved and opened blender and it worked fine.
Dont know what I did but as long as it works I am cool with it.

This addon in my personal opinion is revolutionary as much as going from the 2.4 series to the 2.5x series.
Maybe because I had used Blender very little until 2.5, but still the same the pie menu add is my favorite addition to Blender in a long time.
Thank you for your continued effort in its development.

Thanks for the encouraging comments Scrog - If it gets popular enough I hope it gets pulled over to the Blender Core and implemented in C. I kinda look at this as a ‘Proof of Concept’

Strange that is magically started working for you. You probably had some sort of compiled .py file lurking somewhere or maybe a saved default in your blend that was messing with things. Hard to say.

I have been promoting it myself. I have done two videos letting people know. Since the last update, I will try to put up another update video sometime this coming week.

The videos are on my youtube channel. I am johnnybevo on youtube.

Any word on a clickless operation? I don’t mean to harp on about it, but it would make a huge difference in the usability and speed. To specifiy how I’d like to see it: Just holding down the hotkey, move in the right direction and let go of the hotkey.
Some people might like to see something based on distance travelled (automatically picking that option if you go over it a certain amount of pixels, I would guess?), but for me I’d prefer the former.

Also, at the moment if you hold down the hotkey (I’m just very used to sticky keys :D), the menu appears much slower/later.

Additionally, one way I would like to set it up myself is that pressing tab switches between object mode and whichever other mode was last selected (edit mode by default), but holding down tab serves up the radial menu. I understand this isn’t what everyone will want, so if I’m just given the option of setting it up this way myself I’ll be happy.

Enjoy!