Notifications
Clear all

[Closed] mxs autowelder help

Hello guys.

I am not such a great maxscripter. I was trying to create a maxscript to help me on the retopology process but with no success. Basically i wanted to create a auto-weld option with a spinner or slider for the threshold. As it is in Maya (image below)

Now, for instance, after i created a new polygon with the extend tool (from the ribbon -freeform) and then if i selected a vertex and trying to get closer to another vertex i want them to weld automatically (based on the distance threshold setting). It is possible ? Can you guys help me on this?

Thanks!

4 Replies

This should be enough for you to get started.
If you find a way to reduce the amount of distance checks it could also be used with highpoly meshes
btw Can someone show how to make it undoable?


fn OnGeometryChanged ev nodes = (
    
    if subObjectLevel != 1 or ev != #geometryChanged do return false
    
    local obj = getAnimByHandle nodes[1]
    local threshold = 5.0
    
    
    if classof obj == Editable_Poly do (
        
        local vsel = polyop.getVertSelection obj as array
        
        if vsel.Count == 0 do return false

        -- 
        sort vsel
        for j = vsel.count to 1 by -1 do (
            
            pt = polyop.getVert obj vsel[j]
        
            for i = polyop.getNumVerts obj to 1 by -1 where (d = distance pt (pt2 = polyop.getVert obj i)) <= threshold do (
                
                if i != vsel[j] do (
                    
                    format "welding.. % and %
" i vsel[j]
                    polyop.weldVerts obj vsel[j] i pt2
                    
                )
                
            )    
            
        )
        --
        
        
    ) 
    
    format "event: %
" ev
    format "%
" nodes
)

if isKindOf callback Value do (
    
    callback.Enabled = false
    callback = undefined
    gc light:true
    format "callback reset
" 
    
)
callback = NodeEventCallback mouseUp:true geometryChanged:OnGeometryChanged

Hey! Thanks.
I modified a little bit (added UI and undo). Recommended to not use a high value for the threshold. Otherwise the script will crash:)
Here is the code:


try(destroydialog autowelder)catch()
rollout autowelder ""
(
   checkbox cb01 "Auto-weld"   
   slider sld01 "" pos:(cb01.pos+[110,0]) type:#float ticks:0 width:80 range:[0.1,5,1]
   edittext txt01 "" pos:(cb01.pos +[68,0]) width:35 text:(sld01.value as string)
   
   on sld01 changed state do ( txt01.text = (sld01.value as string) )
   on txt01 changed state do ( sld01.value = (txt01.text as float) )
   on cb01 changed state do (   
   with undo on (
      if  $ != undefined then
      (
         fn OnGeometryChanged ev nodes = 
            (
               if subObjectLevel != 1 or ev != #geometryChanged or cb01.checked == false do return false
               local obj = getAnimByHandle nodes[1]
               local threshold = sld01.value
               if classof obj == Editable_Poly do (
                  local vsel = polyop.getVertSelection obj as array
                  if vsel.Count == 0 do return false
                  --
                  sort vsel
                  for j = vsel.count to 1 by -1 do (
                     pt = polyop.getVert obj vsel[j]
                     for i = polyop.getNumVerts obj to 1 by -1 where (d = distance pt (pt2 = polyop.getVert obj i)) <= threshold do 
                     ( if i != vsel[j] do (
                           format "welding.. % and %
" i vsel[j]
                           polyop.weldVerts obj vsel[j] i pt2
                        )
                     )
                  )
               )
               format "event: %
" ev
               format "%
" nodes
            )
         if isKindOf callback Value do 
            (
--                callback.Enabled = false -- what is this .Enable for?
               callback = undefined
               gc light:true
               format "callback reset
"
            )
      callback = NodeEventCallback mouseUp:true geometryChanged:OnGeometryChanged 
      )
   )
) --end cb01
)--end rollout
createdialog autowelder 200 50

It is better to create NodeEventCallback on rollout open and destroy it on rollout close. Now you destroy it and recreate each time cb01 is toggled.


try(destroydialog ::autowelder)catch()
rollout autowelder ""
(
    local callback
    checkbox cb01 "Auto-weld"
    slider sld01 "" pos:(cb01.pos+[110,0]) type:#float ticks:0 width:80 range:[0.1,5,1]
    edittext txt01 "" pos:(cb01.pos +[68,0]) width:35 text:(sld01.value as string)

    
    fn OnGeometryChanged ev nodes =
    (
       if subObjectLevel != 1 or ev != #geometryChanged or cb01.checked == false do return false
       local obj = getAnimByHandle nodes[1]
       local threshold = sld01.value
       
       if classof obj == Editable_Poly do (
        
            local vsel = polyop.getVertSelection obj as array

            if vsel.Count == 0 do return false

            sort vsel
            for j = vsel.count to 1 by -1 do (
                
                pt = polyop.getVert obj vsel[j]

                for i = polyop.getNumVerts obj to 1 by -1 where (d = distance pt (pt2 = polyop.getVert obj i)) <= threshold do (
                    
                    if i != vsel[j] do (
                        
                        format "welding.. % and %
" i vsel[j]
                        polyop.weldVerts obj vsel[j] i pt2
                        
                    )
                    
                )    
                
            )            
        
        )

    )
        
        
    on sld01 changed state do ( txt01.text = (sld01.value as string) )
    on txt01 changed state do ( sld01.value = (txt01.text as float) )
    
    on cb01 changed state do (

        if isProperty callback #Enabled then (
            
            callback.Enabled = state
            
        ) else cb01.checked = false

    )
    
    on autowelder open do (
            
        if isKindOf callback Value do
        (
            try (callback.Enabled = false ) catch()
            callback = undefined
            gc light:true
            
        )
        
        callback = NodeEventCallback enabled:false mouseUp:true geometryChanged:OnGeometryChanged
        
    )
    
    on autowelder close do (
        
        if isKindOf callback Value do
        (
            try (callback.Enabled = false ) catch()
            callback = undefined
            gc light:true
            format "callback destroyed
"
        )
        
    )
)
createdialog autowelder 200 50

Oh! Yap. It makes sense. Thank you very much for your help, Serejah!