CGTalk > Software > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
Thread Closed share thread « Previous Thread | Next Thread »  
 
Thread Tools Search this Thread Display Modes
Old 09-28-2012, 12:31 AM   #1
JokerMartini
Expert
 
JokerMartini's Avatar
portfolio
John Martini
CG Supervisor, 3D, Maxscript, VFX
Ingenuity Engine
Los Angeles, USA
 
Join Date: Mar 2009
Posts: 1,299
Send a message via AIM to JokerMartini
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.
Code:
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
 
Old 09-28-2012, 12:56 AM   #2
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,338
Send a message via ICQ to denisT
search for replaceinstances in this forum...
 
Old 09-28-2012, 01:08 PM   #3
JokerMartini
Expert
 
JokerMartini's Avatar
portfolio
John Martini
CG Supervisor, 3D, Maxscript, VFX
Ingenuity Engine
Los Angeles, USA
 
Join Date: Mar 2009
Posts: 1,299
Send a message via AIM to JokerMartini
I came across a simple example which only works straight up with single shaders not blends or multimats.

Code:
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'?

Code:
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
 
Old 09-28-2012, 01:31 PM   #4
JokerMartini
Expert
 
JokerMartini's Avatar
portfolio
John Martini
CG Supervisor, 3D, Maxscript, VFX
Ingenuity Engine
Los Angeles, USA
 
Join Date: Mar 2009
Posts: 1,299
Send a message via AIM to JokerMartini
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.




Code:
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


Code:
-- 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-28-2012 at 01:39 PM.
 
Old 09-28-2012, 04:08 PM   #5
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,338
Send a message via ICQ to denisT
go another way:
Code:
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 )
 
Old 09-28-2012, 04:27 PM   #6
JokerMartini
Expert
 
JokerMartini's Avatar
portfolio
John Martini
CG Supervisor, 3D, Maxscript, VFX
Ingenuity Engine
Los Angeles, USA
 
Join Date: Mar 2009
Posts: 1,299
Send a message via AIM to JokerMartini
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
 
Old 09-28-2012, 05:07 PM   #7
JokerMartini
Expert
 
JokerMartini's Avatar
portfolio
John Martini
CG Supervisor, 3D, Maxscript, VFX
Ingenuity Engine
Los Angeles, USA
 
Join Date: Mar 2009
Posts: 1,299
Send a message via AIM to 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.

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
 
Old 09-28-2012, 06:51 PM   #8
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,338
Send a message via ICQ to denisT
Quote:
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.
 
Old 10-01-2012, 10:30 PM   #9
JokerMartini
Expert
 
JokerMartini's Avatar
portfolio
John Martini
CG Supervisor, 3D, Maxscript, VFX
Ingenuity Engine
Los Angeles, USA
 
Join Date: Mar 2009
Posts: 1,299
Send a message via AIM to 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.
__________________
____________ ___ __ _
John A. Martini
JokerMartini@hotmail.com
www.JokerMartini.com
 
Old 10-01-2012, 10:53 PM   #10
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,338
Send a message via ICQ to denisT
Quote:
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
 
Old 10-02-2012, 02:45 PM   #11
JokerMartini
Expert
 
JokerMartini's Avatar
portfolio
John Martini
CG Supervisor, 3D, Maxscript, VFX
Ingenuity Engine
Los Angeles, USA
 
Join Date: Mar 2009
Posts: 1,299
Send a message via AIM to JokerMartini
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
 
Old 10-02-2012, 02:58 PM   #12
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,338
Send a message via ICQ to denisT
Quote:
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

Code:
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) */
 
Old 10-02-2012, 02:58 PM   #13
CGTalk Moderation
Lord of the posts
CGTalk Forum Leader
 
Join Date: Sep 2003
Posts: 1,066,481
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


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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 09:21 AM.


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