How to create a custom Gumball?

Hi,
Complex and uncapped customization:

Summary

Personally I think that a much easier approach would be to make a custom overlay in d3/OpenGL.
it would allow you to easily and extensively customize your overlay.

An example would be this animated overlay (60fps), in Rhino you would be gutting your performance, by running a separate overlay you do not lose performance, It’s not computationally expensive and It’s not too hard to implement.

Personally I think that by going with the ETO path you will be having a harder time than just going straight for your own overlay in ogl/d3 when you will intend to further customize your UI.
Screen capture - b2830eb2edf9e214309e38e41d03ef14 - Gyazo


Simple and efficient

Summary

You could use otp to use PyQt5 if you’re going to be using Rhino8+
Here’s an example of overlay you can easily pull off inside of rhino and to interact with rhino, with a much better event handling and customization capabilities

There you have a sample script demostrating how to implement it :

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtGui import QPainter, QRegion, QCursor
import rhinoscriptsyntax as rs  # Import Rhino's Python library

class CircularOverlay(QMainWindow):
    def __init__(self):
        super().__init__()

        # Get mouse position
        mouse_pos = QCursor.pos()

        # Set window properties
        self.setWindowTitle("Circular Overlay")
        self.setGeometry(mouse_pos.x(), mouse_pos.y(), 200, 200)  # Smaller dimensions and positioned at mouse
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)

        # Create a QWidget for the central widget
        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)

        # Create buttons and connect them to Rhino commands
        self.button1 = self.create_button("SuperMoveEdge", central_widget, 0, 0, 100, 100)
        self.button2 = self.create_button("SuperCut", central_widget, 100, 0, 100, 100)
        self.button3 = self.create_button("Isolate", central_widget, 0, 100, 100, 100)
        self.button4 = self.create_button("View", central_widget, 100, 100, 100, 100)

    def create_button(self, command, parent, x, y, w, h):
        button = QPushButton(command, parent)
        button.setGeometry(x, y, w, h)
        button.clicked.connect(lambda: self.run_rhino_command(command))
        return button

    def run_rhino_command(self, command):
        rs.Command(command)  # Execute the Rhino command

    def paintEvent(self, event):
        # Create QPainter object
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        # Draw circle
        painter.setBrush(Qt.white)
        painter.drawEllipse(0, 0, 200, 200)  # Smaller circle

        # Create a circular region and set it as a mask
        region = QRegion(self.rect(), QRegion.Ellipse)
        self.setMask(region)

if __name__ == "__main__":
    app = QApplication([])
    window = CircularOverlay()
    window.show()
    app.exec_()

Hope this sparks some inspiration,
Farouk

2 Likes