Home Technical Talk

Selecting MaterialIDs MaxScript

NZA
NZA
polycounter lvl 9
Offline / Send Message
NZA polycounter lvl 9
Hello,

I'm quite new to Maxscript and I've been trying to write a simple function that will return true or false if any faces have a specified MaterialID applied to them. I got it working but only by collapsing the object into and editable_poly or editable_mesh. Ideally I would like to be able to add a modifer to the top of the stack and use that to perform the check and then remove it before the user is any the wiser. Heres what I have so far;
fn CheckForMaterialID obj index = 
(
    PolyList = #()
    
    max modify mode
    MatChkMod_01 = Edit_Poly()
    MatChkMod_01.name = "MaterialIDCheck"
    addModifier obj MatChkMod_01
    
    subObjectLevel = 4
    MatChkMod_01.selectByMaterialID = index
    MatChkMod_01.selectByMaterialClear = true
    MatChkMod_01.ButtonOp #SelectByMaterial 
    
-- the script gets this far - successfully selects the polys but 
-- then I'm unable to do a count of them

    PolyList = polyop.getFaceSelection obj
    print PolyList.count
     
    deleteModifier obj MatChkMod_01   
)
Is there any other way (cleaner or faster) of doing this?

Thanks :thumbup:

Replies

  • [PB]Snoelk
    Offline / Send Message
    [PB]Snoelk polycounter lvl 7
    maybe this helps
    fn CheckForMaterialID obj index = 
    (
        PolyList = #()
        InUse = False
        
        MatChkMod_01 = Edit_Poly()
        MatChkMod_01.name = "MaterialIDCheck"
        
        addModifier obj MatChkMod_01
        
        obj.EditablePoly.selectByMaterial index clearCurrentSelection:true
        
        PolyList = (obj.EditablePoly.GetSelection #Face) as array
        
        if PolyList.count > 0 do
             (
                InUse = True
             )
             
        deleteModifier obj MatChkMod_01   
    
        return InUse
    )
    
    obj = selection[1]
    index = 1
    
    if (CheckForMaterialID obj index) then
        (
            print ("Material ID "+index as string +" is in use on Entity "+obj.name as string)
        )
    else
        (
            print ("Material ID "+index as string +" is NOT in use on Entity "+obj.name as string)
        )
    
  • NZA
    Offline / Send Message
    NZA polycounter lvl 9
    Thanks for the post back Snoelk I meant to update this thread to say that I solved the issue I was having. There were a couple of things wrong with my script:
    • When you give a number to the Edit_Poly.selectByMaterialID property it has to be one less than that of the MaterialID you really want. So if your after MatID 2 then you should give the function 3.
    • I was trying to perform a 'count' on a bitarray which didn't yield the result I was expecting. But by converting it to a standard array (which I can see you did in your script) the 'count' function returns the number of faces selected - which is what I wanted.
    Thanks for the help and I'm going to try implementing my script using the EditablePoly functions rather than the EditPoly ones like you have in your snippet of script. :-)
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    If you want to get a "count" of values set in a BitArray without converting to an Array, you can just use:
    <bitarray>.numberSet
    
    Since <bitarray>.count will return the number of elements in the BitArray regardless of whether they're set on or off.
  • NZA
    Offline / Send Message
    NZA polycounter lvl 9
    Cheers for the tip MOP.

    I'll have to learn more about bitarrays in MaxScript and how to use them.
  • [PB]Snoelk
    Offline / Send Message
    [PB]Snoelk polycounter lvl 7
    bitarray are pretty cool for some nice operation. so you dont have to run over a set of faces, edges or vertices.

    here a nice example to get a outline of a current faceselection
    works pretty fast :)
    function FaceSelection_Outline objtosel =
        (
            local varfacelist1 = #{}
            local varfacelist2 = #{}
            local varedgearray1 = #{}
            local varedgearray2 = #{}
            local VarTheEdge = #{}
            
            --get the current face selection as bitarray
            varfacelist1 = polyOp.getFaceSelection objtosel
    
             --set face selection from inverted bitarray    
            polyOp.SetFaceSelection objtosel -(varfacelist1)
    
            --get the inverted face selection as bitarray
            varfacelist2 = polyOp.getFaceSelection objtosel 
            
            --get the all edges from the bitarray selections
            varedgearray1 = polyOp.getEdgesUsingFace objtosel varfacelist1
            varedgearray2 = polyOp.getEdgesUsingFace objtosel varfacelist2
            
            --multiply both edge bitarray to get the outline edges between them
            VarTheEdge = varedgearray1 * varedgearray2 
            
            subobjectlevel=2
            
             -- select the edge 
            polyOp.SetEdgeSelection objtosel VarTheEdge    
            
            local varfacelist1 = #{}
            local varfacelist2 = #{}
            local varedgearray1 = #{}
            local varedgearray2 = #{}
            local VarTheEdge = #{}
            
            gc()        
        )
    
    
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    Cool stuff, Snoelk.

    Out of interest, why do you zero the local bitArrays at the end of the script? Surely since they're local they'll be discarded once that function ends?
    Also any reason why you declare the bitarrays explicitly empty beforehand, instead of just doing:
    local varfacelist1 = polyOp.getFaceSelection objtosel
    

    Cheers :)
  • [PB]Snoelk
    Offline / Send Message
    [PB]Snoelk polycounter lvl 7
    i initialising those arays empty and clearing them at end just in case. maxscripts sometimes doing crazy stuff with variables. :poly122:
    got a bug today with array that where not initialized at the beginning. they just memory garbage from an other variable that wasnt cleared at end.
Sign In or Register to comment.