How to grab the texture map of a surface
V3Digitimes
Posts: 3,172
Hello,
I need to apply one map generally assigned to one variable (for instance diffuse color) to another variable (for instance translucency color), by a script.
I'm a beginner so please be indulgent :)
For now, here is the end what I have written, helped by a script Rob provided to me a while ago (the script works to grab a value on variable having no map, but when there is a map... ouch...) :
DsActions.prototype.setMaterialProperties = function( oMaterial, oShape ){ this.m_oElement = oMaterial; var sID = this.m_oElement.name; if( oShape != undefined ){ sID += "_" + oShape.getLabel(); } // DAZ Studio version 4.6.3.49 filetype DAZ Script // Thanks ONCE AGAIN to Rob for providing some parts of the following code. // <a href="http://www.daz3d.com/forums/discussion/42842/">http://www.daz3d.com/forums/discussion/42842/</a>// Define the list of names you care aboutvar aSurfaceNames = [ "Torso", "Hips" ];// Define the name you want to checksFind = sID// Check if the name is in the listvar nIndex = aSurfaceNames.indexOf( sFind );if (nIndex > -1) { var aPROPERTIES = oMaterial.getPropertyList(sID); var oProperty, oOwner, oValue; for( var i = 0; i < aPROPERTIES.length; i++ ){ oProperty = aPROPERTIES[ i ]; // on remply l'array oOwner = oProperty.getOwner(); oValue = oProperty.getValue(); // on attrape la valeur oNames = oProperty.getName (); // de cette variable print (oNames) print (oValue) if (oNames == "Diffuse Color") {..... // tex = oNames.getMapValue(); // filename = tex.getFilename();
And I stopped there, because I realised I don't know how to have the map value alone. I tried ".getMapValue" but I have a message error
Result of expression 'oValue.getMapValue' [undefined] is not a function...
Any idea what I could use?
Thanks in advance for any help of any sort!
Comments
oValue is a number, you want to use getMapValue() on oProperty itself, first using isMapped() to make sure that there's a map to get (and not a flat colour).
And it works!!!
Thank you so much Richard! if I had a "blow kiss" smiley, this should be place exactly here in this post!
I've finally managed to write the full script catching a map to place it somewhere else! I'm not sure it is really "clean" because I did not understood everything I made (100% trial/error method), but it works.
Now I just have to find out how to load and apply a shader definition asset, or a shader, in the same dsa file. My little finger tells me my troubles are not over ;)
Try saving a Shader preset using the deprecated script format and pick that apart.
Yes, Richard, I remember already had other things working this way in other project with my amazing skins. The drawback is that the brick network is embedded in the dsa file. This is why I wanted to avoid this method, first because while still in development stage, the brick network is often changed, and each time I have to re-modify the dsa, and also because a shader definition asset protects "just a bit" more the author work.
I have second possibility which is to create a dsa calling my main duf, then the "map mover" dsa I just finished. I remember I read somewhere a dsa could call a duf (or the contrary?)
I have a last possibility which will be to keep 2 files "apply me first" (the material) "apply me second" (the maps in the right place). This is not an elegant solution (but sometime pragmatism wins over elegance).
Yes, you could grab the settings, apply the .duf for the base shader, and then restore settings - the only risk would be idiots like me who can never leave files in their default locations, but if you use the script context to get the location from which the script is run you could find the shader preset in that folder or a sub-folder even if it had been moved.
Thanks!
For now all I'm trying to have a "all in one" fails.
I tried to save as a deprecated material, and added at the end the script part to swap files, and the strange thing is that it behaves during the swapping as if the properties were the one of the old material not the new one.
This means in practice that I have to apply the same script twice, and the first time it will apply the shader to the list of surfaces (but will not move the maps), the second time it will move the maps...
So I've told to myself I was going to use the "openFile" you showed me here.
But I cannot set it up yet, well, maybe because I'm just tired...
I'm gonna sleep and try tomorrow morning with a fresh brain (scripting is very tiring!)
Two questions remain :
Can the "openFile( targetFile )" also open a duf file (and in this case will it be applied normally like a material preset)?
what is the format of targetFile? A string? something else? must this contain the path too?
Yes, a string is the input with the full path - which is what I was suggesting using the script file name for. I do, somewhere, have a script that uses this so I will try tomorrow to dig it out and post the relevant snippet.
Thanks, your answer helped me a lot since I had less issues to investigate, and.....
Finally I had it working!!!!!
I based on a script I had made with your help (or Rob one?), which had been modified by Rob, to load an help pdf file from one of my product, and which I re-modified to open my duf with your help (again).
For info :
the rest of the code displays an error message if the files where not found.
I think this is really fine and I am going now to try to load the two scripts (first the shader, then the map mover) successively using this script, I hope this will work! I really love this solution, this is so flexible in term of development !
I just hope the second file will see that the first file was applied...
I really appreciate your help Richard, I'm not sure I would have dared going on with scripting without anybody supporting my effort when I'm lost !
You're welcome.
This is the sort of thing I had in mind (I couldn't find my existing example). If the presets are in a sub-folder of the script's folder, here called "Do not alter", then the function will work wherever the script and the folder are placed. You just need to pass the name of the sub-folder (in order to keep the code portable - you could add the sub-folder name as a string operation inside the function itself and just pass the bare name of the preset) after capturing the existing settings, then if the preset was applied successfully you run the code to apply the stored settings to the new shader.
V3Digitimes, did you ever get this working?
I am looking to do, in sounds like, exactly the same thing you are: apply a material, look for certain maps and apply those maps in alternate channels.
Its been so long since I scripted anything I am feeling totally lost. I can understand a lot of the examples and things I am looking at... but, where to begin is a huge struggle.
PM Mustakettu85, she has a 3Delight shader kit that has scripts to swap maps around; Bump to Displacement, etc.
I may very well already have those scripts, mjc...I shall have to look at the package she gave me (i got distracted by iRay and haven't gone back to 3Delight since).
And why the hell can't I get Richard's above script to work? Seems simple enough... I just need to tell it, somewhere, what the name of the actual duf file I want to apply is, right? And if its saved in the same location as the script I am running, it should apply it, right?
I feel like such a noob! I'm not comfortable with that.
The script is set to load a file (blue.duf) from the folder Do not alter in the folder that contains the script. The .duf file can be anything, even a full scene, but if it's a preset you need to have the target item selected.
Thank you, Richard, for pointing out the obvious, important part of the script that I was too dense to gather.
You really gotta wonder where the hell my brain is at right now.
You guys rock.
I have most of the pieces now, I just gotta figure out how to make them all work together.
Proper usage of isMapped()?
I keep getting a parse error, so I am obviously doing something wrong.
And are those code snippets above posted as an image?
No, that looks like the code tags in the new forum software.
The code snippets are text, for me.
Check that your property is a DzNumericProperty or a derivative, other properties don't have isMapped().
How do Generation 4 figures differ from Genesis in such a way that a script reading and setting material settings would not work the same?
I'm basing my work on someone else's script, so... while I follow what its doing, I'm not sure its the best way to do it.
using getobject, getcurrentshape and getnummaterials to iterate over the materials, then findproperty along with getMapValue to read a map then findproperty and setMap to apply it elsewhere. Works great genesis 1 & 2... does absolutely nothing on Generation 4.
also... what would be the appropriate method to use to set a value on a parameter like Bump Strength (iray uber shader)?
Apparently I was using an older version of the script that didn't work, so ignore the question about Gen 4 vs Genesis. Script works fine on both.
Still looking to set that numeric value, though.
Hi evilded, sorry for the delay. After 3 weeks -or more- working on it, (I'm really not good at scripting), my script finally works "just enough" to do what I need. But there are plenty of things that I could not have work and that are finally by luck made by DS by simple variable name identification (regardless of the script). In order to set the numeric value it depends on the type of the value (the type of the property). Some will accept setmap, some won't, most of the time it remains a mystery to me, but I hope "when I'm tall I'll understand".
In order to set map I use oProperty.setMap("the map") and in order to set the other properties I use for instance : g_oPresetHelper.setNumericPropertyWithAttributes( "name or label of the variable I don't rememeber", false, 0, 1, [ 1 ] );
The g_oPresetHelper.setNumericPropertyWithAttributes is extracted from the dsa you have when you save for instance a material preset in dsa.
I hope this helps..
ok... making my way back in here, understanding better the script I am working from, etc.
How do I grab the pieces of the Iray Uber material to understand what they are and what methods are available? There must be a way to do this.
What do you mean? Are you wanting parameters, or are you wanting shader networks or MDL code?
Richard, looking for parameters and methods available for scripting, like what you see for DZDefaultMaterial in the old docs.
ie
Color getAmbientColor()
DZColorProperty getAmbientColorControl()
I saw there was an example script to get all the available properties, etc of a given node. http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/properties/node_properties/start
I assume one can do the same thing for a material.
The general method is to use findProperty( "name" ) or findProeprtyByLabel( "label" ) on the material.The methods like getAmbientColor() are special utility functions that are tailored, for the most part, to the DAZ Default Shader. Then having got a property use inherits( "DzClassName" ) to make sure it is the right type for what you want to do.
working, thinking, processing. I am not asking the correct question.
I've manged to suss out the class name (DZUberIrayMaterial), but not much else.
WTH does this tell me? And can I use it somehow to find out more information?
TypeError: Result of expression 'myShineStrMap.setTopCoatBumpStrength' [undefined] is not a function
"The DzAsset API is [thus far] undocumented, but can be explored [like any object] using a "for...in" loop to print member signatures." -- rbt, from another post here, I don't know how to pont to particular posts yet.
This is exactly what I want to do, only on the DZUberIUrayMaterial. I understand the loop part, but what is a member signature and how do I tell it to print those?
Took some creative Search Fu, but I found this...http://www.daz3d.com/forums/discussion/37769/
Which may have lead me to what I need. Man, that's a lot of data to sift.