Continuous MouseCallback in GH

Hi there,
I’m trying to implement a continuous MouseCallback in Grasshopper. The goal is to have a GH component that continuously registers mouse clicks in Rhino viewports. (In detail: I want to retrieve a 3d point on mouse down and up, as if to drag smth from one place to another, to use it later similar to the Grab component in Kangaroo2 ).

I have a working Python Script version:

import System
import scriptcontext
import rhinoscriptsyntax as rs
import Rhino


def get_view_pt():
    screenPos = System.Windows.Forms.Cursor.Position 
    doc = Rhino.RhinoDoc.ActiveDoc 
    view = doc.Views.ActiveView 
    point = view.ActiveViewport.ScreenToClient(screenPos)  
    line = view.ActiveViewport.ClientToWorld(point) 
    cplane = view.ActiveViewport.ConstructionPlane() 
    
    _, t = Rhino.Geometry.Intersect.Intersection.LinePlane(line, cplane)
    P = line.PointAt(t)
    return P

class MyMouseCallback(Rhino.UI.MouseCallback):
    def __init__(self):
        self.pt_mouse_down = None
        self.pt_mouse_up = None
        
    def OnMouseDown(self, args):
        p = get_view_pt()
        print "mouse down point : ",p
        self.pt_mouse_down = p
        self.pt_mouse_up = None

    def OnMouseUp(self, args):
        p = get_view_pt()
        print "mouse up point : ",p
        self.pt_mouse_up = p
        self.add_drag_line
        self.pt_mouse_down = None
        self.pt_mouse_up = None
        
    @property
    def add_drag_line(self):
        if self.pt_mouse_down and self.pt_mouse_up:
            return rs.AddLine(self.pt_mouse_down, self.pt_mouse_up)
        else:
            pass
            
cb = MyMouseCallback()
cb.Enabled = True
while True:
    Rhino.RhinoApp.Wait()
    if scriptcontext.escape_test(False):
        print "ESC pressed "
        break     
cb.Enabled = False

adapted from this post and this post.
How can I make it run in a Grasshopper component?

Many thanks in advance for a hint :wink:

Hi, it’s always tricky to do these things in a GH script component. I wouldn’t do this. That’s the issue. You can try the following, which should work on a scripting level:

You need to make sure to register and instanciate it only once. Design it as a singleton class and put the instance in Rhinos global “sticky” dictionary. This object has to run on another thread. Make sure whenever you do something with core functionality, that you make it thread safe and invoke this change on the GUI thread.
Since Iron Python targets the net framework, check the Task library and google how you invoke something in the app main thread.( Dispatcher.Invoke… )
You might need to deal with the Grasshopper way of execution and when and where to invoke something. But as I said, it sounds complicated. Don’t forget that Kangaroo is a GH addin and has much more freedom in doing things apart from the GH logic.