Fusion-API Mouse Handling

Fusion-API Mouse Handling

manfred_weinert
Contributor Contributor
426 Views
4 Replies
Message 1 of 5

Fusion-API Mouse Handling

manfred_weinert
Contributor
Contributor

Hello,
I have been working with the Fusion API recently.
I noticed the following in connection with the development of "MouseEventHandler".
The notify member function of the "MouseEventHandler" class receives the address of the "MouseEventArgs" object from the caller.
"void OnMousexxxxxHandler::notify(const Ptr<MouseEventArgs>& eventArgs)"
The "MouseEventArgs" object also includes the "button" property. This is described in the API as follows: "Retrieves which mouse button(s) are pressed.
The returned value is bitwise and can indicate that more than one button is pressed."
If you follow the link under button you will find out that button is of type "enum MouseButtons{...}", which is defined as follows:
/// Mouse button values.
enum MouseButtons
{
/// None
NoMouseButton = 0x0,
/// Left
LeftMouseButton = 0x1,
/// Right
RightMouseButton = 0x2,
/// Middle
MiddleMouseButton = 0x4
};
But that doesn't match the description of "button", because it explicitly states that all key combinations can occur.
Accordingly, the definition for MuoseButtons should look like this:
/// Mouse button values.
enum MouseButtons
{
/// None
NoMouseButton = 0x0,
/// Left
LeftMouseButton = 0x1,
/// Right
RightMouseButton = 0x2,
/// LeftRight
LeftRightMouseButton = 0x3
/// Middle
MiddleMouseButton = 0x4
/// LeftRight
LeftMiddleMouseButton = 0x5
/// LeftRight
MiddleRightMouseButton = 0x6
/// LeftRight
LeftMiddleRightMouseButton = 0x7
};
It has also been noticed that when reading the button value for all types of mouse events (drag, down, up, click, move) either no mouse button is returned
or only the left mouse button is returned as pressed.
This could of course be because the basic software processes the right mouse button or middle mouse button pressed beforehand and no longer passes the information
on to the subsequently installed mouse event.
I would like to know if anyone can give me more detailed information on how this works in the context of ADDÍN development.
Is there, for example, an API function with which all mouse activities are forwarded to a corresponding ADDIN?
Can the first recipients of the mouse events be switched off under certain circumstances so that the ADDIN becomes the first recipient???

Thank you in advance for your advice.

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

BrianEkins
Mentor
Mentor

I haven't done much with the mouse events and don't have any first-hand information about their behavior, but I can answer your first question about the enums. Bitwise enum values can be combined to indicate more than one value. Notice how the values skip 3. We can see why if we look at the binary equivalent of those numbers:

 

0 - 000

1 -  001

2 - 010

4 - 100

 

Each value is a separate bit in the binary representation. If I get 101, it is a combination of 1 and 4. A value of 7 is all the combined bits, indicating that all three buttons were pressed.

 

Here's how I can check it in the code to see when both the left and right are pressed.

 

 

if pressedButtons & (adsk.core.MouseButtons.LeftMouseButton | adsk.core.MouseButtons.RightMouseButton):
    app.log('left and right mouse buttons (and maybe the middle) are pressed.')

 

 

Here, it checks if only the left and right are pressed.

 

 

if pressedButtons == (adsk.core.MouseButtons.LeftMouseButton | adsk.core.MouseButtons.RightMouseButton):
   app.log('Only the left and right are pressed')

 

 
Or here's a simpler way to check if only the left and right are pressed, but it's not as self-documenting:
 

 

 

if pressedButtons == 3:
   app.log('Only the left and right are pressed')

 

 

Here's a good article on using bitwise operators.

https://www.geeksforgeeks.org/python-bitwise-operators/

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes
Message 3 of 5

manfred_weinert
Contributor
Contributor

Brian, thank you for your quick response.

First of all, I should probably mention that I use C++ as my programming language.

Your contribution helped me a lot.

In general, I already know how data is processed bit by bit.

However, I was not aware that it is possible to assign other values ​​to an enum variable that are not specified in the type definition.

executes the following line of code:

 

 

 

#include <Core/CoreAll.h>
sing namespace adsk::core;
int i_mbs;
MouseButtons mbs_mbs;
i_mbs = LeftMouseButton | RightMouseButton;
mbs_mbs = i_mbs; // compiler Error 2440
mbs_mbs = LeftMouseButton | RightMouseButton;// compiler Error 2440
mbs_mbs = static_cast<MouseButtons> (i_mbs);//OK
mbs_mbs = static_cast<MouseButtons> (LeftMouseButton | RightMouseButton);//OK
mbs_mbs = static_cast<MouseButtons> (8);//OK

 

For line 6 and 7 you will get a compilation error 2440.

line 8 to 10 will run through compilation without errors.

But line 10 shows up, that this way can cause programm errors, because you can set up any integer value to the variable.

 

However, the other problem with the mouse button states not being passed on to the add-in is probably the bigger one.

I have to get into the habit of separating problems from each other because I can't mark the post as solved yet.

best regards

 

0 Likes
Message 4 of 5

BrianEkins
Mentor
Mentor

Here's an article for C++ that explains bitwise operators.
https://www.geeksforgeeks.org/cpp-bitwise-operators/

 

I think the error you're seeing is probably because of the variable type of mbs_mbs. enum values are an integer and not a type.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes
Message 5 of 5

manfred_weinert
Contributor
Contributor
Accepted solution

The following description should explain why this happens.

 

Casting rules

Unscoped enum constants can be implicitly converted to int, but an int is never implicitly convertible to an enum value. The following example shows what happens if you try to assign hand a value that isn't a Suit:

C++Copy
 
int account_num = 135692;
Suit hand;
hand = account_num; // error C2440: '=' : cannot convert from 'int' to 'Suit'

A cast is required to convert an int to a scoped or unscoped enumerator. However, you can promote an unscoped enumerator to an integer value without a cast.

C++Copy
 
int account_num = Hearts; //OK if Hearts is in an unscoped enum

Using implicit conversions in this way can lead to unintended side-effects. To help eliminate programming errors associated with unscoped enums, scoped enum values are strongly typed. Scoped enumerators must be qualified by the enum type name (identifier) and can't be implicitly converted, as shown in the following example:

C++Copy
 
namespace ScopedEnumConversions
{
    enum class Suit { Diamonds, Hearts, Clubs, Spades };

    void AttemptConversions()
    {
        Suit hand;
        hand = Clubs; // error C2065: 'Clubs' : undeclared identifier
        hand = Suit::Clubs; //Correct.
        int account_num = 135692;
        hand = account_num; // error C2440: '=' : cannot convert from 'int' to 'Suit'
        hand = static_cast<Suit>(account_num); // OK, but probably a bug!!!

        account_num = Suit::Hearts; // error C2440: '=' : cannot convert from 'Suit' to 'int'
        account_num = static_cast<int>(Suit::Hearts); // OK
    }
}

Notice that the line hand = account_num; still causes the error that occurs with unscoped enums, as shown earlier. It's allowed with an explicit cast. However, with scoped enums, the attempted conversion in the next statement, account_num = Suit::Hearts;, is no longer allowed without an explicit cast.

 

The complete article can be found here

 

0 Likes