Home Technical Talk

[MAXScript] Detect Mouse Position Event: In/ Over/ Out

interpolator
Offline / Send Message
Revel interpolator
Alright guys, I'm looking for a way to detect whether my mouse cursor is in/ over/ out of an object on the viewport.
Form maxscript help;
mouse.mode
A read only variable to get the mouse mode as an <integer> value.
Return values are:
0 - Idle;
1 - Point;
2 - Move
Im guessing this have to do anything with it, but I have no idea where to proceed from there. Or is this even possible to do?

Replies

  • miauu
    Options
    Offline / Send Message
    miauu polycounter lvl 14
    Do you need to know where the cursor is all the time or only when you activate a script?
  • Revel
    Options
    Offline / Send Message
    Revel interpolator
    It's all the time, my idea was having the selection type to toggle between box/ lasso but whenever the mouse is over an object it will change to paint selection instead. Something like how modo works on it's selection. Max's default feels a little bit 'stiff' compare to modo :\
  • miauu
    Options
    Offline / Send Message
    miauu polycounter lvl 14
    I know how to detect if the mouse cursor is over an object, but this method is not good to be used all the time. There are calculations that have to be done, and on heavy scene(a lot of objects and faces) it takes time to find the object below the cursor. If you have to execute it each milisecond - this will freeze 3dsMax and you will not be able to work with it.
  • Revel
    Options
    Offline / Send Message
    Revel interpolator
    Hmm, yeah I kinda think that might be the possible problem. If lets say it only check when I press Q for example, is it possible?

    So the logic will be, instead of checking it all the time;
    If when script is run (by pressing a hotkey, for my case, Q) by the user, max check whether mouse is over the object or not, if yes then paint selection, else will toggle between box/ lasso.

    Is this more possible to do without leaving max freeze out cold?
  • miauu
    Options
    Offline / Send Message
    miauu polycounter lvl 14
    This is how it should works. :)
    Now, download this script and use it to write your own.
    The nethod that is used is verry similar to what I use in some of my scripts.
  • Revel
    Options
    Offline / Send Message
    Revel interpolator
    Hello miauu, I did looked into that script before but it's just too complected for my eyes =_=" too many scripting "vocabulary" that I have no idea what it does. But instead I google some more and found this guy's maxscript snippet and I implement to mine and out of surprise it works!
    (    
        local theTimer = dotNetObject "System.Windows.Forms.Timer"
        ry = mapScreenToWorldRay mouse.pos
        myray = ray ry.pos ry.dir
        intersect = intersectRayScene myray
        if intersect.count > 0 then
            (
                actionMan.executeAction 0 "59236" -- paint selection
            )
        else actionMan.executeAction 0 "59232"  -- rectangular selection
    )
    
    Miauu (or anyone else), I'll be appreciate if you can check the code and give your opinion whether it's a good/ bad solution? :)

    EDIT: woops, removed part of the code that only served as a testing purpose on my early itteration, heh.
  • miauu
    Options
    Offline / Send Message
    miauu polycounter lvl 14
    What is the purpose of the timer - to execute the script each second/milisecond?

    The problem with your code is that "intersect" always returns an array of objects. If you have several objects one after another, for example Teapot003 is in front of Teapot001, whics is in front of Teapot005, which is in front of Teapot002, the returned array wll be
    Teapot001, Teapot002, Teapot003, Teapot005
    As you see the objects are not in the order the ray hits them. You can try it. If this is not a problem for you then you can use the code. The other problem is that the code not works with splines.
  • Revel
    Options
    Offline / Send Message
    Revel interpolator
    Yeah, you're right. The timer actually redundant as I commented the first line and nothing happen, the code still works like what I expected.

    I don't quite understand your point with the "intersect" though, the original code was for making a list of object under the mouse cursor, hence return the array of objects like what you said. But the other 3 lines of code (variable: ry, myray, intersect) are connecting to each other so I guess I can't really remove any one of them.

    Also what is the different between whether the ray hits the object based on distance or not, for my case? Because for my purpose it's just to tell Max to select paint selection when there is any object bellow the cursor (no matter what object that is). Or am I missing some important detail in optimizing the code?

    As for the code only work for editable poly base object, well I might just put "case of" to tell max to run the code only when its editable poly when it's not, just cycle between rect/ lasso.
  • miauu
    Options
    Offline / Send Message
    miauu polycounter lvl 14
    If you want to know only if there is a mesh object beneath the cursor, then the script is OK.
  • Revel
    Options
    Offline / Send Message
    Revel interpolator
    Alright, thanks miauu :)
  • Revel
    Options
    Offline / Send Message
    Revel interpolator
    Hello guys, using the above code somehow works but I just found out that it actually detect a hidden object as well..is there anyway to treat hidden object as none or undefined? so that the code see nothing when the object is hidden?

    I want to make an if statement but have no idea what should I check as an if condition...
  • miauu
    Options
    Offline / Send Message
    miauu polycounter lvl 14
    Revel wrote: »
    Hello guys, using the above code somehow works but I just found out that it actually detect a hidden object as well..is there anyway to treat hidden object as none or undefined? so that the code see nothing when the object is hidden?

    I want to make an if statement but have no idea what should I check as an if condition...


    (    
        local theTimer = dotNetObject "System.Windows.Forms.Timer"
        ry = mapScreenToWorldRay mouse.pos
        myray = ray ry.pos ry.dir
        intersect = intersectRayScene myray
        if intersect.count > 0 and intersect[1][1].isHidden == false then
            (
                actionMan.executeAction 0 "59236" -- paint selection
            )
        else actionMan.executeAction 0 "59232"  -- rectangular selection
    )
    
  • Br0ken
    Options
    Offline / Send Message
    Br0ken polycounter lvl 3
    My variant of this script:

    fn paintrect =
    (
    ry = mapScreenToWorldRay mouse.pos
    myray = ray ry.pos ry.dir
    intersect = intersectRayScene myray
    sel = selection
    subobjlvl = subobjectlevel
    if intersect.count > 0 and intersect[1][1].isHidden == false and sel.count > 0 and subobjlvl > 0 then
            (
                actionMan.executeAction 0 "59236" -- paint selection
            )
    else actionMan.executeAction 0 "59232"  -- rectangular selection
    )
    theTimer = dotNetObject "System.Windows.Forms.Timer"
    dotnet.addEventHandler theTimer "tick" paintrect
    theTimer.interval = 250
    theTimer.start()

    But how to "pause" a timer when left mousebutton is pressed?
Sign In or Register to comment.