How to access DzOpacityManip (How to change opacity on LIE Layers)

parrotdolphinparrotdolphin Posts: 110

I have a shader preset that uses the Layered Image Editor. I am trying to make a script that will alter the opacity setting on one of the layers. I have been looking at the Daz Script 2 doc and at lots of script examples, but I feel like I'm missing the big picture. I just don't understand how I get to the layer so I can change the opacity. If anyone has any advice I would really appreciate it.

Post edited by parrotdolphin on

Comments

  • EsemwyEsemwy Posts: 577
    edited October 2015

    There's some general good info in programming the LIE here. To the point of your question, it looks like image layers have an opacity property as opposed to a setOpacity() method. 

    // Create a new layervar oLayer = oLayeredTexture.createLayer( sBaseLayerName );// Set the absolute path of the image for the layeroLayer.imageFile = sBaseLayerPath;// Set the layer opacityoLayer.opacity = 0.5;

    I only have a semi-working example right now, or I'd post the entire thing. Aparently if you createLayeredTexture from scratch instead of a file, it defaults to a size of -1 x  -1. I did verify that it sets the opacity of the layer, though.

    Note:

    Prior to 4.6.2.23 you needed to do something like the following (guessing here):

    oLayer.addManapulator(DzOpacityManip(0.5));

    I don't have any way to test it though.

    Post edited by Esemwy on
  • EsemwyEsemwy Posts: 577
    edited October 2015

    OK, this does what I expect:

    function dumpBehavior(obj) {    var aPropertyNames = Object.getOwnPropertyNames(obj).sort();    for (var i = 0; i < aPropertyNames.length; i++) {        print(aPropertyNames[i].toString());    }}function getFirstMaterial() {    var oNode = Scene.getPrimarySelection();    if ( ! oNode ) break;    var oObj = oNode.getObject();    if ( ! oObj ) break;    var nShapes = oObj.getNumShapes();    for (var i = 0; i < nShapes; i++) {        oShape = oObj.getShape(i);        if (! oShape ) continue;        var nMats = oShape.getNumMaterials();        for (var j = 0; j < nMats; j++) {            var oMat = oShape.getMaterial(j);            if ( ! oMat ) continue;            if ( ! oMat.isSelected() )  continue;            var oTexture = oMat.getColorMap();            if ( ! oTexture ) continue;            return oMat;        }    }}        var oImageMgr = App.getImageMgr();// Get a unique name for the imagevar sTextureName = oImageMgr.getUniqueImageName( "My Layered Texture" );var sBaseFile = "/Users/esemwy/Desktop/horizontal.jpg";var sLayerFile = "/Users/esemwy/Desktop/diagonal.jpg";var oBaseFile = new DzFileInfo( sBaseFile );var oLayerFile = new DzFileInfo( sLayerFile );// Define the names of the layersvar sBaseName  = oBaseFile.baseName();var sLayerName  = oLayerFile.baseName();// Create a layered texturevar oLayeredTexture = oImageMgr.createLayeredTexture( sTextureName );oLayeredTexture.size = Size(500,500);var oBase = oLayeredTexture.createLayer( sBaseName );oBase.imageFile = sBaseFile;var oLayer = oLayeredTexture.createLayer( sLayerName );oLayer.imageFile = sLayerFile;oLayer.opacity = 0.5;var oMat = getFirstMaterial();oMat.setColorMap(oLayeredTexture);//dumpBehavior(oLayeredTexture);

    The dumpBehavior function is how I find all the things that DAZ doesn't document.

    The two images were just gradients that I created in photoshop for testing. They're included here for reference.

    diagonal.jpg
    500 x 500 - 60K
    horizontal.jpg
    500 x 500 - 77K
    Post edited by Esemwy on
  • Thanks so much Esemwy! I'm going to see how far I can get with your great example. I'm not creating a layered image with my script, I just want it to change the opacity on an existing layer for a selected surface. Hopefully, using dumpBehavior will be enlightening. I need all the enlightenment I can get. laugh

  • EsemwyEsemwy Posts: 577
    edited October 2015

    Never mind. This was an erroneous response.

    Post edited by Esemwy on
  • EsemwyEsemwy Posts: 577
    edited October 2015

    Hmmm.... 

    var oMat = getFirstMaterial();var oImageMgr = App.getImageMgr();var sFile = oMat.getColorMap().getFilename();var oLayeredImage = DzLayeredImage();oImageMgr.loadLayeredImage(sFile, oLayeredImage);dumpBehavior(oLayeredImage);

    You can then getLayer(int), etc on oLayeredImage.

    Edit:

    P.S. Yes, I'm a bit obsessive when it comes to code.

    Post edited by Esemwy on
  • I managed to get the number of layers and change the opacity on the layer I wanted. I did it a bit differently than your latest post. Now I just want to make sure I have the right name on the layer before I change it. So, I'm working on that. You have helped me so much. I've spent hours and hours on this script and without your example, I got nowhere.  

  • EsemwyEsemwy Posts: 577

    I'm glad I could be of help. 

  • When I have my Viewport set to NVIDIA Iray and I run my script to change opacity on a layer, nothing changes. If I set the Viewport to Texture Shaded then I see the change.

    When I have my Viewport set to NVIDIA Iray and I go directly into the Layered Image Editor and change the opacity then I see the change.

    I looked at the log and noted a difference:

    Direct lie update:

    Loaded image AC08.jpg

    Loaded image F1.jpg

    Loaded image G03.jpg

    Iray INFO - module:category(IMAGE:IO): 1.0 IMAGE io info : Loading image "C:/Users/Janet/AppData/Roaming/DAZ 3D/Studio4/temp/d16.png", pixel type "Rgba", 1024x1024x1 pixels, 1 miplevel.

    Iray INFO - module:category(IRAY:RENDER): 1.0 IRAY rend info : Updating materials.

     

    Update via script:

    Loaded image AC08.jpg

    Loaded image F1.jpg

    Loaded image G03.jpg

    Iray INFO - module:category(IRAY:RENDER): 1.0 IRAY rend info : Updating materials.

     

    So, then I thought maybe I have to save the temp layered image. Here is my script so far, but the temp image is never saved and the Iray Veiwport still isn't changing. Any idea what I could do? Note that you'd need a Layered Image with 3 layers to run it.

    var DSVersion = new Number( App.versionString );var oImageMgr = App.getImageMgr();var oFileIO = App.getFileIOPresetMgr();var nodes = Scene.getSelectedNodeList();var n = nodes.length;setopacity();function setopacity(){	for( var i = 0; i < n; i++ )	{		var node = nodes[i];		if( DSVersion >= 4.8 ) 		{			if( node.inherits( "DzBone" ) )			{				node = node.getSkeleton();			}		}			var obj = node.getObject();				if( obj )		{			var oShp = obj.getCurrentShape();						if( oShp )			{				var nMats = oShp.getNumSelectedMaterials();									for( var j = 0; j < nMats; j++ )				{					var oMat = oShp.getSelectedMaterial( j );					var oTexture = oMat.getColorMap();					if ( oTexture )					{						var onumLayers = oTexture.getNumLayers();						if ( onumLayers == 3 )						{							var oLayer1 = oTexture.getLayer(1);							oLayer1.opacity = 0.4;							oLayer1.dataChanged();							oLayer1.needsRefresh();							oLayer1.needsImageRefresh();							var ofile = oTexture.getFilename();							print( "temp file name: ",ofile);							oTexture.refeshLayeredTexture();							oTexture.setTextureToRefresh();  // updates base color's little image box							var oLayeredImg = DzLayeredImage(oTexture);							oImageMgr.saveLayeredImage(ofile, oLayeredImg);  //image not updated							//oImageMgr.saveImage(ofile, oTexture);       //image not updated						}					}				}			}		}		}}

     

  • EsemwyEsemwy Posts: 577

    My workstation is tied up with a render right now, but I'll try to take a look at it in the morning. 

  • That would be wonderful if you have time. Thanks!

  • EsemwyEsemwy Posts: 577

    OK, I think I see what's going on. The preview issue seems almost, but not quite, opposite from what you describe if you apply the texture to a plane instead of say a cube.

    It appears as if Iray, for whatever reason, caches a bit more fervently than the textured shader. If the LIE is allowed to create a new layered image, all is well, if not, Iray stays with the cached texture regardless of what has been written to the file. In other words, all the work you're doing trying to refresh the image cache is being ignored by Iray. I believe if you re-write your script to save the layered image to a new file and then swap the map, it will behave in both. It's ugly, but this is what the LIE does nornally, and this is probably the reason.

  • parrotdolphinparrotdolphin Posts: 110
    edited October 2015
    Esemwy said:

    OK, I think I see what's going on. The preview issue seems almost, but not quite, opposite from what you describe if you apply the texture to a plane instead of say a cube.

    It appears as if Iray, for whatever reason, caches a bit more fervently than the textured shader. If the LIE is allowed to create a new layered image, all is well, if not, Iray stays with the cached texture regardless of what has been written to the file. In other words, all the work you're doing trying to refresh the image cache is being ignored by Iray. I believe if you re-write your script to save the layered image to a new file and then swap the map, it will behave in both. It's ugly, but this is what the LIE does nornally, and this is probably the reason.

    Thanks Esemwy. I am trying your suggestion. I tried this code below but it doesn't work. I get a .dsi file but no .png

    var oLayer1 = oTexture.getLayer(1);oLayer1.opacity = 0.4;oLayer1.dataChanged();oLayer1.needsRefresh();oLayer1.needsImageRefresh();oTexture.refeshLayeredTexture();var ofile = oTexture.getFilename();print( "temp file name: ",ofile);oTexture.refeshLayeredTexture();oTexture.setTextureToRefresh();  // updates base color's little image boxoMat.setColorMap(oTexture);var ofile2 = new String("C:/Users/Janet/AppData/Roaming/DAZ 3D/Studio4/temp/pd-001.png");print( "temp file name2: ",ofile2);var oLayeredImg = new DzLayeredImage(oTexture);oImageMgr.saveLayeredImage(ofile2, oLayeredImg);  //image not updated, saves a pd-001.dsi file insteadoImageMgr.loadLayeredImage(ofile2, oLayeredImg);

    The pd-001.dsi file is text which says:

    <DAZStudioLayeredImage> <Version>1.1</Version> <Layers/></DAZStudioLayeredImage>

    I suspect the line, var oLayeredImg = new DzLayeredImage(oTexture); is wrong. But I'm not sure how to make it right.

     

    Post edited by parrotdolphin on
  • EsemwyEsemwy Posts: 577
    edited October 2015

    I'm not having much luck either. Perhaps we can create a new layered texture, then copy the layers, that would do the trick. I've not quite figured that out yet, though.

    I think I'll take a break from it for a while, maybe render something, and the answer may come to me.

    Post edited by Esemwy on
  • Esemwy said:

    I'm not having much luck either. Perhaps we can create a new layered texture, then copy the layers, that would do the trick. I've not quite figured that out yet, though.

    I think I'll take a break from it for a while, maybe render something, and the answer may come to me.

     

    I was thinking that might work too. I will give it a shot and post back here when it's working or I get stuck again. Thanks again. smiley

  • Small miracle... I think I'm actually getting somewhere. laugh It needs some more work though, so I'll post more later.

  • When the viewport is set to NVIDIA Iray, this code works if I only select one surface. If I select more than one surface and the viewport is set to NVIDIA Iray, the surfaces turn white. If I then go to Texture Shaded in the Viewport, I see the correct changes. Then if I go back to NVIDIA Iray in the Viewport, the surfaces now look correct. So, I don't know. Still missing something... but it's progress. Again, note that you need 3 layers to run this.

    var DSVersion = new Number( App.versionString );var oImageMgr = App.getImageMgr();var nodes = Scene.getSelectedNodeList();var n = nodes.length;setopacity();function setopacity(){	for( var i = 0; i < n; i++ )	{		var node = nodes[i];		if( DSVersion >= 4.8 ) 		{			if( node.inherits( "DzBone" ) )			{				node = node.getSkeleton();			}		}			var obj = node.getObject();				if( obj )		{			var oShp = obj.getCurrentShape();						if( oShp )			{				var nMats = oShp.getNumSelectedMaterials();									for( var j = 0; j < nMats; j++ )				{					var oMat = oShp.getSelectedMaterial( j );					var oTexture = oMat.getColorMap();					if ( oTexture )					{						var onumLayers = oTexture.getNumLayers();						if ( onumLayers == 3 )						{							// Get a unique name for the new layered image							var sTextureName = oImageMgr.getUniqueImageName( "New Texture" );							//print( "Unique Name = ",sTextureName );														// Get the existing layers 							var oLayer0 = oTexture.getLayer(0);							var oLayer1 = oTexture.getLayer(1);							var oLayer2 = oTexture.getLayer(2);														// Get the existing layer file names							var sLayer0File = oLayer0.imageFile;							var sLayer1File = oLayer1.imageFile;							var sLayer2File = oLayer2.imageFile;														// Define files for the new layers							var oLayer0File = new DzFileInfo( sLayer0File );							var oLayer1File = new DzFileInfo( sLayer1File );							var oLayer2File = new DzFileInfo( sLayer2File );														// Define the names for the new layers							var sLayerName0  = oLayer0File.baseName();							var sLayerName1  = oLayer1File.baseName();							var sLayerName2  = oLayer2File.baseName();														// Create a layered texture 							var oLayeredTexture = oImageMgr.createLayeredTexture( sTextureName );							oLayeredTexture.size = oTexture.size							var newLayer0 = oLayeredTexture.createLayer(sLayerName0);							var newLayer1 = oLayeredTexture.createLayer(sLayerName1);							var newLayer2 = oLayeredTexture.createLayer(sLayerName2);														// Copy from the old layers to the new layers							newLayer0.copyFrom(oLayer0);							newLayer1.copyFrom(oLayer1);							newLayer2.copyFrom(oLayer2);														// Change some opacities on the new layers 							newLayer1.opacity = .8;							newLayer2.opacity = .1;														// Update the texture with the new Layered Image 							oMat.setColorMap(oLayeredTexture);						}					}				}			}		}		}}

     

  • jag11jag11 Posts: 885

    Please. Try this, works for me.

                var layer = oTexture.getLayer(0);            layer.opacity = .08;            layer.needsRefresh();

    You can directly change opacity there's no need to copy it. layer.NeesRefresh() instructs renderer to refresh views.

    HTH

  • jag11jag11 Posts: 885

    Forget it, does not work! It does not refresh the resulting layered image. I'll keep investigating.

  • parrotdolphinparrotdolphin Posts: 110
    edited October 2015
    jag11 said:

    Please. Try this, works for me.

                var layer = oTexture.getLayer(0);            layer.opacity = .08;            layer.needsRefresh();

    You can directly change opacity there's no need to copy it. layer.NeesRefresh() instructs renderer to refresh views.

    HTH

    Thanks. Yes, that works when I use Texture Shaded in the Viewport, but not when I use NVIDIA Iray in the Viewport. I was trying to get it to update the texture for the Iray preview so that's why I resorted to copying the layers.

    Post edited by parrotdolphin on
  • jag11jag11 Posts: 885
    edited October 2015

    Ok, this is working.

    var DSVersion = new Number(App.versionString);var oImageMgr = App.getImageMgr();var nodes = Scene.getSelectedNodeList();var n = nodes.length;setOpacity();function cloneLayeredTexture(srcLayeredTexture) {    if (!srcLayeredTexture) {        return null;    }    var textureName = oImageMgr.getUniqueImageName(srcLayeredTexture.name);    var oNewLayeredTexture = oImageMgr.createLayeredTexture(textureName);    oNewLayeredTexture.size = new QSize(srcLayeredTexture.size);    var srcLayer = null;    var newLayer = null;    var numLayers = srcLayeredTexture.getNumLayers();    for (var i = 0; i < numLayers; i++) {        srcLayer = srcLayeredTexture.getLayer(i);        newLayer = oNewLayeredTexture.createLayer(srcLayer.imageFile);        newLayer.imageFile = srcLayer.imageFile;        newLayer.offset = new QPoint(srcLayer.offset.x, srcLayer.offset.y);    }    return oNewLayeredTexture;}function setOpacity() {    for (var i = 0; i < n; i++) {        var node = nodes[i];        if (DSVersion >= 4.8) {            if (node.inherits("DzBone")) {                node = node.getSkeleton();            }        }        var obj = node.getObject();        if (obj) {            var oShp = obj.getCurrentShape();            if (oShp) {                var nMats = oShp.getNumSelectedMaterials();                for (var j = 0; j < nMats; j++) {                    var oMat = oShp.getSelectedMaterial(j);                    var oTexture = cloneLayeredTexture(oMat.getColorMap());                    if (oTexture) {                        var numLayers = oTexture.getNumLayers();                        if (numLayers >= 3) {                            var oLayer1 = oTexture.getLayer(1);                            var oLayer2 = oTexture.getLayer(2);                            oLayer1.opacity = .8;                            oLayer2.opacity = .1;                            oMat.setColorMap(oTexture);                            MessageBox.information("Done", "Finished", "OK");                        }                    }                }            }        }    }}//# sourceMappingURL=pdsetopacity.js.map

     

    Post edited by jag11 on
  • EsemwyEsemwy Posts: 577
    edited October 2015

    Cool. I'm just now getting back to this. Nice to see it solved in my absence. One minor fix, though. Don't know why I didn't see it when I was looking before.

    function cloneLayeredTexture(srcLayeredTexture) {    if (!srcLayeredTexture) {        return null;    }    var textureName = oImageMgr.getUniqueImageName(srcLayeredTexture.name);    var oNewLayeredTexture = oImageMgr.createLayeredTexture(textureName);    oNewLayeredTexture.copyFrom(srcLayeredTexture);    return oNewLayeredTexture;}

    DzLayeredTexture::copyFrom(const DzLayeredTexture*) will perform a deep copy of the object so you don't have to do all the heavy lifting yourself.


    Post edited by Esemwy on
  • jag11jag11 Posts: 885
    edited October 2015

    Excellent, I think it only needs one additional validation to ensure it is a DzLayeredTexture instance.

        if (srcLayeredTexture.className() != "DzLayeredTexture") {        return null;    }

     

    Post edited by jag11 on
  • EsemwyEsemwy Posts: 577
    edited October 2015

    I reordered things a bit and modified the surface selection logic. Here's the entire thing.

    function getMaterialObject() {    var DSVersion = new Number( App.versionString );    var nNodes = Scene.getNumNodes();    for (var i=0; i < nNodes; i++) {        var oNode = Scene.getNode(i)        if (DSVersion >= 4.8) {            if (oNode.inherits("DzBone")) {                oNode = oNode.getSkeleton();            }        }        var oObj = oNode.getObject();        if (! oObj) continue;        var oShape = oObj.getCurrentShape();        if (! oShape) continue;        var oMat = oShape.getMaterial(0);        if (oMat) return oMat;    }}function setOpacity() {    var oImageMgr = App.getImageMgr();    var oMat = getMaterialObject();    if( !oMat ) return;    var nMaterials = oMat.getNumMaterials();    for( var i = 0; i < nMaterials; i++ ) {        var oMaterial = oMat.getMaterial( i );        if ((!oMaterial) || (!oMaterial.isSelected())) continue;        var oTexture = oMaterial.getColorMap();        if (oTexture && (oTexture.className() == "DzLayeredTexture")) {            var nLayers = oTexture.getNumLayers();            if (nLayers == 3) {                var textureName = oImageMgr.getUniqueImageName(oTexture.name);                var oNewLayeredTexture = oImageMgr.createLayeredTexture(textureName);                oNewLayeredTexture.copyFrom(oTexture);                var oLayer1 = oNewLayeredTexture.getLayer(1);                var oLayer2 = oNewLayeredTexture.getLayer(2);                oLayer1.opacity = .8;                oLayer2.opacity = .1;                oMaterial.setColorMap(oNewLayeredTexture);            }        }    }    MessageBox.information("Done", "Finished", "OK");}setOpacity();

    Once I did all the defensive programming, it made more sense to bring cloneLayeredTexture() inline. I believe the differences in my logic are immaterial. laugh

    Post edited by Esemwy on
  • Thank you both for all the help. This has helped me a lot. :)

  • Just getting back to this script again...

    I am still having the problem where the surface turns white when I run the script while the viewport is set to NVIDIA Iray. This doesn't happen if I run the script from the Script IDE tab, but when I run it out of a folder in the Content Library it does happen. If I create a Custom Action and then run the script from the Scritps menu (on the top tool bar) then it doesn't happen. I have no idea why it works this way. Does anyone have any idea? I would like to be able to run it from a folder in the Content Library.

  • That's a bug in Daz Studio... From what I understand it's been reported. If you click to something else (like texture) and then click back to NVIDIA Iray it should update the viewport.

  • That's a bug in Daz Studio... From what I understand it's been reported. If you click to something else (like texture) and then click back to NVIDIA Iray it should update the viewport.

    Thanks for the info DraagonStorm. Yes, it looks fine if I switch to Texture Shaded and back again.

Sign In or Register to comment.