Wb Products Wb Models Wb Imagery Wb Tutorials Wb Software
PP2 Exporter version 2.1a
Convert OBJ models into Poser Props
(Public Domain script for Daz Studio)

F-R-E-E

Daz Studio Script

The original PP2 Exporter (version 1a) was written by JWAS84 and  DUKE533 with supplements by Rob Whisenant and Guandalug. It was released without any copyright as Public Domain for the benefit of the Daz studio and 3D communities. We are not exactly sure why an individual would take a product released into the Public Domain as not copyrighted, add a couple of simple mods, and then re-release it as copyrighted material.  However, it is in the spirit of the original authors that it has been updated by RoLoW to support Daz Studio v4.10+ and remains copyright free.



The goal for this update to the original non-copyrighted version 2.0d was to keep it copyright free while at the same time ensuring it functions properly under Daz Studio 4.10 or newer.  To do this, we started with release 2.0d and added our own methods of correcting known problems within the code when used with Daz Studio 4.5+. This latest version 2.1a remains non-copyrighted and in the public domain.  You can scroll down to see the full scripting code for this utility.

For those of you new to 3D modeling, or perhaps to using Daz Studio, here is the full User Guide for your review:

USING PP2 EXPORTER TO CREATE POSER PROPS IN DAZ STUDIO
Copyright (c) 2018, Winterbrose Arts and Graphics. All Rights Reserved.

Once you have created your static model in Daz Studio, and have exported all individual components as OBJ format files, start New Scene then use desired method.
Please note that the Classic Dart OBJ model used in this tutorial was created in the training from Modeling Made Simple Volume 1: Create Static Models.



Method A:

01. Load Model into Scene
    - New Scene
    - Import components
    - Group components
    - Rename Group to model name
    - Select Group in scene tab

02. Create Poser Prop
    - Execute PP2 Exporter
    - Select PP2 location and name for PP2
    - Select Geometries location and name for OBJ
    - Select Child Nodes Stored as "Child"
    - Click Save button

03. If successful, receive PROP Created message
04. Load new Prop model
    - New Scene
    - In Poser Formats / My DAZ 3D Library,
      locate prop in Props folder created
    - Double click thumbnail to load into scene

05. Review Geometries folder
06. Review Props folder
07. Test New Prop
    - New Scene
    - Load new prop into scene
    - Select first component and repeat 8/9 for each

08. In Tool Settings/Geometry Editor
    - Check Groups for each component

09. In Surface tab
    - Check Surfaces for each component


Method B:
01. Load Pieces to Build Single Model
    - New Scene
    - Import all components
    - Remove all non-components (ie Camera, Lights)
    - Export complete model

02. Load Single Model
    - New scene
    - Import complete model

03. Create Poser Prop
    - Execute PP2 Exporter
    - Select PP2 location and name for PP2
    - Select Geometries location and name for OBJ
    - Select Child Nodes Stored as "None"
    - Click Save button

04. If successful, receive PROP Created message
05. Load new Prop model
    - New Scene
    - In Poser Formats / My DAZ 3D Library,
      locate prop in Props folder created
    - Double click thumbnail to load into scene

06. Review Geometries folder
07. Review Props folder
08. Test New Prop
    - New Scene
    - Load new prop into scene
    - Select prop in Scene tab

09. In Tool Settings/Geometry Editor
    - Check Groups for complete prop

10. In Surface tab
    - Check Surfaces for complete prop
USER GUIDE: Using PP2 Exporter to Create Poser Props in Daz Studio
Copyright (c) 2018, Winterbrose Arts and Graphics. All Rights Reserved.


Here is the full uncensored code for version 2.1a of the PP2 Exporter script for Daz Studio 4.10 and higher:

/***************************************************************************
**      24-02-09 ver 1a         (JWAS84)
**      PP2 exporter 2.0d
**      Description: Export Prop with limited Mat support.
**      Authors: JWAS84, DUKE533
****************************************************************************
**      24-02-09 ver 1a         (JWAS84)
**      (c) Copyright NONE. Use for whatever you like.
**      ExportObj Was written by Rob Whisenant.
**      renderIcon Was written by Guandalug
****************************************************************************
**      18-11-09 ver 1b  
**      - working on DS 3!
**      - lot of bug fixes
**      - renderIcon was replaced (DS3 compatible)
**      x only single object suport
****************************************************************************
**      22-11-09 ver 1c  
**      - more bug fixes
**      - multi-object support (weld)
**      - new script icon
**      x code tweaking needed
****************************************************************************
**      27-11-09 ver 2a  
**      - more bug fixes
**      - weld & chold mode
**      - trans. channels save
**      - GUI
**      - new script icon
****************************************************************************
**      29-11-09 var 2b
**      - code tweaking
**      - morph settings
****************************************************************************
**      25-12-11 var 2c
**      - fix for non DzDefaultMaterial properties (ie Uber or HSS)
****************************************************************************
**      23-02-12 var 2d
**      - fix to avoid mangling Material names unless absolutely
**                necessary;
****************************************************************************
**      27-02-18 var 2e                (RoLoW)
**      PP2 exporter 2.1a
**      - added version number variable to display in caption header bar
**      - correct scaling to read and use current version of DS scaling
**      - matched init value for writetrans routine to same as writeoffset
**      - set button sizes to half the height of layout panel
**      STILL COPYRIGHT FREE, AS INTENDED.
**      (c) Copyright NONE. Use for whatever you like.
****************************************************************************/

// Variables
var sSrcPath, sObjPath, lObjPath, sFileName, m_oFile;
var nIndent = 0;
const dazScaler = 243.84;   // Scale to DAZ units
var sVersionNumber = "2.1a"

var m_Channels = [
            [ "xOffsetA"   ,"OriginX" ,"OriginX"     ,"0.004" ],
              [ "yOffsetA"   ,"OriginY" ,"OriginY"     ,"0.004" ],
              [ "zOffsetA"   ,"OriginZ" ,"OriginZ"     ,"0.004" ],
            [ "translateX" ,"xTran"   ,"X Translate" ,"0.001" ],
            [ "translateY" ,"yTran"   ,"Y Translate" ,"0.001" ],
            [ "translateZ" ,"zTran"   ,"Z Translate" ,"0.001" ],
            [ "rotateX"    ,"xRotate" ,"X Rotate"    ,"1"     ],
            [ "rotateY"    ,"yRotate" ,"Y Rotate"    ,"1"     ],
            [ "rotateZ"    ,"zRotate" ,"Z Rotate"    ,"1"     ],
            [ "scale"      ,"Scale"   ,"Scale"       ,"0.004" ],
            [ "scaleX"     ,"xScale"  ,"X Scale"     ,"0.004" ],
            [ "scaleY"     ,"yScale"  ,"Y Scale"     ,"0.004" ],
            [ "scaleZ"     ,"zScale"  ,"Z Scale"     ,"0.004" ],
              [ "xOffsetB"   ,"xOffB"   ,"xOffB"       ,"0.004" ],
              [ "yOffsetB"   ,"yOffB"   ,"yOffB"       ,"0.004" ],
              [ "zOffsetB"   ,"zOffB"   ,"zOffB"       ,"0.004" ]
];

// default settings
setup={};
setup.icon=1;

// **********************************************************************************
// This is the main section that produces the Prop file.
// **********************************************************************************

var selected= Scene.getSelectedNodeList();

if( selected.length==1 ) {

   // Target nodes
   oNode = selected[0];
   oNodes= oNode.getNodeChildren(1);
   oNodes.unshift( oNode );

   // Default files
   var root = App.getContentMgr().getAbsolutePath( "runtime",0 );
   setup.pp2= root +"/libraries/props/"+ oNode.name +".pp2";
   setup.obj= root +"/Geometries/"+ oNode.name +".obj";

   // Open gui
   win= initGui();
   loadSetup( win );
   ok= win.exec();

   // If we have filename, carry on, else abort.
   if( ok ) {
         // Save settings
         saveSetup( win );

         oFile= new DzFile( setup.pp2 );
         oFile.open( oFile.ReadWrite | oFile.Truncate );

         // Render an icon into the PROP folder.
         setup.png= setup.pp2.replace(".pp2",".png");
         renderIcon( setup.png );

         // OBJ exporter need unique material names
         setUniqueMetNames();

         // Write PROP file header.
         writeLine("{");
         writeLine("version");
         writeLine("{");
         writeLine("number 4.01");
         writeLine("}");
         writeLine("   //");
         writeLine("   //   PP2 exporter 2a");
         writeLine("   //");

         while( oNode=oNodes[0] ) {
            // Export the OBJ using the DAZ Exporter.
            ExportObj();

            PropName= oNode.name;
            ObjFile= RelativePath( setup.obj );

            // Write PROP geometry statement.
            writeLine(String("prop %1").arg(PropName));
            writeLine("{");
            writeLine("storageOffset 0 0.3487 0");
            writeLine( String("objFileGeom 0 0 %1").arg(ObjFile) );
            writeLine("}");
            writeLine("//");

            // Output the Transformers. This routine will call the function for writing the Materials.
            OutputTransformers(oNode);
            // Meterials section will shift oNodes !
           
            if( setup.single ) { break; }
         }

         // All done, write end of File.
         writeLine("doc");
         writeLine("{");
         writeLine(String("addActor %1").arg( PropName ));
         writeLine("}");
         writeLine("}");

         oFile.close();
         MessageBox.information( "PROP Created..", "Done", "&OK" );
         App.getContentMgr().refresh(1);
   }
  
} else {
      MessageBox.information("You must select an item in the scene first!","Oops!","&OK");
}

// **********************************************************************************
// Routine to write out the Transformers.
//   A lot of default values are set, but we are the creater so we can say what they will be.
//   The values selected are the value that POSER would use as default.
// **********************************************************************************
function OutputTransformers(oNode) {
   parent= oNode.isSelected() ? "UNIVERSE" : oNode.getNodeParent().name;

   // For first section just use Defaults for now.
   writeLine(String("prop %1").arg(PropName));
   writeLine("{");
   writeLine(String("name %1").arg(PropName));
   writeLine("on");
   writeLine("bend               1");
   writeLine("dynamicsLock       1");
   writeLine("hidden             0");
   writeLine("addToMenu          1");
   writeLine("castsShadow        1");
   writeLine("includeInDepthCue  1");
   writeLine("useZBuffer         1");
   writeLine("parent             "+parent);
   writeLine("creaseAngle        80");

   writeLine("channels");
   writeLine("{");

   // Output OffsetsA.
   var orig = oNode.getOrigin();
   var OX= orig.x / dazScaler;
   var OY= orig.y / dazScaler;
   var OZ= orig.z / dazScaler;
   //
   writeOffset( m_Channels[0], OX );
   writeOffset( m_Channels[1], OY );
   writeOffset( m_Channels[2], OZ );

   // Output Translate
   var LP= oNode.getLocalPos();
   if( !setup.pos && oNode.isSelected() ) { LP=DzVec3(); }
   //
   writeTrans( m_Channels[3], LP.x/dazScaler );
   writeTrans( m_Channels[4], LP.y/dazScaler );
   writeTrans( m_Channels[5], LP.z/dazScaler );

   // Output Rotate
   var RX= oNode.getXRotControl().getValue();
   var RY= oNode.getYRotControl().getValue();
   var RZ= oNode.getZRotControl().getValue();
   if( !setup.rot && oNode.isSelected() ) { RX=RY=RZ=0; }
   //
   writeTrans( m_Channels[6], RX );
   writeTrans( m_Channels[7], RY );
   writeTrans( m_Channels[8], RZ );

   // Output Scale
   var LS= oNode.getLocalScale();
   var S1= oNode.getScaleControl().getValue();
   if( !setup.scale && oNode.isSelected() ) { S1=1; LS=DzMatrix3(); }
   //
   writeTrans( m_Channels[9],  S1 );
   writeTrans( m_Channels[10], LS.m11/S1 );
   writeTrans( m_Channels[11], LS.m22/S1 );
   writeTrans( m_Channels[12], LS.m33/S1 );

   // Output OffsetsB.
   writeOffset( m_Channels[13], -OX );
   writeOffset( m_Channels[14], -OY );
   writeOffset( m_Channels[15], -OZ );

   // Deal with MORPHS here.
   ChkMorphs( oNode );

   // Close 'channels'
   writeLine("}")           

   writeLine(String("origin %1 %2 %3").arg(OX).arg(OY).arg(OZ) );

   var oBox = oNode.getEndPoint();
   var PosX = oBox.x / dazScaler;
   var PosY = oBox.y / dazScaler;
   var PosZ = oBox.z / dazScaler;
   writeLine(String("endPoint %1 %2 %3").arg(PosX).arg(PosY).arg(PosZ) );

   var  oOri = oNode.getOrientation();
   writeLine(String("orientation %1 %2 %3").arg( oOri.x ).arg( oOri.y ).arg( oOri.z ) );

   // Use more Default values.
   writeLine("displayOrigin      0");
   writeLine("displayMode USEPARENT");
   writeLine("customMaterial     1");

   // Write out the MATERIAL section from here to keep the format the same as POSER.
   OutputMaterial();

   writeLine("locked 0");
   writeLine("backfaceCull 0");
   writeLine("visibleInReflections 1");
   writeLine("visibleInRender 1");
   writeLine("displacementBounds 0");
   writeLine("shadingRate 0.2");
   writeLine("smoothPolys 1");
   writeLine("}");            // Close 'Prop'
}

// **********************************************************************************
// Check for MORPHS and output data for them.
function ChkMorphs( oNode ) {
   if( setup.morph!=1 ) { return; }

   var oObject = oNode.getObject();
   if( oObject == undefined ){ return; }

   try {
    oGeom= oObject.getCurrentShape().getGeometry();
   } catch(x){ return; }
        
   var nVerts = oGeom.getNumVertices();
//   writeLine(String("# Vertex count %1").arg(nVerts));

   // Check to see if there are any modifiers (MORPHS). Loop through and write them out.
   var nModifiers = oObject.getNumModifiers();
   for( var ci=0; ci < nModifiers; ci++ ) {

         // Get a valid morph.
         var oMorph = oObject.getModifier(ci);
         if( oMorph.className() != "DzMorph" ) { continue; }

         // Not intersted in modifier with no delta.
         var oMorphDeltas = oMorph.getDeltas();
         if(!oMorphDeltas) { continue; }
        
         // If it has deltas we can start.
         if( oMorphDeltas.hasDeltas() ) {

               var sMorphName   = oMorph.name;
               var nMorphValue  = oMorph.getValueChannel().getValue();
               var oMorphDeltas = oMorph.getDeltas();
               var nMorphDeltas = oMorphDeltas.getNumDeltas();

               writeLine( String("targetGeom %1").arg(sMorphName) );
               writeLine("{");
               writeLine( String("name %1").arg(sMorphName) );
               writeLine("initValue 0");
               writeLine("hidden 0");
               writeLine("forceLimits 1");
               writeLine("min -100000");
               writeLine("max 100000");
               writeLine("trackingScale 0.02");
               writeLine("keys");
               writeLine("{");
               writeLine("static  0");
               writeLine( String("k 0 %1").arg(nMorphValue) );
               writeLine("}");
               writeLine("interpStyleLocked 0");
               writeLine( String("indexes %1").arg(nMorphDeltas) );
               writeLine( String("numbDeltas %1").arg(nVerts) );
               writeLine("deltas");
               writeLine("{");

               // For each delta              
               for(var j = 0; j < nMorphDeltas; j++){
                  // Get delta and index
                  var vecDelta = oMorphDeltas.getDeltaVec(j);
                  var nDeltaIdx = oMorphDeltas.getDeltaIndex(j);
                  writeLine(String("d %1 %2 %3 %4").arg(nDeltaIdx).arg(vecDelta.x/dazScaler).arg(vecDelta.y/dazScaler).arg(vecDelta.z/dazScaler));
               }
               writeLine("}");
               writeLine("blendType 0");
               writeLine("}");

         }   // Valid Morph
   }   // Next Morph

}

// **********************************************************************************
//    From here down are the Functions that are called to perform repeated tasks,
//    or best kept seperate i.e. renderIcon, ExportObj etc.
// **********************************************************************************

// Write Name, color and strength.
// **********************************************************************************
function WriteColor(Name,oMatColor,oMatStrength) {
   oRed   = oMatColor.red / 255;
   oGreen = oMatColor.green / 255;
   oBlue  = oMatColor.blue / 255;
   writeLine(String("%1 %2 %3 %4 %5").arg(Name).arg(oRed).arg(oGreen).arg(oBlue).arg(oMatStrength));
}

// **********************************************************************************
// Write a channel section to Prop file - Type 1
// **********************************************************************************
function writeTrans( par, nVal ){
   writeLine(String("%1 %2").arg( par[0] ).arg( par[1] ));
   writeLine("{");
   writeLine(String("name %1").arg( par[2] ));
   writeLine(String("initValue %1").arg( nVal ));
   writeLine("hidden 0");
   writeLine("forceLimits 0");
   writeLine("min -100000");
   writeLine("max 100000");
   writeLine(String("trackingScale %1").arg( par[3] ));
   writeLine("keys");
   writeLine("{");
   writeLine("static  0");
   writeLine(String("k 0 %1").arg( nVal ));
   writeLine("}");
   writeLine("interpStyleLocked 0");
   writeLine("}");
}

// **********************************************************************************
// Write a channel section to Prop file - Type 2
// **********************************************************************************
function writeOffset( par, nVal ){
   writeLine(String("%1 %2").arg( par[0] ).arg( par[1] ));
   writeLine("{");
   writeLine(String("name %1").arg( par[2] ));
   writeLine(String("initValue %1").arg( nVal ));
   writeLine("hidden 1");
   writeLine("forceLimits 0");
   writeLine("min -100000");
   writeLine("max 100000");
   writeLine(String("trackingScale %1").arg( par[3] ));
   writeLine("keys");
   writeLine("{");
   writeLine("static  1");
   writeLine("k 0 0");
   writeLine("}");
   writeLine("interpStyleLocked 0");
   writeLine(String("staticValue %1").arg( nVal ));
   writeLine("}");
}

// **********************************************************************************
// Materials Section
// **********************************************************************************
function OutputMaterial() {
  
   nodes= oNode.getNodeChildren(1);
   nodes.unshift( oNode );

   while( oNode=oNodes.shift() ) {

      try {
       var Mats= oNode.getObject().getCurrentShape().getAllMaterials();
      } catch(x){ break; }

      // Each material has a name, usually corresponding to the material zone (group of polygons) onto which it is applied.
      // These material names must match the usemtl fields defined within the Wavefront .obj file.

      for( var m=0; m< Mats.length; m++ ) {

               var Mat= Mats[m];

               for( x=0; x<20; x++ ) {
                 Mat.name= Mat.name.replace( " ", "_" );
               }

               writeLine( String("material %1").arg( Mat.name ) );
               writeLine("{");
               // ********************************************************************************************
               // KdColor, KaColor, KsColor, TextureColor and ReflectionColor each specify RGB values with a strength setting tagged on.
               // The values for each field are from 0.0 to 1.0.
               // ********************************************************************************************
               var isDefMat = (Mat.className() == "DzDefaultMaterial" );

               // KdColor specifies the material's diffuse color.
               var s = 0.0;
               if (isDefMat) {
                  s = Mat.getDiffuseStrength();
               } else {
                  s = Mat.findPropertyByLabel( "Diffuse Strength" ).getValue();
               }
               WriteColor("KdColor",Mat.getDiffuseColor(),s);

               // KaColor specifies the material's ambient color (for ambient lighting).
               var c;
               if (isDefMat) {
                  c = Mat.getAmbientColor();
                  s = Mat.getAmbientStrength();
               } else {
                  c = Mat.findPropertyByLabel( "Ambient Color" ).getColorValue();
                  s = Mat.findPropertyByLabel( "Ambient Strength" ).getValue();
               }
               WriteColor("KaColor", c, s);

               // KsColor specifies the material's specular color (for specular highlights).
               if (isDefMat) {
                  c = Mat.getSpecularColor();
                  s = Mat.getSpecularStrength();
               } else {
                  c = Mat.findPropertyByLabel( "Specular Color").getColorValue();
                  s = Mat.findPropertyByLabel( "Specular Strength" ).getValue();  
               }
               WriteColor("KsColor", c, s);

               // TextureColor specifies a color, but the RGB is always 1,1,1. The strength setting affects the textureMap image.
               WriteColor("TextureColor ",Mat.getDiffuseColor(), 1 );

               // NsExponent - Glossiness. Its value ranges from 0 to 100.
               oProperty = (1 - Mat.findPropertyByLabel( "Glossiness" ).getValue()) * 200;
               writeLine(String("NsExponent %1").arg(oProperty));

               // tMin - tMax is the transparency minimum and maximum values. Can't find tMin, use defaults
               writeLine("tMin 0");
               oProperty = 1 - Mat.getBaseOpacity( );
               writeLine(String("tMax %1").arg(oProperty));

               // tExpo is the transparency falloff.
               if (isDefMat) {
                  oProperty = Mat.getOpacityControl ().getValue();
               } else {
                  oProperty = Mat.findPropertyByLabel( "Opacity Strength" ).getValue();
               }
               writeLine(String("tExpo %1").arg(oProperty));

               // bumpStrength is the strength of the bump map (how much apparent elevation is added negative values which range from -1.0 to 1.0.
               if (isDefMat) {
                  oProperty = Mat.getBumpStrength();
               } else {
                  oProperty = Mat.findPropertyByLabel( "Bump Strength" ).getValue();
               }
               writeLine(String("bumpStrength %1").arg(oProperty));

               // ksIgnoreTexture determines whether or not to apply texture to specular highlight. 0 or 1. DEFAULT
               writeLine("ksIgnoreTexture 0");

               // reflectThruLights determines whether or not to multiply reflection through lights. 0 or 1. DEFAULT
               writeLine("reflectThruLights 1");

               // reflectThruKd determines whether or not to multiply reflection through object color.
               if (isDefMat) {
                  oProperty = Mat.getMultThroughOpacityControl();
               } else {
                  oProperty = Mat.findPropertyByLabel( "Multiply Reflection Through Opacity" );
               }
               if( oProperty ){ writeLine("reflectThruKd 1"); }
               else           { writeLine("reflectThruKd 0"); }

               // textureMap
               oProperty = Mat.getColorMap();
               if( oProperty ) {
                     oFileName = RelativePath( oProperty.getFilename() );
                     writeLine( String("textureMap %1").arg(oFileName) );
               } else {
                     writeLine("textureMap NO_MAP");
               }

               // bumpMap
               if (isDefMat) {
                  oProperty = Mat.getBumpMap();
               } else {
                  oProperty = Mat.findPropertyByLabel( "Bump Strength" ).getMapValue();
               }
               if( oProperty ) {
                     oFileName = RelativePath( oProperty.getFilename() );
                     writeLine( String("bumpMap %1").arg(oFileName) );
               } else {
                     writeLine("bumpMap NO_MAP");
               }

               // reflectionMap
               if (isDefMat) {
                  oProperty = Mat.getReflectionMap();
               } else {
                  oProperty = Mat.findPropertyByLabel( "Reflection Strength" ).getMapValue();
               }
               if( oProperty ) {
                     oFileName = RelativePath( oProperty.getFilename() );
                     writeLine( String("reflectionMap %1").arg(oFileName) );
               } else {
                     writeLine("reflectionMap NO_MAP");
               }

               // transparencyMap
               oProperty = Mat.getOpacityMap();
               if( oProperty ){
                     oFileName = RelativePath( oProperty.getFilename() );
                     writeLine( String("transparencyMap %1").arg(oFileName) );
               } else {
                     writeLine("transparencyMap NO_MAP");
               }

               // ReflectionColor specifies the material's reflection color.
               if (isDefMat) {
                  c = Mat.getReflectionColor();
               } else {
                  c = Mat.findPropertyByLabel("Reflection Color").getColorValue();
               }
               WriteColor("ReflectionColor", c, 1 );

               // reflectionStrength is the amount or "depth and clarity" of the reflection.
               if (isDefMat) {
                  s = Mat.getReflectionStrength();
               } else {
                  s = Mat.findPropertyByLabel("Reflection Strength").getValue();
               }
               writeLine( String("reflectionStrength %1").arg(s) );
               writeLine("}");

      }   // Next Mat
      if( !setup.weld ) { break; }

   }   // Next Node
   PreviewMat();

// End Material Section.
}

// ********************************************************************************************
// A Default Preview Material.
// ********************************************************************************************
function PreviewMat() {  
   writeLine("material Preview");
   writeLine("{");
   writeLine("KdColor 0.654622 0.497543 0.861782 1");
   writeLine("KaColor 0 0 0 1");
   writeLine("KsColor 0.187072 0.0360363 0.131175 1");
   writeLine("TextureColor 1 1 1 1");
   writeLine("NsExponent 5.0");
   writeLine("tMin 0");
   writeLine("tMax 0");
   writeLine("tExpo 0.6");
   writeLine("bumpStrength 1");
   writeLine("ksIgnoreTexture 0");
   writeLine("reflectThruLights 1");
   writeLine("reflectThruKd 0");
   writeLine("textureMap NO_MAP");
   writeLine("bumpMap NO_MAP");
   writeLine("reflectionMap NO_MAP");
   writeLine("transparencyMap NO_MAP");
   writeLine("ReflectionColor 1 1 1 1");
   writeLine("reflectionStrength 1");
   writeLine("}");
}

// **********************************************************************************
// Write a line to the file and deal with indents.
// **********************************************************************************
function writeLine( sData ){
   if( sData=="{" ) { nIndent++; }
   for( var i=1; i<nIndent; i++ ) { oFile.write("\t"); }
   oFile.writeLine( sData );
   if( sData=="}" ){   nIndent--; }
}

// **********************************************************************************
//      Extract Local file name from ABS filename.
// **********************************************************************************
function RelativePath( path ) {
   path= App.getContentMgr().getRelativePath( path,1 );
   var sep= path.left(1)=="/" ? ":" : "\\";
   while( path.search("/") >= 0 ) {
     path= path.replace( "/", sep );
   }
   path= '"' + path+ '"';
   return path;
}

// **********************************************************************************
// Render an icon for the PROP.
// **********************************************************************************
function renderIcon( file ) {
      if( setup.icon==0 ) { return; }
      if( setup.icon==1 ) {
         Scene.saveThumbnail( file );
      } else {
         var RMgr= App.getRenderMgr();
         var Opts= App.getRenderOptions();
         Opts.applyChanges();
         Opts.imageSize= Size(91,91);
         Opts.renderImgToId=2;
         Opts.renderImgFilename=file;
         RMgr.doRender();
         Opts.resetOptions();
      }
}

// **********************************************************************************
// Set unique meterial names before combine
// **********************************************************************************
function setUniqueMetNames() {
      nodes= oNode.getNodeChildren(1);
      nodes.unshift( oNode );
      used_names = "|";
      for( i=0; i< nodes.length; i++ ) {
         try {
            var Mats= nodes[i].getObject().getCurrentShape().getAllMaterials();
         } catch(x){ continue; }
         for( m=0; m< Mats.length; m++ ){
            MatName= Mats[m].name;
            //MatName= MatName.replace( /[0-9]+-/, "" );
            MatName= MatName.replace( "Default", nodes[i].name );
            if (used_names.find( "|" + MatName + "|") >= 0) {
               Mats[m].name= MatName + "-" + Mats[m].getIndex();
            } else {
               Mats[m].name= MatName
               used_names += MatName + "|";
            }
         }              
      }
}

// **********************************************************************************
// Export the OBJ data to the file location provided.
// **********************************************************************************
function ExportObj() {
      hideUnselected();
      centerNodes();
      getObjName();
      //
      const oEXPORT_MANAGER = App.getExportMgr();
      const oOBJECT_EXPORTER = oEXPORT_MANAGER.findExporterByClassName( 'DzObjExporter' );
      const oEXPORTER_SETTINGS = new DzFileIOSettings();
      oOBJECT_EXPORTER.getDefaultOptions( oEXPORTER_SETTINGS );
      //
      oEXPORTER_SETTINGS.setStringValue( 'Preset', 'Custom (1 unit = 1cm)' );
      oEXPORTER_SETTINGS.setStringValue( 'Scale', '243.84' );
      oEXPORTER_SETTINGS.setBoolValue( 'SwapYZ', false );
      oEXPORTER_SETTINGS.setBoolValue( 'IgnoreInvisible', true );
      oEXPORTER_SETTINGS.setBoolValue( 'WeldSeams', false );
      oEXPORTER_SETTINGS.setBoolValue( 'WriteO', false );
      oEXPORTER_SETTINGS.setBoolValue( 'WriteG', true );
      oEXPORTER_SETTINGS.setBoolValue( 'GroupNodes', false );
      oEXPORTER_SETTINGS.setBoolValue( 'GroupSurfaces', false );
      oEXPORTER_SETTINGS.setBoolValue( 'GroupSingle', false );
      oEXPORTER_SETTINGS.setBoolValue( 'GroupGeom', true );
      oEXPORTER_SETTINGS.setBoolValue( 'WriteVN', false );
      oEXPORTER_SETTINGS.setBoolValue( 'WriteVT', true );
      oEXPORTER_SETTINGS.setBoolValue( 'WriteUsemtl', true );
      oEXPORTER_SETTINGS.setBoolValue( 'WriteMtllib', false );
      oEXPORTER_SETTINGS.setBoolValue( 'CollectMaps', false );
      oEXPORTER_SETTINGS.setBoolValue( 'ConvertMaps', false );
      oEXPORTER_SETTINGS.setBoolValue( 'RemoveUnusedVerts', false );
      oEXPORTER_SETTINGS.setIntValue( 'RunSilent', 1 );
      //
      oOBJECT_EXPORTER.writeFile( setup.obj, oEXPORTER_SETTINGS );
      restoreNodes();
}

// **********************************************************************************
// Get unique names for obj files
// **********************************************************************************
function getObjName() {
      if( oNode.isSelected() ) {
         childIndex=1; return;
      }
      setup.obj= setup.obj.replace( /(.cn)?[0-9]{0,2}.obj$/ ,"" );
      setup.obj= setup.obj +".cn"+ childIndex +".obj";
      childIndex++;
}

// get the object nodes only
function getObjNodes() {
      var nodes= Scene.getNodeList();
      for( i=0; i<nodes.length; i++ ) {
       if( nodes[i].getObject()==null ) {
            nodes.splice(i,1);
      }}
      return nodes;
}

// hide unselected nodes
function hideUnselected() {
      var nodes= getObjNodes();
      for( i=0; i<nodes.length; i++ ) {
       nodes[i].setVisible( 0 );
      }
      oNode.setVisible( 1 );
      // export children too
      if( setup.weld ) {
         var nodes= oNode.getNodeChildren(1);
         for( i=0; i<nodes.length; i++ ) {
          nodes[i].setVisible( 1 );
         }
      }
}

// set the exportin position
function centerNodes() {
      // find current scaling
      myScale = oNode.getWSScale();
      // backup pos & rot
      oNode.Pos= oNode.getWSPos();
      oNode.Rot= oNode.getWSRot();
      // backup scale
      oNode.Sc1= oNode.getScaleControl().getValue();
      oNode.ScX= oNode.getXScaleControl().getValue();
      oNode.ScY= oNode.getYScaleControl().getValue();
      oNode.ScZ= oNode.getZScaleControl().getValue();
      // reset rotation
      oNode.setWSRot( DzQuat(0,0,0,0) );
      oNode.setLocalRot( oNode.getWSRot().inverse() );
      oNode.setWSScale( myScale );
      // center obj
      oNode.setWSPos( oNode.getOrigin() );
      resetMorphs();
}

function restoreNodes() {
      oNode.setWSPos( oNode.Pos );
      oNode.setWSRot( oNode.Rot );
      oNode.Sc1= oNode.getScaleControl().setValue( oNode.Sc1 );
      oNode.ScX= oNode.getXScaleControl().setValue( oNode.ScX );
      oNode.ScY= oNode.getYScaleControl().setValue( oNode.ScY );
      oNode.ScZ= oNode.getZScaleControl().setValue( oNode.ScZ );
      restoreMorphs();
      // unhide all
      var nodes= getObjNodes();
      for( i=0; i<nodes.length; i++ ) {
       nodes[i].setVisible( 1 );
      }
}

function resetMorphs() {
      oNode.mod= new Array();
      if( setup.morph==2 ) { return; }
      var oObject = oNode.getObject();
      if( oObject == undefined ){ return; }
      var nModifiers = oObject.getNumModifiers();
      for( i=0; i < nModifiers; i++ ) {
         var oMorph = oObject.getModifier(i);
         if( oMorph.className() != "DzMorph" ) { continue; }
         oNode.mod[i]= oMorph.getValueChannel().getValue();
         oMorph.getValueChannel().setValue( 0 );
      }
}

function restoreMorphs() {
      var oObject = oNode.getObject();
      if( oObject == undefined ){ return; }
      for( i=0; i < oNode.mod.length; i++ ) {
         var val= oNode.mod[i];
         if( val==0 ) { continue; }
         oObject.getModifier(i).getValueChannel().setValue( val );
      }
}

//////////////////////////////////////
//////////  GUI ONLY   ///////////////
//////////////////////////////////////

function initGui() {
      // DIALOG
      win= new DzDialog;
      win.caption= "PP2 Exporter  v" + sVersionNumber;
      win.width = 260;
      win.height= 150;
      // Main Layout
      var winLyt= new DzVBoxLayout( win );
      winLyt.autoAdd= true;
      winLyt.margin= 5;
      winLyt.spacing= 5;
     
      // PP2 & OBJ files
      var VBox= new DzVGroupBox( win );
      VBox.title = "Destination Files";
      VBox.columns = 2;
      VBox.insideSpacing= 8;
     
      label= new DzLabel( VBox );
      label.text = "PP2:";
      label.maxWidth= 20;
     
      win.pp2= new DzPushButton( VBox );
      win.pp2.maxWidth= 200;
      win.pp2.whatsThis= "PP2 file path and file name";
      connect( win.pp2, "clicked()", openPP2 );
      win.pp2.text= trim( setup.pp2 );
     
      label= new DzLabel( VBox );
      label.text = "OBJ:";
      label.maxWidth= 20;
     
      win.obj= new DzPushButton( VBox );
      win.obj.text= "DzLineEdit Highlighted";
      win.obj.maxWidth= 200;
      win.obj.whatsThis= "OBJ file path and file name";
      connect( win.obj, "clicked()", openOBJ );
      win.obj.text= trim( setup.obj );
     
      // Multi-object mode
      win.mode= new DzVButtonGroup( win );
      win.mode.title= "Child Nodes Stored as";
      win.mode.columns= 3;
     
      wBtn= new DzRadioButton( win.mode );
      wBtn.text= "None";
      wBtn.whatsThis= "Child nodes will be ignored";
      wBtn= new DzRadioButton( win.mode );
      wBtn.text= "Child";
      wBtn.whatsThis= "Child nodes will be stored";
      wBtn= new DzRadioButton( win.mode );
      wBtn.text= "Weld";
      wBtn.whatsThis= "Child nodes will be combined";
      win.mode.selected= 1;

      // Morphs mode
      win.morph= new DzVButtonGroup( win );
      win.morph.title= "Morphs saving method";
      win.morph.columns= 3;
     
      wBtn= new DzRadioButton( win.morph );
      wBtn.text= "Ignore";
      wBtn.whatsThis= "Morphs will be ignored";
      wBtn= new DzRadioButton( win.morph );
      wBtn.text= "Save";
      wBtn.whatsThis= "Morphs will bee saved";
      wBtn= new DzRadioButton( win.morph );
      wBtn.text= "Apply";
      wBtn.whatsThis= "Morphs will bee applyed bedore export";
      win.morph.selected= 1;
           
      // Transformation channels
      var group= new DzVButtonGroup( win );
      group.title= "Transformation Channels";
      group.columns= 3;
     
      win.pos= new DzCheckBox( group );
      win.pos.text= "Position";
      win.pos.whatsThis= "Position parameters will bee stored";
      win.rot= new DzCheckBox( group );
      win.rot.text= "Rotation";
      win.rot.whatsThis= "Rotation parameters will bee stored";
      win.scale= new DzCheckBox( group );
      win.scale.text= "Scale";
      win.scale.whatsThis= "Scale parameters will bee stored";
      win.scale.checked=1;
     
      // Dialog buttons
      var group= new DzGroupBox( win );
      group.maxHeight= 35;
      group.flat= true;
     
      var layout= new DzGridLayout( group );
      layout.margin= layout.spacing= 5;
     
      var oHelpMgr   = App.getHelpMgr();
      var oActionMgr = MainWindow.getActionMgr();
      var oHelpAction= oActionMgr.findAction( "DzWhatsThisAction" );
     
      // "What's This?" push button
      var helpBtn= new DzPushButton( group );
      helpBtn.minHeight = group.maxHeight/2;
      helpBtn.pixmap= new Pixmap( String( "%1/images/icons/whatsthissmallicon.png" ).arg( App.getResourcesPath() ) );
      helpBtn.clicked.connect( oHelpAction, "trigger()" );
      helpBtn.whatsThis = oHelpMgr.getHelpString( "WhatsThis" );
      layout.addWidget( helpBtn, 0, 0 );
     
      // Stretch the column between the left and right sides
      layout.setColStretch( 1,1 );
     
      // Create the cancel push button
      var btn= new DzPushButton( group );
      btn.text= "Cancel";
      btn.minWidth= 80;
      btn.minHeight = group.maxHeight/2;
      win.setRejectButton( btn );
      btn.whatsThis= "Close this dialog";
      layout.addWidget( btn, 0, 2 );
     
      // Create the accept push button
      var btn= new DzPushButton( group );
      btn.text= "Save";
      btn.minWidth= 80;
      btn.minHeight = group.maxHeight/2;
      win.setAcceptButton( btn );
      btn.whatsThis= "Save poser PP2";
      layout.addWidget( btn, 0, 3 );

      return win;
}

function openPP2() {
      var pp2= FileDialog.doFileDialog( 0, "Select PP2 file name", setup.pp2 , "Prop Files (*.pp2)" );
      if( pp2 ) {
         setup.pp2= pp2;
         win.pp2.text= trim(pp2);
      }
}

function openOBJ() {
      var obj= FileDialog.doFileDialog( 0, "Select OBJ file name", setup.obj , "Geometry Files (*.obj)" );
      if( obj ) {
         setup.obj= obj;
         win.obj.text= trim(obj);
      }
}

function trim( path ) {
         if( path.length<23 ) { return path; }
         i= path.findRev( "/", path.length-20 );
         path= "..."+ path.mid( i,50 );
         return path;
}

function loadSetup( win ) {
      var reg= new DzAppSettings("PP2ex");
      if( reg.getIntValue("true")==0 ) { return; }
  
      var path= reg.getStringValue("pp2");
      var dir = path.left( path.findRev("/")+1 );
      setup.pp2= dir + oNode.name +".pp2";
      win.pp2.text= trim( setup.pp2 );
  
      var path= reg.getStringValue("obj");
      var dir = path.left( path.findRev("/")+1 );
      setup.obj= dir + oNode.name +".obj";
      win.obj.text= trim( setup.obj );

      win.mode.selected   = reg.getIntValue("mode");
      win.morph.selected= reg.getIntValue("morph");
      win.pos.checked   = reg.getIntValue("pos");
      win.rot.checked   = reg.getIntValue("rot");
      win.scale.checked   = reg.getIntValue("scale");  
}

function saveSetup( win ) {
      var reg= new DzAppSettings("PP2ex");
      reg.setIntValue("true",1);

      reg.setStringValue( "pp2", setup.pp2 );
      reg.setStringValue( "obj", setup.obj );  

      setup.mode = win.mode.selected;
      setup.morph= win.morph.selected;
      setup.pos  = win.pos.checked;
      setup.rot  = win.rot.checked;
      setup.scale= win.scale.checked;

      setup.single= setup.mode==0 ? 1 : 0;
      setup.weld  = setup.mode==2 ? 1 : 0;

      reg.setIntValue( "mode", setup.mode );
      reg.setIntValue( "morph", setup.morph );
      reg.setIntValue( "pos", setup.pos );
      reg.setIntValue( "rot", setup.rot );
      reg.setIntValue( "scale", setup.scale );
}

If you do not know how to make 3D models, or require an easy to follow step-by-step training that covers the creation of static props using only Daz Studio, please consider purchasing our flagship product for the Modeling Made Simple (MMS) series:

Volume 1: Create Static Models (using ONLY Daz Studio)

                 

Best viewed at
1024 x 768
or higher.
copyright Thanks for Visiting
WINTERBROSE
Arts & Graphics