Timer and Time changing

Hello,

I would like to start a function when a file appears.
Of course, this file would be created by another application.
For me, this action can be done by two way:
   - A signal in a dzFile.
   - A timer which is executed every XXX ms in which it is possible to test if a file exists.
I don't find any solution to resolve this issue.
Someone could help me to find a solution?

My second question is about the time changing in Daz Studio.
I would like to execute a function when the time changes in Daz Studio.
There are two signals which correspond to this action "timeChanged" and "timeChanging" found in the "Scene".
For me, "timeChanging" would be better because this signal appears before the time changing is really done in Daz Studio.
I made many tests and never found a working solution.
Is there an example which shows how to use these signals?

I thank you very much for your replies.

Comments

  • PraxisPraxis Posts: 247
    edited May 2018

    My second question is about the time changing in Daz Studio.

    Hope this helps...

    // SceneTimeChange.dsa//  Demo script to test Scene.timeChanging() and Scene.timeChanged() signals.//  Load this script into the Script IDE Pane, run it, and press the "Next Frame" and "Previous Frame" buttons.// Define an anonymous function;// serves as our main loop,// limits the scope of variables(function(){  //---Build the Dialog---  // Create a Dialog as a child of the App's MainWindow:  var wDlg = new DzDialog( MainWindow );  wDlg.caption = "Scene Time-Change Tester";  // Add a Layout so that widgets auto-size:  wLayout = new DzVBoxLayout( wDlg );  wLayout.autoAdd = true;  wLayout.margin  = 0;  wLayout.spacing = 0;  // Create a TextBox for output display:  var wTextEdit = new DzTextEdit( wDlg );  wTextEdit.pointSize = 12;                   // Make its text larger - more readable  wTextEdit.minWidth  = 500;                  // Force it to be wide enough to avoid word-wrap  wTextEdit.minHeight = 500;  wTextEdit.text = 'Press the "Next" and "Previous" buttons...';  // Create buttons to change the Frame Number:  wFrameGrp = new DzHGroupBox( wDlg );  wFrameGrp.insideMargin  = 0;  wFrameGrp.insideSpacing = 5;  //  wPrevFrame          = new DzPushButton( wFrameGrp );  wPrevFrame.text     = "< Previous frame";  //  Connect it to the event-processor:  connect( wPrevFrame, "clicked()", processPrevFrameClicked );  //  wNextFrame          = new DzPushButton( wFrameGrp );  wNextFrame.text     = "Next frame >";  //  Connect it to the event-processor:  connect( wNextFrame, "clicked()", processNextFrameClicked );  // Create a Script-Global event-counter:  var g_EventNum = 0;  //---Connect our event-processor functions to the Scene's Time signals---  connect( Scene, "timeChanging(DzTime)", processTimeChanging );  connect( Scene, "timeChanged(DzTime)" , processTimeChanged  );  //---Define the Event-Processor functions---  function processPrevFrameClicked() {    var oAction = MainWindow.getActionMgr().findAction( "DzPrevFrameAction" );    if( oAction ) {      oAction.trigger();    }  }  //------------------------------------------  function processNextFrameClicked() {    var oAction = MainWindow.getActionMgr().findAction( "DzNextFrameAction" );    if( oAction ) {      oAction.trigger();    }  }  //------------------------------------------  function processTimeChanging( oDzTime ) {    g_EventNum = g_EventNum + 1;    var sText = "\n" + "Event "+g_EventNum.toString()+": TimeChanging @ Frame " + Scene.getFrame().toString();    wTextEdit.text = wTextEdit.text + sText;  }  //------------------------------------------  function processTimeChanged( oDzTime ) {    g_EventNum = g_EventNum + 1;    var sText = "\n" + "Event "+g_EventNum.toString()+": TimeChanged @ Frame " + Scene.getFrame().toString();    wTextEdit.text = wTextEdit.text + sText;  }  //------------------------------------------  //---Launch the Dialog---  wDlg.exec();// Finalize the function and invoke})();

     

    dsa
    dsa
    SceneTimeChange.dsa
    3K
    Post edited by Praxis on
  • contessgcontessg Posts: 55

    Hello Praxis,

    Thank you very much for your great example.

    It shows me I did not understand correctly how to use the signal functions.

    I will keep this example preciously.

    Have a fine day.

  • PraxisPraxis Posts: 247

    You are welcome.

    P.

     

  • contessgcontessg Posts: 55

    Excuse me, I come back to my first question.

    Is there a way to create a waiting loop. A loop which allows to wait for the existence of a file for instance.

    This loop must let the Daz Studio interface work normally, by letting the messages pass.

  • PraxisPraxis Posts: 247
    contessg said:
    Is there a way to create a waiting loop...

    Yes, there is:  For example see the use of processEvents() in http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/rendering/render_to_rib/start

    BUT:  Be aware that use of such a mechanism to create a "Non-Modal" or "Modeless" dialog in Script is "categorically not supported" by DAZ.

    See https://www.daz3d.com/forums/discussion/comment/657812/#Comment_657812:  'a "modeless dialog" is implemented as a DzPane subclass in DAZ Studio. And while portions of DzPane are exposed to script, you cannot construct one via script. You must use the SDK for that.'

    For more on this topic, see this thread, and the threads it refers to: https://www.daz3d.com/forums/discussion/248766/script-window-show-hide

    P.

  • contessgcontessg Posts: 55

    Hello Praxis,

    one more time, thank you for your help.

    I tried to find a method named "processMessage()". The right name is "ProcessEvents()".

    I was not so far :-)

    I will make many tests using the informations you gave me.
    To be sure this will not generate some issues.

    Thanks again.

         Gérald

  • contessgcontessg Posts: 55

    Hello Praxis,

    I hope you will continue to read this post.
    Just a very simple question.
    I wrote a script using the method you described with a "timeChanging" signal. Thank you for your help.

    This function works perfectly but, when I load it in the script interface and  I execute it, nothing happens.
    I have to start it using the debug interface. As soon as I start the script in this interface, it works fine.

    It is as if I didn't have validated the signal, or something like that.
    I tried to use a "Scene.update()" but this don't resolve the issue.

    Should I use another function?

         Gérald

     

  • PraxisPraxis Posts: 247
    contessg said:
    This function works perfectly but, when I load it in the script interface and  I execute it, nothing happens.

    I have to start it using the debug interface. As soon as I start the script in this interface, it works fine.

    I don't know why that would happen.  In what way is your script different from the demo script I posted earlier?

    P.

  • contessgcontessg Posts: 55

    My script has no interface. Perhaps this is the main reason.

    I open the DazScript interface, I open the dsa file and I execute the script.
    Making this, the script don't work correctly. If I open the Debug interface and start the script (F5), the script works fine.

    The script just contains the function and the connect function.

  • PraxisPraxis Posts: 247
    edited May 2018
    contessg said:
     

    The script just contains the function and the connect function.

    You need some way to make the Scene time change, to trigger the signal that your function is connected to.

    In a modal dialog you cannot access the DAZ Studio Timeline, but your dialog (if you used one) can contain buttons and/or sliders to change the Scene time - as per my demo script

    A simple test: Your function should get called (once) if you simply add this to your script, just after the "connect(...)" statement:

    Scene.setFrame( Scene.getFrame() + 1 );

    P.

    Post edited by Praxis on
  • contessgcontessg Posts: 55

    The behaviour is very curious.

    If I add a "Scene.setFrame(xxx)" as you propose me, the frame changes and the function is executed.
    After this action,  if I try to change the frame in the scene, nothing happens.

    I suppose, the "connect" function needs to be in a loop to work correctly.
    I also suppose the debug interface generates an invisible loop to activate correctly the connection.

    I will continue to make tests to try to understand the behaviour of this function.

    Thank you for your help.

         Gérald

  • PraxisPraxis Posts: 247
    edited May 2018
    contessg said:

    If I add a "Scene.setFrame(xxx)" as you propose me, the frame changes and the function is executed.
    After this action,  if I try to change the frame in the scene, nothing happens.

     Yes, that is why I said "Your function should get called (once)..."

    As soon as your script has executed (once), it goes "out of scope" and is automatically "garbage-collected" (effectively deleted from the Scene).

     

    contessg said:

    I suppose, the "connect" function needs to be in a loop to work correctly.

    Yes - that is, effectively, what happens when your event-handler function is executing in the context of a Dialog (which automatically provides a Message- or Event-handling loop).

    You said "My script has no interface. Perhaps this is the main reason." Yes - to achieve what you want, it seems to me that you must use a Dialog:

    That Dialog can be "Modal" and implemented using DAZ Script - like my demo script above - in which case the User cannot interact directly with the rest of the DAZ Studio interface, but can still control many aspects of that interface by means of buttons, sliders, etc.  For more complex examples, see e.g. https://www.daz3d.com/forums/discussion/87636/a-script-to-control-a-selected-property-with-large-font-size-and-preview-buttons, or here: https://www.daz3d.com/forums/discussion/293/list-of-free-daz-studio-script-and-plugins

    Or, that Dialog can be "Non-Modal" in which case it cannot be implemented using DAZ Script, and must instead be implemented in C++ using the  SDK

    P.

    Post edited by Praxis on
  • Richard HaseltineRichard Haseltine Posts: 100,747

    It is possible to have a script triggered by an event, but it requires some setting up:

    To have a script run when a scene event occurs, you would need to either load a script "On Launch" and/or "On New," or use a post-load script for a node that is added to the scene, to create one or more DzCallBack instances that are connected to the desired signals... which in turn cause a script that evaulates/manipulates the scene to execute. Using the post-load approach is more adventagous because the signal for the node being destroyed can be used to clean up the callbacks. I have samples of this posted on the Documentation Center; http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/start#post-load_callbacks. Said samples are the basis of the IBL Master product.

  • PraxisPraxis Posts: 247

    It is possible to have a script triggered by an event, but it requires some setting up:

    "Post-load callbacks..." - in effect, allowing much Scripted control, without needing a "Non-Modal" Dialog.

    That is VERY interesting... I became aware of those Script API additions only 3 weeks ago, and haven't yet made time to investigate them. I intend to fix that now...

    Thank you Richard! (and Rob!).

    Gérald - keep watching this space...

    P.

  • PraxisPraxis Posts: 247
    edited May 2018

    It is possible to have a script triggered by an event, but it requires some setting up:

    Well, that was easy...

    Simplified for demo purposes, from http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/scripting/api_reference/samples/start#post-load_callbacks.

    1) Save this script to wherever you want:

    // SceneTimeChangingProcessor.dsa//  DzCallback script to process Scene.timeChanging events.// Simplified for demo purposes from://  DAZ Scripting_API_v4\Samples\_Elements\_Callbacks\Callbacks_Element_Post_Load_Create.dsa// Define an anonymous function;// serves as our main loop,// limits the scope of variables(function(){  // Note: This script is re-loaded from disk EACH TIME it gets executed by the Callback,  //  so you can change its code between calls.  var sMsg = 'Scene.timeChanging @ Frame '+Scene.getFrame().toString();  // Because this script is not being executed from the Script Editor,  //  this gets logged in the Log file, but does not appear in the Script IDE Pane:  //  NB: Likewise for any sytnax errors, etc. caused by this script!  print( sMsg );  //  // So to provide feedback do this:  //  MessageBox.information( sMsg, 'Test', '&OK' );  MainWindow.windowTitle = sMsg;  // $$$ Testing:  //  //  // 'CallBack' is a global transient DzCallback variable,  //  //    available when this script is executed by a DzCallBack  //  if( typeof( CallBack ) != "undefined" ){  //    // This script is executing inside the context of a DzCallBack  //  //    // Get the object that prompted the callback  //    var oSender = CallBack.getSender();  //    if( oSender ) {  //      print( oSender.className() );     // DzScene  //    }  //  //  }// Finalize the function and invoke})();

     

    2) Save this script to the same place as 1 above, then load it into the Script IDE and run it...

    // SceneTimeChanging_Setup.dsa//  Set up a DzCallback script to process Scene.timeChanging events.// Simplified for demo purposes from://  DAZ Scripting_API_v4\Samples\_Elements\_Callbacks\Callbacks_Element_Post_Load_Create.dsa// Define an anonymous function;// serves as our main loop,// limits the scope of variables(function(){  var sMsg = '';  // We set up a DzCallback to call a script to process Scene.timeChanging events:  //---Check that the Callback processor script file exists---  // Get the base path of this Setup script  var oSetupScriptFileInfo = new DzFileInfo( getScriptFileName() );  var sBasePath = oSetupScriptFileInfo.path() +'/';  var sTitle = oSetupScriptFileInfo.baseName();  // Create a Globally Unique IDentifier for all callbacks wihin sBasePath:  var sGroupGUID = App.createDigest( sBasePath );  // We set up a DzCallback to call the following script to process Scene.timeChanging events:  var sCallbackName = 'SceneTimeChanging';            // A unique name within sBasePath  var sScriptName = sCallbackName+'_Processor.dsa';  //  We assume the Callback processor script should be in the same directory as this Setup script:  var sScriptFileSpec = sBasePath + sScriptName;  var oCallbackScriptFileInfo = new DzFileInfo( sScriptFileSpec );  if( !oCallbackScriptFileInfo.exists() ) {    sMsg = 'Callback script file not found:' +'\n'+ sScriptFileSpec;  } else {    // The Callback Script file exists    //---Create the Callback if it does not already exist---    // Get the callback manager    var oCallBackMgr = App.getCallBackMgr();    // Get the callback with the name    var oCallBack = oCallBackMgr.getCallBack( sCallbackName );    if( oCallBack ) {      sMsg = 'Callback "'+sCallbackName+'" already exists. (so no need to run this script again)';    } else {      // Create a callback with the name      oCallBack = oCallBackMgr.createCallBack( sCallbackName );      // Spcify its unique Group ID:      oCallBack.addToGroup( sGroupGUID );      // We want the callback to be processed as an event      oCallBack.setProcessAsEvent( true );      // Specify the script in the callback      //  false: sScriptFileSpec specifies a disk file, not embedded code      oCallBack.setScript( sScriptFileSpec, false );      // Connect the callback to the signal on the Scene      //  true: Remove this callback from the DzCallBackMgr when Sender (this Scene) is deleted.      oCallBack.setConnection( Scene, 'timeChanging(DzTime)', true );      sMsg = 'Callback "'+sCallbackName+'" created.'               + '\n' + 'Now change the Frame number in the Timeline Pane,'               // See notes in SceneTimeChanging_Processor.dsa for why we do this:               + '\n' + 'and watch the TitleBar of the MainWindow...';    } // Need to create the Callback  } // The Callback Script file exists  if( sMsg != '' ) {    MessageBox.information( sMsg, sTitle, '&OK' );  }// Finalize the function and invoke})();

     

    Note that after you have set up this Callback, you can use DzCallback::clearConnection() and DzCallback::setConnection() to disable/enable it, or even to make it execute a different script, without having to re-create it.

    This opens up all sorts of useful possibilities!

    Thank you again Rob!laugh

    So Gérald - you don't need a loop!  And you don't need an interface!  Thank you for starting this thread!

    (Updated 12-May - just tidied-up some comments in the scripts)

    P.

     

    dsa
    dsa
    SceneTimeChanging_Processor.dsa
    1K
    dsa
    dsa
    SceneTimeChanging_Setup.dsa
    3K
    Post edited by Praxis on
  • contessgcontessg Posts: 55

    Hello,

    I just read this post.

    Thank you for your replies and for your time.

    I will implement this method in my script. This will help to activate the TimeChanging signal.

    Richard, I will reply to the other post. Actually, I will use several GZFiles to create the cache file.

    Praxis, your examples are great. If this thread has been useful to other developers, that is perfect.

    Thank you again.

    Have a fine day.

         Gérald

Sign In or Register to comment.