Skip to content

How to integrate HFSM into your WebGME project

William Emfinger edited this page Mar 9, 2018 · 1 revision

Adding the Meta

You can simply import the base seed as a Library within your project or use it as the base for creating your own meta.

Adding the HFSM Visualizer

Use the webgme-cli

webgme import viz HFSMViz webgme-hfsm

Adding the SoftwareGenerator Plugin

Use the webgme-cli

webgme import plugin SoftwareGenerator webgme-hfsm

Configuring the CodeEditor Visualizer

Update your CodeEditor component config to include the CodeEditor config from webgme-hfsm's component config.

Updating your webgme config

In your webgme config (e.g. config.webgme.js or config.default.js), you'll want to add the following dependencies:

config.requirejsPaths['hfsm'] = './node_modules/webgme-hfsm/src/common/'; 
config.requirejsPaths['hfsm-library'] = './node_modules/webgme-hfsm/'; 

Calling the SoftwareGenerator plugin from your own plugin code

Assuming you've updated your config according to the section above, you can load the SoftwareGenerator plugin into your own plugin at the path

'hfsm-library/src/plugins/SoftwareGenerator/SoftwareGenerator'

e.g.

define([
   ...
   'hfsm-library/src/plugins/SoftwareGenerator/SoftwareGenerator',
   ...
], function(
   ...
   hfsmSoftwareGenerator
   ...
){
   let hfsmSW = new hfsmSoftwareGenerator();
   hfsmSW.notify = function(level, msg) { console.log(`${level}::${msg}`); } // can replace with your own logger

Then in you function you can use it like click here to see a more complete version of this example:

    MyNewPlugin.prototype.generateHFSM = function(projectModel) {
        var self = this;
        var hfsmSW = new hfsmSoftwareGenerator();
        hfsmSW.notify = function(level, msg) {self.notify(level,msg);}

        var originalRoot = projectModel.root;

        hfsmSW.setProjectModel(projectModel);
        function objToFilePrefix(obj) {
            // object here will be a stateMachine
            // get the package name from parent->parent (comp->package)
            var filePrefix = null;
            var comp = obj.parent;
            var pkg = comp.parent;
            if (comp.type == 'Component' && pkg.type == 'Package') {
                var pkgName = pkg.name;
                var compName = comp.name;
                var prefix = 'src';
                filePrefix = prefix + '/' + pkgName + '/include/' + pkgName + '/' + compName + '_HFSM/';
            }
            return filePrefix;
        }
        // add component includes to State Machines
        Object.keys(projectModel.objects).map(function(k) {
            var obj = projectModel.objects[k];
            if (obj.type == 'State Machine') {
                var comp = projectModel.objects[obj.parentPath];
                var pkg = projectModel.objects[comp.parentPath];
                if (comp.type == 'Component' && pkg.type == 'Package') {
                    var pkgName = pkg.name;
                    var compName = comp.name;
                    var includes = [
                        `#include "${pkgName}/${compName}.hpp"`,
                        `class ${compName};`,
                        ''
                    ].join('\n');
                    obj.Includes = includes + obj.Includes;
                    // make sure we have functions and pointers to the component itself
                    var declarations = [
                        `static ${compName}* this_component;`,
                        `void setComponentPtr( ${compName}* c ) { this_component = c; }`,
                        ''
                    ].join('\n');
                    obj.Declarations = declarations + obj.Declarations;
                    var definitions = [
                        `${compName}* StateMachine::${obj.sanitizedName}::this_component;`,
                    ].join('\n');
                    obj.Definitions = definitions + obj.Definitions;
                }
            }
        });
        // now render the HFSM code
        var hfsmArtifacts = hfsmSW.generateArtifacts(self.result, false, false, objToFilePrefix)
        self.artifacts = Object.assign(self.artifacts, hfsmArtifacts);

        projectModel.root = originalRoot;
    };

In that example we are injecting some more code into the generated state machine code and also providing a prefix for how the HFSM code generator should create its files.