Below is an example demonstrating how you can create proxy nodes in the scene for each of the predefined view cameras, create properties on the proxy nodes that correspond with properties on the view cameras and link the properties on the view cameras to the corresponding properties on the proxy nodes. The example also demonstrates how to embed post-load data on each proxy node and cause a script to be executed after the node has been loaded into the scene in order to re-establish the links between the properties which are not otherwise saved.
See Also: Post-Load View Proxy Link Properties
// Define an anonymous function; // serves as our main loop, // limits the scope of variables (function(){ /*********************************************************************/ // String : A function for retrieving a translation if one exists function text( sText ) { // If the version of the application supports qsTr() if( typeof( qsTr ) != "undefined" ){ // Return the translated (if any) text return qsTr( sText ); } // Return the original text return sText; }; /*********************************************************************/ // String : A function for finding an absolute file path of a relative one function findAbsContentFilePath( sRelFilePath ) { // If the relative path is empty if( sRelFilePath.isEmpty() ){ // We're done... return ""; } // Get the content manager var oContentMgr = App.getContentMgr(); // Declare working variable var sFilePath; // Initialize var bHasAllEnums = (App.version64 >= 0x000400090000002e);//4.9.0.46 var nDirType = DzContentMgr.AllDirs; // Get the import manager var oImportMgr = App.getImportMgr(); // If the file type is imported if( oImportMgr.findImporter( sRelFilePath ) ){ // If the version does not provide all enumerated values if( !bHasAllEnums ){ // Update the directory type nDirType = DzContentMgr.PoserDirs | DzContentMgr.ImportDirs | 0x20; //DzContentMgr.CloudDB // Otherwise } else { // Update the directory type nDirType = DzContentMgr.PoserDirs | DzContentMgr.ImportDirs | DzContentMgr.CloudDB; } // If the file type is native } else { // If the version does not provide all enumerated values if( !bHasAllEnums ){ // Update the directory type nDirType = DzContentMgr.NativeDirs | 0x20; //DzContentMgr.CloudDB // Otherwise } else { // Update the directory type nDirType = DzContentMgr.NativeDirs | DzContentMgr.CloudDB; } } // Return the path return oContentMgr.findFile( sRelFilePath, nDirType ); }; /*********************************************************************/ // String : A function for retrieving the name of the vendor function getVendorName( sOverride ) { // Set the vendor to the registered author var sVendor = App.getCurrentAuthor().name; // If a name was specified if( !sOverride.isEmpty() ){ // Use the specified name sVendor = sOverride; } // If we still don't have a name if( sVendor.isEmpty() ){ // Use a default sVendor = "Vendor Name"; } // Return the vendor name return sVendor; }; /*********************************************************************/ // String : A function for retrieving a name for a product function getProductName( sDefault ) { // Initialize var sProductName = "Product Name"; // Create a basic dialog var wDlg = new DzBasicDialog(); wDlg.caption = text( sProductName ); // Add a label var wLbl = new DzLabel( wDlg ); wLbl.text = text( sProductName ) + ":"; wDlg.addWidget( wLbl ); // Add a line edit var wNameLEdit = new DzLineEdit( wDlg ); wNameLEdit.text = sDefault; wDlg.addWidget( wNameLEdit ); // Get the wrapped widget var oDlg = wDlg.getWidget(); // Set the object name of the wrapped widget; // this is used for recording position and size oDlg.objectName = sProductName.replace( / /g, "" ); // Get the minimum height var sizeHint = oDlg.minimumSizeHint; var nHeight = sizeHint.height; // Set the fixed height to the minimum wDlg.setFixedHeight( nHeight ); // If the user didn't cancel the dialog if( wDlg.exec() ){ // Get the name specified var sUserInput = wNameLEdit.text; // If the input is valid if( !sUserInput.isEmpty() ){ // Update the product name sProductName = sUserInput; } } // Return the product name return sProductName; }; /*********************************************************************/ // void : A function for copying the attribute of one property to another function copyPropertyAttributes( oSrcProperty, oTgtProperty, oSettings ) { // Get the attributes of the source property oSrcProperty.getAttributes( oSettings ); // Set the attributes of the target property oTgtProperty.setAttributes( oSettings ); // Clean up oSettings.clear(); }; /*********************************************************************/ // void : A function for creating a one to one link between properties function linkProperties( oSlaveProperty, oMasterProperty ) { // Link the slave property to the master property oSlaveProperty.linkTo( oMasterProperty ); }; /*********************************************************************/ // String : A function for establishing the post-load for linking properties function setLinkPropertiesPostLoad( oProxyElement, oTargetElement, aProperties ) { // Get the name of the target element var sTargetName = oTargetElement.name; // Define a unique name for our data item var sDataName = String("%1__%2__%3__LinkPropertiesPostLoad") .arg( m_sVendorName ) .arg( m_sProductName ) .arg( sTargetName ); // Get our data item var oDataItem = oProxyElement.findDataItem( sDataName ); // If we didn't find our data item if( !oDataItem ){ // Create our data item; we want it to be saved with the element oDataItem = new DzSimpleElementScriptData( sDataName, true ); // Set the path to our script oDataItem.setScriptFilePath( m_sScriptRelPath ); // Add the data item to the element oProxyElement.addDataItem( oDataItem ); } // Get the settings for the data item var oSettings = oDataItem.getSettings(); // Assign key/value pairs oSettings.setStringValue( "vendor", m_sVendorName ); oSettings.setStringValue( "product", m_sProductName ); oSettings.setStringValue( "target", sTargetName ); // Get the properties settings var oPropertySettings = oSettings.getSettingsValue( "properties" ); // If the properties settings does not exist if( !oPropertySettings ){ // Create the properties settings oPropertySettings = new DzSettings(); // If the properties settings does exist } else { // Clear the list of properties oPropertySettings.clear(); } // Declare working variables var sProperty; // Iterate over the property names for( var i = 0, nProps = aProperties.length; i < nProps; i += 1 ){ // Get the 'current' property name sProperty = aProperties[ i ]; // Add the setting for the property oPropertySettings.setBoolValue( sProperty, true ); } // Assign key/value pairs oSettings.setSettingsValue( "properties", oPropertySettings ); }; /*********************************************************************/ // Get the vendor name var m_sVendorName = getVendorName( "" ); // Get the product name var m_sProductName = getProductName( "" ); // Define the post-load script name var m_sScriptName = "Post_Load_View_Proxy_Link_Properties"; // Define the script extension var sExtension = "dsa"; // Construct the relative path of the post-load script; // by placing the script within the data folder, under a // vendor/product/item name for organizational purposes, // you have prepared it for product-ization and for being // installed via Daz Connect or Daz Install Manager var m_sScriptRelPath = String("data/%1/%2/%3.%4") .arg( m_sVendorName ) .arg( m_sProductName ) .arg( m_sScriptName ) .arg( sExtension ); // Find the post-load script within the content management system var sScriptAbsPath = findAbsContentFilePath( m_sScriptRelPath ); // If the script could not be found if( sScriptAbsPath.isEmpty() ){ // Define text variables for the message var sTitle = text( "File Not Found" ); var sMessage = text( "The '%1' file could not be found." ) .arg( m_sScriptRelPath ); var sButton = text( "&OK" ); // Inform the user MessageBox.information( sMessage, sTitle, sButton ); // We're done... return; } // Define the list of properties on the // target node to create a proxy for var aPropertyNames = [ "XTranslate", "YTranslate", "ZTranslate", "XRotate", "YRotate", "ZRotate", "Perspective", "Frame Width", "Focal Length", "DOF", "Depth of Field", "Aperature" ]; // Declare working variables var oCamera, oProxyNode; var oCameraProperty, oProxyProperty; var sProxyName, sProxyLabel; var aCameraProperties, aLinkProperties; // Create a settings object for copying property attributes var oSettings = new DzPropertySettings(); // Get the viewport manager var oViewportMgr = MainWindow.getViewportMgr(); // Get the number of view cameras var nCameras = oViewportMgr.getNumViewCameras(); // Iterate over all view cameras for( var i = 0; i < nCameras; i += 1 ){ // Get the 'current' view camera oCamera = oViewportMgr.getViewCamera( i ); // Construct the proxy node name sProxyName = String("%1Proxy").arg( oCamera.name ); // Construct the proxy node label sProxyLabel = String("%1 Proxy").arg( oCamera.getLabel() ); // Find the proxy node in the scene oProxyNode = Scene.findNode( sProxyName ); // If the proxy was not found if( !oProxyNode ){ // Create a new Null node oProxyNode = new DzNode(); // Set the name of the proxy oProxyNode.setName( sProxyName ); // Set the label of the proxy oProxyNode.setLabel( sProxyLabel ); // Add the node to the scene Scene.addNode( oProxyNode ); } // Copy values of node properties oProxyNode.copyFrom( oCamera ); // Initialize a list of properties aLinkProperties = []; // Get the properties on the camera aCameraProperties = oCamera.getPropertyList(); // Iterate over the properties for( var j = 0; j < aCameraProperties.length; j += 1 ){ // Get the 'current' camera property oCameraProperty = aCameraProperties[ j ]; // If the name of the property is not in our list if( aPropertyNames.indexOf( oCameraProperty.name ) < 0 ){ // Next!! continue; } // Attempt to find the property on the proxy node oProxyProperty = oProxyNode.findProperty( oCameraProperty.name ); // If the property was not found if( !oProxyProperty ){ // Duplicate the property oProxyProperty = oCameraProperty.propertyDuplicate(); // Add the property to the proxy node oProxyNode.addProperty( oProxyProperty ); } // Copy the setup of the camera property to the proxy property copyPropertyAttributes( oCameraProperty, oProxyProperty, oSettings ); // If the property is numeric if( oCameraProperty.inherits( "DzNumericProperty" ) ){ // Link the camera property to the proxy property linkProperties( oCameraProperty, oProxyProperty ); // If the property is a transform if( oCameraProperty.getXYZInterest() != DzNumericProperty.NO_INTEREST ){ // Linking transform properties causes issues when attempting to // animate; when keyframes exist on the proxy node's transforms, // viewport navigation appears to stop responding to user input // if the playhead is positioned beyond the last keyed frame as // a result of the proxy node's property being the 'master' of // the link (which forces the view camera's property to mimic // its value) oProxyProperty.setCanAnimate( false ); } // Capture the name of the property aLinkProperties.push( oCameraProperty.name ); } } // If we've linked properties if( aLinkProperties.length > 0 ){ // Set/Create the post-load that will re-establish the links setLinkPropertiesPostLoad( oProxyNode, oCamera, aLinkProperties ); } } // Finalize the function and invoke })();