Home Technical Talk

[MaxScript] - Remove duplicate materials from array

polycounter lvl 13
Offline / Send Message
csprance polycounter lvl 13
(
	
	
	function uniquifyArray arr = 
	(
		curnum = arr.count
		for i in arr do
		(
			if (findItem arr i > 0 ) and ( finditem arr i == curnum ) do
			(
				deleteItem arr (findItem arr i)
			)
			curnum -= 1
		)
		return arr
	)
	tm1 = Standardmaterial name:"Test1"
	tm2 = Standardmaterial name:"Test2"
	pm1 = Standardmaterial name:"Proxy1"
	pm2 = Standardmaterial name:"Proxy2"
	pm3 = Standardmaterial name:"Proxy1"
	pm4 = Standardmaterial name:"Proxy1"

	-- if you uncomment pm4 the whole script fails. How can I prevent this from happening?
	mlist = #(
				 tm1
				,tm2
				,pm1
				,pm2
				,pm3
				/*,pm4*/
			)
	uniquifyArray mlist
        actionMan.executeAction 0 "50048"  -- Tools: Material Editor Toggle
	mm = MultiMaterial numsubs:(mlist.count)
	meditMaterials[1] = mm
	count = 1 

	for x in mlist do 
	(
		meditMaterials[1].materialList[count] = x
		count += 1
	)
)

This doesn't seem to be working if there are more then two of the same materials. Why?

If you run the above code you'll see that if Proxy1 is in there twice it runs just fine and everything is happy.

However... if you uncomment pm4 from the mlist array everything just goes to hell.

Can someone give me a bit of insight on why this is happening and how I can prevent it from making my uniquifyArray function stop working? Thank you!

Replies

  • monster
    Options
    Offline / Send Message
    monster polycounter
    There are two issues here.

    1. I'll be honest I'm not sure what your uniqueifyArray function is doing. However, there is already a command to make a unique array so we don't need it.
    makeuniquearray <array>
    

    2. The other issue is that just because 2 materials share a name doesn't make them the same. The following command will return false.
    Standardmaterial name:"Proxy1" == Standardmaterial name:"Proxy1"
    

    The findItem command basically does a == comparison through the whole array. The == comparison looks for variables that reference the same memory. For example the following would return false as well.
    a = #(5)
    b = #(5)
    a == b
    
    [COLOR="green"][I]false[/I][/COLOR]
    

    The proper way to fix your code would be to test for names against the array as you create the array.
  • Swordslayer
    Options
    Offline / Send Message
    Swordslayer interpolator
    Your function will delete the middle item of the list (which in your case also happens to be one of the duplicate entries). To make it work, you can for example try something like this:

    (
        function uniquifyArray arr = 
        (
            local matNames = #()
            for m in arr where
            (
                local found = findItem matNames m.name > 0
                if not found do append matNames m.name
                not found
            ) collect m
        )
    
        tm1 = StandardMaterial name:"Test1"
        tm2 = StandardMaterial name:"Test2"
        pm1 = StandardMaterial name:"Proxy1"
        pm2 = StandardMaterial name:"Proxy2"
        pm3 = StandardMaterial name:"Proxy1"
        pm4 = StandardMaterial name:"Proxy1"
    
        mlist = #(
                     tm1
                    ,tm2
                    ,pm1
                    ,pm2
                    ,pm3
                    ,pm4
                )
        meditMaterials[1] = MultiMaterial materialList:(uniquifyArray mlist)
        matEditor.open()
    )
    
Sign In or Register to comment.