PDA

View Full Version : material change by name


Bixel
10-03-2007, 01:39 AM
weirdest thing. This scripts works perfectly fine with the exception of 1 thing. Here is what it is supposed to do. Change Material properties in scene only if it has a name. If it doesn't have a name, i.e. .name = undefined, then leave it alone. However it seems to change everything named or not.

for i = 1 to meditmaterials.count do
(
local changemat = meditmaterials[i].name
if changemat != undefined then
(
meditMaterials[changemat].opacity = 0 --100% transparent
meditMaterials[changemat].specularLevel = 0 --no specular
meditMaterials[changemat].specularMapEnable = off --no specular map
meditMaterials[changemat].specularLevelMapEnable = off --no specularmap level
meditMaterials[changemat].reflectionLevel - 0 --advanced reflection level
meditMaterials[changemat].reflectionMapEnable = off --get rid of reflextions.
meditMaterials[changemat].refractionMapEnable = off --no refraction
)
)
renderers.production = Default_Scanline_Renderer()
renderers.production.AntiAliasing = true
renderers.production.objectMotionBlur = off
renderers.production.imageMotionBlur = off
renderers.production.shadows = on
--renderers.production.filterMaps = off --enable/disable

where am I going wrong here?

focomoso
10-03-2007, 01:56 AM
Maybe test for .name != "" as well. Could be that a null name is stored as an empty string...

Bixel
10-03-2007, 02:03 AM
hrmm.. tried your suggestion, didn't work. now (ok this is strange), example. I named material 1,2,3 something1, something2 something3. I run the script, it changes something1 and everything else except something2 and something3. It is supposed to change anything named, so why did it ignore something 2 and something 3. and why did it change the undefined ones???

as an experiment I changed this line

local changemat = meditmaterials[i].name
if changemat != undefined and changemat != "" then

to this

local changemat = meditmaterials[i].name
if changemat == undefined and changemat == "" then

and it did nothing?? I am just flabbergasted. That should have changed everythign but it does the opposite.

RustyKnight
10-03-2007, 05:49 AM
I took you code and said:

if changemat == "" then (
format "[%]\n" changemat
)

And this worked fine...

I don't think your materials are named with empty strings...try the above and see what you get.

You could also play with the trimleft and trimright functions...so long as you don't have an "undefined" value - but I can't see the name been undefined

Shane

focomoso
10-03-2007, 06:32 AM
as an experiment I changed this line

local changemat = meditmaterials[i].name
if changemat != undefined and changemat != "" then

to this

local changemat = meditmaterials[i].name
if changemat == undefined and changemat == "" then

and it did nothing?? I am just flabbergasted. That should have changed everythign but it does the opposite.
I think you're misunderstanding boolean operations. The second if statement will ever execute because changemat can never be both undefined and empty at the same time. Boolean ands are limiting (always make the set smaller) So you read it as, "give me everything that is both x and y" not "give me everything that is x and also give me everything that is y". That's why nothing's getting changed. Switch the and to an or.

RustyKnight
10-03-2007, 06:36 AM
I think you're misunderstanding boolean operations. The second if statement will ever execute because changemat can never be both undefined and empty at the same time. Boolean ands are limiting (always make the set smaller) So you read it as, "give me everything that is both x and y" not "give me everything that is x and also give me everything that is y". That's why nothing's getting changed. Switch the and to an or.
Nice spot! Well done!

Bixel
10-03-2007, 07:04 AM
well thanks guys for helping me out. I didnt know that "" meant empty, I thought it mean any string entered/ I also didn't know proper boolean arguments. So thanx for that as well.

both recommendations worked - sort of. focomoso and RustyKnight's code changes made everything change. the only thing I need to change is materials with a name on it and not the default ones like 01 - Default.

I wil have to do some more meddling, if I get it to work right I will post the code.

PiXeL_MoNKeY
10-03-2007, 04:38 PM
The question I have is, why are you applying it to the materials in the editor? The reason I ask is because meditmaterials will be a material in the scene only if it is in the Material Editor. If you want to change the materials applied to something in the scene use scenematerials[i] which is an array of materials used in the scene and not just those currently in the materialeditor. I would reccomend reading up on "MaterialLibrary Values" in the maxscript reference.

-Eric

focomoso
10-03-2007, 08:30 PM
Glad to help.

I'll add to PiXeL_MoNKeY's concern that using empty names as a way differentiate materials is probably not good design to start with. You're better off putting a unique marker into the names that you may want to change like: "skin_mat_changeable" "green_grass_ changeable" and then use findString to test for you marker:

if findString changemat "changeable" != undefined then ...

This way you're being proactive about the objects your code works on: just things you've explicitly marked will get through.

Bixel
10-04-2007, 02:21 AM
focomoso, PiXeL_MoNKeY: Awesome! Those are so good points you raised. the findString approach is the right way to go. Also I will use scenematerials[i] instead since I am writing a script for several projects with different artist they could be merging in data into the scene as well. So I will update the code. if it works I will post it as an example.

Bixel
10-07-2007, 12:54 AM
ok, I got alot of stuff running really well. I have to write several scripts for different kinds of reasons. But with your help I was able to get most of them working. Now I have to change materials into composite, and assign a texture and an ADD color. The only problem now is I am getting this error

--unable to convert: unidentified to type: Point 3
@ this location >>> meditMaterials[sName].diffuse = noMaterial() --get rid of textures 1st
here's the sample code

if (findstring meditMaterials[i].name "input") == 1 then
(
-- Get the material name for easier use...
local sName = meditMaterials[i].name -- as integer
-- Convert the sufix to an integer
local iSufix = (substring sName 6 sName.count) as integer
-- Check how big the integer is
if iSufix != undefined and iSufix < 999 then
(
meditMaterials[sName].diffuse = noMaterial() --get rid of textures 1st
meditMaterials[sName] = compositematerial () --change to composite materials
----get uvtexture and put in main slot of composite materials
meditMaterials[sName][#materialList].diffuseMap = Bitmaptexture fileName:"E:\3dsmax9\maps\uvtex.png"
meditMaterials[sName][#materialList][#Maps][#Diffuse_Color__Map__1__uvtex_png].alphaSource = 2
----------------------------------------------------------------
meditMaterials[sName].materialList[2] = Standardmaterial () --setting up the added layer
--added layer is blue
meditMaterials[sName][#materialList][#Shader_Basic_Parameters].ambient = color 0 0 255
meditMaterials[sName][#materialList][#Shader_Basic_Parameters].diffuse = color 0 0 255
)
)


I tried changing sName to integer but this didnt help

focomoso
10-07-2007, 05:57 AM
meditMaterials[sName].diffuse is the color of the diffuse slot (a point3). You can't assign a material (or no material) to a property that expects a color. You could change it to

meditMaterials[sName] = noMaterial()

but you don't need that because in the next line you assign it to a compositematerial (just kill the line).

Also, a bit of coding practice: you start by referring to the material by it's index [i] and then switch to using the material's name [sName]. It won't brake the code, but it makes it difficult to follow (it took me a sec to figure out what you were doing). Your best bet is, after the findstring test, to assign the material to a variable (m works well) and do all your work on that. Much easier to read.

RustyKnight
10-07-2007, 06:00 AM
meditMaterials[sName].diffuse = noMaterial() --get rid of textures 1st
[/code]


.diffuse is not a material, it is actually a color. It is the color applied to the object when no map exists. You actually want &quot;meditMaterials[i].diffuseMap = noMaterial()&quot;

While testing your code, I had lots of issues with referencing the materials array using a string, so I'd recommend, rather then using &quot;sName&quot;, use &quot;i&quot;
meditMaterials[sName][#materialList].diffuseMap = Bitmaptexture fileName:&quot;E:\3dsmax9\maps\uvtex.png&quot;Should readmeditMaterials[i].baseMaterial.diffusemap = (Bitmaptexture fileName:&quot;E:\3dsmax9\maps\uvtex.png&quot;)

meditMaterials[sName][#materialList][#Maps][#Diffuse_Color__Map__1__uvtex_png].alphaSource = 2I'm sorry, but I have no idea what it is you are trying to achieve, but it does not work for.

This section...
meditMaterials[sName][#materialList][#Shader_Basic_Parameters].ambient = color 0 0 255
meditMaterials[sName][#materialList][#Shader_Basic_Parameters].diffuse = color 0 0 255Should readmeditMaterials[i].materialList[2].ambient = color 0 0 255
meditMaterials[i].materialList[2].diffuse = color 0 0 255
Again, it could just be that I'm missing parts of the code that will help make the rest run, but this is what I did to get it to work

Bixel
10-10-2007, 01:28 AM
I know I am a total noob at this but these scripts must be written. Please understand it is imperitive that only certain materials must be affected by name. Thus when I am looking for materials with "input" only those will be affected. I need to change them to composite but it seems impossible to change the .name to an integer as it seems that this:

meditMaterials[m] = compositematerial () --change to composite materials

requires an integer. (unable to convert standard type: integer)
even with this code it fails and gives me the same error

if (findstring meditMaterials.name "input") == 1 then
(
meditMaterials[i] = compositematerial () --change to composite materials
)
or this

if (findstring meditMaterials[i].name "input") == 1 then
(
--Get the material name for easier use...
local m = meditMaterials[i] as integer
meditMaterials[m] = compositematerial () --change to composite materials
)

--------------------------------------------------------------------------------------
The job of the script is to change materials from other people's scene's and have a certain render output. So these materials have specific names set up by the artist. This is why I am constantly trying to weed out materials by name. So in this piece of code only certain materials are changed to a composite.

the other materials that do no have "input" in the name have to be checked for this
This peice of code runs after the above

else if meditMaterials[i].opacity < 100 then -- is there transparency in materials???
( some code)

unknown property: "opacity" in compositematerial:Composite
Its not a composite material but a Standard Material so I do not understand why I am getting this error. Here is the code.


for i = 1 to meditMaterials.count do
(
-- looking for any named materials with the word "input"
if (findstring meditMaterials[i].name "input") == 1 then
(
-- Get the material name for easier use...
local m = meditMaterials[i] as integer
meditMaterials[i] = compositematerial () --change to composite materials
----get uvtexture and put in main slot of composite materials
meditMaterials[i].baseMaterial.diffusemap = (Bitmaptexture fileName:"E:\3dsmax9\maps\uvtex.png")
----------------------------------------------------------------
meditMaterials[i].materialList[2] = Standardmaterial () --setting up the added layer
--added layer is blue
meditMaterials[i].ambient = color 0 0 255
meditMaterials[i].diffuse = color 0 0 255
)
else if meditMaterials[i].opacity < 100 then -- is there transparency in other materials???
(
meditMaterials[i].opacity = 0 --if so make 100% transparent
)
else if meditMaterials[i].reflectionMapEnable == on then --is their reflection mapping?
(
if meditMaterials[i].opacity == 100 then --check for no transparency, for transparency takes presidence
(
meditMaterials[i].reflectionMapAmount = 100 --make reflection 100%
)
)
)


please understand I have to change materials by name, and only certain ones.

I think perhaps there is a completely circuitous way of doing this, maybe I can somehow isolate the "input" materials, perhaps even rename them as 0001 0002 and pass that as an integer I dunno.

RustyKnight
10-10-2007, 01:57 AM
I know I am a total noob at this but these scripts must be written.
Join the club!


local m = meditMaterials[i] as integer

I know this won't work, material can not be converted to an interger, it just isn't possible, it would like saying "person as car"...makes no sense...
--------------------------------------------------------------------------------------

[i] else if meditMaterials[i].opacity < 100 then -- is there transparency in materials???
( some code)

unknown property: "opacity" in compositematerial:Composite
Its not a composite material but a Standard Material so I do not understand why I am getting this error. Here is the code.

How do you know what they are? You're assuming that they are standard materials, when they may not be! Hence you are getting an error

You need to perform a check as to what type of material you are dealing with.

if (classof meditMaterials[i]) == Standardmaterial then (
-- Now you have a standard material
)

I've updated the main section of the code and corrected some additional mistakes. I also noticed that when you change the material, the name is also reset, so I reapply it at the end of the if block...

for i = 1 to meditMaterials.count do
(
-- looking for any named materials with the word "input"
if (findstring meditMaterials[i].name "input") == 1 then
(
-- Get the material name for easier use...
local sName = meditMaterials[i].name

/***** This will bite you the back end *****/
--local m = meditMaterials[i] as integer
meditMaterials[i] = compositematerial () --change to composite materials
----get uvtexture and put in main slot of composite materials
meditMaterials[i].baseMaterial.diffusemap = (Bitmaptexture fileName:"E:\3dsmax9\maps\uvtex.png")
----------------------------------------------------------------
meditMaterials[i].materialList[2] = Standardmaterial () --setting up the added layer
--added layer is blue

/***** This will bite you the back end... *****/
/** Composite material does not have an ambient or diffuse slot... ****/
--meditMaterials[i].ambient = color 0 0 255
--meditMaterials[i].diffuse = color 0 0 255
/** BUT, the standard material you just applied does! **/
meditMaterials[i].materialList[2].ambient = color 0 0 255
meditMaterials[i].materialList[2].diffuse = color 0 0 255

-- Reset the material name...
meditMaterials[i].name = sName
)
)

please understand I have to change materials by name, and only certain ones.
Yeah, I think we got that part ;)

ed:
I should also point out that you can name the composite material when you create it:

meditMaterials[i] = compositematerial name:meditMaterials[i].name

Bixel
10-10-2007, 02:41 AM
:applause:OH MAH GAWD:applause:

The forum will not let me increase your rep. unless I increase somebody else's. Thanks for being so understanding. I totally forgot I could do this

local sName = meditMaterials[i].name
{make some changes}
meditMaterials[i].name = sName >>then apply the changes after. Everything works!

Except unlike previous scripts this doesnt change any of the materials that are applied to objects in the scene. I even choose the eyedropper from one of the objects and it returned as input001 - but no composite. While input001, 002 and 003 in the Materials lib. have been changed. I even tried the Update Active Material. hrmm...I will scour the reference to find something.

Ah i got it. this works. Put Material to Scene. Now I just have to find a function for that, perhaps this can be used. But I am not using it right. >>UpdateMtlEditorBrackets()

RustyKnight
10-10-2007, 03:06 AM
:applause:OH MAH GAWD:applause:

The forum will not let me increase your rep. unless I increase somebody else's. Thanks for being so understanding. I totally forgot I could do this

That's okay, everyone knows I'm an idiot ;) ( lol )


local sName = meditMaterials[i].name
{make some changes}
meditMaterials[i].name = sName >>then apply the changes after. Everything works!

Except unlike previous scripts this doesnt change any of the materials that are applied to objects in the scene. I even choose the eyedropper from one of the objects and it returned as input001 - but no composite. While input001, 002 and 003 in the Materials lib. have been changed. I even tried the Update Active Material. hrmm...I will scour the reference to find something.

Ah i got it. this works. Put Material to Scene. Now I just have to find a function for that, perhaps this can be used. But I am not using it right. >>UpdateMtlEditorBrackets()
The bad news is, I think you will need to reapply the materials to the objects...this thought is straight off the top of my head

Shane

Bixel
10-10-2007, 03:11 AM
Yeh thats exactly it, is there a way to not manually reapply materials to the objects? I've been looking for a function that does Put Materials to Scene in the reference but found nothing.

RustyKnight
10-10-2007, 03:21 AM
Yeh thats exactly it, is there a way to not manually reapply materials to the objects? I've been looking for a function that does Put Materials to Scene in the reference but found nothing.
I gotta tell ya, this forum rocks! :buttrock:

This is the solution that I've been able find...

-- Grab a reference to the current material
local mOld = meditMaterials[1]
local sName = mOld.name
-- Create our new material
local mNew = (compositematerial name:sName)

-- Do everything you were before, just act on the mNew instead...
mNew.materialList[2] = Standardmaterial () --setting up the added layer
mNew.materialList[2].ambient = color 0 0 255
mNew.materialList[2].diffuse = color 0 0 255

-- And the magic solution!
replaceInstances mOld mNew

While I would sincerly like to take credit, it just wouldn't be right, this is where I found the solution...
http://forums.cgsociety.org/showthread.php?f=98&t=482548&highlight=update+material

Shane

Bixel
10-10-2007, 03:36 AM
Yes!!! thats It! Whoo hoo!! (now hopefully I wont have to write any scripts for a couple of weeks).

focomoso
10-10-2007, 03:42 AM
Bixel, I thought you were going to change your script to work on scene materials and not medit materials. The way it is now, if you have a material in the scene that isn't in the editor, it won't get changed.

Bixel
10-10-2007, 05:04 AM
Actually the entire script handles the scenematerials as well, its basically the above with medit swtiched out with scene. Now all I have to do is write a script to check all objects in the scene without any materials applied to them - ie. no textures.

RustyKnight
10-10-2007, 06:34 AM
The forum will not let me increase your rep.
If you really want to thank me, feed back into the community. You might think you're a noob now (I still think I am), but you might just have the answer some one else is looking for. So when you become more confident, try helping some others out. I would consider it payment in full ;)

Shane

CGTalk Moderation
10-10-2007, 06:34 AM
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.