Daz Studio Scripting help (also, have a really kludgy autosave script on me)

Zavijava_

Member
Oct 19, 2020
456
7,803
None of the autosave scripts I could find really complemented my workflow, so I made my own. It's workable, but I have a question about something it's doing.

Code:
/*
 * Crappy DAZ Autosave script v0.1 by Zavijava
 * ================================================================================================
 *
 * Usage:
 *
 * Boot up Daz and run the script, or set Daz to run it automatically after starting. The script
 * will be active and will constantly back up your work until you close Daz, even across saving and
 * loading different scenes.
 *
 * Every five minutes, Daz will automatically save your in-progress scene. This won't overwrite the
 * scene you loaded; rather, "_Autosave" will be appended to the current working filename, and you
 * can save it over your original scene or as a new one when you're done.
 *
 * Autosaves will also be made for a "new" scene that hasn't been saved anywhere, as long as you've
 * done any work in the scene. These autosaves go to a default location, since there is no current
 * working filename.
 *
 * Fair warning: This script is REALLY CRAP!
 *
 * This is a kludgy and bug-ridden script made in a few hours with very little understanding of the
 * Daz scripting API. There are a number of issues, including:
 *
 * - The Daz process will stay alive after you close the program, since the timer is somehow
 *   blocking it from closing. Use task manager or similar to end the DazStudio.exe process.
 *
 * - Relatedly, there is no way to stop the script from running after starting it, other than
 *   ending the Daz process and restarting.
 *
 * - The autosave dialog steals focus if you've alt-tabbed away, which can be irritating. This
 *   won't happen repeatedly, as the script checks if the scene has been modified before saving.
 *
 * - The save interval and location for the default autosave are hardcoded below, and you must
 *   modify and re-run the script to change them.
 *
 * ================================================================================================
 */

(function(){

    // ==================================================================================

    var libraryPath = "D:/Stuff/Daz/DAZ Studio Content/My Library/";
    var saveIntervalMinutes = 5;

    // ==================================================================================



    var timer = new DzTimer();
    timer.start(100);

    connect(timer, "timeout()", save);

    function save() {
        if (Scene.needsSave()) {
            var priorName = Scene.getFilename();
            if (!priorName) {
                priorName = libraryPath + "_Autosave.duf";
            }
            if (!killext(priorName).endsWith("_Autosave")) {
                priorName = killext(priorName) + "_Autosave.duf";
            }
            var path = priorName.substring(0, priorName.lastIndexOf("/"));

            var oAssetIOMgr = App.getAssetIOMgr();
            var oAssetIOFilter = oAssetIOMgr.getFilter(oAssetIOMgr.findFilter("DzSceneAssetFilter"));
            var oSettings = new DzFileIOSettings();
            oAssetIOFilter.getDefaultOptions(oSettings);
            oSettings.setBoolValue("RunSilent", true);

            var oError = oAssetIOMgr.doSaveWithOptions(oAssetIOFilter, oSettings, true, priorName, path);
        }

        timer.start(saveIntervalMinutes*60*1000);
    }

    function killext(filename) {
        return filename.substring(0, filename.lastIndexOf('.')) || filename
    }

    while (true) {
        sleep(1000);
    }

})();
The main issue is - as documented - that the timer (or the while(true)) keeps the script alive even after closing Daz, which prevents the DazStudio.exe process from ending. I can end it from task manager, but I'm sure there much be a better way to do this. Instead of "while(true)", what's the proper way to keep a script running until Daz closes, then end it?

(The while(true) is necessary - if the script ends, the timer falls out of scope and gets cleaned up before it does anything)

Also go ahead and use this script if you want it! Just keep in mind it's crap
 

NeverEast

Newbie
May 26, 2017
74
2,752
Please note I know very little about the API on this application, but you should be able to put a connection watch on the broadcast of the main window about to close and control the loop that way? Code below, let me know if it works...


Code:
(function(){

    // ==================================================================================

    var filePath = "";
    var saveIntervalMinutes = 5;

    // ==================================================================================

    var timer = new DzTimer();
    var directoryFound = setScriptFolder();

    if(!directoryFound) {
        disableLoop();
    }

    timer.start(100);

    connect(MainWindow, "aboutToClose()", disableLoop);
    connect(timer, "timeout()", save);

    function save() {
        if (Scene.needsSave()) {
            var priorName = Scene.getFilename();
            if (!priorName) {
                priorName = filePath + "_Autosave.duf";
            }
            if (!killext(priorName).endsWith("_Autosave")) {
                priorName = killext(priorName) + "_Autosave.duf";
            }
            var path = priorName.substring(0, priorName.lastIndexOf("/"));

            var oAssetIOMgr = App.getAssetIOMgr();
            var oAssetIOFilter = oAssetIOMgr.getFilter(oAssetIOMgr.findFilter("DzSceneAssetFilter"));
            var oSettings = new DzFileIOSettings();
            oAssetIOFilter.getDefaultOptions(oSettings);
            oSettings.setBoolValue("RunSilent", true);

            var oError = oAssetIOMgr.doSaveWithOptions(oAssetIOFilter, oSettings, true, priorName, path);
        }

        timer.start(saveIntervalMinutes*60*1000);
    }

    function setScriptFolder() {
    // Get the global file name value
    var fileName = getScriptFileName();
    if (fileName == "") {   
        return false;
    }
    // Create a FileInfor object for the file name
    filePath = new DzFileInfo(fileName).path() + "/Auto Saves/";

    return true;
    }

    function killext(filename) {
        return filename.substring(0, filename.lastIndexOf('.')) || filename;
    }

    function disableLoop() {
        exit();
    }

    while (timer.active) {
        sleep(1000);
    }

})();
 
Last edited:
  • Love
Reactions: Zavijava_

Zavijava_

Member
Oct 19, 2020
456
7,803
Great, thanks! I hadn't looked at this script at all since I cobbled it together :sleep: But if that signal works as advertised it should do the job nicely. You're awesome as always, NeverEast :cool:
 
  • Red Heart
Reactions: NeverEast

NeverEast

Newbie
May 26, 2017
74
2,752
I edited the above again. I found out that timer has an active boolean attached to it, so I just made the loop based on if the timer is active. This allows for the script to stop 1 second after the window is closed rather than having to wait for the full sleep timer to finish.

Edit: So apparently the timer API isn't available to system resources after the app closes... weird. BUT! I did get this working on my end, it does shut down after the app closes now. Code revised above.

I took the liberty of making a ZIP of the script finished and put into a DSA for anyone who wants to use it. The script (as seen above) has been modified to save the backup files in a folder under ContentLibrary/Scripts/Auto Saves/ folder. That way we don't have to worry about a hardcoded folder location any more. It uses the location of the script when it is executed. Hopefully this will help someone out.
 
Last edited:
  • Like
Reactions: Zavijava_

Zavijava_

Member
Oct 19, 2020
456
7,803
Cool cool! I won't be at my main PC for a while so I won't be able to check this out until later today. Thanks again for the help :D