Scripting: Replacing nodes in the render tree


To get this script to work in 2011 and later, you need to do this to find the Blinn shaders:

// Get a collection of all Blinn nodes
var sProgID = "Softimage.material-blinn.1.0" 
var oShaderDef = Application.GetShaderDef( sProgID ) ;  

var oBlinnCollection =  oShaderDef.ShaderInstances ;  
if (debug) LogMessage( "Found " + oBlinnCollection.Count + " Blinn shaders" );


The rest of the script can stay the same.
Note: I split the script into two parts below, for the purposes of this blog post. Just combine them to get the full script.

Here’s a script that shows how to replace every Blinn shader in a scene with a Phong shader.
There’s other ways to do it, but I used the connection stack.

var debug = 0;

// Class ID of the Blinn shader in XSI
var sClassID = "{8FAC63AC-E392-11D1-804C-00A0C906835D}";
SetValue("preferences.scripting.cmdlog", false, null);

// Get a collection of all Blinn nodes
var oBlinnCollection = FindObjects( null, sClassID );
if (debug) LogMessage( "Found " + oBlinnCollection.Count + " Blinn shaders" );

// Loop over the Blinn collection and replace all Blinn nodes with Phongs
var s = new Date();
oEnum = new Enumerator( oBlinnCollection ) ;
for (;!oEnum.atEnd();oEnum.moveNext() )
{
	var oBlinn = oEnum.item() ;

	// try catch will skip over any TransientObjectContainer.Blinn shaders we find
	try
	{
		var oMaterial = oBlinn.Owners(0);
	}
	catch(e)
	{
		LogMessage( "Skipping " + oBlinn );
		continue;
	}
	LogMessage( "Replacing " + oBlinn );
	blinn2phong( oMaterial, oBlinn );
}
var e = new Date();
LogMessage( "Finished replacing Blinn shaders. Elapsed time: " + (e-s)/1000 + "s" );



function blinn2phong( oMaterial, oBlinn )
{
	// Create a new Phong node
	var oPhong = CreateShaderFromPreset("$XSI_DSPRESETS\\Shaders\\Material\\Phong.Preset", oMaterial, null);

	// Get the node connections from the ConnectionStack
	// And then insert the Phong node

	var oDR = XSIUtils.DataRepository ;
	var strOpInfo = oDR.GetConnectionStackInfo( oBlinn );

	var oTopNode = ParseXML( strOpInfo ) ;
	var oConnections = oTopNode.childNodes ;

	if ( oConnections.length == 0 )
	{
		LogMessage( "Cannot replace the Blinn node " + oBlinn + " .It has no connections." );
	}
	else
	{

		for ( var i = 0 ; i < oConnections.length ; i++ )
		{
			var oConnection = oConnections(i) ;
							
			strtype = SafeGetNodeValue( oConnection, "type", "Unknown" ) ;
			strobj = SafeGetNodeValue( oConnection, "object", "Not Connected" ) ; 
			localparam = SafeGetNodeValue( oConnection, "localparameter", "&nbsp;" ) ;  
			destparam = SafeGetNodeValue( oConnection, "remoteparameter", "&nbsp;" ) ;  				
			
			if ( strtype == "in" )
			{
				var oParam = oPhong.Parameters( localparam );
				if ( oParam == null )
				{
					LogMessage( "Cannot connect " + strobj + " to Phong." + localparam + ". That parameter does not exist.", siWarning );
				}
				else
				{
					//SIConnectShaderToCnxPoint("Sources.Materials.Proteus_Body_MatLib_Proteus.MAT_Brass11.Image5", oPhong + ".ambient", false);
					SIConnectShaderToCnxPoint( strobj, oParam );
					if( debug ) LogMessage( "IN: " + strobj + ", " + oParam );
				}
			}
			if ( strtype == "out" )
			{
				var oTarget = Dictionary.GetObject( strobj );
				var oParam = oTarget.Parameters( destparam );
				//SIConnectShaderToCnxPoint("Sources.Materials.Proteus_Body_MatLib_Proteus.MAT_Brass11.Phong1", "Sources.Materials.Proteus_Body_MatLib_Proteus.MAT_Brass11.Mix_2colors.base_color", false);
				SIConnectShaderToCnxPoint( oPhong, oParam );
				if( debug ) LogMessage( "OUT: " + oPhong + ", " + oParam );
			}
		}	
	}
}

The bling2phong() function is based on the code that builds this HTML page in the SDK Explorer:

Notice how the Connection Stack Details give you everything you need to replace a Blinn node with some other node in the render tree:

See below the cut for the code for the helper functions ParseXML() and SafeGetNodeValue().

//----------------------------------------
// Helpers
//----------------------------------------


// Helper function to load the XML data using the Microsoft
// implementation of the DOM (see msdn.microsoft.com for documentation)
function ParseXML( strXML )
{
	var oXMLParser = new ActiveXObject("Microsoft.XMLDOM") 
	oXMLParser.async = false	
	oXMLParser.loadXML( strXML ) ;

	if (oXMLParser.parseError.errorCode != 0) 
	{
		logmessage( "Invalid XML " + oXMLParser.parseError.reason , siError ) ;	
		return null ;
	}

	// the xsi_file node
	// If this is NULL we must have failed to load the XML
	var oTopNode = oXMLParser.documentElement ;

	return oTopNode ;
}

// SafeGetNodeValue
//
// in_parentnode - XML DOM node
// in_nodename - name of a nested node to query
// in_default - value to return if nested node not found
//
// Example: If in_parent node points to this XML: <item><info>4</info><other></other></item>
// then SafeGetNodeValue( node, "info", 0 ) ; returns "4".
// and SafeGetNodeValue( node, "bogus", "not found" ) ; returns "not found".
function SafeGetNodeValue( in_parentnode, in_nodename, in_default )
{
	strInfo = in_default ;

	try
	{
		oNode = in_parentnode.selectSingleNode( in_nodename ) ;
		if ( oNode != null )
		{
			// Note: the property name is case sensitive, "Text" does not work
			strInfo = oNode.text ;  
		}
	}
	catch( e )
	{
	}
	return strInfo ;	
}

6 thoughts on “Scripting: Replacing nodes in the render tree

  1. Thanks for posting this script up, very useful esp for mia conversions.

    PS if you do read this, can you ask the area guys to make the ‘lost’ password email address greater than 25 or so characters, would help.

    Thanks 2wice.

  2. Hi!
    I have a slight problem with the script, I need it to work with xsi 6.5 to convert from soft 3d materials to normal bilnns.
    Its the CreateShaderFromPreset command wont work for me and I havent found any subsititute.
    Do you have any advice for me?

    Thanks
    -Martin

  3. please forgive my ignorance and please help .. this script.. is it simply copypaste and run as JS ? it doesn’t detect the Blinn shaders in the scene.. what am i doing wrong??? on soft2012

      • Hi there ; thanks for the quick response ; I now realize that there are lots of treasures to be found In the sdk XML ( nicely documented folks ) I came across blinn2phong script ( show how) because that was what I was looking for .. Any Chance of that happening ? Ie not a show how but actually the script doing it because cross walk sucks , documentation sucks and we are not psyop and if it’s such a specialized field to understand the nuances of soft backend ; could you please forward a contact person that we can hire to get those scripts out fast . Thank you .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s