Using JavaScript in Verge3D applications

Thanks to the Puzzles, you can implement most of the functionality found in typical WebGL applications without writing a single line of code. However, there can be special cases where you may want to use JavaScript - for example, to leverage third-party programming libraries or to implement some non-trivial feature which cannot be realized with the Puzzles alone.
You can use any text editor for adding JavaScript code, but it is more convenient to work if your editor supports syntax highlighting and line numbering, like Notepad++ or Atom.

Method #1 (Basic)

Suppose you created your application using the App Manager (with default configuration options), and named it my_awesome_app. Go to the verge3d/applications folder and then to my_awesome_app folder, and open the JavaScript file my_awesome_app.js with your favorite text editor.
Search for "runCode" - this place in the file should look something like this:
function runCode(app) { // add your code here, e.g. console.log('Hello, World!'); }
You can add some code inside that declaration (between the curly brackets), so that it turns to:
function runCode(app) { // add your code here, e.g. console.log('Hello, World!'); console.log('Just added some JavaScript!'); }
Now, if you save the .js file and run your app you'll notice... nothing until you open the browser console. The latter can usually be opened with the F12 key (Chrome, Firefox on Windows, Linux). On Mac use the View > Developer > JavaScript Console menu (Option-Cmd-J) in Chrome, or the Develop > Show Error Console menu (Option-Cmd-C) in Safari.
With code you can change something in your scene, for example, move the default Verge3D cube (named "Box001" in 3ds Max and "Cube" in Blender)...
function runCode(app) { var obj = app.scene.getObjectByName('Cube'); obj.position.x = 2; }
... or create a new material out of thin air:
function runCode(app) { var obj = app.scene.getObjectByName('Cube'); obj.material = new v3d.MeshPhongMaterial({ color: '#00BB00', emissive: '#550000' }); }
Check out Verge3D code examples to get inspired. Click View source button to open the code for an example.

Method #2 (Versatile)

Adding your code inside the runCode function makes it executed upon application loading, once and for all. But what if you need some piece of code to be triggered by user action instead? For example, the user clicks on a 3D object and something should happen with that object.
This scenario can be implemented more easily with some help from Puzzles, rather than in pure code. You can setup capturing user events with Puzzles, and only perform special actions with code. This approach may save you a lot of time.
Open the application .js file (for example, my_awesome_app.js located in verge3d/applications/my_awesome_app) with your favorite text editor. Search for "prepareExternalInterface" and add a function inside that declaration (between the curly brackets), so that it looks like this:
function prepareExternalInterface(app) { app.ExternalInterface.myJSFunction = function() { console.log('Running my JavaScript function!'); } }
As you can see, the function was added to the app.ExternalInterface namespace - this is crucial for Puzzles to pick it up. You can add more functions with different names to this namespace if needed.
You can now trigger your function called "myJSFunction" from puzzles. To do this, run the Puzzles editor and add a puzzle call JS function to the workspace. By default it will trigger the function with the name "myJSFunction", so if your function is named differently, make sure to change its name in this puzzle's text field.
Now if you save your Puzzles and run your app, the puzzles scenario should trigger the function that you added, and the message should appear in the browser console.
More Puzzles can be added to make your function only run when the user clicks on an object.
If you'd like to pass a parameter from puzzles to your JavaScript function (for example, the name of the object the user clicked on), you can modify the call JS function puzzle by adding an input socket to it.
The code should also be modified for the function to accept a parameter as its argument:
function prepareExternalInterface(app) { app.ExternalInterface.myJSFunction = function(myObject) { console.log(myObject); } }
So, a code snippet that assigns a programmatically-generated material to whatever object is picked can look like this:
function prepareExternalInterface(app) { app.ExternalInterface.myJSFunction = function(myObject) { var obj = app.scene.getObjectByName(myObject); obj.material = new v3d.MeshPhongMaterial({ color: '#00DD00', emissive: '#880000' }); } }

Method #3 (–°ompact)

This method will suit experienced programmers who would like to have just a minimal working code snippet to begin with.
When creating a new application, switch the App Type selector to Custom:
This will result in a simpler project structure with no Puzzles editor attached to your application, and the app .js file will contain just a few lines of code:
'use strict'; window.addEventListener('load', function() { var app = new v3d.App('container', null, new v3d.SimplePreloader({ container: 'container' })); var url = 'my_awesome_app.gltf'; app.load(url, function() { app.enableControls(); runCode(); }); function runCode() { // add your code here, e.g. console.log('Hello, World!'); } });
Applications of this type are very simple yet they are still capable of loading a scene in .gltf format (with preloader), and offer standard camera controls to the user.
You can proceed by adding your code inside the "runCode" function as described in Method #1. Of course, you can completely overhaul this application template instead - for example, you can discard the App class, load the scene using some other file format or setup the controls in some specific way.

Method #4 (Hardcore)

You can take the v3d.js file from the verge3d/build folder, link it to an .html file and start coding! How did you think the code examples were created in the first place?