MouseEventArgs.position

MouseEventArgs.position

SaeedHamza
Advisor Advisor
636 Views
4 Replies
Message 1 of 5

MouseEventArgs.position

SaeedHamza
Advisor
Advisor

Hi,

 

So I'm trying to create a copy tool that works similar to the copy tool in AutoCAD (for sketch entities only), which by the way does already exist in Fusion 360 here : drawings workspace > Create Menu > Create Sketch > Modify Menu > Copy.

 

I already created everything I need for the add-in but only one thing is left and that is the position of the mouse left click when the user presses it ...

so I need to get the mouse position in the viewport the moment the user clicks it, also to specify that the click should be a left-click for it to work.

 

The problem I'm facing is with the MouseEventArgs, I just don't know where or how exactly to use it. I read almost every topic on the forums regarding this matter but didn't get a clear answer on how to do it, so if there is a sample on how to do it, it would be much appreciated, thanks.

 

Saeed

 

Capture.PNG

 

Saeed Hamza
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature

0 Likes
Accepted solutions (1)
637 Views
4 Replies
Replies (4)
Message 2 of 5

kandennti
Mentor
Mentor
Accepted solution

Hi @SaeedHamza .

 

When I tried this in the past, I was able to get the coordinates I wanted by using MouseEventArgs.viewportPosition.
However, since the object obtained was a Point2D, it needed to be calculated.

 

The following sample shows how to run the script while working on a sketch, and it will display the coordinate values on the sketch every time you click on it.

# Fusion360API Python script

import traceback
import adsk.cam
import adsk.fusion
import adsk.core

_app: adsk.core.Application = None
_ui: adsk.core.UserInterface = None
_handlers = []


class MyMouseClickHandler(adsk.core.MouseEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.MouseEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)

        # Current mouse cursor position.
        cursor2D: adsk.core.Point2D = args.viewportPosition

        # get viewport.
        vp: adsk.core.Viewport = args.viewport

        # Convert from view coordinates to 3D coordinates.
        pos3d: adsk.core.Point3D = vp.viewToModelSpace(cursor2D)

        # Get a sketch of the work in progress.
        global _app
        skt: adsk.fusion.Sketch = _app.activeEditObject

        # Get the geometry of the sketch plane.
        # But I think this method does not work in direct mode.
        refPlane = skt.referencePlane
        plane: adsk.core.Plane = refPlane.geometry

        # Get vector of eye-target from camera.
        # In short, get the direction you are facing.
        cam: adsk.core.Camera = vp.camera
        vec: adsk.core.Vector3D = cam.eye.vectorTo(cam.target)

        # Create an infinite line of the camera direction passing through the mouse cursor position.
        infiniteLine: adsk.core.InfiniteLine3D = adsk.core.InfiniteLine3D.create(
            pos3d, vec
        )

        # Obtain the intersection of a plane and an infinite line.
        interPnt: adsk.core.Point3D = plane.intersectWithLine(infiniteLine)

        # Convert to coordinates on the sketch.
        posSkt: adsk.core.Point3D = skt.modelToSketchSpace(interPnt)

        # Calculate the ratio for unit conversion.
        des: adsk.fusion.Design = _app.activeProduct
        unitMgr: adsk.core.UnitsManager = des.unitsManager
        unitInter = unitMgr.internalUnits
        unitDef = unitMgr.defaultLengthUnits

        ratio: float = unitMgr.convert(1, unitInter, unitDef)

        # Update the coordinate values of the dialog.
        global _txtIptInfo
        inputs: adsk.core.CommandInputs = args.firingEvent.sender.commandInputs
        txtIpt: adsk.core.TextBoxCommandInput = inputs.itemById('txtIpt')

        txtIpt.text = f'X:{posSkt.x * ratio}\nY:{posSkt.y * ratio}\nZ:{posSkt.z * ratio}'


class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandCreatedEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)
        try:
            global _handlers
            cmd: adsk.core.Command = adsk.core.Command.cast(args.command)
            cmd.isOKButtonVisible = False

            # event
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onMouseClick = MyMouseClickHandler()
            cmd.mouseClick.add(onMouseClick)
            _handlers.append(onMouseClick)

            # inputs
            inputs: adsk.core.CommandInputs = cmd.commandInputs

            inputs.addTextBoxCommandInput(
                'txtIpt',
                'position',
                '-',
                3,
                True
            )

        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)
        adsk.terminate()


def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        # Quit the script when you are not working on a sketch.
        actEditObj = _app.activeProduct.activeEditObject
        if actEditObj.classType() != adsk.fusion.Sketch.classType():
            _ui.messageBox(
                'This can only be done in a sketch task.'
            )
            return

        cmdDef: adsk.core.CommandDefinition = _ui.commandDefinitions.itemById(
            'test_cmd'
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                'test_cmd',
                'Test',
                'Test'
            )

        global _handlers
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        cmdDef.execute()

        adsk.autoTerminate(False)

    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

I don't think it will work correctly in direct mode or sketching in deep Occurrence.

 

There may be an easier way to get the coordinate values, but this is the only way I could find.

Message 3 of 5

SaeedHamza
Advisor
Advisor

Hi @kandennti ,

 

Thanks so much for the above example, this showed me a lot of things that I was missing, definitely gonna help!

 

Also, I found a mouse example that shows how to get the coordinates and pretty much every mouse event that occurs by the user, and with your example above I'm confident I  got all I need.

 

Here is the Mouse Example : https://adndevblog.typepad.com/manufacturing/2016/09/fusion-api-usage-of-mouse-event.html

Saeed Hamza
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

EESignature

Message 4 of 5

kandennti
Mentor
Mentor

@SaeedHamza .

 

1.png

The viewportPosition property (0,0) means the top-left corner of Fusion360.

 

The position property (0,0) means the top-left corner of the display.
Therefore, you will not be able to get the correct coordinates due to the position of the Fusion360 window.

 

On the other hand, if you want to know the position of the Fusion360 window, the position property will be useful.

Message 5 of 5

BrianEkins
Mentor
Mentor

The Viewport object also contains several methods that will convert points in different spaces to another space. For example, there is screenToView and viewToModelSpace.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com