Skip to content

Instantly share code, notes, and snippets.

@marcuswilm marcuswilm/animMorph.dsa
Last active Aug 22, 2019

Embed
What would you like to do?
/*******************************************************************************************************************************
DAZ Studio 4.x Pro - filetype : DAZ Script (.dsa = ascii | .dsb = binary)
File Name of this Script : animMorph.ds(a|b) - Released on July 30, 2013 GMT
This new version is replacing the previous versions of
- animMorph (for Daz Studio 4.0 Pro)
- animMorph2 (for Daz Studio 4.5 Pro)
both of them were released on May 2012
and published on Marvelous Designer Website (in the freestuff's pages).
The purpose of this new version of the script animMorph is to make it compatible with each version
of Daz Studio 4.x Pro.
It has been developed for Daz Studio 4.x Pro (PC version)
and tested with Daz Studio 4.0 Pro, Daz Studio 4.5 Pro and Daz Studio 4.6 Pro (versions 64-bit).
This script was inspired by a script published by DREDMARK in Marvelous Designer's Forum.
However, the script animMorph is based upon a new algorithm with enhanced performances.
The algorithm provided in this script is the result of my own research on Animate 2.
Before running this script, a Wavefront Object (.OBJ) sequence needs to be loaded in the scene
with the plugin "Morph Loader Pro".
Then this script creates automatically an animation with the sequence of morphs.
I am grateful to DREDMARK for having shown his solution.
I put lots of comments to explain the process in this script. :-)
This script is secure :
- it doesn't write or read any data on your disks.
- it doesn't interact with any other applications outside Daz Studio 4.x Pro.
- it doesn't send or receive any data to or from Internet.
However, I would recommend you to save your Daz Scene and to save your active works running
in other applications before the execution of this script.
A programmer can NEVER predict everything.
You may use this script for every purposes. No copyright is bound to my contribution.
********************************************************************************************************************************/
/******************************************************************************************************************************
Variables for the detection of Daz Manager's Actions used by this script : useful for the compatibility
of this script with existing (and probably future) subversions of Daz Studio 4 Pro
******************************************************************************************************************************/
var oAction ; // variable used to store the value of each Daz Manager Action to be tested
var nActionNextFrame ; // variable used to store the index number of the Action Next Frame
var nActionAddKeys ; // variable used to store the index number of the Action Add Keys
var sActionText ; // variable used to store and compare sequentially each Daz Manager Action Text
/**************************************************************************************************************
Settings for a RichTextPad DialogBox that will help debugging inside Daz Studio 4.x Pro
**************************************************************************************************************/
var clrWHITE = new Color( 255, 255, 255 ); // color is white for the output in the RichTextPad
var clrBKD = new Color( 100, 140, 250 ); // color is a discreet blue for some backgrounds
var nMargin = 10;
var nSpacing = 10;
var wDlgRTP = new DzDialog; // it is the Dialog Box which contains the RichTextPad
wDlgRTP.caption = "My Little Debugger :-)"; // :-)
wDlgRTP.paletteBackgroundColor = clrBKD // the background has a light blue color
wDlgRTP.sizeGripEnabled = 1; // Dialog Box is resizable by the user (grip is on Bottom Right)
var wDlgRTPLyt = new DzVBoxLayout( wDlgRTP ); // Layout of this Dialog Box
wDlgRTPLyt.autoAdd = true; // Dialog Box Container may extend automatically
wDlgRTPLyt.margin = nMargin; // to set the margin inside the Dialog Box
wDlgRTPLyt.spacing = nSpacing; // perhaps useful, not sure in this case
var wRichTxt = new DzTextEdit( wDlgRTP ); // it is the RichTextPad itself
wRichTxt.documentTitle = "MyLittleDebugger"; // why not ?
wRichTxt.clear(); // let's start with a blank page
wRichTxt.color = clrWHITE; // text in white
wRichTxt.pointSize = 8; // the value 8 seems to be a good size for the text
/*****************************************************************
Setting of the variables for the Dialog with the user
*****************************************************************/
var wDlg = new DzDialog; // it is the Dialog Box to interact with the user
wDlg.paletteBackgroundColor = clrBKD ; // the background has a light blue color
wDlg.caption = "ANIMATION WITH A SEQUENCE OF MORPHS - DAZ Studio 4.x Pro" ;
var wDlgLyt = new DzVBoxLayout( wDlg ); // Layout of this Dialog Box
wDlgLyt.autoAdd = true; // Dialog Box Container may extend automatically
wDlgLyt.margin = nMargin; // to set the margin inside the Dialog Box
wDlgLyt.spacing = nSpacing; // perhaps useful, not sure in this case
var wComment = new DzGroupBox( wDlg ); // to store a comment in this Dialog Box
wComment.title = "This script is inspired by a script "
+ "that DREDMARK published in Marvelous Designer's Forum";
var wLineEdit1 = new DzLabel (wDlg); // initialisation of some lines in the DialogBox
var wLineEdit2 = new DzLabel (wDlg);
var wLineEdit3 = new DzLabel (wDlg);
var wLineEdit4 = new DzLabel (wDlg);
/*********************************************************************
Warning Message when the user tries to run this script
IF no OBJECT is selected in the Scene
*********************************************************************/
var oNode = Scene.getPrimarySelection();
if( ! oNode ){ // the warning message if the user forgot to select the Object
MessageBox.information( "Please select an Object in the Scene",
"NOTHING IS SELECTED", "&Click this button to continue" )
}
/*****************************************************
Setting of the variables for the Animation
*****************************************************/
var i, j, k; // iterators for the main function
var oObject = oNode.getObject(); // to locate the Selected Object
var oNodeLabel = oNode.getLabel(); // to get the Label of the Selected Object
var nModifiers = oObject.getNumModifiers(); // to get the number of morphs loaded for this object
var oModifier = undefined; // to find and get the Object Modifiers
var mgr = MainWindow.getActionMgr(); // to get the available actions in Daz Studio 4 Pro's Window
var nLastFrame = oObject.getNumModifiers() ; // the Last Frame of the animation = the number of Loaded Morphs
var nTimeStep = Scene.getTimeStep(); // the Time Step applied by Daz Studio : a value of 160 is awaited
// please read comment #1 at the end of this script
var oTimeRange = DzTimeRange(0, nTimeStep * nLastFrame); // to determine the Time Range to apply to the Scene
Scene.setAnimRange( oTimeRange ); // Animation Range : the number of frames = the Sequence of Morphs + 1
var nFirstFrame = Scene.getAnimRange().start / nTimeStep; // to determine the first frame : a value of 0 is awaited
wRichTxt.append ("Time Step = " + nTimeStep); // Output to help for debugging
wRichTxt.append ("First Frame = " + nFirstFrame);
wRichTxt.append ("Last Frame = " + nLastFrame);
// wDlgRTP.exec(); // a first launch of my little debugger :-)
// please read comment #2 at the end of this script
/***************************************************************************************
Output of comments and instructions in the DialogBox with the user
***************************************************************************************/
wLineEdit1.text = "You selected this object : "+ oNodeLabel ;
wLineEdit2.text = "if valid, the sequence of morphs "
+ "will be used to create an animation for your selection";
wLineEdit3.text = "The animation starts on frame [ "
+ nFirstFrame + " ] and ends on frame [ " + nLastFrame + " ]";
wLineEdit4.text = "If you don't want to proceed, please click on CANCEL";
var wDlgAcceptCancel = new DzGroupBox( wDlg ); // creation of the Group Accept / Cancel
wDlgAcceptCancel.flat = true; // Daz Script Sample "Widget Test" in the DOC was very useful :-)
var wDlgBtnsLyt = new DzGridLayout( wDlgAcceptCancel );
var wAcceptBtn = new DzPushButton( wDlgAcceptCancel );
wAcceptBtn.text = "&ACCEPT = PROCEED";
wAcceptBtn.minWidth = 100;
wAcceptBtn.minHeight = 80;
wDlg.setAcceptButton( wAcceptBtn );
wDlgBtnsLyt.addWidget( wAcceptBtn, 0, 2 );
var wCancelBtn = new DzPushButton( wDlgAcceptCancel );
wCancelBtn.text = "&CANCEL = DON'T PROCEED";
wCancelBtn.minWidth = 100;
wCancelBtn.minHeight = 80;
wDlg.setRejectButton( wCancelBtn );
wDlgBtnsLyt.addWidget( wCancelBtn, 0, 3 );
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
if( wDlg.exec() ) // the user clicked on the "ACCEPT = PROCEED" button
{ // let's load the sequence of morphs to convert it into an animation
load_morphs(); // the function [ load_morphs() ] is called
// wDlgRTP.exec(); // a second launch of my little debugger to see the script's termination
wRichTxt.append ("Script Terminated"); // This last output for a happy end :-)
// wDlgRTP.exec();
}
//°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
//__________________________________________________________END OF THE MAIN SECTION___________________________________________________________________________________________
//__________________________________________________________FUNCTION(S) IN THIS SECTION ______________________________________________________________________________________
function load_morphs()
{
n = mgr.getNumActions();
for( i = 0; i < n; i++ ){
oAction = mgr.getAction( i ); // Daz Manager Actions are scanned sequentially
wRichTxt.append ( oAction.text + ": " + i ); // script line for debugging purpose
sActionText = oAction.text ;
if ( sActionText == "Step to Next Frame" ){
nActionNextFrame = i ; // the action "Step to Next Frame" is found and its index is stored
wRichTxt.append ("OK action " + i); // script line for debugging purpose
}
else if ( sActionText == "Create Keyframe" ) {
nActionAddKeys = i ; // the action "Create Keyframe" is found and its index is stored
wRichTxt.append ("OK action " + i); // script line for debugging purpose
}
}
wRichTxt.append ("Number of Modifiers for this Object " // output to my little debugger :-)
+ nModifiers);
oStepNextFrame = mgr.getAction(nActionNextFrame); // The Action "Step to Next Frame" (DzNextFrameAction) is identified
oCreateKeyFrame = mgr.getAction(nActionAddKeys); // The Action "Create KeyFrame" (AddKeysAction) is identified
/************************************************************
It is here that the serious job begins
This algorithm is executing a very tedious task
***********************************************************/
Scene.setFrame (0) ; // Frame #0 is created (no other step required for this frame)
oCreateKeyFrame.trigger(); // Parameters of the selected Object are recorded in this frame
for( i = 1; i <= nLastFrame ; i++){ // The iterative process of this algorithm is controlled by the variable i
// The variable i is incremented by 1 unit with each iteration until its value reaches the Last Frame's value
oStepNextFrame.trigger (i) ; // The first action is to move to the next frame in the animation
j = i - 1 ; // The variable j is used to locate the Morph in position (i-1) in the sequence of Morphs
k = i - 2 ; // The variable k is used to locate the Morph in position (i-2) in the sequence of Morphs
if ( i >= 2) {
// The variable k starts playing its role when frame #2 is reached
oModifier = oObject.getModifier(k); // oModifier gets the Modifier #k in the sequence of Morphs
oModifier.getValueChannel().setValue(0); // The Morph #k recorded in the previous frame is reset to 0 (0%) to disable its useless interpolation
}
// This last part of the algorithm is executed for each frame ranging from 1 to the end of the animation
oModifier = oObject.getModifier(j); // oModifier gets the Modifier #j in the sequence of Morphs
oModifier.getValueChannel().setValue(1); // The Morph #j is set to 1 (= 100%)
Scene.setFrame (i); // The Morphs #j and #k are recorded in each frame #i within the iteration
oCreateKeyFrame.trigger(); // THAT'S THE MAGIC ACTION ! Without this action, this script would be a nonsense,
// because simply "moving to the next step" enables the interpolation process between the morphs
}
}
//______________________________________________________________________________________________________________________________________________________________________________
/**************************************** COMMENTS *****************************************************************************************************************************************************
#1 / Time references in Daz Studio are stored in ticks. There are 4800 ticks per second. Therefore the default setting of 30 FPS (frames per second) in Daz Timeline
will create 4800/30 =160 ticks between each frame. The choice of that time format by Daz Studio Developers is clever ! Because the value of 4800 ticks can be divided
by many values (10, 15, 20, 25, 30, 50, 100, 120 frames per second).
The adjustment of the setting "FPS" in Daz Timeline's pane provides a way to synchronize imported morphs sequence created with a different "FPS".
Please consult the document "2013-03-20-v4-animation.pdf " : "a particular approach of Marvelous Designer's Animation Editor" to learn more about the
synchronization of garment's animation with avatar's animation.
#2 / some lines of this script were disabled ("// wDlgRTP.exec();" = considered as comments ). They are relative to "my little debugger".
It is not useful for the user.
**************************************************************************************************************************************************************************************************************/
@versluis

This comment has been minimized.

Copy link

commented May 10, 2017

Thanks for all those comments, and thanks again for sharing this script!

@marcuswilm

This comment has been minimized.

Copy link
Owner Author

commented May 12, 2017

Jay Versluis, thank you for your appreciation.
That script would be incomplete without your excellent tutorials (and particularly this video : https://youtu.be/Wz5AQ8azl4A with which you clearly explain how to export animations from DAZ Studio to Marvelous Designer and back ).
I also would like to recommend your very nice website https://www.versluis.com/ full of useful articles relative to 3D applications.

@versluis

This comment has been minimized.

Copy link

commented Aug 22, 2019

😍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.