With Python, how to create a point that follows the movement of mouse?

Hi, guys, I`m trying to write a python script to create a point that follows the mouse moving and then stays at the position where the mouse is clicked.

I tried rs.addpoint() but it only create point after mouse clicked. Is there other ways to make it?

The short answer is “event handling” in general and Rhino’s “display conduits” in particular. It’s all a bit tricky.

Many Thanks for reply.

Im quit new on this aspect, for me, it means a lot tricky Im afraid…

when you mentioned “event handling” & “display conduits”, do you means they are 2 different solutions for my need or they must cooperate together to work? The official introduction is not so detailed, do you know any completed tutorial on this aspect?

Have you seen this:

2 Likes

Hi Martin,

I downloaded it, but it is not able to work anyway. And I read its code, it gets mouse position from screen while my intention is to get mouse position in 3D space dynamically in realtime.

1 Like

Here’s quick update to the code, but you probably still want to solve the dynamic updating using events:


230503_TrackMousePoints3D_00.gh (3.9 KB)

Edit: Just read your original question, you probably want to have a look at the Rhino.UI.MouseCallback class to intercept mouse movement and clicks (i.e. in addition to its position in 2D/3D).

4 Likes

Thank you for the quick fix, Anders. Now it’s working.
I’ll spend some time to dive in, to see what I can learn from it. I’m pretty sure it`s a very valuable reference in my case.

1 Like

In case that helps, here is a simple example using RhinoScript, should be easy to port to Python.
This works assuming you are ok with a loop and not getting into complexities of events programming:

Option Explicit

Call PointOnMouse()
Sub PointOnMouse()
	
	Dim c,p

	c = Rhino.GetCursorPos()(0)
	p = Rhino.AddPoint(c)
	Do
		Rhino.Sleep 10
		c = Rhino.GetCursorPos()(0)
		Call Rhino.PointCoordinates(p, c)
		If KeyStatus(&h01) Then Exit Sub
	Loop
	
End Sub

Function KeyStatus(hexKey)
	Call Rhino.GetAsyncKeyState(hexKey)
	If Cbool(Rhino.GetAsyncKeyState(hexKey) And -32768) Then KeyStatus = True Else KeyStatus = False
End Function
1 Like

Thanks, Jarek. I’ll look into this script as well.

I did some research on Official examples and found out that there is an example of dynamic drawing circle code that might be useful for my goal.
Dynamically Draw Geometry when Picking Points

I think if I can replace drawcircle to addpoint/drawpoint, it may work.
But in this code, I’m confused about the line with “e.Display.DrawCircle(circle, Color.Black)”. What is the “e” mean in this situation? I didn’t find its explaination on this page: Rhinocommon API

Hi guys, I have a quistion when I try to understand this code:

from Rhino import *
from Rhino.Geometry import *
from Rhino.Commands import *
from Rhino.Input.Custom import *
from scriptcontext import doc
from System.Drawing import *


def RunCommand():
    gp = GetPoint()
    gp.SetCommandPrompt("Center point")
    gp.Get()
    if gp.CommandResult() != Result.Success:
        return gp.CommandResult()
    center_point = gp.Point()
    if center_point == Point3d.Unset:
        return Result.Failure

    gcp = GetCircleRadiusPoint(center_point)
    gcp.SetCommandPrompt("Radius")
    gcp.ConstrainToConstructionPlane(False)
    gcp.SetBasePoint(center_point, True)
    gcp.DrawLineFromPoint(center_point, True)
    gcp.Get()
    if gcp.CommandResult() != Result.Success:
        return gcp.CommandResult()

    radius = center_point.DistanceTo(gcp.Point())
    cplane = doc.Views.ActiveView.ActiveViewport.ConstructionPlane()
    doc.Objects.AddCircle(Circle(cplane, center_point, radius))
    doc.Views.Redraw()
    return Result.Success


class GetCircleRadiusPoint(GetPoint):
    def __init__(self, centerPoint):
        self.m_center_point = centerPoint

    def OnDynamicDraw(self, e):
        cplane = e.RhinoDoc.Views.ActiveView.ActiveViewport.ConstructionPlane()
        radius = self.m_center_point.DistanceTo(e.CurrentPoint)
        circle = Circle(cplane, self.m_center_point, radius)
        e.Display.DrawCircle(circle, Color.Black)

if __name__ == "__main__":
    RunCommand()

In this code, OnDynamicDraw() is only defined in GetCircleRadiusPoint class, but not invoked in Runcommand(), how did it work for the whole script?

For anyone that may have same confusion.

OndynamicDraw() is a method from RhinoCommon, didn’t showed on the new Rhinocommon page:
RhinoCommon API(new)

But it did listed in the Old page:
OndynamicDraw

@mkarimi - can you help with the new help (above)?

Looks like the new site doesn’t include the protected methods. Looking into it …

Working on a fix right now:
https://mcneel.myjetbrains.com/youtrack/issue/WWW-2042/Include-private-members

@fmyl protected methods are now in the new documentation. Thanks for bringing it up.
https://developer.rhino3d.com/api/rhinocommon/rhino.input.custom.getpoint/ondynamicdraw

2 Likes

Thank you very much @mkarimi @dale That will help a lot for beginners like me.