Material Glitch

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

THREAD CLOSED
 
Thread Tools Search this Thread Display Modes
  09 September 2012
Material Glitch

So in a max scene I want to create a material through maxscript and replace an existing material in the scene with the newly created one.

The Glitch: Via maxscript you can have two materials with the same exact name on two different objects in the scene. It will render both objects with the two different materials.

For those who don't know maxscript, when you try to apply a material with the same name as an already existing scene material you'll be prompt to rename it or replace existing.

What I'm after: Does anyone know of a way to do the replace method with a material that is either created via maxscript or brought into the max scene through reading in a mat lib file?

Because I have a shader in the max scene called "Screw" and I want to bring in a new material named the same exact thing "Screw" but I can not figure out a way to replace that material. I want to stay away from any dialog popping up that says to replace, I just want it to happen. This way if the screw material is in a multi-sub on accident, that will also get updated to the new one. I hope this makes sense. I hope you guys can help.


This below code reads in a .mat file and applies it to an object in the scene.

matFile = @"C:\Users\Crabs User\Desktop\trash\Shot001\MATERIALS\Box\Box.mat"
loadMaterialLibrary matFile
mats = for i = 1 to currentMaterialLibrary.count where superClassof currentMaterialLibrary[i] == material collect currentMaterialLibrary[i]
	
userSel = selection as array

for o in userSel where isValidNode o while mats.count > 0 do (
	o.material = mats[1]
)
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
  09 September 2012
search for replaceinstances in this forum...
 
  09 September 2012
I came across a simple example which only works straight up with single shaders not blends or multimats.


fn thefunction m = 
(
	vm = VrayMtl diffuse:yellow
	Replaceinstances m vm
)

mats = for i in sceneMaterials where superClassof i == material AND i.name == "Box" collect i

for m in mats do (
	thefunction m
)



I did come across this snippet of yours. Now how do I use this?
Do I pass it the 'Material to replace in the scene' and the 'material to replace it with'?


fn xchangeMats source target = if source != target and iskindof source material and iskindof target material do
(
	for n in refs.dependents source do case of
	(
		(isvalidnode n and n.mat == source): n.mat = target
		(iskindof n material): for i=1 to (getNumSubMtls n) where (getSubMtl n i) == source do setSubMtl n i target
	)
	target	
)
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
  09 September 2012
http://forums.cgsociety.org/showthread.php?t=756047

This method works only if the materials are instances. I'm trying to make it fool proof by replacing not only the instances but also the materials which matching names. Run the script I provide below to create the scene. It makes two cubes with a copy of the same material with the same name on each one. When you run the replace materials code it only replaces the one material and not all of them....why is that? It doesn't seem to find it in the sub material or blends.





delete objects

redWhite = standard diffuseMap:(checker color1:red color2:white) name:"redWhite"
blueGreen = standard diffuseMap:(checker color1:blue color2:green)  name:"blueGreen"

multi = multimaterial numSubs:2
multi[1] = copy redWhite
multi[2] = copy blueGreen

blnd = blend map1:(copy redWhite) map2:(copy blueGreen)

myA = box material:redWhite name:"Single Shader" width:30 height:30 length:30 pos:[-20,0,0]
myB = box material:multi name:"Multi Sub" width:30 height:30 length:30 pos:[20,0,0]
myC = box material:blnd name:"Multi Sub" width:30 height:30 length:30 pos:[60,0,0]

showTextureMap myA.material myA.material.diffuseMap on
showTextureMap myC.material myC.material.map1.diffuseMap on	
showTextureMap myB.material myB.material[1].diffuseMap on




 -- Recursive functions to find and replace materials, in the scene and in the material editor.
 fn replacematerialserachmtlsubs m s t=if getnumsubmtls m>0 then for i=1 to (getNumSubMtls m) do if getNumSubMtls (getSubMtl m i)==0 then (if (getSubMtl m i)==s then setSubMtl m i t) else replacematerialserachmtlsubs (getSubMtl m i) s t
 fn replacematerial s t=
 (
 	for n in refs.dependents s do case of
 	(
 		(isvalidnode n and n.mat==s)		:	n.mat = t
 		(iskindof n material)						:	replacematerialserachmtlsubs n s t
 		(iskindof n Material_Editor)			:				
 		(
 			for j=1 to meditmaterials.count do case of
 			(
 				(meditmaterials[j]==s)		:	medit.PutMtlToMtlEditor t j
 				default								:	replacematerialserachmtlsubs meditmaterials[j] s t
 			)
 		)
 	)
 )
 -- replacematerial <source material> <target material>

newYellow = standard diffuseMap:(checker color1:yellow color2:orange)  name:"newYellow"

mats = for i in sceneMaterials where superClassof i == material AND i.name == "redWhite" collect i

for m in mats do (
	replacematerial m newYellow
)
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com

Last edited by JokerMartini : 09 September 2012 at 01:39 PM.
 
  09 September 2012
go another way:

fn replaceAllMaterialDups target = 
(	
	mats = #()
	for class in material.classes do join mats (getclassinstances class)
	for source in mats where source != target and stricmp source.name target.name == 0 do replaceinstances source target
)
 
  09 September 2012
unaware that material.classes was even a thing. That is awesome. Thank you Denis very much for the help on this one. I thought I was going to go nuts.

It's a huge time saver.
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
  09 September 2012
What is interesting is when I update a multiSub with 3 subs:
1.Screw
2.Bolt
3.Nut
It doesn't find the single shader that may exist already in the scene and replace it with an instance.

Is there a way to have the sub or blend materials loop through their material array and search for solo shaders with duplicate names and replace them with an instance of the matching multisub shader. because with the current script it is doing a find and replace looking for the parent multiMat material and not it's children. Does that make sense?
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
  09 September 2012
Originally Posted by JokerMartini: What is interesting is when I update a multiSub with 3 subs:
1.Screw
2.Bolt
3.Nut
It doesn't find the single shader that may exist already in the scene and replace it with an instance.

that the solo shader is? is it a shader that assign for nothing?
getclassinstances collects only instances which are objects of any subanim. if add this solo shader to anything (material editor, scenematerilas, material library, custom property, etc.) it will be found as an instance.
 
  10 October 2012
This is where the loop-hole happens

So for a example you have two objects in the scene, a box and sphere.

Sphere.material = "Screw"
Box.material = multimat "Bolt, Screw"

When you bring in the .mat of the multimat material it doesn't know to replace the Screw material on the sphere with the one found in the multimat.
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
  10 October 2012
Originally Posted by JokerMartini: This is where the loop-hole happens

So for a example you have two objects in the scene, a box and sphere.

Sphere.material = "Screw"
Box.material = multimat "Bolt, Screw"

When you bring in the .mat of the multimat material it doesn't know to replace the Screw material on the sphere with the one found in the multimat.

look at my function. it needs a target material. after that it searches for all materials in the scene and replaces all with the same as the target name to the target.
so if you call my function with box.multi.screw as target it replaces the sphere.screw.
if you create new screw material and use it as target, the new material will replace both box.multi.screw and sphere.screw
 
  10 October 2012
Alright. If i come across the error I had ill save the scene and upload. Until then thanks Denis for your help on this one.
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
  10 October 2012
Originally Posted by denisT: look at my function. it needs a target material. after that it searches for all materials in the scene and replaces all with the same as the target name to the target.
so if you call my function with box.multi.screw as target it replaces the sphere.screw.
if you create new screw material and use it as target, the new material will replace both box.multi.screw and sphere.screw


fn replaceAllMaterialDups target = 
(	
	mats = #()
	for class in material.classes do join mats (getclassinstances class)
	for source in mats where source != target and stricmp source.name target.name == 0 do replaceinstances source target
)

delete objects
meditmaterials[1] = m1 = standard name:"Screw" diffuse:red
meditmaterials[2] = m2 = multimaterial materialList:#(standard name:"Bolt" diffuse:blue, standard name:"Screw" diffuse:green)
sp = sphere material:m1 
bx = box material:m2

/*
replaceAllMaterialDups bx.mat[2]
-- or
replaceAllMaterialDups sp.mat
-- or
replaceAllMaterialDups (meditmaterials[1] = m3 = standard name:"Screw" diffuse:orange)
*/
 
  10 October 2012
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
__________________
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
 
Thread Closed share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 03:47 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.