[Closed] Weld vertices in multiple splines at once
Hello,
I have a file with lots of splines (hundreds) to which I need to apply weld command as many vertices are not connected.
So I’m trying to automate that through a script. I found on the forum a base code to do that and tried to wrap it into a loop to cycle through all the splines in my selection :
for s in selection do
(
select s
subobjectLevel=1
max select all
splineOps.weld $
updateshape $
)
The problem is that it does not cycle through all the splines but only performs the operation on one and stops.
I think the problem might be that once I enter in subobjectlevel I should exit it no ?
Any help is welcome of course.
Thanks
Look at the code. You want to cycle through the selection set. Then the first thing you say is: select s. So now you’ve replaced the selection set with just the first object in the selection. So it makes sense that it only works on the first object. After the first time through the loop, it’s the only thing selected and the loop ends.
You need to create a copy of the selection set before you start manipulating it. Something like:
for s in selection as array do
(
select s
subobjectLevel=1
max select all
splineOps.weld $
subobjectLevel=0 -- you need this, otherwise everything stays at 1
updateshape $
)
Now s steps through the selection set as it was at the start, ignoring the changes you make. Also note that you should close the subobject level.
focomoso is correct (as I’m sure he knew he was), it is good practice to first make a “snapshot” of any of max’s collection sets (objects, geometry, lights, cameras, helpers, systems, spacewarps and selection) before you try and do any work against them. This allows you to work on the result in isolation without been adversly affected by changes to the original objectset.
Shane
Thanks a lot for your help focomoso.
With your suggestion, the script seems to do what it should as it runs for a few seconds while it used to run instantaneously with my lame version.
But the problem is that when it finishes I end up with only the last shape of the set being welded.
I tried to run it on a very simple test scene with only 5 rectangles with one corner vertex broken and it doesn’t work neither, well it works on the last one only.
Things may have changed since I last tried something like this a few years ago, but at the time there was a problem with welding spline verts in a loop, it simply didn’t work and was apparently a limitation of the ancient spline code.
Really !? . So I am not lucky at all : I almost never do any scripting (and you might have guessed that throgh my poor code hehe) and now that I want to script something it happens to be precisely a thing that does not work because of a limitation :shrug:
I tried this for max8 and haven’t looked at it since, but a few pointers:
The AVG Extension has a better spline weld routine that lets you specify a threshold.
Prior to max9 more than a few thousand verts selected and welded really slows everything down so try to reduce the count before doing the weld – I went through the splines and only selected the end verts (the middle ones don’t need welding) on open splines (exclude ones that are closed as they can’t weld to anything anyway).
I also at the time did a count routine that split the operation into batches of 500 verts so that I could see if max had crashed or was just being really slow.
hope that helps
Alex
The problem is in the splineOps. The function only works if the object is selected and the modify panel is on the right modifier. So in the loop you would need to call a redraw for it to work. But from what I know maxscript doesn’t let you do a complete redraw or something… looks like splineOps is too slow too catch up with max for loops or something… don’t know why exactly it doesn’t work… But I have a workaround:
global objs
global theTimer
fn splineWeld =
(
o = objs[1]
if o == undefined then
(
theTimer.stop()
) else (
modpanel.setCurrentObject o.baseObject ui:true
subobjectLevel = 1
max select all
splineOps.weld o
updateshape o
subobjectLevel = 0
deleteItem objs 1
)
)
objs = for o in selection where iskindof o line collect o
/* WORKS */
theTimer = dotNetObject "System.Windows.Forms.Timer"
dotnet.addEventHandler theTimer "tick" SplineWeld
theTimer.interval = 100
theTimer.start()
/* DOESN'T WORK */
--for o in objs do splineWeld()
Basicly it’s an dotnet Timer function which calls the weld function. This seems to update max innerworkings as I think the “dotnet scope” is not the same as the maxscript scope… somehow this way updates max the right way making it accept the splineOps function…
Anyone who can explain better please do!
Probably the code can be made better too… feel free!
-Johan
Or you could do what Alex said:
for o in selection where iskindof o line do weldSpline o 0.1
Where 0.1 is the treshold… weldspline is default in max2008, previous version you would have to get the AVG extension from maxplugins.
Thanx Alex… ohwell, still the timer function could be usefull for other Ops structs…
-Johan
Thanks a lot JHN for taking the time to write down that wonderful script though I must admit I didn’t understand neither the problem neither the solution you brought to it
Anyways, I first tried the script on my test file with just a few simple splines and it worked like a charm, cycling through all the shapes and welding them. But when I tried to run it on my project it just does nothing, and there is no error message. Very strange.
But it’s ok. The deadline is approaching and I have to finish that thing. So I just assigned the part of script that welds a spline to a hotkey and then welded them all one by one. It took me about 20mn :rolleyes:
I’ll look deeper into this as soon as I have a little time because I’m sure I’ll have to face such situation again in future projects.
Again, thanks to all of you for your kind help.