События

Логические ноды и JavaScript

2017-07-27

Blend4Web предлагает отличный визуальный редактор логики, с помощью которого можно программировать, не выходя из Blender. Для определенных задач этого хватает. Однако гораздо больше возможностей открывается при использовании JavaScript с полноценным доступом к API движка.

Возникает вопрос, можно ли совместить в одном приложении легкость визуального программирования и мощь кода на JavaScript? Оказывается, да. Разработчики Blend4Web предусмотрели такую возможность. Разберёмся в ней.

Нодовая логика

Основным элементом связи между нодовой логикой и JavaScript является узел JS Callback. Именно он обеспечивает вызов нужной функции в коде и передает ей параметры. Пока функция выполняет работу, JS Callback будет терпеливо ожидать результата. После завершения задачи, вызванная функция возвращает управление JS Callback, и цепочка логики продолжает работу дальше.

Рассмотрим простейший пример такого взаимодействия.

Допустим, в сцене есть объект, при выделении которого должна срабатывать некая функция в скрипте. При этом в код будет передаваться текстовое сообщение в духе «Hello World!». Хотя нет, тут будет более удачным возглас: «Эй, скрипт!».

Создадим цепочку логики, где будет создана соответствующая переменная и отслеживаться выделение объекта.

Это очень простая логическая цепь. Сначала инициализируется регистр R1 и присваивается ему текст «Hey Script!». Затем управление передается ноде Switch Select, которая ожидает выделение объекта Cube. Если это он, то управление передается дальше. Если нет, то ждем еще.

Следующая на очереди нода JS Callback!

Сначала нам нужно указать название функции, которая будет вызываться нодой. Это делается в поле Callback ID. Если требуется передать ей какие-либо данные, то следует добавить их в поле In Params.

Каждая переменная занимает отдельный слот, добавить который можно с помощью кнопки «+». Причем, JS Callback может передавать не только значения переменных, но и целые объекты сцены в виде массивов. В нашем случае, нужно указать в первом слоте регистр R1.

Допустим, нода JS Callback отработала и получила некий результат от вызываемой функции. Чтобы удостовериться в этом, выведем значение регистра R1 в консоль браузера с помощью узла Console Print.

В целом, готовая логическая цепочка должна выглядеть так…

Код JavaScript

Так как взаимодействие нодовой логики и JavaScript обеспечивается специальным модулем, то сначала нужно его импортировать.

var m_logic = require("logic_nodes");

Теперь зарегистрируем нашу функцию. Это следует сделать до загрузки самой сцены:

m_logic.append_custom_callback("node", node_cb);

Как видите, в ней имеется идентификатор «node», которое указывался в JS Callback, а также название функции.

А вот и сама функция:

function node_cb(input, output) {
    console.log (input[0]);
    output[0] = "Hey Logic!";
}

Обратите внимание, что нода JS Callback передает и принимает значения переменных в виде массива. Переменная Input[0] здесь содержит значение регистра R1, которое будет показано в консоли браузера. Далее функция возвращает output[0] с неким текстовым сообщением.

Нода JS Callback принимает результат, а следующая Console Print выводит текст в консоль браузера.

Полный код скрипта:

"use strict"

// register the application module
b4w.register("logic_nodes_js_main", function(exports, require) {

// import modules used by the app
var m_app       = require("app");
var m_cfg       = require("config");
var m_data      = require("data");
var m_preloader = require("preloader");
var m_ver       = require("version");
var m_logic     = require("logic_nodes");

// detect application mode
var DEBUG = (m_ver.type() == "DEBUG");

// automatically detect assets path
var APP_ASSETS_PATH = m_cfg.get_assets_path("logic_nodes_js");

/**
 * export the method to initialize the app (called at the bottom of this file)
 */
exports.init = function() {
    m_app.init({
        canvas_container_id: "main_canvas_container",
        callback: init_cb,
        show_fps: DEBUG,
        console_verbose: DEBUG,
        autoresize: true
    });
}

/**
 * callback executed when the app is initialized 
 */
function init_cb(canvas_elem, success) {

    if (!success) {
        console.log("b4w init failure");
        return;
    }

    m_preloader.create_preloader();

    // ignore right-click on the canvas element
    canvas_elem.oncontextmenu = function(e) {
        e.preventDefault();
        e.stopPropagation();
        return false;
    };
    m_logic.append_custom_callback("node", node_cb);
    load();
}

/**
 * load the scene data
 */
function load() {
    m_data.load(APP_ASSETS_PATH + "logic_nodes_js.json", load_cb, preloader_cb);
}

/**
 * update the app's preloader
 */
function preloader_cb(percentage) {
    m_preloader.update_preloader(percentage);
}

/**
 * callback executed when the scene data is loaded
 */
function load_cb(data_id, success) {

    if (!success) {
        console.log("b4w load failure");
        return;
    }

    m_app.enable_camera_controls();

    // place your code here

}

function node_cb(input,output) {
    console.log (input[0]);
    output[0] = " Hey Logic!";
}

});

// import the app module and start the app by calling the init method
b4w.require("logic_nodes_js_main").init();
Комментарии
Пожалуйста, зарегистрируйтесь или войдите под своей учетной записью , чтобы оставлять сообщения.