296 lines · 13.1 KB · JavaScript
RawDownload
////  controllerDisplay.js////  Created by Anthony J. Thibault on 10/20/16//  Originally created by Ryan Huffman on 9/21/2016//  Copyright 2016 High Fidelity, Inc.//  Copyright 2023, Overte e.V.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html /* globals createControllerDisplay:true, deleteControllerDisplay:true, Controller, Entities, Vec3, MyAvatar, Quat */ function clamp(value, min, max) {    if (value < min) {        return min;    } else if (value > max) {        return max;    }    return value;} function resolveHardware(path) {    if (typeof path === 'string') {        var parts = path.split(".");        function resolveInner(base, path, i) {            if (i >= path.length) {                return base;            }            return resolveInner(base[path[i]], path, ++i);        }        return resolveInner(Controller.Hardware, parts, 0);    }    return path;} var DEBUG = true;function debug() {    if (DEBUG) {        var args = Array.prototype.slice.call(arguments);        args.unshift("controllerDisplay.js | ");        print.apply(this, args);    }} createControllerDisplay = function(config) {    var controllerDisplay = {        overlays: [],        partOverlays: {},        parts: {},        mappingName: "mapping-display-" + Math.random(),        partValues: {},         setVisible: function(visible) {            for (var i = 0; i < this.overlays.length; ++i) {                Entities.editEntity(this.overlays[i], {                    "visible": visible                });            }        },         setPartVisible: function(partName, visible) {            // Disabled            /*            if (partName in this.partOverlays) {                for (var i = 0; i < this.partOverlays[partName].length; ++i) {                    Entities.editEntity(this.partOverlays[partName][i], {                        //"visible": visible                    });                }            }            */        },         setLayerForPart: function(partName, layerName) {            if (partName in this.parts) {                var part = this.parts[partName];                if (part.textureLayers && layerName in part.textureLayers) {                    var layer = part.textureLayers[layerName];                    var textures = {};                    if (layer.defaultTextureURL) {                        textures[part.textureName] = layer.defaultTextureURL;                    }                    for (var i = 0; i < this.partOverlays[partName].length; ++i) {                        Entities.editEntity(this.partOverlays[partName][i], {                            "textures": textures                        });                    }                }            }        },         resize: function(sensorScaleFactor) {            if (this.overlays.length >= 0) {                var controller = config.controllers[0];                var position = controller.position;                 // first overlay/Local Entity is main body.                var overlayID = this.overlays[0];                var localPosition = Vec3.multiply(sensorScaleFactor, Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position));                var dimensions = Vec3.multiply(sensorScaleFactor, controller.dimensions);                 Entities.editEntity(overlayID, {                    "dimensions": dimensions,                    "localPosition": localPosition                });                 if (controller.parts) {                    var i = 1;                    for (var partName in controller.parts) {                        overlayID = this.overlays[i++];                        var part = controller.parts[partName];                        localPosition = Vec3.subtract(part.naturalPosition, controller.naturalPosition);                        var localRotation;                        var value = this.partValues[partName];                        var offset, rotation;                        if (value !== undefined) {                            if (part.type === "linear") {                                offset = Vec3.multiply(part.maxTranslation * value, part.axis);                                localPosition = Vec3.sum(localPosition, offset);                                localRotation = undefined;                            } else if (part.type === "joystick") {                                rotation = Quat.fromPitchYawRollDegrees(value.y * part.xHalfAngle, 0, value.x * part.yHalfAngle);                                if (part.originOffset) {                                    offset = Vec3.multiplyQbyV(rotation, part.originOffset);                                    offset = Vec3.subtract(part.originOffset, offset);                                } else {                                    offset = { x: 0, y: 0, z: 0 };                                }                                localPosition = Vec3.sum(offset, localPosition);                                localRotation = rotation;                            } else if (part.type === "rotational") {                                value = clamp(value, part.minValue, part.maxValue);                                var pct = (value - part.minValue) / part.maxValue;                                var angle = pct * part.maxAngle;                                rotation = Quat.angleAxis(angle, part.axis);                                if (part.origin) {                                    offset = Vec3.multiplyQbyV(rotation, part.origin);                                    offset = Vec3.subtract(offset, part.origin);                                } else {                                    offset = { x: 0, y: 0, z: 0 };                                }                                localPosition = Vec3.sum(offset, localPosition);                                localRotation = rotation;                            }                        }                        if (localRotation !== undefined) {                            Entities.editEntity(overlayID, {                                "dimensions": Vec3.multiply(sensorScaleFactor, part.naturalDimensions),                                "localPosition": Vec3.multiply(sensorScaleFactor, localPosition),                                "localRotation": localRotation                            });                        } else {                            Entities.editEntity(overlayID, {                                "dimensions": Vec3.multiply(sensorScaleFactor, part.naturalDimensions),                                "localPosition": Vec3.multiply(sensorScaleFactor, localPosition)                            });                        }                    }                }            }        }    };     var mapping = Controller.newMapping(controllerDisplay.mappingName);    for (var i = 0; i < config.controllers.length; ++i) {        var controller = config.controllers[i];        var position = controller.position;        var sensorScaleFactor = MyAvatar.sensorToWorldScale;         if (controller.naturalPosition) {            position = Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position);        } else {            controller.naturalPosition = { x: 0, y: 0, z: 0 };        }         var baseOverlayID = Entities.addEntity({            "type": "Model",            "modelURL": controller.modelURL,            "dimensions": Vec3.multiply(sensorScaleFactor, controller.dimensions),            "localRotation": controller.rotation,            "localPosition": Vec3.multiply(sensorScaleFactor, position),            "parentID": MyAvatar.SELF_ID,            "parentJointIndex": controller.jointIndex,            "ignorePickIntersection": true        }, "local");         controllerDisplay.overlays.push(baseOverlayID);         if (controller.parts) {            for (var partName in controller.parts) {                var part = controller.parts[partName];                var localPosition = Vec3.subtract(part.naturalPosition, controller.naturalPosition);                var localRotation = { x: 0, y: 0, z: 0, w: 1 };                 controllerDisplay.parts[partName] = controller.parts[partName];                 var properties = {                    "type": "Model",                    "modelURL": part.modelURL,                    "localPosition": localPosition,                    "localRotation": localRotation,                    "parentID": baseOverlayID,                    "ignorePickIntersection": true                };                 if (part.defaultTextureLayer) {                    var textures = {};                    textures[part.textureName] = part.textureLayers[part.defaultTextureLayer].defaultTextureURL;                    properties.textures = textures;                }                 var overlayID = Entities.addEntity(properties, "local");                 if (part.type === "rotational") {                    var input = resolveHardware(part.input);                    mapping.from([input]).peek().to(function(partName) {                        return function(value) {                            // insert the most recent controller value into controllerDisplay.partValues.                            controllerDisplay.partValues[partName] = value;                            controllerDisplay.resize(MyAvatar.sensorToWorldScale);                        };                    }(partName));                } else if (part.type === "touchpad") {                    var visibleInput = resolveHardware(part.visibleInput);                    var xInput = resolveHardware(part.xInput);                    var yInput = resolveHardware(part.yInput);                     // TODO: Touchpad inputs are currently only working for half                    // of the touchpad. When that is fixed, it would be useful                    // to update these to display the current finger position.                    mapping.from([visibleInput]).peek().to(function(value) {                    });                    mapping.from([xInput]).peek().to(function(value) {                    });                    mapping.from([yInput]).peek().invert().to(function(value) {                    });                } else if (part.type === "joystick") {                    (function(part, partName) {                        var xInput = resolveHardware(part.xInput);                        var yInput = resolveHardware(part.yInput);                        mapping.from([xInput]).peek().to(function(value) {                            // insert the most recent controller value into controllerDisplay.partValues.                            if (controllerDisplay.partValues[partName]) {                                controllerDisplay.partValues[partName].x = value;                            } else {                                controllerDisplay.partValues[partName] = {x: value, y: 0};                            }                            controllerDisplay.resize(MyAvatar.sensorToWorldScale);                        });                        mapping.from([yInput]).peek().to(function(value) {                            // insert the most recent controller value into controllerDisplay.partValues.                            if (controllerDisplay.partValues[partName]) {                                controllerDisplay.partValues[partName].y = value;                            } else {                                controllerDisplay.partValues[partName] = {x: 0, y: value};                            }                            controllerDisplay.resize(MyAvatar.sensorToWorldScale);                        });                    })(part, partName);                 } else if (part.type === "linear") {                    (function(part, partName) {                        var input = resolveHardware(part.input);                        mapping.from([input]).peek().to(function(value) {                            // insert the most recent controller value into controllerDisplay.partValues.                            controllerDisplay.partValues[partName] = value;                            controllerDisplay.resize(MyAvatar.sensorToWorldScale);                        });                    })(part, partName);                 } else if (part.type === "static") {                    // do nothing                } else {                    debug("TYPE NOT SUPPORTED: ", part.type);                }                 controllerDisplay.overlays.push(overlayID);                if (!(partName in controllerDisplay.partOverlays)) {                    controllerDisplay.partOverlays[partName] = [];                }                controllerDisplay.partOverlays[partName].push(overlayID);            }        }    }    Controller.enableMapping(controllerDisplay.mappingName);    controllerDisplay.resize(MyAvatar.sensorToWorldScale);    return controllerDisplay;}; deleteControllerDisplay = function(controllerDisplay) {    for (var i = 0; i < controllerDisplay.overlays.length; ++i) {        Entities.deleteEntity(controllerDisplay.overlays[i]);    }    Controller.disableMapping(controllerDisplay.mappingName);};