<commit_before>Backbone.Siren = (function (_, Backbone, undefined) {
    'use strict';

    // The store-cache
    var _store = {}

    /**
     * Super simple store.  Good enough for now.
     *
     * @type {Object}
     * @private
     */
    , store = {

        /**
         *
         * @param {Backbone.Siren.Model} model
         * @return {Backbone.Siren.Model}
         */
        add: function (model) {
            return _store[model.url()] = model;
        }

        /**
         *
         * @param {Backbone.Siren.Model} model
         * @return {Boolean}
         */
        , exists: function (model) {
            return !!_store[model.url()];
        }

        /**
         *
         * @return {Array}
         */
        , all: function () {
            return _store;
        }
    }

    /**
     *
     * @type {Object}
     * @private
     */
    , warn = function () {
        if (Backbone.Siren.settings.showWarnings && console) {
            console.warn.apply(console, arguments);
        }
    };

    /**
     *
     * @param {Backbone.Siren.Model|Backbone.Siren.Collection} parent
     * @param actionData
     * @constructor
     */
    function Action(actionData, parent) {
        _.extend(this, actionData);
        this.parent = parent;
    }

    Action.prototype = {

        /**
         *
         * @param name
         * @return {*}
         */
        getFieldByName: function (name) {
            return _.find(this.fields, function (field) {
                return field.name == name;
            });
        }

        /**
         *
         * @param {Object} options
         * @return {$.Deferred|undefined}
         */
        , execute: function (options) {
            if (! this.parent) {
                return;
            }

            var defaults = {
                url: this.href
                , actionName: this.name
                , method: this.method
                , type: this.type
                , validate: true
                , patch: true
                , content: 'application/vnd.siren+json'
            };

            options = _.extend(defaults, options);
            return this.parent.save(this.parent.getAllByAction(this.name), options);
        }

    };

    /**
     *
     * @static
     * @param name
     * @return {String}
     */
    function toCamelCase(name) {
        return name.replace(/(\-[a-z])/g, function(match){return match.toUpperCase().replace('-','');});
    }

    /**
     *
     * @static
     * @param entity
     * @return {String}
     */
    function getUrl(entity) {
        var link, url;

        if (entity.href) {
            url = entity.href;
        } else if (entity.links) {
            link = entity.links.filter(function (link) {
                return !!(link.rel && link.rel.filter(function (relType) {
                    return relType == 'self';
                }).length);
            })[0];

            if (link) {
                url = link.href;
            }
        } else {
            warn('Missing href or "self" link');
            url = '';
        }

        return url;
    }

    /**
     * Access to the representation's "self" url, or its "href" if there is one.
     *
     * @return {String}
     */
    function url() {
        return getUrl(this._data);
    }

    /**
     *
     * @static
     * @param {Object} sirenObj Can be a siren entity or siren action object
     * @return {Array}
     */
    function getClassNames(sirenObj) {
        return sirenObj['class'] || [];
    }

    /**
     *
     * @static
     * @param {Array} entities
     * @param {Object} filters
     * @return {Array}
     */
    function filter(entities, filters) {
        return _.filter(entities, function (entity) {
            return hasProperties(entity, filters);
        });
    }

    /**
     *
     * @param {Backbone.Siren.Model|Backbone.Siren.Collection} bbSiren
     * @param {Object} filters
     * @return {Boolean}
     */
    function hasProperties(bbSiren, filters) {
        var _hasProperties = true;

        if (filters.className) {
            _hasProperties = bbSiren.hasClass(filters.className);
        }

        if (filters.rel) {
            _hasProperties = bbSiren.rel() == filters.rel;
        }

        return _hasProperties;
    }

    /**
     *
     * @param {Object} action
     * @param {Object} filters
     * @return {Boolean}
     */
    function actionHasProperties(action, filters) {
        var hasProperties = true;

        if (filters.className) {
            hasProperties = _hasClass(action, filters.className);
        }

        if (filters.name) {
            hasProperties = action.name == filters.name;
        }

        return hasProperties;
    }

    /**
     *
     * @static
     * @param sirenObj
     * @param className
     * @return {Boolean}
     */
    function _hasClass(sirenObj, className) {
        return _.indexOf(getClassNames(sirenObj), className) > -1;
    }

    /**
     *
     * @param className
     * @return {Boolean}
     */
    function hasClass(className) {
        return _hasClass(this._data, className);
    }

    /**
     * Accesses the "class" property of the Siren Object
     *
     * @return {Array}
     */
    function classes() {
        return getClassNames(this._data);
    }

    /**
     *
     * @param {String} rel
     * @return {Array}
     */
    function links(rel) {
        var _links = this._data.links;

        if (rel) {
            _links = _.filter(_links, function (link) {
                return _.indexOf(link.rel, rel) > -1;
            });
        }

        return _links || [];
    }

    /**
     *
     * @param {String} rel
     * @return {Array} An array of jqXhr objects.
     */
    function request(rel) {
        var self = this
        , requests = []
        , links = this.links(rel);

        _.each(links, function (link) {
            requests.push($.getJSON(link.href, function (sirenResponse) {
                self.parseEntity(sirenResponse);
            }));
        });

        return requests;
    }

    /**
     *
     * @static
     * @param sirenObj
     * @return {String}
     */
    function getRel(sirenObj) {
        var rel = sirenObj.rel;

        if (rel) {
            rel = rel[0]; // @todo, arbitrarily grabbing the first rel might be bad but I still don't understand the use case for many rels...
            rel = rel.slice(rel.lastIndexOf('/') + 1, rel.length);
        }

        return rel;
    }

    /**
     *
     * @return {String}
     */
    function rel() {
        return getRel(this._data);
    }

    /**
     *
     * @param filters
     * @return {*|Array}
     */
    function actions(filters) {
        var _actions = this._actions;

        if (filters) {
            _actions = _.filter(_actions, function (action) {
                return actionHasProperties(action, filters);
            });
        }
        return _actions;
    }

    /**
     *
     * @param {String} actionName
     * @return {Object}
     */
    function getAllByAction(actionName) {
        var values
        , action = this.getActionByName(actionName)
        , self = this;

        if (action) {
            values = {};
            _.each(action.fields, function (field) {
                if (self instanceof Backbone.Model) {
                    values[field.name] = self.get(field.name);
                } else {
                    values[field.name] = self.meta(field.name);
                }

            });
        }

        return values;
    }

    /**
     *
     * @param {String} name
     * @return {Object|undefined}
     */
    function getActionByName(name) {
        return _.find(this._actions, function (action) {
            return action.name == name;
        });
    }

    /**
     * Access to the representation's "title"
     *
     * @return {String}
     */
    function title() {
        return this._data.title;
    }

    /**
     *
     * @return {Array}
     */
    function parseActions() {
        var self = this
        , _actions = [];

        _.each(self._data.actions, function (action) {
            var bbSirenAction = new Backbone.Siren.Action(action, self);

            _actions.push(bbSirenAction);

            if (action.name) {
                self[toCamelCase(action.name)] = _.bind(bbSirenAction.execute, bbSirenAction);
            } else {
                warn('Action is missing a name, unable to add top level method', action);
            }
        });

        self._actions = _actions;
        return _actions;
    }

    return {
        settings: {
            showWarnings: true
        }

        , store: store
        , warn: warn
        , Action: Action

        , Model: Backbone.Model.extend({

            url: url
            , classes: classes
            , hasClass: hasClass
            , rel: rel
            , title: title
            , actions: actions
            , links: links
            , getActionByName: getActionByName
            , getAllByAction: getAllByAction
            , parseActions: parseActions
            , request: request

            /**
             *
             * @param {Object} sirenObj
             * @param {Object} options
             */
            , resolveEntities: function (sirenObj, options) {
                var self = this
                , resolvedEntities = [];

                _.each(sirenObj.entities, function(entity) {
                    if ((entity.href && options.autoFetch == 'linked') || options.autoFetch == 'all') {
                        resolvedEntities.push(self.fetchEntity(entity, options));
                    } else {
                        resolvedEntities.push(self.addEntity(entity, options));
                    }
                });

                return $.when(resolvedEntities).done(function () {
                    self.trigger('resolve', self);
                });
            }

            /**
             * http://backbonejs.org/#Model-parse
             *
             * @param {Object} sirenObj
             */
            , parse: function (sirenObj, options) {
                this._data = sirenObj; // Stores the entire siren object in raw json
                this._entities = [];

                this.resolveEntities(sirenObj, options);
                this.parseActions(options);

                return sirenObj.properties;
            }

            /**
             * http://backbonejs.org/#Model-toJSON
             *
             * @param {Object} options
             */
            , toJSON: function () {
                var json = _.clone(this.attributes)
                , entities = this.entities();

                _.each(entities, function (entity) {
                    json[entity.rel()] = entity;
                });

                return json;
            }

            /**
             * Filters the entity's properties and returns only sub-entities
             *
             * @return {Array}
             */
            , entities: function (filters) {
                var self = this
                , entities = _.filter(this, function (val, name) {
                    return _.indexOf(self._entities, name) > -1;
                });

                if (filters) {
                    entities = filter(entities, filters);
                }

                return entities;
            }

            /**
             *
             * @param {Object} entity
             */
            , fetchEntity: function (entity) {
                var self = this;

                return $.getJSON(getUrl(entity), function (resolvedEntity) {
                    self.addEntity(resolvedEntity);
                });
            }

            /**
             *
             * @param {Object} entity
             */
            , parseEntity: function (entity) {
                var bbSiren;

                if (_hasClass(entity, 'collection')) {
                    bbSiren = new Backbone.Siren.Collection(entity);
                } else if (_hasClass(entity, 'error')) {
                    // @todo how should we represent errors?
                    warn('@todo - errors');
                } else {
                    bbSiren = new Backbone.Siren.Model(entity);
                    store.add(bbSiren);
                }

                return bbSiren;
            }

            /**
             *
             * @param {Object} entity
             */
            , addEntity: function (entity) {
                var bbSiren = this.parseEntity(entity)
                , rel = bbSiren.rel();

                this.set(rel, bbSiren);
                this._entities.push(rel);

                return bbSiren;
            }

            /**
             * http://backbonejs.org/#Model-constructor
             *
             * @param {Object} attributes
             * @param {Object} options
             */
            , constructor: function (sirenObj, options) {
                options = options || {};
                options.parse = true; // Force "parse" to be called on instantiation: http://stackoverflow.com/questions/11068989/backbone-js-using-parse-without-calling-fetch/14950519#14950519

                Backbone.Model.call(this, sirenObj, options);
            }

        })

        , Collection: Backbone.Collection.extend({
            url: url
            , classes: classes
            , hasClass: hasClass
            , title: title
            , rel: rel
            , links: links
            , actions: actions
            , getActionByName: getActionByName
            , getAllByAction: getAllByAction
            , parseActions: parseActions
            , request: request

            /**
             * http://backbonejs.org/#Collection-toJSON
             *
             * @param {Object} options
             */
            , toJSON: function (options) {
                return this.map(function(model){
                    return model.toJSON(options);
                });
            }

            /**
             *
             * @param {Function|Object} arg
             * @return {Array}
             */
            , filter: function (arg) {
                if (typeof arg ==  'function') {
                    return _.filter(this, arg);
                } else {
                    return filter(this, arg);
                }
            }

            /**
             * http://backbonejs.org/#Collection-parse
             *
             * @param {Object} sirenObj
             */
            , parse: function (sirenObj, options) {
                this._data = sirenObj; // Store the entire siren object in raw json
                this._meta = sirenObj.properties || {};

                var models = [];
                _.each(sirenObj.entities, function (entity) {
                    var model = new Backbone.Siren.Model(entity);
                    models.push(model);
                    store.add(model);
                });

                this.parseActions(options);

                return models;
            }

            /**
             * Unlike Models, collections don't have attributes.
             * However, there are times we need to store "meta" data about the collection such as
             * the paging "offset".
             *
             * @param {*} prop
             * @param {*} value
             * @return {Object}
             */
            , meta: function (name) {
                return this._meta[name];
            }

            /**
             * http://backbonejs.org/#Collection-constructor
             *
             * @param {Object} attributes
             * @param {Object} options
             */
            , constructor: function (sirenObj, options) {
                options = options || {};
                options.parse = true; // Force "parse" to be called on instantiation: http://stackoverflow.com/questions/11068989/backbone-js-using-parse-without-calling-fetch/14950519#14950519

                Backbone.Collection.call(this, sirenObj, options);
            }
        })
    };
}(_, Backbone));<commit_msg>fix type/method/enctype confusion<commit_after>Backbone.Siren = (function (_, Backbone, undefined) {
    'use strict';

    // The store-cache
    var _store = {}

    /**
     * Super simple store.  Good enough for now.
     *
     * @type {Object}
     * @private
     */
    , store = {

        /**
         *
         * @param {Backbone.Siren.Model} model
         * @return {Backbone.Siren.Model}
         */
        add: function (model) {
            return _store[model.url()] = model;
        }

        /**
         *
         * @param {Backbone.Siren.Model} model
         * @return {Boolean}
         */
        , exists: function (model) {
            return !!_store[model.url()];
        }

        /**
         *
         * @return {Array}
         */
        , all: function () {
            return _store;
        }
    }

    /**
     *
     * @type {Object}
     * @private
     */
    , warn = function () {
        if (Backbone.Siren.settings.showWarnings && console) {
            console.warn.apply(console, arguments);
        }
    };

    /**
     *
     * @param {Backbone.Siren.Model|Backbone.Siren.Collection} parent
     * @param actionData
     * @constructor
     */
    function Action(actionData, parent) {
        _.extend(this, actionData);
        this.parent = parent;
    }

    Action.prototype = {

        /**
         *
         * @param name
         * @return {*}
         */
        getFieldByName: function (name) {
            return _.find(this.fields, function (field) {
                return field.name == name;
            });
        }

        /**
         *
         * @param {Object} options
         * @return {$.Deferred|undefined}
         */
        , execute: function (options) {
            if (! this.parent) {
                return;
            }

            var defaults = {
                url: this.href
                , actionName: this.name
                , type: this.method
                , contentType: this.type
                , validate: true
                , patch: true
            };

            options = _.extend(defaults, options);
            return this.parent.save(this.parent.getAllByAction(this.name), options);
        }

    };

    /**
     *
     * @static
     * @param name
     * @return {String}
     */
    function toCamelCase(name) {
        return name.replace(/(\-[a-z])/g, function(match){return match.toUpperCase().replace('-','');});
    }

    /**
     *
     * @static
     * @param entity
     * @return {String}
     */
    function getUrl(entity) {
        var link, url;

        if (entity.href) {
            url = entity.href;
        } else if (entity.links) {
            link = entity.links.filter(function (link) {
                return !!(link.rel && link.rel.filter(function (relType) {
                    return relType == 'self';
                }).length);
            })[0];

            if (link) {
                url = link.href;
            }
        } else {
            warn('Missing href or "self" link');
            url = '';
        }

        return url;
    }

    /**
     * Access to the representation's "self" url, or its "href" if there is one.
     *
     * @return {String}
     */
    function url() {
        return getUrl(this._data);
    }

    /**
     *
     * @static
     * @param {Object} sirenObj Can be a siren entity or siren action object
     * @return {Array}
     */
    function getClassNames(sirenObj) {
        return sirenObj['class'] || [];
    }

    /**
     *
     * @static
     * @param {Array} entities
     * @param {Object} filters
     * @return {Array}
     */
    function filter(entities, filters) {
        return _.filter(entities, function (entity) {
            return hasProperties(entity, filters);
        });
    }

    /**
     *
     * @param {Backbone.Siren.Model|Backbone.Siren.Collection} bbSiren
     * @param {Object} filters
     * @return {Boolean}
     */
    function hasProperties(bbSiren, filters) {
        var _hasProperties = true;

        if (filters.className) {
            _hasProperties = bbSiren.hasClass(filters.className);
        }

        if (filters.rel) {
            _hasProperties = bbSiren.rel() == filters.rel;
        }

        return _hasProperties;
    }

    /**
     *
     * @param {Object} action
     * @param {Object} filters
     * @return {Boolean}
     */
    function actionHasProperties(action, filters) {
        var hasProperties = true;

        if (filters.className) {
            hasProperties = _hasClass(action, filters.className);
        }

        if (filters.name) {
            hasProperties = action.name == filters.name;
        }

        return hasProperties;
    }

    /**
     *
     * @static
     * @param sirenObj
     * @param className
     * @return {Boolean}
     */
    function _hasClass(sirenObj, className) {
        return _.indexOf(getClassNames(sirenObj), className) > -1;
    }

    /**
     *
     * @param className
     * @return {Boolean}
     */
    function hasClass(className) {
        return _hasClass(this._data, className);
    }

    /**
     * Accesses the "class" property of the Siren Object
     *
     * @return {Array}
     */
    function classes() {
        return getClassNames(this._data);
    }

    /**
     *
     * @param {String} rel
     * @return {Array}
     */
    function links(rel) {
        var _links = this._data.links;

        if (rel) {
            _links = _.filter(_links, function (link) {
                return _.indexOf(link.rel, rel) > -1;
            });
        }

        return _links || [];
    }

    /**
     *
     * @param {String} rel
     * @return {Array} An array of jqXhr objects.
     */
    function request(rel) {
        var self = this
        , requests = []
        , links = this.links(rel);

        _.each(links, function (link) {
            requests.push($.getJSON(link.href, function (sirenResponse) {
                self.parseEntity(sirenResponse);
            }));
        });

        return requests;
    }

    /**
     *
     * @static
     * @param sirenObj
     * @return {String}
     */
    function getRel(sirenObj) {
        var rel = sirenObj.rel;

        if (rel) {
            rel = rel[0]; // @todo, arbitrarily grabbing the first rel might be bad but I still don't understand the use case for many rels...
            rel = rel.slice(rel.lastIndexOf('/') + 1, rel.length);
        }

        return rel;
    }

    /**
     *
     * @return {String}
     */
    function rel() {
        return getRel(this._data);
    }

    /**
     *
     * @param filters
     * @return {*|Array}
     */
    function actions(filters) {
        var _actions = this._actions;

        if (filters) {
            _actions = _.filter(_actions, function (action) {
                return actionHasProperties(action, filters);
            });
        }
        return _actions;
    }

    /**
     *
     * @param {String} actionName
     * @return {Object}
     */
    function getAllByAction(actionName) {
        var values
        , action = this.getActionByName(actionName)
        , self = this;

        if (action) {
            values = {};
            _.each(action.fields, function (field) {
                if (self instanceof Backbone.Model) {
                    values[field.name] = self.get(field.name);
                } else {
                    values[field.name] = self.meta(field.name);
                }

            });
        }

        return values;
    }

    /**
     *
     * @param {String} name
     * @return {Object|undefined}
     */
    function getActionByName(name) {
        return _.find(this._actions, function (action) {
            return action.name == name;
        });
    }

    /**
     * Access to the representation's "title"
     *
     * @return {String}
     */
    function title() {
        return this._data.title;
    }

    /**
     *
     * @return {Array}
     */
    function parseActions() {
        var self = this
        , _actions = [];

        _.each(self._data.actions, function (action) {
            var bbSirenAction = new Backbone.Siren.Action(action, self);

            _actions.push(bbSirenAction);

            if (action.name) {
                self[toCamelCase(action.name)] = _.bind(bbSirenAction.execute, bbSirenAction);
            } else {
                warn('Action is missing a name, unable to add top level method', action);
            }
        });

        self._actions = _actions;
        return _actions;
    }

    return {
        settings: {
            showWarnings: true
        }

        , store: store
        , warn: warn
        , Action: Action

        , Model: Backbone.Model.extend({

            url: url
            , classes: classes
            , hasClass: hasClass
            , rel: rel
            , title: title
            , actions: actions
            , links: links
            , getActionByName: getActionByName
            , getAllByAction: getAllByAction
            , parseActions: parseActions
            , request: request

            /**
             *
             * @param {Object} sirenObj
             * @param {Object} options
             */
            , resolveEntities: function (sirenObj, options) {
                var self = this
                , resolvedEntities = [];

                _.each(sirenObj.entities, function(entity) {
                    if ((entity.href && options.autoFetch == 'linked') || options.autoFetch == 'all') {
                        resolvedEntities.push(self.fetchEntity(entity, options));
                    } else {
                        resolvedEntities.push(self.addEntity(entity, options));
                    }
                });

                return $.when(resolvedEntities).done(function () {
                    self.trigger('resolve', self);
                });
            }

            /**
             * http://backbonejs.org/#Model-parse
             *
             * @param {Object} sirenObj
             */
            , parse: function (sirenObj, options) {
                this._data = sirenObj; // Stores the entire siren object in raw json
                this._entities = [];

                this.resolveEntities(sirenObj, options);
                this.parseActions(options);

                return sirenObj.properties;
            }

            /**
             * http://backbonejs.org/#Model-toJSON
             *
             * @param {Object} options
             */
            , toJSON: function () {
                var json = _.clone(this.attributes)
                , entities = this.entities();

                _.each(entities, function (entity) {
                    json[entity.rel()] = entity;
                });

                return json;
            }

            /**
             * Filters the entity's properties and returns only sub-entities
             *
             * @return {Array}
             */
            , entities: function (filters) {
                var self = this
                , entities = _.filter(this, function (val, name) {
                    return _.indexOf(self._entities, name) > -1;
                });

                if (filters) {
                    entities = filter(entities, filters);
                }

                return entities;
            }

            /**
             *
             * @param {Object} entity
             */
            , fetchEntity: function (entity) {
                var self = this;

                return $.getJSON(getUrl(entity), function (resolvedEntity) {
                    self.addEntity(resolvedEntity);
                });
            }

            /**
             *
             * @param {Object} entity
             */
            , parseEntity: function (entity) {
                var bbSiren;

                if (_hasClass(entity, 'collection')) {
                    bbSiren = new Backbone.Siren.Collection(entity);
                } else if (_hasClass(entity, 'error')) {
                    // @todo how should we represent errors?
                    warn('@todo - errors');
                } else {
                    bbSiren = new Backbone.Siren.Model(entity);
                    store.add(bbSiren);
                }

                return bbSiren;
            }

            /**
             *
             * @param {Object} entity
             */
            , addEntity: function (entity) {
                var bbSiren = this.parseEntity(entity)
                , rel = bbSiren.rel();

                this.set(rel, bbSiren);
                this._entities.push(rel);

                return bbSiren;
            }

            /**
             * http://backbonejs.org/#Model-constructor
             *
             * @param {Object} attributes
             * @param {Object} options
             */
            , constructor: function (sirenObj, options) {
                options = options || {};
                options.parse = true; // Force "parse" to be called on instantiation: http://stackoverflow.com/questions/11068989/backbone-js-using-parse-without-calling-fetch/14950519#14950519

                Backbone.Model.call(this, sirenObj, options);
            }

        })

        , Collection: Backbone.Collection.extend({
            url: url
            , classes: classes
            , hasClass: hasClass
            , title: title
            , rel: rel
            , links: links
            , actions: actions
            , getActionByName: getActionByName
            , getAllByAction: getAllByAction
            , parseActions: parseActions
            , request: request

            /**
             * http://backbonejs.org/#Collection-toJSON
             *
             * @param {Object} options
             */
            , toJSON: function (options) {
                return this.map(function(model){
                    return model.toJSON(options);
                });
            }

            /**
             *
             * @param {Function|Object} arg
             * @return {Array}
             */
            , filter: function (arg) {
                if (typeof arg ==  'function') {
                    return _.filter(this, arg);
                } else {
                    return filter(this, arg);
                }
            }

            /**
             * http://backbonejs.org/#Collection-parse
             *
             * @param {Object} sirenObj
             */
            , parse: function (sirenObj, options) {
                this._data = sirenObj; // Store the entire siren object in raw json
                this._meta = sirenObj.properties || {};

                var models = [];
                _.each(sirenObj.entities, function (entity) {
                    var model = new Backbone.Siren.Model(entity);
                    models.push(model);
                    store.add(model);
                });

                this.parseActions(options);

                return models;
            }

            /**
             * Unlike Models, collections don't have attributes.
             * However, there are times we need to store "meta" data about the collection such as
             * the paging "offset".
             *
             * @param {*} prop
             * @param {*} value
             * @return {Object}
             */
            , meta: function (name) {
                return this._meta[name];
            }

            /**
             * http://backbonejs.org/#Collection-constructor
             *
             * @param {Object} attributes
             * @param {Object} options
             */
            , constructor: function (sirenObj, options) {
                options = options || {};
                options.parse = true; // Force "parse" to be called on instantiation: http://stackoverflow.com/questions/11068989/backbone-js-using-parse-without-calling-fetch/14950519#14950519

                Backbone.Collection.call(this, sirenObj, options);
            }
        })
    };
}(_, Backbone));<|endoftext|>


<commit_before>import GLBoost from '../../globals';
import SkeletalShaderSource from '../shaders/SkeletalShader';
import Geometry from '../../low_level/geometries/Geometry';
import M_Joint from '../elements/skeletons/M_Joint';
import M_Group from '../elements/M_Group';
import Matrix44 from '../../low_level/math/Matrix44';
import FreeShader from '../shaders/FreeShader';
import Shader from '../../low_level/shaders/Shader';
import Vector3 from '../../low_level/math/Vector3';
import Vector4 from '../../low_level/math/Vector4';
import Quaternion from '../../low_level/math/Quaternion';
import MathUtil from '../../low_level/math/MathUtil';

export default class M_SkeletalGeometry extends Geometry {
  constructor(glBoostContext) {
    super(glBoostContext);

    this._jointMatrices = null;
    this._qArray = null;
    this._tArray = null;
    this._qtArray = null;
    this._translationScale = 0;
  }

  update(skeletalMesh) {

    var joints = skeletalMesh._joints;
    var matrices = [];

    let areThereAnyJointsWhichHaveAnimation = false;

    for (let i=0; i<joints.length; i++) {
      if (typeof joints[i].parent._getCurrentAnimationInputValue(joints[i].parent._activeAnimationLineName) !== 'undefined') {
        areThereAnyJointsWhichHaveAnimation = true;
      }
    }

    let input = joints[0]._getCurrentAnimationInputValue('time');

    let jointZeroTransformMatrixAccumulatedAncestry = null;
    let skeletalMeshTransformMatrixAccumulatedAncestry = null;
    for (let i=0; i<joints.length; i++) {
      let globalJointTransform = null;
      let inverseBindMatrix = (typeof skeletalMesh.inverseBindMatrices[i] !== 'undefined') ? skeletalMesh.inverseBindMatrices[i] : Matrix44.identity();
      if (areThereAnyJointsWhichHaveAnimation) {
        globalJointTransform = joints[i].getTransformMatrixAccumulatedAncestryAt(input);
        if (i === 0) {
          jointZeroTransformMatrixAccumulatedAncestry = globalJointTransform;
        }
      } else {
        globalJointTransform = skeletalMesh.getTransformMatrixAccumulatedAncestryAt(input);
        skeletalMeshTransformMatrixAccumulatedAncestry = globalJointTransform;
        let inverseMat = Matrix44.multiply(Matrix44.invert(skeletalMesh.bindShapeMatrix), Matrix44.invert(inverseBindMatrix));
        //globalJointTransform = Matrix44.multiply(skeletalMesh.transformMatrixAccumulatedAncestry, inverseMat);
        globalJointTransform = Matrix44.multiply(skeletalMeshTransformMatrixAccumulatedAncestry, inverseMat);
      }
//      if (true) {
      if (this._materialForSkeletal.shaderInstance.constructor === FreeShader) {
        matrices[i] = Matrix44.invert(skeletalMeshTransformMatrixAccumulatedAncestry);//skeletalMesh.transformMatrixAccumulatedAncestry);
      } else {
        matrices[i] = Matrix44.identity();
      }
      matrices[i] = Matrix44.multiply(matrices[i], globalJointTransform);
      joints[i].jointPoseMatrix = Matrix44.multiply(Matrix44.identity(), globalJointTransform);
      matrices[i] = Matrix44.multiply(matrices[i], inverseBindMatrix);
      matrices[i] = Matrix44.multiply(matrices[i], skeletalMesh.bindShapeMatrix);
    }

    for (let i=0; i<joints.length; i++) {

      let backOfJointMatrix = Matrix44.identity();
      let tipOfJointMatrix = null;

      tipOfJointMatrix = joints[i].jointPoseMatrix;
      if (i > 0) {
        let backOfJoint = joints[i].jointsOfParentHierarchies[joints[i].jointsOfParentHierarchies.length - 1];
        if (backOfJoint) {
          backOfJointMatrix = backOfJoint.jointPoseMatrix;
        } else {
          joints[i].isVisible = false;
        }
      } else {
        backOfJointMatrix = jointZeroTransformMatrixAccumulatedAncestry;//joints[0].transformMatrixAccumulatedAncestry;
      }

      let backOfJointPos = backOfJointMatrix.multiplyVector(Vector4.zero()).toVector3();
      let tipOfJointPos = tipOfJointMatrix.multiplyVector(Vector4.zero()).toVector3();

      joints[i].worldPositionOfThisJoint = tipOfJointPos.clone();
      joints[i].worldPositionOfParentJoint = backOfJointPos.clone();

      joints[i].updateGizmoDisplay();
    }

/*
      let s = matrices[i].getScale();

      matrices[i].m00 /= s.x;
      matrices[i].m01 /= s.x;
      matrices[i].m02 /= s.x;
      matrices[i].m10 /= s.y;
      matrices[i].m11 /= s.y;
      matrices[i].m12 /= s.y;
      matrices[i].m20 /= s.z;
      matrices[i].m21 /= s.z;
      matrices[i].m22 /= s.z;

      let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
      q.normalize();
      let t = matrices[i].getTranslate();
      let matrix = q.rotationMatrix;

      matrix.m00 *= s.x;
      matrix.m01 *= s.x;
      matrix.m02 *= s.x;
      matrix.m10 *= s.y;
      matrix.m11 *= s.y;
      matrix.m12 *= s.y;
      matrix.m20 *= s.z;
      matrix.m21 *= s.z;
      matrix.m22 *= s.z;

      matrix.putTranslate(t);
      matrices[i] = matrix;
    }
    */

    if (!GLBoost.VALUE_TARGET_IS_MOBILE) {

      let flatMatrices = [];
      for (let i=0; i<matrices.length; i++) {
        Array.prototype.push.apply(flatMatrices, matrices[i].flattenAsArray());
      }

      if (matrices.length < 4) {
        let identityMatrices = [];
        for (let i=0; i<(4 - matrices.length); i++) {
          Array.prototype.push.apply(identityMatrices,
            [1, 0, 0, 0,
              0, 1, 0, 0,
              0, 0, 1, 0,
              0, 0, 0, 1]
          );
        }
        Array.prototype.push.apply(flatMatrices, identityMatrices);
      }
      this._jointMatrices = flatMatrices;

    } else {
      /*

      {
        // no comporess

        this._qArray = new Float32Array(matrices.length * 4);
        this._tArray = new Float32Array(matrices.length * 3);

        for (let i=0; i<matrices.length; i++) {
          let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
          q.normalize();
          this._qArray[i*4+0] = q.x;
          this._qArray[i*4+1] = q.y;
          this._qArray[i*4+2] = q.z;
          this._qArray[i*4+3] = q.w;
          let t = matrices[i].getTranslate();
          this._tArray[i*3+0] = t.x;
          this._tArray[i*3+1] = t.y;
          this._tArray[i*3+2] = t.z;
        }
      }
      */
      /*
      {
        // comporess quaternion only

        this._qArray = new Float32Array(matrices.length * 2);
        this._tArray = new Float32Array(matrices.length * 3);

        for (let i=0; i<matrices.length; i++) {
          let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
          q.normalize();
          let vec2QPacked = MathUtil.packNormalizedVec4ToVec2(q.x, q.y, q.z, q.w, 4096);
          this._qArray[i*2+0] = vec2QPacked[0];
          this._qArray[i*2+1] = vec2QPacked[1];
          let t = matrices[i].getTranslate();
          this._tArray[i*3+0] = t.x;
          this._tArray[i*3+1] = t.y;
          this._tArray[i*3+2] = t.z;
        }
      }
      */

      {
        // comporess both of quaternion and traslation

        this._qtArray = new Float32Array(matrices.length * 4);
        let tXArray = [];
        let tYArray = [];
        let tZArray = [];
        for (let i=0; i<matrices.length; i++) {
          let t = matrices[i].getTranslate();
          tXArray.push(Math.abs(t.x));
          tYArray.push(Math.abs(t.y));
          tZArray.push(Math.abs(t.z));
        }

        this._translationScale = new Vector3();
        let maxX = Math.max.apply(null, tXArray);
        let maxY = Math.max.apply(null, tYArray);
        let maxZ = Math.max.apply(null, tZArray);
        this._translationScale.x = maxX*1.1;
        this._translationScale.y = maxY*1.1;
        this._translationScale.z = maxZ*1.1;

        // console.log('getScale are ...');
        for (let i=0; i<matrices.length; i++) {
          let s = matrices[i].getScale();
          // console.log(s.toString());

          let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
          q.normalize();
          let vec2QPacked = MathUtil.packNormalizedVec4ToVec2(q.x, q.y, q.z, q.w, 4096);
          let t = matrices[i].getTranslate();
          this._qtArray[i*4+0] = vec2QPacked[0];
          this._qtArray[i*4+1] = vec2QPacked[1];
          let vec2TPacked = MathUtil.packNormalizedVec4ToVec2(
            t.x/this._translationScale.x, t.y/this._translationScale.y,
            t.z/this._translationScale.z, 0.0, 4096);
          this._qtArray[i*4+2] = vec2TPacked[0];
          this._qtArray[i*4+3] = vec2TPacked[1];
        }
      }
    }

  }

  draw(expression, lights, camera, skeletalMesh, scene, renderPass_index) {
    if (this._jointMatrices === null && this._qtArray === null) {
      return;
    }
    var gl = this._glContext.gl;
    if (this._materials.length > 0) {
      var materials = this._materials;
    } else if (skeletalMesh.material){
      var materials = [skeletalMesh.material];
    } else {
      var materials = [];
    }

    for (let i=0; i<materials.length;i++) {
      var glslProgram = materials[i].shaderInstance.glslProgram;
      this._glContext.useProgram(glslProgram);

      if (!GLBoost.VALUE_TARGET_IS_MOBILE) {
        Shader.trySettingMatrix44ToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINTMATRIX', new Float32Array(this._jointMatrices));
      } else {
 //     Shader.trySettingVec4ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_QUATERNION', this._qArray);
//      Shader.trySettingVec2ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_QUATERNION', this._qArray);
 //     Shader.trySettingVec3ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_TRANSLATION', this._tArray);
        Shader.trySettingVec4ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_QUATTRANSLATION', this._qtArray);//
        this._glContext.uniform3f(materials[i].getUniform(glslProgram, 'uniform_translationScale'),
          this._translationScale.x, this._translationScale.y, this._translationScale.z, true);
      }
    }

    super.draw(expression, lights, camera, skeletalMesh, scene, renderPass_index);
  }

  prepareToRender(expression, existCamera_f, pointLight, meshMaterial, skeletalMesh) {
    // before prepareForRender of 'Geometry' class, a new 'BlendShapeShader'(which extends default shader) is assigned.

    if (this._materials.length > 0) {
      this._materialForSkeletal = this._materials[0];
    } else if (meshMaterial) {
      this._materialForSkeletal = meshMaterial;
    } else {
      this._materialForSkeletal = this._defaultMaterial;
    }

    if (!(this._materialForSkeletal.shaderInstance !== null && this._materialForSkeletal.shaderInstance.constructor === FreeShader)) {

      class SkeletalShader extends this._materialForSkeletal.shaderClass {
        constructor(glBoostContext, basicShader) {
          super(glBoostContext, basicShader);
          SkeletalShader.mixin(SkeletalShaderSource);
        }
      }

      if (this._materials.length > 0) {
        for (let i = 0; i < this._materials.length; i++) {
          if (this._materials[i].shaderClass.name !== SkeletalShader.name) {
            this._materials[i].shaderClass = SkeletalShader;
          }
        }
      } else if (meshMaterial) {
        if (meshMaterial.shaderClass.name !== SkeletalShader.name) {
          meshMaterial.shaderClass = SkeletalShader;
        }
      } else {
        if (this._defaultMaterial.shaderClass.name !== SkeletalShader.name) {
          this._defaultMaterial.shaderClass = SkeletalShader;
        }
      }
    }

    return super.prepareToRender(expression, existCamera_f, pointLight, meshMaterial, skeletalMesh);
  }
}
<commit_msg>Improve performance of skeletal animation<commit_after>import GLBoost from '../../globals';
import SkeletalShaderSource from '../shaders/SkeletalShader';
import Geometry from '../../low_level/geometries/Geometry';
import M_Joint from '../elements/skeletons/M_Joint';
import M_Group from '../elements/M_Group';
import Matrix44 from '../../low_level/math/Matrix44';
import FreeShader from '../shaders/FreeShader';
import Shader from '../../low_level/shaders/Shader';
import Vector3 from '../../low_level/math/Vector3';
import Vector4 from '../../low_level/math/Vector4';
import Quaternion from '../../low_level/math/Quaternion';
import MathUtil from '../../low_level/math/MathUtil';

export default class M_SkeletalGeometry extends Geometry {
  constructor(glBoostContext) {
    super(glBoostContext);

    this._jointMatrices = null;
    this._qArray = null;
    this._tArray = null;
    this._qtArray = null;
    this._translationScale = 0;
  }

  update(skeletalMesh) {

    var joints = skeletalMesh._joints;
    var matrices = [];

    let areThereAnyJointsWhichHaveAnimation = false;

    for (let i=0; i<joints.length; i++) {
      if (typeof joints[i].parent._getCurrentAnimationInputValue(joints[i].parent._activeAnimationLineName) !== 'undefined') {
        areThereAnyJointsWhichHaveAnimation = true;
      }
    }

    let input = joints[0]._getCurrentAnimationInputValue('time');

    let jointZeroTransformMatrixAccumulatedAncestry = null;
    let skeletalMeshTransformMatrixAccumulatedAncestry = null;
    for (let i=joints.length-1; i>=0; i--) {
      let globalJointTransform = null;
      let inverseBindMatrix = (typeof skeletalMesh.inverseBindMatrices[i] !== 'undefined') ? skeletalMesh.inverseBindMatrices[i] : Matrix44.identity();
      if (areThereAnyJointsWhichHaveAnimation) {
        globalJointTransform = joints[i].getTransformMatrixAccumulatedAncestryAt(input);
        if (i === 0) {
          jointZeroTransformMatrixAccumulatedAncestry = globalJointTransform;
        }
      } else {
        globalJointTransform = skeletalMesh.getTransformMatrixAccumulatedAncestryAt(input);
        skeletalMeshTransformMatrixAccumulatedAncestry = globalJointTransform;
        let inverseMat = Matrix44.multiply(Matrix44.invert(skeletalMesh.bindShapeMatrix), Matrix44.invert(inverseBindMatrix));
        globalJointTransform = Matrix44.multiply(skeletalMeshTransformMatrixAccumulatedAncestry, inverseMat);
      }
//      if (true) {
      if (this._materialForSkeletal.shaderInstance.constructor === FreeShader) {
        matrices[i] = Matrix44.invert(skeletalMeshTransformMatrixAccumulatedAncestry);
      } else {
        matrices[i] = Matrix44.identity();
      }
      matrices[i] = Matrix44.multiply(matrices[i], globalJointTransform);
      joints[i].jointPoseMatrix = Matrix44.multiply(Matrix44.identity(), globalJointTransform);
      matrices[i] = Matrix44.multiply(matrices[i], inverseBindMatrix);
      matrices[i] = Matrix44.multiply(matrices[i], skeletalMesh.bindShapeMatrix);
    }

    for (let i=0; i<joints.length; i++) {

      let backOfJointMatrix = Matrix44.identity();
      let tipOfJointMatrix = null;

      tipOfJointMatrix = joints[i].jointPoseMatrix;
      if (i > 0) {
        let backOfJoint = joints[i].jointsOfParentHierarchies[joints[i].jointsOfParentHierarchies.length - 1];
        if (backOfJoint) {
          backOfJointMatrix = backOfJoint.jointPoseMatrix;
        } else {
          joints[i].isVisible = false;
        }
      } else {
        backOfJointMatrix = jointZeroTransformMatrixAccumulatedAncestry;
      }

      let backOfJointPos = backOfJointMatrix.multiplyVector(Vector4.zero()).toVector3();
      let tipOfJointPos = tipOfJointMatrix.multiplyVector(Vector4.zero()).toVector3();

      joints[i].worldPositionOfThisJoint = tipOfJointPos.clone();
      joints[i].worldPositionOfParentJoint = backOfJointPos.clone();

      joints[i].updateGizmoDisplay();
    }

/*
      let s = matrices[i].getScale();

      matrices[i].m00 /= s.x;
      matrices[i].m01 /= s.x;
      matrices[i].m02 /= s.x;
      matrices[i].m10 /= s.y;
      matrices[i].m11 /= s.y;
      matrices[i].m12 /= s.y;
      matrices[i].m20 /= s.z;
      matrices[i].m21 /= s.z;
      matrices[i].m22 /= s.z;

      let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
      q.normalize();
      let t = matrices[i].getTranslate();
      let matrix = q.rotationMatrix;

      matrix.m00 *= s.x;
      matrix.m01 *= s.x;
      matrix.m02 *= s.x;
      matrix.m10 *= s.y;
      matrix.m11 *= s.y;
      matrix.m12 *= s.y;
      matrix.m20 *= s.z;
      matrix.m21 *= s.z;
      matrix.m22 *= s.z;

      matrix.putTranslate(t);
      matrices[i] = matrix;
    }
    */

    if (!GLBoost.VALUE_TARGET_IS_MOBILE) {

      let flatMatrices = [];
      for (let i=0; i<matrices.length; i++) {
        Array.prototype.push.apply(flatMatrices, matrices[i].flattenAsArray());
      }

      if (matrices.length < 4) {
        let identityMatrices = [];
        for (let i=0; i<(4 - matrices.length); i++) {
          Array.prototype.push.apply(identityMatrices,
            [1, 0, 0, 0,
              0, 1, 0, 0,
              0, 0, 1, 0,
              0, 0, 0, 1]
          );
        }
        Array.prototype.push.apply(flatMatrices, identityMatrices);
      }
      this._jointMatrices = flatMatrices;

    } else {
      /*

      {
        // no comporess

        this._qArray = new Float32Array(matrices.length * 4);
        this._tArray = new Float32Array(matrices.length * 3);

        for (let i=0; i<matrices.length; i++) {
          let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
          q.normalize();
          this._qArray[i*4+0] = q.x;
          this._qArray[i*4+1] = q.y;
          this._qArray[i*4+2] = q.z;
          this._qArray[i*4+3] = q.w;
          let t = matrices[i].getTranslate();
          this._tArray[i*3+0] = t.x;
          this._tArray[i*3+1] = t.y;
          this._tArray[i*3+2] = t.z;
        }
      }
      */
      /*
      {
        // comporess quaternion only

        this._qArray = new Float32Array(matrices.length * 2);
        this._tArray = new Float32Array(matrices.length * 3);

        for (let i=0; i<matrices.length; i++) {
          let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
          q.normalize();
          let vec2QPacked = MathUtil.packNormalizedVec4ToVec2(q.x, q.y, q.z, q.w, 4096);
          this._qArray[i*2+0] = vec2QPacked[0];
          this._qArray[i*2+1] = vec2QPacked[1];
          let t = matrices[i].getTranslate();
          this._tArray[i*3+0] = t.x;
          this._tArray[i*3+1] = t.y;
          this._tArray[i*3+2] = t.z;
        }
      }
      */

      {
        // comporess both of quaternion and traslation

        this._qtArray = new Float32Array(matrices.length * 4);
        let tXArray = [];
        let tYArray = [];
        let tZArray = [];
        for (let i=0; i<matrices.length; i++) {
          let t = matrices[i].getTranslate();
          tXArray.push(Math.abs(t.x));
          tYArray.push(Math.abs(t.y));
          tZArray.push(Math.abs(t.z));
        }

        this._translationScale = new Vector3();
        let maxX = Math.max.apply(null, tXArray);
        let maxY = Math.max.apply(null, tYArray);
        let maxZ = Math.max.apply(null, tZArray);
        this._translationScale.x = maxX*1.1;
        this._translationScale.y = maxY*1.1;
        this._translationScale.z = maxZ*1.1;

        // console.log('getScale are ...');
        for (let i=0; i<matrices.length; i++) {
          let s = matrices[i].getScale();
          // console.log(s.toString());

          let q = (Quaternion.quaternionFromRotationMatrix(matrices[i]));
          q.normalize();
          let vec2QPacked = MathUtil.packNormalizedVec4ToVec2(q.x, q.y, q.z, q.w, 4096);
          let t = matrices[i].getTranslate();
          this._qtArray[i*4+0] = vec2QPacked[0];
          this._qtArray[i*4+1] = vec2QPacked[1];
          let vec2TPacked = MathUtil.packNormalizedVec4ToVec2(
            t.x/this._translationScale.x, t.y/this._translationScale.y,
            t.z/this._translationScale.z, 0.0, 4096);
          this._qtArray[i*4+2] = vec2TPacked[0];
          this._qtArray[i*4+3] = vec2TPacked[1];
        }
      }
    }

  }

  draw(expression, lights, camera, skeletalMesh, scene, renderPass_index) {
    if (this._jointMatrices === null && this._qtArray === null) {
      return;
    }
    var gl = this._glContext.gl;
    if (this._materials.length > 0) {
      var materials = this._materials;
    } else if (skeletalMesh.material){
      var materials = [skeletalMesh.material];
    } else {
      var materials = [];
    }

    for (let i=0; i<materials.length;i++) {
      var glslProgram = materials[i].shaderInstance.glslProgram;
      this._glContext.useProgram(glslProgram);

      if (!GLBoost.VALUE_TARGET_IS_MOBILE) {
        Shader.trySettingMatrix44ToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINTMATRIX', new Float32Array(this._jointMatrices));
      } else {
 //     Shader.trySettingVec4ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_QUATERNION', this._qArray);
//      Shader.trySettingVec2ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_QUATERNION', this._qArray);
 //     Shader.trySettingVec3ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_TRANSLATION', this._tArray);
        Shader.trySettingVec4ArrayToUniform(gl, glslProgram, materials[i], materials[i]._semanticsDic, 'JOINT_QUATTRANSLATION', this._qtArray);//
        this._glContext.uniform3f(materials[i].getUniform(glslProgram, 'uniform_translationScale'),
          this._translationScale.x, this._translationScale.y, this._translationScale.z, true);
      }
    }

    super.draw(expression, lights, camera, skeletalMesh, scene, renderPass_index);
  }

  prepareToRender(expression, existCamera_f, pointLight, meshMaterial, skeletalMesh) {
    // before prepareForRender of 'Geometry' class, a new 'BlendShapeShader'(which extends default shader) is assigned.

    if (this._materials.length > 0) {
      this._materialForSkeletal = this._materials[0];
    } else if (meshMaterial) {
      this._materialForSkeletal = meshMaterial;
    } else {
      this._materialForSkeletal = this._defaultMaterial;
    }

    if (!(this._materialForSkeletal.shaderInstance !== null && this._materialForSkeletal.shaderInstance.constructor === FreeShader)) {

      class SkeletalShader extends this._materialForSkeletal.shaderClass {
        constructor(glBoostContext, basicShader) {
          super(glBoostContext, basicShader);
          SkeletalShader.mixin(SkeletalShaderSource);
        }
      }

      if (this._materials.length > 0) {
        for (let i = 0; i < this._materials.length; i++) {
          if (this._materials[i].shaderClass.name !== SkeletalShader.name) {
            this._materials[i].shaderClass = SkeletalShader;
          }
        }
      } else if (meshMaterial) {
        if (meshMaterial.shaderClass.name !== SkeletalShader.name) {
          meshMaterial.shaderClass = SkeletalShader;
        }
      } else {
        if (this._defaultMaterial.shaderClass.name !== SkeletalShader.name) {
          this._defaultMaterial.shaderClass = SkeletalShader;
        }
      }
    }

    return super.prepareToRender(expression, existCamera_f, pointLight, meshMaterial, skeletalMesh);
  }
}
<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var path = require('path');
var chalk = require('chalk');
var rimraf = require('rimraf');
var yeoman = require('yeoman-generator');
var git = require('../util/git');
var spawn = require('../util/spawn');

var DroughtGenerator = module.exports = function DroughtGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(DroughtGenerator, yeoman.generators.Base);

DroughtGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    name: 'projectName',
    message: 'What would you like to call this project?',
    default: 'myDroughtProject'
  }, {
    type: 'confirm',
    name: 'confirmSASS',
    message: 'Would you like to use SASS?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmGrunt',
    message: 'Would you like to use Grunt?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmBower',
    message: 'Would you like to use Bower?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmjQuery',
    message: 'Would you like to use jQuery?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmFoundation',
    message: 'Would you like to use Foundation?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmIE8',
    message: 'Do you need to support IE8? *sigh*',
    default: false
  }];

  this.prompt(prompts, function (props) {
    this.projectName = props.projectName;
    this.confirmSASS = props.confirmSASS;
    this.confirmGrunt = props.confirmGrunt;
    this.confirmBower = props.confirmBower;
    this.confirmjQuery = props.confirmjQuery;
    this.confirmFoundation = props.confirmFoundation;
    this.confirmIE8 = props.confirmIE8;

    cb();
  }.bind(this));
};

DroughtGenerator.prototype.usegit = function usegit() {
  var done = this.async();

  console.log(chalk.red('\n----------------------------\n'));
  console.log([
chalk.cyan(',------.                               ,--.       ,--.'),
chalk.cyan('|  .-.  \\ ,--.--. ,---. ,--.,--. ,---. |  ,---. ,-\'  \'-.'),
chalk.cyan('|  |  \\  :|  .--\'| .-. ||  ||  || .-. ||  .-.  |\'-.  .-\''),
chalk.cyan('|  \'--\'  /|  |   \' \'-\' \'\'  \'\'  \'\' \'-\' \'|  | |  |  |  |'),
chalk.cyan('`-------\' `--\'    `---\'  `----\' .`-  / `--\' `--\'  `--\''),
chalk.cyan('                                `---\'                    ')].join('\n'));

  console.log('Now I\'m going to do a quick clone of the latest Drought files...');

  git.clone('git@github.com:fleeting/Drought.git', '.', function() {
    console.log(chalk.green('Drought successfully cloned.'));
    done();
  });
};

DroughtGenerator.prototype.app = function app() {
  console.log(chalk.red('\n----------------------------\n'));

  var done = this.async();
  console.log('I\'ve got Drought so lets customize this build based on your earlier needs.');

  //this.copy('humans.txt', 'humans.txt');
  this.template('_package.json', 'package.json');

  if(!this.confirmSASS) {
    rimraf('css/mixins.scss', function () { });
    rimraf('css/normalize.scss', function () { });
    rimraf('css/style.scss', function () { });

    console.log(chalk.green('You aren\'t using SASS for this project so I\'ve removed those files.'));
  }

  if(this.confirmBower) {
    this.template('_bower.json', 'bower.json');
  }

  if(this.confirmGrunt) {
    this.copy('gruntfile.js', 'gruntfile.js');
  }

  done();
};
<commit_msg>Use public git url for Drought.<commit_after>'use strict';
var util = require('util');
var path = require('path');
var chalk = require('chalk');
var rimraf = require('rimraf');
var yeoman = require('yeoman-generator');
var git = require('../util/git');
var spawn = require('../util/spawn');

var DroughtGenerator = module.exports = function DroughtGenerator(args, options, config) {
  yeoman.generators.Base.apply(this, arguments);

  this.on('end', function () {
    this.installDependencies({ skipInstall: options['skip-install'] });
  });

  this.pkg = JSON.parse(this.readFileAsString(path.join(__dirname, '../package.json')));
};

util.inherits(DroughtGenerator, yeoman.generators.Base);

DroughtGenerator.prototype.askFor = function askFor() {
  var cb = this.async();

  // have Yeoman greet the user.
  console.log(this.yeoman);

  var prompts = [{
    name: 'projectName',
    message: 'What would you like to call this project?',
    default: 'myDroughtProject'
  }, {
    type: 'confirm',
    name: 'confirmSASS',
    message: 'Would you like to use SASS?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmGrunt',
    message: 'Would you like to use Grunt?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmBower',
    message: 'Would you like to use Bower?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmjQuery',
    message: 'Would you like to use jQuery?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmFoundation',
    message: 'Would you like to use Foundation?',
    default: true
  }, {
    type: 'confirm',
    name: 'confirmIE8',
    message: 'Do you need to support IE8? *sigh*',
    default: false
  }];

  this.prompt(prompts, function (props) {
    this.projectName = props.projectName;
    this.confirmSASS = props.confirmSASS;
    this.confirmGrunt = props.confirmGrunt;
    this.confirmBower = props.confirmBower;
    this.confirmjQuery = props.confirmjQuery;
    this.confirmFoundation = props.confirmFoundation;
    this.confirmIE8 = props.confirmIE8;

    cb();
  }.bind(this));
};

DroughtGenerator.prototype.usegit = function usegit() {
  var done = this.async();

  console.log(chalk.red('\n----------------------------\n'));
  console.log([
chalk.cyan(',------.                               ,--.       ,--.'),
chalk.cyan('|  .-.  \\ ,--.--. ,---. ,--.,--. ,---. |  ,---. ,-\'  \'-.'),
chalk.cyan('|  |  \\  :|  .--\'| .-. ||  ||  || .-. ||  .-.  |\'-.  .-\''),
chalk.cyan('|  \'--\'  /|  |   \' \'-\' \'\'  \'\'  \'\' \'-\' \'|  | |  |  |  |'),
chalk.cyan('`-------\' `--\'    `---\'  `----\' .`-  / `--\' `--\'  `--\''),
chalk.cyan('                                `---\'                    ')].join('\n'));

  console.log('Now I\'m going to do a quick clone of the latest Drought files...');

  git.clone('git://github.com/fleeting/Drought.git', '.', function() {
    console.log(chalk.green('Drought successfully cloned.'));
    done();
  });
};

DroughtGenerator.prototype.app = function app() {
  console.log(chalk.red('\n----------------------------\n'));

  var done = this.async();
  console.log('I\'ve got Drought so lets customize this build based on your earlier needs.');

  //this.copy('humans.txt', 'humans.txt');
  this.template('_package.json', 'package.json');

  if(!this.confirmSASS) {
    rimraf('css/mixins.scss', function () { });
    rimraf('css/normalize.scss', function () { });
    rimraf('css/style.scss', function () { });

    console.log(chalk.green('You aren\'t using SASS for this project so I\'ve removed those files.'));
  }

  if(this.confirmBower) {
    this.template('_bower.json', 'bower.json');
  }

  if(this.confirmGrunt) {
    this.copy('gruntfile.js', 'gruntfile.js');
  }

  done();
};
<|endoftext|>


<commit_before>/**
 * @fileoverview
This module provides generic logging support. It uses
 * Apache log4j by default,
 * but can be used with any Logging framework supported by
 * SLF4J.

 *
 *
If the first argument passed to any of the logging methods is a string
 * containing any number of curly bracket pairs ({}), the logger will interpret
 * it as format string and use any following arguments to replace the curly
 * bracket pairs. If an argument is an Error or Java Exception object, the
 * logger will render a stack trace for it and append it to the log message.

 */

require('core/string');
var utils = require('ringo/utils');

var LoggerFactory = org.slf4j.LoggerFactory;

module.shared = true;
var configured = false;

/**
 * Logger class. This constructor is not exported, use this module's
 * {@link getLogger} to get a logger instance.
 * @param name
 * @constructor
 * @name Logger
 * @see getLogger
 */
function Logger(name) {

    var log = LoggerFactory.getLogger(name.replace(/\//g, '.'));

    /**
     * Log a debug message.
     */
    this.trace = function() {
        log.trace(formatMessage(arguments));
    };

    this.debug = function() {
        log.debug(formatMessage(arguments));
    };

    this.info = function() {
        log.info(formatMessage(arguments));
    };

    this.warn = function() {
        log.warn(formatMessage(arguments));
    };

    this.error = function() {
        log.error(formatMessage(arguments));
    };

    this.isTraceEnabled = function() {
        return log.isTraceEnabled();
    };

    this.isDebugEnabled = function() {
        return log.isDebugEnabled();
    };

    this.isInfoEnabled = function() {
        return log.isInfoEnabled();
    };

    this.isWarnEnabled = function() {
        return log.isWarnEnabled();
    };

    this.isErrorEnabled = function() {
        return log.isErrorEnabled();
    };
}

/**
 * Configure log4j using the given file resource.
 * Make sure to set the reset property to true in the <log4j:configuration> header
 * e.g. <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' reset="true">
 */
var setConfig = exports.setConfig = function(resource) {
    var {path, url} = resource;
    var PropertyConfigurator = org.apache.log4j.PropertyConfigurator,
        DOMConfigurator = org.apache.log4j.xml.DOMConfigurator;
    var configurator = path.endsWith('.properties') || path.endsWith('.props') ?
                       PropertyConfigurator : DOMConfigurator;
    configurator.configure(url);
    try {
        configurator.configureAndWatch(path, 2000);
    } catch (e) {
        print("Error watching log configuration file:", e);
    }
    configured = true;
};

/**
 * Get a logger for the given name.
 * @param {string} name the name of the logger
 * @returns {Logger} a logger instance for the given name
 */
var getLogger = exports.getLogger = function(name) {
    if (!configured) {
        // getResource('foo').name gets us the absolute path to a local resource
        this.setConfig(getResource('config/log4j.properties'));
    }
    return new Logger(name);
};

function formatMessage(args) {
    var message = utils.format.apply(null, args);
    for each (var arg in args) {
        if (arg instanceof Error || arg instanceof java.lang.Throwable) {
            message  = [
                message,
                "Script stack:",
                utils.getScriptStack(arg).trim(),
                "Java stack:",
                utils.getJavaStack(arg)
            ].join('\n');
        }
    }
    return message;
}

<commit_msg>Fix script stack rendering.<commit_after>/**
 * @fileoverview
This module provides generic logging support. It uses
 * Apache log4j by default,
 * but can be used with any Logging framework supported by
 * SLF4J.

 *
 *
If the first argument passed to any of the logging methods is a string
 * containing any number of curly bracket pairs ({}), the logger will interpret
 * it as format string and use any following arguments to replace the curly
 * bracket pairs. If an argument is an Error or Java Exception object, the
 * logger will render a stack trace for it and append it to the log message.

 */

require('core/string');
var utils = require('ringo/utils');

var LoggerFactory = org.slf4j.LoggerFactory;

module.shared = true;
var configured = false;

/**
 * Logger class. This constructor is not exported, use this module's
 * {@link getLogger} to get a logger instance.
 * @param name
 * @constructor
 * @name Logger
 * @see getLogger
 */
function Logger(name) {

    var log = LoggerFactory.getLogger(name.replace(/\//g, '.'));

    /**
     * Log a debug message.
     */
    this.trace = function() {
        log.trace(formatMessage(arguments));
    };

    this.debug = function() {
        log.debug(formatMessage(arguments));
    };

    this.info = function() {
        log.info(formatMessage(arguments));
    };

    this.warn = function() {
        log.warn(formatMessage(arguments));
    };

    this.error = function() {
        log.error(formatMessage(arguments));
    };

    this.isTraceEnabled = function() {
        return log.isTraceEnabled();
    };

    this.isDebugEnabled = function() {
        return log.isDebugEnabled();
    };

    this.isInfoEnabled = function() {
        return log.isInfoEnabled();
    };

    this.isWarnEnabled = function() {
        return log.isWarnEnabled();
    };

    this.isErrorEnabled = function() {
        return log.isErrorEnabled();
    };
}

/**
 * Configure log4j using the given file resource.
 * Make sure to set the reset property to true in the <log4j:configuration> header
 * e.g. <log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/' reset="true">
 */
var setConfig = exports.setConfig = function(resource) {
    var {path, url} = resource;
    var PropertyConfigurator = org.apache.log4j.PropertyConfigurator,
        DOMConfigurator = org.apache.log4j.xml.DOMConfigurator;
    var configurator = path.endsWith('.properties') || path.endsWith('.props') ?
                       PropertyConfigurator : DOMConfigurator;
    configurator.configure(url);
    try {
        configurator.configureAndWatch(path, 2000);
    } catch (e) {
        print("Error watching log configuration file:", e);
    }
    configured = true;
};

/**
 * Get a logger for the given name.
 * @param {string} name the name of the logger
 * @returns {Logger} a logger instance for the given name
 */
var getLogger = exports.getLogger = function(name) {
    if (!configured) {
        // getResource('foo').name gets us the absolute path to a local resource
        this.setConfig(getResource('config/log4j.properties'));
    }
    return new Logger(name);
};

function formatMessage(args) {
    var message = utils.format.apply(null, args);
    for each (var arg in args) {
        if (arg instanceof Error || arg instanceof java.lang.Throwable) {
            message  = [
                message,
                "\nScript stack:\n",
                utils.getScriptStack(arg),
                "Java stack:\n",
                utils.getJavaStack(arg)
            ].join('');
        }
    }
    return message;
}

<|endoftext|>


<commit_before>(function () {
	'use strict';

	const View = window.View;
	const Player = window.Player;
	const MessagingTools = window.MessagingTools;

	class GamePlayView extends View {
		constructor(options = {}) {
			super(options);
			this._el = document.querySelector('.js-canvas');
			this.allowGameStart = false;

      this.init();
      this.show();

      //потом сюда надо будет вбить урл сервера
			//---------------------------------------------------------------------
      //var socket = new WebSocket("ws://localhost:8080/game");
      var socket = new WebSocket("wss://java-heroku-test-victor.herokuapp.com/game");
            var messaging = new MessagingTools(socket);
      socket.onopen = function () {
        // Socket open.. start the game loop.
        console.log('Info: WebSocket connection opened.');
        console.log('Info: Waiting for another player...');
      };

      function Send(){
      	messaging.sendJoinGameMsg();
      }

      setTimeout(Send,1000);
      socket.onclose = function () {
        console.log('Info: WebSocket closed.');
      };

      socket.onmessage = function (event) {
      	var content = {};
        var responseContent = {};
        var response = {};
        var message = JSON.parse(event.data);
        if (message.type === "ru.mail.park.websocket.MessageToClient$Request") {
            content = JSON.parse(message.content);
            responseContent.myMessage = content.myMessage;
            console.log(responseContent.myMessage);
            return;
        }
        if ( message.type === "ru.mail.park.mechanics.requests.BoardMapForUsers$Request"){
            console.log("Wow. Seems loke game been started");
            content = JSON.parse(message.content);
            gameCellIds = content.gameBoard;
            gameCellIds = gameCellIds.split(",");
            for(var j = 0; j < gameCellIds.length; j++){
            	gameCellIds[j]= +gameCellIds[j];
            };
            if(content.active){
            	thisPlayer = player1;
            	enemy = player2;
            	var pirats1 = player1.get_pirats();
            	pirats1.forEach(function(elem){
            		elem.isPickable = true;
            	});
            }
            else{
            	thisPlayer = player2;
            	enemy = player1;
            	var pirats2 = player2.get_pirats();
            	pirats2.forEach(function(elem){
            		elem.isPickable = false;
            	})
            }
            console.log("Проверяем проставление активного игрока");
            console.log(content.active);
            console.log(thisPlayer);
            console.log(player1);
			//this.allowGameStart = true;

        }
		if ( message.type === "ru.mail.park.mechanics.requests.NeighborsMessage$Request"){
            console.log("Получены соседи клетки!");
            content = JSON.parse(message.content);
            console.log(content);
			    neighbors = content.neighbors;
				neighbors = neighbors.split(",");
				for(var j = 0; j < neighbors.length; j++){
            		neighbors[j]= +neighbors[j];
            		console.log(typeof(neighbors[j]));
            	};

            console.log('Соседи: ' + neighbors.length);

			for(var i = 0; i < neighbors.length; ++i){
				gameField.subMeshes[neighbors[i]].materialIndex = 0;
				//console.log("пытаемся подсветить клетку");
			}
        }
        if(message.type === "ru.mail.park.mechanics.requests.PiratMoveMessage$Request") {
        	console.log("О_о сервер ghbckfk ход другого игрока");
            content = JSON.parse(message.content);
            console.log(content);
            if(content.active){
            	var thisPirats = thisPlayer.get_pirats();
            	thisPirats.forEach(function(elem){
            		elem.isPickable = true;
            	});
            	MovementPiratId = content.piratId;
            	MovementTargetCell = content.newCellIndexOfPirat;
            	MovementUnresolved = true;

            }

        }
      }

			//--------------------------------------------------------------------------

      var engine = new BABYLON.Engine(this._el, true);
      var canvas = this._el;

      var createScene = function(){
        var scene = new BABYLON.Scene(engine);
        var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI/2, Math.PI / 3,
				                                         12, new BABYLON.Vector3(-100,100,100), scene);
        camera.lowerBetaLimit = 0.1;
        camera.lowerRadiusLimit = 30;
        camera.upperRadiusLimit = 250;
        camera.attachControl(canvas, true);
        var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
        light.intensity = .5;

        return scene;
      }

      var scene = createScene();

			//начинаем игровой цикл
			const player1 = new Player(0, scene, {}); //первый игрок и его меши
			const player2 = new Player(1, scene, {}); // 2-й игрок и его меши
			var thisPlayer, enemy;
			var MovementPiratId, MovementTargetCell;

		//	var pirats = player1.get_pirats();
		//	var possibleIds = player1.get_ids();

			this.createSkyBox(scene);
			var gameField = this.createGameField(scene);
			var gameCellIds = " ";
			var MovementUnresolved = false;
            //var str = " ";
			//пошёл цикл
			var pirats ;
			var mesh;
			var neighbors = [];
			var picked = false;
			var ball;
			var index, ids = [], cellIndex, piratMove;
			scene.onPointerDown = function(evt, pickResult){

				if(pickResult.hit){
					mesh = pickResult.pickedMesh;
					pirats = thisPlayer.get_pirats();
					if(pirats.indexOf(mesh)!= -1){
						mesh.material.diffuseColor = new BABYLON.Color3(0, 1, 0);
						ball = mesh;

						//здесь нужно получить от сервера смежные клетки
						index = pirats.indexOf(mesh);
					 	ids = thisPlayer.get_ids(); //номер пирата
						cellIndex = ids[index]; //айди клетки
						piratMove = {};

				 		var getCellneighbors = {};
			      		getCellneighbors.cellIndex = cellIndex;
			      		messaging.sendGetNeighbors(getCellneighbors);

						picked = true;
					}
					if((mesh === gameField)&&(picked == true)){

						//здесь уже выбираем из смежных клетку, на которую пойдем
						console.log("мы хотим передвинуть шарик");
						var id = pickResult.subMeshId;
						console.log(id);
						console.log(typeof(+neighbors[0]));
						 if(neighbors.indexOf(id) != -1){
						 	console.log("мы кликнули на подсвеченную клетку");
						 	 ball.position.x = pickResult.pickedPoint.x;
							 ball.position.z = pickResult.pickedPoint.z;
							 console.log("Куда мы должны были передвинуться")
							 console.log(ball.position.x);
							 console.log(ball.position.z);
							 ball.material.diffuseColor = new BABYLON.Color3(1,0,0);
							 ids[index] = id;
							 thisPlayer.set_ids(ids);
							 picked = false;
							 for (var i = 0; i < neighbors.length; ++i){
								 gameField.subMeshes[neighbors[i]].materialIndex = 1;
							 }
							 pirats.forEach(function(elem){
					           elem.isPickable = false;
				             });
				             //отправляем сообщение на сервер, что мы сходили
				             var piratMove = {};
				             piratMove.targetCellIndex = id;
				             piratMove.piratId = index;
				             messaging.sendPiratMove(piratMove);
						 }
						//передвигаем шарик
						//посылаем серверу инфу о ходе
					}

					if(MovementUnresolved){
						var enemyPirats = enemy.get_pirats();
						var x, z, y = 15;
						x = - (6 - MovementTargetCell%13 + 0.5)*(1200/13);
						z = (6 - MovementTargetCell/13 + 0.5)*(1200/13);
						console.log("Куда мы передвинулись по факту")
						console.log(x);
						console.log(z);
						enemyPirats[MovementPiratId].position = new BABYLON.Vector3(x,y,z);
					}

				}

			}

		//	this.game_init(possibleIds, gameField, pirats, scene);

      engine.runRenderLoop(function () {
        scene.render();
      })

      window.addEventListener("resize", function () {
        engine.resize();
      });
		}

		init(options = {}) {
      var video = document.querySelector('.bgvideo');
      video.hidden = true;
		}

	  createSkyBox(scene){
			var skybox = BABYLON.Mesh.CreateBox("skyBox", 10000.0, scene);
			var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
			skyboxMaterial.backFaceCulling = false;
			skyboxMaterial.disableLighting = true;
			skybox.material = skyboxMaterial;
			skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
			skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
			skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("sky34/sky34", scene);
			skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
			skybox.renderingGroupId = 0;
		}

		createGameField(scene){
			 var xmin = -600,  zmin = -600;
			 var xmax =  600,  zmax =  600;
			 var precision = {"w" : 1, "h" : 1};
			 var subdivisions = {'h' : 13, 'w' : 13};

			 var tiledGround = new BABYLON.Mesh.CreateTiledGround("Tiled Ground", xmin, zmin, xmax, zmax,
																														 subdivisions, precision, scene);
			 var LightGreen = new BABYLON.StandardMaterial("LGreen", scene);
			 LightGreen.diffuseTexture = new BABYLON.Texture("texture1.1.jpg", scene);
			 LightGreen.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
			 LightGreen.emissiveColor = new BABYLON.Color3(0, 0.5 , 0);

			 var bumpMaterial = new BABYLON.StandardMaterial("bumpMaterial", scene);
			 bumpMaterial.diffuseTexture = new BABYLON.Texture("texture1.1.jpg", scene);
			 bumpMaterial.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
			 bumpMaterial.emissiveColor = new BABYLON.Color3(0.5, 0.5 , 0.5);

			 var DarkGreen = new BABYLON.StandardMaterial("DGreen", scene);
			 DarkGreen.diffuseTexture = new BABYLON.Texture("texture1.2.jpg", scene);
			 DarkGreen.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
			 DarkGreen.emissiveColor = new BABYLON.Color3(0, 0 , 1);
			 DarkGreen.alpha = 0.4;

			 var multimat = new BABYLON.MultiMaterial("multi", scene);
			 multimat.subMaterials.push(LightGreen);
			 multimat.subMaterials.push(bumpMaterial);
			 multimat.subMaterials.push(DarkGreen);

			 tiledGround.material = multimat;
			 tiledGround.renderingGroupId = 1;
			 var verticesCount = tiledGround.getTotalVertices();
			 var tileIndicesLength = tiledGround.getIndices().length / (subdivisions.w * subdivisions.h);

			 tiledGround.subMeshes = [];
			 var base = 0;

			 for(var j = 0; j < 2*subdivisions.h; j++){
				 var subMeshIndex = 2;
				 if((j > 14)&&(j < 24)){
					 subMeshIndex = 1;
				 }
				 new BABYLON.SubMesh(subMeshIndex, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;
			 }

       for(var j = 0; j < subdivisions.h - 4; j++){
				 new BABYLON.SubMesh(2, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;

				 for(var i = 0; i < subdivisions.w - 2; i++){
					 new BABYLON.SubMesh(1, 0, verticesCount, base , tileIndicesLength, tiledGround);
					 base += tileIndicesLength;
				 }

				 new BABYLON.SubMesh(2, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;
			 }

			 for(var j = 0; j < 2*subdivisions.h; j++){
				 var subMeshIndex = 2;
				 if((j > 1)&&(j < 15-4)){
					 subMeshIndex = 1;
				 }
				 new BABYLON.SubMesh(subMeshIndex, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;
			 }

			 return tiledGround;
		 }

		 game_init(Ids, gameField, pirats, scene){
			 var condition = false;
			 var pirat, mesh;
			 var index;
			 var sphere = pirats[0];
 			 var pirat1 = pirats[1];
 			 var pirat2 = pirats[2];
			 scene.onPointerDown = function(evt, pickResult){
				 if(pickResult.hit){
					 pirat = pickResult.pickedMesh;
					 if((pirat == sphere)||(pirat == pirat1)||(pirat == pirat2)){
						 mesh = pirat;
						 mesh.material.diffuseColor = new BABYLON.Color3(0, 1, 0);
						 //----------------------------------------------------
						 if(mesh == sphere){
							 index = 0;
						 }
						 if(mesh == pirat1){
							 index = 1;
						 }
						 if(mesh == pirat2){
							 index = 2;
						 }
						 //-----------------------------------------------------
						 for (var i = 0; i < Ids[index].length; ++i){
							 gameField.subMeshes[Ids[index][i]].materialIndex = 0;
						 }
						 condition = true;
					 }
					 if((pirat == gameField)&&(condition == true)){
						 var id = pickResult.subMeshId;
						 if(Ids[index].indexOf(id) != -1){
							 mesh.position.x = pickResult.pickedPoint.x;
							 mesh.position.z = pickResult.pickedPoint.z;
							 mesh.material.diffuseColor = new BABYLON.Color3(1,0,0);
							 condition = false;
							 for (var i = 0; i < Ids[index].length; ++i){
								 gameField.subMeshes[Ids[index][i]].materialIndex = 1;
							 }
							 Ids[index] = [id+11, id-11, id+1, id-10, id+12, id - 1, id +10, id -12];
						 }
					 }
				 }
			 }
		 }

	}

	// export
	window.GamePlayView = GamePlayView;

})();
<commit_msg>Web Sockets ready1<commit_after>(function () {
	'use strict';

	const View = window.View;
	const Player = window.Player;
	const MessagingTools = window.MessagingTools;

	class GamePlayView extends View {
		constructor(options = {}) {
			super(options);
			this._el = document.querySelector('.js-canvas');
			this.allowGameStart = false;

      this.init();
      this.show();

      //потом сюда надо будет вбить урл сервера
			//---------------------------------------------------------------------
      //var socket = new WebSocket("ws://localhost:8080/game");
      var socket = new WebSocket("wss://java-heroku-test-victor.herokuapp.com/game");
            var messaging = new MessagingTools(socket);
      socket.onopen = function () {
        // Socket open.. start the game loop.
        console.log('Info: WebSocket connection opened.');
        console.log('Info: Waiting for another player...');
      };

      function Send(){
      	messaging.sendJoinGameMsg();
      }

      setTimeout(Send,1500);
      socket.onclose = function () {
        console.log('Info: WebSocket closed.');
      };

      socket.onmessage = function (event) {
      	var content = {};
        var responseContent = {};
        var response = {};
        var message = JSON.parse(event.data);
        if (message.type === "ru.mail.park.websocket.MessageToClient$Request") {
            content = JSON.parse(message.content);
            responseContent.myMessage = content.myMessage;
            console.log(responseContent.myMessage);
            return;
        }
        if ( message.type === "ru.mail.park.mechanics.requests.BoardMapForUsers$Request"){
            console.log("Wow. Seems loke game been started");
            content = JSON.parse(message.content);
            gameCellIds = content.gameBoard;
            gameCellIds = gameCellIds.split(",");
            for(var j = 0; j < gameCellIds.length; j++){
            	gameCellIds[j]= +gameCellIds[j];
            };
            if(content.active){
            	thisPlayer = player1;
            	enemy = player2;
            	var pirats1 = player1.get_pirats();
            	pirats1.forEach(function(elem){
            		elem.isPickable = true;
            	});
            }
            else{
            	thisPlayer = player2;
            	enemy = player1;
            	var pirats2 = player2.get_pirats();
            	pirats2.forEach(function(elem){
            		elem.isPickable = false;
            	})
            }
            console.log("Проверяем проставление активного игрока");
            console.log(content.active);
            console.log(thisPlayer);
            console.log(player1);
			//this.allowGameStart = true;

        }
		if ( message.type === "ru.mail.park.mechanics.requests.NeighborsMessage$Request"){
            console.log("Получены соседи клетки!");
            content = JSON.parse(message.content);
            console.log(content);
			    neighbors = content.neighbors;
				neighbors = neighbors.split(",");
				for(var j = 0; j < neighbors.length; j++){
            		neighbors[j]= +neighbors[j];
            		console.log(typeof(neighbors[j]));
            	};

            console.log('Соседи: ' + neighbors.length);

			for(var i = 0; i < neighbors.length; ++i){
				gameField.subMeshes[neighbors[i]].materialIndex = 0;
				//console.log("пытаемся подсветить клетку");
			}
        }
        if(message.type === "ru.mail.park.mechanics.requests.PiratMoveMessage$Request") {
        	console.log("О_о сервер ghbckfk ход другого игрока");
            content = JSON.parse(message.content);
            console.log(content);
            if(content.active){
            	var thisPirats = thisPlayer.get_pirats();
            	thisPirats.forEach(function(elem){
            		elem.isPickable = true;
            	});
            	MovementPiratId = content.piratId;
            	MovementTargetCell = content.newCellIndexOfPirat;
            	MovementUnresolved = true;

            }

        }
      }

			//--------------------------------------------------------------------------

      var engine = new BABYLON.Engine(this._el, true);
      var canvas = this._el;

      var createScene = function(){
        var scene = new BABYLON.Scene(engine);
        var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI/2, Math.PI / 3,
				                                         12, new BABYLON.Vector3(-100,100,100), scene);
        camera.lowerBetaLimit = 0.1;
        camera.lowerRadiusLimit = 30;
        camera.upperRadiusLimit = 250;
        camera.attachControl(canvas, true);
        var light = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 1, 0), scene);
        light.intensity = .5;

        return scene;
      }

      var scene = createScene();

			//начинаем игровой цикл
			const player1 = new Player(0, scene, {}); //первый игрок и его меши
			const player2 = new Player(1, scene, {}); // 2-й игрок и его меши
			var thisPlayer, enemy;
			var MovementPiratId, MovementTargetCell;

		//	var pirats = player1.get_pirats();
		//	var possibleIds = player1.get_ids();

			this.createSkyBox(scene);
			var gameField = this.createGameField(scene);
			var gameCellIds = " ";
			var MovementUnresolved = false;
            //var str = " ";
			//пошёл цикл
			var pirats ;
			var mesh;
			var neighbors = [];
			var picked = false;
			var ball;
			var index, ids = [], cellIndex, piratMove;
			scene.onPointerDown = function(evt, pickResult){

				if(pickResult.hit){
					mesh = pickResult.pickedMesh;
					pirats = thisPlayer.get_pirats();
					if(pirats.indexOf(mesh)!= -1){
						mesh.material.diffuseColor = new BABYLON.Color3(0, 1, 0);
						ball = mesh;

						//здесь нужно получить от сервера смежные клетки
						index = pirats.indexOf(mesh);
					 	ids = thisPlayer.get_ids(); //номер пирата
						cellIndex = ids[index]; //айди клетки
						piratMove = {};

				 		var getCellneighbors = {};
			      		getCellneighbors.cellIndex = cellIndex;
			      		messaging.sendGetNeighbors(getCellneighbors);

						picked = true;
					}
					if((mesh === gameField)&&(picked == true)){

						//здесь уже выбираем из смежных клетку, на которую пойдем
						console.log("мы хотим передвинуть шарик");
						var id = pickResult.subMeshId;
						console.log(id);
						console.log(typeof(+neighbors[0]));
						 if(neighbors.indexOf(id) != -1){
						 	console.log("мы кликнули на подсвеченную клетку");
						 	 ball.position.x = pickResult.pickedPoint.x;
							 ball.position.z = pickResult.pickedPoint.z;
							 console.log("Куда мы должны были передвинуться")
							 console.log(ball.position.x);
							 console.log(ball.position.z);
							 ball.material.diffuseColor = new BABYLON.Color3(1,0,0);
							 ids[index] = id;
							 thisPlayer.set_ids(ids);
							 picked = false;
							 for (var i = 0; i < neighbors.length; ++i){
								 gameField.subMeshes[neighbors[i]].materialIndex = 1;
							 }
							 pirats.forEach(function(elem){
					           elem.isPickable = false;
				             });
				             //отправляем сообщение на сервер, что мы сходили
				             var piratMove = {};
				             piratMove.targetCellIndex = id;
				             piratMove.piratId = index;
				             messaging.sendPiratMove(piratMove);
						 }
						//передвигаем шарик
						//посылаем серверу инфу о ходе
					}

					if(MovementUnresolved){
						var enemyPirats = enemy.get_pirats();
						var x, z, y = 15;
						x = - (6 - MovementTargetCell%13 + 0.5)*(1200/13);
						z = (6 - MovementTargetCell/13 + 0.5)*(1200/13);
						console.log("Куда мы передвинулись по факту")
						console.log(x);
						console.log(z);
						enemyPirats[MovementPiratId].position = new BABYLON.Vector3(x,y,z);
					}

				}

			}

		//	this.game_init(possibleIds, gameField, pirats, scene);

      engine.runRenderLoop(function () {
        scene.render();
      })

      window.addEventListener("resize", function () {
        engine.resize();
      });
		}

		init(options = {}) {
      var video = document.querySelector('.bgvideo');
      video.hidden = true;
		}

	  createSkyBox(scene){
			var skybox = BABYLON.Mesh.CreateBox("skyBox", 10000.0, scene);
			var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
			skyboxMaterial.backFaceCulling = false;
			skyboxMaterial.disableLighting = true;
			skybox.material = skyboxMaterial;
			skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
			skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
			skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("sky34/sky34", scene);
			skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
			skybox.renderingGroupId = 0;
		}

		createGameField(scene){
			 var xmin = -600,  zmin = -600;
			 var xmax =  600,  zmax =  600;
			 var precision = {"w" : 1, "h" : 1};
			 var subdivisions = {'h' : 13, 'w' : 13};

			 var tiledGround = new BABYLON.Mesh.CreateTiledGround("Tiled Ground", xmin, zmin, xmax, zmax,
																														 subdivisions, precision, scene);
			 var LightGreen = new BABYLON.StandardMaterial("LGreen", scene);
			 LightGreen.diffuseTexture = new BABYLON.Texture("texture1.1.jpg", scene);
			 LightGreen.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
			 LightGreen.emissiveColor = new BABYLON.Color3(0, 0.5 , 0);

			 var bumpMaterial = new BABYLON.StandardMaterial("bumpMaterial", scene);
			 bumpMaterial.diffuseTexture = new BABYLON.Texture("texture1.1.jpg", scene);
			 bumpMaterial.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
			 bumpMaterial.emissiveColor = new BABYLON.Color3(0.5, 0.5 , 0.5);

			 var DarkGreen = new BABYLON.StandardMaterial("DGreen", scene);
			 DarkGreen.diffuseTexture = new BABYLON.Texture("texture1.2.jpg", scene);
			 DarkGreen.bumpTexture = new BABYLON.Texture("normalMap.jpg", scene);
			 DarkGreen.emissiveColor = new BABYLON.Color3(0, 0 , 1);
			 DarkGreen.alpha = 0.4;

			 var multimat = new BABYLON.MultiMaterial("multi", scene);
			 multimat.subMaterials.push(LightGreen);
			 multimat.subMaterials.push(bumpMaterial);
			 multimat.subMaterials.push(DarkGreen);

			 tiledGround.material = multimat;
			 tiledGround.renderingGroupId = 1;
			 var verticesCount = tiledGround.getTotalVertices();
			 var tileIndicesLength = tiledGround.getIndices().length / (subdivisions.w * subdivisions.h);

			 tiledGround.subMeshes = [];
			 var base = 0;

			 for(var j = 0; j < 2*subdivisions.h; j++){
				 var subMeshIndex = 2;
				 if((j > 14)&&(j < 24)){
					 subMeshIndex = 1;
				 }
				 new BABYLON.SubMesh(subMeshIndex, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;
			 }

       for(var j = 0; j < subdivisions.h - 4; j++){
				 new BABYLON.SubMesh(2, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;

				 for(var i = 0; i < subdivisions.w - 2; i++){
					 new BABYLON.SubMesh(1, 0, verticesCount, base , tileIndicesLength, tiledGround);
					 base += tileIndicesLength;
				 }

				 new BABYLON.SubMesh(2, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;
			 }

			 for(var j = 0; j < 2*subdivisions.h; j++){
				 var subMeshIndex = 2;
				 if((j > 1)&&(j < 15-4)){
					 subMeshIndex = 1;
				 }
				 new BABYLON.SubMesh(subMeshIndex, 0, verticesCount, base , tileIndicesLength, tiledGround);
				 base += tileIndicesLength;
			 }

			 return tiledGround;
		 }

		 game_init(Ids, gameField, pirats, scene){
			 var condition = false;
			 var pirat, mesh;
			 var index;
			 var sphere = pirats[0];
 			 var pirat1 = pirats[1];
 			 var pirat2 = pirats[2];
			 scene.onPointerDown = function(evt, pickResult){
				 if(pickResult.hit){
					 pirat = pickResult.pickedMesh;
					 if((pirat == sphere)||(pirat == pirat1)||(pirat == pirat2)){
						 mesh = pirat;
						 mesh.material.diffuseColor = new BABYLON.Color3(0, 1, 0);
						 //----------------------------------------------------
						 if(mesh == sphere){
							 index = 0;
						 }
						 if(mesh == pirat1){
							 index = 1;
						 }
						 if(mesh == pirat2){
							 index = 2;
						 }
						 //-----------------------------------------------------
						 for (var i = 0; i < Ids[index].length; ++i){
							 gameField.subMeshes[Ids[index][i]].materialIndex = 0;
						 }
						 condition = true;
					 }
					 if((pirat == gameField)&&(condition == true)){
						 var id = pickResult.subMeshId;
						 if(Ids[index].indexOf(id) != -1){
							 mesh.position.x = pickResult.pickedPoint.x;
							 mesh.position.z = pickResult.pickedPoint.z;
							 mesh.material.diffuseColor = new BABYLON.Color3(1,0,0);
							 condition = false;
							 for (var i = 0; i < Ids[index].length; ++i){
								 gameField.subMeshes[Ids[index][i]].materialIndex = 1;
							 }
							 Ids[index] = [id+11, id-11, id+1, id-10, id+12, id - 1, id +10, id -12];
						 }
					 }
				 }
			 }
		 }

	}

	// export
	window.GamePlayView = GamePlayView;

})();
<|endoftext|>


<commit_before>var fs = require('fs');

module.exports = function (grunt) {

  grunt.registerTask('sketchbox', 'css web components', function() {
    var done = this.async();
    parseOption.apply(this, [ grunt, done ]);
  });
};

var availableOptions = [ 'component' ];
var actions = {
  component: function(name, configOptions, logger, done) {
    var filepath = __dirname + '/../../components/' + name,
        stypePreProcessor = configOptions.stylePreProcessor;

    fs.mkdir(filepath, function(err) {
      if(err) { console.log(err); return; }

      logger.oklns("Component named `" + name + "` created.")

      fs.writeFile(filepath + '/style.' + stypePreProcessor, fs.readFileSync(__dirname + '/templates/component/style.tpl', 'utf8'), function(err) {
        if(err) { console.log(err); return; }

        logger.oklns("Style file for `" + name + "` created.")

        fs.writeFile(filepath + '/example.html', fs.readFileSync(__dirname + '/templates/component/example.html'), function(err) {
          logger.oklns("Example file for `" + name + "` created.")
          done();
        });
      });
    });
  }
}

var parseOption = function(grunt, done) {
  var i,
      length,
      availableOption,
      optionValue,
      action,
      configOptions = this.options(),
      option = grunt.option;

  for(i=0, length = availableOptions.length; i<length; i++) {
    availableOption = availableOptions[i];
    optionValue = option(availableOption);

    if(optionValue) {
      action = actions[availableOption];
      if(action) { break; }
    }
  }

  if(action) {
    action(optionValue, configOptions, grunt.log, done);
  }
};
<commit_msg>renamed parseOption to dispatch<commit_after>var fs = require('fs');

module.exports = function (grunt) {

  grunt.registerTask('sketchbox', 'css web components', function() {
    var done = this.async();

    dispatch.apply(this, [ grunt, done ]);
  });
};

var availableOptions = [ 'component' ];
var actions = {
  component: function(name, configOptions, logger, done) {
    var filepath = __dirname + '/../../components/' + name,
        stypePreProcessor = configOptions.stylePreProcessor;

    fs.mkdir(filepath, function(err) {
      if(err) { console.log(err); return; }

      logger.oklns("Component named `" + name + "` created.")

      fs.writeFile(filepath + '/style.' + stypePreProcessor, fs.readFileSync(__dirname + '/templates/component/style.tpl', 'utf8'), function(err) {
        if(err) { console.log(err); return; }

        logger.oklns("Style file for `" + name + "` created.")

        fs.writeFile(filepath + '/example.html', fs.readFileSync(__dirname + '/templates/component/example.html'), function(err) {
          logger.oklns("Example file for `" + name + "` created.")

          // Done Callback
          done();
        });
      });
    });
  }
}

var dispatch = function(grunt, done) {
  var i,
      length,
      availableOption,
      optionValue,
      action,
      configOptions = this.options(),
      option = grunt.option;

  for(i=0, length = availableOptions.length; i<length; i++) {
    availableOption = availableOptions[i];
    optionValue = option(availableOption);

    if(optionValue) {
      action = actions[availableOption];

      if(action) {
        action(optionValue, configOptions, grunt.log, done);
        return;
      }
    }
  }

};
<|endoftext|>