Skip to content

Updates in xeogl v0.9

Lindsay Kay edited this page Sep 24, 2018 · 43 revisions

Annotated hand anatomy loaded from glTF - [Run demo]

Contents

V0.9 Overview

This v0.9 release essentially upgrades xeogl to ES6, which lets us more easily integrate it with our modern JavaScript apps. It also contains one small API change, which was required in order to be able to modularize the library and build it using Rollup.

ES6 classes

(See issue 272)

In v0.9 all core components are now implemented as ES6 classes. Therefore, when you need to extend xeogl by subclassing those, your subclasses will also be ES6 classes (see below). This turned out to be a win in terms of clean code and modularity.

Like THREE.js, only the core components are ES6 modules. The non-core component subclasses bundled with examples are also of course ES6 classes, but are regular JS files instead of modules, so that we can simply include them in pages using <script> tags. When you need to use those in your apps, you should make your own ES6 modules based on them.

We're still using YUIDoc to generate API docs, since that's got all the tags we need to support an object-oriented API. In future, we may switch to ESDoc, however that's a pretty big job since many tags in the API comments will need to be converted.

Building with Gulp

In v0.9 we're now using Gulp and Rollup to build the xeogl binaries.

This builds two versions of xeogl in the build directory:

  1. xeogl.js - a UMD module
  2. xeogl.module.js - an ES6 module

Getting and setting the default scene

In v0.8 we can set and get the current default xeogl.Scene via the static xeogl.scene property. In v0.9, I've just replaced that property with xeogl.getDefaultScene() and xeogl.setDefaultScene( myScene ).

In v0.8 (EC5), it was:

// Get default scene, internally creating first if needed
var theDefaultScene = xeogl.scene; 

// Set the default scene
xeogl.scene = new xeogl.Scene({... });

// Subsequently created components will be within xeogl.scene
// if no scene is explicitly provided for them.

var myObject = new xeogl.Mesh({
    geometry: new xeogl.TorusGeometry({... }),
    material: new xeogl.MetallicMaterial({ ... }),
    //...
});

Now in v0.9 (EC6) it is:

// Get default scene, internally creating first if needed
var theDefaultScene = xeogl.getDefaultScene(); 

// Set the default scene
xeogl.setDefaultScene( new xeogl.Scene({... }) );

// Create an object in the default scene
var myObject = new xeogl.Mesh({
    geometry: new xeogl.TorusGeometry({... }),
    material: new xeogl.MetallicMaterial({ ... }),
    //...
});

The reason for this is simply that the xeogl namespace is constructed by a file (src/xeogl.js) that exports all the members of that namespace, and we're not able to export an object property.

So to upgrade your apps, just search for all occurrences of xeogl.scene in your code and convert accordingly.

Subclassing components

xeogl components are now ES6 classes. Therefore, if you extend those components, your subclasses will now look like this:

// Define the ColoredTorus component class

class ColoredTorus extends xeogl.Component {

    // The component "constructor", which initializes the component instance:

    init(cfg) {

        super.init(cfg); // Make sure you call the super class constructor!

        // Note how each component is instantiated with a reference
        // to this ColoredTorus. This means they will inherit this 
        // ColoredTorus' Scene, and will be automatically destroyed 
        // when this ColoredTorus is destroyed.

        this._torus = new xeogl.Mesh(this, {
            geometry: new xeogl.TorusGeometry(this, {radius: 2, tube: .6}),
            material: new xeogl.MetallicMaterial(this, {
                baseColor: [1.0, 0.5, 0.5],
                roughness: 0.4,
                metallic: 0.1
            })
        });

        this.color = cfg.color; // Calls the `color` setter defined below
    }

    // Properties are now defined as ES6 getters and setters (if mutable):

    set color(color) {
        this._torus.material.baseColor = color || [0.5, 0.5, 0.5];

        // Fire change events for the color property, if useful.
        this.fire("color", this._torus.material.baseColor);
    }

    get color() {
        return this._torus.material.baseColor;
    }

    // The component "destructor", which releases any resources set up 
    // by the init() method (the "constructor"). This overrides the 
    // super class' destroy() method, and needs to invoke that super method. 

    // If your subclass doesn't set up any resources, however, then you 
    // don't need to define it, however, we'll define it here for 
    // demonstration.

    destroy() { // Redundant really, since subclass ads nothing new here
        super.destroy(); // Make sure you call the super class destructor!
    }
}

// Instantiate a ColoredTorus (in the default xeogl.Scene)
var coloredTorus = new ColoredTorus({
    id: "myColoredTorus",
    color: [0.3, 1.0, 0.3]
});

// Update the ColoredTorus color property
coloredTorus.color = [0.3, 0.3, 1.0];

coloredTorus.destroy();
  • We don't need to provide a type property on our classes anymore, unless you really need that to check their class types. When you don't provide that, your subclasses will just inherit the type of their superclasses, which is fine for most purposes.

Removed example component subclasses

To keep the maintenance overhead manageable, these classes were removed from the bundled examples:

  • HeighMapGeometry - a subclass of xeogl.Geometry which generated a heightmap from a texture.