Dual v4_v6 Script Example: Inheritance, Modules

PraxisPraxis Posts: 285

Summary:
 The Main script file together with its associated modules demonstrates one way to implement Inheritance and Modules in DAZ Script so that the same files can be used in both v4 and v6.
  It demonstrates a simple Personnel App with an Inheritance hierarchy like this:
    BaseObject      : Provides className() and inherits() functions (like a QObject)
      Person           : A BaseObject with FirstName, LastName properties
        Employee    : A Person with ID property
          Manager   : An Employee with Department property
  This mechanism is intended only for non-trivial applications that would be simplified by using inheritance and/or modules - i.e. it would be overkill for many simple utilities.

 Files (attached to this post):
   Test_v4_v6_Main.dsa   : Top-level script, containing the Main Routine of the Application:
                                     Open it in the Script IDE Pane and Execute it from there.
   zzzOBJ_lib.dsa   : Module: App-generic BASE Object class
   zzzUTY_lib.dsa   : Module: App-generic Library of Utility facilities
   zzzPER_lib.dsa   : Module: App-specific: Simple Personnel facilities

 Inheritance:
  Inheritance between Object Classes is implemented via the ECMAScript 'Object.create( <prototypeObj> )'
    mechanism, and involves no version-specific code: https://docs.daz3d.com/public/software/dazstudio/4/referenceguide/scripting/api_reference/object_index/object
  Note that v4 does not recognize v6 stuff like: class, extends, constructor(), super()

 Modules:
  In v4: Modules are simply external script files 'included' into the Main script in its Global scope, i.e. before any anonymous function that serves as the Main Routine.
    The 'include()' commands execute only within v4-specific code that is activated by testing: if( (App.versionString < '6.') ) { ...v4-specific code.
    All facilities in the Global scopes of the Main script, and of all modules already 'included', automatically become visible to the code in the 'included' module.
    All facilities in the Global scope of a module automatically becomes visible to all code following the 'include()' command that loaded that module.

  In v6: Modules are implemented via the CommonJS facilities provided by DSv6, i.e:
    Modules Export their facilities by adding them as properties to their 'module.exports' Object provided by the v6 script context.
    Scripts Import facilities from a module via the 'require(<module>)' function provided by the v6 script context, which returns the 'module.exports' Object from the <module>.
    The 'module.exports' and 'require()' commands execute only within v6-specific code that is activated by testing: if( (App.versionString >= '6.') ) { ...v6-specific code.
    NO facilities in the Global scopes of the Main script, or of any modules already 'required', automatically become visible to the code in the 'required' module.
      BUT: You can 'inject' visibility of any existing facilities into any module:
        Immediately after the 'require()' call,
        by passing the relevant context data to an Exported function of the module,
        which saves references to that context into its local scope,
        all of which must occur before the module refers to such Context in its body.
      In this demo that is done by passing Object g_zzzAPP_Context to a LoadAppContext() function that is provided by each relevant module.
    ONLY facilities explicitly Exported by the 'module.exports' command are visible outside the module.

 I found it simplest to develop the code in v4, which automatically excludes any v6-specific commands, and only once that is working add the version-specific IMPORTS and EXPORTS sections  to handle the differences in module scope.

 I am NOT expert in any of DAZScript, QtScript, ECMAScript, or JavaScript. If you can suggest better ways to do this, please post them to this forum topic.

Hope you find this useful.

P

dsa
dsa
Test_v4_v6_Main.dsa
19K
dsa
dsa
zzzOBJ_lib.dsa
8K
dsa
dsa
zzzUTY_lib.dsa
8K
dsa
dsa
zzzPER_lib.dsa
15K
Post edited by Praxis on

Comments

  • PraxisPraxis Posts: 285
    edited September 3

    The v6 Script Context:

    As at: v6.25.2026.19821

    The Script Engine post of the "evergreen" thread summarizes the Context provided to scripts in v6.

    The attached file Test_v6_Context.dsa reports some details of that Context - open and run it from the Script IDE.

    Some key points from the output of this test:

    1. At present the require() call that imports a Module requires an Absolute file path:  If you specify a relative path the default directory is the DS v6 .executable install directory - which is probably not what you want.  So: You need to either put your module files in a directory whose path you can get from DS at runtime - e.g. via App.getContentMgr().getContentDirectory( 0 )+'/data/You/YourApp/modules/' or if your modules are in a directory relative to your top-level script then you need to get that top-level directory name at runtime.  BUT...
    2. The exports, require, module, __filename, __dirname values are empty when the script is executed from the Script IDE Pane, or when executed direct from disk via a .djl shortcut.  That means you cannot use the __dirname or __filename values to get the path to any Modules that are in the same directory as your top-level script.  So you need to use a different method - which is demonstrated in the attached Test_v6_Context.dsa
    3. *** UPDATE 2026-Sep-04 ***  Points 1 and 2 above apply only if the script disk file uses CRLFs as End-Of-Line characters - if it uses LFs only then __dirname and __filename behaved as desired, as per the new file I've attached to this post: Test_v6_Context_LFsOnly.dsa.  I'll update these first 2 posts accordingly when i get some more time.  Meantime, I have reported this bizzare behaviour in Ticket #504845

    Attached .dsa file updated 2026-Sep-03

    dsa
    dsa
    Test_v6_Context.dsa
    10K
    dsa
    dsa
    Test_v6_Context_LFsOnly.dsa
    10K
    Post edited by Praxis on
  • PraxisPraxis Posts: 285

    reserved

  • TugpsxTugpsx Posts: 921

    Very cool, thanks for sharing. The process of making the script in DS4 and then porting to DS6 has been what I have adopted in the past. Will check to see how this class process could fit into the workflow. 

  • PraxisPraxis Posts: 285
    edited September 1

    Tugpsx said:

    Very cool, thanks for sharing. The process of making the script in DS4 and then porting to DS6 has been what I have adopted in the past. Will check to see how this class process could fit into the workflow. 

    You are very welcome.  Looking forward to your feedback.

     

    Post edited by Praxis on
Sign In or Register to comment.