Pie Menu

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Pie Menu

Post by looo »

Blender has this pie menu, and I think freecad could also benefit from such a menu. It extends the short-cuts and is useable for both, beginners and power users.
First I tried to directly paint to the graphics view of the viewer but then the pie-menu can be displayed not outside the viewer. (The blender pie-menu is displayed anywhere on the window.) In the code I'm posting below the menu is inside a new graphics view which is shown or hidden on key-press-event ("a" for the example) holding the key will show you the possibilities (no icons yet, but this shouldn't be too hard). Releasing the key hides the menu and executes the highlighted command.
For this example the menu is used as a workbench-switcher. When switching to arch or draft the key-press-event is disabled somehow and the behaviour of the menu changes a bit.

if you want, try it out and if you know how to improve it let me know... :D
thanks

Code: Select all

from __future__ import division
import FreeCADGui as Gui
from PySide import QtCore, QtGui
import numpy as np

class PieButton(QtGui.QGraphicsEllipseItem):
    def __init__(self, pos=[0, 0], angle_range=(0, 1), size=[50, 50], view=None, parent=None):
        super(PieButton, self).__init__(None, scene=parent)
        self.view = view
        self.angle_range = angle_range
        self.setRect(pos[0] - size[0] / 2, pos[1] - size[1] / 2, size[0], size[1])
        self.setBrush(QtGui.QBrush(QtCore.Qt.red))
        self.setAcceptHoverEvents(True)
        self.command = None
        self.hoover = False

    def setHoover(self, value):
        if not self.hoover == value:
            self.hoover = value
            if value:
                self.setBrush(QtGui.QBrush(QtCore.Qt.blue))
                self.view.setText(self.command[0])
            else:
                self.setBrush(QtGui.QBrush(QtCore.Qt.red))


class PieView(QtGui.QGraphicsView):
    def __init__(self, key, commands, parent=None):
        super(PieView, self).__init__(parent)
        self.key = key
        self.setWindowFlags(QtCore.Qt.Widget | QtCore.Qt.FramelessWindowHint)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        self.setStyleSheet("QGraphicsView {border-style: none; background: transparent;}" )
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.scene = QtGui.QGraphicsScene(self)
        self.scene.setSceneRect(-200, -200, 400, 400)
        self.setScene(self.scene)
        self.center = [0, 0]
        self.buttons = []
        self.label = QtGui.QGraphicsSimpleTextItem("")
        self.scene.addItem(self.label)
        self.add_commands(commands)

    def setText(self, text):
        self.label.setText(text)
        self.label.update()
        self.label.setPos(-self.label.sceneBoundingRect().width() / 2, 0)

    def add_commands(self, commands):
        num = len(commands)
        r = 100
        a = 70
        pie_phi = np.linspace(0, np.pi * 2, num + 1)
        phi = [(p + pie_phi[i + 1]) / 2 for i, p in enumerate(pie_phi[:-1])]
        for i, command in enumerate(commands):
            button = PieButton(
                [r * np.cos(phi[i]), r * np.sin(phi[i])],
                [pie_phi[i], pie_phi[i + 1]],
                [a, a], self, self.scene)
            button.command = command
            self.scene.addItem(button)
            self.buttons.append(button)

    def mouseMoveEvent(self, event):
        r2, angle = self.polarCoordinates
        hoover = False
        for item in self.buttons:
            if (item.angle_range[0] < angle and
                angle < item.angle_range[1] and
                r2 > 1000):
                item.setHoover(True)
                hoover = True
            else:
                item.setHoover(False)
        if not hoover:
            self.setText("")

    @property
    def polarCoordinates(self):
        pos = QtGui.QCursor.pos() - self.center
        r2 = pos.x() ** 2 + pos.y() ** 2
        angle = np.arctan2(pos.y(), pos.x())
        return r2, angle + (angle < 0) * 2 * np.pi

    def showAtMouse(self, event):
        if event["Key"] == self.key:
            self.show()
            self.center = QtGui.QCursor.pos()
            self.move(self.center.x()-(self.width()/2), self.center.y()-(self.height()/2))

    def keyReleaseEvent(self, event):
        super(PieView, self).keyReleaseEvent(event)
        if event.key() == QtGui.QKeySequence(self.key):
            if not event.isAutoRepeat():
                for item in self.scene.items():
                    if hasattr(item, "hoover"):
                        if item.hoover:
                            item.command[1]()
                self.hide()


if __name__ == "__main__":
    def part_design(): Gui.activateWorkbench("PartDesignWorkbench")
    def part(): Gui.activateWorkbench("PartWorkbench")
    def draft(): Gui.activateWorkbench("DraftWorkbench")
    def arch(): Gui.activateWorkbench("ArchWorkbench")
    def fem(): Gui.activateWorkbench("FemWorkbench")
    def sketch(): Gui.activateWorkbench("SketcherWorkbench")
    def draw(): Gui.activateWorkbench("DrawingWorkbench")
    def mesh(): Gui.activateWorkbench("MeshWorkbench")

    command_list = [
        ["PartDesign", part_design],
        ["Part", part],
        ["Draft", draft],
        ["Arch", arch],
        ["Fem", fem],
        ["sketch", sketch],
        ["draw", draw],
        ["mesh", mesh]]

    a = PieView("a", command_list)
    view = Gui.ActiveDocument.ActiveView
    view.addEventCallback("SoKeyboardEvent", a.showAtMouse)
drei
Posts: 479
Joined: Sun May 11, 2014 7:47 pm
Location: Mexico
Contact:

Re: Pie Menu

Post by drei »

This looks really good :D,

Perhaps an implementation could be set to also use this within the workbenches,
say if I'm in sketcher and I summon the macro it will allow me to select tools within the WB, and if I enter another one, it may allow me to use the commands of that WB.
Need help? Feel free to ask, but please read the guidelines first
User avatar
TT-RS
Posts: 70
Joined: Fri Oct 24, 2014 9:19 pm

Re: Pie Menu

Post by TT-RS »

drei wrote:Perhaps an implementation could be set to also use this within the workbenches,
say if I'm in sketcher and I summon the macro it will allow me to select tools within the WB, and if I enter another one, it may allow me to use the commands of that WB.
+1

Yes, such context pop-up menu is good idea, and as drei says it should have functionality dependend on WB.
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Pie Menu

Post by looo »

That is the plan. One global menu for wb.switch and one locale menu for every workbench. The problem is, that it is too heavy and buggy in this state and I don't know how to improve that. One thing is that background events sometimes close the window, or maybe that is a problem with the autorepeat option of the keyevent. The other thing is the key down suppress of the draft wb...
Here is a short demo of the menu connected with some framebuild functionality in action.
https://vimeo.com/127369120
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Pie Menu

Post by looo »

The other thing is the key down suppress of the draft wb
Ok, I have connected the menu to a key allready used in Draft. So this shouldn't be that difficult to solve.
User avatar
microelly2
Veteran
Posts: 4688
Joined: Tue Nov 12, 2013 4:06 pm
Contact:

Re: Pie Menu

Post by microelly2 »

very nice idea,
this is the functionality I have looked for to get direct context sensitive interaction. New opportunities to get the jobs faster done. Thanks.
User avatar
NormandC
Veteran
Posts: 18587
Joined: Sat Feb 06, 2010 9:52 pm
Location: Québec, Canada

Re: Pie Menu

Post by NormandC »

I shared your video on the FreeCAD Google+ community: https://plus.google.com/117324667497119 ... 4Hg7QxbnKZ
ilyxa
Posts: 7
Joined: Mon Mar 23, 2015 12:28 pm

Re: Pie Menu

Post by ilyxa »

Can you provide bit more infos about Beam and Shape feature used in this video for fast and nice tube contsruction?
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: Pie Menu

Post by looo »

thanks for the promotion normandC :)
Can you provide bit more infos about Beam and Shape feature used in this video for fast and nice tube contsruction?
The frame-builder stuff is a macro I've done some time ago. The idea was to simplify the procedure of dragging and rotating a sketch to a line and extruding it. The cutting tools are a miter cut, a plane cut and a shape cut.
if you want you can try: https://bitbucket.org/looooo/beam
User avatar
r-frank
Veteran
Posts: 2180
Joined: Thu Jan 24, 2013 6:26 pm
Location: Möckmühl, Germany
Contact:

Re: Pie Menu

Post by r-frank »

Reading about the pie menu ... well I had no idea what you were talking about ...
Then I saw your video on vimeo.
Now this is quite cool ...
It would speed up things and make FreeCAD more user-freindly and context-sensitive.

Please keep on working on this loo.

Roland
Deutsche FreeCAD Tutorials auf Youtube
My GrabCAD FreeCAD-Projects
FreeCAD lessons for beginners in english

Native german speaker - so apologies for my english, no offense intended :)
Post Reply