Can I automatically run a DSA script when I load a prop from a DUF/DSF file?

3dcheapskate3dcheapskate Posts: 2,719
edited December 1969 in Daz Script Developer Discussion

When I use DAZ Studio I've always used Poser files (PP2, CR2, etc). I've never really used DAZ Studio native files (except my own DSA scripts for loading Poser props, automatically applying DS materials, and doing other useful stuff), and I've decided it's now time to take a look at the DS-native files.

As far as I can tell the DS4 DUF/DSF files are purely datafiles (i.e. no scripting).
Q1: is this correct?

The easiest way to convert my Poser prop (or imported OBJ) into a DS-native prop seems to be load it into DS and save it as either a 'Scene Subset' or a 'Figure/Prop asset'. The former (Scene Subset) seems to create a new folder in ':My Library:data:auto_adapted::' props internal name to contain a number of DSF files (geometry and morphs).The latter (Figure/Prop Asset) gives you more options when saving (vendor/product/item name) and uses these to create a subfolder structure ':My Library:data::::' with the DSF files.

Q2: So what is the difference between saving a prop as a 'Scene Subset' and as a 'Figure/Prop Asset'?

I've got used to being able to connect a Poser prop/pose file with a DSA script so I can do some custom stuff when I click the PP2/PZ2 icon. (basically by putting a .dsa file in the same folder as the .pp2/pz2 and using maclean's customized 'collectnodes()' which loads the pp2/pz2 with a call to 'App.getImportMgr().readFile( getArguments()[0] )'.) I've tried simply moving my existing DSA into the same folder as the DUF on the off-chance that it would work automatically... but it doesn't.

Q3: Is there a mechanism to automatically load a prop from a DUF/DSF file and run a DSA script?

Comments

  • rbtwhizrbtwhiz Posts: 2,267
    edited May 2014

    1) Correct. DSON is an acronym for DAZ Scene Object Notation. The DSON file format is based on JSON. JSON, and thus DSON, is described as "a lightweight data-interchange format."

    2) A Scene Subset is a DUF (DSON User-facing File) that is capable of defining an entire scene. It can embed the data that defines the scene, and/or it can reference externally stored "assets" that define different parts of a scene. The ability to select a "subset" of the scene aside, it is equivalent to a Scene [file] in every way, with one important distinction... A Scene [file] is "opened" (meaning, it replaces what is in the scene) by default, while a Scene Subset is "merged" (meaning, it adds to what may already be in the scene) by default.

    Saving an "Asset", of any kind, means that you are creating a/several DSF (DSON Support File) while simultaneously modifying the current scene [in memory] to reference those assets. This is advantageous because it allows you to define common assets once and reference/instantiate them many times, across many scenes. Not only does that significantly reduce the amount of disk space consumed by multiple scenes that share various combinations of the same objects, it is also part of a mechanism that allows a user to share a Scene [file] without also sharing the product(s) that the scene depends on.

    The "auto_adapted" folder [and the contents within it] is the result of importing a non-native object, whether that be an OBJ or a Poser Prop (PP2|PPZ) or some other non-native dataset, and saving it to the native format without first saving a proper asset. This is fine for working locally until proper assets are saved, but products should not be distributed in this form.

    3) Yes. It's used in, and is the result of work on, the Creature Creator Add-ons for Genesis 2 Female(s) product. At a basic level, you add custom Element Data (a "Post Load Data Item") to an Object or Figure (i.e. Main Menu Bar > Edit > Object > Element Data...) and then save. Near the end of the loading routine for the file that provides the element with the data item, the file at the path specified by the data item will be loaded. For a more involved example, I'd suggest picking up the product linked above and study that - the included script is not encrypted and is heavily commented.

    DAZ Studio supports data items that reference DAZ Script files (DSA/DSB/DSE). DSON Importer for Poser supports data items that reference a Poser Pose (PZ2) or a Poser Material Collection (MC6); which can reference Poser Python scripts should you need/want to perform more involved tasks.

    -Rob

    Post edited by rbtwhiz on
  • RainbowArtistRainbowArtist Posts: 101
    edited December 1969

    Thank you Rob, for this clear DSON explanation. It makes a lot more sense than other stuff I have read about what DSON is.
    All these acronyms and arcane terminology are so confusing until they have been properly explained. :exclaim:

    IMO, The most serious problem that DAZ Studio has had is the lack adequate documentation to help the user get the most out of the software, It has a nice customizable interface and lots of nifty advance features but often the user doesn't have a clue how to use them, me included. Now, the Studio ver. 3 had a good adequate manual, and the new Quick start Guide is good for new users getting started. But all the new advanced features, which are fantastic improvements, aren't intuitively obvious to most people in how you use them, so they need some clear documentation and tutorials for the new stuff. While there has been the DAZ Studio 4.x Reference Guide Wiki available, it has only the most superficial info and usually has absolutely no info about the subject you are needing help with, or goes to a dead '404 Page not Found' link.

    Lacking clear documentation, you have lots of frustrated people prowling the forums to find out how use the features that have been added. Sometimes they are rewarded by other users or gurus like yourself, who kindly provide the explanation or tutorial that lets them move forward to their creative goals. But much of that frustration could be avoided with comprehensive manual.

    Having worked in the software industry, I understand that it is not so easy to whip out great documentaion for complex software like DS, but it really is an essential part of the software package. Hopefully somebody at DAZ will do what needs to be done soon to help us really enjoy this fantastic artistic tool.

    Thanks to all you folks at DAZ for this wonderful software. :coolsmile:

  • 3dcheapskate3dcheapskate Posts: 2,719
    edited May 2014

    Thanks Rob, clear and detailed reply as usual . So I've now got my DUF file successfully calling my DSA file.

    I also need to ensure that the prop is automatically selected once it loads. This was done courtesy of macleans 'collectNodes()' before, but that method (which compared the nodes before/after loading the PP2) won't work with the DUF/DSA combination. So:

    - Is there a way in the DUF file to specify the prop is to be automatically selected? (I can't see any 'selected' or suchlike parameter, so I guess not)

    - Alternatively is there a foolproof way to tell which of the nodes returned by 'g_oSceneHelper.collectNodes()' is the most recently added? It seems to be the one with the highest index, but after deleting and adding many items to the scene I'm fairly sure this isn't guaranteed.

    Cheers!
    Pete

    (P.S. re the commented script in the G2F creature creator morphs - I already have the creature creator stuff for V3/M3/V4/M4, and only ever use Genesis to check that the stuff I'm doing works with it, so it's not really an option.)

    Post edited by 3dcheapskate on
  • rbtwhizrbtwhiz Posts: 2,267
    edited July 2015

    @RainbowArtist

    You probably don't realize this, but you are "preaching to the choir" as the saying goes. Trust... I'm the last person that needs convincing. A stronger proponent does not exist. Having said that, rather than let my frustrations on the topic get the better of me, I'll simply say that I hear you, loud and clear... Unfortunately, I'm not the one who needs to. If you feel inclined, you are free to use the Help > Contact Us link to submit feedback and/or make a request.

    @3dcheapskate

    The script that gets executed is provided a global transient variable named DataItem, of the DzElementPostLoadFileData type. Since the data item was added to a DzNode... and since that node takes ownership when it's added... and since DzElementPostLoadFileData inherits DzElementData (which provides a getOwner() method)... you can use DataItem.getOwner() to get the DzNode that caused the execution of the script associated with the data item. You'll want to be sure that you validate DataItem before you attempt to use it though...

    // 'DataItem' is a global transient variable, available when// this script is executed as a 'post load data item'// Declare a working variablevar sInfo;// If we found the 'DataItem' global transientif( typeof( DataItem ) != "undefined" ){    // Get the owner of the data item    var oOwner = DataItem.getOwner();        // Define a variable for extra object specific info    var sExtraInfo = "";    // If the data item is of the type we expect    if( DataItem.inherits("DzElementPostLoadFileData") ){        // Get some extra info        sExtraInfo = String("\nData File: %1").arg( DataItem.getPostLoadFilePath() );    }        // Construct the data portion of the message    var sDataInfo = String("Data Class: %1\nData Name: %2%3")            .arg( DataItem.className() ).arg( DataItem.name ).arg( sExtraInfo );        // Declare a working variable    var sOwnerInfo;        // If we have an owner    if( oOwner ){        // Construct the owner portion of the message        sOwnerInfo = String("Owner Class: %1\nOwner Name: %2\nOwner Label: %3")            .arg( oOwner.className() ).arg( oOwner.name ).arg( oOwner.getLabel() );    // If we don't have an owner    } else {        // Construct the owner portion of the message        sOwnerInfo = String("Oops... the '%1' data item doesn't have an owner.").arg( DataItem.name );    }        // Construct the message    sInfo = String("%1\n-----\n%2").arg( sDataInfo ).arg( sOwnerInfo );    // If we didn't find the 'DataItem' global transient;// this script was executed outside the context of a 'post load data item'} else {    // Construct the message    sInfo = "Oops... 'DataItem' doesn't exist.";}// Display the messageMessageBox.information( sInfo, "Data Item Info", "&Ok;" );

    This and other important details are covered in the script I mentioned in my previous response.

    -Rob

    Post edited by rbtwhiz on
  • 3dcheapskate3dcheapskate Posts: 2,719
    edited December 1969

    Thanks again Rob, that does the trick.

  • 3dcheapskate3dcheapskate Posts: 2,719
    edited December 1969

    Playing around a bit I've come across an unexpected problem. It happens if I save a scene which includes some of these props with attached scripts.

    Of course, when I load the scene from disk the scripts get called. Totally logical.

    But the scripts in question are purely for positioning the prop in the hand of the currently selected figure, parenting the prop to that figure's hand, and applying a hand pose to grip the prop. Of course, none of this needs to be done if you're loading from a scene file (or scene subset including the figure and prop) because the prop is already positioned, parented and gripped!

    I can't think of an obvious way around this little conindrum - anybody have any ideas?

  • Richard HaseltineRichard Haseltine Posts: 101,507
    edited December 1969

    Is the prop parented when the script runs on loading? if not you could test to see if it had a parent, then run the rest of the script only if it didn't. The other option that springs to mind would be adding a hidden numeric property and setting it to 1 when the script first runs, and have a check for that property at the beginning of execution.

  • 3dcheapskate3dcheapskate Posts: 2,719
    edited December 1969

    Since I also use the script to move an already-parented prop from the hand of one figure to the hand of another I'd already considered and scrapped those two options.

    But I've just done a double-check and I think that my decision was premature - looking at it again I think they'd both work...

    The script that's called as a Post Load Data Item is a small script specific to the prop, which simply calls a generic script and passes a couple of prop-specific parameters.
    The script for moving a prop that's already in the scene is a separate, similar small script, and also calls the same generic script with a couple of parameters.

    I'd only considered a test in the generic script - but of course the appropriate test in the Post Load Data Item script itself should work...

    Thanks Richard

  • 3dcheapskate3dcheapskate Posts: 2,719
    edited May 2014

    I've decided to load the prop with x/y/z rotations each set to 360. When the script's called, if they're all set to 360 then they get reset to zero and the rest of the script gets run. If they're not all 360 then the script terminates. A bit cack-handed, but it seems to work fine!

    Post edited by 3dcheapskate on
  • V3DigitimesV3Digitimes Posts: 3,172
    edited December 1969

    I have a similar issue.
    I understand that it is possible to load a dsa via duf when loading a prop, but could it also be done when using a material?

  • rbtwhizrbtwhiz Posts: 2,267
    edited June 2015

    Any DzElement derived object can have a DzElementPostLoadFileData and/or a DzSimpleElementScriptData added to it. The difference between the two being that a DzElementPostLoadFileData will simply cause a file to be loaded... while a DzSimpleElementScriptData will cause a script to be executed, and [because it inherits from DzSimpleElementData] it provides access to a DzSettings object that can be used to pass information to [and ultimately control] said script; which is accomplished by accessing the settings object and its values from the DataItem global transient, within said script.

    We do not provide UI to add these data items to a DzMaterial, so you'll have to do that using script, as in the Post-Load Script Data Item samples.

    -Rob

    Post edited by rbtwhiz on
  • V3DigitimesV3Digitimes Posts: 3,172
    edited December 1969

    Thank you Rob!
    I finally managed to do it, using a completely different method, less general than yours, but more adapted to my own need.
    But I kept your examples for further projects of the same kind I could have.

Sign In or Register to comment.