[Closed] getPropNames for subobject selections
hi all
maxscript newbie warning!
i need to establish which control points are selected in a ffd modifier. Is this possible? do i use something like
getPropNames $[color=green][font=‘Courier New’]sphere01[/color].‘FFD(box) 4x4x4’ #dynamicOnly[/font]
which produces a list of the animated control points.
but instead of dynamic only is there a flag to show selected only?
cheers
paul
There’s no way to check whether a control point is selected or not. Also, the points can only be accessed/changed (position only) after they have been animated manually so that makes it even less useful I’m afraid
Martijn
Although ‘position only’ is correct, you can certainly animate the control points programmatically.
For the modifier variants:
animateVertex <modifier> <#all|index>
For the spacewarp variants:
http://forums.cgsociety.org/showthread.php?t=720508
( That thread also contains some useful hints for alternatives to the FFD )
here’s a function to get the currently selected control points; not sure what you want to do with it, but anyway…
-- usage:
-- <array>getSelectedCPs <ffdModifier>
-- output array contains selected control points as <int>index for each CP
fn getSelectedCPs FFDmod = (
-- defines
local WM_SETFOCUS = 0x007
-- back up some stuff we'll be changing
local oldCommandMode = toolmode.commandmode
local cmdPanelMode = getCommandPanelTaskMode()
local modPanelObj = modpanel.getCurrentObject()
local oldSubObjectLevel = subObjectLevel
local oldModEnabledInViews = FFDmod.enabledInViews
-- disable the modifier in viewports to speed up some calculations
FFDmod.enabledInViews = false
-- let's collect all the control points' current positions
local curPositions = for prop in (getPropNames FFDmod) collect (
propValue = getProperty FFDmod prop
if (classOf propValue == point3) then ( propValue )
else ( dontcollect )
)
-- go into modify mode
setCommandPanelTaskMode #modify
-- select the modifier
modpanel.setCurrentObject FFDmod
-- go to the control point sub-object level
subObjectLevel = 1
-- change to move mode
toolmode.commandmode = #move
-- open the transform type-in dialog
max tti
-- find the tti dialog
local desktopHWND = windows.getDesktopHWND()
local desktopChildren = windows.getChildrenHWND desktopHWND
local tti
for child in desktopChildren do (
if (child[5] == "Move Transform Type-In") then (
tti = child
exit
)
)
if (tti == undefined) then ( return false )
-- get the tti's handle
local ttiHWND = tti[1]
-- get its children
local ttiChildren = windows.getChildrenHWND ttiHWND
-- set focus to the X Offset custedit control
UIAccessor.sendMessage ttiChildren[10][1] WM_SETFOCUS 0 0
-- change its value via the proper edit control - let's just offset by 1.0 unit
UIAccessor.setWindowText ttiChildren[12][1] "1.0"
-- now set focus to the Y offset custedit control
UIAccessor.sendMessage ttiChildren[13][1] WM_SETFOCUS 0 0
-- now, let's collect the new positions.
local newPositions = for prop in (getPropNames FFDmod) collect (
propValue = getProperty FFDmod prop
if (classOf propValue == point3) then ( propValue )
else ( dontcollect )
)
-- set focus to the X Offset custedit control
UIAccessor.sendMessage ttiChildren[10][1] WM_SETFOCUS 0 0
-- change its value via the proper edit control - move the control points back 1.0 unit
UIAccessor.setWindowText ttiChildren[12][1] "-1.0"
-- now set focus to the Y offset custedit control
UIAccessor.sendMessage ttiChildren[13][1] WM_SETFOCUS 0 0
-- close that tti dialog
UIAccessor.CloseDialog ttiHWND
-- now let's figure out what the difference between the two arrays is
local selectedCPs = for i = 1 to curPositions.count collect (
if (curPositions[i] != newPositions[i]) then ( i )
else ( dontcollect )
)
-- restore stuff
FFDmod.enabledInViews = oldModEnabledInViews
setCommandPanelTaskMode cmdPanelMode
if (modPanelObj != undefined) then (
modpanel.setCurrentObject modPanelObj
)
if (oldSubObjectLevel != undefined) then (
subObjectLevel = oldSubObjectLevel
)
toolmode.commandmode = oldCommandMode
selectedCPs
)
Note that this uses some UI interaction methods (opening a dialog, changing a spinner value) that will briefly make the screen flicker.
In addition, due to the UI interaction, focus changes to different controls. If you are calling this from a scripted UI, make sure you use ‘setFocus <control>’ after calling the function to return focus to one of the controls in your own UI.
The script above was written for 3ds Max 2009; I’m hoping none of the spinner indices are different in older versions of 3ds Max.
If you run into any problems, just let me know.
Edit: Forgot to mention – as it has to be able to access the control points to determine whether they moved, the control points -must- be made accessible via ‘animateVertex <ffdmod> <#all|index>’ at some point before calling the function.
Or, open 3dsmax.exe in a hex editor, go to byte offset 4815162 and change the value to 42
err ok not sure i get the in jokes there…scripters humour hey!
zeeboxx thats fantastic i’ll try it thanks…geez that seems like a lot of script for something i thought would be simple…
what i want to do is offset various groups of control points in time from one another
…anyways…so how do i call the function. When i evaluate it it echos back getSelectedCPs () in the window but thats it.
cheers
paul
The basic usage example is:
animateVertex FFD_modifier #all -- to make sure all points can be accessed
selectedControlPoints = getSelectedCPs FFD_modifier
So if the modifier is the top-most modifier on your currently selected object:
animateVertex $.modifiers[1] #all -- to make sure all points can be accessed
selectedControlPoints = getSelectedCPs $.modifiers[1]
The ‘selectedControlPoints’ variable at that points contains the indices of the selected control points in an array, e.g.
#(1,2,3,4,7,8,9)
So if you want to move those control points…
for index in selectedControlPoints do (
-- $.modifiers[1][3] = Control Points master track
$.modifiers[1][3][index] = [x,y,z] --position
)
Note that control points are the in the FFD modifier’s local coordinate space – have a search through this forum for a few functions to get/set the control point positions in world coordinate space if that’s what you’d need
thanks Zeebox
this all makes sense thanks to your explanations.
much appreciated.
paul