Apply a shader base to every object in a scene via script?

SickleYieldSickleYield Posts: 7,634

Or everything selected in scene tab, preferably.  Is this possible with scripting?  I apologize if this is a really stupid question.

 

I'm sort of just flailing about here and I've done so little scripting before that I just have no idea.  I'd like to eliminate some intermediate steps for the user (viz. select all the objects, expand everything in surfaces tab, click everything in surfaces tab, then apply the shader).

Post edited by SickleYield on

Comments

  • evilded777evilded777 Posts: 2,464

    Pretty sure, theoretically at least, that this is possible.

    Starting from the scene object, create an array of objects in the scene, loop through that getting all the materials on each object, etc.

    I was working on something similar, once.

  • nonesuch00nonesuch00 Posts: 18,120
    edited July 2016

    This is something I want to work on as well but realistically it is not going to happen for me to try until winter. Would be fun though to figure it out.

    Post edited by nonesuch00 on
  • Mustakettu85Mustakettu85 Posts: 2,933
    edited July 2016

    Hi! I adjusted some of my code to cycle through all nodes and their surfaces (if they have any), and you can freely use this as a base for yours. It's licensed the same way as everything in the DAZ Script sample lib, parts of which it may be based on - https://creativecommons.org/licenses/by/3.0/

    The script itself automagically copies bump maps to displacements, but once you get the material, you can swap it altogether for something else, I believe. Here are the scripting docs in their current state, you can find methods and properties for a given class there: http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/object_index/start

    And these are official samples to adapt: http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/start

    Sorry I still haven't fixed the nomenclature to look professional, but you certainly can rename variables to make it all look proper =)

    // DAZ Studio version 3.0  filetype DAZ Script    // Declare local variablesvar i, j, k, numI, numIMat, numIShad;var oNode;var myTempObj;var myTempShape;var myWorkMat;var myWorkProperty;var myBumpMap;var myDispStr; // Get the total number of scene nodesnumI = Scene.getNumNodes();// Iterate over each nodefor( i = 0; i < numI; i++ ){// Get the current nodeoNode = Scene.getNode( i );myTempObj = oNode.getObject();// does it have geometry?if (myTempObj != null) {myTempShape = myTempObj.getCurrentShape();// now digging for the materials!!numIMat = myTempShape.getNumMaterials();// iterating aaaagain	for( j = 0; j < numIMat; j++ ){		myWorkMat = myTempShape.getMaterial( j );// Here comes the name of the channel you copy from		myWorkProperty = myWorkMat.findProperty( "Bump Strength" );							if( myWorkProperty && myWorkProperty.className() == "DzFloatProperty" ) {							myBumpMap = myWorkProperty.getMapValue();							}		// Here comes the name you copy to		myDispStr = myWorkMat.findProperty( "Displacement Strength" );							if( myDispStr && myDispStr.className() == "DzFloatProperty" ) {							myDispStr.setMap(myBumpMap);							}						}					}//the second iteration is ended above}//the first iteration is ended above

    And here is the code that cycles through selected objects only: www.daz3d.com/forums/discussion/76708/script-to-attach-the-base-color-image-node-to-the-top-coat-color-node

    Post edited by Mustakettu85 on
  • nonesuch00nonesuch00 Posts: 18,120

    thanks Mustakettu85

  • SickleYieldSickleYield Posts: 7,634

    Thank you, that's very generous!

  • Mustakettu85Mustakettu85 Posts: 2,933

    You're most welcome =)

  • Mustakettu85Mustakettu85 Posts: 2,933

    Oh, sorry, just noticed there were two older calls that only dug for selected materials. Check the post above again, all fixed now, no selections needed whatsoever.

  • nonesuch00nonesuch00 Posts: 18,120

    Thanks again.

  • SickleYieldSickleYield Posts: 7,634

    Another stupid question!

    I want to change everything in the scene from one shader base type (studio/material/uber_iray) to (studio/material/daz_shader).  So rather than finding one channel in a material and changing it to the value of another material, I want to change a known, set characteristic of everything in the scene to a different known, set characteristic.

    I've been trying to do this by swapping things out from "Map" to "Type," and having the findproperty be "definition," but that's not working, so obviously I'm doing something wrong.  Do I need to instead use DzStringProperty here somehow?  I did change the variable names My3DLShader and MyIrayShader up top so I don't think it's that.

    // Here comes the name of the channel you copy from

            myWorkProperty = myWorkMat.findProperty( "definition" );
                                if( myWorkProperty && myWorkProperty.className() == "studio/material/daz_shader" ) {
                                my3DLShader = myWorkProperty.getTypeValue();
                                }
            
    // Here comes the name you copy to

            myIrayShader = myWorkMat.findProperty( "definition" );
                                if( myIrayShader && myIrayShader.className() == "studio/material/uber_iray" ) {
                                myIrayShader.setType(my3DLShader);
                                }
                            }
                    


        }

     

  • Richard HaseltineRichard Haseltine Posts: 100,781

    Try going to File>Save as>Deprecated>Materials preset and then look at that - you need (as I recall) to create a new material with the sahder you are goign to use and only then edit its properties.

  • Mustakettu85Mustakettu85 Posts: 2,933

    Nothing stupid about your questions. It's all normal when you start working with DS scripting and its wonderfully concise documentation =)

    I'm not on the computer right now so can't debug for real, but what looks incorrect is looking for the  "studio/material/daz_shader" as a class name. Class names are those "DzSomething" strings.

    The 4.x scripting docs is still missing the DzShape and DzMaterial info, but I found the 3.x documentation archive "DAZ Script API.zip" here:

    http://docs.daz3d.com/doku.php/public/software/dazstudio/3/start

    It still works.

    In the DzMaterial there was a method IIRC to swap out the definition files on the fly (they would be the *Def.ds* scripts found inside the scripts subfolder in the DS installation folder), but there may be an easier way if you look at this example (the first script):

    http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/remote_operation/sub_script/start

    If you save out a .dsa "deprecated" preset as Richard says (which is a fully fledged DS script), you should be able to call it on the myWorkMat. And then this preset/script should take care of finding the correct interface scripts.

     

  • evilded777evilded777 Posts: 2,464

    I'm starting to be happy I didn't tackle this project.

    Good luck, SY. I think you have a hard row to hoe.

  • Richard HaseltineRichard Haseltine Posts: 100,781

    Nothing stupid about your questions. It's all normal when you start working with DS scripting and its wonderfully concise documentation =)

    I'm not on the computer right now so can't debug for real, but what looks incorrect is looking for the  "studio/material/daz_shader" as a class name. Class names are those "DzSomething" strings.

    The 4.x scripting docs is still missing the DzShape and DzMaterial info, but I found the 3.x documentation archive "DAZ Script API.zip" here:

    http://docs.daz3d.com/doku.php/public/software/dazstudio/3/start

    It still works.

    In the DzMaterial there was a method IIRC to swap out the definition files on the fly (they would be the *Def.ds* scripts found inside the scripts subfolder in the DS installation folder), but there may be an easier way if you look at this example (the first script):

    http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/remote_operation/sub_script/start

    If you save out a .dsa "deprecated" preset as Richard says (which is a fully fledged DS script), you should be able to call it on the myWorkMat. And then this preset/script should take care of finding the correct interface scripts.

    Do please keep in mind that the scripting docs (and samples) are something Rob works on in his own time. We would of course all like to have complete documentation, but we owe a considerable debt for what Rob is able to get out and should try to remember that when commenting.

  • Mustakettu85Mustakettu85 Posts: 2,933
    edited July 2016

    Okay gang, I figured out the "hard" part for everyone =)

    It's the easier way out because I'm using a "real" DzRSLMaterial to swap to, not the built-in DS Default that has no external support files.

    This example swaps Iray Uber bases (only them!) in the scene for the DAZ Plastic shader. We also copy part of the code from its definition file which is licensed the same as DAZ Script docs.

    I suggest UberSurface for the final destination, though. It's so much better than all those little DAZ shaders. Its own definition file is encrypted, but it shouldn't be difficult to just replace the calls in the definition provided. 

    I didn't spell out all the copy values, only the diffuse map and colour. Copy snippets are all extendable via copy/paste and modifications. The "work" variables just get new values.

    The comments should provide more info, but if something isn't clear, I'll help.

    // DAZ Studio version 3.0  filetype DAZ Script    // Declare local variablesvar i, j, k, numI, numIMat, numIShad;var oNode;var myTempObj;var myTempShape;var myWorkMat;var myWorkProperty;var myNewWorkProperty;var myWorkMap;var myWorkColour; // Get the total number of selected nodesnumI = Scene.getNumNodes();// Iterate over each nodefor( i = 0; i < numI; i++ ){// Get the current nodeoNode = Scene.getNode( i );myTempObj = oNode.getObject();// does it have geometry?if (myTempObj != null) {// now digging for the materials!!myTempShape = myTempObj.getCurrentShape();numIMat = myTempShape.getNumMaterials();// iterating aaaagain	for( j = 0; j < numIMat; j++ ){		myWorkMat = myTempShape.getMaterial( j );		var myClassIs;		myClassIs = myWorkMat.className();//		MessageBox.information( myClassIs, "MyScript", "&OK" );// So we're only swapping the Iray Uber materials for the basic DAZ Plastic shader for 3Delightif (myClassIs == "DzUberIrayMaterial") {	var myNewMat = new DzShaderMaterial;// This is a standard definition file, only edited!// We use our new material name instead of// the rendertime "Material" predefined variable// These shaders are like the DS default built-in material// but separated into "plastic", "toon plastic" etc// They are in the "Shader Presets - DS Defaults" content folder// AND// Their definitions to copy from// are in the "\scripts\support\DAZ\shaderDefinitions\surface\" folder// underneath the DS installation path// Don't copy everything, only these lines!// Change "Material" to "myNewMat" everywheremyNewMat.setMaterialName( "DAZ Studio Plastic" );// Beauty PassoShader = new DzRSLShader;myNewMat.addShader( oShader );oShader.setShaderType( DzRSLShader.Surface );oShader.setShaderFile( "dzplastic" );oShader.setDefinitionFile( "support/DAZ/shaderDefinitions/surface/dzdefaultspecSurf.dsa" );oShader.setRenderTimeFile( "support/DAZ/rendertime/surface/dzDefaultAttribs.dsa" );// Shadow PassoShader = new DzRSLShader;myNewMat.addShader( oShader );oShader.setShaderType( DzRSLShader.Surface );oShader.setShaderFile( "dzdefaultshadow" );oShader.setDefinitionFile( "support/DAZ/shaderDefinitions/surface/dzdefaultshadowSurf.dsa" );oShader.setRenderTimeFile( "support/DAZ/rendertime/surface/dzDefaultShadowAttribs.dsa" );oShader.setOnlyInShadowPass( true );// Displacement/BumpoShader = new DzRSLShader;myNewMat.addShader( oShader );oShader.setShaderType( DzRSLShader.Displacement );oShader.setShaderFile( "dzdisplace" );oShader.setDefinitionFile( "support/DAZ/shaderDefinitions/displacement/dzdisplaceSurf.dsa" );oShader.setRenderTimeFile( "support/DAZ/rendertime/displacement/dzDefaultDisplaceAttribs.dsa" );oShader.setActiveInShadowPass( true );// Here we have ended the definitions// // Now we can copy the Iray Uber property values// that are meaningful for the basic DS shaders// The property names are easiest to look up// by clicking the little gear and then "Parameter settings"// We need NAMES not labels// Let's get rid of the class type check as wellmyWorkProperty = myWorkMat.findProperty( "Diffuse Color" );							if( myWorkProperty ) {							myWorkMap = myWorkProperty.getMapValue();							// change getColorValue() to getBoolValue() for on/off switches// or to getValue() for float/integer numeric sliders 																					myWorkColour = myWorkProperty.getColorValue();							}							myNewWorkProperty = myNewMat.findProperty( "Diffuse Color" );							if( myNewWorkProperty ) {							myNewWorkProperty.setMap(myWorkMap);							// same here, but for setColorValue() 																				myNewWorkProperty.setColorValue(myWorkColour);							}// Now we are ready for the final swap!myTempShape.replaceMaterial (myWorkMat, myNewMat);		}						}					}//the second iteration is ended above}//the first iteration is ended above

    Hope it helps.

    Post edited by Mustakettu85 on
  • Mustakettu85Mustakettu85 Posts: 2,933

    Do please keep in mind that the scripting docs (and samples) are something Rob works on in his own time. We would of course all like to have complete documentation, but we owe a considerable debt for what Rob is able to get out and should try to remember that when commenting.

    I understand. I have no problem with Rob, but I do wish there were more DAZ employees who could help with development and documentation.

  • Mustakettu85Mustakettu85 Posts: 2,933
    edited July 2016

    ...and then I thought, "if it's built-in, maybe it doesn't even _need_ external interface scripts?.."

    And it doesn't =)

    So for swapping to the full, lighting-model-switch-enabled DS Default material, the script is even simpler.

    But you need to watch out for the DzDefaultMaterial different behaviour: it is not built property-by-property, but rather as a whole, so when you copy values to it, you use the methods of the DzDefaultMaterial and not individual property methods. Thankfully these are all (save for maybe the previously non-exposed "skin"-model related params like sheen) documented in the DS3.x scripting doc zip, and haven't changed.

    // DAZ Studio version 3.0  filetype DAZ Script    // Declare local variablesvar i, j, k, numI, numIMat, numIShad;var oNode;var myTempObj;var myTempShape;var myWorkMat;var myWorkProperty;var myNewWorkProperty;var myWorkMap;var myWorkColour; // Get the total number of selected nodesnumI = Scene.getNumNodes();// Iterate over each nodefor( i = 0; i < numI; i++ ){// Get the current nodeoNode = Scene.getNode( i );myTempObj = oNode.getObject();// does it have geometry?if (myTempObj != null) {// now digging for the materials!!myTempShape = myTempObj.getCurrentShape();numIMat = myTempShape.getNumMaterials();// iterating aaaagain	for( j = 0; j < numIMat; j++ ){		myWorkMat = myTempShape.getMaterial( j );		var myClassIs;		myClassIs = myWorkMat.className();//		MessageBox.information( myClassIs, "MyScript", "&OK" );// So we're only swapping the Iray Uber materials for the basic DS Default shader for 3Delightif (myClassIs == "DzUberIrayMaterial") {	var myNewMat = new DzDefaultMaterial;// Now we can copy the Iray Uber property values// that are meaningful for the basic DS shaders// The property names are easiest to look up// by clicking the little gear and then "Parameter settings"// We need NAMES not labels// Let's get rid of the class type check as wellmyWorkProperty = myWorkMat.findProperty( "Diffuse Color" );							if( myWorkProperty ) {							myWorkMap = myWorkProperty.getMapValue();							// change getColorValue() to getBoolValue() for on/off switches// or to getValue() for float/integer numeric sliders 																					myWorkColour = myWorkProperty.getColorValue();							}							myNewWorkProperty = myNewMat.findProperty( "Diffuse Color" );							if( myNewWorkProperty ) {// for setting, we use myNewMat - DzDefaultMaterial - methods, not those of its properties! // The "new" property check might even be redundant here							myNewMat.setColorMap(myWorkMap);																									myNewMat.setDiffuseColor(myWorkColour);							}// Now we are ready for the final swap!myTempShape.replaceMaterial (myWorkMat, myNewMat);		}						}					}}

     

    Post edited by Mustakettu85 on
Sign In or Register to comment.