Script to attach the Base-Color Image Node to the Top-Coat-Color Node

Hello,

I'm sorry, I'm a complete beginner concerning scripting and haven't done anything like that before, but now I really need a solution to quickly attach the Base-Color-Image-Node to the Top-Coat-Color-Node of a material zone. The prop(s) I want to use this method on have hundreds of material zones and it would take ages to do it manually :(

Thank you in advantage!

Comments

  • Richard HaseltineRichard Haseltine Posts: 100,871

    You mean to copy the value from one to the other? Does it matter which is th source and which the target? You could, without scruipting, set up one surface, save a Shader Preset with just the Base Colour and Top Coat Color, then select all surfaces and aply the preset to that.

  • Nope :) I need to attach an image which is on the base-color-node to the top-coat-color-node. Unfortunately all Material-Zones have different images :(

    basecolortotopcoatcolor.PNG
    457 x 935 - 51K
  • mjc1016mjc1016 Posts: 15,001

    Do you want to copy the map or move it?

  • I need to copy it :-)

  • Mustakettu85Mustakettu85 Posts: 2,933

    Hi 321nimb, you could use this code to make a script that would copy maps for selected objects and selected surfaces, but you will need to replace the property names with the names of the channels you want to copy from/to.

    Sorry for the messy nomenclature, I wrote it a while ago for myself =)

    // 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 number of selected nodesnumI = Scene.getNumSelectedNodes();// Iterate over each selected nodefor( i = 0; i < numI; i++ ){// Get the selected nodeoNode = Scene.getSelectedNode( i );// now digging for the materials!!myTempObj = oNode.getObject();myTempShape = myTempObj.getCurrentShape();numIMat = myTempShape.getNumSelectedMaterials();// iterating aaaagain	for( j = 0; j < numIMat; j++ ){		myWorkMat = myTempShape.getSelectedMaterial( 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

    You may also find this thread interesting (copying/setting colours)

    www.daz3d.com/forums/discussion/65526/copying-modifying-surface-color-values

  • Hello,

    thanks for the script. Maybe it's because I'm a complete beginner and barely figured out how to create a custom action for the script - but I'm completely overchallenged :( It doesn't work...

    I replaced the term
    myWorkProperty = myWorkMat.findProperty( "Bump Strength" );

    with
    myWorkProperty = myWorkMat.findProperty( "Base Color" );

    and
    myDispStr = myWorkMat.findProperty( "Displacement Strength" );

    with
    myDispStr = myWorkMat.findProperty( "Top Coat Color" );

     

    but when I click on the custom action, nothing happens :(
     

  • Richard HaseltineRichard Haseltine Posts: 100,871

    Try pasting it into the Script IDE pane and clicking the Execute button. You do need to have an object and surfaces on the object selected.

  • mjc1016mjc1016 Posts: 15,001
    edited April 2016

    And the proper names...

    Most of the time the name and label match, but sometimes they don't.  So you may need to look in the Parameter Settings (little gear icon in the upper right corner of each parameter) for each to make sure that the name is what you think it is.

    Post edited by mjc1016 on
  • Nope, nothing worked :( even though I found out that "Base Color" is in fact a disguised "Diffuse Color"...

  • Mustakettu85Mustakettu85 Posts: 2,933

    Hmm, then it most likely means the developers kept the old structure for Iray presets as well, where the "base" map is considered to be the default colour map of the whole mesh.

    Try this?

     

    // DAZ Studio version 3.0  filetype DAZ Script// Hello world, this is Kettu and I am writing a lengthy script for a simple action// That's DS for you =)    // Declare local variablesvar i, j, k, numI, numIMat, numIShad;var oNode;var myTempObj;var myTempShape;var myWorkMat;var mySSSMap;var myDiffMap; // Get the number of selected nodesnumI = Scene.getNumSelectedNodes();// Iterate over each selected nodefor( i = 0; i < numI; i++ ){// Get the selected nodeoNode = Scene.getSelectedNode( i );// now digging for the materials!!myTempObj = oNode.getObject();myTempShape = myTempObj.getCurrentShape();numIMat = myTempShape.getNumSelectedMaterials();// iterating aaaagain	for( j = 0; j < numIMat; j++ ){		myWorkMat = myTempShape.getSelectedMaterial( j );		mySSSMap = myWorkMat.getColorMap();		myDiffMap = myWorkMat.findProperty( "colourBaseDiffuse" );							if( myDiffMap && myDiffMap.className() == "DzColorProperty" ) {							myDiffMap.setMap(mySSSMap);							}					}//the second iteration is ended above}//the first iteration is ended above
  • OK, I'm bumping this because it is the best lead I have right now. Disclaimer, my scripting skills are about (but not quite) as good as my modeling skills.

    I want to do the exact thing as the OP, copy the map in the base color to the translucency color and top coat color. Here is what I have done and what happens.

    1. Copy the first bit of code generously provided by Kettu into the Script TDE window, hit execute, and as expected the bump map copies to the displacement map. OK, that is a result, and more information than I started with this morning.

    2. Next, change the 
    myWorkProperty = myWorkMat.findProperty( "Bump Strength" );

    with
    myWorkProperty = myWorkMat.findProperty( "Diffuse Color" );

    and
    myDispStr = myWorkMat.findProperty( "Displacement Strength" );

    with
    myDispStr = myWorkMat.findProperty( "Top Coat Color" );

    as described above by 321nimb, hit the execute button and nothing happens. Downer.

    3. Troubleshooting - trial and error shows me I can copy the image from and/or to any parameter with a slider attached, but not one with a color attached. Example:Translucency Weight to Glossy Reflectivity is not a problem. Those are image maps with value sliders attached. On parameters that have a color control box instead of a value slider, the script does nothing.

    4. Speculation that the DzFloatProperty is not the correct variable, so I substitute in DzColorProperty with equally zero result.

    5. Conclusion - I have hit a brick wall. (I could have built a procedural shader in shader mixer to texture the brick wall, and turn it into a fur blanket, but I can't figure out how to script the copying of a simple image map. Heh)

    Please, any help here would be much appreciated..

    cheers!

  • Richard HaseltineRichard Haseltine Posts: 100,871
    edited September 2017

    Make sure you are using the right name, by clicking the gear icon on the slider and copying the name across.

    You could also, as a trouble-shooting step, try

    print( myWorkProperty.className() );

    instead of the if statement, to see exactly what object type you should be dealing with, and then use that in the if statement.

    Another option, instead of checking the exact className (which is prone to break) would be to use

    myWorkProperty.className().inherits( "DzNumericProperty" )

    to make sure it was a property, then

    myWorkProperty.isMappable()

    and then

    myWorkProperty.isMapped()

    to make sure that the property takes a map or that it has one assigned. So something like

    		myWorkProperty = myWorkMat.findProperty( "Bump Strength" );							if( myWorkProperty && myWorkProperty.inherits( "DzNumericProperty" ) &&  myWorkProperty .isMapped() ) {							myBumpMap = myWorkProperty.getMapValue();							}

    to get the map, and then replace isMapped with isMappable for the properties you want to place the map on.

    Post edited by Richard Haseltine on
  • jag11jag11 Posts: 885

    Try this, this copies "Diffuse Color" property to "Top Coat Color"property from the Face material(Surface):

    HTH

    Saludos

    // DAZ Studio version 4.9.4.115 filetype DAZ Script(function() {	function collectMaterialsFromShape(shape) {		var materials = [];		for(var i = 0; i < shape.getNumMaterials(); i++) {			materials.push(m = shape.getMaterial(i));			materials[m.name] = m;		}				return materials;	}		function CopyColorImage(material, srcPropertyName, targetPropertyName) {		var textureFilename = null;		var texture = null;		var property = material.findProperty(srcPropertyName);		if (null != property) {			if (property.isMapped()) {				texture = property.getMapValue();				/* get current texture path */				textureFilename = texture.getFilename();			}						/* set texture map */			material.findProperty(targetPropertyName).setMap(textureFilename); /* <-- set your new difusse map" */		}	}	var node = null;	var shellObject = null;	var shape = null;	var mat = null;	var property = null;	var materials = null;		/* get selected figure/prop/object/whatever */	if(!(node = Scene.getPrimarySelection())){		print("Great! nothing to do.");		 return;	 };	 	shellObject = node.getObject();	shape = shellObject.getCurrentShape();	materials = collectMaterialsFromShape(shape);		CopyColorImage(materials.Face, "Diffuse Color", "Top Coat Color");})();

     

  • DestinysGardenDestinysGarden Posts: 2,550
    edited September 2017

    Richard, you are (not wanting to say god among men) a lion among tiny ginger tabbies. Thanks ever so for eternal willingness to help. I must confess though that I'm not sure what to do with your code. Baby steps please and don't be afraid to dumb it way down. Script Screen1 attached below is my attempt at pasting in the code as suggested. Nothing happened. I definately did copy/paste the parameter name, and not the label, from the properties pop-up. That was good tip to eliminate one possible place for failure.

    Jag, your bit of code is really pretty, streamlined and elegant. I'm getting an error on line 17, as shown in script screen 2 attached below. Any thoughts?

    I really do apprecaite all your attempts to help out with this. We must conquer or perish in the attempt!

    script screen1.PNG
    1883 x 951 - 265K
    script screen2.PNG
    1890 x 983 - 279K
    Post edited by DestinysGarden on
  • jag11jag11 Posts: 885

    The error is produced because the material requested was not found, in the original code it was material.Face.

    On the sample code I assumed you were using a Genesis Figure, which has a very specific set of material names, but I see you are working on a sphere, which has just one material name, "Default".

    Try this:

    Locate this line CopyColorImage(materials.Face, "Diffuse Color", "Top Coat Color");

    And replace materials.Face to materials.Default

    Now, keep this list handy, as it is the valid Iray property names:

    Diffuse ColorDiffuse StrengthGlossinessSpecular ColorSpecular StrengthMultiply Specular Through OpacityAmbient ColorAmbient StrengthOpacity StrengthBump StrengthNegative BumpPositive BumpDisplacement StrengthMinimum DisplacementMaximum DisplacementNormal MapReflection ColorReflection StrengthRefraction ColorRefraction StrengthIndex of RefractionSheen ColorScatter ColorThicknessHorizontal TilesHorizontal OffsetVertical TilesVertical OffsetLighting ModelTagsUV SetSmooth OnSmooth AngleRender PriorityPropagate PriorityFollow Blend
  • DestinysGardenDestinysGarden Posts: 2,550
    edited September 2017

    Ah, great explanation Jag. The end goal was to have a helper script for a set of shader presets that would work on any object. The shader presets turn on the translucency and top coat, but if no color or image map is previously assigned, the rendered result is white. The work around is to give instructions to have the end user manually apply the base color map to those channels, but I was hoping to make it more user friendly.

    Is that not going to be possible? I won't be able to know in advance the material name that the end user will be using it with.

    Well that definately did work by changing Face to Default, so I'm much farther along than I was an hour ago. I really do appreciate your help, and I'm learning.

    Post edited by DestinysGarden on
  • GolaMGolaM Posts: 109
    edited September 2017

    This code fragment does what you need:

    // Here comes the name you copy tomyTopCoatColor = myWorkMat.findProperty( "Top Coat Color" );// this makes sure the Top Coat is a DzFloatColorProperty too.if( myTopCoatColor && myTopCoatColor.className() == "DzFloatColorProperty" ) {    //To set the map we have to set the filename, no the temp map object!    myTopCoatColor.setMap(myTempMap.getFilename());}

     

    For some reason the getMap returns an object, while setMap wants a file path.

    Post edited by GolaM on
  • DestinysGardenDestinysGarden Posts: 2,550
    edited September 2017

    Yes! GolaM for the win. The missing part of the puzzle was that we needed to change the DzFloatProperty to DzFloatColorProperty. Modifying Kettu's original script as thus

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

    myWorkProperty = myWorkMat.findProperty( "Diffuse Color" );

    if( myWorkProperty && myWorkProperty.className() == "DzFloatColorProperty" ) {

    myBumpMap = myWorkProperty.getMapValue();

    }

     

    // Here comes the name you copy to

     

    myDispStr = myWorkMat.findProperty( "Top Coat Color" );

    if( myDispStr && myDispStr.className() == "DzFloatColorProperty" ) {

    myDispStr.setMap(myBumpMap);

    }

    should solve the OP's original question.

    Many, many thanks to those who responded.

    Post edited by DestinysGarden on
  • jag11jag11 Posts: 885

    This also does what you requires, and it tests if weight maps are set:

    	materials.forEach(function(currentMaterial){		var p = currentMaterial.findProperty("Translucency Weight");		var value = p.getValue();		if(value > 0) {			CopyColorImage(currentMaterial, "Diffuse Color", "Translucency Color");		}		p = currentMaterial.findProperty("Top Coat Weight");		value = p.getValue()		if(value > 0) {			CopyColorImage(currentMaterial, "Diffuse Color", "Top Coat Color");		}	});

     

  • Thank you Jag. I see what you did there with the currentMaterial instead of specifing the material. Very elegant indeed.

    So, two solutions to the problem, which is fabulous.

Sign In or Register to comment.