zsSplineTools

Version: 
1.02
Date Updated: 
04/22/2012

Some tools to simplify spline-editing. Works only on Editable Splines without any modifiers.

- SELECT vertices by spline (add to current selection or replace it)
- ADD vertices within the specified distance to selection
- ALIGN position of selected vertices to min / average / max value in specified axes
- DISPLAY AND ADJUST position of selected vertices (to value or custom grid)
- SET TYPE of selected vertices (corner / smooth / bezier / bezier corner)

Will be extended occasionally. The initial release is what I wrote when I had to model a splinecage and realised that the Editable Splines are missing a lot of options...

Additional Info: 

v1.00: initial release
v1.01: bugfix: bezier-tangents are now moved correctly with each vertex
v1.02: code rewritten, performance increased

Please report any bugs you may encounter!

Version Requirement: 
written for 3ds Max 2010, should also work in older versions

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Derp Meowslurp's picture

it works! thanks for the help

it works!

thanks for the help :)

All your scriptz are belong to me!

Jan Köhl's picture

Just put an "Edit Spline"

Just put an "Edit Spline" Modifier on top and collapse the stack. Right-click-conversion doesn't work on "Line"-objects.

Derp Meowslurp's picture

doesn't want to work

in max 2014 x64;

im getting -- No "numSplines" function for undefined.

doesn't seem to be registering any verts i select. I made new spline, converted to editable spline. then try to use scrpt.

thanks

All your scriptz are belong to me!

Jan Köhl's picture

You're right - it seems that

You're right - it seems that you can't edit posts with a reply...
So don't worry about it. ;-)

crystal3d's picture

so sorry but , i can not edit this post

maybe because it was replied? i recon having and edit button next to reply but double checked and no edit button...:(

sorry to cause such a mess, will do what i can but a mod can be help me with this.

Jan Köhl's picture

Drag and drop...

Just create a new Toolbar, open the original script in the editor, select all and drag-and-drop it onto the new toolbar.
And please remove the code from your post... ;-)

crystal3d's picture

Hello, i like this script but

it only runs through"run" command, i tired to convert it to a macroscript type where i can assign short cut or toolbar but it gives syntax error

May you correct this please?

macroScript SplineTools
category:"#Scripts"
tooltip:"SplineTools"
buttontext:"Splinetools"

-- helper functions
fn round num =
(
if zsSplineToolsFloater != undefined do closeRolloutFloater zsSplineToolsFloater
zsSplineToolsFloater = newRolloutFloater "zsSplineTools" 160 515

if floor(num + 0.5) > floor num then return ceil num else return floor num
)
fn roundToIncrement num inc =
(
(round (num/inc))* inc
)

-- struct definitions
struct vert (obj, spl, num, pos=[0,0,0], invec=[0,0,0], outvec=[0,0,0])
struct seg (obj, spl, num)
struct zsSplineSelection
(
private
selSplines = #(), -- selected splines per object as struct subspline
selSegs = #(), -- selected segments per spline as struct seg

public
selVerts = #(),
-- min, center and max vertex positions
minVert = [0, 0, 0],
midVert = [0, 0, 0],
maxVert = [0, 0, 0],

-- create selectionset from selection (always call first!)
-- returns true if exactly one Editable Spline is selected
fn make =
(
valid = false
selObject = undefined
if $ != undefined then
(
for obj in $ do if ClassOf obj != SplineShape or obj.modifiers.count > 0 do deselect obj
if selection.count > 1 then (messageBox "Multiple Objects selected!") else
(
selSegs = #()
selVerts = #()
posVerts = #(#(), #(), #())
for i = 1 to numSplines $ do
(
for s in (getSegSelection $ i) do append selSegs (seg $ i s)
for v in (getKnotSelection $ i) do
(
current = getKnotPoint $ i v
append selVerts (vert $ i v current (getInVec $ i v) (getOutVec $ i v))
append posVerts[1] current.x
append posVerts[2] current.y
append posVerts[3] current.z
)
)
if posVerts[1].count > 0 do
(
minVert = [(amin posVerts[1]), (amin posVerts[2]), (amin posVerts[3])]
maxVert = [(amax posVerts[1]), (amax posVerts[2]), (amax posVerts[3])]
midVert = [((minVert.x + maxVert.x) / 2), ((minVert.y + maxVert.y) / 2), ((minVert.z + maxVert.z) / 2)]
)
posVerts = undefined
valid = true
)
)
else messageBox "No valid selection!"
valid
),

-- move selected vertices
fn moveVerts axis val =
(
for v in selVerts do
(
newpos = [v.pos.x, v.pos.y, v.pos.z]
case axis of
(
"x": newpos.x = val
"y": newpos.y = val
"z": newpos.z = val
"grid": newpos = [(roundToIncrement v.pos.x val), (roundToIncrement v.pos.y val), (roundToIncrement v.pos.z val)]
)
setKnotPoint v.obj v.spl v.num newpos
setInVec v.obj v.spl v.num (v.invec + newpos - v.pos)
setOutVec v.obj v.spl v.num (v.outvec + newpos - v.pos)
newpos = undefined
)
updateShape $
),

fn setVertexType type =
(
for v in selVerts do case type of
(
"corner": setKnotType v.obj v.spl v.num #corner
"smooth": setKnotType v.obj v.spl v.num #smooth
"bezier": setKnotType v.obj v.spl v.num #bezier
"bezierCorner": setKnotType v.obj v.spl v.num #bezierCorner
)
updateShape $
),

fn selectVertexBySpline add =
(
if add == false do for i = 1 to numSplines $ do setKnotSelection $ i #()
for s in (getSplineSelection $) do setKnotSelection $ s (for i = 1 to numKnots $ s collect i)
subObjectLevel = 1
),

fn growVertexSelection threshold =
(
for i = 1 to numSplines $ do
(
selectedVerts = for v in selVerts where v.spl == i collect v.num
unselectedVerts = for n = 1 to numKnots $ i where findItem selectedVerts n == 0 collect n
for n in unselectedVerts do
(
check = getKnotPoint $ i n
for v in selVerts do
(
if (check.x + threshold >= v.pos.x) and (check.x - threshold <= v.pos.x) do
(
if (check.y + threshold >= v.pos.y) and (check.y - threshold <= v.pos.y) do
(
if (check.z + threshold >= v.pos.z) and (check.z - threshold <= v.pos.z) do append selectedVerts n
)
)
)
)
setKnotSelection $ i selectedVerts
selectedVerts = unselectedVerts = undefined
)
subObjectLevel = 1
)
)

selSpline = zsSplineSelection()

rollout selectVertices "Select Vertices"
(
-- layout (Select Vertices)
label lab_selVerts "0 Selected"
group "Select By Spline"
(
button but_replaceSelection "Replace" width:60 height:20 align:#left across:2 tooltip:"Replace current selection"
button but_addSelection "Add" width:60 height:20 align:#left tooltip:"Add to current selection"
)
group "Area Selection"
(
button but_areaSelection "Grow" width:60 height:20 align:#left across:2
spinner spn_setThreshold "" type:#worldunits align:#left width:59 scale:0.01 range:[0,100,0.01] offset:[0,2]
)

fn displaySelectedVerts =
(
if selSpline.make() do lab_selVerts.text = (selSpLine.selVerts.count as string) + " Selected"
)

-- event handlers (Select Vertices)

on but_addSelection pressed do if selSpline.make() do if selSpline.make() do
(
selSpline.selectVertexBySpline true
displaySelectedVerts()
)
on but_replaceSelection pressed do if selSpline.make() do if selSpline.make() do
(
selSpline.selectVertexBySpline false
displaySelectedVerts()
)
on but_areaSelection pressed do if selSpline.make() do
(
selSpline.growVertexSelection spn_setThreshold.value
displaySelectedVerts()
)
)

rollout modifyVertices "Modify Vertices"
(
-- layout (Modify Vertices)

group "Align"
(
label lab_vertsX "X: " align:#left offset:[0,2] across:4
button but_vertsXmin "<" width:30 height:20 align:#left tooltip:"Align to X min"
button but_vertsXmid "|" width:30 height:20 align:#left tooltip:"Align to X center"
button but_vertsXmax ">" width:30 height:20 align:#left tooltip:"Align to X max"
label lab_vertsY "Y: " align:#left offset:[0,2] across:4
button but_vertsYmin "<" width:30 height:20 align:#left tooltip:"Align to Y min"
button but_vertsYmid "|" width:30 height:20 align:#left tooltip:"Align to Y center"
button but_vertsYmax ">" width:30 height:20 align:#left tooltip:"Align to Y max"
label lab_vertsZ "Z: " align:#left offset:[0,2] across:4
button but_vertsZmin "<" width:30 height:20 align:#left tooltip:"Align to Z min"
button but_vertsZmid "|" width:30 height:20 align:#left tooltip:"Align to Z center"
button but_vertsZmax ">" width:30 height:20 align:#left tooltip:"Align to Z max"
)
group "Position"
(
button but_getCurrent "Get Current Position" width:122 height:20
button but_setX "Set X" width:60 height:20 align:#left across:2
spinner spn_setX "" width:60 offset:[0,2] align:#left range:[-1000000,1000000,0] type:#worldunits scale:0.01
button but_setY "Set Y" width:60 height:20 align:#left across:2
spinner spn_setY "" width:60 offset:[0,2] align:#left range:[-100000,100000,0] type:#worldunits scale:0.01
button but_setZ "Set Z" width:60 height:20 align:#left across:2
spinner spn_setZ "" width:60 offset:[0,2] align:#left range:[-1000000,1000000,0] type:#worldunits scale:0.01
button but_setGrid "To Grid" width:60 height:20 align:#left across:2
spinner spn_setGrid "" width:60 offset:[0,2] align:#left range:[0,100,0.01] type:#worldunits scale:0.01
)
group "Set Vertex Type"
(
button but_makeCorner "Corner" width:60 height:20 align:#left across:2
button but_makeSmooth "Smooth" width:60 height:20 align:#left
button but_makeBezier "Bezier" width:60 height:20 align:#left across:2
button but_makeBezierCorner "Bez.Corner" width:60 height:20 align:#left
)

-- function definitions (Modify Vertices)

fn displayCurrentPosition =
(
if selSpline.make() do
(
spn_setX.value = selSpline.midVert.x
spn_setY.value = selSpline.midVert.y
spn_setZ.value = selSpline.midVert.z
)
)

-- event handlers (Modify Vertices)

on but_vertsXmin pressed do if selSpline.make() do selSpline.moveVerts "x" selSpline.minVert.x
on but_vertsXmid pressed do if selSpline.make() do selSpline.moveVerts "x" selSpline.midVert.x
on but_vertsXmax pressed do if selSpline.make() do selSpline.moveVerts "x" selSpline.maxVert.x
on but_vertsYmin pressed do if selSpline.make() do selSpline.moveVerts "y" selSpline.minVert.y
on but_vertsYmid pressed do if selSpline.make() do selSpline.moveVerts "y" selSpline.midVert.y
on but_vertsYmax pressed do if selSpline.make() do selSpline.moveVerts "y" selSpline.maxVert.y
on but_vertsZmin pressed do if selSpline.make() do selSpline.moveVerts "z" selSpline.minVert.z
on but_vertsZmid pressed do if selSpline.make() do selSpline.moveVerts "z" selSpline.midVert.z
on but_vertsZmax pressed do if selSpline.make() do selSpline.moveVerts "z" selSpline.maxVert.z
on but_getCurrent pressed do displayCurrentPosition()
on but_setX pressed do if selSpline.make() do selSpline.moveVerts "x" spn_setX.value
on but_setY pressed do if selSpline.make() do selSpline.moveVerts "y" spn_setY.value
on but_setZ pressed do if selSpline.make() do selSpline.moveVerts "z" spn_setZ.value
on but_setGrid pressed do if selSpline.make() do
(
selSpline.moveVerts "grid" spn_setGrid.value
displayCurrentPosition()
)

on but_makeCorner pressed do if selSpLine.make() do selSpline.setVertexType "corner"
on but_makeSmooth pressed do if selSpLine.make() do selSpline.setVertexType "smooth"
on but_makeBezier pressed do if selSpLine.make() do selSpline.setVertexType "bezier"
on but_makeBezierCorner pressed do if selSpLine.make() do selSpline.setVertexType "bezierCorner"
)

addRollout selectVertices zsSplineToolsFloater
addRollout modifyVertices zsSplineToolsFloater

Jan Köhl's picture

Hi, are there any error

Hi, are there any error messages in the MAXScript Listener?
What happens when you execute the script?
Since I don't have 3dsmax 2009, I can not try it myself.

edit: Please try this:

- open script in Editor
- delete keywords "private" (line 27) and "public" (line 31)
- save script and try again

I just had a look at the changes of MAXScript in v2010 and found out that private/public members in structure definitions were a new feature...

mb3d's picture

Not Work in 3dsmax2009

Hi Jan, i use 3dsmax2009, how you say " written for 3ds Max 2010, should also work in older versions ", i try, but dont work, can you test? and tellme if there are a solution, thanks for your script, and for share, Best Regards.

Jan Köhl's picture

Thanks for your comment.

Thanks for your comment. Modifier support would be great, but it seems to be a limitation of maxscript, that you can only access the base object on subObjectLevel. But I will try to find a solution...

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.