[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
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?
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.