Condense and Swap SubMaterials

Hello, I've been searching and didn't found something doing this, maybe some of you know if this exist or how it can be done.
All faces on all selected objects (these objects are using different multimaterials) pointing to the material named "Grass" before the script (id 2 5 and 1 in the exemple) are, after the script, assigned to id 30, and all the objects are using a single multimaterial.

I have a scene organized like this :

Id - name - Sub-Material
[Multimaterial A]
[1] [ ] [Dirt]
[2] [ ] [Grass]
...
[12] [ ] [Rock]

[Multimaterial B]
[1] [ ] [Dirt]
[5] [ ] [Grass]
[25] [ ] [Rock]

[Multimaterial C]
[1] [ ] [Grass]
[2] [ ] [Dirt]
[25] [ ] [Rock]

etc...
after running the script,I need all the selected objects to use :

[MY Multimaterial]

...

[30] [ ] [30-Grass]
...
[42] [ ] [42-Dirt]
...
[46] [ ] [46-Rock]

Where the correspondance [ID]<-->[SubMaterial] has been defined by me, the renaming here is not mandatory, but I will name the material this way in the future, so this naming convention could be used as input for the script.

It's a kind of "organized condense materials"

Thanks !

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
barigazy's picture

...

What kind of script you talking about?

barigazy

Fix's picture

Kind of script ?

I don't understand the question, what are the different kinds of scripts ?

I'd say it's a utility script, thats is run on a selection of EditPolys using different MultiMaterials; that condense the different MultiMaterials into a single one, while modifying the selected EditPolys faces' IDs to fit the new Id's order.

barigazy's picture

...

Try this

try(destroyDialog ::bgaRoll)catch()
rollout bgaRoll "• • •"
(
	spinner spn_mm "SubMat ID:        " pos:[5,5] type:#integer range:[1,100,1] fieldwidth:50
	checkbox cb_swap "Change SubMat ID" pos:[5,25] checked:on
	spinner spn_face "NewFace ID:      " pos:[5,45] type:#integer range:[1,100,1]  fieldwidth:50 
	button btn "Do the Job!" pos:[5,65] width:140
	on btn pressed do
	(
		if selection.count != 1 then messageBox "Select an object" beep:off else
		(
			local obj = selection[1]
			if not isKindOf obj.mat Multimaterial then messageBox "Object material need to be multimaterial" beep:off else
			(
				max modify mode
				if obj.mat[spn_mm.value] == null then messageBox ("SubMaterial ["+spn_mm.value as string+"] not exists") beep:off else
				local ep = edit_poly name:"NewMtlID"
				addmodifier obj ep
				ep.setselection #Face #{1..(obj.GetNumFaces())}
				ep.SetOperation #SetMaterial
				ep.materialIDToSet = spn_face.value - 1
				if cb_swap.checked then obj.mat.materialIDList[spn_mm.value] = spn_face.value else obj.mat = obj.mat[spn_mm.value]
			)
		)
	)
 
)
createDialog bgaRoll 150 90 style:#(#style_titlebar, #style_sysmenu, #style_toolwindow)

barigazy

Fix's picture

It works

Thanks a lot barigazy for the time spent writing this script.
It works, excepted the submaterial changes aren't undo-able.
I'll try to learn how to make it evolve to support multiple objects selected, with different multimaterials, and resolve ID conflicts, I don't want to take too much of your time.
Because in this state, it's almost more powerfull to add an EditPoly modifier on all objects sharing the same multimaterial, select faces by ID and assign a new ID.
Thanks again for your help.

barigazy's picture

...

Here we go.
Now this tool works with multiple selected objects that share same multimaterial.
Also undo is supported here. ;)
Try it and thel me what you think

try(destroyDialog ::bgaRoll)catch()
rollout bgaRoll "• • •"
(
 
	spinner spn_mm "SubMat ID:        " pos:[5,5] type:#integer range:[1,100,1] fieldwidth:50
	checkbox cb_swap "Change SubMat ID" pos:[5,25] checked:on
	spinner spn_face "NewFace ID:      " pos:[5,45] type:#integer range:[1,100,1]  fieldwidth:50 
	checkbox cb_deselect "Auto Deselect Intruders" pos:[5,65] checked:on
	button btn "Do the Job!" pos:[5,85] width:140
	fn doTheJob =
	(
		if selection.count == 0 then messageBox "Select some objects that share same multimaterial" beep:off else
		(
			local objMat = selection[1].mat
			if not isKindOf objMat Multimaterial then messageBox "Selected object material need to be multimaterial" beep:off else
			(
				if cb_deselect.checked then (deselect (for o in selection where o.mat != objMat collect o)) else
				(
					for o in selection where o.mat != objMat do exit with (return messageBox "All Selected objects must share same multimaterial!" beep:off)
				)
				if objMat[spn_mm.value] == null then (messageBox ("SubMaterial["+spn_mm.value as string+"] not exists. Try with other one.") beep:off) else
				(
					max modify mode
					undo "ReassigneID" on
					(
						local ep = edit_poly name:("MtlID_#"+spn_face.value as string)
						modPanel.addModToSelection ep ui:on ; subobjectLevel = 4 ; max select all
						ep.SetOperation #SetMaterial
						ep.materialIDToSet = spn_face.value - 1 ; subobjectLevel = 0
						if cb_swap.checked then objMat.materialIDList[spn_mm.value] = spn_face.value else selection.mat = objMat[spn_mm.value]
					)
				)
			)
		)
	)	
	on btn pressed do doTheJob()
)
createDialog bgaRoll 150 110 style:#(#style_titlebar, #style_sysmenu, #style_toolwindow)

barigazy

barigazy's picture

...

edit:
Find in "undo" list "ReassigneID" if you want to back to previous state.
When use this version make sure that first you select object with multimaterial and
then ctrl + select the rest.
Also if "Auto deselect intruders" is checked then all object in selection which not share same material as first selected object will be automatically deselected from process.
I hope this is the option that you looking for :)

barigazy

Fix's picture

Awesome !

Thank you very much, this is really helpfull and pretty robust :)

barigazy's picture

...

My pleasure :)
Cheers!

barigazy

barigazy's picture

how it works

Select an object which have assigned Multimaterial.
Set *SubMat ID* value to be sub-material that you want to change.
Set *"NewFace ID* value to be new object face ID.
Note: New edit poly modifier will take care of face ID.
If "Change SubMat ID" checkbox is checked then object material ID will be also changed to correspond to face ID else sub-mat that you have chosen will be new object material.

barigazy

barigazy's picture

...

Small correction. Use this code

try(destroyDialog ::bgaRoll)catch()
rollout bgaRoll "• • •"
(
	spinner spn_mm "SubMat ID:        " pos:[5,5] type:#integer range:[1,100,1] fieldwidth:50
	checkbox cb_swap "Change SubMat ID" pos:[5,25] checked:on
	spinner spn_face "NewFace ID:      " pos:[5,45] type:#integer range:[1,100,1]  fieldwidth:50 
	button btn "Do the Job!" pos:[5,65] width:140
	on btn pressed do
	(
		if selection.count != 1 then messageBox "Select an object" beep:off else
		(
			local obj = selection[1]
			if not isKindOf obj.mat Multimaterial then messageBox "Object material need to be multimaterial" beep:off else
			(
				max modify mode
				if obj.mat[spn_mm.value] == null then messageBox ("SubMaterial ["+spn_mm.value as string+"] not exists") beep:off else
				(
					local ep = edit_poly name:"NewMtlID"
					addmodifier obj ep
					ep.setselection #Face #{1..(obj.GetNumFaces())}
					ep.SetOperation #SetMaterial
					ep.materialIDToSet = spn_face.value - 1
					if cb_swap.checked then obj.mat.materialIDList[spn_mm.value] = spn_face.value else obj.mat = obj.mat[spn_mm.value]
				)
			)
		)
	)
)
createDialog bgaRoll 150 90 style:#(#style_titlebar, #style_sysmenu, #style_toolwindow)

barigazy

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.