268 lines · 9.5 KB · JavaScript
RawDownload
////  flashlight.js////  Script Type: Entity////  Created by Sam Gateau on 9/9/15.//  Additions by James B. Pollack @imgntn on 9/21/2015//  Copyright 2015 High Fidelity, Inc.////  This is a toy script that can be added to the Flashlight model entity://  Script.getExternalPath(Script.ExternalPaths.HF_Public, "/models/props/flashlight.fbx")//  that creates a spotlight attached with the flashlight model while the entity is grabbed////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// (function() {     var ON_SOUND_URL = Script.getExternalPath(Script.ExternalPaths.HF_Public, '/sounds/Switches%20and%20sliders/flashlight_on.wav');    var OFF_SOUND_URL = Script.getExternalPath(Script.ExternalPaths.HF_Public, '/sounds/Switches%20and%20sliders/flashlight_off.wav');     //we are creating lights that we don't want to get stranded so lets make sure that we can get rid of them    //if you're going to be using this in a dungeon or something and holding it for a long time, increase this lifetime value.    var LIFETIME = 100;      // this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember    // our this object, so we can access it in cases where we're called without a this (like in the case of various global signals)    function Flashlight() {        return;    }     //if the trigger value goes below this while held, the flashlight will turn off.  if it goes above, it will     var DISABLE_LIGHT_THRESHOLD = 0.7;     // These constants define the Spotlight position and orientation relative to the model     var MODEL_LIGHT_POSITION = {        x: 0,        y: -0.3,        z: 0    };    var MODEL_LIGHT_ROTATION = Quat.angleAxis(-90, {        x: 1,        y: 0,        z: 0    });     //there's another small point light we put at the end of the flashlight to make the end glow     var GLOW_LIGHT_POSITION = {        x: 0,        y: -0.1,        z: 0    };     // Evaluate the world light entity positions and orientations from the model ones    function evalLightWorldTransform(modelPosition, modelRotation) {         return {            p: Vec3.sum(modelPosition, Vec3.multiplyQbyV(modelRotation, MODEL_LIGHT_POSITION)),            q: Quat.multiply(modelRotation, MODEL_LIGHT_ROTATION)        };    }     function glowLightWorldTransform(modelPosition, modelRotation) {        return {            p: Vec3.sum(modelPosition, Vec3.multiplyQbyV(modelRotation, GLOW_LIGHT_POSITION)),            q: Quat.multiply(modelRotation, MODEL_LIGHT_ROTATION)        };    }     Flashlight.prototype = {        lightOn: false,        hand: null,        whichHand: null,        hasSpotlight: false,        spotlight: null,         startNearGrab: function(entityID, args) {            //this first second parameter in this method contains arguments from the grab script, the first of which is the 'hand' that was used to start the grab            this.hand = args[0];            if (!this.hasSpotlight) {                 var modelProperties = Entities.getEntityProperties(this.entityID, ['position', 'rotation']);                var lightTransform = evalLightWorldTransform(modelProperties.position, modelProperties.rotation);                var glowLightTransform = glowLightWorldTransform(modelProperties.position, modelProperties.rotation);                  //this light casts the beam                this.spotlight = Entities.addEntity({                    type: "Light",                    isSpotlight: true,                    dimensions: {                        x: 2,                        y: 2,                        z: 20                    },                    parentID: this.entityID,                    color: {                        red: 255,                        green: 255,                        blue: 255                    },                    intensity:  1,                    falloffRadius:0.9,                    exponent: 0.5,                    cutoff: 20,                    lifetime: LIFETIME,                    position: lightTransform.p,                    rotation: lightTransform.q,                });                 //this light creates the effect of a bulb at the end of the flashlight                this.glowLight = Entities.addEntity({                    type: "Light",                    dimensions: {                        x: 0.25,                        y: 0.25,                        z: 0.25                    },                    parentID: this.entityID,                    isSpotlight: false,                    color: {                        red: 255,                        green: 255,                        blue: 255                    },                    exponent: 0,                    intensity:1.0,                    falloffRadius:0.3,                    lifetime: LIFETIME,                    cutoff: 90, // in degrees                    position: glowLightTransform.p,                    rotation: glowLightTransform.q,                 });                 this.hasSpotlight = true;             }         },        startEquip: function(id, params) {            this.startNearGrab(id, params);        },         setWhichHand: function() {            this.whichHand = this.hand;        },         continueNearGrab: function() {            if (this.whichHand === null) {                //only set the active hand once -- if we always read the current hand, our 'holding' hand will get overwritten                this.setWhichHand();            } else {                this.changeLightWithTriggerPressure(this.whichHand);            }        },        continueEquip: function(entityID, args) {            this.continueNearGrab(entityID, args);        },         releaseGrab: function(entityID, args) {            //delete the lights and reset state            if (this.hasSpotlight) {                Entities.deleteEntity(this.spotlight);                Entities.deleteEntity(this.glowLight);                this.hasSpotlight = false;                this.glowLight = null;                this.spotlight = null;                this.whichHand = null;                this.lightOn = false;            }        },         releaseEquip: function(entityID, args) {            this.releaseGrab(entityID, args);        },                changeLightWithTriggerPressure: function(flashLightHand) {            //read the value of the controller trigger and use it to turn the light on / off when the value reaches certain thresholds            if (flashLightHand === 'LEFT') {                this.triggerValue = Controller.getValue(Controller.Standard.LT);            }            if (flashLightHand === 'RIGHT') {                this.triggerValue = Controller.getValue(Controller.Standard.RT);             }             if (this.triggerValue < DISABLE_LIGHT_THRESHOLD && this.lightOn === true) {                this.turnLightOff();            } else if (this.triggerValue >= DISABLE_LIGHT_THRESHOLD && this.lightOn === false) {                this.turnLightOn();            }            return;        },         turnLightOff: function() {            this.playSoundAtCurrentPosition(false);            Entities.editEntity(this.spotlight, {                intensity: 0            });            Entities.editEntity(this.glowLight, {                intensity: 0            });            this.lightOn = false;        },         turnLightOn: function() {            this.playSoundAtCurrentPosition(true);             Entities.editEntity(this.glowLight, {                intensity: 2            });            Entities.editEntity(this.spotlight, {                intensity: 2            });            this.lightOn = true;        },         playSoundAtCurrentPosition: function(playOnSound) {            //when someone grabs, play a clicking noise for turning the flashlight on/off            var position = Entities.getEntityProperties(this.entityID, "position").position;             var audioProperties = {                volume: 0.25,                position: position            };             if (playOnSound) {                Audio.playSound(this.ON_SOUND, audioProperties);            } else {                Audio.playSound(this.OFF_SOUND, audioProperties);            }        },         preload: function(entityID) {            //  preload() will be called when the entity has become visible (or known) to the interface            //  it gives us a chance to set our local JavaScript object up. In this case it means:            //  * remembering our entityID, so we can access it in cases where we're called without an entityID            //  * preloading sounds            this.entityID = entityID;            this.ON_SOUND = SoundCache.getSound(ON_SOUND_URL);            this.OFF_SOUND = SoundCache.getSound(OFF_SOUND_URL);         },         unload: function() {            // unload() will be called when our entity is no longer available. It may be because we were deleted,            // or because we've left the domain or quit the application.            if (this.hasSpotlight) {                Entities.deleteEntity(this.spotlight);                Entities.deleteEntity(this.glowLight);                this.hasSpotlight = false;                this.glowLight = null;                this.spotlight = null;                this.whichHand = null;                this.lightOn = false;            }         },     };     // entity should return a newly constructed object of our type    return new Flashlight();});