Notifications
Clear all

[Closed] Manipulate while in mouseTrack/mouseTool

While creating primitives, you can use the manipulators (like the radius manip) without exiting the creation mode, cursor changes while hovering over the manipulator and after dragging it and releasing mouse, dragging once again creates a new primitive:

Trying to do the same with mouseTrack and mouseTool seems to block out the manipulator completely, though:

Is there any way to make it work so that you can continuously create new primitives while being able to manipulate them just like in the max creation mode?
This is the mouseTrack version (simplified but working):

global startPos, prevEvent, currEvent
manipulateMode = on

fn sphereTrack msg ir o f shift ctrl alt =
(
    prevEvent = copy currEvent
    currEvent = msg

    case currEvent of
    (
        #mouseMove:
        (
            if prevEvent == #mouseMove then $.radius = distance ir.pos startPos
            else Sphere radius:0 pos:(startPos = ir.pos) isSelected:on
            #continue
        )            
        #mouseAbort : #stop
        default : #continue
    )
)

mouseTrack trackCallback:sphereTrack snap:#3D

And this is the mouseTool variant (same, not a production-level code but shows the issue):

manipulateMode = on

tool sphereTool
(
    local startPos
    local pressed = off
    local prevEvent = #freeMove
    local currEvent = #freeMove

    on mousePoint click do
    (
        prevEvent = copy currEvent
        currEvent = #mouseClick
        
        if prevEvent == #freeMove do
            Sphere radius:0 pos:(startPos = gridPoint) isSelected:on
    )

    on mouseMove click do
    (
        prevEvent = copy currEvent
        currEvent = if lButton then case prevEvent of ( #mouseDrag : #mouseDrag; #mouseClick : #mouseDrag; default: #mouseClick )
                    else #mouseMove

        if currEvent == #mouseDrag then
            $.radius = distance gridPoint startPos
        else if currEvent == #mouseClick do
            Sphere radius:0 pos:(startPos = gridPoint) isSelected:on
    )
)

startTool sphereTool snap:#3D
9 Replies

it seems like the first animated example shows the creation mode using max UI and the create panel. Right?

the thing is : the real creation mode starts in this case after first mouse click, and ends after the cycle of creation was completed. After that MAX interface starts another cycle of creation (you still see the current object button pushed on)… But it will start only after you click a button first time…

it means you can “manipulate” inbetween creation modes. not during the creation mode.

both mouseTool and mouseTracking are going immediately to a special command mode which overrides “manipulation” mode. There is nothing you can do with it. Just maybe you can write your own MouseCallBack using SDK without overriding the manager’s mode (which might be “manipulate”).

The only solution I see is to write your own “dummy” (“fake”) plugin just for going into plugin instance creation mode and use it to build/create/modify what you want.

Right, the first gif shows what happens when the action is initiated from the create panel. The idea with fake plugin sounds great but it seems the plugin has to have a category and a button and subsequently, the commandpanel will be switched to the Create mode and that category – and I’d prefer to avoid that…
For example, I can create a node instance of this but not start the creation process:

plugin geometry creationLoop name:""
    classID:#(0x52d6520f, 0x1e582e5b)
    invisible:on
(
    tool create ( 
        on mousePoint click do (
            print "looping"
        )
    )
)

startObjectCreation creationLoop

You say the creation process doesn’t start until first click. At the same time the freeMove event of the create mousetool already fires at the same time when you can manipulate the object, same as if you normally start the tool. That’s what made me think there could be a way to override that:

manipulateMode = on

plugin geometry sphereTest name:"SphereTest"
    classID:#(0x68d85e2d, 0x587a91ad)
    category:"Standard"
    extends:Sphere
    replaceUI:on
(
    parameters main
    (
        radius type:#worldUnits default:5
        on radius set val do delegate.radius = val
    )

    tool create numPoints:2
    (
        on freeMove do format "free move + manipulate, %
" (int (mod (timeStamp()) 100))
        on mousePoint click do if click == 1 do nodeTM.translation = gridPoint
        on mouseMove click do radius = length gridDist
    )
)

startObjectCreation sphereTest

Either way, a custom MouseCallBack sounds a bit too complicated, especially as I’d like to be able to pass a custom function (say like the callback function of mousetrack). Since the creation cycle itself only starts after clicking – when the cursor isn’t changed to the manipulate one – could it be maybe made simpler (if possible) by only making a MouseCallBack that allows the manipulate mode to take precedence and exits on first ‘normal’ click?

is for your tool being able to manipulate an optional feature or the requirement?

It’s a requirement.

Okay, so after digging through the SDK, I now know why the same mouseTool run separately vs during object creation behaves differently, there’s an additional window proc during creation time to handle manipulators. I only know that because it’s removed when creating bones:

    MouseManager* mm = createInterface->GetMouseManager();
    if ((mm != NULL) && (NULL == suspendProc)) {
        // This is the additional window proc that intercepts
        // the mouse event for the manipulator. It interferes
        // with bone creation. We temporarily suspend it.
       suspendProc = mm->GetMouseWindProcCallback();
    }
    mm->SetMouseWindProcCallback(NULL);

    ...

    if (suspendProc != NULL) {
       createInterface->GetMouseManager()->SetMouseWindProcCallback(suspendProc);
       suspendProc = NULL;
    }

yes… that’s what i expected. during mouse tracking the system suspends some messages to not interfere with manipulator… but we want exact to “interfere”

i have couple tools where it would be a nice addition if i can combine “creation” and “manipulation” processes in one tool. so your idea challenged me, and i’m looking for a solution, but not yet lucky

And of course, the Painter Interface doesn’t do that:

global startPos, prevEvent, currObj
global lHit, lDir, wHit, wDir, str, rad
manipulateMode = on

fn paintStroke =
(
    thePainterInterface.getHitPointData &lHit &lDir &wHit &wDir &rad &str 0
    if currObj == undefined then currObj = Sphere radius:0 pos:(startPos = wHit) isSelected:on
    else currObj.radius = distance wHit startPos
)

fn startStroke = (thePainterInterface.undoStart(); currObj = undefined)
fn endStroke = thePainterInterface.undoAccept()
fn cancelStroke = thePainterInterface.undoCancel()
fn systemEnd = thePainterInterface.endPaintSession()

fn startPainter =
(
    local tpi = thePainterInterface

    tpi.undoCancel()
    tpi.endPaintSession()
    tpi.offMeshHitType = 2
    tpi.offMeshHitPos = [0,0,0]
    tpi.drawRing = tpi.drawNormal = tpi.drawTrace = tpi.pressureEnable = off
    tpi.scriptFunctions startStroke paintStroke endStroke cancelStroke systemEnd

    tpi.startPaintSession()
)

startPainter()

[quote=]– Error occurred in paintStroke(); position: 168; line: 7
– Frame:Should it work or this error is expected?

Might be that older max versions need to have the lHit, lDir, wHit, wDir, str, rad assigned to values of matching type, but yeah it should work as is.