Home Technical Talk

maxscript - DivideEdge problem

polycount lvl 666
Offline / Send Message
PolyHertz polycount lvl 666
Im trying to add the ability to add a vert to the middle of an edge while in an Edit_Poly modifier, but it's not working out so well. Using the DivideEdge function it'll split the edge, but the new vert wont be selectable. This is what I'm doing after selecting the edge:

varEdjIndex = ((($.Edit_Poly.getSelection #Edge) as array)[1])
$.modifiers[#Edit_Poly].DivideEdge varEdjIndex 0.5

Is this a glitch or am I doing something wrong?

Replies

  • SyncViewS
    Options
    Offline / Send Message
    SyncViewS polycounter lvl 13
    Hi Greg, because of the nature of 3ds Max Edit Poly Modifier you need to commit the operation before it actually "takes effect". If you need to insert a single vertex, do it then commit, if you need to insert a bunch of them, insert them all, then commit.
    -- In your case:
    $.modifiers[#Edit_Poly].commit()
    

    As a general suggestion do not rely on Modifiers name with the syntax modifiers[#name], because even if it's a remote case, the user can change it, or there can be more modifiers with the same name. Getting them by index modifiers[1] is a bit better but still unsafe, because stack order can change. Better to verify modifier class before storing it in a variable that is tied to such modifier, something like: if (classOf modifiers[1] == Edit_Poly) do ( myModVar = modifiers[1] ), assuming you know modifiers[1] is the one you're looking for. Otherwise you can use: modPanel.getCurrentObject() to get currently active modifier then test its class.
  • PolyHertz
    Options
    Offline / Send Message
    PolyHertz polycount lvl 666
    Thanks for the help Sync :)

    How would you go about getting a modifiers actual name then? Using modPanel.getCurrentObject() it'd return the modifier class:name, and with classOf you'd obviously get just the class , but what about getting just the name, as I assume that's what you're saying would be the most safe/correct method? Or would it be possible to see how you'd change this to be more correct / safe?:
    if (classOf (modPanel.getCurrentObject()) == Edit_Poly) then
    (
            if ((subObjectLevel == 2) and (((($.Edit_Poly.getSelection #Edge) as array).count) == 1)) then
                    (
                    varEdjIndex = ((($.Edit_Poly.getSelection #Edge) as array)[1])
                    $.modifiers[#Edit_Poly].DivideEdge varEdjIndex 0.5
                    $.modifiers[#Edit_Poly].commit()
                    subObjectLevel = 1
                    )
    )
    
  • SyncViewS
    Options
    Offline / Send Message
    SyncViewS polycounter lvl 13
    Hi Greg, I want to say that there is not THE way to write code. Following is only how I'd write it to be safe. There are a bunch rules to keep in mind and a lot of case testing. For instance: never use the direct $ to retrieve a selection. That's so generic it can lead to many errors. Same goes for "Selection" collection.

    Store its single elements in a variable like:
    local theNode = Selection[1]

    Or if you need the whole array make a static copy like:
    local theSelArray = Selection as Array

    Here is the code the way I'd write it, if meant to work on the currently active Edit Poly Modifier.
    (
        -- make sure the script works only when a single node is selected
        local theNode = undefined
        if (Selection.count == 1) do
            theNode = Selection[1]
    
        if (theNode != undefined) do
        (
            -- make sure Modifier Panel is in Modify mode
            -- (required by many Edit Poly Mod commands)
            -- not really needed in this case because subObjectLevel MUST be == 2
            if (getCommandPanelTaskMode() != #modify) do
                setCommandPanelTaskMode #modify
    
            -- store Current Edit Object (Modifier Stack active element) in a variable
            local theEditObj = modPanel.getCurrentObject()
    
            if ((classOf theEditObj) == Edit_Poly) do
            (
                local baEdgeSelection = theEditObj.getSelection #Edge node:theNode
    
                -- baEdgeSelection is a BitArray, you can get the number of elements set
                -- with .numberSet and query if it is empty with .isEmpty
                -- latter is faster than testing .numberSet == 0
                if ( (subObjectLevel == 2) and (baEdgeSelection.numberSet == 1) ) do
                (
                    theEditObj.divideEdge (baEdgeSelection as Array)[1] 0.5
                    theEditObj.commit()
    
                    subObjectLevel = 1
                )
                /*
                -- if you want to make the script work on one or more selected edges
                -- loop through them (substitute previous if..do block)
                if ( (subObjectLevel == 2) and (baEdgeSelection.isEmpty == false) ) do
                (
                    for iEdge in baEdgeSelection do
                    (
                        theEditObj.divideEdge iEdge 0.5
                    )
    
                    theEditObj.commit()
    
                    subObjectLevel = 1
                )
                */
            )
        )
    )
    
Sign In or Register to comment.