Custom JavaScript Components

We continue where we left off in Getting Started.

Overview 

Goal of this tutorial is to get you familiar with adding custom logic to your project.

We will be creating two scripts that allow counting the number of frames an object was looked at.

One script will be added to the camera and will cast rays to check if we are looking at a specific object. The other is added to an object to do the display of the frame count.

JavaScript Reloading 

To make our workflow as smooth as possibly, the editor will automatically watch changes to your JavaScript files and parse them on save.

If you have the app running in the browser it will even reload the page for you with the changes sources.

Create a JavaScript Component 

Right click the empty space in the “Asset Browser” and add a new JavaScript component.

Custom JavaScript Components

Name the component counting-gaze.js.

By double-clicking the file, it will be opened with the application you configured your system to open .js files with.

Code 

And finally, we fill the component with life. The following code sends out a ray cast into the scene every frame:

 1import {Component} from '@wonderlandengine/api';
 2
 3export class CountingGaze extends Component {
 4    static TypeName = 'counting-gaze';
 5
 6    origin = [0, 0, 0];
 7    dir = [0, 0, 0];
 8
 9    init() {
10        console.log('Counting gaze initialized');
11    }
12
13    update() {
14        /* Get the translation of this object and store it in "origin" */
15        this.object.getPositionWorld(this.origin);
16        /* Get the direction of this object and store it in "dir" */
17        this.object.getForwardWorld(this.dir);
18
19        /* Send a ray into the scene and see if it hits and object in
20         * collision group "1" or "2" */
21        const rayHit = this.engine.scene.rayCast(
22            this.origin, this.dir, (1 << 1) | (1 << 2));
23        if(rayHit.hitCount > 0) {
24            for(let i = 0; i < rayHit.hitCount; ++i) {
25                let o = rayHit.objects[i];
26
27                // TODO: We will count up the counter on the
28                // hit object here later instead!
29                console.log('Raycast hit object:', o.name);
30            }
31        }
32    }
33}

For now we are just printing the names of the objects we hit with our ray cast.

Add Component to Object 

This component is not run automatically. We need to attach it to the camera!

Custom JavaScript Components

Run 

To see the component in action, “Package” and “Open Browser”.

If you open the JavaScript console in your Browser with Ctrl + Shift + C, you will notice the component has been initialized.

Custom JavaScript Components

No object names are being printed, though. this.engine.scene.rayCast() uses the collision system, which only works with collider components. To make sure the ray cast hits something, we need to add more components!

Collision 

Add a child to the mailbox object as shown in the following screenshot. Add a collision component to that new child object.

Set the radius to, e.g., 0.15.

Custom JavaScript Components

With this setup, we can “Package” and see that the ray cast works.

Counting and Displaying 

We need to keep track of the count and finally display it with a text component.

Add a “text” component to our “Collider” object and change the text to “0”.

Then add a new JavaScript source file with the name gaze-counter.js.

 1import {Component, Property} from '@wonderlandengine/api';
 2
 3export class GazeCounter extends Component {
 4    static TypeName = 'gaze-counter';
 5    static Properties = {
 6        msg: Property.string('i')
 7    };
 8
 9    count = 0;
10
11    init() {
12        console.log('Gaze counter initialized');
13    }
14
15    start() {
16        this.textComp = this.object.getComponent('text');
17    }
18
19    update() {
20        this.textComp.text = `${this.msg} ${this.count}`;
21    }
22}

You will notice the msg property here. The editor will automatically generate an input field for it, when we add the component to the “Collider” object:

Custom JavaScript Components

Finally, replace the // TODO comment in counting-gaze.js with the following:

1    const counterComp = o.getComponent('gaze-counter');
2    if(counterComp) {
3        counterComp.count++;
4    }

Result 

“Package” and check the browser. You will now see the final result!

Custom JavaScript Components

Summary 

Wonderland Engine allows you to use any JavaScript library that runs in the browser.

With the automatic reloading, the workflow allows for very quick iterations.

Find the Wonderland Engine JavaScript API reference here and many bite-sized tutorials.