Attaching text/JSON files to the compiled binary?
-
Hi everyone,
I'm trying to figure out how to add JSON files to the compiled plugin in order to access to them in HISEScript. I really tried to use some "tricks" like:- Pre-loading the JSON-file content into a panel value as an object, but it doesn't really work on the compiled binary (only works during development).
- Saving the encrypted object into a panel's property (e.g.
panel.set( 'text', encryptedJSON )
). - Save them (JSON files) as a image file or audio during development but (obviously) the compilation crashes because is not a valid image/audio file.
The only viable option I have is to include the JSON files in the plugin's installer to extract them in some folder like the
%appdata%
. Anyways I really interested about finding a way to already include the files in the compiled binary.Basically, I need to use the JSON files for multiple purposes, like importing filmstrips automatically (created with a tiny tool I made that exports a JSON file with all coordinates).
-
@diablo99 Put the objects in a regular script file, .js
-
@d-healey The problem is that these files are dynamic, they change depending on each project. However, it seems to me a good solution (combined with what I have tried before), later in the day I will try to create a .js file that will be modified during the development to be able to access the data during the compilation.
Thanks for the advice, if it works I will post the solution in case someone has the same problem :)
-
@diablo99 I use a bunch of JSON files in my product(s) so
- you will need to have a "default" version in your plugin - probably somewhere like David suggests as a separate include .js file
- when the plugin starts it should try and read the json from disk - if its not there it should write the default to disk.
- next process the contents of your json file
- when you make changes to your data - update the json on disk.
-
Thank you for your suggestions,
I made this little "module" to access to pre-stored objects during production (compiled binary). I will leave it here in case someone has the same problem (already tested with pluginval).Note: Remember, the goal is to be able to access JSON files that cannot be added directly into the compiled binary, so data-writing is only available during development.
First add this script in your Scripts/ folder and create an additional
JSONStorage.data
file in the same folder (you can executeJSONStorage.createDataFile()
from console after compiling your project with the next script included):// JSONStorage.js /** * Store JSON data during development to use in production. * @namespace JSONStorage * @property {Object} data - The current object where all JSON data is stored. * @property {Boolean} ignoreWarnings=false - Don't show warning messages in production-mode (e.g. trying to write data-file during production). * @property {Boolean} autoWrite=true - Write data-file automatically at every change. * @example * JSONStorage.set( 'myJson', { myProp : 1 } ) ; // <- Only in dev-mode, in production it will be skipped with a warning-message. * var json = JSONStorage.get( 'myJson' ) ; * var data = json.data ; // <- Already saved data (cached) in 'Scripts/JSONStorage.data' file. * Console.print( trace( data ) ) ; // <- Expected : "{ myProp : 1 }" */ namespace JSONStorage { /** Current cached data (Stored-Objects) */ reg data = { } ; /** If enabled, the warning messages in prod-mode will not showing */ reg ignoreWarnings = false ; /** If enabled, the data-file will be written automatically after every change. */ reg autoWrite = true ; /** Check current enviroment (DEV/PROD) */ const var DEV = Engine.isHISE( ) ? true : false ; /** * Get the data-file reference from "Scripts/" folder (Only works during development). * @memberof JSONStorage * @function getDataFile * @returns {FileObject} */ inline function getDataFile( ) { if( !DEV && ignoreWarnings != true ) { Console.print( 'WARNING: (JSONStorage) You are trying to access to the JSONStorage.data file during production mode.' ) ; } // prod-mode notice [^] ; local scriptsDir = FileSystem.fromReferenceString( '{PROJECT_FOLDER}../Scripts/', FileSystem.AudioFiles ) ; return scriptsDir.getChildFile( 'JSONStorage.data' ) ; } ; /** * (DEV) Call this function to a quick data-file creation (remove `"include( 'JSONStorage.data' )" first to avoid errors`). * @memberof JSONStorage * @function createDataFile * @returns {Void} */ inline function createDataFile( ) { if( !DEV && ignoreWarnings != true ) { Console.print( 'WARNING: JSONStorage.createDataFile( ) is only available at development (skipping).' ) ; return void 0 ; } // create if doesn't exists [v] local scriptFile = getDataFile( ) ; if( !scriptFile.isFile( ) ) { scriptFile.writeString( "/** JSON STORAGE */" ) ; } // finish [v] ; return void 0 ; } ; /** * Store the given JSON-Object into the current data and print a message in the console (used by the `"JSONStorage.data"` file). * @param {Object} json - The object to store in the data-file. * @memberof JSONStorage * @function loadData * @returns {Void} */ inline function loadData( json ) { if( typeof json != 'object' ) { return Console.print( 'ERROR:JSONStorage.loadData( ) requires 1 parameter: json<Object>.' ) ; } // store in data prop [v] ; data = json ; Console.print( 'JSON-STORAGE-DATA LOADED.' ) ; return void 0 ; } ; /** * Get a stored JSON-Object with the given *key*. * @param {String} key - The key of the stored object. * @memberof JSONStorage * @function get * @returns {Object|Null} */ inline function get( key ) { if( typeof key != 'string' ) { return Console.print( 'ERROR:JSONStorage.get( ) requires 1 parameter: key<String>' ) ; } else if( typeof data != 'object' ) { data = { } ; } // retreive [v] ; return data[ key ] ; } ; /** * (DEV) Write all current data into the `"JSONStorage.data"` file to be available during production mode (or next compilation). * @memberof JSONStorage * @function write * @returns {Void} */ inline function write( ) { if( !DEV && ignoreWarnings != true ) { Console.print( 'WARNING: JSONStorage.write( ) is only available during development (skipping).' ) ; return void 0 ; } // save [v] ; local fileContent = 'JSONStorage.loadData( ' + JSON.stringify( data ) + ' ) ;' ; local scriptFile = getDataFile( ) ; if( !scriptFile.isFile( ) ) { createDataFile( ) ; } scriptFile.writeString( fileContent ) ; Console.print( 'JSON-STORAGE-DATA UPDATED.' ) ; return void 0 ; } ; /** * (DEV) Store a JSON-Object with the given *key*. * @param {String} key - The object key to store in the data-file. * @param {Object} value - The actual object to store in the data. * @memberof JSONStorage * @function set * @returns {Void} */ inline function set( key, value ) { if( typeof key != 'string' || typeof value != 'object' ) { return Console.print( 'ERROR:JSONStorage.set( ) requires 2 parameters: key<String> & value<Object>' ) ; } // continue [v] ; if( typeof data != 'object' ) { data = { } ; } data[ key ] = value ; if( autoWrite == true ) { return write( ) ; } else { return void 0 ; } } ; /** * (DEV) Remove an specific object object from the stored data. * @memberof JSONStorage * @function remove * @returns {Void} */ inline function remove( key ) { if( typeof key != 'string' ) { return Console.print( 'ERROR:JSONStorage.remove( ) requires 1 parameter: key<String>.' ) ; } else if( !isDefined( data[ key ] ) ) { return void 0 ; } // remove [v] ; data[ key ] = null ; local obj = { } ; local z ; for( z in data ) { if( !isDefined( data[ z ] ) ) { continue ; } obj[ z ] = data[ z ] ; } // finish [v] ; data = obj ; if( autoWrite == true ) { return write( ) ; } else { return void 0 ; } } ; /** * (DEV) Remove all objects from cached-data. If `autoWrite` is enabled, it will clear the `"JSONStorage.data"` file too. * @memberof JSONStorage * @function clear * @returns {Void} */ inline function clear( ) { data = { } ; if( autoWrite == true ) { return write( ) ; } else { return void 0 ; } } ; /** * (DEV) Load a given file and stores it in the cached data. * @param {FileObject|String} fileOrPath - The file or file-path to use in object loading. * @param {String|Null} key=null - The *key* to use locate the loaded object into the *data*. If not set, the filename will be used as *key*. * @param {Null|Boolean} forceUpdate=false - If set `false`, the object will be not loaded if already exists in the current cached-data. * @memberof JSONStorage * @function loadFile * @returns {String} - The key used to access to the data (the filename without extension). * @example * JSONStorage.loadFile( '{PROJECT_FOLDER}../Objects/MyFile.json', null, true ) ; * // It will be saved as 'MyFile' ; * var json = JSONStorage.get( 'MyFile' ) ; */ inline function loadFile( fileOrPath, key, forceUpdate ) { if( !DEV && ignoreWarnings != true ) { Console.print( "(JSONStorage) You are trying to load a JSON-file during production-mode (skipping)." ) ; return void 0 ; } // skip during prod-mode [^] ; if( !isDefined( fileOrPath ) ) { return Console.print( 'ERROR:JSONStorage.loadFile( ) requires 3 parameters: fileOrPath<FileObject|String>, key<Null|String> & replace<Null|Boolean>.' ) ; ; } // get file ref [v] ; local file = typeof fileOrPath != 'string' ? fileOrPath : fileOrPath.indexOf( '{PROJECT_FOLDER}' ) == 0 ? FileSystem.fromReferenceString( fileOrPath, FileSystem.AudioFiles ) : FileSystem.fromAbsolutePath( fileOrPath ) ; if( !file.isFile( ) ) { return Console.print( 'ERROR:(JSONStorage) No JSON file found "' + file.toString( 0 ) + '"' ) ; } // check [v] ; local force = forceUpdate == true ? true : false ; local name = typeof key == 'string' ? key : file.toString( 1 ) ; if( !isDefined( data ) ) { data = { } ; } else if( typeof data[ name ] == 'object' && force == false ) { return name ; } // store it [v] ; local json = file.loadAsObject( ) ; data[ name ] = json ; if( autoWrite == true ) { write( ) ; } return name ; } ; } ;
And now you will be able to add your JSON files during development to access them in production (compiled binary):
include( 'JSONStorage.js' ) ; include( 'JSONStorage.data' ) ; // <- You must include the data file just after the given script. // LOADING FILES ; JSONStorage.loadFile( '{PROJECT_FOLDER}../MyObjectsFolder/MyObject.json', null, false ) ; // [^] Load 'MyObject.json' with no custom key (using the filename as key) and not update it at every compilation. var file = FileSystem.fromAbsolutePath( 'C://myObject/path.json' ) ; JSONStorage.loadFile( file, 'absoluteObject', true ) ; // [^] Loads 'path.json' from file-object with custom key ("absoluteObject") and update it at every compilation. // MANUAL ADD JSONStorage.set( 'myManualObject', { prop1 : 'value' } ) ; // All changes will be saved automatically into "JSONStorage.data" file 'cause JSONStorage.autoWrite is enabled. // GET OBJECTS ; var myObject = JSONStorage.get( 'MyObject' ) ; // The first json-file loaded in this example. var data = JSONStorage.data ; Console.print( trace( data ) ) ; // EXPECTED PRINT [v] ; // { // MyObject : ... , // absoluteObject : ... , // myManualObject : ... // } //
Some tips:
Try to make data-changes only if you are in dev-mode.var devMode = Engine.isHISE( ) ; if( devMode == true ) { // LOAD FILES [v] JSONStorage.loadFile( 'FILE_PATH', 'myJSONFile', false ) ; } var myObject = JSONStorage.get( 'myJSONFile' ) ;
By default, to avoid errors, the module will skip changes (writing) in production mode, but it will print a WARNING message in the console. If you want to remove those message, just set the
ignoreWarnings
property totrue
in order to use all features without getting warnings (in production mode).JSONStorage.ignoreWarnings = true ; JSONStorage.loadFile( ... ) ;
Hope it can be helpful to someone :)
-
This post is deleted!