Okay I've been trying to find an answer to this question, maybe someone here knows the answer. I'm not too great at scripting.
Basically, I have this script that I found that increments the falloff value of soft selection by a value (for example 0.5). This can be bound to a key so that every time I tap it, I can increase or decrease my falloff.
What I'd like to do, is be able to modify this script such that you could hold down a key, and then increment up & down using the mouseCursorY position. This would provide a functionality similar to a sculpting program like Mudbox. Is this even possible?
<font class="small">Code:</font><hr /><pre>
first macroscript
[begin snip]
macroScript ShrinkSoftSel
category:"MyScripts"
toolTip:"Shrink Soft Select"
(
on isEnabled return
(
if (((getcurrentselection()).count == 1) and ($ != undefined)) then
if (classof $.baseobject == Editable_Poly) then true else false
else false
)
on Execute do
(
undo off
(
local tempvalue = $.Falloff
tempvalue = tempvalue - 0.5
if (tempvalue < 0) then tempvalue = 0
$.Falloff = tempvalue
)
)
)
[end snip]
second macroscript
[begin snip]
macroScript GrowSoftSel
category:"MyScripts"
toolTip:"Grow Soft Select"
(
on isEnabled return
(
if (((getcurrentselection()).count == 1) and ($ != undefined)) then
if (classof $.baseobject == Editable_Poly) then true else false
else false
)
on Execute do
(
undo off
(
local tempvalue = $.Falloff
tempvalue = tempvalue + 0.5
$.Falloff = tempvalue
)
)
)
[end snip]
</pre><hr />
Thanks for any insight.
Replies
category:"MyScripts"
toolTip:""
(
curent_mouse = undefined
l_mouse = undefined
tool Falloff_control_0
(
on mousePoint xx do
(
curent_mouse = viewPoint
#stop
)
)
tool Falloff_control_1
(
on mousePoint xx do
(
l_mouse = viewPoint
#stop
)
)
on execute do
(
if (selection[1] != undefined) and ((classof selection[1].baseobject) == Editable_Poly) do
(
startTool Falloff_control_0
startTool Falloff_control_1
mouse_o = curent_mouse - l_mouse
tempvalue = selection[1].Falloff
---in order to change sensitivity use this and re-run the script
sensitivity = 5
tempvalue = tempvalue + (mouse_o.y/sensitivity)
selection[1].Falloff = (tempvalue)
)
)
)
macroScript mouse_falloff_2
category:"MyScripts"
toolTip:""
(
rollout falloff_mouseRollout "Untitled" width:360 height:25
(
slider sld1 "" pos:[73,1] width:300 height:25 range:[0,100,0] orient:#horizontal ticks:0
editText edt1 "" pos:[-3,3] width:68 height:16 enabled:false
on sld1 buttonup do
(
if (selection[1] != undefined) and ((classof selection[1].baseobject) == Editable_Poly) do
(
selection[1].Falloff = sld1.Value
DestroyDialog falloff_mouseRollout
)
)
on falloff_mouseRollout open do
(
if (selection[1] != undefined) and ((classof selection[1].baseobject) == Editable_Poly) do
(
edt1.Text = selection[1].Falloff as string
sld1.Value = selection[1].Falloff
)
)
)
createdialog falloff_mouseRollout style:#(#style_sysmenu)
)
category:"MyScripts"
toolTip:""
(
rollout falloff_mouseRollout "Untitled" width:344 height:25
(
slider sld1 "" pos:[51,1] width:300 height:25 range:[0,selection[1].Falloff*2,selection[1].Falloff] orient:#horizontal ticks:0
label edt1 "" pos:[2,3] width:44 height:16
on sld1 buttonup do
(
if (selection[1] != undefined) and ((classof selection[1].baseobject) == Editable_Poly) do
(
selection[1].Falloff = sld1.Value
selection[1].useSoftSel = true
DestroyDialog falloff_mouseRollout
)
)
on falloff_mouseRollout open do
(
if (selection[1] != undefined) and ((classof selection[1].baseobject) == Editable_Poly) do
(
edt1.Text = selection[1].Falloff as string
sld1.Value = selection[1].Falloff
)
)
)
on execute do
(
try(DestroyDialog falloff_mouseRollout) catch()
if (((classof selection[1].baseobject) == Editable_Poly)) do
(
createdialog falloff_mouseRollout style:#(#style_sysmenu) pos:(mouse.screenpos-[194,10])
)
)
)
Any way to make it so that the mouse immediately controls the slider that pops up, rather than having to click again on the popup slider?
<font class="small">Code:</font><hr /><pre>--Falloff Mouse Script
macroScript MouseFalloff
category:"MyTools"
(
try(DestroyDialog falloff_mouseRollout) catch()
try (
local sliderUpper
bbMax = $.max
bbMin = $.min
bbx = bbMax.x - bbMin.x
bby = bbMax.y - bbMin.y
bbz = bbMax.z - bbMin.z
if bbx >= bby then sliderUpper = bbx
if bby >= bbz then sliderUpper = bby
if bbz >= bby then sliderUpper = bbz
rollout falloff_mouseRollout "Falloff" width:200 height:24
(
slider sld1 "" pos:[51,1] width:160 height:10 range:[0 , sliderUpper, $.Falloff ] orient:#horizontal ticks:0
label edt1 "" pos:[2,3] width:40 height:16
on sld1 changed val do
(
selection[1].Falloff = sld1.Value
edt1.Text = selection[1].Falloff as string
)
on sld1 buttonup do
(
selection[1].useSoftSel = true
DestroyDialog falloff_mouseRollout
)
on falloff_mouseRollout open do
(
origMousePos = mouse.screenpos
sld1.Value = selection[1].Falloff
edt1.Text = selection[1].Falloff as string
)
)
createDialog falloff_mouseRollout pos:(mouse.screenpos-[194,10])
)
catch ()
)</pre><hr />
I'm sure it's possible in Maxscript, to actually have it increment the falloff value based on the offset of the mouse position from its original position in screenspace (either horizontally or vertically would be ideal). That way you don't have to pop up a slider which you then have to pull to a value ... you can just hold down a button while moving the mouse and let go of the button to "accept" the current falloff value. I'll maybe take a look into it over the weekend, I've been meaning to do some more maxscripting anyway.
My workaround solution for the moment is with an AutoHotkey script I wrote that enables me to bind the falloff to shift + the scroll wheel.
It works pretty well, the only downside is that I always have to execute the script when I reboot my computer. There's probably a way for me to tell it to run on startup, but I didn't look that much into AutoHotkey.
I've been testing it at home, and I'm really enjoying the ability to scale my falloff on the fly when adjusting mesh.
If anyone is interested in it, I can post it up. It's a really simple key remap.
What I do for my scripts is, I have a directory I work on my scripts in, and in my Scripts/Startup folder I have a .ms file that uses getFiles "C:\\foo\\*.ms" and .mcr, then fileIn's them. I also delete any .bmp files in ui\icons and then copy over any bmp files in that folder.
This way, when max starts, the artists automatically get the most recent version of my scripts and icons (as long as SVN is updated). Not as needed when you are just working on your own scripts, but having the script evaluated/executed automatically when you start Max, without having to put it in the startup folder, is good. If you want I can post the script Monday.
What I meant though was, the script I am using for key remapping is not a maxscript, but an AutoHotkey script
www.autohotkey.com
Which remaps Shift + MouseWheelDown to downArrow and Shift + MouseWheelUP to upArrow. Then in my scripts/startup folder I have my maxscript that binds the falloff controls to downArrow and upArrow.
The AutoHotkey script is a .ahk file that I let run in the background all the time, it's just that when I reboot I have to start it up again
1. Copy and paste this into a new Maxscript, run it, and bind a hotkey to this new function.
2. Press the hotkey then just move the mouse up or down to set the falloff value greater or smaller.
3. Left-click to accept the value, or right-click to cancel and reset the falloff value to the initial value.
<font class="small">Code:</font><hr /><pre>
macroscript falloffSlider
category:"MoP's Tools"
tooltip:"Soft Sel. Falloff Slider"
buttonText:"Falloff Slider"
(
try
(
local obj = selection[1]
local falloffValue
local origPos = mouse.pos.y
local origFalloff = obj.Falloff
local avgScale = ( obj.scale.x + obj.scale.y + obj.scale.z ) / 3
local maxFalloff
bbMax = $.max
bbMin = $.min
bbx = bbMax.x - bbMin.x
bby = bbMax.y - bbMin.y
bbz = bbMax.z - bbMin.z
if bbx >= bby and bbx >= bbz then maxFalloff = ( bbx * 2 ) / avgScale
if bby >= bbz and bby >= bbx then maxFalloff = ( bby * 2 ) / avgScale
if bbz >= bbx and bbz >= bby then maxFalloff = ( bbz * 2 ) / avgScale
if classOf obj == Editable_Poly and subobjectlevel != 0 and subobjectlevel != undefined then
if obj.useSoftSel == false then obj.useSoftSel = true
tool falloffSlider
(
on freeMove do
(
falloffValue = ( mouse.pos.y - origPos ) * ( maxFalloff / 500 )
obj.Falloff = ( origFalloff - falloffValue )
if obj.Falloff >= maxFalloff then obj.Falloff = maxFalloff
if obj.Falloff <= 0 then obj.Falloff = 0
)
on mousePoint click do #stop
on mouseAbort click do obj.Falloff = origFalloff
on stop do print obj.Falloff
)
startTool falloffSlider prompt:"Soft Selection Falloff Distance"
)
catch ()
)
</pre><hr />
Thanks to Professor420 for sharing his code. Useful starting point for some of this stuff!
I've added a more thorough (I think?) bounds-checker. It now takes the object's world scale into account too, since the falloff value in the EPoly isn't related to the world unit size, so just using the bounds of the object doesn't set a sensible range if the whole object has been scaled.
Now it will only become active if you're in sub-object mode of an Editable Poly. I figured it doesn't make much sense being able to change the value when you can't see the effect it's having, so it automatically turns on soft selection if it wasn't on already when you hit the hotkey.
At the moment it doesn't work on Editable Meshes (does anyone use those any more?) and it doesn't work on Edit Poly modifiers. If this is causing problems for people, I can quite easily build in support for those.
Lemme know if anyone likes it, or has suggestions for improvement.
-MoP
I still want to get it set up to only be active while a key is pressed and held down, but I'm not sure if that's even possible using Maxscript.
Just press the hotkey you assign to the script, then move the mouse up or down to shrink or grow the selection.
<font class="small">Code:</font><hr /><pre>
macroscript selectionSlider
category:"MoP's Tools"
tooltip:"Grow/Shrink Selection Slider"
buttonText:"Selection Slider"
(
try
(
local obj = selection[1]
local dist
local origPos = mouse.pos.y
local newPos = mouse.pos.y
local origVertSel = polyOp.getVertSelection obj
local newVertSel = origVertSel
local origEdgeSel = polyOp.getEdgeSelection obj
local newEdgeSel = origVertSel
local origFaceSel = polyOp.getFaceSelection obj
local newFaceSel = origVertSel
if classOf obj == Editable_Poly and subobjectlevel == 1 and obj.selectedVerts.count != 0 then (
tool selectionSlider (
on freeMove do (
dist = - ( mouse.pos.y - origPos )
if dist > 5 then (
obj.growSelection ()
origPos = mouse.pos.y
)
if dist < -5 then (
obj.shrinkSelection ()
origPos = mouse.pos.y
)
if obj.selectedVerts.count == 0 then (
obj.selectedVerts = newVertSel
) else (
newVertSel = polyOp.getVertSelection obj
)
if obj.selectedVerts.count == obj.verts.count then #stop
)
on mousePoint click do #stop
on mouseAbort click do obj.selectedVerts = origVertSel
)
)
if classOf obj == Editable_Poly and (subobjectlevel == 2 or subobjectlevel ==3) and obj.selectedEdges.count != 0 then (
tool selectionSlider (
on freeMove do (
dist = - ( mouse.pos.y - origPos )
if dist > 5 then (
obj.growSelection ()
origPos = mouse.pos.y
)
if dist < -5 then (
obj.shrinkSelection ()
origPos = mouse.pos.y
)
if obj.selectedEdges.count == 0 then (
obj.selectedEdges = newEdgeSel
) else (
newEdgeSel = polyOp.getEdgeSelection obj
)
if obj.selectedEdges.count == obj.edges.count then #stop
)
on mousePoint click do #stop
on mouseAbort click do obj.selectedEdges = origEdgeSel
)
)
if classOf obj == Editable_Poly and subobjectlevel == 4 and obj.selectedFaces.count != 0 then (
tool selectionSlider (
on freeMove do (
dist = - ( mouse.pos.y - origPos )
if dist > 5 then (
obj.growSelection ()
origPos = mouse.pos.y
)
if dist < -5 then (
obj.shrinkSelection ()
origPos = mouse.pos.y
)
if obj.selectedFaces.count == 0 then (
obj.selectedFaces = newFaceSel
) else (
newFaceSel = polyOp.getFaceSelection obj
)
if obj.selectedFaces.count == obj.faces.count then #stop
)
on mousePoint click do #stop
on mouseAbort click do obj.selectedFaces = origFaceSel
)
)
startTool selectionSlider prompt:"Growing/Shrinking Selection"
)
catch ()
)
</pre><hr />
Lemme know how you find it. It's a bit lengthy, but it will only activate if you're in Vertex, Edge, Border or Face mode of an Editable Poly. I figure there's no point trying to grow/shrink an element selection :P
It also won't activate if you don't have a selection.
I also updated the soft sel. falloff script to get rid of the annoying print every time the value changed.
http://www.martincoven.com/tools/SSFalloff_Manip.zip