diff --git a/examples/libraries/walkApi.js b/examples/libraries/walkApi.js new file mode 100644 index 0000000000..90b9dad623 --- /dev/null +++ b/examples/libraries/walkApi.js @@ -0,0 +1,409 @@ +// +// walkObjects.js +// +// version 1.000 +// +// Created by David Wooldridge, Autumn 2014 +// +// Motion, state and Transition objects for use by the walk.js script v1.1 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +// constructor for the Motion object +Motion = function() { + + this.setGender = function(gender) { + + this.avatarGender = gender; + + switch(this.avatarGender) { + + case MALE: + + this.selWalk = walkAssets.maleStandardWalk; + this.selStand = walkAssets.maleStandOne; + this.selFlyUp = walkAssets.maleFlyingUp; + this.selFly = walkAssets.maleFlying; + this.selFlyDown = walkAssets.maleFlyingDown; + this.selSideStepLeft = walkAssets.maleSideStepLeft; + this.selSideStepRight = walkAssets.maleSideStepRight; + this.curAnim = this.selStand; + return; + + case FEMALE: + + this.selWalk = walkAssets.femaleStandardWalk; + this.selStand = walkAssets.femaleStandOne; + this.selFlyUp = walkAssets.femaleFlyingUp; + this.selFly = walkAssets.femaleFlying; + this.selFlyDown = walkAssets.femaleFlyingDown; + this.selSideStepLeft = walkAssets.femaleSideStepLeft; + this.selSideStepRight = walkAssets.femaleSideStepRight; + this.curAnim = this.selStand; + return; + } + } + + this.hydraCheck = function() { + + // function courtesy of Thijs Wenker, frisbee.js + var numberOfButtons = Controller.getNumberOfButtons(); + var numberOfTriggers = Controller.getNumberOfTriggers(); + var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); + var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + hydrasConnected = (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2); + return hydrasConnected; + } + + // settings + this.armsFree = this.hydraCheck(); // automatically sets true for Hydra support - temporary fix + this.makesFootStepSounds = true; + this.avatarGender = MALE; + this.motionPitchMax = 60; + this.motionRollMax = 40; + + // timing + this.frameStartTime = 0; // used for measuring frame execution times + this.frameExecutionTimeMax = 0; // keep track of the longest frame execution time + this.cumulativeTime = 0.0; + this.lastWalkStartTime = 0; + + // selected animations + this.selWalk = walkAssets.maleStandardWalk; + this.selStand = walkAssets.maleStandOne; + this.selFlyUp = walkAssets.maleFlyingUp; + this.selFly = walkAssets.maleFlying; + this.selFlyDown = walkAssets.maleFlyingDown; + this.selSideStepLeft = walkAssets.maleSideStepLeft; + this.selSideStepRight = walkAssets.maleSideStepRight; + + // the currently selected animation, joint and transition + this.curAnim = this.selStand; + this.curJointIndex = 0; + this.curTransition = null; + + // zero out avi's joints, curl the fingers nicely then take some measurements + this.avatarJointNames = MyAvatar.getJointNames(); + if (!this.armsFree) { + + for (var i = 0; i < this.avatarJointNames.length; i++) { + + if (i > 17 || i < 34) + // left hand fingers + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(16, 0, 0)); + + else if (i > 33 || i < 38) + // left hand thumb + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(4, 0, 0)); + + else if (i > 41 || i < 58) + // right hand fingers + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(16, 0, 0)); + + else if (i > 57 || i < 62) + // right hand thumb + MyAvatar.setJointData(this.avatarJointNames[i], Quat.fromPitchYawRollDegrees(4, 0, 0)); + + else + // zero out the remaining joints + MyAvatar.clearJointData(this.avatarJointNames[i]); + } + } + + this.footRPos = MyAvatar.getJointPosition("RightFoot"); + this.hipsToFeet = MyAvatar.getJointPosition("Hips").y - this.footRPos.y; + + // walkwheel (foot / ground speed matching) + this.direction = FORWARDS; + this.nextStep = RIGHT; + this.nFrames = 0; + this.strideLength = this.selWalk.calibration.strideLengthForwards; + this.walkWheelPos = 0; + + this.advanceWalkWheel = function(angle){ + + this.walkWheelPos += angle; + if (motion.walkWheelPos >= 360) + this.walkWheelPos = this.walkWheelPos % 360; + } + + // last frame history + this.lastDirection = 0; + this.lastVelocity = 0; + +}; // end Motion constructor + +// finite state machine +state = (function () { + + return { + + // the finite list of states + STANDING: 1, + WALKING: 2, + SIDE_STEP: 3, + FLYING: 4, + EDIT_WALK_STYLES: 5, + EDIT_WALK_TWEAKS: 6, + EDIT_WALK_JOINTS: 7, + EDIT_STANDING: 8, + EDIT_FLYING: 9, + EDIT_FLYING_UP: 10, + EDIT_FLYING_DOWN: 11, + EDIT_SIDESTEP_LEFT: 12, + EDIT_SIDESTEP_RIGHT: 14, + currentState: this.STANDING, + + // status vars + powerOn: true, + minimised: true, + editing:false, + editingTranslation: false, + + setInternalState: function(newInternalState) { + + switch (newInternalState) { + + case this.WALKING: + + this.currentState = this.WALKING; + this.editing = false; + motion.lastWalkStartTime = new Date().getTime(); + walkInterface.updateMenu(); + return; + + case this.FLYING: + + this.currentState = this.FLYING; + this.editing = false; + motion.lastWalkStartTime = 0; + walkInterface.updateMenu(); + return; + + case this.SIDE_STEP: + + this.currentState = this.SIDE_STEP; + this.editing = false; + motion.lastWalkStartTime = new Date().getTime(); + walkInterface.updateMenu(); + return; + + case this.EDIT_WALK_STYLES: + + this.currentState = this.EDIT_WALK_STYLES; + this.editing = true; + motion.lastWalkStartTime = new Date().getTime(); + motion.curAnim = motion.selWalk; + walkInterface.updateMenu(); + return; + + case this.EDIT_WALK_TWEAKS: + + this.currentState = this.EDIT_WALK_TWEAKS; + this.editing = true; + motion.lastWalkStartTime = new Date().getTime(); + motion.curAnim = motion.selWalk; + walkInterface.updateMenu(); + return; + + case this.EDIT_WALK_JOINTS: + + this.currentState = this.EDIT_WALK_JOINTS; + this.editing = true; + motion.lastWalkStartTime = new Date().getTime(); + motion.curAnim = motion.selWalk; + walkInterface.updateMenu(); + return; + + case this.EDIT_STANDING: + + this.currentState = this.EDIT_STANDING; + this.editing = true; + motion.lastWalkStartTime = 0; + motion.curAnim = motion.selStand; + walkInterface.updateMenu(); + return; + + case this.EDIT_SIDESTEP_LEFT: + + this.currentState = this.EDIT_SIDESTEP_LEFT; + this.editing = true; + motion.lastWalkStartTime = new Date().getTime(); + motion.curAnim = motion.selSideStepLeft; + walkInterface.updateMenu(); + return; + + case this.EDIT_SIDESTEP_RIGHT: + + this.currentState = this.EDIT_SIDESTEP_RIGHT; + this.editing = true; + motion.lastWalkStartTime = new Date().getTime(); + motion.curAnim = motion.selSideStepRight; + walkInterface.updateMenu(); + return; + + case this.EDIT_FLYING: + + this.currentState = this.EDIT_FLYING; + this.editing = true; + motion.lastWalkStartTime = 0; + motion.curAnim = motion.selFly; + walkInterface.updateMenu(); + return; + + case this.EDIT_FLYING_UP: + + this.currentState = this.EDIT_FLYING_UP; + this.editing = true; + motion.lastWalkStartTime = 0; + motion.curAnim = motion.selFlyUp; + walkInterface.updateMenu(); + return; + + case this.EDIT_FLYING_DOWN: + + this.currentState = this.EDIT_FLYING_DOWN; + this.editing = true; + motion.lastWalkStartTime = 0; + motion.curAnim = motion.selFlyDown; + walkInterface.updateMenu(); + return; + + case this.STANDING: + default: + + this.currentState = this.STANDING; + this.editing = false; + motion.lastWalkStartTime = 0; + motion.curAnim = motion.selStand; + walkInterface.updateMenu(); + + // initialisation - runs at script startup only + if (motion.strideLength === 0) { + + motion.setGender(MALE); + if (motion.direction === BACKWARDS) + motion.strideLength = motion.selWalk.calibration.strideLengthBackwards; + else + motion.strideLength = motion.selWalk.calibration.strideLengthForwards; + } + return; + } + } + } +})(); // end state object literal + +// constructor for animation Transition +Transition = function(lastAnimation, nextAnimation, reachPoses, transitionDuration, easingLower, easingUpper) { + + this.lastAnim = lastAnimation; // name of last animation + if (lastAnimation === motion.selWalk || + nextAnimation === motion.selSideStepLeft || + nextAnimation === motion.selSideStepRight) + this.walkingAtStart = true; // boolean - is the last animation a walking animation? + else + this.walkingAtStart = false; // boolean - is the last animation a walking animation? + this.nextAnimation = nextAnimation; // name of next animation + if (nextAnimation === motion.selWalk || + nextAnimation === motion.selSideStepLeft || + nextAnimation === motion.selSideStepRight) + this.walkingAtEnd = true; // boolean - is the next animation a walking animation? + else + this.walkingAtEnd = false; // boolean - is the next animation a walking animation? + this.reachPoses = reachPoses; // placeholder / stub: array of reach poses for squash and stretch techniques + this.transitionDuration = transitionDuration; // length of transition (seconds) + this.easingLower = easingLower; // Bezier curve handle (normalised) + this.easingUpper = easingUpper; // Bezier curve handle (normalised) + this.startTime = new Date().getTime(); // Starting timestamp (seconds) + this.progress = 0; // how far are we through the transition? + this.walkWheelIncrement = 6; // how much to turn the walkwheel each frame when transitioning to / from walking + this.walkWheelAdvance = 0; // how many degrees the walk wheel has been advanced during the transition + this.walkStopAngle = 0; // what angle should we stop the walk cycle? + +}; // end Transition constructor + + +walkAssets = (function () { + + // path to the sounds used for the footsteps + var _pathToSounds = 'https://s3.amazonaws.com/hifi-public/sounds/Footsteps/'; + + // read in the sounds + var _footsteps = []; + _footsteps.push(new Sound(_pathToSounds+"FootstepW2Left-12db.wav")); + _footsteps.push(new Sound(_pathToSounds+"FootstepW2Right-12db.wav")); + _footsteps.push(new Sound(_pathToSounds+"FootstepW3Left-12db.wav")); + _footsteps.push(new Sound(_pathToSounds+"FootstepW3Right-12db.wav")); + _footsteps.push(new Sound(_pathToSounds+"FootstepW5Left-12db.wav")); + _footsteps.push(new Sound(_pathToSounds+"FootstepW5Right-12db.wav")); + + // load the animation datafiles + Script.include(pathToAssets+"animations/dd-female-standard-walk-animation.js"); + Script.include(pathToAssets+"animations/dd-female-flying-up-animation.js"); + Script.include(pathToAssets+"animations/dd-female-flying-animation.js"); + Script.include(pathToAssets+"animations/dd-female-flying-down-animation.js"); + Script.include(pathToAssets+"animations/dd-female-standing-one-animation.js"); + Script.include(pathToAssets+"animations/dd-female-sidestep-left-animation.js"); + Script.include(pathToAssets+"animations/dd-female-sidestep-right-animation.js"); + Script.include(pathToAssets+"animations/dd-male-standard-walk-animation.js"); + Script.include(pathToAssets+"animations/dd-male-flying-up-animation.js"); + Script.include(pathToAssets+"animations/dd-male-flying-animation.js"); + Script.include(pathToAssets+"animations/dd-male-flying-down-animation.js"); + Script.include(pathToAssets+"animations/dd-male-standing-one-animation.js"); + Script.include(pathToAssets+"animations/dd-male-sidestep-left-animation.js"); + Script.include(pathToAssets+"animations/dd-male-sidestep-right-animation.js"); + + // read in the animation files + var _FemaleStandardWalkFile = new FemaleStandardWalk(); + var _femaleStandardWalk = _FemaleStandardWalkFile.loadAnimation(); + var _FemaleFlyingUpFile = new FemaleFlyingUp(); + var _femaleFlyingUp = _FemaleFlyingUpFile.loadAnimation(); + var _FemaleFlyingFile = new FemaleFlying(); + var _femaleFlying = _FemaleFlyingFile.loadAnimation(); + var _FemaleFlyingDownFile = new FemaleFlyingDown(); + var _femaleFlyingDown = _FemaleFlyingDownFile.loadAnimation(); + var _FemaleStandOneFile = new FemaleStandingOne(); + var _femaleStandOne = _FemaleStandOneFile.loadAnimation(); + var _FemaleSideStepLeftFile = new FemaleSideStepLeft(); + var _femaleSideStepLeft = _FemaleSideStepLeftFile.loadAnimation(); + var _FemaleSideStepRightFile = new FemaleSideStepRight(); + var _femaleSideStepRight = _FemaleSideStepRightFile.loadAnimation(); + var _MaleStandardWalkFile = new MaleStandardWalk(filter); + var _maleStandardWalk = _MaleStandardWalkFile.loadAnimation(); + var _MaleFlyingUpFile = new MaleFlyingUp(); + var _maleFlyingUp = _MaleFlyingUpFile.loadAnimation(); + var _MaleFlyingFile = new MaleFlying(); + var _maleFlying = _MaleFlyingFile.loadAnimation(); + var _MaleFlyingDownFile = new MaleFlyingDown(); + var _maleFlyingDown = _MaleFlyingDownFile.loadAnimation(); + var _MaleStandOneFile = new MaleStandingOne(); + var _maleStandOne = _MaleStandOneFile.loadAnimation(); + var _MaleSideStepLeftFile = new MaleSideStepLeft(); + var _maleSideStepLeft = _MaleSideStepLeftFile.loadAnimation(); + var _MaleSideStepRightFile = new MaleSideStepRight(); + var _maleSideStepRight = _MaleSideStepRightFile.loadAnimation(); + + return { + + // expose the sound assets + footsteps: _footsteps, + + // expose the animation assets + femaleStandardWalk: _femaleStandardWalk, + femaleFlyingUp: _femaleFlyingUp, + femaleFlying: _femaleFlying, + femaleFlyingDown: _femaleFlyingDown, + femaleStandOne: _femaleStandOne, + femaleSideStepLeft: _femaleSideStepLeft, + femaleSideStepRight: _femaleSideStepRight, + maleStandardWalk: _maleStandardWalk, + maleFlyingUp: _maleFlyingUp, + maleFlying: _maleFlying, + maleFlyingDown: _maleFlyingDown, + maleStandOne: _maleStandOne, + maleSideStepLeft: _maleSideStepLeft, + maleSideStepRight: _maleSideStepRight, + } +})(); \ No newline at end of file diff --git a/examples/libraries/walkFilters.js b/examples/libraries/walkFilters.js new file mode 100644 index 0000000000..608618e580 --- /dev/null +++ b/examples/libraries/walkFilters.js @@ -0,0 +1,230 @@ +// +// walkFilters.js +// +// version 1.000 +// +// Created by David Wooldridge, Autumn 2014 +// +// Provides a variety of filters for use by the walk.js script v1.1 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +AveragingFilter = function(length) { + + //this.name = name; + this.pastValues = []; + + for(var i = 0; i < length; i++) { + + this.pastValues.push(0); + } + + // single arg is the nextInputValue + this.process = function() { + + if (this.pastValues.length === 0 && arguments[0]) { + return arguments[0]; + } + else if (arguments[0]) { + + // apply quick and simple LP filtering + this.pastValues.push(arguments[0]); + this.pastValues.shift(); + var nextOutputValue = 0; + for (var ea in this.pastValues) nextOutputValue += this.pastValues[ea]; + return nextOutputValue / this.pastValues.length; + } + else return 0; + }; +}; + +// 2nd order Butterworth LP filter - calculate coeffs here: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html +// provides LP filtering with a more stable frequency / phase response +ButterworthFilter = function(cutOff) { + + switch(cutOff) { + + case 5: + + this.gain = 20.20612010; + this.coeffOne = -0.4775922501; + this.coeffTwo = 1.2796324250; + break; + } + + // initialise the arrays + this.xv = []; + this.yv = []; + for(var i = 0; i < 3; i++) { + this.xv.push(0); + this.yv.push(0); + } + + // process values + this.process = function(nextInputValue) { + + this.xv[0] = this.xv[1]; + this.xv[1] = this.xv[2]; + this.xv[2] = nextInputValue / this.gain; + + this.yv[0] = this.yv[1]; + this.yv[1] = this.yv[2]; + this.yv[2] = (this.xv[0] + this.xv[2]) + + 2 * this.xv[1] + + (this.coeffOne * this.yv[0]) + + (this.coeffTwo * this.yv[1]); + + return this.yv[2]; + }; +}; // end Butterworth filter contructor + +// Add harmonics to a given sine wave to form square, sawtooth or triangle waves +// Geometric wave synthesis fundamentals taken from: http://hyperphysics.phy-astr.gsu.edu/hbase/audio/geowv.html +WaveSynth = function(waveShape, numHarmonics, smoothing) { + + this.numHarmonics = numHarmonics; + this.waveShape = waveShape; + this.averagingFilter = new AveragingFilter(smoothing); + + // NB: frequency in radians + this.shapeWave = function(frequency) { + + // make some shapes + var harmonics = 0; + var multiplier = 0; + var iterations = this.numHarmonics * 2 + 2; + if (this.waveShape === TRIANGLE) iterations++; + + for(var n = 2; n < iterations; n++) { + + switch(this.waveShape) { + + case SAWTOOTH: + + multiplier = 1 / n; + harmonics += multiplier * Math.sin(n * frequency); + break; + + case TRIANGLE: + + if (n % 2 === 1) { + + var mulitplier = 1 / (n * n); + + // multiply every (4n-1)th harmonic by -1 + if (n === 3 || n === 7 || n === 11 || n === 15) + mulitplier *= -1; + harmonics += mulitplier * Math.sin(n * frequency); + } + break; + + case SQUARE: + + if (n % 2 === 1) { + + multiplier = 1 / n; + harmonics += multiplier * Math.sin(n * frequency); + } + break; + } + } + + // smooth the result and return + return this.averagingFilter.process(harmonics); + }; +}; + +// Create a wave shape by summing pre-calcualted sinusoidal harmonics +HarmonicsFilter = function(magnitudes, phaseAngles) { + + this.magnitudes = magnitudes; + this.phaseAngles = phaseAngles; + + this.calculate = function(twoPiFT) { + + var harmonics = 0; + var numHarmonics = magnitudes.length; + + for(var n = 0; n < numHarmonics; n++) + + harmonics += this.magnitudes[n] * Math.cos(n * twoPiFT - this.phaseAngles[n]); + + return harmonics; + }; +}; + +// the main filter object literal +filter = (function() { + + // Bezier private functions + function _B1(t) { return t * t * t }; + function _B2(t) { return 3 * t * t * (1 - t) }; + function _B3(t) { return 3 * t * (1 - t) * (1 - t) }; + function _B4(t) { return (1 - t) * (1 - t) * (1 - t) }; + + return { + + // helper methods + degToRad: function(degrees) { + + var convertedValue = degrees * Math.PI / 180; + return convertedValue; + }, + + radToDeg: function(radians) { + + var convertedValue = radians * 180 / Math.PI; + return convertedValue; + }, + + // these filters need instantiating, as they hold arrays of previous values + createAveragingFilter: function(length) { + + var newAveragingFilter = new AveragingFilter(length); + return newAveragingFilter; + }, + + createButterworthFilter: function(cutoff) { + + var newButterworthFilter = new ButterworthFilter(cutoff); + return newButterworthFilter; + }, + + createWaveSynth: function(waveShape, numHarmonics, smoothing) { + + var newWaveSynth = new WaveSynth(waveShape, numHarmonics, smoothing); + return newWaveSynth; + }, + + createHarmonicsFilter: function(magnitudes, phaseAngles) { + + var newHarmonicsFilter = new HarmonicsFilter(magnitudes, phaseAngles); + return newHarmonicsFilter; + }, + + + // the following filters do not need separate instances, as they hold no previous values + bezier: function(percent, C1, C2, C3, C4) { + + // Bezier functions for more natural transitions + // based on script by Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/ + var pos = {x: 0, y: 0}; + pos.x = C1.x * _B1(percent) + C2.x * _B2(percent) + C3.x * _B3(percent) + C4.x * _B4(percent); + pos.y = C1.y * _B1(percent) + C2.y * _B2(percent) + C3.y * _B3(percent) + C4.y * _B4(percent); + return pos; + }, + + // simple clipping filter (faster way to make square waveforms) + clipTrough: function(inputValue, peak, strength) { + + var outputValue = inputValue * strength; + if (outputValue < -peak) + outputValue = -peak; + + return outputValue; + } + } + +})(); \ No newline at end of file diff --git a/examples/libraries/walkInterface.js b/examples/libraries/walkInterface.js new file mode 100644 index 0000000000..71e4462933 --- /dev/null +++ b/examples/libraries/walkInterface.js @@ -0,0 +1,2713 @@ +// +// walkInterface.js +// +// version 1.000 +// +// Created by David Wooldridge, Autumn 2014 +// +// Presents the UI for the walk.js script v1.1 +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +walkInterface = (function() { + + // controller element positions and dimensions + var _backgroundWidth = 350; + var _backgroundHeight = 700; + var _backgroundX = Window.innerWidth - _backgroundWidth - 58; + var _backgroundY = Window.innerHeight / 2 - _backgroundHeight / 2; + var _minSliderX = _backgroundX + 30; + var _sliderRangeX = 295 - 30; + var _jointsControlWidth = 200; + var _jointsControlHeight = 300; + var _jointsControlX = _backgroundX + _backgroundWidth / 2 - _jointsControlWidth / 2; + var _jointsControlY = _backgroundY + 242 - _jointsControlHeight / 2; + var _buttonsY = 20; // distance from top of panel to menu buttons + var _bigButtonsY = 408; // distance from top of panel to top of first big button + + // arrays of overlay names + var _sliderThumbOverlays = []; + var _backgroundOverlays = []; + var _buttonOverlays = []; + var _jointsControlOverlays = []; + var _bigbuttonOverlays = []; + + // reference to the internal state + var _state = { + editingTranslation: false + }; + + // reference to the Motion object + var _motion = null; + + var _walkAssets = null; + + // constants + var MAX_WALK_SPEED = 1257; + + // look and feel + var momentaryButtonTimer = null; + + // all slider controls have a range (with the exception of phase controls that are always +-180) + var _sliderRanges = { + "joints": [{ + "name": "hips", + "pitchRange": 12, + "yawRange": 18, + "rollRange": 12, + "pitchOffsetRange": 25, + "yawOffsetRange": 25, + "rollOffsetRange": 25, + "swayRange": 0.12, + "bobRange": 0.05, + "thrustRange": 0.05, + "swayOffsetRange": 0.25, + "bobOffsetRange": 0.25, + "thrustOffsetRange": 0.25 + }, { + "name": "upperLegs", + "pitchRange": 30, + "yawRange": 35, + "rollRange": 35, + "pitchOffsetRange": 20, + "yawOffsetRange": 20, + "rollOffsetRange": 20 + }, { + "name": "lowerLegs", + "pitchRange": 10, + "yawRange": 20, + "rollRange": 20, + "pitchOffsetRange": 180, + "yawOffsetRange": 20, + "rollOffsetRange": 20 + }, { + "name": "feet", + "pitchRange": 10, + "yawRange": 20, + "rollRange": 20, + "pitchOffsetRange": 180, + "yawOffsetRange": 50, + "rollOffsetRange": 50 + }, { + "name": "toes", + "pitchRange": 90, + "yawRange": 20, + "rollRange": 20, + "pitchOffsetRange": 90, + "yawOffsetRange": 20, + "rollOffsetRange": 20 + }, { + "name": "spine", + "pitchRange": 40, + "yawRange": 40, + "rollRange": 40, + "pitchOffsetRange": 90, + "yawOffsetRange": 50, + "rollOffsetRange": 50 + }, { + "name": "spine1", + "pitchRange": 20, + "yawRange": 40, + "rollRange": 20, + "pitchOffsetRange": 90, + "yawOffsetRange": 50, + "rollOffsetRange": 50 + }, { + "name": "spine2", + "pitchRange": 20, + "yawRange": 40, + "rollRange": 20, + "pitchOffsetRange": 90, + "yawOffsetRange": 50, + "rollOffsetRange": 50 + }, { + "name": "shoulders", + "pitchRange": 35, + "yawRange": 40, + "rollRange": 20, + "pitchOffsetRange": 180, + "yawOffsetRange": 180, + "rollOffsetRange": 180 + }, { + "name": "upperArms", + "pitchRange": 90, + "yawRange": 90, + "rollRange": 90, + "pitchOffsetRange": 180, + "yawOffsetRange": 180, + "rollOffsetRange": 180 + }, { + "name": "lowerArms", + "pitchRange": 90, + "yawRange": 90, + "rollRange": 120, + "pitchOffsetRange": 180, + "yawOffsetRange": 180, + "rollOffsetRange": 180 + }, { + "name": "hands", + "pitchRange": 90, + "yawRange": 180, + "rollRange": 90, + "pitchOffsetRange": 180, + "yawOffsetRange": 180, + "rollOffsetRange": 180 + }, { + "name": "head", + "pitchRange": 20, + "yawRange": 20, + "rollRange": 20, + "pitchOffsetRange": 90, + "yawOffsetRange": 90, + "rollOffsetRange": 90 + }] + }; + + // load overlay images + var _controlsMinimisedTab = Overlays.addOverlay("image", { + x: Window.innerWidth - 58, + y: Window.innerHeight - 145, + width: 50, + height: 50, + imageURL: pathToAssets + 'overlay-images/ddao-minimise-tab.png', + visible: true, + alpha: 0.9 + }); + + var _controlsBackground = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX, + y: _backgroundY, + width: _backgroundWidth, + height: _backgroundHeight + }, + imageURL: pathToAssets + "overlay-images/ddao-background.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _backgroundOverlays.push(_controlsBackground); + + var _controlsBackgroundWalkEditStyles = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX, + y: _backgroundY, + width: _backgroundWidth, + height: _backgroundHeight + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-styles.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _backgroundOverlays.push(_controlsBackgroundWalkEditStyles); + + var _controlsBackgroundWalkEditTweaks = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX, + y: _backgroundY, + width: _backgroundWidth, + height: _backgroundHeight + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-tweaks.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _backgroundOverlays.push(_controlsBackgroundWalkEditTweaks); + + var _controlsBackgroundWalkEditHipTrans = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX, + y: _backgroundY, + width: _backgroundWidth, + height: _backgroundHeight + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-translation.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _backgroundOverlays.push(_controlsBackgroundWalkEditHipTrans); + + var _controlsBackgroundWalkEditJoints = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX, + y: _backgroundY, + width: _backgroundWidth, + height: _backgroundHeight + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-joints.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _backgroundOverlays.push(_controlsBackgroundWalkEditJoints); + + // load character joint selection control images + var _hipsJointsTranslation = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-hips-translation.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_hipsJointsTranslation); + + var _hipsJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-hips.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_hipsJointControl); + + var _upperLegsJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-upper-legs.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_upperLegsJointControl); + + var _lowerLegsJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-lower-legs.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_lowerLegsJointControl); + + var _feetJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-feet.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_feetJointControl); + + var _toesJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-toes.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_toesJointControl); + + var _spineJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-spine.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_spineJointControl); + + var _spine1JointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-spine1.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_spine1JointControl); + + var _spine2JointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-spine2.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_spine2JointControl); + + var _shouldersJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-shoulders.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_shouldersJointControl); + + var _upperArmsJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-upper-arms.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_upperArmsJointControl); + + var _forearmsJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-forearms.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_forearmsJointControl); + + var _handsJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-hands.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_handsJointControl); + + var _headJointControl = Overlays.addOverlay("image", { + bounds: { + x: _jointsControlX, + y: _jointsControlY, + width: 200, + height: 300 + }, + imageURL: pathToAssets + "overlay-images/ddao-background-edit-head.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _jointsControlOverlays.push(_headJointControl); + + + // slider thumb overlays + var _sliderOne = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderOne); + + var _sliderTwo = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderTwo); + + var _sliderThree = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderThree); + + var _sliderFour = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderFour); + + var _sliderFive = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderFive); + + var _sliderSix = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderSix); + + var _sliderSeven = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderSeven); + + var _sliderEight = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderEight); + + var _sliderNine = Overlays.addOverlay("image", { + bounds: { + x: 0, + y: 0, + width: 25, + height: 25 + }, + imageURL: pathToAssets + "overlay-images/ddao-slider-handle.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _sliderThumbOverlays.push(_sliderNine); + + + // button overlays + var _onButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 20, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-on-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_onButton); + + var _offButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 20, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-off-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_offButton); + + var _configWalkButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-walk-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkButton); + + var _configWalkButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-walk-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkButtonSelected); + + var _configStandButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 146, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-stand-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configStandButton); + + var _configStandButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 146, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-stand-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configStandButtonSelected); + + var _configFlyingButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 209, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-fly-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configFlyingButton); + + var _configFlyingButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 209, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-fly-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configFlyingButtonSelected); + + var _configFlyingUpButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-fly-up-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configFlyingUpButton); + + var _configFlyingUpButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-fly-up-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configFlyingUpButtonSelected); + + var _configFlyingDownButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 146, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-fly-down-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configFlyingDownButton); + + var _configFlyingDownButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 146, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-fly-down-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configFlyingDownButtonSelected); + + var _hideButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 272, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-hide-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_hideButton); + + var _hideButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 272, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-hide-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_hideButtonSelected); + + var _configWalkStylesButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-walk-styles-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkStylesButton); + + var _configWalkStylesButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-walk-styles-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkStylesButtonSelected); + + var _configWalkTweaksButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 146, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-walk-tweaks-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkTweaksButton); + + var _configWalkTweaksButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 146, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-walk-tweaks-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkTweaksButtonSelected); + + var _configSideStepLeftButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-left-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configSideStepLeftButton); + + var _configSideStepLeftButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 83, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-left-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configSideStepLeftButtonSelected); + + var _configSideStepRightButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 209, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-right-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configSideStepRightButton); + + var _configSideStepRightButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 209, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-edit-sidestep-right-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configSideStepRightButtonSelected); + + var _configWalkJointsButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 209, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-joints-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkJointsButton); + + var _configWalkJointsButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 209, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-joints-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_configWalkJointsButtonSelected); + + var _backButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 272, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-back-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_backButton); + + var _backButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + 272, + y: _backgroundY + _buttonsY, + width: 60, + height: 47 + }, + imageURL: pathToAssets + "overlay-images/ddao-back-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _buttonOverlays.push(_backButtonSelected); + + // big button overlays - front panel + var _femaleBigButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-female-big-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_femaleBigButton); + + var _femaleBigButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-female-big-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_femaleBigButtonSelected); + + var _maleBigButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 60, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-male-big-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_maleBigButton); + + var _maleBigButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 60, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-male-big-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_maleBigButtonSelected); + + var _armsFreeBigButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 120, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-arms-free-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_armsFreeBigButton); + + var _armsFreeBigButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 120, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-arms-free-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_armsFreeBigButtonSelected); + + var _footstepsBigButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 180, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-footsteps-big-button.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_footstepsBigButton); + + var _footstepsBigButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 180, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-footsteps-big-button-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_footstepsBigButtonSelected); + + + // walk styles + _bigButtonsY = 121; + var _standardWalkBigButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-walk-select-button-standard.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_standardWalkBigButton); + + var _standardWalkBigButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, + height: 36 + }, + imageURL: pathToAssets + "overlay-images/ddao-walk-select-button-standard-selected.png", + color: { + red: 255, + green: 255, + blue: 255 + }, + alpha: 1, + visible: false + }); + _bigbuttonOverlays.push(_standardWalkBigButtonSelected); + + // various show / hide GUI element functions + function minimiseDialog(minimise) { + + if (momentaryButtonTimer) { + Script.clearInterval(momentaryButtonTimer); + momentaryButtonTimer = null; + } + + if (minimise) { + setBackground(); + hideMenuButtons(); + setSliderThumbsVisible(false); + hideJointSelectors(); + initialiseFrontPanel(false); + Overlays.editOverlay(_controlsMinimisedTab, { + visible: true + }); + } else { + Overlays.editOverlay(_controlsMinimisedTab, { + visible: false + }); + } + }; + + function setBackground(backgroundID) { + for (var i in _backgroundOverlays) { + if (_backgroundOverlays[i] === backgroundID) + Overlays.editOverlay(_backgroundOverlays[i], { + visible: true + }); + else Overlays.editOverlay(_backgroundOverlays[i], { + visible: false + }); + } + }; + + // top row menu type buttons (on | walk | stand | fly | hide) + function hideMenuButtons() { + for (var i in _buttonOverlays) { + Overlays.editOverlay(_buttonOverlays[i], { + visible: false + }); + } + }; + + function hideJointSelectors() { + for (var i in _jointsControlOverlays) { + Overlays.editOverlay(_jointsControlOverlays[i], { + visible: false + }); + } + }; + + function setSliderThumbsVisible(thumbsVisible) { + for (var i = 0; i < _sliderThumbOverlays.length; i++) { + Overlays.editOverlay(_sliderThumbOverlays[i], { + visible: thumbsVisible + }); + } + }; + + function setButtonOverlayVisible(buttonOverlayName) { + for (var i in _buttonOverlays) { + if (_buttonOverlays[i] === buttonOverlayName) { + Overlays.editOverlay(buttonOverlayName, { + visible: true + }); + } + } + }; + + function initialiseFrontPanel(showButtons) { + + if (_motion.avatarGender === FEMALE) { + Overlays.editOverlay(_femaleBigButtonSelected, { + visible: showButtons + }); + Overlays.editOverlay(_femaleBigButton, { + visible: false + }); + Overlays.editOverlay(_maleBigButtonSelected, { + visible: false + }); + Overlays.editOverlay(_maleBigButton, { + visible: showButtons + }); + + } else { + + Overlays.editOverlay(_femaleBigButtonSelected, { + visible: false + }); + Overlays.editOverlay(_femaleBigButton, { + visible: showButtons + }); + Overlays.editOverlay(_maleBigButtonSelected, { + visible: showButtons + }); + Overlays.editOverlay(_maleBigButton, { + visible: false + }); + } + if (_motion.armsFree) { + Overlays.editOverlay(_armsFreeBigButtonSelected, { + visible: showButtons + }); + Overlays.editOverlay(_armsFreeBigButton, { + visible: false + }); + + } else { + + Overlays.editOverlay(_armsFreeBigButtonSelected, { + visible: false + }); + Overlays.editOverlay(_armsFreeBigButton, { + visible: showButtons + }); + } + if (_motion.makesFootStepSounds) { + Overlays.editOverlay(_footstepsBigButtonSelected, { + visible: showButtons + }); + Overlays.editOverlay(_footstepsBigButton, { + visible: false + }); + + } else { + + Overlays.editOverlay(_footstepsBigButtonSelected, { + visible: false + }); + Overlays.editOverlay(_footstepsBigButton, { + visible: showButtons + }); + } + }; + + function initialiseWalkStylesPanel(showButtons) { + + // set all big buttons to hidden, but skip the first 8, as are used by the front panel + for (var i = 8; i < _bigbuttonOverlays.length; i++) { + Overlays.editOverlay(_bigbuttonOverlays[i], { + visible: false + }); + } + + if (!showButtons) return; + + // set all the non-selected ones to showing + for (var i = 8; i < _bigbuttonOverlays.length; i += 2) { + Overlays.editOverlay(_bigbuttonOverlays[i], { + visible: true + }); + } + + // set the currently selected one + if (_motion.selWalk === _walkAssets.femaleStandardWalk || + _motion.selWalk === _walkAssets.maleStandardWalk) { + + Overlays.editOverlay(_standardWalkBigButtonSelected, { + visible: true + }); + Overlays.editOverlay(_standardWalkBigButton, { + visible: false + }); + } + }; + + function initialiseWalkTweaksPanel() { + + // sliders for commonly required walk adjustments + var i = 0; + var yLocation = _backgroundY + 71; + + // walk speed + var sliderXPos = _motion.curAnim.calibration.frequency / MAX_WALK_SPEED * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // lean (hips pitch offset) + sliderXPos = (((_sliderRanges.joints[0].pitchOffsetRange + _motion.curAnim.joints[0].pitchOffset) / 2) / + _sliderRanges.joints[0].pitchOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // stride (upper legs pitch) + sliderXPos = _motion.curAnim.joints[1].pitch / _sliderRanges.joints[1].pitchRange * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // Legs separation (upper legs roll offset) + sliderXPos = (((_sliderRanges.joints[1].rollOffsetRange + _motion.curAnim.joints[1].rollOffset) / 2) / + _sliderRanges.joints[1].rollOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // Legs forward (upper legs pitch offset) + sliderXPos = (((_sliderRanges.joints[1].pitchOffsetRange + _motion.curAnim.joints[1].pitchOffset) / 2) / + _sliderRanges.joints[1].pitchOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // Lower legs splay (lower legs roll offset) + sliderXPos = (((_sliderRanges.joints[2].rollOffsetRange + _motion.curAnim.joints[2].rollOffset) / 2) / + _sliderRanges.joints[2].rollOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // Arms forward (upper arms yaw offset) + sliderXPos = (((_sliderRanges.joints[9].yawOffsetRange + _motion.curAnim.joints[9].yawOffset) / 2) / + _sliderRanges.joints[9].yawOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // Arms out (upper arm pitch offset) + sliderXPos = (((_sliderRanges.joints[9].pitchOffsetRange - _motion.curAnim.joints[9].pitchOffset) / 2) / + _sliderRanges.joints[9].pitchOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + + // Lower arms splay (lower arm pitch offset) + sliderXPos = (((_sliderRanges.joints[10].pitchOffsetRange - _motion.curAnim.joints[10].pitchOffset) / 2) / + _sliderRanges.joints[10].pitchOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 60, + visible: true + }); + }; + + function initialiseJointsEditingPanel() { + + var i = 0; + var yLocation = _backgroundY + 359; + hideJointSelectors(); + + if (_state.editingTranslation) { + + // display the joint control selector for hips translations + Overlays.editOverlay(_hipsJointsTranslation, {visible: true}); + + // Hips sway + var sliderXPos = _motion.curAnim.joints[0].sway / _sliderRanges.joints[0].swayRange * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // Hips bob + sliderXPos = _motion.curAnim.joints[0].bob / _sliderRanges.joints[0].bobRange * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // Hips thrust + sliderXPos = _motion.curAnim.joints[0].thrust / _sliderRanges.joints[0].thrustRange * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // Sway Phase + sliderXPos = (90 + _motion.curAnim.joints[0].swayPhase / 2) / 180 * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // Bob Phase + sliderXPos = (90 + _motion.curAnim.joints[0].bobPhase / 2) / 180 * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // Thrust Phase + sliderXPos = (90 + _motion.curAnim.joints[0].thrustPhase / 2) / 180 * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // offset ranges are also -ve thr' zero to +ve, so we centre them + sliderXPos = (((_sliderRanges.joints[0].swayOffsetRange + _motion.curAnim.joints[0] + .swayOffset) / 2) / _sliderRanges.joints[0].swayOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = (((_sliderRanges.joints[0].bobOffsetRange + _motion.curAnim.joints[0] + .bobOffset) / 2) / _sliderRanges.joints[0].bobOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = (((_sliderRanges.joints[0].thrustOffsetRange + _motion.curAnim.joints[0] + .thrustOffset) / 2) / _sliderRanges.joints[0].thrustOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + } else { + + switch (_motion.curJointIndex) { + + case 0: + Overlays.editOverlay(_hipsJointControl, { + visible: true + }); + break; + case 1: + Overlays.editOverlay(_upperLegsJointControl, { + visible: true + }); + break; + case 2: + Overlays.editOverlay(_lowerLegsJointControl, { + visible: true + }); + break; + case 3: + Overlays.editOverlay(_feetJointControl, { + visible: true + }); + break; + case 4: + Overlays.editOverlay(_toesJointControl, { + visible: true + }); + break; + case 5: + Overlays.editOverlay(_spineJointControl, { + visible: true + }); + break; + case 6: + Overlays.editOverlay(_spine1JointControl, { + visible: true + }); + break; + case 7: + Overlays.editOverlay(_spine2JointControl, { + visible: true + }); + break; + case 8: + Overlays.editOverlay(_shouldersJointControl, { + visible: true + }); + break; + case 9: + Overlays.editOverlay(_upperArmsJointControl, { + visible: true + }); + break; + case 10: + Overlays.editOverlay(_forearmsJointControl, { + visible: true + }); + break; + case 11: + Overlays.editOverlay(_handsJointControl, { + visible: true + }); + break; + case 12: + Overlays.editOverlay(_headJointControl, { + visible: true + }); + break; + } + + var sliderXPos = _motion.curAnim.joints[_motion.curJointIndex].pitch / + _sliderRanges.joints[_motion.curJointIndex].pitchRange * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = _motion.curAnim.joints[_motion.curJointIndex].yaw / + _sliderRanges.joints[_motion.curJointIndex].yawRange * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = _motion.curAnim.joints[_motion.curJointIndex].roll / + _sliderRanges.joints[_motion.curJointIndex].rollRange * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // set phases (full range, -180 to 180) + sliderXPos = (90 + _motion.curAnim.joints[_motion.curJointIndex].pitchPhase / 2) / 180 * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = (90 + _motion.curAnim.joints[_motion.curJointIndex].yawPhase / 2) / 180 * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = (90 + _motion.curAnim.joints[_motion.curJointIndex].rollPhase / 2) / 180 * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + // offset ranges are also -ve thr' zero to +ve, so we offset + sliderXPos = (((_sliderRanges.joints[_motion.curJointIndex].pitchOffsetRange + + _motion.curAnim.joints[_motion.curJointIndex].pitchOffset) / 2) / + _sliderRanges.joints[_motion.curJointIndex].pitchOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = (((_sliderRanges.joints[_motion.curJointIndex].yawOffsetRange + + _motion.curAnim.joints[_motion.curJointIndex].yawOffset) / 2) / + _sliderRanges.joints[_motion.curJointIndex].yawOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + + sliderXPos = (((_sliderRanges.joints[_motion.curJointIndex].rollOffsetRange + + _motion.curAnim.joints[_motion.curJointIndex].rollOffset) / 2) / + _sliderRanges.joints[_motion.curJointIndex].rollOffsetRange) * _sliderRangeX; + Overlays.editOverlay(_sliderThumbOverlays[++i], { + x: _minSliderX + sliderXPos, + y: yLocation += 30, + visible: true + }); + } + }; + + // mouse event handlers + var _movingSliderOne = false; + var _movingSliderTwo = false; + var _movingSliderThree = false; + var _movingSliderFour = false; + var _movingSliderFive = false; + var _movingSliderSix = false; + var _movingSliderSeven = false; + var _movingSliderEight = false; + var _movingSliderNine = false; + + function mousePressEvent(event) { + + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + + if (_state.currentState === _state.EDIT_WALK_JOINTS || + _state.currentState === _state.EDIT_STANDING || + _state.currentState === _state.EDIT_FLYING || + _state.currentState === _state.EDIT_FLYING_UP || + _state.currentState === _state.EDIT_FLYING_DOWN || + _state.currentState === _state.EDIT_SIDESTEP_LEFT || + _state.currentState === _state.EDIT_SIDESTEP_RIGHT) { + + // check for new joint selection and update display accordingly + var clickX = event.x - _backgroundX - 75; + var clickY = event.y - _backgroundY - 92; + + if (clickX > 60 && clickX < 120 && clickY > 123 && clickY < 155) { + _motion.curJointIndex = 0; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 63 && clickX < 132 && clickY > 156 && clickY < 202) { + _motion.curJointIndex = 1; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 58 && clickX < 137 && clickY > 203 && clickY < 250) { + _motion.curJointIndex = 2; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 58 && clickX < 137 && clickY > 250 && clickY < 265) { + _motion.curJointIndex = 3; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 58 && clickX < 137 && clickY > 265 && clickY < 280) { + _motion.curJointIndex = 4; + initialiseJointsEditingPanel(); + return; + } else if (clickX > 78 && clickX < 121 && clickY > 111 && clickY < 128) { + _motion.curJointIndex = 5; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 78 && clickX < 128 && clickY > 89 && clickY < 111) { + _motion.curJointIndex = 6; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 85 && clickX < 118 && clickY > 77 && clickY < 94) { + _motion.curJointIndex = 7; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 64 && clickX < 125 && clickY > 55 && clickY < 77) { + _motion.curJointIndex = 8; + initialiseJointsEditingPanel(); + return; + + } else if ((clickX > 44 && clickX < 73 && clickY > 71 && clickY < 94) || + (clickX > 125 && clickX < 144 && clickY > 71 && clickY < 94)) { + _motion.curJointIndex = 9; + initialiseJointsEditingPanel(); + return; + + } else if ((clickX > 28 && clickX < 57 && clickY > 94 && clickY < 119) || + (clickX > 137 && clickX < 170 && clickY > 97 && clickY < 114)) { + _motion.curJointIndex = 10; + initialiseJointsEditingPanel(); + return; + + } else if ((clickX > 18 && clickX < 37 && clickY > 115 && clickY < 136) || + (clickX > 157 && clickX < 182 && clickY > 115 && clickY < 136)) { + _motion.curJointIndex = 11; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 81 && clickX < 116 && clickY > 12 && clickY < 53) { + _motion.curJointIndex = 12; + initialiseJointsEditingPanel(); + return; + + } else if (clickX > 188 && clickX < 233 && clickY > 6 && clickY < 34) { + + // translation editing radio selection + if (_state.editingTranslation) { + + hideJointSelectors(); + setBackground(_controlsBackgroundWalkEditJoints); + _state.editingTranslation = false; + + } else { + + hideJointSelectors(); + setBackground(_controlsBackgroundWalkEditHipTrans); + _state.editingTranslation = true; + } + initialiseJointsEditingPanel(); + return; + } + } + + switch (clickedOverlay) { + + case _offButton: + + _state.powerOn = true; + Overlays.editOverlay(_offButton, { + visible: false + }); + Overlays.editOverlay(_onButton, { + visible: true + }); + _state.setInternalState(state.STANDING); + return; + + case _controlsMinimisedTab: + + _state.minimised = false; + minimiseDialog(_state.minimised); + _state.setInternalState(_state.STANDING); + return; + + case _hideButton: + _hideButtonSelected: + + Overlays.editOverlay(_hideButton, { + visible: false + }); + Overlays.editOverlay(_hideButtonSelected, { + visible: true + }); + _state.minimised = true; + momentaryButtonTimer = Script.setInterval(function() { + minimiseDialog(_state.minimised); + }, 80); + return; + + case _backButton: + + Overlays.editOverlay(_backButton, { + visible: false + }); + Overlays.editOverlay(_backButtonSelected, { + visible: true + }); + momentaryButtonTimer = Script.setInterval(function() { + + _state.setInternalState(_state.STANDING); + Overlays.editOverlay(_backButton, { + visible: false + }); + Overlays.editOverlay(_backButtonSelected, { + visible: false + }); + Script.clearInterval(momentaryButtonTimer); + momentaryButtonTimer = null; + }, 80); + return; + + case _footstepsBigButton: + + _motion.makesFootStepSounds = true; + Overlays.editOverlay(_footstepsBigButtonSelected, { + visible: true + }); + Overlays.editOverlay(_footstepsBigButton, { + visible: false + }); + return; + + case _footstepsBigButtonSelected: + + _motion.makesFootStepSounds = false; + Overlays.editOverlay(_footstepsBigButton, { + visible: true + }); + Overlays.editOverlay(_footstepsBigButtonSelected, { + visible: false + }); + return; + + case _femaleBigButton: + case _maleBigButtonSelected: + + _motion.setGender(FEMALE); + + Overlays.editOverlay(_femaleBigButtonSelected, { + visible: true + }); + Overlays.editOverlay(_femaleBigButton, { + visible: false + }); + Overlays.editOverlay(_maleBigButton, { + visible: true + }); + Overlays.editOverlay(_maleBigButtonSelected, { + visible: false + }); + return; + + case _maleBigButton: + case _femaleBigButtonSelected: + + _motion.setGender(MALE); + + Overlays.editOverlay(_femaleBigButton, { + visible: true + }); + Overlays.editOverlay(_femaleBigButtonSelected, { + visible: false + }); + Overlays.editOverlay(_maleBigButtonSelected, { + visible: true + }); + Overlays.editOverlay(_maleBigButton, { + visible: false + }); + return; + + case _armsFreeBigButton: + + _motion.armsFree = true; + + Overlays.editOverlay(_armsFreeBigButtonSelected, { + visible: true + }); + Overlays.editOverlay(_armsFreeBigButton, { + visible: false + }); + return; + + case _armsFreeBigButtonSelected: + + _motion.armsFree = false; + + Overlays.editOverlay(_armsFreeBigButtonSelected, { + visible: false + }); + Overlays.editOverlay(_armsFreeBigButton, { + visible: true + }); + return; + + case _standardWalkBigButton: + + if (_motion.avatarGender === FEMALE) _motion.selWalk = _motion.femaleStandardWalk; + else _motion.selWalk = _motion.maleStandardWalk; + _motion.curAnim = _motion.selWalk; + initialiseWalkStylesPanel(true); + return; + + case _standardWalkBigButtonSelected: + + // toggle forwards / backwards walk display + if (_motion.direction === FORWARDS) { + _motion.direction = BACKWARDS; + } else _motion.direction = FORWARDS; + return; + + case _sliderOne: + + _movingSliderOne = true; + return; + + case _sliderTwo: + + _movingSliderTwo = true; + return; + + case _sliderThree: + + _movingSliderThree = true; + return; + + case _sliderFour: + + _movingSliderFour = true; + return; + + case _sliderFive: + + _movingSliderFive = true; + return; + + case _sliderSix: + + _movingSliderSix = true; + return; + + case _sliderSeven: + + _movingSliderSeven = true; + return; + + case _sliderEight: + + _movingSliderEight = true; + return; + + case _sliderNine: + + _movingSliderNine = true; + return; + + case _configWalkButtonSelected: + case _configStandButtonSelected: + case _configSideStepLeftButtonSelected: + case _configSideStepRightButtonSelected: + case _configFlyingButtonSelected: + case _configFlyingUpButtonSelected: + case _configFlyingDownButtonSelected: + case _configWalkStylesButtonSelected: + case _configWalkTweaksButtonSelected: + case _configWalkJointsButtonSelected: + + // exit edit modes + _motion.curAnim = _motion.selStand; + _state.setInternalState(_state.STANDING); + break; + + case _onButton: + + _state.powerOn = false; + _state.setInternalState(state.STANDING); + Overlays.editOverlay(_offButton, { + visible: true + }); + Overlays.editOverlay(_onButton, { + visible: false + }); + //resetJoints(); + break; + + case _backButton: + case _backButtonSelected: + + Overlays.editOverlay(_backButton, { + visible: false + }); + Overlays.editOverlay(_backButtonSelected, { + visible: false + }); + _state.setInternalState(_state.STANDING); + break; + + case _configWalkStylesButton: + + _state.setInternalState(_state.EDIT_WALK_STYLES); + break; + + case _configWalkTweaksButton: + + _state.setInternalState(_state.EDIT_WALK_TWEAKS); + break; + + case _configWalkJointsButton: + + _state.setInternalState(_state.EDIT_WALK_JOINTS); + break; + + case _configWalkButton: + + _state.setInternalState(_state.EDIT_WALK_STYLES); + break; + + case _configStandButton: + + _state.setInternalState(_state.EDIT_STANDING); + break; + + case _configSideStepLeftButton: + _state.setInternalState(_state.EDIT_SIDESTEP_LEFT); + + break; + + case _configSideStepRightButton: + + _state.setInternalState(_state.EDIT_SIDESTEP_RIGHT); + break; + + case _configFlyingButton: + + _state.setInternalState(_state.EDIT_FLYING); + break; + + case _configFlyingUpButton: + + _state.setInternalState(_state.EDIT_FLYING_UP); + break; + + case _configFlyingDownButton: + + _state.setInternalState(_state.EDIT_FLYING_DOWN); + break; + } + }; + + function mouseMoveEvent(event) { + + // workaround for bug (https://worklist.net/20160) + if ((event.x > 310 && event.x < 318 && event.y > 1350 && event.y < 1355) || + (event.x > 423 && event.x < 428 && event.y > 1505 && event.y < 1508 )) return; + + if (_state.currentState === _state.EDIT_WALK_JOINTS || + _state.currentState === _state.EDIT_STANDING || + _state.currentState === _state.EDIT_FLYING || + _state.currentState === _state.EDIT_FLYING_UP || + _state.currentState === _state.EDIT_FLYING_DOWN || + _state.currentState === _state.EDIT_SIDESTEP_LEFT || + _state.currentState === _state.EDIT_SIDESTEP_RIGHT) { + + var thumbClickOffsetX = event.x - _minSliderX; + var thumbPositionNormalised = thumbClickOffsetX / _sliderRangeX; + if (thumbPositionNormalised < 0) thumbPositionNormalised = 0; + if (thumbPositionNormalised > 1) thumbPositionNormalised = 1; + var sliderX = thumbPositionNormalised * _sliderRangeX; // sets range + + if (_movingSliderOne) { + + // currently selected joint pitch or sway + Overlays.editOverlay(_sliderOne, { + x: sliderX + _minSliderX + }); + if (_state.editingTranslation) { + + _motion.curAnim.joints[0].sway = + thumbPositionNormalised * _sliderRanges.joints[0].swayRange; + + } else { + + _motion.curAnim.joints[_motion.curJointIndex].pitch = + thumbPositionNormalised * _sliderRanges.joints[_motion.curJointIndex].pitchRange; + } + + } else if (_movingSliderTwo) { + + // currently selected joint yaw or bob + Overlays.editOverlay(_sliderTwo, { + x: sliderX + _minSliderX + }); + if (_state.editingTranslation) { + + _motion.curAnim.joints[0].bob = + thumbPositionNormalised * _sliderRanges.joints[0].bobRange; + + } else { + + _motion.curAnim.joints[_motion.curJointIndex].yaw = + thumbPositionNormalised * _sliderRanges.joints[_motion.curJointIndex].yawRange; + } + + } else if (_movingSliderThree) { + + // currently selected joint roll or thrust + Overlays.editOverlay(_sliderThree, { + x: sliderX + _minSliderX + }); + if (_state.editingTranslation) { + + _motion.curAnim.joints[0].thrust = + thumbPositionNormalised * _sliderRanges.joints[0].thrustRange; + + } else { + + _motion.curAnim.joints[_motion.curJointIndex].roll = + thumbPositionNormalised * _sliderRanges.joints[_motion.curJointIndex].rollRange; + } + + } else if (_movingSliderFour) { + + // currently selected joint pitch phase + Overlays.editOverlay(_sliderFour, { + x: sliderX + _minSliderX + }); + + var newPhase = 360 * thumbPositionNormalised - 180; + + if (_state.editingTranslation) { + + _motion.curAnim.joints[0].swayPhase = newPhase; + + } else { + + _motion.curAnim.joints[_motion.curJointIndex].pitchPhase = newPhase; + } + + } else if (_movingSliderFive) { + + // currently selected joint yaw phase; + Overlays.editOverlay(_sliderFive, { + x: sliderX + _minSliderX + }); + + var newPhase = 360 * thumbPositionNormalised - 180; + + if (_state.editingTranslation) { + + _motion.curAnim.joints[0].bobPhase = newPhase; + + } else { + + _motion.curAnim.joints[_motion.curJointIndex].yawPhase = newPhase; + } + + } else if (_movingSliderSix) { + + // currently selected joint roll phase + Overlays.editOverlay(_sliderSix, { + x: sliderX + _minSliderX + }); + + var newPhase = 360 * thumbPositionNormalised - 180; + + if (_state.editingTranslation) { + + _motion.curAnim.joints[0].thrustPhase = newPhase; + + } else { + + _motion.curAnim.joints[_motion.curJointIndex].rollPhase = newPhase; + } + + } else if (_movingSliderSeven) { + + // currently selected joint pitch offset + Overlays.editOverlay(_sliderSeven, { + x: sliderX + _minSliderX + }); + if (_state.editingTranslation) { + + var newOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[0].swayOffsetRange; + _motion.curAnim.joints[0].swayOffset = newOffset; + + } else { + + var newOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[_motion.curJointIndex].pitchOffsetRange; + _motion.curAnim.joints[_motion.curJointIndex].pitchOffset = newOffset; + } + + } else if (_movingSliderEight) { + + // currently selected joint yaw offset + Overlays.editOverlay(_sliderEight, { + x: sliderX + _minSliderX + }); + if (_state.editingTranslation) { + + var newOffset = (thumbPositionNormalised - 0.5) * + 2 *_sliderRanges.joints[0].bobOffsetRange; + _motion.curAnim.joints[0].bobOffset = newOffset; + + } else { + + var newOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[_motion.curJointIndex].yawOffsetRange; + _motion.curAnim.joints[_motion.curJointIndex].yawOffset = newOffset; + } + + } else if (_movingSliderNine) { + + // currently selected joint roll offset + Overlays.editOverlay(_sliderNine, { + x: sliderX + _minSliderX + }); + if (_state.editingTranslation) { + + var newOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[0].thrustOffsetRange; + _motion.curAnim.joints[0].thrustOffset = newOffset; + + } else { + + var newOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[_motion.curJointIndex].rollOffsetRange; + _motion.curAnim.joints[_motion.curJointIndex].rollOffset = newOffset; + } + } + + } // end if editing joints + else if (_state.currentState === _state.EDIT_WALK_TWEAKS) { + + // sliders for commonly required walk adjustments + var thumbClickOffsetX = event.x - _minSliderX; + var thumbPositionNormalised = thumbClickOffsetX / _sliderRangeX; + if (thumbPositionNormalised < 0) thumbPositionNormalised = 0; + if (thumbPositionNormalised > 1) thumbPositionNormalised = 1; + var sliderX = thumbPositionNormalised * _sliderRangeX; // sets range + + if (_movingSliderOne) { + + // walk speed + Overlays.editOverlay(_sliderOne, { + x: sliderX + _minSliderX + }); + _motion.curAnim.calibration.frequency = thumbPositionNormalised * MAX_WALK_SPEED; + + } else if (_movingSliderTwo) { + + // lean (hips pitch offset) + Overlays.editOverlay(_sliderTwo, { + x: sliderX + _minSliderX + }); + var newOffset = (thumbPositionNormalised - 0.5) * 2 * _sliderRanges.joints[0].pitchOffsetRange; + _motion.curAnim.joints[0].pitchOffset = newOffset; + + } else if (_movingSliderThree) { + + // stride (upper legs pitch) + Overlays.editOverlay(_sliderThree, { + x: sliderX + _minSliderX + }); + _motion.curAnim.joints[1].pitch = thumbPositionNormalised * _sliderRanges.joints[1].pitchRange; + + } else if (_movingSliderFour) { + + // legs separation (upper legs roll) + Overlays.editOverlay(_sliderFour, { + x: sliderX + _minSliderX + }); + _motion.curAnim.joints[1].rollOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[1].rollOffsetRange; + + } else if (_movingSliderFive) { + + // legs forward (lower legs pitch offset) + Overlays.editOverlay(_sliderFive, { + x: sliderX + _minSliderX + }); + _motion.curAnim.joints[1].pitchOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[1].pitchOffsetRange; + + } else if (_movingSliderSix) { + + // lower legs splay (lower legs roll offset) + Overlays.editOverlay(_sliderSix, { + x: sliderX + _minSliderX + }); + _motion.curAnim.joints[2].rollOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[2].rollOffsetRange; + + } else if (_movingSliderSeven) { + + // arms forward (upper arms yaw offset) + Overlays.editOverlay(_sliderSeven, { + x: sliderX + _minSliderX + }); + _motion.curAnim.joints[9].yawOffset = (thumbPositionNormalised - 0.5) * + 2 * _sliderRanges.joints[9].yawOffsetRange; + + } else if (_movingSliderEight) { + + // arms out (upper arm pitch offset) + Overlays.editOverlay(_sliderEight, { + x: sliderX + _minSliderX + }); + _motion.curAnim.joints[9].pitchOffset = (thumbPositionNormalised - 0.5) * + -2 * _sliderRanges.joints[9].pitchOffsetRange; + + } else if (_movingSliderNine) { + + // lower arms splay (lower arm pitch offset) + Overlays.editOverlay(_sliderNine, { + x: sliderX + _minSliderX + }); + _motion.curAnim.joints[10].pitchOffset = (thumbPositionNormalised - 0.5) * + -2 * _sliderRanges.joints[10].pitchOffsetRange; + } + + } // if tweaking + }; + + function mouseReleaseEvent(event) { + + if (_movingSliderOne) _movingSliderOne = false; + else if (_movingSliderTwo) _movingSliderTwo = false; + else if (_movingSliderThree) _movingSliderThree = false; + else if (_movingSliderFour) _movingSliderFour = false; + else if (_movingSliderFive) _movingSliderFive = false; + else if (_movingSliderSix) _movingSliderSix = false; + else if (_movingSliderSeven) _movingSliderSeven = false; + else if (_movingSliderEight) _movingSliderEight = false; + else if (_movingSliderNine) _movingSliderNine = false; + }; + + Controller.mousePressEvent.connect(mousePressEvent); + Controller.mouseMoveEvent.connect(mouseMoveEvent); + Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + + // Script ending + Script.scriptEnding.connect(function() { + + // delete the background overlays + for (var i in _backgroundOverlays) { + Overlays.deleteOverlay(_backgroundOverlays[i]); + } + // delete the button overlays + for (var i in _buttonOverlays) { + Overlays.deleteOverlay(_buttonOverlays[i]); + } + // delete the slider thumb overlays + for (var i in _sliderThumbOverlays) { + Overlays.deleteOverlay(_sliderThumbOverlays[i]); + } + // delete the character joint control overlays + for (var i in _jointsControlOverlays) { + Overlays.deleteOverlay(_jointsControlOverlays[i]); + } + // delete the big button overlays + for (var i in _bigbuttonOverlays) { + Overlays.deleteOverlay(_bigbuttonOverlays[i]); + } + // delete the mimimised tab + Overlays.deleteOverlay(_controlsMinimisedTab); + }); + + // public methods + return { + + // gather references to objects from the walk.js script + initialise: function(state, motion, walkAssets) { + + _state = state; + _motion = motion; + _walkAssets = walkAssets; + }, + + updateMenu: function() { + + if (!_state.minimised) { + + switch (_state.currentState) { + + case _state.EDIT_WALK_STYLES: + case _state.EDIT_WALK_TWEAKS: + case _state.EDIT_WALK_JOINTS: + + hideMenuButtons(); + initialiseFrontPanel(false); + hideJointSelectors(); + + if (_state.currentState === _state.EDIT_WALK_STYLES) { + + setBackground(_controlsBackgroundWalkEditStyles); + initialiseWalkStylesPanel(true); + setSliderThumbsVisible(false); + hideJointSelectors(); + setButtonOverlayVisible(_configWalkStylesButtonSelected); + setButtonOverlayVisible(_configWalkTweaksButton); + setButtonOverlayVisible(_configWalkJointsButton); + + } else if (_state.currentState === _state.EDIT_WALK_TWEAKS) { + + setBackground(_controlsBackgroundWalkEditTweaks); + initialiseWalkStylesPanel(false); + setSliderThumbsVisible(true); + hideJointSelectors(); + initialiseWalkTweaksPanel(); + setButtonOverlayVisible(_configWalkStylesButton); + setButtonOverlayVisible(_configWalkTweaksButtonSelected); + setButtonOverlayVisible(_configWalkJointsButton); + + } else if (_state.currentState === _state.EDIT_WALK_JOINTS) { + + if (_state.editingTranslation) + setBackground(_controlsBackgroundWalkEditHipTrans); + else + setBackground(_controlsBackgroundWalkEditJoints); + + initialiseWalkStylesPanel(false); + setSliderThumbsVisible(true); + setButtonOverlayVisible(_configWalkStylesButton); + setButtonOverlayVisible(_configWalkTweaksButton); + setButtonOverlayVisible(_configWalkJointsButtonSelected); + initialiseJointsEditingPanel(); + } + setButtonOverlayVisible(_onButton); + setButtonOverlayVisible(_backButton); + return; + + case _state.EDIT_STANDING: + case _state.EDIT_SIDESTEP_LEFT: + case _state.EDIT_SIDESTEP_RIGHT: + + if (_state.editingTranslation) + setBackground(_controlsBackgroundWalkEditHipTrans); + else + setBackground(_controlsBackgroundWalkEditJoints); + hideMenuButtons(); + initialiseWalkStylesPanel(false); + initialiseFrontPanel(false); + + if (_state.currentState === _state.EDIT_SIDESTEP_LEFT) { + + setButtonOverlayVisible(_configSideStepRightButton); + setButtonOverlayVisible(_configSideStepLeftButtonSelected); + setButtonOverlayVisible(_configStandButton); + + } else if (_state.currentState === _state.EDIT_SIDESTEP_RIGHT) { + + setButtonOverlayVisible(_configSideStepRightButtonSelected); + setButtonOverlayVisible(_configSideStepLeftButton); + setButtonOverlayVisible(_configStandButton); + + } else if (_state.currentState === _state.EDIT_STANDING) { + + setButtonOverlayVisible(_configSideStepRightButton); + setButtonOverlayVisible(_configSideStepLeftButton); + setButtonOverlayVisible(_configStandButtonSelected); + } + initialiseJointsEditingPanel(); + setButtonOverlayVisible(_onButton); + setButtonOverlayVisible(_backButton); + return; + + case _state.EDIT_FLYING: + case _state.EDIT_FLYING_UP: + case _state.EDIT_FLYING_DOWN: + + setBackground(_controlsBackgroundWalkEditJoints); + hideMenuButtons(); + initialiseWalkStylesPanel(false); + initialiseFrontPanel(false); + if (_state.currentState === _state.EDIT_FLYING) { + + setButtonOverlayVisible(_configFlyingUpButton); + setButtonOverlayVisible(_configFlyingDownButton); + setButtonOverlayVisible(_configFlyingButtonSelected); + + } else if (_state.currentState === _state.EDIT_FLYING_UP) { + + setButtonOverlayVisible(_configFlyingUpButtonSelected); + setButtonOverlayVisible(_configFlyingDownButton); + setButtonOverlayVisible(_configFlyingButton); + + } else if (_state.currentState === _state.EDIT_FLYING_DOWN) { + + setButtonOverlayVisible(_configFlyingUpButton); + setButtonOverlayVisible(_configFlyingDownButtonSelected); + setButtonOverlayVisible(_configFlyingButton); + } + initialiseJointsEditingPanel(); + setButtonOverlayVisible(_onButton); + setButtonOverlayVisible(_backButton); + return; + + case _state.STANDING: + case _state.WALKING: + case _state.FLYING: + case _state.SIDE_STEP: + default: + + hideMenuButtons(); + hideJointSelectors(); + setBackground(_controlsBackground); + if (_state.powerOn) setButtonOverlayVisible(_onButton); + else setButtonOverlayVisible(_offButton); + setButtonOverlayVisible(_configWalkButton); + setButtonOverlayVisible(_configStandButton); + setButtonOverlayVisible(_configFlyingButton); + setButtonOverlayVisible(_hideButton); + setSliderThumbsVisible(false); + initialiseFrontPanel(true); + initialiseWalkStylesPanel(false); + return; + } + } + } + }; // end public methods (return) + +})(); \ No newline at end of file diff --git a/examples/walk.js b/examples/walk.js index a9e8f401d6..1e1cd7748b 100644 --- a/examples/walk.js +++ b/examples/walk.js @@ -1,3851 +1,2562 @@ // // walk.js // -// version 1.007b +// version 1.1 // -// Created by Davedub, August / September 2014 +// Created by David Wooldridge, Autumn 2014 +// +// Animates an avatar using procedural animation techniques // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// path to the animation files -var pathToAnimFiles = 'http://s3-us-west-1.amazonaws.com/highfidelity-public/procedural-animator/animation-files/'; // working (but only without https) - -// path to the images used for the overlays -var pathToOverlays = 'http://s3-us-west-1.amazonaws.com/highfidelity-public/procedural-animator/overlays/'; // working (but only without https) - -// path to the sounds used for the footsteps -var pathToSounds = 'http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/Footsteps/'; - -// load the animation datafiles -Script.include(pathToAnimFiles+"dd-female-strut-walk-animation.js"); -Script.include(pathToAnimFiles+"dd-female-flying-up-animation.js"); -Script.include(pathToAnimFiles+"dd-female-flying-animation.js"); -Script.include(pathToAnimFiles+"dd-female-flying-down-animation.js"); -Script.include(pathToAnimFiles+"dd-female-standing-one-animation.js"); -Script.include(pathToAnimFiles+"dd-female-sidestep-left-animation.js"); -Script.include(pathToAnimFiles+"dd-female-sidestep-right-animation.js"); -Script.include(pathToAnimFiles+"dd-male-strut-walk-animation.js"); -Script.include(pathToAnimFiles+"dd-male-flying-up-animation.js"); -Script.include(pathToAnimFiles+"dd-male-flying-animation.js"); -Script.include(pathToAnimFiles+"dd-male-flying-down-animation.js"); -Script.include(pathToAnimFiles+"dd-male-standing-one-animation.js"); -Script.include(pathToAnimFiles+"dd-male-sidestep-left-animation.js"); -Script.include(pathToAnimFiles+"dd-male-sidestep-right-animation.js"); - -// read in the data from the animation files -var FemaleStrutWalkFile = new FemaleStrutWalk(); -var femaleStrutWalk = FemaleStrutWalkFile.loadAnimation(); -var FemaleFlyingUpFile = new FemaleFlyingUp(); -var femaleFlyingUp = FemaleFlyingUpFile.loadAnimation(); -var FemaleFlyingFile = new FemaleFlying(); -var femaleFlying = FemaleFlyingFile.loadAnimation(); -var FemaleFlyingDownFile = new FemaleFlyingDown(); -var femaleFlyingDown = FemaleFlyingDownFile.loadAnimation(); -var FemaleStandOneFile = new FemaleStandingOne(); -var femaleStandOne = FemaleStandOneFile.loadAnimation(); -var FemaleSideStepLeftFile = new FemaleSideStepLeft(); -var femaleSideStepLeft = FemaleSideStepLeftFile.loadAnimation(); -var FemaleSideStepRightFile = new FemaleSideStepRight(); -var femaleSideStepRight = FemaleSideStepRightFile.loadAnimation(); -var MaleStrutWalkFile = new MaleStrutWalk(); -var maleStrutWalk = MaleStrutWalkFile.loadAnimation(); -var MaleFlyingUpFile = new MaleFlyingUp(); -var maleFlyingUp = MaleFlyingUpFile.loadAnimation(); -var MaleFlyingFile = new MaleFlying(); -var maleFlying = MaleFlyingFile.loadAnimation(); -var MaleFlyingDownFile = new MaleFlyingDown(); -var maleFlyingDown = MaleFlyingDownFile.loadAnimation(); -var MaleStandOneFile = new MaleStandingOne(); -var maleStandOne = MaleStandOneFile.loadAnimation(); -var MaleSideStepLeftFile = new MaleSideStepLeft(); -var maleSideStepLeft = MaleSideStepLeftFile.loadAnimation(); -var MaleSideStepRightFile = new MaleSideStepRight(); -var maleSideStepRight = MaleSideStepRightFile.loadAnimation(); - -// read in the sounds -var footsteps = []; -footsteps.push(new Sound(pathToSounds+"FootstepW2Left-12db.wav")); -footsteps.push(new Sound(pathToSounds+"FootstepW2Right-12db.wav")); -footsteps.push(new Sound(pathToSounds+"FootstepW3Left-12db.wav")); -footsteps.push(new Sound(pathToSounds+"FootstepW3Right-12db.wav")); -footsteps.push(new Sound(pathToSounds+"FootstepW5Left-12db.wav")); -footsteps.push(new Sound(pathToSounds+"FootstepW5Right-12db.wav")); - -// all slider controls have a range (with the exception of phase controls that are always +-180) so we store them all here -var sliderRanges = {"joints":[{"name":"hips","pitchRange":25,"yawRange":25,"rollRange":25,"pitchOffsetRange":25,"yawOffsetRange":25,"rollOffsetRange":25,"thrustRange":0.01,"bobRange":0.02,"swayRange":0.01},{"name":"upperLegs","pitchRange":90,"yawRange":35,"rollRange":35,"pitchOffsetRange":60,"yawOffsetRange":20,"rollOffsetRange":20},{"name":"lowerLegs","pitchRange":90,"yawRange":20,"rollRange":20,"pitchOffsetRange":90,"yawOffsetRange":20,"rollOffsetRange":20},{"name":"feet","pitchRange":60,"yawRange":20,"rollRange":20,"pitchOffsetRange":60,"yawOffsetRange":50,"rollOffsetRange":50},{"name":"toes","pitchRange":90,"yawRange":20,"rollRange":20,"pitchOffsetRange":90,"yawOffsetRange":20,"rollOffsetRange":20},{"name":"spine","pitchRange":40,"yawRange":40,"rollRange":40,"pitchOffsetRange":90,"yawOffsetRange":50,"rollOffsetRange":50},{"name":"spine1","pitchRange":20,"yawRange":40,"rollRange":20,"pitchOffsetRange":90,"yawOffsetRange":50,"rollOffsetRange":50},{"name":"spine2","pitchRange":20,"yawRange":40,"rollRange":20,"pitchOffsetRange":90,"yawOffsetRange":50,"rollOffsetRange":50},{"name":"shoulders","pitchRange":35,"yawRange":40,"rollRange":20,"pitchOffsetRange":180,"yawOffsetRange":180,"rollOffsetRange":180},{"name":"upperArms","pitchRange":90,"yawRange":90,"rollRange":90,"pitchOffsetRange":180,"yawOffsetRange":180,"rollOffsetRange":180},{"name":"lowerArms","pitchRange":90,"yawRange":90,"rollRange":120,"pitchOffsetRange":180,"yawOffsetRange":180,"rollOffsetRange":180},{"name":"hands","pitchRange":90,"yawRange":180,"rollRange":90,"pitchOffsetRange":180,"yawOffsetRange":180,"rollOffsetRange":180},{"name":"head","pitchRange":20,"yawRange":20,"rollRange":20,"pitchOffsetRange":90,"yawOffsetRange":90,"rollOffsetRange":90}]}; - -// internal state (FSM based) constants -var STANDING = 1; -var WALKING = 2; -var SIDE_STEPPING = 3; -var FLYING = 4; -var CONFIG_WALK_STYLES = 5; -var CONFIG_WALK_TWEAKS = 6; -var CONFIG_WALK_JOINTS = 7; -var CONFIG_STANDING = 8; -var CONFIG_FLYING = 9; -var CONFIG_FLYING_UP = 10; -var CONFIG_FLYING_DOWN = 11; -var CONFIG_SIDESTEP_LEFT = 12; -var CONFIG_SIDESTEP_RIGHT = 14; -var INTERNAL_STATE = STANDING; - -// status -var powerOn = true; -var paused = false; // pause animation playback whilst adjusting certain parameters -var minimised = true; -var armsFree = true; // set true for hydra support - temporary fix for Hydras -var statsOn = false; -var playFootStepSounds = true; - // constants -var MAX_WALK_SPEED = 1257; // max oscillation speed -var FLYING_SPEED = 6.4;// 12.4; // m/s - real humans can't run any faster than 12.4 m/s -var TERMINAL_VELOCITY = 300; // max speed imposed by Interface -var DIRECTION_UP = 1; -var DIRECTION_DOWN = 2; -var DIRECTION_LEFT = 4; -var DIRECTION_RIGHT = 8; -var DIRECTION_FORWARDS = 16; -var DIRECTION_BACKWARDS = 32; -var DIRECTION_NONE = 64; var MALE = 1; var FEMALE = 2; +var MAX_WALK_SPEED = 2.5; +var TAKE_FLIGHT_SPEED = 4.55; +var TOP_SPEED = 300; +var UP = 1; +var DOWN = 2; +var LEFT = 4; +var RIGHT = 8; +var FORWARDS = 16; +var BACKWARDS = 32; -// start of animation control section -var cumulativeTime = 0.0; -var lastOrientation; +// ovelay images location +var pathToAssets = 'http://s3.amazonaws.com/hifi-public/WalkScript/'; -// avi gender and default animations -var avatarGender = MALE; -var selectedWalk = maleStrutWalk; // the currently selected animation walk file (to edit any animation, paste it's name here and select walk editing mode) -var selectedStand = maleStandOne; -var selectedFlyUp = maleFlyingUp; -var selectedFly = maleFlying; -var selectedFlyDown = maleFlyingDown; -var selectedSideStepLeft = maleSideStepLeft; -var selectedSideStepRight = maleSideStepRight; -if(avatarGender===FEMALE) { +// load the UI +Script.include("./libraries/walkInterface.js"); - // to make toggling the default quick - selectedWalk = femaleStrutWalk; - selectedStand = femaleStandOne; - selectedFlyUp = femaleFlyingUp; - selectedFly = femaleFlying; - selectedFlyDown = femaleFlyingDown; - selectedSideStepLeft = femaleSideStepLeft; - selectedSideStepRight = femaleSideStepRight; -} -var currentAnimation = selectedStand; // the current animation -var selectedJointIndex = 0; // the index of the joint currently selected for editing -var currentTransition = null; // used as a pointer to a Transition +// load filters (Bezier, Butterworth, add harmonics, averaging) +Script.include("./libraries/walkFilters.js"); -// walkwheel (foot / ground speed matching) -var sideStepCycleStartLeft = 270; -var sideStepCycleStartRight = 90; -var walkWheelPosition = 0; -var nextStep = DIRECTION_RIGHT; // first step is always right, because the sine waves say so. Unless you're mirrored. -var nFrames = 0; // counts number of frames -var strideLength = 0; // stride calibration -var aviFootSize = {x:0.1, y:0.1, z:0.25}; // experimental values for addition to stride length - TODO: analyse and confirm is increasing smaller stride lengths accuracy once we have better ground detection +// load objects, constructors and assets (state, Motion, Transition, walkAssets) +Script.include("./libraries/walkApi.js"); -// stats -var frameStartTime = 0; // when the frame first starts we take a note of the time -var frameExecutionTimeMax = 0; // keep track of the longest frame execution time +// initialise the motion state / history object +var motion = new Motion(); -// constructor for recent RecentMotion (i.e. frame data) class -function RecentMotion(velocity, acceleration, principleDirection, state) { - this.velocity = velocity; - this.acceleration = acceleration; - this.principleDirection = principleDirection; - this.state = state; -} +// initialise Transitions +var nullTransition = new Transition(); +motion.curTransition = nullTransition; -// constructor for the FramesHistory object -function FramesHistory() { - this.recentMotions = []; - for(var i = 0 ; i < 10 ; i++) { - var blank = new RecentMotion({ x:0, y:0, z:0 }, { x:0, y:0, z:0 }, DIRECTION_FORWARDS, STANDING ); - this.recentMotions.push(blank); - } +// initialise the UI +walkInterface.initialise(state, motion, walkAssets); - // recentDirection 'method' args: (direction enum, number of steps back to compare) - this.recentDirection = function () { +// wave shapes +var SAWTOOTH = 1; +var TRIANGLE = 2; +var SQUARE = 4; - if( arguments[0] && arguments[1] ) { +// filters for synthesising more complex, natural waveforms +var leanPitchFilter = filter.createAveragingFilter(15); +var leanRollFilter = filter.createAveragingFilter(15); +var hipsYawShaper = filter.createWaveSynth(TRIANGLE, 3, 2); +var hipsBobLPFilter = filter.createButterworthFilter(5); - var directionCount = 0; - if( arguments[1] > this.recentMotions.length ) - arguments[1] = this.recentMotions.length; - - for(var i = 0 ; i < arguments[1] ; i++ ) { - if( this.recentMotions[i].principleDirection === arguments[0] ) - directionCount++; - } - return directionCount / arguments[1] === 1 ? true : false; - } - return false; - } - - // recentState 'method' args: (state enum, number of steps back to compare) - this.recentState = function () { - - if( arguments[0] && arguments[1] ) { - - var stateCount = 0; - if( arguments[1] > this.recentMotions.length ) - arguments[1] = this.recentMotions.length; - - for(var i = 0 ; i < arguments[1] ; i++ ) { - if( this.recentMotions[i].state === arguments[0] ) - stateCount++; - } - return stateCount / arguments[1] === 1 ? true : false; - } - return false; - } - this.lastWalkStartTime = 0; // short walks and long walks need different handling -} -var framesHistory = new FramesHistory(); - -// constructor for animation Transition class -function Transition(lastAnimation, nextAnimation, reachPoses, transitionDuration, easingLower, easingUpper) { - this.lastAnimation = lastAnimation; // name of last animation - if(lastAnimation === selectedWalk || - nextAnimation === selectedSideStepLeft || - nextAnimation === selectedSideStepRight) - this.walkingAtStart = true; // boolean - is the last animation a walking animation? - else - this.walkingAtStart = false; // boolean - is the last animation a walking animation? - this.nextAnimation = nextAnimation; // name of next animation - if(nextAnimation === selectedWalk || - nextAnimation === selectedSideStepLeft || - nextAnimation === selectedSideStepRight) - this.walkingAtEnd = true; // boolean - is the next animation a walking animation? - else - this.walkingAtEnd = false; // boolean - is the next animation a walking animation? - this.reachPoses = reachPoses; // array of reach poses - am very much looking forward to putting these in! - this.transitionDuration = transitionDuration; // length of transition (seconds) - this.easingLower = easingLower; // Bezier curve handle (normalised) - this.easingUpper = easingUpper; // Bezier curve handle (normalised) - this.startTime = new Date().getTime(); // Starting timestamp (seconds) - this.progress = 0; // how far are we through the transition? - this.walkWheelIncrement = 3; // how much to turn the walkwheel each frame when coming to a halt. Get's set to 0 once the feet are under the avi - this.walkWheelAdvance = 0; // how many degrees the walk wheel has been advanced during the transition - this.walkStopAngle = 0; // what angle should we stop the walk cycle? (calculated on the fly) -} - -// convert a local (to the avi) translation to a global one -function localToGlobal(localTranslation) { - - var aviOrientation = MyAvatar.orientation; - var front = Quat.getFront(aviOrientation); - var right = Quat.getRight(aviOrientation); - var up = Quat.getUp (aviOrientation); - var aviFront = Vec3.multiply(front,localTranslation.z); - var aviRight = Vec3.multiply(right,localTranslation.x); - var aviUp = Vec3.multiply(up ,localTranslation.y); - var globalTranslation = {x:0,y:0,z:0}; // final value - globalTranslation = Vec3.sum(globalTranslation, aviFront); - globalTranslation = Vec3.sum(globalTranslation, aviRight); - globalTranslation = Vec3.sum(globalTranslation, aviUp); - return globalTranslation; -} - -// similar ot above - convert hips translations to global and apply -function translateHips(localHipsTranslation) { - - var aviOrientation = MyAvatar.orientation; - var front = Quat.getFront(aviOrientation); - var right = Quat.getRight(aviOrientation); - var up = Quat.getUp (aviOrientation); - var aviFront = Vec3.multiply(front,localHipsTranslation.y); - var aviRight = Vec3.multiply(right,localHipsTranslation.x); - var aviUp = Vec3.multiply(up ,localHipsTranslation.z); - var AviTranslationOffset = {x:0,y:0,z:0}; // final value - AviTranslationOffset = Vec3.sum(AviTranslationOffset, aviFront); - AviTranslationOffset = Vec3.sum(AviTranslationOffset, aviRight); - AviTranslationOffset = Vec3.sum(AviTranslationOffset, aviUp); - MyAvatar.position = {x: MyAvatar.position.x + AviTranslationOffset.x, - y: MyAvatar.position.y + AviTranslationOffset.y, - z: MyAvatar.position.z + AviTranslationOffset.z }; -} - -// clear all joint data -function resetJoints() { - - var avatarJointNames = MyAvatar.getJointNames(); - for (var i = 0; i < avatarJointNames.length; i++) { - MyAvatar.clearJointData(avatarJointNames[i]); - } -} - -// play footstep sound -function playFootstep(side) { - - var options = new AudioInjectionOptions(); - options.position = Camera.getPosition(); - options.volume = 0.5; - var walkNumber = 2; // 0 to 2 - if(side===DIRECTION_RIGHT && playFootStepSounds) { - Audio.playSound(footsteps[walkNumber+1], options); - } - else if(side===DIRECTION_LEFT && playFootStepSounds) { - Audio.playSound(footsteps[walkNumber], options); - } -} - -// put the fingers into a relaxed pose -function curlFingers() { - - // left hand fingers - for(var i = 18 ; i < 34 ; i++) { - MyAvatar.setJointData(jointList[i], Quat.fromPitchYawRollDegrees(8,0,0)); - } - // left hand thumb - for(var i = 34 ; i < 38 ; i++) { - MyAvatar.setJointData(jointList[i], Quat.fromPitchYawRollDegrees(0,0,0)); - } - // right hand fingers - for(var i = 42 ; i < 58 ; i++) { - MyAvatar.setJointData(jointList[i], Quat.fromPitchYawRollDegrees(8,0,0)); - } - // right hand thumb - for(var i = 58 ; i < 62 ; i++) { - MyAvatar.setJointData(jointList[i], Quat.fromPitchYawRollDegrees(0,0,0)); - } -} - -// additional maths functions -function degToRad( degreesValue ) { return degreesValue * Math.PI / 180; } -function radToDeg( radiansValue ) { return radiansValue * 180 / Math.PI; } - -// animateAvatar - sine wave generators working like clockwork -function animateAvatar( deltaTime, velocity, principleDirection ) { - - // adjusting the walk speed in edit mode causes a nasty flicker. pausing the animation stops this - if(paused) return; - - var cycle = cumulativeTime; - var transitionProgress = 1; - var adjustedFrequency = currentAnimation.settings.baseFrequency; - - // upper legs phase reversal for walking backwards - var forwardModifier = 1; - if(principleDirection===DIRECTION_BACKWARDS) - forwardModifier = -1; - - // don't want to lean forwards if going directly upwards - var leanPitchModifier = 1; - if(principleDirection===DIRECTION_UP) - leanPitchModifier = 0; - - // is there a Transition to include? - if(currentTransition!==null) { - - // if is a new transiton - if(currentTransition.progress===0) { - - if( currentTransition.walkingAtStart ) { - - if( INTERNAL_STATE !== SIDE_STEPPING ) { - - // work out where we want the walk cycle to stop - var leftStop = selectedWalk.settings.stopAngleForwards + 180; - var rightStop = selectedWalk.settings.stopAngleForwards; - if( principleDirection === DIRECTION_BACKWARDS ) { - leftStop = selectedWalk.settings.stopAngleBackwards + 180; - rightStop = selectedWalk.settings.stopAngleBackwards; - } - - // find the closest stop point from the walk wheel's angle - var angleToLeftStop = 180 - Math.abs( Math.abs( walkWheelPosition - leftStop ) - 180); - var angleToRightStop = 180 - Math.abs( Math.abs( walkWheelPosition - rightStop ) - 180); - if( walkWheelPosition > angleToLeftStop ) angleToLeftStop = 360 - angleToLeftStop; - if( walkWheelPosition > angleToRightStop ) angleToRightStop = 360 - angleToRightStop; - - currentTransition.walkWheelIncrement = 6; - - // keep the walkwheel turning by setting the walkWheelIncrement until our feet are tucked nicely underneath us. - if( angleToLeftStop < angleToRightStop ) { - - currentTransition.walkStopAngle = leftStop; - - } else { - - currentTransition.walkStopAngle = rightStop; - } - - } else { - - // freeze wheel for sidestepping transitions - currentTransition.walkWheelIncrement = 0; - } - } - } // end if( currentTransition.walkingAtStart ) - - // calculate the Transition progress - var elapasedTime = (new Date().getTime() - currentTransition.startTime) / 1000; - currentTransition.progress = elapasedTime / currentTransition.transitionDuration; - transitionProgress = getBezier((1-currentTransition.progress), {x:0,y:0}, currentTransition.easingLower, currentTransition.easingUpper, {x:1,y:1}).y; - - if(currentTransition.progress>=1) { - - // time to kill off the transition - delete currentTransition; - currentTransition = null; - - } else { - - if( currentTransition.walkingAtStart ) { - - if( INTERNAL_STATE !== SIDE_STEPPING ) { - - // if at a stop angle, hold the walk wheel position for remainder of transition - var tolerance = 7; // must be greater than the walkWheel increment - if(( walkWheelPosition > (currentTransition.walkStopAngle - tolerance )) && - ( walkWheelPosition < (currentTransition.walkStopAngle + tolerance ))) { - - currentTransition.walkWheelIncrement = 0; - } - // keep turning walk wheel until both feet are below the avi - walkWheelPosition += currentTransition.walkWheelIncrement; - currentTransition.walkWheelAdvance += currentTransition.walkWheelIncrement; - } - } - } - } - - // will we need to use the walk wheel this frame? - if(currentAnimation === selectedWalk || - currentAnimation === selectedSideStepLeft || - currentAnimation === selectedSideStepRight || - currentTransition !== null) { - - // set the stride length - if( INTERNAL_STATE!==SIDE_STEPPING && - INTERNAL_STATE!==CONFIG_SIDESTEP_LEFT && - INTERNAL_STATE!==CONFIG_SIDESTEP_RIGHT && - currentTransition===null ) { - - // if the timing's right, take a snapshot of the stride max and recalibrate - var tolerance = 1.0; // higher the number, the higher the chance of a calibration taking place, but is traded off with lower accuracy - var strideOne = 40; - var strideTwo = 220; - - if( principleDirection === DIRECTION_BACKWARDS ) { - strideOne = 130; - strideTwo = 300; - } - - if(( walkWheelPosition < (strideOne+tolerance) && walkWheelPosition > (strideOne-tolerance) ) || - ( walkWheelPosition < (strideTwo+tolerance) && walkWheelPosition > (strideTwo-tolerance) )) { - - // calculate the feet's offset from each other (in local Z only) - var footRPos = localToGlobal(MyAvatar.getJointPosition("RightFoot")); - var footLPos = localToGlobal(MyAvatar.getJointPosition("LeftFoot")); - var footOffsetZ = Math.abs(footRPos.z - footLPos.z); - if(footOffsetZ>1) strideLength = 2 * footOffsetZ + aviFootSize.z; // sometimes getting very low value here - just ignore for now - if(statsOn) print('Stride length calibrated to '+strideLength.toFixed(4)+' metres at '+walkWheelPosition.toFixed(1)+' degrees'); - if(principleDirection===DIRECTION_FORWARDS) { - currentAnimation.calibration.strideLengthForwards = strideLength; - } else if (principleDirection===DIRECTION_BACKWARDS) { - currentAnimation.calibration.strideLengthBackwards = strideLength; - } - - } else { - - if(principleDirection===DIRECTION_FORWARDS) - strideLength = currentAnimation.calibration.strideLengthForwards; - else if (principleDirection===DIRECTION_BACKWARDS) - strideLength = currentAnimation.calibration.strideLengthBackwards; - } - } - else if(( INTERNAL_STATE===SIDE_STEPPING || - INTERNAL_STATE===CONFIG_SIDESTEP_LEFT || - INTERNAL_STATE===CONFIG_SIDESTEP_RIGHT ) ) { - - // calculate lateral stride - same same, but different - // if the timing's right, take a snapshot of the stride max and recalibrate the stride length - var tolerance = 1.0; // higher the number, the higher the chance of a calibration taking place, but is traded off with lower accuracy - if(principleDirection===DIRECTION_LEFT) { - - if( walkWheelPosition < (3+tolerance) && walkWheelPosition > (3-tolerance) ) { - - // calculate the feet's offset from the hips (in local X only) - var footRPos = localToGlobal(MyAvatar.getJointPosition("RightFoot")); - var footLPos = localToGlobal(MyAvatar.getJointPosition("LeftFoot")); - var footOffsetX = Math.abs(footRPos.x - footLPos.x); - strideLength = footOffsetX; - if(statsOn) print('Stride width calibrated to '+strideLength.toFixed(4)+ ' metres at '+walkWheelPosition.toFixed(1)+' degrees'); - currentAnimation.calibration.strideLengthLeft = strideLength; - - } else { - - strideLength = currentAnimation.calibration.strideLengthLeft; - } - } - else if (principleDirection===DIRECTION_RIGHT) { - - if( walkWheelPosition < (170+tolerance) && walkWheelPosition > (170-tolerance) ) { - - // calculate the feet's offset from the hips (in local X only) - var footRPos = localToGlobal(MyAvatar.getJointPosition("RightFoot")); - var footLPos = localToGlobal(MyAvatar.getJointPosition("LeftFoot")); - var footOffsetX = Math.abs(footRPos.x - footLPos.x); - strideLength = footOffsetX; - if(statsOn) print('Stride width calibrated to '+strideLength.toFixed(4)+ ' metres at '+walkWheelPosition.toFixed(1)+' degrees'); - currentAnimation.calibration.strideLengthRight = strideLength; - - } else { - - strideLength = currentAnimation.calibration.strideLengthRight; - } - } - } // end stride length calculations - - // wrap the stride length around a 'surveyor's wheel' twice and calculate the angular velocity at the given (linear) velocity - // omega = v / r , where r = circumference / 2 PI , where circumference = 2 * stride length - var wheelRadius = strideLength / Math.PI; - var angularVelocity = velocity / wheelRadius; - - // calculate the degrees turned (at this angular velocity) since last frame - var radiansTurnedSinceLastFrame = deltaTime * angularVelocity; - var degreesTurnedSinceLastFrame = radToDeg(radiansTurnedSinceLastFrame); - - // if we are in an edit mode, we will need fake time to turn the wheel - if( INTERNAL_STATE!==WALKING && - INTERNAL_STATE!==SIDE_STEPPING ) - degreesTurnedSinceLastFrame = currentAnimation.settings.baseFrequency / 70; - - if( walkWheelPosition >= 360 ) - walkWheelPosition = walkWheelPosition % 360; - - // advance the walk wheel the appropriate amount - if( currentTransition===null || currentTransition.walkingAtEnd ) - walkWheelPosition += degreesTurnedSinceLastFrame; - - // set the new values for the exact correct walk cycle speed at this velocity - adjustedFrequency = 1; - cycle = walkWheelPosition; - - // show stats and walk wheel? - if(statsOn) { - - var distanceTravelled = velocity * deltaTime; - var deltaTimeMS = deltaTime * 1000; - - if( INTERNAL_STATE===SIDE_STEPPING || - INTERNAL_STATE===CONFIG_SIDESTEP_LEFT || - INTERNAL_STATE===CONFIG_SIDESTEP_RIGHT ) { - - // draw the walk wheel turning around the z axis for sidestepping - var directionSign = 1; - if(principleDirection===DIRECTION_RIGHT) directionSign = -1; - var yOffset = hipsToFeetDistance - (wheelRadius/1.2); // /1.2 is a visual kludge, probably necessary because of either the 'avi feet penetrate floor' issue - TODO - once ground plane following is in Interface, lock this down - var sinWalkWheelPosition = wheelRadius * Math.sin(degToRad( directionSign * walkWheelPosition )); - var cosWalkWheelPosition = wheelRadius * Math.cos(degToRad( directionSign * -walkWheelPosition )); - var wheelXPos = {x: cosWalkWheelPosition, y:-sinWalkWheelPosition - yOffset, z: 0}; - var wheelXEnd = {x: -cosWalkWheelPosition, y:sinWalkWheelPosition - yOffset, z: 0}; - sinWalkWheelPosition = wheelRadius * Math.sin(degToRad( -directionSign * walkWheelPosition+90 )); - cosWalkWheelPosition = wheelRadius * Math.cos(degToRad( -directionSign * walkWheelPosition+90 )); - var wheelYPos = {x:cosWalkWheelPosition, y:sinWalkWheelPosition - yOffset, z: 0}; - var wheelYEnd = {x:-cosWalkWheelPosition, y:-sinWalkWheelPosition - yOffset, z: 0}; - Overlays.editOverlay(walkWheelYLine, {visible: true, position:wheelYPos, end:wheelYEnd}); - Overlays.editOverlay(walkWheelZLine, {visible: true, position:wheelXPos, end:wheelXEnd}); - - } else { - - // draw the walk wheel turning around the x axis for walking forwards or backwards - var yOffset = hipsToFeetDistance - (wheelRadius/1.2); // /1.2 is a visual kludge, probably necessary because of either the 'avi feet penetrate floor' issue - TODO - once ground plane following is in Interface, lock this down - var sinWalkWheelPosition = wheelRadius * Math.sin(degToRad((forwardModifier*-1) * walkWheelPosition)); - var cosWalkWheelPosition = wheelRadius * Math.cos(degToRad((forwardModifier*-1) * -walkWheelPosition)); - var wheelZPos = {x:0, y:-sinWalkWheelPosition - yOffset, z: cosWalkWheelPosition}; - var wheelZEnd = {x:0, y:sinWalkWheelPosition - yOffset, z: -cosWalkWheelPosition}; - sinWalkWheelPosition = wheelRadius * Math.sin(degToRad(forwardModifier * walkWheelPosition+90)); - cosWalkWheelPosition = wheelRadius * Math.cos(degToRad(forwardModifier * walkWheelPosition+90)); - var wheelYPos = {x:0, y:sinWalkWheelPosition - yOffset, z: cosWalkWheelPosition}; - var wheelYEnd = {x:0, y:-sinWalkWheelPosition - yOffset, z: -cosWalkWheelPosition}; - Overlays.editOverlay(walkWheelYLine, { visible: true, position:wheelYPos, end:wheelYEnd }); - Overlays.editOverlay(walkWheelZLine, { visible: true, position:wheelZPos, end:wheelZEnd }); - } - - // populate stats overlay - var walkWheelInfo = - ' Walk Wheel Stats\n--------------------------------------\n \n \n' - + '\nFrame time: '+deltaTimeMS.toFixed(2) - + ' mS\nVelocity: '+velocity.toFixed(2) - + ' m/s\nDistance: '+distanceTravelled.toFixed(3) - + ' m\nOmega: '+angularVelocity.toFixed(3) - + ' rad / s\nDeg to turn: '+degreesTurnedSinceLastFrame.toFixed(2) - + ' deg\nWheel position: '+cycle.toFixed(1) - + ' deg\nWheel radius: '+wheelRadius.toFixed(3) - + ' m\nHips To Feet: '+hipsToFeetDistance.toFixed(3) - + ' m\nStride: '+strideLength.toFixed(3) - + ' m\n'; - Overlays.editOverlay(walkWheelStats, {text: walkWheelInfo}); - } - } // end of walk wheel and stride length calculation - - - // Start applying motion - var pitchOscillation = 0; - var yawOscillation = 0; - var rollOscillation = 0; - var pitchOscillationLast = 0; - var yawOscillationLast = 0; - var rollOscillationLast = 0; - var pitchOffset = 0; - var yawOffset = 0; - var rollOffset = 0; - var pitchOffsetLast = 0; - var yawOffsetLast = 0; - var rollOffsetLast = 0; - - // calcualte any hips translation - // Note: can only apply hips translations whilst in a config (edit) mode at present, not whilst under locomotion - if( INTERNAL_STATE===CONFIG_WALK_STYLES || - INTERNAL_STATE===CONFIG_WALK_TWEAKS || - INTERNAL_STATE===CONFIG_WALK_JOINTS || - INTERNAL_STATE===CONFIG_SIDESTEP_LEFT || - INTERNAL_STATE===CONFIG_SIDESTEP_RIGHT || - INTERNAL_STATE===CONFIG_FLYING || - INTERNAL_STATE===CONFIG_FLYING_UP || - INTERNAL_STATE===CONFIG_FLYING_DOWN ) { - - // calculate hips translation - var motorOscillation = Math.sin(degToRad((cycle * adjustedFrequency * 2) + currentAnimation.joints[0].thrustPhase)) + currentAnimation.joints[0].thrustOffset; - var swayOscillation = Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[0].swayPhase)) + currentAnimation.joints[0].swayOffset; - var bobOscillation = Math.sin(degToRad((cycle * adjustedFrequency * 2) + currentAnimation.joints[0].bobPhase)) + currentAnimation.joints[0].bobOffset; - - // apply hips translation - translateHips({x:swayOscillation*currentAnimation.joints[0].sway, y:motorOscillation*currentAnimation.joints[0].thrust, z:bobOscillation*currentAnimation.joints[0].bob}); - } - - // hips rotation - // apply the current Transition? - if(currentTransition!==null) { - - if( currentTransition.walkingAtStart ) { - - pitchOscillation = currentAnimation.joints[0].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency * 2) - + currentAnimation.joints[0].pitchPhase)) + currentAnimation.joints[0].pitchOffset; - - yawOscillation = currentAnimation.joints[0].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[0].yawPhase)) + currentAnimation.joints[0].yawOffset; - - rollOscillation = (currentAnimation.joints[0].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[0].rollPhase)) + currentAnimation.joints[0].rollOffset); - - pitchOscillationLast = currentTransition.lastAnimation.joints[0].pitch * Math.sin(degToRad(( walkWheelPosition * 2) - + currentTransition.lastAnimation.joints[0].pitchPhase)) + currentTransition.lastAnimation.joints[0].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[0].yaw * Math.sin(degToRad(( walkWheelPosition ) - + currentTransition.lastAnimation.joints[0].yawPhase)) + currentTransition.lastAnimation.joints[0].yawOffset; - - rollOscillationLast = (currentTransition.lastAnimation.joints[0].roll * Math.sin(degToRad(( walkWheelPosition ) - + currentTransition.lastAnimation.joints[0].rollPhase)) + currentTransition.lastAnimation.joints[0].rollOffset); - - } else { - - pitchOscillation = currentAnimation.joints[0].pitch * Math.sin(degToRad((cycle * adjustedFrequency * 2) - + currentAnimation.joints[0].pitchPhase)) + currentAnimation.joints[0].pitchOffset; - - yawOscillation = currentAnimation.joints[0].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) - + currentAnimation.joints[0].yawPhase)) + currentAnimation.joints[0].yawOffset; - - rollOscillation = (currentAnimation.joints[0].roll * Math.sin(degToRad((cycle * adjustedFrequency ) - + currentAnimation.joints[0].rollPhase)) + currentAnimation.joints[0].rollOffset); - - pitchOscillationLast = currentTransition.lastAnimation.joints[0].pitch * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency * 2) - + currentTransition.lastAnimation.joints[0].pitchPhase)) + currentTransition.lastAnimation.joints[0].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[0].yaw * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[0].yawPhase)) + currentTransition.lastAnimation.joints[0].yawOffset; - - rollOscillationLast = (currentTransition.lastAnimation.joints[0].roll * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[0].rollPhase)) + currentTransition.lastAnimation.joints[0].rollOffset); - - } - - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - } else { - - pitchOscillation = currentAnimation.joints[0].pitch * Math.sin(degToRad((cycle * adjustedFrequency * 2) - + currentAnimation.joints[0].pitchPhase)) + currentAnimation.joints[0].pitchOffset; - - yawOscillation = currentAnimation.joints[0].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) - + currentAnimation.joints[0].yawPhase)) + currentAnimation.joints[0].yawOffset; - - rollOscillation = (currentAnimation.joints[0].roll * Math.sin(degToRad((cycle * adjustedFrequency ) - + currentAnimation.joints[0].rollPhase)) + currentAnimation.joints[0].rollOffset); - } - - // apply hips rotation - MyAvatar.setJointData("Hips", Quat.fromPitchYawRollDegrees(-pitchOscillation + (leanPitchModifier * getLeanPitch(velocity)), // getLeanPitch - lean forwards as velocity increases - yawOscillation, // Yup, that's correct ;-) - rollOscillation + getLeanRoll(deltaTime, velocity))); // getLeanRoll - banking on cornering - - // upper legs - if( INTERNAL_STATE!==SIDE_STEPPING && - INTERNAL_STATE!==CONFIG_SIDESTEP_LEFT && - INTERNAL_STATE!==CONFIG_SIDESTEP_RIGHT ) { - - // apply the current Transition to the upper legs? - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[1].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + (forwardModifier * currentAnimation.joints[1].pitchPhase))); - yawOscillation = currentAnimation.joints[1].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[1].yawPhase)); - rollOscillation = currentAnimation.joints[1].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[1].rollPhase)); - - pitchOffset = currentAnimation.joints[1].pitchOffset; - yawOffset = currentAnimation.joints[1].yawOffset; - rollOffset = currentAnimation.joints[1].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[1].pitch - * Math.sin(degToRad( walkWheelPosition + (forwardModifier * currentTransition.lastAnimation.joints[1].pitchPhase ))); - - yawOscillationLast = currentTransition.lastAnimation.joints[1].yaw - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[1].yawPhase )); - - rollOscillationLast = currentTransition.lastAnimation.joints[1].roll - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[1].rollPhase )); - - pitchOffsetLast = currentTransition.lastAnimation.joints[1].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[1].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[1].rollOffset; - - } else { - - pitchOscillation = currentAnimation.joints[1].pitch * Math.sin(degToRad((cycle * adjustedFrequency ) + (forwardModifier * currentAnimation.joints[1].pitchPhase))); - yawOscillation = currentAnimation.joints[1].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[1].yawPhase)); - rollOscillation = currentAnimation.joints[1].roll * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[1].rollPhase)); - - pitchOffset = currentAnimation.joints[1].pitchOffset; - yawOffset = currentAnimation.joints[1].yawOffset; - rollOffset = currentAnimation.joints[1].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[1].pitch - * Math.sin(degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + (forwardModifier * currentTransition.lastAnimation.joints[1].pitchPhase ))); - - yawOscillationLast = currentTransition.lastAnimation.joints[1].yaw - * Math.sin(degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[1].yawPhase )); - - rollOscillationLast = currentTransition.lastAnimation.joints[1].roll - * Math.sin(degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[1].rollPhase )); - - pitchOffsetLast = currentTransition.lastAnimation.joints[1].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[1].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[1].rollOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation ) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation ) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation ) + ((1-transitionProgress) * rollOscillationLast); - - pitchOffset = (transitionProgress * pitchOffset) + ((1-transitionProgress) * pitchOffsetLast); - yawOffset = (transitionProgress * yawOffset) + ((1-transitionProgress) * yawOffsetLast); - rollOffset = (transitionProgress * rollOffset) + ((1-transitionProgress) * rollOffsetLast); - - } else { - - pitchOscillation = currentAnimation.joints[1].pitch * Math.sin(degToRad((cycle * adjustedFrequency ) + (forwardModifier * currentAnimation.joints[1].pitchPhase))); - yawOscillation = currentAnimation.joints[1].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[1].yawPhase)); - rollOscillation = currentAnimation.joints[1].roll * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[1].rollPhase)); - - pitchOffset = currentAnimation.joints[1].pitchOffset; - yawOffset = currentAnimation.joints[1].yawOffset; - rollOffset = currentAnimation.joints[1].rollOffset; - } - - // apply the upper leg rotations - MyAvatar.setJointData("RightUpLeg", Quat.fromPitchYawRollDegrees( pitchOscillation + pitchOffset, yawOscillation + yawOffset, -rollOscillation - rollOffset )); - MyAvatar.setJointData("LeftUpLeg", Quat.fromPitchYawRollDegrees( -pitchOscillation + pitchOffset, yawOscillation - yawOffset, -rollOscillation + rollOffset )); - - - // lower leg - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[2].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[2].pitchPhase)); - yawOscillation = currentAnimation.joints[2].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[2].yawPhase)); - rollOscillation = currentAnimation.joints[2].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[2].rollPhase)); - - pitchOffset = currentAnimation.joints[2].pitchOffset; - yawOffset = currentAnimation.joints[2].yawOffset; - rollOffset = currentAnimation.joints[2].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[2].pitch * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[2].pitchPhase)); - yawOscillationLast = currentTransition.lastAnimation.joints[2].yaw * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[2].yawPhase)); - rollOscillationLast = currentTransition.lastAnimation.joints[2].roll * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[2].rollPhase)); - - pitchOffsetLast = currentTransition.lastAnimation.joints[2].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[2].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[2].rollOffset; - - } else { - - pitchOscillation = currentAnimation.joints[2].pitch * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[2].pitchPhase)); - yawOscillation = currentAnimation.joints[2].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[2].yawPhase)); - rollOscillation = currentAnimation.joints[2].roll * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[2].rollPhase)); - - pitchOffset = currentAnimation.joints[2].pitchOffset; - yawOffset = currentAnimation.joints[2].yawOffset; - rollOffset = currentAnimation.joints[2].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[2].pitch - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[2].pitchPhase)); - yawOscillationLast = currentTransition.lastAnimation.joints[2].yaw - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[2].yawPhase)); - rollOscillationLast = currentTransition.lastAnimation.joints[2].roll - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[2].rollPhase)); - - pitchOffsetLast = currentTransition.lastAnimation.joints[2].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[2].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[2].rollOffset; - } - - pitchOscillation = ( transitionProgress * pitchOscillation ) + ( (1-transitionProgress) * pitchOscillationLast ); - yawOscillation = ( transitionProgress * yawOscillation ) + ( (1-transitionProgress) * yawOscillationLast ); - rollOscillation = ( transitionProgress * rollOscillation ) + ( (1-transitionProgress) * rollOscillationLast ); - - pitchOffset = ( transitionProgress * pitchOffset ) + ( (1-transitionProgress) * pitchOffsetLast ); - yawOffset = ( transitionProgress * yawOffset ) + ( (1-transitionProgress) * yawOffsetLast ); - rollOffset = ( transitionProgress * rollOffset ) + ( (1-transitionProgress) * rollOffsetLast ); - - } else { - - pitchOscillation = currentAnimation.joints[2].pitch * Math.sin( degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[2].pitchPhase )); - yawOscillation = currentAnimation.joints[2].yaw * Math.sin( degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[2].yawPhase )); - rollOscillation = currentAnimation.joints[2].roll * Math.sin( degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[2].rollPhase )); - - pitchOffset = currentAnimation.joints[2].pitchOffset; - yawOffset = currentAnimation.joints[2].yawOffset; - rollOffset = currentAnimation.joints[2].rollOffset; - } - - // apply lower leg joint rotations - MyAvatar.setJointData("RightLeg", Quat.fromPitchYawRollDegrees( -pitchOscillation + pitchOffset, yawOscillation - yawOffset, rollOscillation - rollOffset )); - MyAvatar.setJointData("LeftLeg", Quat.fromPitchYawRollDegrees( pitchOscillation + pitchOffset, yawOscillation + yawOffset, rollOscillation + rollOffset )); - - } // end if !SIDE_STEPPING - - else if( INTERNAL_STATE===SIDE_STEPPING || - INTERNAL_STATE===CONFIG_SIDESTEP_LEFT || - INTERNAL_STATE===CONFIG_SIDESTEP_RIGHT ) { - - // sidestepping uses the sinewave generators slightly differently for the legs - pitchOscillation = currentAnimation.joints[1].pitch * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[1].pitchPhase)); - yawOscillation = currentAnimation.joints[1].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[1].yawPhase)); - rollOscillation = currentAnimation.joints[1].roll * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[1].rollPhase)); - - // apply upper leg rotations for sidestepping - MyAvatar.setJointData("RightUpLeg", Quat.fromPitchYawRollDegrees( - -pitchOscillation + currentAnimation.joints[1].pitchOffset, - yawOscillation + currentAnimation.joints[1].yawOffset, - rollOscillation + currentAnimation.joints[1].rollOffset )); - MyAvatar.setJointData("LeftUpLeg", Quat.fromPitchYawRollDegrees( - pitchOscillation + currentAnimation.joints[1].pitchOffset, - yawOscillation - currentAnimation.joints[1].yawOffset, - -rollOscillation - currentAnimation.joints[1].rollOffset )); - - // calculate lower leg joint rotations for sidestepping - pitchOscillation = currentAnimation.joints[2].pitch * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[2].pitchPhase)); - yawOscillation = currentAnimation.joints[2].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[2].yawPhase)); - rollOscillation = currentAnimation.joints[2].roll * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[2].rollPhase)); - - // apply lower leg joint rotations - MyAvatar.setJointData("RightLeg", Quat.fromPitchYawRollDegrees( - -pitchOscillation + currentAnimation.joints[2].pitchOffset, - yawOscillation - currentAnimation.joints[2].yawOffset, - rollOscillation - currentAnimation.joints[2].rollOffset)); // TODO: needs a kick just before fwd peak - MyAvatar.setJointData("LeftLeg", Quat.fromPitchYawRollDegrees( - pitchOscillation + currentAnimation.joints[2].pitchOffset, - yawOscillation + currentAnimation.joints[2].yawOffset, - rollOscillation + currentAnimation.joints[2].rollOffset)); - } - - // feet - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[3].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[3].pitchPhase)); - yawOscillation = currentAnimation.joints[3].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[3].yawPhase)); - rollOscillation = currentAnimation.joints[3].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[3].rollPhase)); - - pitchOffset = currentAnimation.joints[3].pitchOffset; - yawOffset = currentAnimation.joints[3].yawOffset; - rollOffset = currentAnimation.joints[3].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[3].pitch * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[3].pitchPhase)); - yawOscillationLast = currentTransition.lastAnimation.joints[3].yaw * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[3].yawPhase)); - rollOscillationLast = currentTransition.lastAnimation.joints[3].roll * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[3].rollPhase)); - - pitchOffsetLast = currentTransition.lastAnimation.joints[3].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[3].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[3].rollOffset; - - } else { - - pitchOscillation = currentAnimation.joints[3].pitch * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[3].pitchPhase)); - yawOscillation = currentAnimation.joints[3].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[3].yawPhase)); - rollOscillation = currentAnimation.joints[3].roll * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[3].rollPhase)); - - pitchOffset = currentAnimation.joints[3].pitchOffset; - yawOffset = currentAnimation.joints[3].yawOffset; - rollOffset = currentAnimation.joints[3].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[3].pitch - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[3].pitchPhase)); - - yawOscillationLast = currentTransition.lastAnimation.joints[3].yaw - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[3].yawPhase)); - - rollOscillationLast = currentTransition.lastAnimation.joints[3].roll - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[3].rollPhase)); - - pitchOffsetLast = currentTransition.lastAnimation.joints[3].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[3].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[3].rollOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation ) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation ) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation ) + ((1-transitionProgress) * rollOscillationLast); - - pitchOffset = (transitionProgress * pitchOffset) + ((1-transitionProgress) * pitchOffsetLast); - yawOffset = (transitionProgress * yawOffset) + ((1-transitionProgress) * yawOffsetLast); - rollOffset = (transitionProgress * rollOffset) + ((1-transitionProgress) * rollOffsetLast); - - } else { - - pitchOscillation = currentAnimation.joints[3].pitch * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[3].pitchPhase)); - yawOscillation = currentAnimation.joints[3].yaw * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[3].yawPhase)); - rollOscillation = currentAnimation.joints[3].roll * Math.sin(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[3].rollPhase)); - - pitchOffset = currentAnimation.joints[3].pitchOffset; - yawOffset = currentAnimation.joints[3].yawOffset; - rollOffset = currentAnimation.joints[3].rollOffset; - } - - // apply foot rotations - MyAvatar.setJointData("RightFoot", Quat.fromPitchYawRollDegrees( pitchOscillation + pitchOffset, yawOscillation + yawOffset, rollOscillation + rollOffset )); - MyAvatar.setJointData("LeftFoot", Quat.fromPitchYawRollDegrees( -pitchOscillation + pitchOffset, yawOscillation - yawOffset, rollOscillation - rollOffset )); - - // play footfall sound yet? To determine this, we take the differential of the foot's pitch curve to decide when the foot hits the ground. - if( INTERNAL_STATE===WALKING || - INTERNAL_STATE===SIDE_STEPPING || - INTERNAL_STATE===CONFIG_WALK_STYLES || - INTERNAL_STATE===CONFIG_WALK_TWEAKS || - INTERNAL_STATE===CONFIG_WALK_JOINTS || - INTERNAL_STATE===CONFIG_SIDESTEP_LEFT || - INTERNAL_STATE===CONFIG_SIDESTEP_RIGHT ) { - - // finding dy/dx is as simple as determining the cosine wave for the foot's pitch function. - var feetPitchDifferential = Math.cos(degToRad((cycle * adjustedFrequency ) + currentAnimation.joints[3].pitchPhase)); - var threshHold = 0.9; // sets the audio trigger point. with accuracy. - if(feetPitchDifferential<-threshHold && - nextStep===DIRECTION_LEFT && - principleDirection!==DIRECTION_UP && - principleDirection!==DIRECTION_DOWN) { - - playFootstep(DIRECTION_LEFT); - nextStep = DIRECTION_RIGHT; - } - else if(feetPitchDifferential>threshHold && - nextStep===DIRECTION_RIGHT && - principleDirection!==DIRECTION_UP && - principleDirection!==DIRECTION_DOWN) { - - playFootstep(DIRECTION_RIGHT); - nextStep = DIRECTION_LEFT; - } - } - - // toes - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[4].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[4].pitchPhase)); - yawOscillation = currentAnimation.joints[4].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[4].yawPhase)) + currentAnimation.joints[4].yawOffset; - rollOscillation = currentAnimation.joints[4].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[4].rollPhase)) + currentAnimation.joints[4].rollOffset; - - pitchOffset = currentAnimation.joints[4].pitchOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[4].pitch * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[4].pitchPhase)); - yawOscillationLast = currentTransition.lastAnimation.joints[4].yaw * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[4].yawPhase)) + currentTransition.lastAnimation.joints[4].yawOffset;; - rollOscillationLast = currentTransition.lastAnimation.joints[4].roll * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[4].rollPhase))+ currentTransition.lastAnimation.joints[4].rollOffset; - - pitchOffsetLast = currentTransition.lastAnimation.joints[4].pitchOffset; - - } else { - - pitchOscillation = currentAnimation.joints[4].pitch * Math.sin(degToRad((cycle * adjustedFrequency) + currentAnimation.joints[4].pitchPhase)); - yawOscillation = currentAnimation.joints[4].yaw * Math.sin(degToRad((cycle * adjustedFrequency) + currentAnimation.joints[4].yawPhase)) + currentAnimation.joints[4].yawOffset; - rollOscillation = currentAnimation.joints[4].roll * Math.sin(degToRad((cycle * adjustedFrequency) + currentAnimation.joints[4].rollPhase)) + currentAnimation.joints[4].rollOffset; - - pitchOffset = currentAnimation.joints[4].pitchOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[4].pitch - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[4].pitchPhase)); - - yawOscillationLast = currentTransition.lastAnimation.joints[4].yaw - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[4].yawPhase)) + currentTransition.lastAnimation.joints[4].yawOffset;; - - rollOscillationLast = currentTransition.lastAnimation.joints[4].roll - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[4].rollPhase))+ currentTransition.lastAnimation.joints[4].rollOffset; - - pitchOffsetLast = currentTransition.lastAnimation.joints[4].pitchOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - pitchOffset = (transitionProgress * pitchOffset) + ((1-transitionProgress) * pitchOffsetLast); - - } else { - - pitchOscillation = currentAnimation.joints[4].pitch * Math.sin(degToRad((cycle * adjustedFrequency) + currentAnimation.joints[4].pitchPhase)); - yawOscillation = currentAnimation.joints[4].yaw * Math.sin(degToRad((cycle * adjustedFrequency) + currentAnimation.joints[4].yawPhase)) + currentAnimation.joints[4].yawOffset; - rollOscillation = currentAnimation.joints[4].roll * Math.sin(degToRad((cycle * adjustedFrequency) + currentAnimation.joints[4].rollPhase)) + currentAnimation.joints[4].rollOffset; - - pitchOffset = currentAnimation.joints[4].pitchOffset; - } - - // apply toe rotations - MyAvatar.setJointData("RightToeBase", Quat.fromPitchYawRollDegrees(-pitchOscillation + pitchOffset, yawOscillation, rollOscillation)); - MyAvatar.setJointData("LeftToeBase", Quat.fromPitchYawRollDegrees( pitchOscillation + pitchOffset, yawOscillation, rollOscillation)); - - // spine - if( currentTransition !== null ) { - - if( currentTransition.walkingAtStart ) { - - pitchOscillation = currentAnimation.joints[5].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency * 2 ) + currentAnimation.joints[5].pitchPhase)) + currentAnimation.joints[5].pitchOffset; - yawOscillation = currentAnimation.joints[5].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[5].yawPhase)) + currentAnimation.joints[5].yawOffset; - rollOscillation = currentAnimation.joints[5].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[5].rollPhase)) + currentAnimation.joints[5].rollOffset; - - // calculate where we would have been if we'd continued in the last state - pitchOscillationLast = currentTransition.lastAnimation.joints[5].pitch - * Math.sin(degToRad(( walkWheelPosition * 2 ) + currentTransition.lastAnimation.joints[5].pitchPhase)) - + currentTransition.lastAnimation.joints[5].pitchOffset; - yawOscillationLast = currentTransition.lastAnimation.joints[5].yaw - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[5].yawPhase)) - + currentTransition.lastAnimation.joints[5].yawOffset; - rollOscillationLast = currentTransition.lastAnimation.joints[5].roll - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[5].rollPhase)) - + currentTransition.lastAnimation.joints[5].rollOffset; - } else { - - pitchOscillation = currentAnimation.joints[5].pitch * Math.sin( degToRad(( cycle * adjustedFrequency * 2) - + currentAnimation.joints[5].pitchPhase)) + currentAnimation.joints[5].pitchOffset; - - yawOscillation = currentAnimation.joints[5].yaw * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[5].yawPhase)) + currentAnimation.joints[5].yawOffset; - - rollOscillation = currentAnimation.joints[5].roll * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[5].rollPhase)) + currentAnimation.joints[5].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[5].pitch - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency * 2 ) - + currentTransition.lastAnimation.joints[5].pitchPhase)) - + currentTransition.lastAnimation.joints[5].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[5].yaw - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[5].yawPhase)) - + currentTransition.lastAnimation.joints[5].yawOffset; - - rollOscillationLast = currentTransition.lastAnimation.joints[5].roll - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[5].rollPhase)) - + currentTransition.lastAnimation.joints[5].rollOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation ) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation ) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation ) + ((1-transitionProgress) * rollOscillationLast); - - } else { - - pitchOscillation = currentAnimation.joints[5].pitch * Math.sin(degToRad(( cycle * adjustedFrequency * 2) + currentAnimation.joints[5].pitchPhase)) + currentAnimation.joints[5].pitchOffset; - yawOscillation = currentAnimation.joints[5].yaw * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[5].yawPhase)) + currentAnimation.joints[5].yawOffset; - rollOscillation = currentAnimation.joints[5].roll * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[5].rollPhase)) + currentAnimation.joints[5].rollOffset; - } - - // apply spine joint rotations - MyAvatar.setJointData("Spine", Quat.fromPitchYawRollDegrees( pitchOscillation, yawOscillation, rollOscillation )); - - // spine 1 - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[6].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency * 2) + currentAnimation.joints[6].pitchPhase)) + currentAnimation.joints[6].pitchOffset; - yawOscillation = currentAnimation.joints[6].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[6].yawPhase)) + currentAnimation.joints[6].yawOffset; - rollOscillation = currentAnimation.joints[6].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[6].rollPhase)) + currentAnimation.joints[6].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[6].pitch - * Math.sin(degToRad(( walkWheelPosition * 2 ) + currentTransition.lastAnimation.joints[6].pitchPhase)) - + currentTransition.lastAnimation.joints[6].pitchOffset; - yawOscillationLast = currentTransition.lastAnimation.joints[6].yaw - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[6].yawPhase)) - + currentTransition.lastAnimation.joints[6].yawOffset; - rollOscillationLast = currentTransition.lastAnimation.joints[6].roll - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[6].rollPhase)) - + currentTransition.lastAnimation.joints[6].rollOffset; - - } else { - - pitchOscillation = currentAnimation.joints[6].pitch * Math.sin( degToRad(( cycle * adjustedFrequency * 2) - + currentAnimation.joints[6].pitchPhase)) + currentAnimation.joints[6].pitchOffset; - - yawOscillation = currentAnimation.joints[6].yaw * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[6].yawPhase)) + currentAnimation.joints[6].yawOffset; - - rollOscillation = currentAnimation.joints[6].roll * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[6].rollPhase)) + currentAnimation.joints[6].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[6].pitch - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency * 2 ) - + currentTransition.lastAnimation.joints[6].pitchPhase)) - + currentTransition.lastAnimation.joints[6].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[6].yaw - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[6].yawPhase)) - + currentTransition.lastAnimation.joints[6].yawOffset; - - rollOscillationLast = currentTransition.lastAnimation.joints[6].roll - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[6].rollPhase)) - + currentTransition.lastAnimation.joints[6].rollOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - } else { - - pitchOscillation = currentAnimation.joints[6].pitch * Math.sin(degToRad(( cycle * adjustedFrequency * 2) + currentAnimation.joints[6].pitchPhase)) + currentAnimation.joints[6].pitchOffset; - yawOscillation = currentAnimation.joints[6].yaw * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[6].yawPhase)) + currentAnimation.joints[6].yawOffset; - rollOscillation = currentAnimation.joints[6].roll * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[6].rollPhase)) + currentAnimation.joints[6].rollOffset; - } - // apply spine1 joint rotations - MyAvatar.setJointData("Spine1", Quat.fromPitchYawRollDegrees( pitchOscillation, yawOscillation, rollOscillation )); - - // spine 2 - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - pitchOscillation = currentAnimation.joints[7].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency * 2) + currentAnimation.joints[7].pitchPhase)) + currentAnimation.joints[7].pitchOffset; - yawOscillation = currentAnimation.joints[7].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[7].yawPhase)) + currentAnimation.joints[7].yawOffset; - rollOscillation = currentAnimation.joints[7].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[7].rollPhase)) + currentAnimation.joints[7].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[7].pitch - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[7].pitchPhase)) - + currentTransition.lastAnimation.joints[7].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[7].yaw - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[7].yawPhase)) - + currentTransition.lastAnimation.joints[7].yawOffset; - - rollOscillationLast = currentTransition.lastAnimation.joints[7].roll - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[7].rollPhase)) - + currentTransition.lastAnimation.joints[7].rollOffset; - - } else { - - pitchOscillation = currentAnimation.joints[7].pitch - * Math.sin( degToRad(( cycle * adjustedFrequency * 2) - + currentAnimation.joints[7].pitchPhase)) - + currentAnimation.joints[7].pitchOffset; - - yawOscillation = currentAnimation.joints[7].yaw - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[7].yawPhase)) - + currentAnimation.joints[7].yawOffset; - - rollOscillation = currentAnimation.joints[7].roll - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[7].rollPhase)) - + currentAnimation.joints[7].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[7].pitch - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[7].pitchPhase)) - + currentTransition.lastAnimation.joints[7].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[7].yaw - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[7].yawPhase)) - + currentTransition.lastAnimation.joints[7].yawOffset; - - rollOscillationLast = currentTransition.lastAnimation.joints[7].roll - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[7].rollPhase)) - + currentTransition.lastAnimation.joints[7].rollOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation ) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation ) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation ) + ((1-transitionProgress) * rollOscillationLast); - - } else { - - pitchOscillation = currentAnimation.joints[7].pitch * Math.sin(degToRad(( cycle * adjustedFrequency * 2) + currentAnimation.joints[7].pitchPhase)) - + currentAnimation.joints[7].pitchOffset; - - yawOscillation = currentAnimation.joints[7].yaw * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[7].yawPhase)) - + currentAnimation.joints[7].yawOffset; - - rollOscillation = currentAnimation.joints[7].roll * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[7].rollPhase)) - + currentAnimation.joints[7].rollOffset; - } - // apply spine2 joint rotations - MyAvatar.setJointData("Spine2", Quat.fromPitchYawRollDegrees( pitchOscillation, yawOscillation, rollOscillation )); - - if(!armsFree) { - - // shoulders - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - pitchOscillation = currentAnimation.joints[8].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[8].pitchPhase)) + currentAnimation.joints[8].pitchOffset; - - yawOscillation = currentAnimation.joints[8].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[8].yawPhase)); - - rollOscillation = currentAnimation.joints[8].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency * 2) - + currentAnimation.joints[8].rollPhase)) + currentAnimation.joints[8].rollOffset; - - yawOffset = currentAnimation.joints[8].yawOffset; - - - pitchOscillationLast = currentTransition.lastAnimation.joints[8].pitch - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[8].pitchPhase)) - + currentTransition.lastAnimation.joints[8].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[8].yaw - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[8].yawPhase)) - - rollOscillationLast = currentTransition.lastAnimation.joints[8].roll - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[8].rollPhase)) - + currentTransition.lastAnimation.joints[8].rollOffset; - - yawOffsetLast = currentTransition.lastAnimation.joints[8].yawOffset; - - } else { - - pitchOscillation = currentAnimation.joints[8].pitch * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[8].pitchPhase)) + currentAnimation.joints[8].pitchOffset; - - yawOscillation = currentAnimation.joints[8].yaw * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[8].yawPhase)); - - rollOscillation = currentAnimation.joints[8].roll * Math.sin( degToRad(( cycle * adjustedFrequency * 2) - + currentAnimation.joints[8].rollPhase)) + currentAnimation.joints[8].rollOffset; - - yawOffset = currentAnimation.joints[8].yawOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[8].pitch - * Math.sin( degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[8].pitchPhase)) - + currentTransition.lastAnimation.joints[8].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[8].yaw - * Math.sin( degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[8].yawPhase)) - - rollOscillationLast = currentTransition.lastAnimation.joints[8].roll - * Math.sin( degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[8].rollPhase)) - + currentTransition.lastAnimation.joints[8].rollOffset; - - yawOffsetLast = currentTransition.lastAnimation.joints[8].yawOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - yawOffset = (transitionProgress * yawOffset) + ((1-transitionProgress) * yawOffsetLast); - - } else { - - pitchOscillation = currentAnimation.joints[8].pitch * Math.sin(degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[8].pitchPhase)) + currentAnimation.joints[8].pitchOffset; - - yawOscillation = currentAnimation.joints[8].yaw * Math.sin(degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[8].yawPhase)); - - rollOscillation = currentAnimation.joints[8].roll * Math.sin(degToRad(( cycle * adjustedFrequency * 2) - + currentAnimation.joints[8].rollPhase)) + currentAnimation.joints[8].rollOffset; - - yawOffset = currentAnimation.joints[8].yawOffset; - } - - MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(pitchOscillation, yawOscillation + yawOffset, rollOscillation )); - MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(pitchOscillation, yawOscillation - yawOffset, -rollOscillation )); - - // upper arms - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[9].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[9].pitchPhase)); - yawOscillation = currentAnimation.joints[9].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[9].yawPhase)); - rollOscillation = currentAnimation.joints[9].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency * 2) + currentAnimation.joints[9].rollPhase)) + currentAnimation.joints[9].rollOffset; - - pitchOffset = currentAnimation.joints[9].pitchOffset; - yawOffset = currentAnimation.joints[9].yawOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[9].pitch - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[9].pitchPhase)) - - yawOscillationLast = currentTransition.lastAnimation.joints[9].yaw - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[9].yawPhase)) - - rollOscillationLast = currentTransition.lastAnimation.joints[9].roll - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[9].rollPhase)) - + currentTransition.lastAnimation.joints[9].rollOffset; - - pitchOffsetLast = currentTransition.lastAnimation.joints[9].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[9].yawOffset; - - } else { - - pitchOscillation = currentAnimation.joints[9].pitch - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[9].pitchPhase)); - - yawOscillation = currentAnimation.joints[9].yaw - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[9].yawPhase)); - - rollOscillation = currentAnimation.joints[9].roll - * Math.sin(degToRad(( cycle * adjustedFrequency * 2) - + currentAnimation.joints[9].rollPhase)) - + currentAnimation.joints[9].rollOffset; - - pitchOffset = currentAnimation.joints[9].pitchOffset; - yawOffset = currentAnimation.joints[9].yawOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[9].pitch - * Math.sin( degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[9].pitchPhase)) - - yawOscillationLast = currentTransition.lastAnimation.joints[9].yaw - * Math.sin( degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[9].yawPhase)) - - rollOscillationLast = currentTransition.lastAnimation.joints[9].roll - * Math.sin( degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[9].rollPhase)) - + currentTransition.lastAnimation.joints[9].rollOffset; - - pitchOffsetLast = currentTransition.lastAnimation.joints[9].pitchOffset; - yawOffsetLast = currentTransition.lastAnimation.joints[9].yawOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - pitchOffset = (transitionProgress * pitchOffset) + ((1-transitionProgress) * pitchOffsetLast); - yawOffset = (transitionProgress * yawOffset) + ((1-transitionProgress) * yawOffsetLast); - - } else { - - pitchOscillation = currentAnimation.joints[9].pitch - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[9].pitchPhase)); - - yawOscillation = currentAnimation.joints[9].yaw - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[9].yawPhase)); - - rollOscillation = currentAnimation.joints[9].roll - * Math.sin( degToRad(( cycle * adjustedFrequency * 2) - + currentAnimation.joints[9].rollPhase)) - + currentAnimation.joints[9].rollOffset; - - pitchOffset = currentAnimation.joints[9].pitchOffset; - yawOffset = currentAnimation.joints[9].yawOffset; - - } - MyAvatar.setJointData("RightArm", Quat.fromPitchYawRollDegrees( -pitchOscillation + pitchOffset, yawOscillation - yawOffset, rollOscillation )); - MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees( pitchOscillation + pitchOffset, yawOscillation + yawOffset, -rollOscillation )); - - // forearms - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[10].pitch - * Math.sin( degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[10].pitchPhase )) - + currentAnimation.joints[10].pitchOffset; - - yawOscillation = currentAnimation.joints[10].yaw - * Math.sin( degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[10].yawPhase )); - - rollOscillation = currentAnimation.joints[10].roll - * Math.sin( degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[10].rollPhase )); - - yawOffset = currentAnimation.joints[10].yawOffset; - rollOffset = currentAnimation.joints[10].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[10].pitch - * Math.sin( degToRad(( walkWheelPosition ) - + currentTransition.lastAnimation.joints[10].pitchPhase)) - + currentTransition.lastAnimation.joints[10].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[10].yaw - * Math.sin( degToRad(( walkWheelPosition ) - + currentTransition.lastAnimation.joints[10].yawPhase)); - - rollOscillationLast = currentTransition.lastAnimation.joints[10].roll - * Math.sin( degToRad(( walkWheelPosition ) - + currentTransition.lastAnimation.joints[10].rollPhase)); - - yawOffsetLast = currentTransition.lastAnimation.joints[10].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[10].rollOffset; - - } else { - - pitchOscillation = currentAnimation.joints[10].pitch - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[10].pitchPhase )) - + currentAnimation.joints[10].pitchOffset; - - yawOscillation = currentAnimation.joints[10].yaw - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[10].yawPhase )); - - rollOscillation = currentAnimation.joints[10].roll - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[10].rollPhase )); - - yawOffset = currentAnimation.joints[10].yawOffset; - rollOffset = currentAnimation.joints[10].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[10].pitch - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[10].pitchPhase)) - + currentTransition.lastAnimation.joints[10].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[10].yaw - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[10].yawPhase)); - - rollOscillationLast = currentTransition.lastAnimation.joints[10].roll - * Math.sin( degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[10].rollPhase)); - - yawOffsetLast = currentTransition.lastAnimation.joints[10].yawOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[10].rollOffset; - } - - // blend the previous and next - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = -(transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - yawOffset = (transitionProgress * yawOffset) + ((1-transitionProgress) * yawOffsetLast); - rollOffset = (transitionProgress * rollOffset) + ((1-transitionProgress) * rollOffsetLast); - - } else { - - pitchOscillation = currentAnimation.joints[10].pitch - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[10].pitchPhase )) - + currentAnimation.joints[10].pitchOffset; - - yawOscillation = currentAnimation.joints[10].yaw - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[10].yawPhase )); - - rollOscillation = currentAnimation.joints[10].roll - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[10].rollPhase )); - - yawOffset = currentAnimation.joints[10].yawOffset; - rollOffset = currentAnimation.joints[10].rollOffset; - } - - // apply forearms rotations - MyAvatar.setJointData("RightForeArm", Quat.fromPitchYawRollDegrees( pitchOscillation, yawOscillation + yawOffset, rollOscillation + rollOffset )); - MyAvatar.setJointData("LeftForeArm", Quat.fromPitchYawRollDegrees( pitchOscillation, yawOscillation - yawOffset, rollOscillation - rollOffset )); - - // hands - var sideStepSign = 1; - if(INTERNAL_STATE===SIDE_STEPPING) { - sideStepSign = 1; - } - if(currentTransition!==null) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = currentAnimation.joints[11].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[11].pitchPhase)) + currentAnimation.joints[11].pitchOffset; - yawOscillation = currentAnimation.joints[11].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[11].yawPhase)) + currentAnimation.joints[11].yawOffset; - rollOscillation = currentAnimation.joints[11].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) + currentAnimation.joints[11].rollPhase)) ; - - pitchOscillationLast = currentTransition.lastAnimation.joints[11].pitch - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[11].pitchPhase)) - + currentTransition.lastAnimation.joints[11].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[11].yaw - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[11].yawPhase)) - + currentTransition.lastAnimation.joints[11].yawOffset; - - rollOscillationLast = currentTransition.lastAnimation.joints[11].roll - * Math.sin(degToRad( walkWheelPosition + currentTransition.lastAnimation.joints[11].rollPhase)) - - rollOffset = currentAnimation.joints[11].rollOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[11].rollOffset; - - } else { - - pitchOscillation = currentAnimation.joints[11].pitch - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[11].pitchPhase)) - + currentAnimation.joints[11].pitchOffset; - - yawOscillation = currentAnimation.joints[11].yaw - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[11].yawPhase)) - + currentAnimation.joints[11].yawOffset; - - rollOscillation = currentAnimation.joints[11].roll - * Math.sin( degToRad(( cycle * adjustedFrequency ) - + currentAnimation.joints[11].rollPhase)); - - rollOffset = currentAnimation.joints[11].rollOffset; - - pitchOscillationLast = currentTransition.lastAnimation.joints[11].pitch - * Math.sin(degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[11].pitchPhase)) - + currentTransition.lastAnimation.joints[11].pitchOffset; - - yawOscillationLast = currentTransition.lastAnimation.joints[11].yaw - * Math.sin(degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[11].yawPhase)) - + currentTransition.lastAnimation.joints[11].yawOffset; - - rollOscillationLast = currentTransition.lastAnimation.joints[11].roll - * Math.sin(degToRad( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency - + currentTransition.lastAnimation.joints[11].rollPhase)) - - rollOffset = currentAnimation.joints[11].rollOffset; - rollOffsetLast = currentTransition.lastAnimation.joints[11].rollOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - rollOffset = (transitionProgress * rollOffset) + ((1-transitionProgress) * rollOffsetLast); - - } else { - - pitchOscillation = currentAnimation.joints[11].pitch * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[11].pitchPhase)) + currentAnimation.joints[11].pitchOffset; - yawOscillation = currentAnimation.joints[11].yaw * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[11].yawPhase)) + currentAnimation.joints[11].yawOffset; - rollOscillation = currentAnimation.joints[11].roll * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[11].rollPhase)); - - rollOffset = currentAnimation.joints[11].rollOffset; - } - - // set the hand rotations - MyAvatar.setJointData("RightHand", Quat.fromPitchYawRollDegrees( sideStepSign * pitchOscillation, yawOscillation, rollOscillation + rollOffset)); - MyAvatar.setJointData("LeftHand", Quat.fromPitchYawRollDegrees( pitchOscillation, -yawOscillation, rollOscillation - rollOffset)); - - } // end if(!armsFree) - - // head (includes neck joint) - currently zeroed out in STANDING animation files by request - if( currentTransition !== null ) { - - if(currentTransition.walkingAtStart) { - - pitchOscillation = 0.5 * currentAnimation.joints[12].pitch * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency * 2) - + currentAnimation.joints[12].pitchPhase)) + currentAnimation.joints[12].pitchOffset; - - yawOscillation = 0.5 * currentAnimation.joints[12].yaw * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[12].yawPhase)) + currentAnimation.joints[12].yawOffset; - - rollOscillation = 0.5 * currentAnimation.joints[12].roll * Math.sin(degToRad(( cumulativeTime * currentAnimation.settings.baseFrequency ) - + currentAnimation.joints[12].rollPhase)) + currentAnimation.joints[12].rollOffset; - - pitchOscillationLast = 0.5 * currentTransition.lastAnimation.joints[12].pitch - * Math.sin(degToRad(( walkWheelPosition * 2) + currentTransition.lastAnimation.joints[12].pitchPhase)) - + currentTransition.lastAnimation.joints[12].pitchOffset; - - yawOscillationLast = 0.5 * currentTransition.lastAnimation.joints[12].yaw - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[12].yawPhase)) - + currentTransition.lastAnimation.joints[12].yawOffset; - - rollOscillationLast = 0.5 * currentTransition.lastAnimation.joints[12].roll - * Math.sin(degToRad(( walkWheelPosition ) + currentTransition.lastAnimation.joints[12].rollPhase)) - + currentTransition.lastAnimation.joints[12].rollOffset; - - } else { - - pitchOscillation = 0.5 * currentAnimation.joints[12].pitch * Math.sin(degToRad(( cycle * adjustedFrequency * 2) + currentAnimation.joints[12].pitchPhase)) + currentAnimation.joints[12].pitchOffset; - yawOscillation = 0.5 * currentAnimation.joints[12].yaw * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[12].yawPhase)) + currentAnimation.joints[12].yawOffset; - rollOscillation = 0.5 * currentAnimation.joints[12].roll * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[12].rollPhase)) + currentAnimation.joints[12].rollOffset; - - pitchOscillationLast = 0.5 * currentTransition.lastAnimation.joints[12].pitch - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency * 2) - + currentTransition.lastAnimation.joints[12].pitchPhase)) - + currentTransition.lastAnimation.joints[12].pitchOffset; - - yawOscillationLast = 0.5 * currentTransition.lastAnimation.joints[12].yaw - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[12].yawPhase)) - + currentTransition.lastAnimation.joints[12].yawOffset; - - rollOscillationLast = 0.5 * currentTransition.lastAnimation.joints[12].roll - * Math.sin(degToRad(( cumulativeTime * currentTransition.lastAnimation.settings.baseFrequency ) - + currentTransition.lastAnimation.joints[12].rollPhase)) - + currentTransition.lastAnimation.joints[12].rollOffset; - } - - pitchOscillation = (transitionProgress * pitchOscillation) + ((1-transitionProgress) * pitchOscillationLast); - yawOscillation = (transitionProgress * yawOscillation) + ((1-transitionProgress) * yawOscillationLast); - rollOscillation = (transitionProgress * rollOscillation) + ((1-transitionProgress) * rollOscillationLast); - - } else { - - pitchOscillation = 0.5 * currentAnimation.joints[12].pitch * Math.sin(degToRad(( cycle * adjustedFrequency * 2) + currentAnimation.joints[12].pitchPhase)) + currentAnimation.joints[12].pitchOffset; - yawOscillation = 0.5 * currentAnimation.joints[12].yaw * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[12].yawPhase)) + currentAnimation.joints[12].yawOffset; - rollOscillation = 0.5 * currentAnimation.joints[12].roll * Math.sin(degToRad(( cycle * adjustedFrequency ) + currentAnimation.joints[12].rollPhase)) + currentAnimation.joints[12].rollOffset; - } - - MyAvatar.setJointData( "Head", Quat.fromPitchYawRollDegrees( pitchOscillation, yawOscillation, rollOscillation )); - MyAvatar.setJointData( "Neck", Quat.fromPitchYawRollDegrees( pitchOscillation, yawOscillation, rollOscillation )); -} - - - -// Bezier function for applying to transitions - src: Dan Pupius (www.pupius.net) http://13thparallel.com/archive/bezier-curves/ -Coord = function (x,y) { - if(!x) var x=0; - if(!y) var y=0; - return {x: x, y: y}; -} - -function B1(t) { return t*t*t } -function B2(t) { return 3*t*t*(1-t) } -function B3(t) { return 3*t*(1-t)*(1-t) } -function B4(t) { return (1-t)*(1-t)*(1-t) } - -function getBezier(percent,C1,C2,C3,C4) { - var pos = new Coord(); - pos.x = C1.x*B1(percent) + C2.x*B2(percent) + C3.x*B3(percent) + C4.x*B4(percent); - pos.y = C1.y*B1(percent) + C2.y*B2(percent) + C3.y*B3(percent) + C4.y*B4(percent); - return pos; -} - -// Butterworth LP filter - coeffs calculated using: http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html -var NZEROS = 8; -var NPOLES = 8; -var GAIN = 17.40692157; -var xv = [0,0,0,0,0,0,0,0,0]; //xv.length = NZEROS+1; -var yv = [0,0,0,0,0,0,0,0,0]; //yv.length = NPOLES+1; - -function filterButterworth(nextInputValue) -{ - xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6]; xv[6] = xv[7]; xv[7] = xv[8]; - xv[8] = nextInputValue / GAIN; - yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6]; yv[6] = yv[7]; yv[7] = yv[8]; - yv[8] = (xv[0] + xv[8]) + 8 * (xv[1] + xv[7]) + 28 * (xv[2] + xv[6]) - + 56 * (xv[3] + xv[5]) + 70 * xv[4] - + ( -0.0033008230 * yv[0]) + ( -0.0440409341 * yv[1]) - + ( -0.2663485333 * yv[2]) + ( -0.9570250765 * yv[3]) - + ( -2.2596729000 * yv[4]) + ( -3.6088345059 * yv[5]) - + ( -3.9148571397 * yv[6]) + ( -2.6527135283 * yv[7]); - return yv[8]; -} - -// the faster we go, the further we lean forward. the angle is calcualted here -var leanAngles = []; // smooth out and add damping with simple averaging filter. -leanAngles.length = 15; - -function getLeanPitch(velocity) { - - if(velocity>TERMINAL_VELOCITY) velocity=TERMINAL_VELOCITY; - var leanProgress = velocity / TERMINAL_VELOCITY; - var responseSharpness = 1.8; - if(principleDirection==DIRECTION_BACKWARDS) responseSharpness = 3.6; // lean back a bit extra when walking backwards - var leanProgressBezier = getBezier((1-leanProgress),{x:0,y:0},{x:0,y:responseSharpness},{x:0,y:1},{x:1,y:1}).y; - - // simple averaging filter seems to give best results - leanAngles.push(leanProgressBezier); - leanAngles.shift(); // FIFO - var totalLeanAngles = 0; - for(ea in leanAngles) totalLeanAngles += leanAngles[ea]; - var leanProgressAverageFiltered = totalLeanAngles / leanAngles.length; - - // calculate final return value - var leanPitchFinal = 0; - if(principleDirection===DIRECTION_BACKWARDS) { - leanPitchFinal = -currentAnimation.settings.flyingHipsPitch * leanProgressAverageFiltered;// + finalAccelerationResponse; - } else { - leanPitchFinal = currentAnimation.settings.flyingHipsPitch * leanProgressAverageFiltered;// + finalAccelerationResponse; - } - return leanPitchFinal; -} - -// calculate the angle at which to bank into corners when turning -var leanRollAngles = []; // smooth out and add damping with simple averaging filter -leanRollAngles.length = 25; - -var angularVelocities = []; // keep a record of the last few so can filter out spurious values -angularVelocities.length = 5; - -function getLeanRoll(deltaTime, velocity) { - - // what's our current anglular velocity? - var angularVelocityMax = 70; // from observation - var currentOrientationVec3 = Quat.safeEulerAngles(MyAvatar.orientation); - var lastOrientationVec3 = Quat.safeEulerAngles(lastOrientation); - var deltaYaw = lastOrientationVec3.y-currentOrientationVec3.y; - lastOrientation = MyAvatar.orientation; - - var angularVelocity = deltaYaw / deltaTime; - if(angularVelocity>angularVelocityMax) angularVelocity = angularVelocityMax; - if(angularVelocity<-angularVelocityMax) angularVelocity = -angularVelocityMax; - - // filter the angular velocity for a nicer response and a bit of wobble (intentional overshoot / ringing) - angularVelocity = filterButterworth(angularVelocity); - - var turnSign = 1; - if(angularVelocity<0) turnSign = -1; - if(principleDirection===DIRECTION_BACKWARDS) - turnSign *= -1; - - // calculate the amount of roll based on both angular and linear velocities - if(velocity>TERMINAL_VELOCITY) velocity = TERMINAL_VELOCITY; - var leanRollProgress = (velocity / TERMINAL_VELOCITY) * (Math.abs(angularVelocity) / angularVelocityMax); - - // apply our response curve - var leanRollProgressBezier = getBezier((1-leanRollProgress),{x:0,y:0},{x:0,y:2.5},{x:0,y:1},{x:1,y:1}).y; - - // simple averaging filter - leanRollAngles.push(turnSign * leanRollProgressBezier); - leanRollAngles.shift(); // FIFO - var totalLeanRollAngles = 0; - for(var ea in leanRollAngles) totalLeanRollAngles += leanRollAngles[ea]; - var leanRollProgressAverageFiltered = totalLeanRollAngles / leanRollAngles.length; - - return currentAnimation.settings.maxBankingAngle * leanRollProgressAverageFiltered; -} - -// set up the interface components, update the internal state and kick off any transitions -function setInternalState(newInternalState) { - - switch(newInternalState) { - - case WALKING: - - if(!minimised) doStandardMenu(); - INTERNAL_STATE = WALKING; - return; - - case FLYING: - - if(!minimised) doStandardMenu(); - INTERNAL_STATE = FLYING; - return; - - case SIDE_STEPPING: - - if(!minimised) doStandardMenu(); - INTERNAL_STATE = SIDE_STEPPING; - return; - - case CONFIG_WALK_STYLES: - - INTERNAL_STATE = CONFIG_WALK_STYLES; - currentAnimation = selectedWalk; - if(!minimised) { - hidebuttonOverlays(); - hideJointControls(); - showFrontPanelButtons(false); - showWalkStyleButtons(true); - setBackground(controlsBackgroundWalkEditStyles); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configWalkStylesButtonSelected); - setButtonOverlayVisible(configWalkTweaksButton); - setButtonOverlayVisible(configWalkJointsButton); - setButtonOverlayVisible(backButton); - setSliderThumbsVisible(false); - } - return; - - case CONFIG_WALK_TWEAKS: - - INTERNAL_STATE = CONFIG_WALK_TWEAKS; - currentAnimation = selectedWalk; - if(!minimised) { - hidebuttonOverlays(); - hideJointControls(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditTweaks); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configWalkStylesButton); - setButtonOverlayVisible(configWalkTweaksButtonSelected); - setButtonOverlayVisible(configWalkJointsButton); - setButtonOverlayVisible(backButton); - initialiseWalkTweaks(); - } - return; - - case CONFIG_WALK_JOINTS: - - INTERNAL_STATE = CONFIG_WALK_JOINTS; - currentAnimation = selectedWalk; - if(!minimised) { - hidebuttonOverlays(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditJoints); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configWalkStylesButton); - setButtonOverlayVisible(configWalkTweaksButton); - setButtonOverlayVisible(configWalkJointsButtonSelected); - setButtonOverlayVisible(backButton); - initialiseJointsEditingPanel(selectedJointIndex); - } - return; - - case CONFIG_STANDING: - - INTERNAL_STATE = CONFIG_STANDING; - currentAnimation = selectedStand; - if(!minimised) { - hidebuttonOverlays(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditJoints); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configSideStepRightButton); - setButtonOverlayVisible(configSideStepLeftButton); - setButtonOverlayVisible(configStandButtonSelected); - setButtonOverlayVisible(backButton); - initialiseJointsEditingPanel(selectedJointIndex); - } - return; - - case CONFIG_SIDESTEP_LEFT: - - INTERNAL_STATE = CONFIG_SIDESTEP_LEFT; - currentAnimation = selectedSideStepLeft; - if(!minimised) { - hidebuttonOverlays(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditJoints); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configSideStepRightButton); - setButtonOverlayVisible(configSideStepLeftButtonSelected); - setButtonOverlayVisible(configStandButton); - setButtonOverlayVisible(backButton); - initialiseJointsEditingPanel(selectedJointIndex); - } - return; - - case CONFIG_SIDESTEP_RIGHT: - - INTERNAL_STATE = CONFIG_SIDESTEP_RIGHT; - currentAnimation = selectedSideStepRight; - if(!minimised) { - hidebuttonOverlays(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditJoints); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configSideStepRightButtonSelected); - setButtonOverlayVisible(configSideStepLeftButton); - setButtonOverlayVisible(configStandButton); - setButtonOverlayVisible(backButton); - initialiseJointsEditingPanel(selectedJointIndex); - } - return; - - case CONFIG_FLYING: - - INTERNAL_STATE = CONFIG_FLYING; - currentAnimation = selectedFly; - if(!minimised) { - hidebuttonOverlays(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditJoints); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configFlyingUpButton); - setButtonOverlayVisible(configFlyingDownButton); - setButtonOverlayVisible(configFlyingButtonSelected); - setButtonOverlayVisible(backButton); - initialiseJointsEditingPanel(selectedJointIndex); - } - return; - - case CONFIG_FLYING_UP: - - INTERNAL_STATE = CONFIG_FLYING_UP; - currentAnimation = selectedFlyUp; - if(!minimised) { - hidebuttonOverlays(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditJoints); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configFlyingUpButtonSelected); - setButtonOverlayVisible(configFlyingDownButton); - setButtonOverlayVisible(configFlyingButton); - setButtonOverlayVisible(backButton); - initialiseJointsEditingPanel(selectedJointIndex); - } - return; - - case CONFIG_FLYING_DOWN: - - INTERNAL_STATE = CONFIG_FLYING_DOWN; - currentAnimation = selectedFlyDown; - if(!minimised) { - hidebuttonOverlays(); - showFrontPanelButtons(false); - showWalkStyleButtons(false); - setBackground(controlsBackgroundWalkEditJoints); - setButtonOverlayVisible(onButton); - setButtonOverlayVisible(configFlyingUpButton); - setButtonOverlayVisible(configFlyingDownButtonSelected); - setButtonOverlayVisible(configFlyingButton); - setButtonOverlayVisible(backButton); - initialiseJointsEditingPanel(selectedJointIndex); - } - return; - - case STANDING: - default: - - INTERNAL_STATE = STANDING; - if(!minimised) doStandardMenu(); - - // initialisation - runs at script startup only - if(strideLength===0) { - - if(principleDirection===DIRECTION_BACKWARDS) - strideLength = selectedWalk.calibration.strideLengthBackwards; - else - strideLength = selectedWalk.calibration.strideLengthForwards; - - curlFingers(); - } - return; - } -} // Main loop - -// stabilising vars - most state changes are preceded by a couple of hints that they are about to happen rather than -// momentarilly switching between states (causes flicker), we count the number of hints in a row before actually changing state -var standHints = 0; -var walkHints = 0; -var flyHints = 0; -var requiredHints = 2; // tweakable - debounce state changes - how many times do we get a state change request in a row before we actually change state? (used to be 4 or 5) -var principleDirection = 0; - -// helper function for stats output -function directionAsString(directionEnum) { - - switch(directionEnum) { - case DIRECTION_UP: return 'Up'; - case DIRECTION_DOWN: return 'Down'; - case DIRECTION_LEFT: return 'Left'; - case DIRECTION_RIGHT: return 'Right'; - case DIRECTION_FORWARDS: return 'Forwards'; - case DIRECTION_BACKWARDS: return 'Backwards'; - default: return 'Unknown'; - } -} -// helper function for stats output -function internalStateAsString(internalState) { - - switch(internalState) { - case STANDING: return 'Standing'; - case WALKING: return 'Walking'; - case SIDE_STEPPING: return 'Side Stepping'; - case FLYING: return 'Flying'; - default: return 'Editing'; - } -} - Script.update.connect(function(deltaTime) { - if(powerOn) { + if (state.powerOn) { - frameStartTime = new Date().getTime(); - cumulativeTime += deltaTime; - nFrames++; - var speed = 0; + motion.frameStartTime = new Date().getTime(); + motion.cumulativeTime += deltaTime; + motion.nFrames++; + var speed = 0; - // firstly check for editing modes, as these require no positioning calculations - var editing = false; - switch(INTERNAL_STATE) { + // check for editing modes first, as these require no positioning calculations + switch (state.currentState) { - case CONFIG_WALK_STYLES: - currentAnimation = selectedWalk; - animateAvatar(deltaTime, speed, principleDirection); - editing = true; - break; - case CONFIG_WALK_TWEAKS: - currentAnimation = selectedWalk; - animateAvatar(deltaTime, speed, DIRECTION_FORWARDS); - editing = true; - break; - case CONFIG_WALK_JOINTS: - currentAnimation = selectedWalk; - animateAvatar(deltaTime, speed, DIRECTION_FORWARDS); - editing = true; - break; - case CONFIG_STANDING: - currentAnimation = selectedStand; - animateAvatar(deltaTime, speed, DIRECTION_FORWARDS); - editing = true; - break; - case CONFIG_SIDESTEP_LEFT: - currentAnimation = selectedSideStepLeft; - animateAvatar(deltaTime, speed, DIRECTION_LEFT); - editing = true; - break; - case CONFIG_SIDESTEP_RIGHT: - currentAnimation = selectedSideStepRight; - animateAvatar(deltaTime, speed, DIRECTION_RIGHT); - editing = true; - break; - case CONFIG_FLYING: - currentAnimation = selectedFly; - animateAvatar(deltaTime, speed, DIRECTION_FORWARDS); - editing = true; - break; - case CONFIG_FLYING_UP: - currentAnimation = selectedFlyUp; - animateAvatar(deltaTime, speed, DIRECTION_UP); - editing = true; - break; - case CONFIG_FLYING_DOWN: - currentAnimation = selectedFlyDown; - animateAvatar(deltaTime, speed, DIRECTION_DOWN); - editing = true; - break; - default: - break; - } + case state.EDIT_WALK_STYLES: + motion.curAnim = motion.selWalk; + animateAvatar(deltaTime, speed); + break; - // we have to declare these vars here ( outside 'if(!editing)' ), so they are still in scope - // when we record the frame's data and when we do the stats update at the end - var deltaX = 0; - var deltaY = 0; - var deltaZ = 0; - var acceleration = { x:0, y:0, z:0 }; - var accelerationJS = MyAvatar.getAcceleration(); + case state.EDIT_WALK_TWEAKS: + motion.curAnim = motion.selWalk; + animateAvatar(deltaTime, speed); + break; - // calculate overriding (local) direction of translation for use later when decide which animation should be played - var inverseRotation = Quat.inverse(MyAvatar.orientation); - var localVelocity = Vec3.multiplyQbyV(inverseRotation, MyAvatar.getVelocity()); + case state.EDIT_WALK_JOINTS: + motion.curAnim = motion.selWalk; + animateAvatar(deltaTime, speed); + break; - if(!editing) { + case state.EDIT_STANDING: + motion.curAnim = motion.selStand; + motion.direction = FORWARDS; + animateAvatar(deltaTime, speed); + break; - // the first thing to do is find out how fast we're going, - // what our acceleration is and which direction we're principly moving in + case state.EDIT_SIDESTEP_LEFT: + motion.curAnim = motion.selSideStepLeft; + motion.direction = LEFT; + animateAvatar(deltaTime, speed); + break; - // calcualte (local) change in velocity - var velocity = MyAvatar.getVelocity(); - speed = Vec3.length(velocity); + case state.EDIT_SIDESTEP_RIGHT: + motion.curAnim = motion.selSideStepRight; + motion.direction = RIGHT; + animateAvatar(deltaTime, speed); + break; - // determine the candidate animation to play - var actionToTake = 0; - if( speed < 0.5) { - actionToTake = STANDING; - standHints++; - } - else if( speed < FLYING_SPEED ) { - actionToTake = WALKING; - walkHints++; - } - else if( speed >= FLYING_SPEED ) { - actionToTake = FLYING; - flyHints++; - } + case state.EDIT_FLYING: + motion.curAnim = motion.selFly; + motion.direction = FORWARDS; + animateAvatar(deltaTime, speed); + break; - deltaX = localVelocity.x; - deltaY = localVelocity.y; - deltaZ = -localVelocity.z; + case state.EDIT_FLYING_UP: + motion.curAnim = motion.selFlyUp; + motion.direction = UP; + animateAvatar(deltaTime, speed); + break; + + case state.EDIT_FLYING_DOWN: + motion.curAnim = motion.selFlyDown; + motion.direction = DOWN; + animateAvatar(deltaTime, speed); + break; + + default: + break; + } + + // calcualte velocity and speed + var velocity = MyAvatar.getVelocity(); + speed = Vec3.length(velocity); + + if (motion.curTransition !== nullTransition) { + + // finish any live transition before changing state + animateAvatar(deltaTime, speed); + return; + } + var localVelocity = {x: 0, y: 0, z: 0}; + if (speed > 0) + localVelocity = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), velocity); + + if (!state.editing) { + + // determine the candidate animation state + var actionToTake = undefined; + if (speed < 0.05) actionToTake = state.STANDING; // as per MIN_AVATAR_SPEED, MyAvatar.cpp + else if (speed < TAKE_FLIGHT_SPEED) actionToTake = state.WALKING; + else if (speed >= TAKE_FLIGHT_SPEED) actionToTake = state.FLYING; // determine the principle direction - if(Math.abs(deltaX)>Math.abs(deltaY) - &&Math.abs(deltaX)>Math.abs(deltaZ)) { - if(deltaX<0) { - principleDirection = DIRECTION_RIGHT; - } else { - principleDirection = DIRECTION_LEFT; - } - } - else if(Math.abs(deltaY)>Math.abs(deltaX) - &&Math.abs(deltaY)>Math.abs(deltaZ)) { - if(deltaY>0) { - principleDirection = DIRECTION_UP; - } - else { - principleDirection = DIRECTION_DOWN; - } - } - else if(Math.abs(deltaZ)>Math.abs(deltaX) - &&Math.abs(deltaZ)>Math.abs(deltaY)) { - if(deltaZ>0) { - principleDirection = DIRECTION_FORWARDS; - } else { - principleDirection = DIRECTION_BACKWARDS; - } - } + if (Math.abs(localVelocity.x) > Math.abs(localVelocity.y) && + Math.abs(localVelocity.x) > Math.abs(localVelocity.z)) { - // NB: this section will change significantly once we are ground plane aware - // it will change even more once we have uneven surfaces to deal with + if (localVelocity.x < 0) motion.direction = LEFT; + else motion.direction = RIGHT; + + } else if (Math.abs(localVelocity.y) > Math.abs(localVelocity.x) && + Math.abs(localVelocity.y) > Math.abs(localVelocity.z)) { + + if (localVelocity.y > 0) motion.direction = UP; + else motion.direction = DOWN; + + } else if (Math.abs(localVelocity.z) > Math.abs(localVelocity.x) && + Math.abs(localVelocity.z) > Math.abs(localVelocity.y)) { + + if (localVelocity.z < 0) motion.direction = FORWARDS; + else motion.direction = BACKWARDS; + } // maybe at walking speed, but sideways? - if( actionToTake === WALKING && - ( principleDirection === DIRECTION_LEFT || - principleDirection === DIRECTION_RIGHT )) { - - actionToTake = SIDE_STEPPING; - } - - // maybe at walking speed, but flying up? - if( actionToTake === WALKING && - ( principleDirection === DIRECTION_UP )) { - - actionToTake = FLYING; - standHints--; - flyHints++; - } - - // maybe at walking speed, but flying down? - if( actionToTake === WALKING && - ( principleDirection === DIRECTION_DOWN )) { - - actionToTake = FLYING; - standHints--; - flyHints++; - } - - // log this frame's motion for later reference - var accelerationX = ( framesHistory.recentMotions[0].velocity.x - localVelocity.x ) / deltaTime; - var accelerationY = ( localVelocity.y - framesHistory.recentMotions[0].velocity.y ) / deltaTime; - var accelerationZ = ( framesHistory.recentMotions[0].velocity.z - localVelocity.z ) / deltaTime; - acceleration = {x:accelerationX, y:accelerationY, z:accelerationZ}; + if (actionToTake === state.WALKING && + (motion.direction === LEFT || + motion.direction === RIGHT)) + actionToTake = state.SIDE_STEP; + // maybe at walking speed, but flying up or down? + if (actionToTake === state.WALKING && + (motion.direction === UP))// || + //motion.direction === DOWN)) + actionToTake = state.FLYING; // select appropriate animation and initiate Transition if required - switch(actionToTake) { + switch (actionToTake) { - case STANDING: + case state.STANDING: - if( standHints > requiredHints || INTERNAL_STATE===STANDING) { // wait for a few consecutive hints (17mS each) + // do we need to change state? + if (state.currentState !== state.STANDING) { - standHints = 0; - walkHints = 0; - flyHints = 0; + switch (motion.curAnim) { - // do we need to change state? - if( INTERNAL_STATE!==STANDING ) { + case motion.selWalk: - // initiate the transition - if(currentTransition) { - delete currentTransition; - currentTransition = null; - } + // Walking to standing + motion.curTransition = new Transition( + motion.curAnim, + motion.selWalk, + [], 0.25, + {x: 0.1, y: 0.5}, + {x: -0.25, y: 1.22}); + break; - switch(currentAnimation) { + case motion.selSideStepLeft: + case motion.selSideStepRight: - case selectedWalk: + break; - // Walking to Standing - var timeWalking = new Date().getTime() - framesHistory.lastWalkStartTime; + default: - var bezierCoeffsOne = {x:0.0, y:1.0}; - var bezierCoeffsTwo = {x:0.0, y:1.0}; - var transitionTime = 0.4; + // flying to standing + motion.curTransition = new Transition( + motion.curAnim, + motion.selStand, + [], 0.25, + {x: 0.5, y: 0.08}, + {x: 0.28, y: 1}); + break; + } + state.setInternalState(state.STANDING); + motion.curAnim = motion.selStand; + } + animateAvatar(deltaTime, speed); + break; - // very different curves for incremental steps - if( timeWalking < 550 ) { - bezierCoeffsOne = {x:0.63, y:0.17}; - bezierCoeffsTwo = {x:0.77, y:0.3}; - transitionTime = 0.75; - } - currentTransition = new Transition( currentAnimation, selectedStand, [], transitionTime, bezierCoeffsOne, bezierCoeffsTwo ); - break; + case state.WALKING: + if (state.currentState !== state.WALKING) { - case selectedSideStepLeft: - case selectedSideStepRight: + if (motion.direction === BACKWARDS) + motion.walkWheelPos = motion.selWalk.calibration.startAngleBackwards; + + else motion.walkWheelPos = motion.selWalk.calibration.startAngleForwards; + + switch (motion.curAnim) { + + case motion.selStand: + + // Standing to Walking + motion.curTransition = new Transition( + motion.curAnim, + motion.selWalk, + [], 0.1, + {x: 0.5, y: 0.1}, + {x: 0.5, y: 0.9}); + break; + + case motion.selSideStepLeft: + case motion.selSideStepRight: + + break; + + default: + + // Flying to Walking + motion.curTransition = new Transition( + motion.curAnim, + motion.selWalk, + [], 0.1, + {x: 0.24, y: 0.03}, + {x: 0.42, y: 1.0}); + break; + } + state.setInternalState(state.WALKING); + } + motion.curAnim = motion.selWalk; + animateAvatar(deltaTime, speed); + break; + + case state.SIDE_STEP: + + var selSideStep = 0; + if (motion.direction === LEFT) { + + if (motion.lastDirection !== LEFT) + motion.walkWheelPos = motion.selSideStepLeft.calibration.cycleStart; + selSideStep = motion.selSideStepLeft; + + } else { + + if (motion.lastDirection !== RIGHT) + motion.walkWheelPos = motion.selSideStepRight.calibration.cycleStart; + selSideStep = motion.selSideStepRight; + } + + if (state.currentState !== state.SIDE_STEP) { + + if (motion.direction === LEFT) { + + motion.walkWheelPos = motion.selSideStepLeft.calibration.cycleStart; + switch (motion.curAnim) { + + case motion.selStand: break; default: - currentTransition = new Transition(currentAnimation, selectedStand, [], 0.3, {x:0.5,y:0.08}, {x:0.28,y:1}); break; } - setInternalState(STANDING); - currentAnimation = selectedStand; - - } - animateAvatar(1,0,principleDirection); - } - break; - - case WALKING: - case SIDE_STEPPING: - if( walkHints > requiredHints || - INTERNAL_STATE===WALKING || - INTERNAL_STATE===SIDE_STEPPING ) { // wait for few consecutive hints (17mS each) - - standHints = 0; - walkHints = 0; - flyHints = 0; - - if( actionToTake === WALKING && INTERNAL_STATE !== WALKING) { - - // initiate the transition - if(currentTransition) { - delete currentTransition; - currentTransition = null; - } - - // set the appropriate start position for the walk wheel - if( principleDirection === DIRECTION_BACKWARDS ) { - - walkWheelPosition = selectedWalk.settings.startAngleBackwards; - - } else { - - walkWheelPosition = selectedWalk.settings.startAngleForwards; - } - - switch(currentAnimation) { - - case selectedStand: - - // Standing to Walking - currentTransition = new Transition(currentAnimation, selectedWalk, [], 0.25, {x:0.5,y:0.08}, {x:0.05,y:0.75}); - break; - - case selectedSideStepLeft: - case selectedSideStepRight: - - break; - - default: - - currentTransition = new Transition(currentAnimation, selectedWalk, [], 0.3, {x:0.5,y:0.08}, {x:0.05,y:0.75}); - break; - } - framesHistory.lastWalkStartTime = new Date().getTime(); - setInternalState(WALKING); - currentAnimation = selectedWalk; - } - else if(actionToTake===SIDE_STEPPING) { - - var selectedSideStep = selectedSideStepRight; - if( principleDirection === DIRECTION_LEFT ) { - - selectedSideStep = selectedSideStepLeft; - - } else { - - selectedSideStep = selectedSideStepRight; - } - - if( INTERNAL_STATE !== SIDE_STEPPING ) { - - if( principleDirection === DIRECTION_LEFT ) { - - walkWheelPosition = sideStepCycleStartLeft; - - } else { - - walkWheelPosition = sideStepCycleStartRight; - } - switch(currentAnimation) { - - case selectedStand: - - break; - - default: - - break; - } - setInternalState(SIDE_STEPPING); - } - - currentAnimation = selectedSideStep; - } - animateAvatar( deltaTime, speed, principleDirection ); - } - break; - - case FLYING: - - if( flyHints > requiredHints - 1 || INTERNAL_STATE===FLYING ) { // wait for a few consecutive hints (17mS each) - - standHints = 0; - walkHints = 0; - flyHints = 0; - - if(INTERNAL_STATE!==FLYING) setInternalState(FLYING); - - // change animation for flying directly up or down. TODO - check RecentMotions, if is a change then put a transition on it - if(principleDirection===DIRECTION_UP) { - - if(currentAnimation !== selectedFlyUp) { - - // initiate a Transition - if(currentTransition && currentTransition.nextAnimation!==selectedFlyUp) { - delete currentTransition; - currentTransition = null; - } - switch(currentAnimation) { - - case selectedStand: - - currentTransition = new Transition(currentAnimation, selectedFlyUp, [], 0.35, {x:0.5,y:0.08}, {x:0.28,y:1}); - break; - - case selectedSideStepLeft: - case selectedSideStepRight: - - break; - - default: - - currentTransition = new Transition(currentAnimation, selectedFlyUp, [], 0.35, {x:0.5,y:0.08}, {x:0.28,y:1}); - break; - } - currentAnimation = selectedFlyUp; - } - - } else if(principleDirection==DIRECTION_DOWN) { - - if(currentAnimation !== selectedFlyDown) { // TODO: as the locomotion gets cleaner (i.e. less false reports from Interface) this value can be reduced - - // initiate a Transition - if(currentTransition && currentTransition.nextAnimation!==selectedFlyDown) { - delete currentTransition; - currentTransition = null; - } - switch(currentAnimation) { - - case selectedStand: - - currentTransition = new Transition(currentAnimation, selectedFlyDown, [], 0.35, {x:0.5,y:0.08}, {x:0.28,y:1}); - break; - - case selectedSideStepLeft: - case selectedSideStepRight: - - break; - - default: - - currentTransition = new Transition(currentAnimation, selectedFlyDown, [], 0.35, {x:0.5,y:0.08}, {x:0.28,y:1}); - break; - } - currentAnimation = selectedFlyDown; - } - } else { - if(currentAnimation !== selectedFly) { // TODO: as the locomotion gets cleaner (i.e. less false reports from Interface) this value can be reduced + motion.walkWheelPos = motion.selSideStepRight.calibration.cycleStart; + switch (motion.curAnim) { - // initiate a Transition - if(currentTransition && currentTransition.nextAnimation!==selectedFly) { - delete currentTransition; - currentTransition = null; - } - switch(currentAnimation) { + case motion.selStand: - case selectedStand: + break; - currentTransition = new Transition(currentAnimation, selectedFly, [], 0.35, {x:0.5,y:0.08}, {x:0.28,y:1}); - break; + default: - case selectedSideStepLeft: - case selectedSideStepRight: - - break; - - default: - - currentTransition = new Transition(currentAnimation, selectedFly, [], 0.35, {x:0.5,y:0.08}, {x:0.28,y:1}); - break; - } - currentAnimation = selectedFly; + break; } } - animateAvatar(deltaTime, speed, principleDirection); + state.setInternalState(state.SIDE_STEP); } + motion.curAnim = selSideStep; + animateAvatar(deltaTime, speed); + break; + + case state.FLYING: + + if (state.currentState !== state.FLYING) + state.setInternalState(state.FLYING); + + // change animation for flying directly up or down + if (motion.direction === UP) { + + if (motion.curAnim !== motion.selFlyUp) { + + switch (motion.curAnim) { + + case motion.selStand: + case motion.selWalk: + + // standing | walking to flying up + motion.curTransition = new Transition( + motion.curAnim, + motion.selFlyUp, + [], 0.25, + {x: 0.5, y: 0.08}, + {x: 0.28, y: 1}); + break; + + case motion.selSideStepLeft: + case motion.selSideStepRight: + + break; + + default: + + motion.curTransition = new Transition( + motion.curAnim, + motion.selFlyUp, + [], 0.35, + {x: 0.5, y: 0.08}, + {x: 0.28, y: 1}); + break; + } + motion.curAnim = motion.selFlyUp; + } + + } else if (motion.direction == DOWN) { + + if (motion.curAnim !== motion.selFlyDown) { + + switch (motion.curAnim) { + + case motion.selStand: + case motion.selWalk: + + motion.curTransition = new Transition( + motion.curAnim, + motion.selFlyDown, + [], 0.35, + {x: 0.5, y: 0.08}, + {x: 0.28, y: 1}); + break; + + case motion.selSideStepLeft: + case motion.selSideStepRight: + + break; + + default: + + motion.curTransition = new Transition( + motion.curAnim, + motion.selFlyDown, + [], 0.5, + {x: 0.5, y: 0.08}, + {x: 0.28, y: 1}); + break; + } + motion.curAnim = motion.selFlyDown; + } + + } else { + + if (motion.curAnim !== motion.selFly) { + + switch (motion.curAnim) { + + case motion.selStand: + case motion.selWalk: + + motion.curTransition = new Transition( + motion.curAnim, + motion.selFly, + [], 0.35, + {x: 1.44, y:0.24}, + {x: 0.61, y:0.92}); + break; + + case motion.selSideStepLeft: + case motion.selSideStepRight: + + break; + + default: + + motion.curTransition = new Transition( + motion.curAnim, + motion.selFly, + [], 0.75, + {x: 0.5, y: 0.08}, + {x: 0.28, y: 1}); + break; + } + motion.curAnim = motion.selFly; + } + } + animateAvatar(deltaTime, speed); break; } // end switch(actionToTake) - } // end if(!editing) + } // end if (!state.editing) + + // record the frame's direction and local avatar's local velocity for future reference + motion.lastDirection = motion.direction; + motion.lastVelocity = localVelocity; + } +}); + +// the faster we go, the further we lean forward. the angle is calcualted here +function getLeanPitch(speed) { + + if (speed > TOP_SPEED) speed = TOP_SPEED; + var leanProgress = speed / TOP_SPEED; + + if (motion.direction === LEFT || + motion.direction === RIGHT) + leanProgress = 0; + + else { + + var responseSharpness = 1.5; + if (motion.direction == BACKWARDS) responseSharpness = 3.0; + + leanProgress = filter.bezier((1 - leanProgress), + {x: 0, y: 0.0}, + {x: 0, y: responseSharpness}, + {x: 0, y: 1.5}, + {x: 1, y: 1}).y; + + // determine final pitch and adjust for direction of momentum + if (motion.direction === BACKWARDS) + leanProgress = -motion.motionPitchMax * leanProgress; + else + leanProgress = motion.motionPitchMax * leanProgress; + } + + // return the smoothed response + return leanPitchFilter.process(leanProgress); +} + +// calculate the angle at which to bank into corners when turning +function getLeanRoll(deltaTime, speed) { + + var leanRollProgress = 0; + if (speed > TOP_SPEED) speed = TOP_SPEED; + + // what's our our anglular velocity? + var angularVelocityMax = 70; // from observation + var angularVelocity = filter.radToDeg(MyAvatar.getAngularVelocity().y); + if (angularVelocity > angularVelocityMax) angularVelocity = angularVelocityMax; + if (angularVelocity < -angularVelocityMax) angularVelocity = -angularVelocityMax; + + leanRollProgress = speed / TOP_SPEED; + + if (motion.direction !== LEFT && + motion.direction !== RIGHT) + leanRollProgress *= (Math.abs(angularVelocity) / angularVelocityMax); + + // apply our response curve + leanRollProgress = filter.bezier((1 - leanRollProgress), + {x: 0, y: 0}, + {x: 0, y: 1}, + {x: 0, y: 1}, + {x: 1, y: 1}).y; + // which way to lean? + var turnSign = -1; + if (angularVelocity < 0.001) turnSign = 1; + if (motion.direction === BACKWARDS || + motion.direction === LEFT) + turnSign *= -1; + + if (motion.direction === LEFT || + motion.direction === RIGHT) + leanRollProgress *= 2; + + // add damping with simple averaging filter + leanRollProgress = leanRollFilter.process(turnSign * leanRollProgress); + return motion.motionRollMax * leanRollProgress; +} + +function playFootstep(side) { + + var options = new AudioInjectionOptions(); + options.position = Camera.getPosition(); + options.volume = 0.2; + var soundNumber = 2; // 0 to 2 + if (side === RIGHT && motion.makesFootStepSounds) + Audio.playSound(walkAssets.footsteps[soundNumber + 1], options); + else if (side === LEFT && motion.makesFootStepSounds) + Audio.playSound(walkAssets.footsteps[soundNumber], options); +} + +// animate the avatar using sine wave generators. inspired by Victorian clockwork dolls +function animateAvatar(deltaTime, speed) { + + var cycle = motion.cumulativeTime; + var transProgress = 1; + var adjFreq = motion.curAnim.calibration.frequency; + + // legs phase and cycle reversal for walking backwards + var reverseModifier = 0; + var reverseSignModifier = 1; + if (motion.direction === BACKWARDS) { + reverseModifier = -180; + reverseSignModifier = -1; + } + + // don't lean into the direction of travel if going up + var leanMod = 1; + if (motion.direction === UP) + leanMod = 0; + + // adjust leaning direction for flying + var flyingModifier = 1; + if (state.currentState.FLYING) + flyingModifier = -1; + + if (motion.curTransition !== nullTransition) { + + // new transiton? + if (motion.curTransition.progress === 0 && + motion.curTransition.walkingAtStart) { + + if (state.currentState !== state.SIDE_STEP) { + + // work out where we want the walk cycle to stop + var leftStop = motion.selWalk.calibration.stopAngleForwards + 180; + var rightStop = motion.selWalk.calibration.stopAngleForwards; + + if (motion.direction === BACKWARDS) { + leftStop = motion.selWalk.calibration.stopAngleBackwards + 180; + rightStop = motion.selWalk.calibration.stopAngleBackwards; + } + + // find the closest stop point from the walk wheel's angle + var angleToLeftStop = 180 - Math.abs(Math.abs(motion.walkWheelPos - leftStop) - 180); + var angleToRightStop = 180 - Math.abs(Math.abs(motion.walkWheelPos - rightStop) - 180); + if (motion.walkWheelPos > angleToLeftStop) angleToLeftStop = 360 - angleToLeftStop; + if (motion.walkWheelPos > angleToRightStop) angleToRightStop = 360 - angleToRightStop; - // record the frame's stats for later reference - var thisMotion = new RecentMotion(localVelocity, acceleration, principleDirection, INTERNAL_STATE); - framesHistory.recentMotions.push(thisMotion); - framesHistory.recentMotions.shift(); + motion.curTransition.walkWheelIncrement = 3; + // keep the walkwheel turning by setting the walkWheelIncrement + // until our feet are tucked nicely underneath us. + if (angleToLeftStop < angleToRightStop) - // before we go, populate the stats overlay - if( statsOn ) { + motion.curTransition.walkStopAngle = leftStop; - var cumulativeTimeMS = Math.floor(cumulativeTime*1000); - var deltaTimeMS = deltaTime * 1000; - var frameExecutionTime = new Date().getTime() - frameStartTime; - if(frameExecutionTime>frameExecutionTimeMax) frameExecutionTimeMax = frameExecutionTime; + else + motion.curTransition.walkStopAngle = rightStop; - var angluarVelocity = Vec3.length(MyAvatar.getAngularVelocity()); + } else { - var debugInfo = '\n \n \n \n Stats\n--------------------------------------\n \n \n' - + '\nFrame number: '+nFrames - + '\nFrame time: '+deltaTimeMS.toFixed(2) - + ' mS\nRender time: '+frameExecutionTime.toFixed(0) - + ' mS\nLocalised speed: '+speed.toFixed(3) - + ' m/s\nCumulative Time '+cumulativeTimeMS.toFixed(0) - + ' mS\nState: '+internalStateAsString(INTERNAL_STATE) - + ' \nDirection: '+directionAsString(principleDirection) - + ' \nAngular Velocity: ' + angluarVelocity.toFixed(3) - + ' rad/s'; - Overlays.editOverlay(debugStats, {text: debugInfo}); - - // update these every 250 mS (assuming 60 fps) - if( nFrames % 15 === 0 ) { - var debugInfo = ' Periodic Stats\n--------------------------------------\n \n \n' - + ' \n \nRender time peak hold: '+frameExecutionTimeMax.toFixed(0) - + ' mS\n \n \n(L) MyAvatar.getVelocity()' - + ' \n \nlocalVelocityX: '+deltaX.toFixed(1) - + ' m/s\nlocalVelocityY: '+deltaY.toFixed(1) - + ' m/s\nlocalVelocityZ: '+deltaZ.toFixed(1) - + ' m/s\n \n(G) MyAvatar.getAcceleration()' - + ' \n\nAcceleration X: '+accelerationJS.x.toFixed(1) - + ' m/s/s\nAcceleration Y: '+accelerationJS.y.toFixed(1) - + ' m/s/s\nAcceleration Z: '+accelerationJS.z.toFixed(1) - + ' m/s/s\n \n(L) Acceleration using\nMyAvatar.getVelocity()' - + ' \n \nAcceleration X: '+acceleration.x.toFixed(1) - + ' m/s/s\nAcceleration Y: '+acceleration.y.toFixed(1) - + ' m/s/s\nAcceleration Z: '+acceleration.z.toFixed(1) - + ' m/s/s'; - Overlays.editOverlay(debugStatsPeriodic, {text: debugInfo}); - frameExecutionTimeMax = 0; + // freeze wheel for sidestepping transitions (for now) + motion.curTransition.walkWheelIncrement = 0; } + } // end if (new transition and curTransition.walkingAtStart) + + // update the Transition progress + var elapasedTime = (new Date().getTime() - motion.curTransition.startTime) / 1000; + motion.curTransition.progress = elapasedTime / motion.curTransition.transitionDuration; + transProgress = filter.bezier((1 - motion.curTransition.progress), {x: 0, y: 0}, + motion.curTransition.easingLower, + motion.curTransition.easingUpper, {x: 1, y: 1}).y; + + if (motion.curTransition.progress >= 1) { + + // time to kill off the transition + delete motion.curTransition; + motion.curTransition = nullTransition; + + } else { + + if (motion.curTransition.walkingAtStart) { + + if (state.currentState !== state.SIDE_STEP) { + + // if at a stop angle, hold the walk wheel position for remainder of transition + var tolerance = 7; // must be greater than the walkWheel increment + if ((motion.walkWheelPos > (motion.curTransition.walkStopAngle - tolerance)) && + (motion.walkWheelPos < (motion.curTransition.walkStopAngle + tolerance))) { + + motion.curTransition.walkWheelIncrement = 0; + } + // keep turning walk wheel until both feet are below the avi + + motion.advanceWalkWheel(motion.curTransition.walkWheelIncrement); + //motion.curTransition.walkWheelAdvance += motion.curTransition.walkWheelIncrement; + } + else motion.curTransition.walkWheelIncrement = 0; // sidestep + } + } } // end motion.curTransition !== nullTransition + + + // walking? then get the stride length + if (motion.curAnim === motion.selWalk) { + + // if the timing's right, take a snapshot of the stride max and recalibrate + var strideMaxAt = motion.curAnim.calibration.forwardStrideMaxAt; + if (motion.direction === BACKWARDS) + strideMaxAt = motion.curAnim.calibration.backwardsStrideMaxAt; + + var tolerance = 1.0; + if (motion.walkWheelPos < (strideMaxAt + tolerance) && + motion.walkWheelPos > (strideMaxAt - tolerance)) { + + // measure and save stride length + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + + if (motion.direction === FORWARDS) + motion.curAnim.calibration.strideLengthForwards = motion.strideLength; + else if (motion.direction === BACKWARDS) + motion.curAnim.calibration.strideLengthBackwards = motion.strideLength; + + } else { + + // use the saved value for stride length + if (motion.direction === FORWARDS) + motion.strideLength = motion.curAnim.calibration.strideLengthForwards; + else if (motion.direction === BACKWARDS) + motion.strideLength = motion.curAnim.calibration.strideLengthBackwards; } - } -}); + } // end get walk stride length + // sidestepping? get the stride length + if (motion.curAnim === motion.selSideStepLeft || + motion.curAnim === motion.selSideStepRight) { -// overlays start + // if the timing's right, take a snapshot of the stride max and recalibrate the stride length + var tolerance = 1.0; + if (motion.direction === LEFT) { -// controller dimensions -var backgroundWidth = 350; -var backgroundHeight = 700; -var backgroundX = Window.innerWidth-backgroundWidth-58; -var backgroundY = Window.innerHeight/2 - backgroundHeight/2; -var minSliderX = backgroundX + 30; -var maxSliderX = backgroundX + 295; -var sliderRangeX = 295 - 30; -var jointsControlWidth = 200; -var jointsControlHeight = 300; -var jointsControlX = backgroundX + backgroundWidth/2 - jointsControlWidth/2; -var jointsControlY = backgroundY + 242 - jointsControlHeight/2; -var buttonsY = 20; // distance from top of panel to buttons + if (motion.walkWheelPos < motion.curAnim.calibration.strideMaxAt + tolerance && + motion.walkWheelPos > motion.curAnim.calibration.strideMaxAt - tolerance) { -// arrays of overlay names -var sliderThumbOverlays = []; // thumb sliders -var backgroundOverlays = []; -var buttonOverlays = []; -var jointsControlOverlays = []; -var bigButtonOverlays = []; + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + motion.curAnim.calibration.strideLength = motion.strideLength; + } else motion.strideLength = motion.selSideStepLeft.calibration.strideLength; -// load UI backgrounds -var controlsBackground = Overlays.addOverlay("image", { - bounds: { x: backgroundX, y: backgroundY, width: backgroundWidth, height: backgroundHeight }, - imageURL: pathToOverlays+"ddao-background.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -backgroundOverlays.push(controlsBackground); + } else if (motion.direction === RIGHT) { -var controlsBackgroundWalkEditStyles = Overlays.addOverlay("image", { - bounds: { x: backgroundX, y: backgroundY, width: backgroundWidth, height: backgroundHeight }, - imageURL: pathToOverlays+"ddao-background-edit-styles.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -backgroundOverlays.push(controlsBackgroundWalkEditStyles); + if (motion.walkWheelPos < motion.curAnim.calibration.strideMaxAt + tolerance && + motion.walkWheelPos > motion.curAnim.calibration.strideMaxAt - tolerance) { -var controlsBackgroundWalkEditTweaks = Overlays.addOverlay("image", { - bounds: { x: backgroundX, y: backgroundY, width: backgroundWidth, height: backgroundHeight }, - imageURL: pathToOverlays+"ddao-background-edit-tweaks.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -backgroundOverlays.push(controlsBackgroundWalkEditTweaks); + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + motion.curAnim.calibration.strideLength = motion.strideLength; -var controlsBackgroundWalkEditJoints = Overlays.addOverlay("image", { - bounds: { x: backgroundX, y: backgroundY, width: backgroundWidth, height: backgroundHeight }, - imageURL: pathToOverlays+"ddao-background-edit-joints.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -backgroundOverlays.push(controlsBackgroundWalkEditJoints); + } else motion.strideLength = motion.selSideStepRight.calibration.strideLength; + } + } // end get sidestep stride length -var controlsBackgroundFlyingEdit = Overlays.addOverlay("image", { - bounds: { x: backgroundX, y: backgroundY, width: backgroundWidth, height: backgroundHeight }, - imageURL: pathToOverlays+"ddao-background-flying-edit.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -backgroundOverlays.push(controlsBackgroundFlyingEdit); + // turn the walk wheel + if (motion.curAnim === motion.selWalk || + motion.curAnim === motion.selSideStepLeft || + motion.curAnim === motion.selSideStepRight || + motion.curTransition.walkingAtStart) { -// minimised tab - not put in array, as is a one off -var controlsMinimisedTab = Overlays.addOverlay("image", { - x: Window.innerWidth-58, y: Window.innerHeight -145, width: 50, height: 50, - //subImage: { x: 0, y: 50, width: 50, height: 50 }, - imageURL: pathToOverlays + 'ddao-minimise-tab.png', - visible: minimised, - alpha: 0.9 - }); + // wrap the stride length around a 'surveyor's wheel' twice and calculate + // the angular speed at the given (linear) speed: + // omega = v / r , where r = circumference / 2 PI , where circumference = 2 * stride length + var strideLength = motion.strideLength; + var wheelRadius = strideLength / Math.PI; + var angularVelocity = speed / wheelRadius; -// load character joint selection control images -var hipsJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-hips.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(hipsJointControl); + // calculate the degrees turned (at this angular speed) since last frame + var radiansTurnedSinceLastFrame = deltaTime * angularVelocity; + var degreesTurnedSinceLastFrame = filter.radToDeg(radiansTurnedSinceLastFrame); -var upperLegsJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-upper-legs.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(upperLegsJointControl); + // if we are in an edit mode, we will need fake time to turn the wheel + if (state.currentState !== state.WALKING && + state.currentState !== state.SIDE_STEP) + degreesTurnedSinceLastFrame = motion.curAnim.calibration.frequency / 70; -var lowerLegsJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-lower-legs.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(lowerLegsJointControl); + // advance the walk wheel the appropriate amount + motion.advanceWalkWheel(degreesTurnedSinceLastFrame); -var feetJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-feet.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(feetJointControl); + // set the new values for the exact correct walk cycle speed + adjFreq = 1; + cycle = motion.walkWheelPos; -var toesJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-toes.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(toesJointControl); + } // end of walk wheel and stride length calculation -var spineJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-spine.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(spineJointControl); + // motion vars + var pitchOsc = 0; + var pitchOscLeft = 0; + var pitchOscRight = 0; + var yawOsc = 0; + var yawOscLeft = 0; + var yawOscRight = 0; + var rollOsc = 0; + var pitchOffset = 0; + var yawOffset = 0; + var rollOffset = 0; + var swayOsc = 0; + var bobOsc = 0; + var thrustOsc = 0; + var swayOscLast = 0; + var bobOscLast = 0; + var thrustOscLast = 0; -var spine1JointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-spine1.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(spine1JointControl); + // historical (for transitions) + var pitchOscLast = 0; + var pitchOscLeftLast = 0; + var pitchOscRightLast = 0; + var yawOscLast = 0; + var rollOscLast = 0; + var pitchOffsetLast = 0; + var yawOffsetLast = 0; + var rollOffsetLast = 0; -var spine2JointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-spine2.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(spine2JointControl); + // feet + var sideStepFootPitchModifier = 1; + var sideStepHandPitchSign = 1; -var shouldersJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-shoulders.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(shouldersJointControl); + // The below code should probably be optimised into some sort of loop, where + // the joints are iterated through. However, this has not been done yet, as there + // are still some quite fundamental changes to be made (e.g. turning on the spot + // animation and sidestepping transitions) so it's been left as is for ease of + // understanding and editing. -var upperArmsJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-upper-arms.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(upperArmsJointControl); + // calculate hips translation + if (motion.curTransition !== nullTransition) { -var forearmsJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-forearms.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(forearmsJointControl); + if (motion.curTransition.walkingAtStart) { -var handsJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-hands.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(handsJointControl); + swayOsc = motion.curAnim.joints[0].sway * + Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency + + motion.curAnim.joints[0].swayPhase)) + motion.curAnim.joints[0].swayOffset; -var headJointControl = Overlays.addOverlay("image", { - bounds: { x: jointsControlX, y: jointsControlY, width: 200, height: 300}, - imageURL: pathToOverlays+"ddao-background-edit-head.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -jointsControlOverlays.push(headJointControl); + var bobPhase = motion.curAnim.joints[0].bobPhase; + if (motion.direction === motion.BACKWARDS) bobPhase += 90; + bobOsc = motion.curAnim.joints[0].bob * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + bobPhase)) + + motion.curAnim.joints[0].bobOffset; + thrustOsc = motion.curAnim.joints[0].thrust * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency * 2 + + motion.curAnim.joints[0].thrustPhase)) + + motion.curAnim.joints[0].thrustOffset; -// sider thumb overlays -var sliderOne = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderOne); -var sliderTwo = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderTwo); -var sliderThree = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderThree); -var sliderFour = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderFour); -var sliderFive = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderFive); -var sliderSix = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderSix); -var sliderSeven = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderSeven); -var sliderEight = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderEight); -var sliderNine = Overlays.addOverlay("image", { - bounds: { x: 0, y: 0, width: 25, height: 25 }, - imageURL: pathToOverlays+"ddao-slider-handle.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -sliderThumbOverlays.push(sliderNine); + swayOscLast = motion.curTransition.lastAnim.joints[0].sway * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[0].swayPhase)) + + motion.curTransition.lastAnim.joints[0].swayOffset; + var bobPhaseLast = motion.curTransition.lastAnim.joints[0].bobPhase; + if (motion.direction === motion.BACKWARDS) bobPhaseLast +=90; + bobOscLast = motion.curTransition.lastAnim.joints[0].bob * + Math.sin(filter.degToRad(motion.walkWheelPos + bobPhaseLast)); + bobOscLast = filter.clipTrough(bobOscLast, motion.curTransition.lastAnim.joints[0].bob , 2); + bobOscLast = hipsBobLPFilter.process(bobOscLast); + bobOscLast += motion.curTransition.lastAnim.joints[0].bobOffset; -// button overlays -var onButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+20, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-on-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(onButton); -var offButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+20, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-off-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(offButton); -var configWalkButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-walk-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkButton); -var configWalkButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-walk-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkButtonSelected); -var configStandButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+146, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-stand-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configStandButton); -var configStandButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+146, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-stand-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configStandButtonSelected); + thrustOscLast = motion.curTransition.lastAnim.joints[0].thrust * + Math.sin(filter.degToRad(motion.walkWheelPos * 2 + + motion.curTransition.lastAnim.joints[0].thrustPhase)) + + motion.curTransition.lastAnim.joints[0].thrustOffset; -var configFlyingButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+209, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-fly-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configFlyingButton); -var configFlyingButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+209, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-fly-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configFlyingButtonSelected); + } // end if walking at start of transition + else { -var configFlyingUpButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-fly-up-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configFlyingUpButton); -var configFlyingUpButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-fly-up-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configFlyingUpButtonSelected); + swayOsc = motion.curAnim.joints[0].sway * + Math.sin(filter.degToRad(cycle * adjFreq + motion.curAnim.joints[0].swayPhase)) + + motion.curAnim.joints[0].swayOffset; -var configFlyingDownButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+146, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-fly-down-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configFlyingDownButton); -var configFlyingDownButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+146, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-fly-down-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configFlyingDownButtonSelected); + var bobPhase = motion.curAnim.joints[0].bobPhase; + if (motion.direction === motion.BACKWARDS) bobPhase += 90; + bobOsc = motion.curAnim.joints[0].bob * + Math.sin(filter.degToRad(cycle * adjFreq * 2 + bobPhase)); + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { -var hideButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+272, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-hide-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(hideButton); -var hideButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+272, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-hide-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(hideButtonSelected); -var configWalkStylesButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-walk-styles-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkStylesButton); -var configWalkStylesButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-walk-styles-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkStylesButtonSelected); -var configWalkTweaksButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+146, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-walk-tweaks-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkTweaksButton); -var configWalkTweaksButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+146, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-walk-tweaks-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkTweaksButtonSelected); + // apply clipping filter to flatten the curve's peaks (inputValue, peak, strength) + bobOsc = filter.clipTrough(bobOsc, motion.curAnim.joints[0].bob , 2); + bobOsc = hipsBobLPFilter.process(bobOsc); + } + bobOsc += motion.curAnim.joints[0].bobOffset; -var configSideStepLeftButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-sidestep-left-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configSideStepLeftButton); -var configSideStepLeftButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+83, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-sidestep-left-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configSideStepLeftButtonSelected); + thrustOsc = motion.curAnim.joints[0].thrust * + Math.sin(filter.degToRad(cycle * adjFreq * 2 + + motion.curAnim.joints[0].thrustPhase)) + + motion.curAnim.joints[0].thrustOffset; -var configSideStepRightButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+209, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-sidestep-right-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configSideStepRightButton); -var configSideStepRightButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+209, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-edit-sidestep-right-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configSideStepRightButtonSelected); + swayOscLast = motion.curTransition.lastAnim.joints[0].sway * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[0].swayPhase)) + + motion.curTransition.lastAnim.joints[0].swayOffset; -var configWalkJointsButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+209, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-bones-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkJointsButton); -var configWalkJointsButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+209, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-bones-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(configWalkJointsButtonSelected); + bobOscLast = motion.curTransition.lastAnim.joints[0].bob * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency * 2 + + motion.curTransition.lastAnim.joints[0].bobPhase)) + + motion.curTransition.lastAnim.joints[0].bobOffset; -var backButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX+272, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-back-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(backButton); -var backButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX+272, y: backgroundY+buttonsY, width: 60, height: 47 }, - imageURL: pathToOverlays+"ddao-back-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -buttonOverlays.push(backButtonSelected); + thrustOscLast = motion.curTransition.lastAnim.joints[0].thrust * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency * 2 + + motion.curTransition.lastAnim.joints[0].thrustPhase)) + + motion.curTransition.lastAnim.joints[0].thrustOffset; + } -// big button overlays - front panel -var bigButtonYOffset = 408; // distance from top of panel to top of first button + swayOsc = (transProgress * swayOsc) + ((1 - transProgress) * swayOscLast); + bobOsc = (transProgress * bobOsc) + ((1 - transProgress) * bobOscLast); + thrustOsc = (transProgress * thrustOsc) + ((1 - transProgress) * thrustOscLast); -var femaleBigButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-female-big-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(femaleBigButton); + }// if current transition active + else { -var femaleBigButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-female-big-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(femaleBigButtonSelected); + swayOsc = motion.curAnim.joints[0].sway * + Math.sin(filter.degToRad(cycle * adjFreq + motion.curAnim.joints[0].swayPhase)) + + motion.curAnim.joints[0].swayOffset; -var maleBigButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset + 60, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-male-big-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(maleBigButton); + bobPhase = motion.curAnim.joints[0].bobPhase; + if (motion.direction === motion.BACKWARDS) bobPhase += 90; + bobOsc = motion.curAnim.joints[0].bob * Math.sin(filter.degToRad(cycle * adjFreq * 2 + bobPhase)); + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { -var maleBigButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset + 60, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-male-big-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(maleBigButtonSelected); + // apply clipping filter to flatten the curve's peaks (inputValue, peak, strength) + bobOsc = filter.clipTrough(bobOsc, motion.curAnim.joints[0].bob , 2); + bobOsc = hipsBobLPFilter.process(bobOsc); + } + bobOsc += motion.curAnim.joints[0].bobOffset; -var armsFreeBigButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset + 120, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-arms-free-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(armsFreeBigButton); + thrustOsc = motion.curAnim.joints[0].thrust * + Math.sin(filter.degToRad(cycle * adjFreq * 2 + + motion.curAnim.joints[0].thrustPhase)) + + motion.curAnim.joints[0].thrustOffset; + } -var armsFreeBigButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset + 120, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-arms-free-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(armsFreeBigButtonSelected); + // convert local hips translations to global and apply + var aviOrientation = MyAvatar.orientation; + var front = Quat.getFront(aviOrientation); + var right = Quat.getRight(aviOrientation); + var up = Quat.getUp(aviOrientation); + var aviFront = Vec3.multiply(front, thrustOsc); + var aviRight = Vec3.multiply(right, swayOsc); + var aviUp = Vec3.multiply(up, bobOsc); + var aviTranslationOffset = {x: 0, y: 0, z: 0}; -var footstepsBigButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset + 180, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-footsteps-big-button.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(footstepsBigButton); + aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviFront); + aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviRight); + aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviUp); -var footstepsBigButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset + 180, width: 230, height: 36}, - imageURL: pathToOverlays+"ddao-footsteps-big-button-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(footstepsBigButtonSelected); + MyAvatar.setSkeletonOffset({ + x: aviTranslationOffset.x, + y: aviTranslationOffset.y, + z: aviTranslationOffset.z + }); + // hips rotation + if (motion.curTransition !== nullTransition) { -// walk styles -bigButtonYOffset = 121; -var strutWalkBigButton = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset, width: 230, height: 36 }, - imageURL: pathToOverlays+"ddao-walk-select-button-strut.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(strutWalkBigButton); + if (motion.curTransition.walkingAtStart) { -var strutWalkBigButtonSelected = Overlays.addOverlay("image", { - bounds: { x: backgroundX + backgroundWidth/2 - 115, y: backgroundY + bigButtonYOffset, width: 230, height: 36 }, - imageURL: pathToOverlays+"ddao-walk-select-button-strut-selected.png", - color: { red: 255, green: 255, blue: 255}, - alpha: 1, - visible: false - }); -bigButtonOverlays.push(strutWalkBigButtonSelected); + pitchOsc = motion.curAnim.joints[0].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency * 2 + + motion.curAnim.joints[0].pitchPhase)) + motion.curAnim.joints[0].pitchOffset; -// overlays to show the walk wheel stats -var walkWheelZLine = Overlays.addOverlay("line3d", { - position: { x: 0, y: 0, z:hipsToFeetDistance }, - end: { x: 0, y: 0, z: -hipsToFeetDistance }, - color: { red: 0, green: 255, blue: 255}, - alpha: 1, - lineWidth: 5, - visible: statsOn, - anchor: "MyAvatar" - }); -var walkWheelYLine = Overlays.addOverlay("line3d", { - position: { x: 0, y: hipsToFeetDistance, z:0 }, - end: { x: 0, y: -hipsToFeetDistance, z:0 }, - color: { red: 255, green: 0, blue: 255}, - alpha: 1, - lineWidth: 5, - visible: statsOn, - anchor: "MyAvatar" - }); -var debugStats = Overlays.addOverlay("text", { - x: backgroundX-199, y: backgroundY, - width: 200, - height: 180, - color: { red: 204, green: 204, blue: 204}, - topMargin: 10, - leftMargin: 15, - visible: statsOn, - backgroundColor: { red: 34, green: 34, blue: 34}, - alpha: 1.0, - text: "Debug Stats\n\n\nNothing to report yet." - }); -var debugStatsPeriodic = Overlays.addOverlay("text", { - x: backgroundX-199, y: backgroundY+179, - width: 200, - height: 392, - color: { red: 204, green: 204, blue: 204}, - topMargin: 5, - leftMargin: 15, - visible: statsOn, - backgroundColor: { red: 34, green: 34, blue: 34}, - alpha: 1.0, - text: "Debug Stats\n\n\nNothing to report yet." - }); -var walkWheelStats = Overlays.addOverlay("text", { - x: backgroundX-199, y: backgroundY+510, - width: 200, - height: 190, - color: { red: 204, green: 204, blue: 204}, - topMargin: 5, - leftMargin: 15, - visible: statsOn, - backgroundColor: { red: 34, green: 34, blue: 34}, - alpha: 1.0, - text: "WalkWheel Stats\n\n\nNothing to report yet.\n\n\nPlease start walking\nto see the walkwheel." - }); + yawOsc = motion.curAnim.joints[0].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency + + motion.curAnim.joints[0].yawPhase - reverseModifier)) + motion.curAnim.joints[0].yawOffset; -// various show / hide GUI element functions -function doStandardMenu() { - hidebuttonOverlays(); - hideJointControls(); - setBackground(controlsBackground); - if(powerOn) setButtonOverlayVisible(onButton); - else setButtonOverlayVisible(offButton); - setButtonOverlayVisible(configWalkButton); - setButtonOverlayVisible(configStandButton); - setButtonOverlayVisible(configFlyingButton); - setButtonOverlayVisible(hideButton); - setSliderThumbsVisible(false); - showFrontPanelButtons(true); - showWalkStyleButtons(false); -} -function showFrontPanelButtons(showButtons) { + rollOsc = motion.curAnim.joints[0].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * motion.curAnim.calibration.frequency + + motion.curAnim.joints[0].rollPhase)) + motion.curAnim.joints[0].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[0].pitch * + Math.sin(filter.degToRad(motion.walkWheelPos * 2 + + motion.curTransition.lastAnim.joints[0].pitchPhase)) + + motion.curTransition.lastAnim.joints[0].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[0].yaw * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[0].yawPhase)); + + yawOscLast += motion.curTransition.lastAnim.joints[0].yaw * + hipsYawShaper.shapeWave(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[0].yawPhase - reverseModifier)) + + motion.curTransition.lastAnim.joints[0].yawOffset; + + rollOscLast = (motion.curTransition.lastAnim.joints[0].roll * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[0].rollPhase)) + + motion.curTransition.lastAnim.joints[0].rollOffset); + + } else { + + pitchOsc = motion.curAnim.joints[0].pitch * + Math.sin(filter.degToRad(cycle * adjFreq * 2 + + motion.curAnim.joints[0].pitchPhase)) + + motion.curAnim.joints[0].pitchOffset; + + yawOsc = motion.curAnim.joints[0].yaw * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[0].yawPhase - reverseModifier)) + + motion.curAnim.joints[0].yawOffset; + + rollOsc = motion.curAnim.joints[0].roll * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[0].rollPhase)) + + motion.curAnim.joints[0].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[0].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency * 2 + + motion.curTransition.lastAnim.joints[0].pitchPhase)) + + motion.curTransition.lastAnim.joints[0].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[0].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[0].yawPhase - reverseModifier)) + + motion.curTransition.lastAnim.joints[0].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[0].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[0].rollPhase)) + + motion.curTransition.lastAnim.joints[0].rollOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); - if(avatarGender===FEMALE) { - Overlays.editOverlay(femaleBigButtonSelected, { visible: showButtons } ); - Overlays.editOverlay(femaleBigButton, { visible: false } ); - Overlays.editOverlay(maleBigButtonSelected, { visible: false } ); - Overlays.editOverlay(maleBigButton, { visible: showButtons } ); } else { - Overlays.editOverlay(femaleBigButtonSelected, { visible: false } ); - Overlays.editOverlay(femaleBigButton, { visible: showButtons } ); - Overlays.editOverlay(maleBigButtonSelected, { visible: showButtons } ); - Overlays.editOverlay(maleBigButton, { visible: false } ); + + pitchOsc = motion.curAnim.joints[0].pitch * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[0].pitchPhase)) + + motion.curAnim.joints[0].pitchOffset; + + yawOsc = motion.curAnim.joints[0].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[0].yawPhase)); + + yawOsc += motion.curAnim.joints[0].yaw * + hipsYawShaper.shapeWave(filter.degToRad(cycle * adjFreq) + + motion.curAnim.joints[0].yawPhase - reverseModifier)+ + motion.curAnim.joints[0].yawOffset; + + rollOsc = (motion.curAnim.joints[0].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[0].rollPhase)) + + motion.curAnim.joints[0].rollOffset); } - if(armsFree) { - Overlays.editOverlay(armsFreeBigButtonSelected, { visible: showButtons } ); - Overlays.editOverlay(armsFreeBigButton, { visible: false } ); + + // apply hips rotation + MyAvatar.setJointData("Hips", Quat.fromPitchYawRollDegrees( + pitchOsc + (leanMod * getLeanPitch(speed)), + yawOsc, + rollOsc + getLeanRoll(deltaTime, speed))); + + // upper legs + if (state.currentState !== state.SIDE_STEP && + state.currentState !== state.EDIT_SIDESTEP_LEFT && + state.currentState !== state.EDIT_SIDESTEP_RIGHT) { + + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOscLeft = motion.curAnim.joints[1].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + reverseModifier * motion.curAnim.joints[1].pitchPhase)); + + pitchOscRight = motion.curAnim.joints[1].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + reverseModifier * motion.curAnim.joints[1].pitchPhase)); + + yawOsc = motion.curAnim.joints[1].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[1].yawPhase)); + + rollOsc = motion.curAnim.joints[1].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[1].rollPhase)); + + pitchOffset = motion.curAnim.joints[1].pitchOffset; + yawOffset = motion.curAnim.joints[1].yawOffset; + rollOffset = motion.curAnim.joints[1].rollOffset; + + pitchOscLeftLast = motion.curTransition.lastAnim.joints[1].pitch * + motion.curTransition.lastAnim.harmonics.leftUpperLeg.calculate( + filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[1].pitchPhase + 180 + reverseModifier)); + + pitchOscRightLast = motion.curTransition.lastAnim.joints[1].pitch * + motion.curTransition.lastAnim.harmonics.rightUpperLeg.calculate( + filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[1].pitchPhase + reverseModifier)); + + yawOscLast = motion.curTransition.lastAnim.joints[1].yaw * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[1].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[1].roll * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[1].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[1].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[1].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[1].rollOffset; + + } else { + + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { + + pitchOscLeft = motion.curAnim.joints[1].pitch * + motion.curAnim.harmonics.leftUpperLeg.calculate(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase + 180 + reverseModifier)); + pitchOscRight = motion.curAnim.joints[1].pitch * + motion.curAnim.harmonics.rightUpperLeg.calculate(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase + reverseModifier)); + } else { + + pitchOscLeft = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase)); + pitchOscRight = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase)); + } + + yawOsc = motion.curAnim.joints[1].yaw * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].yawPhase)); + + rollOsc = motion.curAnim.joints[1].roll * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].rollPhase)); + + pitchOffset = motion.curAnim.joints[1].pitchOffset; + yawOffset = motion.curAnim.joints[1].yawOffset; + rollOffset = motion.curAnim.joints[1].rollOffset; + + pitchOscLeftLast = motion.curTransition.lastAnim.joints[1].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + reverseModifier * motion.curTransition.lastAnim.joints[1].pitchPhase)); + + pitchOscRightLast = motion.curTransition.lastAnim.joints[1].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + reverseModifier * motion.curTransition.lastAnim.joints[1].pitchPhase)); + + yawOscLast = motion.curTransition.lastAnim.joints[1].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[1].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[1].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[1].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[1].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[1].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[1].rollOffset; + } + pitchOscLeft = (transProgress * pitchOscLeft) + ((1 - transProgress) * pitchOscLeftLast); + pitchOscRight = (transProgress * pitchOscRight) + ((1 - transProgress) * pitchOscRightLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); + yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); + rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); + + } else { + + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { + + pitchOscLeft = motion.curAnim.joints[1].pitch * + motion.curAnim.harmonics.leftUpperLeg.calculate(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase + 180 + reverseModifier)); + pitchOscRight = motion.curAnim.joints[1].pitch * + motion.curAnim.harmonics.rightUpperLeg.calculate(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase + reverseModifier)); + } else { + + pitchOscLeft = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase)); + pitchOscRight = motion.curAnim.joints[1].pitch * Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[1].pitchPhase)); + } + + yawOsc = motion.curAnim.joints[1].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[1].yawPhase)); + + rollOsc = motion.curAnim.joints[1].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[1].rollPhase)); + + pitchOffset = motion.curAnim.joints[1].pitchOffset; + yawOffset = motion.curAnim.joints[1].yawOffset; + rollOffset = motion.curAnim.joints[1].rollOffset; + } + + // apply the upper leg rotations + MyAvatar.setJointData("LeftUpLeg", Quat.fromPitchYawRollDegrees( + pitchOscLeft + pitchOffset, + yawOsc - yawOffset, + -rollOsc + rollOffset)); + + MyAvatar.setJointData("RightUpLeg", Quat.fromPitchYawRollDegrees( + pitchOscRight + pitchOffset, + yawOsc + yawOffset, + -rollOsc - rollOffset)); + + // lower leg + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOscLeft = motion.curAnim.joints[2].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[2].pitchPhase + 180)); + + pitchOscRight = motion.curAnim.joints[2].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[2].pitchPhase)); + + yawOsc = motion.curAnim.joints[2].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[2].yawPhase)); + + rollOsc = motion.curAnim.joints[2].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[2].rollPhase)); + + pitchOffset = motion.curAnim.joints[2].pitchOffset; + yawOffset = motion.curAnim.joints[2].yawOffset; + rollOffset = motion.curAnim.joints[2].rollOffset; + + pitchOscLeftLast = motion.curTransition.lastAnim.joints[2].pitch * + motion.curTransition.lastAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[2].pitchPhase + 180)); + + pitchOscRightLast = motion.curTransition.lastAnim.joints[2].pitch * + motion.curTransition.lastAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[2].pitchPhase)); + + yawOscLast = motion.curTransition.lastAnim.joints[2].yaw * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[2].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[2].roll * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[2].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[2].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[2].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[2].rollOffset; + + } else { + + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { + + pitchOscLeft = motion.curAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[2].pitchPhase + 180)); + pitchOscRight = motion.curAnim.harmonics.rightLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[2].pitchPhase)); + + } else { + + pitchOscLeft = Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].pitchPhase + 180)); + + pitchOscRight = Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].pitchPhase)); + } + pitchOscLeft *= motion.curAnim.joints[2].pitch; + pitchOscRight *= motion.curAnim.joints[2].pitch; + + yawOsc = motion.curAnim.joints[2].yaw * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[2].yawPhase)); + + rollOsc = motion.curAnim.joints[2].roll * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[2].rollPhase)); + + pitchOffset = motion.curAnim.joints[2].pitchOffset; + yawOffset = motion.curAnim.joints[2].yawOffset; + rollOffset = motion.curAnim.joints[2].rollOffset; + + pitchOscLeftLast = motion.curTransition.lastAnim.joints[2].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[2].pitchPhase + 180)); + + pitchOscRightLast = motion.curTransition.lastAnim.joints[2].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[2].pitchPhase)); + + yawOscLast = motion.curTransition.lastAnim.joints[2].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[2].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[2].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[2].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[2].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[2].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[2].rollOffset; + } + + pitchOscLeft = (transProgress * pitchOscLeft) + ((1 - transProgress) * pitchOscLeftLast); + pitchOscRight = (transProgress * pitchOscRight) + ((1 - transProgress) * pitchOscRightLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); + yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); + rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); + + rollOscLeft = rollOsc; + rollOscRight = rollOsc; + + } else { // end if transitioning + + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { + + pitchOscLeft = motion.curAnim.harmonics.leftLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[2].pitchPhase + 180)); + pitchOscRight = motion.curAnim.harmonics.rightLowerLeg.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[2].pitchPhase)); + + } else { + + pitchOscLeft = Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].pitchPhase + 180)); + + pitchOscRight = Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].pitchPhase)); + } + + pitchOscLeft *= motion.curAnim.joints[2].pitch; + pitchOscRight *= motion.curAnim.joints[2].pitch; + + yawOsc = motion.curAnim.joints[2].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].yawPhase)); + + rollOsc = Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].rollPhase)); + + rollOsc = motion.curAnim.joints[2].roll; + + pitchOffset = motion.curAnim.joints[2].pitchOffset; + yawOffset = motion.curAnim.joints[2].yawOffset; + rollOffset = motion.curAnim.joints[2].rollOffset; + } + + pitchOscLeft += pitchOffset; + pitchOscRight += pitchOffset; + + // apply lower leg joint rotations + MyAvatar.setJointData("LeftLeg", Quat.fromPitchYawRollDegrees( + pitchOscLeft, + yawOsc + yawOffset, + rollOsc + rollOffset)); + MyAvatar.setJointData("RightLeg", Quat.fromPitchYawRollDegrees( + pitchOscRight, + yawOsc - yawOffset, + rollOsc - rollOffset)); + + } // end if !state.SIDE_STEP + + else if (state.currentState === state.SIDE_STEP || + state.currentState === state.EDIT_SIDESTEP_LEFT || + state.currentState === state.EDIT_SIDESTEP_RIGHT) { + + // sidestepping uses the sinewave generators slightly differently for the legs + pitchOsc = motion.curAnim.joints[1].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[1].pitchPhase)); + + yawOsc = motion.curAnim.joints[1].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[1].yawPhase)); + + rollOsc = motion.curAnim.joints[1].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[1].rollPhase)); + + // apply upper leg rotations for sidestepping + MyAvatar.setJointData("RightUpLeg", Quat.fromPitchYawRollDegrees( + -pitchOsc + motion.curAnim.joints[1].pitchOffset, + yawOsc + motion.curAnim.joints[1].yawOffset, + rollOsc + motion.curAnim.joints[1].rollOffset)); + + MyAvatar.setJointData("LeftUpLeg", Quat.fromPitchYawRollDegrees( + pitchOsc + motion.curAnim.joints[1].pitchOffset, + yawOsc - motion.curAnim.joints[1].yawOffset, + -rollOsc - motion.curAnim.joints[1].rollOffset)); + + // calculate lower leg joint rotations for sidestepping + pitchOsc = motion.curAnim.joints[2].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].pitchPhase)); + + yawOsc = motion.curAnim.joints[2].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].yawPhase)); + + rollOsc = motion.curAnim.joints[2].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[2].rollPhase)); + + // apply lower leg joint rotations + MyAvatar.setJointData("RightLeg", Quat.fromPitchYawRollDegrees( + -pitchOsc + motion.curAnim.joints[2].pitchOffset, + yawOsc - motion.curAnim.joints[2].yawOffset, + rollOsc - motion.curAnim.joints[2].rollOffset)); + + MyAvatar.setJointData("LeftLeg", Quat.fromPitchYawRollDegrees( + pitchOsc + motion.curAnim.joints[2].pitchOffset, + yawOsc + motion.curAnim.joints[2].yawOffset, + rollOsc + motion.curAnim.joints[2].rollOffset)); + } + + // feet + if (motion.curAnim === motion.selSideStepLeft || + motion.curAnim === motion.selSideStepRight ) { + + sideStepHandPitchSign = -1; + sideStepFootPitchModifier = 0.5; + } + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOscLeft = motion.curAnim.joints[3].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[3].pitchPhase) + 180); + + pitchOscRight = motion.curAnim.joints[3].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[3].pitchPhase)); + + yawOsc = motion.curAnim.joints[3].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[3].yawPhase)); + + rollOsc = motion.curAnim.joints[3].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[3].rollPhase)); + + pitchOffset = motion.curAnim.joints[3].pitchOffset; + yawOffset = motion.curAnim.joints[3].yawOffset; + rollOffset = motion.curAnim.joints[3].rollOffset; + + pitchOscLeftLast = motion.curTransition.lastAnim.joints[3].pitch * + motion.curTransition.lastAnim.harmonics.leftFoot.calculate(filter.degToRad(reverseSignModifier * motion.walkWheelPos + + motion.curTransition.lastAnim.joints[3].pitchPhase + reverseModifier)); + + pitchOscRightLast = motion.curTransition.lastAnim.joints[3].pitch * + motion.curTransition.lastAnim.harmonics.rightFoot.calculate(filter.degToRad(reverseSignModifier * motion.walkWheelPos + + motion.curTransition.lastAnim.joints[3].pitchPhase + 180 + reverseModifier)); + + yawOscLast = motion.curTransition.lastAnim.joints[3].yaw * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[3].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[3].roll * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[3].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[3].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[3].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[3].rollOffset; + + } else { + + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { + + pitchOscLeft = motion.curAnim.harmonics.leftFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[3].pitchPhase + reverseModifier)); + + pitchOscRight = motion.curAnim.harmonics.rightFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[3].pitchPhase + 180 + reverseModifier)); + + } else { + + pitchOscLeft = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + + motion.curAnim.joints[3].pitchPhase)); + + pitchOscRight = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + + motion.curAnim.joints[3].pitchPhase + 180)); + } + + yawOsc = motion.curAnim.joints[3].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[3].yawPhase)); + + rollOsc = motion.curAnim.joints[3].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[3].rollPhase)); + + pitchOffset = motion.curAnim.joints[3].pitchOffset; + yawOffset = motion.curAnim.joints[3].yawOffset; + rollOffset = motion.curAnim.joints[3].rollOffset; + + pitchOscLeftLast = motion.curTransition.lastAnim.joints[3].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[3].pitchPhase + 180)); + + pitchOscRightLast = motion.curTransition.lastAnim.joints[3].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[3].pitchPhase)); + + yawOscLast = motion.curTransition.lastAnim.joints[3].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[3].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[3].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[3].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[3].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[3].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[3].rollOffset; + } + + pitchOscLeft = (transProgress * pitchOscLeft) + ((1 - transProgress) * pitchOscLeftLast); + pitchOscRight = (transProgress * pitchOscRight) + ((1 - transProgress) * pitchOscRightLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); + yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); + rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); + } else { - Overlays.editOverlay(armsFreeBigButtonSelected, { visible: false } ); - Overlays.editOverlay(armsFreeBigButton, { visible: showButtons } ); + + if (state.currentState === state.WALKING || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS) { + + pitchOscLeft = motion.curAnim.harmonics.leftFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[3].pitchPhase + reverseModifier)); + + pitchOscRight = motion.curAnim.harmonics.rightFoot.calculate(filter.degToRad(reverseSignModifier * cycle * adjFreq + + motion.curAnim.joints[3].pitchPhase + 180 + reverseModifier)); + + } else { + + pitchOscLeft = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + + motion.curAnim.joints[3].pitchPhase)); + + pitchOscRight = Math.sin(filter.degToRad(cycle * adjFreq * sideStepFootPitchModifier + + motion.curAnim.joints[3].pitchPhase + 180)); + } + + yawOsc = Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[3].yawPhase)); + + pitchOscLeft *= motion.curAnim.joints[3].pitch; + pitchOscRight *= motion.curAnim.joints[3].pitch; + + yawOsc *= motion.curAnim.joints[3].yaw; + + rollOsc = motion.curAnim.joints[3].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[3].rollPhase)); + + pitchOffset = motion.curAnim.joints[3].pitchOffset; + yawOffset = motion.curAnim.joints[3].yawOffset; + rollOffset = motion.curAnim.joints[3].rollOffset; } - if(playFootStepSounds) { - Overlays.editOverlay(footstepsBigButtonSelected, { visible: showButtons } ); - Overlays.editOverlay(footstepsBigButton, { visible: false } ); + + // apply foot rotations + MyAvatar.setJointData("LeftFoot", Quat.fromPitchYawRollDegrees( + pitchOscLeft + pitchOffset, + yawOsc - yawOffset, + rollOsc - rollOffset)); + + MyAvatar.setJointData("RightFoot", Quat.fromPitchYawRollDegrees( + pitchOscRight + pitchOffset, + yawOsc + yawOffset, + rollOsc + rollOffset)); + + // play footfall sound yet? To determine this, we take the differential of the + // foot's pitch curve to decide when the foot hits the ground. + if (state.currentState === state.WALKING || + state.currentState === state.SIDE_STEP || + state.currentState === state.EDIT_WALK_STYLES || + state.currentState === state.EDIT_WALK_TWEAKS || + state.currentState === state.EDIT_WALK_JOINTS || + state.currentState === state.EDIT_SIDESTEP_LEFT || + state.currentState === state.EDIT_SIDESTEP_RIGHT) { + + // find dy/dx by determining the cosine wave for the foot's pitch function. + var feetPitchDifferential = Math.cos(filter.degToRad((cycle * adjFreq) + motion.curAnim.joints[3].pitchPhase)); + var threshHold = 0.9; // sets the audio trigger point. with accuracy. + if (feetPitchDifferential < -threshHold && + motion.nextStep === LEFT && + motion.direction !== UP && + motion.direction !== DOWN) { + + playFootstep(LEFT); + motion.nextStep = RIGHT; + } else if (feetPitchDifferential > threshHold && + motion.nextStep === RIGHT && + motion.direction !== UP && + motion.direction !== DOWN) { + + playFootstep(RIGHT); + motion.nextStep = LEFT; + } + } + + // toes + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[4].pitch * + Math.sin(filter.degToRad((2 * motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[4].pitchPhase)); + + yawOsc = motion.curAnim.joints[4].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[4].yawPhase)); + + rollOsc = motion.curAnim.joints[4].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[4].rollPhase)); + + pitchOffset = motion.curAnim.joints[4].pitchOffset; + yawOffset = motion.curAnim.joints[4].yawOffset; + rollOffset = motion.curAnim.joints[4].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[4].pitch * + Math.sin(filter.degToRad((2 * motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[4].pitchPhase)); + + yawOscLast = motion.curTransition.lastAnim.joints[4].yaw * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[4].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[4].roll * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[4].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[4].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[4].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[4].rollOffset; + + } else { + + pitchOsc = motion.curAnim.joints[4].pitch * + Math.sin(filter.degToRad((2 * cycle * adjFreq) + + motion.curAnim.joints[4].pitchPhase)); + + yawOsc = motion.curAnim.joints[4].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[4].yawPhase)); + + rollOsc = motion.curAnim.joints[4].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[4].rollPhase)); + + pitchOffset = motion.curAnim.joints[4].pitchOffset; + yawOffset = motion.curAnim.joints[4].yawOffset; + rollOffset = motion.curAnim.joints[4].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[4].pitch * + Math.sin(filter.degToRad((2 * motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[4].pitchPhase)); + + yawOscLast = motion.curTransition.lastAnim.joints[4].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[4].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[4].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[4].rollPhase)); + + pitchOffsetLast = motion.curTransition.lastAnim.joints[4].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[4].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[4].rollOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); + yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); + rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); + } else { - Overlays.editOverlay(footstepsBigButtonSelected, { visible: false } ); - Overlays.editOverlay(footstepsBigButton, { visible: showButtons } ); - } -} -function minimiseDialog() { - if(minimised) { - setBackground(); - hidebuttonOverlays(); - setSliderThumbsVisible(false); - hideJointControls(); - showFrontPanelButtons(false); - Overlays.editOverlay(controlsMinimisedTab, { visible: true } ); - } else { - setInternalState(STANDING); // show all the controls again - Overlays.editOverlay(controlsMinimisedTab, { visible: false } ); - } -} -function setBackground(backgroundName) { - for(var i in backgroundOverlays) { - if(backgroundOverlays[i] === backgroundName) - Overlays.editOverlay(backgroundName, { visible: true } ); - else Overlays.editOverlay(backgroundOverlays[i], { visible: false } ); - } -} -function setButtonOverlayVisible(buttonOverlayName) { - for(var i in buttonOverlays) { - if(buttonOverlays[i] === buttonOverlayName) { - Overlays.editOverlay(buttonOverlayName, { visible: true } ); - } - } -} -// top row menu type buttons (smaller) -function hidebuttonOverlays() { - for(var i in buttonOverlays) { - Overlays.editOverlay(buttonOverlays[i], { visible: false } ); - } -} -function hideJointControls() { - for(var i in jointsControlOverlays) { - Overlays.editOverlay(jointsControlOverlays[i], { visible: false } ); - } -} -function setSliderThumbsVisible(thumbsVisible) { - for(var i = 0 ; i < sliderThumbOverlays.length ; i++) { - Overlays.editOverlay(sliderThumbOverlays[i], { visible: thumbsVisible } ); - } -} -function initialiseJointsEditingPanel(propertyIndex) { + pitchOsc = motion.curAnim.joints[4].pitch * + Math.sin(filter.degToRad((2 * cycle * adjFreq) + + motion.curAnim.joints[4].pitchPhase)); - selectedJointIndex = propertyIndex; + yawOsc = motion.curAnim.joints[4].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[4].yawPhase)); - // set the image for the selected joint on the character control - hideJointControls(); - switch (selectedJointIndex) { - case 0: - Overlays.editOverlay(hipsJointControl, { visible: true }); - break; - case 1: - Overlays.editOverlay(upperLegsJointControl, { visible: true }); - break; - case 2: - Overlays.editOverlay(lowerLegsJointControl, { visible: true }); - break; - case 3: - Overlays.editOverlay(feetJointControl, { visible: true }); - break; - case 4: - Overlays.editOverlay(toesJointControl, { visible: true }); - break; - case 5: - Overlays.editOverlay(spineJointControl, { visible: true }); - break; - case 6: - Overlays.editOverlay(spine1JointControl, { visible: true }); - break; - case 7: - Overlays.editOverlay(spine2JointControl, { visible: true }); - break; - case 8: - Overlays.editOverlay(shouldersJointControl, { visible: true }); - break; - case 9: - Overlays.editOverlay(upperArmsJointControl, { visible: true }); - break; - case 10: - Overlays.editOverlay(forearmsJointControl, { visible: true }); - break; - case 11: - Overlays.editOverlay(handsJointControl, { visible: true }); - break; - case 12: - Overlays.editOverlay(headJointControl, { visible: true }); - break; - } + rollOsc = motion.curAnim.joints[4].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[4].rollPhase)); - // set sliders to adjust individual joint properties - var i = 0; - var yLocation = backgroundY+359; - - // pitch your role - var sliderXPos = currentAnimation.joints[selectedJointIndex].pitch - / sliderRanges.joints[selectedJointIndex].pitchRange * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - sliderXPos = currentAnimation.joints[selectedJointIndex].yaw - / sliderRanges.joints[selectedJointIndex].yawRange * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - sliderXPos = currentAnimation.joints[selectedJointIndex].roll - / sliderRanges.joints[selectedJointIndex].rollRange * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - - // set phases (full range, -180 to 180) - sliderXPos = (90 + currentAnimation.joints[selectedJointIndex].pitchPhase/2)/180 * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - sliderXPos = (90 + currentAnimation.joints[selectedJointIndex].yawPhase/2)/180 * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - sliderXPos = (90 + currentAnimation.joints[selectedJointIndex].rollPhase/2)/180 * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - - // offset ranges are also -ve thr' zero to +ve, so have to offset - sliderXPos = (((sliderRanges.joints[selectedJointIndex].pitchOffsetRange+currentAnimation.joints[selectedJointIndex].pitchOffset)/2) - /sliderRanges.joints[selectedJointIndex].pitchOffsetRange) * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - sliderXPos = (((sliderRanges.joints[selectedJointIndex].yawOffsetRange+currentAnimation.joints[selectedJointIndex].yawOffset)/2) - /sliderRanges.joints[selectedJointIndex].yawOffsetRange) * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); - sliderXPos = (((sliderRanges.joints[selectedJointIndex].rollOffsetRange+currentAnimation.joints[selectedJointIndex].rollOffset)/2) - /sliderRanges.joints[selectedJointIndex].rollOffsetRange) * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=30, visible: true }); -} - -function initialiseWalkTweaks() { - - // set sliders to adjust walk properties - var i = 0; - var yLocation = backgroundY+71; - - var sliderXPos = currentAnimation.settings.baseFrequency / MAX_WALK_SPEED * sliderRangeX; // walk speed - Overlays.editOverlay(sliderThumbOverlays[i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = 0 * sliderRangeX; // start flying speed - depricated - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = currentAnimation.joints[0].sway / sliderRanges.joints[0].swayRange * sliderRangeX; // Hips sway - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = currentAnimation.joints[0].bob / sliderRanges.joints[0].bobRange * sliderRangeX; // Hips bob - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = currentAnimation.joints[0].thrust / sliderRanges.joints[0].thrustRange * sliderRangeX; // Hips thrust - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = (((sliderRanges.joints[1].rollOffsetRange+currentAnimation.joints[1].rollOffset)/2) // legs separation - is upper legs roll offset - / sliderRanges.joints[1].rollOffsetRange) * sliderRangeX; - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = currentAnimation.joints[1].pitch / sliderRanges.joints[1].pitchRange * sliderRangeX; // stride - is upper legs pitch - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = currentAnimation.joints[9].yaw / sliderRanges.joints[9].yawRange * sliderRangeX; // arms swing - is upper arms yaw - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); - sliderXPos = (((sliderRanges.joints[9].pitchOffsetRange-currentAnimation.joints[9].pitchOffset)/2) - / sliderRanges.joints[9].pitchOffsetRange) * sliderRangeX; // arms out - is upper arms pitch offset - Overlays.editOverlay(sliderThumbOverlays[++i], { x: minSliderX + sliderXPos, y: yLocation+=60, visible: true }); -} - -function showWalkStyleButtons(showButtons) { - - // set all big buttons to hidden, but skip the first 8, as are for the front panel - for(var i = 8 ; i < bigButtonOverlays.length ; i++) { - Overlays.editOverlay(bigButtonOverlays[i], { visible: false }); + pitchOffset = motion.curAnim.joints[4].pitchOffset; + yawOffset = motion.curAnim.joints[4].yawOffset; + rollOffset = motion.curAnim.joints[4].rollOffset; } - if(!showButtons) return; + // apply toe rotations + MyAvatar.setJointData("RightToeBase", Quat.fromPitchYawRollDegrees( + pitchOsc + pitchOffset, + yawOsc + yawOffset, + rollOsc + rollOffset)); - // set all the non-selected ones to showing - for(var i = 8 ; i < bigButtonOverlays.length ; i+=2) { - Overlays.editOverlay(bigButtonOverlays[i], { visible: showButtons }); + MyAvatar.setJointData("LeftToeBase", Quat.fromPitchYawRollDegrees( + pitchOsc + pitchOffset, + yawOsc - yawOffset, + rollOsc - rollOffset)); + + // spine + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[5].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency * 2) + + motion.curAnim.joints[5].pitchPhase)) + + motion.curAnim.joints[5].pitchOffset; + + yawOsc = motion.curAnim.joints[5].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[5].yawPhase)) + + motion.curAnim + .joints[5].yawOffset; + + rollOsc = motion.curAnim.joints[5].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[5].rollPhase)) + + motion.curAnim.joints[5].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[5].pitch * + Math.sin(filter.degToRad((motion.walkWheelPos * 2) + + motion.curTransition.lastAnim.joints[5].pitchPhase)) + + motion.curTransition.lastAnim.joints[5].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[5].yaw * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[5].yawPhase)) + + motion.curTransition.lastAnim.joints[5].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[5].roll * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[5].rollPhase)) + + motion.curTransition.lastAnim.joints[5].rollOffset; + } else { + + pitchOsc = motion.curAnim.joints[5].pitch * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[5].pitchPhase)) + + motion.curAnim.joints[5].pitchOffset; + + yawOsc = motion.curAnim.joints[5].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[5].yawPhase)) + + motion.curAnim.joints[5].yawOffset; + + rollOsc = motion.curAnim.joints[5].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[5].rollPhase)) + + motion.curAnim.joints[5].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[5].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency * 2) + + motion.curTransition.lastAnim.joints[5].pitchPhase)) + + motion.curTransition.lastAnim.joints[5].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[5].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[5].yawPhase)) + + motion.curTransition.lastAnim.joints[5].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[5].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[5].rollPhase)) + + motion.curTransition.lastAnim.joints[5].rollOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + } else { + + pitchOsc = motion.curAnim.joints[5].pitch * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[5].pitchPhase)) + + motion.curAnim.joints[5].pitchOffset; + + yawOsc = motion.curAnim.joints[5].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[5].yawPhase)) + + motion.curAnim.joints[5].yawOffset; + + rollOsc = motion.curAnim.joints[5].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[5].rollPhase)) + + motion.curAnim.joints[5].rollOffset; } - // set the currently selected one - if(selectedWalk === femaleStrutWalk || selectedWalk === maleStrutWalk) { - Overlays.editOverlay(strutWalkBigButtonSelected, { visible: showButtons }); - Overlays.editOverlay(strutWalkBigButton, {visible: false}); + // apply spine joint rotations + MyAvatar.setJointData("Spine", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); + + // spine 1 + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[6].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency * 2) + + motion.curAnim.joints[6].pitchPhase)) + + motion.curAnim.joints[6].pitchOffset; + + yawOsc = motion.curAnim.joints[6].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[6].yawPhase)) + + motion.curAnim.joints[6].yawOffset; + + rollOsc = motion.curAnim.joints[6].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[6].rollPhase)) + + motion.curAnim.joints[6].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[6].pitch * + Math.sin(filter.degToRad((motion.walkWheelPos * 2) + + motion.curTransition.lastAnim.joints[6].pitchPhase)) + + motion.curTransition.lastAnim.joints[6].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[6].yaw * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[6].yawPhase)) + + motion.curTransition.lastAnim.joints[6].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[6].roll * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[6].rollPhase)) + + motion.curTransition.lastAnim.joints[6].rollOffset; + + } else { + + pitchOsc = motion.curAnim.joints[6].pitch * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[6].pitchPhase)) + + motion.curAnim.joints[6].pitchOffset; + + yawOsc = motion.curAnim.joints[6].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[6].yawPhase)) + + motion.curAnim.joints[6].yawOffset; + + rollOsc = motion.curAnim.joints[6].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[6].rollPhase)) + + motion.curAnim.joints[6].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[6].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency * 2) + + motion.curTransition.lastAnim.joints[6].pitchPhase)) + + motion.curTransition.lastAnim.joints[6].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[6].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[6].yawPhase)) + + motion.curTransition.lastAnim.joints[6].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[6].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[6].rollPhase)) + + motion.curTransition.lastAnim.joints[6].rollOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + } else { + + pitchOsc = motion.curAnim.joints[6].pitch * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[6].pitchPhase)) + + motion.curAnim.joints[6].pitchOffset; + + yawOsc = motion.curAnim.joints[6].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[6].yawPhase)) + + motion.curAnim.joints[6].yawOffset; + + rollOsc = motion.curAnim.joints[6].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[6].rollPhase)) + + motion.curAnim.joints[6].rollOffset; } + + // apply spine1 joint rotations + MyAvatar.setJointData("Spine1", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); + + // spine 2 + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[7].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency * 2 + + motion.curAnim.joints[7].pitchPhase)) + + motion.curAnim.joints[7].pitchOffset; + + yawOsc = motion.curAnim.joints[7].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[7].yawPhase)) + + motion.curAnim.joints[7].yawOffset; + + rollOsc = motion.curAnim.joints[7].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[7].rollPhase)) + + motion.curAnim.joints[7].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[7].pitch * + Math.sin(filter.degToRad(motion.walkWheelPos * 2 + + motion.curTransition.lastAnim.joints[7].pitchPhase)) + + motion.curTransition.lastAnim.joints[7].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[7].yaw * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[7].yawPhase)) + + motion.curTransition.lastAnim.joints[7].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[7].roll * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[7].rollPhase)) + + motion.curTransition.lastAnim.joints[7].rollOffset; + } else { + + pitchOsc = motion.curAnim.joints[7].pitch * + Math.sin(filter.degToRad(cycle * adjFreq * 2 + + motion.curAnim.joints[7].pitchPhase)) + + motion.curAnim.joints[7].pitchOffset; + + yawOsc = motion.curAnim.joints[7].yaw * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[7].yawPhase)) + + motion.curAnim.joints[7].yawOffset; + + rollOsc = motion.curAnim.joints[7].roll * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[7].rollPhase)) + + motion.curAnim.joints[7].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[7].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * 2 * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[7].pitchPhase)) + + motion.curTransition.lastAnim.joints[7].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[7].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[7].yawPhase)) + + motion.curTransition.lastAnim.joints[7].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[7].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[7].rollPhase)) + + motion.curTransition.lastAnim.joints[7].rollOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + } else { + + pitchOsc = motion.curAnim.joints[7].pitch * + Math.sin(filter.degToRad(cycle * adjFreq * 2 + + motion.curAnim.joints[7].pitchPhase)) + + motion.curAnim.joints[7].pitchOffset; + + yawOsc = motion.curAnim.joints[7].yaw * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[7].yawPhase)) + + motion.curAnim.joints[7].yawOffset; + + rollOsc = motion.curAnim.joints[7].roll * + Math.sin(filter.degToRad(cycle * adjFreq + + motion.curAnim.joints[7].rollPhase)) + + motion.curAnim.joints[7].rollOffset; + } + + // apply spine2 joint rotations + MyAvatar.setJointData("Spine2", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); + + if (!motion.armsFree) { + + // shoulders + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[8].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[8].pitchPhase)) + + motion.curAnim.joints[8].pitchOffset; + + yawOsc = motion.curAnim.joints[8].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[8].yawPhase)); + + rollOsc = motion.curAnim.joints[8].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curAnim.calibration.frequency + + motion.curAnim.joints[8].rollPhase)) + + motion.curAnim.joints[8].rollOffset; + + yawOffset = motion.curAnim.joints[8].yawOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[8].pitch * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[8].pitchPhase)) + + motion.curTransition.lastAnim.joints[8].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[8].yaw * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[8].yawPhase)) + + rollOscLast = motion.curTransition.lastAnim.joints[8].roll * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[8].rollPhase)) + + motion.curTransition.lastAnim.joints[8].rollOffset; + + yawOffsetLast = motion.curTransition.lastAnim.joints[8].yawOffset; + + } else { + + pitchOsc = motion.curAnim.joints[8].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[8].pitchPhase)) + + motion.curAnim.joints[8].pitchOffset; + + yawOsc = motion.curAnim.joints[8].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[8].yawPhase)); + + rollOsc = motion.curAnim.joints[8].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[8].rollPhase)) + + motion.curAnim.joints[8].rollOffset; + + yawOffset = motion.curAnim.joints[8].yawOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[8].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[8].pitchPhase)) + + motion.curTransition.lastAnim.joints[8].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[8].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[8].yawPhase)) + + rollOscLast = motion.curTransition.lastAnim.joints[8].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[8].rollPhase)) + + motion.curTransition.lastAnim.joints[8].rollOffset; + + yawOffsetLast = motion.curTransition.lastAnim.joints[8].yawOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); + + } else { + + pitchOsc = motion.curAnim.joints[8].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[8].pitchPhase)) + + motion.curAnim.joints[8].pitchOffset; + + yawOsc = motion.curAnim.joints[8].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[8].yawPhase)); + + rollOsc = motion.curAnim.joints[8].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[8].rollPhase)) + + motion.curAnim.joints[8].rollOffset; + + yawOffset = motion.curAnim.joints[8].yawOffset; + } + + MyAvatar.setJointData("RightShoulder", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc + yawOffset, rollOsc)); + MyAvatar.setJointData("LeftShoulder", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc - yawOffset, -rollOsc)); + + // upper arms + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[9].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[9].pitchPhase)); + + yawOsc = motion.curAnim.joints[9].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[9].yawPhase)); + + rollOsc = motion.curAnim.joints[9].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency * 2) + + motion.curAnim.joints[9].rollPhase)) + + motion.curAnim.joints[9].rollOffset; + + pitchOffset = motion.curAnim.joints[9].pitchOffset; + yawOffset = motion.curAnim.joints[9].yawOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[9].pitch * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[9].pitchPhase)); + + yawOscLast = motion.curTransition.lastAnim.joints[9].yaw * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[9].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[9].roll * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[9].rollPhase)) + + motion.curTransition.lastAnim.joints[9].rollOffset; + + pitchOffsetLast = motion.curTransition.lastAnim.joints[9].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[9].yawOffset; + + } else { + + pitchOsc = motion.curAnim.joints[9].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[9].pitchPhase)); + + yawOsc = motion.curAnim.joints[9].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[9].yawPhase)); + + rollOsc = motion.curAnim.joints[9].roll * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[9].rollPhase)) + + motion.curAnim.joints[9].rollOffset; + + pitchOffset = motion.curAnim.joints[9].pitchOffset; + yawOffset = motion.curAnim.joints[9].yawOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[9].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[9].pitchPhase)) + + yawOscLast = motion.curTransition.lastAnim.joints[9].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[9].yawPhase)) + + rollOscLast = motion.curTransition.lastAnim.joints[9].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[9].rollPhase)) + + motion.curTransition.lastAnim.joints[9].rollOffset; + + pitchOffsetLast = motion.curTransition.lastAnim.joints[9].pitchOffset; + yawOffsetLast = motion.curTransition.lastAnim.joints[9].yawOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + pitchOffset = (transProgress * pitchOffset) + ((1 - transProgress) * pitchOffsetLast); + yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); + + } else { + + pitchOsc = motion.curAnim.joints[9].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[9].pitchPhase)); + + yawOsc = motion.curAnim.joints[9].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[9].yawPhase)); + + rollOsc = motion.curAnim.joints[9].roll * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[9].rollPhase)) + + motion.curAnim.joints[9].rollOffset; + + pitchOffset = motion.curAnim.joints[9].pitchOffset; + yawOffset = motion.curAnim.joints[9].yawOffset; + + } + + MyAvatar.setJointData("RightArm", Quat.fromPitchYawRollDegrees( + (-1 * flyingModifier) * pitchOsc + pitchOffset, + yawOsc - yawOffset, + rollOsc)); + + MyAvatar.setJointData("LeftArm", Quat.fromPitchYawRollDegrees( + pitchOsc + pitchOffset, + yawOsc + yawOffset, + -rollOsc)); + + // forearms + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[10].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[10].pitchPhase)) + + motion.curAnim.joints[10].pitchOffset; + + yawOsc = motion.curAnim.joints[10].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[10].yawPhase)); + + rollOsc = motion.curAnim.joints[10].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[10].rollPhase)); + + yawOffset = motion.curAnim.joints[10].yawOffset; + rollOffset = motion.curAnim.joints[10].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[10].pitch * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[10].pitchPhase)) + + motion.curTransition.lastAnim.joints[10].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[10].yaw * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[10].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[10].roll * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[10].rollPhase)); + + yawOffsetLast = motion.curTransition.lastAnim.joints[10].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[10].rollOffset; + + } else { + + pitchOsc = motion.curAnim.joints[10].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[10].pitchPhase)) + + motion.curAnim.joints[10].pitchOffset; + + yawOsc = motion.curAnim.joints[10].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[10].yawPhase)); + + rollOsc = motion.curAnim.joints[10].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[10].rollPhase)); + + yawOffset = motion.curAnim.joints[10].yawOffset; + rollOffset = motion.curAnim.joints[10].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[10].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[10].pitchPhase)) + + motion.curTransition.lastAnim.joints[10].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[10].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[10].yawPhase)); + + rollOscLast = motion.curTransition.lastAnim.joints[10].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[10].rollPhase)); + + yawOffsetLast = motion.curTransition.lastAnim.joints[10].yawOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[10].rollOffset; + } + + // blend the animations + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = -(transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + yawOffset = (transProgress * yawOffset) + ((1 - transProgress) * yawOffsetLast); + rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); + + } else { + + pitchOsc = motion.curAnim.joints[10].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[10].pitchPhase)) + + motion.curAnim.joints[10].pitchOffset; + + yawOsc = motion.curAnim.joints[10].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[10].yawPhase)); + + rollOsc = motion.curAnim.joints[10].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[10].rollPhase)); + + yawOffset = motion.curAnim.joints[10].yawOffset; + rollOffset = motion.curAnim.joints[10].rollOffset; + } + + // apply forearms rotations + MyAvatar.setJointData("RightForeArm", + Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc + yawOffset, rollOsc + rollOffset)); + MyAvatar.setJointData("LeftForeArm", + Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc - yawOffset, rollOsc - rollOffset)); + + // hands + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = motion.curAnim.joints[11].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[11].pitchPhase)) + + motion.curAnim.joints[11].pitchOffset; + + yawOsc = motion.curAnim.joints[11].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[11].yawPhase)) + + motion.curAnim.joints[11].yawOffset; + + rollOsc = motion.curAnim.joints[11].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[11].rollPhase)); + + pitchOscLast = motion.curTransition.lastAnim.joints[11].pitch * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[11].pitchPhase)) + + motion.curTransition.lastAnim.joints[11].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[11].yaw * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[11].yawPhase)) + + motion.curTransition.lastAnim.joints[11].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[11].roll * + Math.sin(filter.degToRad(motion.walkWheelPos + + motion.curTransition.lastAnim.joints[11].rollPhase)) + + rollOffset = motion.curAnim.joints[11].rollOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[11].rollOffset; + + } else { + + pitchOsc = motion.curAnim.joints[11].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[11].pitchPhase)) + + motion.curAnim.joints[11].pitchOffset; + + yawOsc = motion.curAnim.joints[11].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[11].yawPhase)) + + motion.curAnim.joints[11].yawOffset; + + rollOsc = motion.curAnim.joints[11].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[11].rollPhase)); + + rollOffset = motion.curAnim.joints[11].rollOffset; + + pitchOscLast = motion.curTransition.lastAnim.joints[11].pitch * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[11].pitchPhase)) + + motion.curTransition.lastAnim.joints[11].pitchOffset; + + yawOscLast = motion.curTransition.lastAnim.joints[11].yaw * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[11].yawPhase)) + + motion.curTransition.lastAnim.joints[11].yawOffset; + + rollOscLast = motion.curTransition.lastAnim.joints[11].roll * + Math.sin(filter.degToRad(motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency + + motion.curTransition.lastAnim.joints[11].rollPhase)) + + rollOffset = motion.curAnim.joints[11].rollOffset; + rollOffsetLast = motion.curTransition.lastAnim.joints[11].rollOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + rollOffset = (transProgress * rollOffset) + ((1 - transProgress) * rollOffsetLast); + + } else { + + pitchOsc = motion.curAnim.joints[11].pitch * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[11].pitchPhase)) + + motion.curAnim.joints[11].pitchOffset; + + yawOsc = motion.curAnim.joints[11].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[11].yawPhase)) + + motion.curAnim.joints[11].yawOffset; + + rollOsc = motion.curAnim.joints[11].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[11].rollPhase)); + + rollOffset = motion.curAnim.joints[11].rollOffset; + } + + // set the hand rotations + MyAvatar.setJointData("RightHand", + Quat.fromPitchYawRollDegrees(sideStepHandPitchSign * pitchOsc, yawOsc, rollOsc + rollOffset)); + MyAvatar.setJointData("LeftHand", + Quat.fromPitchYawRollDegrees(pitchOsc, -yawOsc, rollOsc - rollOffset)); + + } // end if (!motion.armsFree) + + // head and neck + if (motion.curTransition !== nullTransition) { + + if (motion.curTransition.walkingAtStart) { + + pitchOsc = 0.5 * motion.curAnim.joints[12].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency * 2) + + motion.curAnim.joints[12].pitchPhase)) + + motion.curAnim.joints[12].pitchOffset; + + yawOsc = 0.5 * motion.curAnim.joints[12].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[12].yawPhase)) + + motion.curAnim.joints[12].yawOffset; + + rollOsc = 0.5 * motion.curAnim.joints[12].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curAnim.calibration.frequency) + + motion.curAnim.joints[12].rollPhase)) + + motion.curAnim.joints[12].rollOffset; + + pitchOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].pitch * + Math.sin(filter.degToRad((motion.walkWheelPos * 2) + + motion.curTransition.lastAnim.joints[12].pitchPhase)) + + motion.curTransition.lastAnim.joints[12].pitchOffset; + + yawOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].yaw * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[12].yawPhase)) + + motion.curTransition.lastAnim.joints[12].yawOffset; + + rollOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].roll * + Math.sin(filter.degToRad((motion.walkWheelPos) + + motion.curTransition.lastAnim.joints[12].rollPhase)) + + motion.curTransition.lastAnim.joints[12].rollOffset; + + } else { + + pitchOsc = 0.5 * motion.curAnim.joints[12].pitch * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[12].pitchPhase)) + + motion.curAnim.joints[12].pitchOffset; + + yawOsc = 0.5 * motion.curAnim.joints[12].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[12].yawPhase)) + + motion.curAnim.joints[12].yawOffset; + + rollOsc = 0.5 * motion.curAnim.joints[12].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[12].rollPhase)) + + motion.curAnim.joints[12].rollOffset; + + pitchOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].pitch * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency * 2) + + motion.curTransition.lastAnim.joints[12].pitchPhase)) + + motion.curTransition.lastAnim.joints[12].pitchOffset; + + yawOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].yaw * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[12].yawPhase)) + + motion.curTransition.lastAnim.joints[12].yawOffset; + + rollOscLast = 0.5 * motion.curTransition.lastAnim.joints[12].roll * + Math.sin(filter.degToRad((motion.cumulativeTime * + motion.curTransition.lastAnim.calibration.frequency) + + motion.curTransition.lastAnim.joints[12].rollPhase)) + + motion.curTransition.lastAnim.joints[12].rollOffset; + } + + pitchOsc = (transProgress * pitchOsc) + ((1 - transProgress) * pitchOscLast); + yawOsc = (transProgress * yawOsc) + ((1 - transProgress) * yawOscLast); + rollOsc = (transProgress * rollOsc) + ((1 - transProgress) * rollOscLast); + + } else { + + pitchOsc = 0.5 * motion.curAnim.joints[12].pitch * + Math.sin(filter.degToRad((cycle * adjFreq * 2) + + motion.curAnim.joints[12].pitchPhase)) + + motion.curAnim.joints[12].pitchOffset; + + yawOsc = 0.5 * motion.curAnim.joints[12].yaw * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[12].yawPhase)) + + motion.curAnim.joints[12].yawOffset; + + rollOsc = 0.5 * motion.curAnim.joints[12].roll * + Math.sin(filter.degToRad((cycle * adjFreq) + + motion.curAnim.joints[12].rollPhase)) + + motion.curAnim.joints[12].rollOffset; + } + + MyAvatar.setJointData("Head", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); + MyAvatar.setJointData("Neck", Quat.fromPitchYawRollDegrees(pitchOsc, yawOsc, rollOsc)); } -// mouse event handlers -var movingSliderOne = false; -var movingSliderTwo = false; -var movingSliderThree = false; -var movingSliderFour = false; -var movingSliderFive = false; -var movingSliderSix = false; -var movingSliderSeven = false; -var movingSliderEight = false; -var movingSliderNine = false; - -function mousePressEvent(event) { - - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - // check for a character joint control click - switch (clickedOverlay) { - - case hideButton: - Overlays.editOverlay(hideButton, { visible: false } ); - Overlays.editOverlay(hideButtonSelected, { visible: true } ); - return; - - case backButton: - Overlays.editOverlay(backButton, { visible: false } ); - Overlays.editOverlay(backButtonSelected, { visible: true } ); - return; - - case controlsMinimisedTab: - // TODO: add visual user feedback for tab click - return; - - case footstepsBigButton: - playFootStepSounds = true; - Overlays.editOverlay(footstepsBigButtonSelected, { visible: true } ); - Overlays.editOverlay(footstepsBigButton, { visible: false } ); - return; - - case footstepsBigButtonSelected: - playFootStepSounds = false; - Overlays.editOverlay(footstepsBigButton, { visible: true } ); - Overlays.editOverlay(footstepsBigButtonSelected, { visible: false } ); - return; - - case femaleBigButton: - case maleBigButtonSelected: - avatarGender = FEMALE; - selectedWalk = femaleStrutWalk; - selectedStand = femaleStandOne; - selectedFlyUp = femaleFlyingUp; - selectedFly = femaleFlying; - selectedFlyDown = femaleFlyingDown; - selectedSideStepLeft = femaleSideStepLeft; - selectedSideStepRight = femaleSideStepRight; - Overlays.editOverlay(femaleBigButtonSelected, { visible: true } ); - Overlays.editOverlay(femaleBigButton, { visible: false } ); - Overlays.editOverlay(maleBigButton, { visible: true } ); - Overlays.editOverlay(maleBigButtonSelected, { visible: false } ); - return; - - case armsFreeBigButton: - armsFree = true; - Overlays.editOverlay(armsFreeBigButtonSelected, { visible: true } ); - Overlays.editOverlay(armsFreeBigButton, { visible: false } ); - return; - - case armsFreeBigButtonSelected: - armsFree = false; - Overlays.editOverlay(armsFreeBigButtonSelected, { visible: false } ); - Overlays.editOverlay(armsFreeBigButton, { visible: true } ); - return; - - case maleBigButton: - case femaleBigButtonSelected: - avatarGender = MALE; - selectedWalk = maleStrutWalk; - selectedStand = maleStandOne; - selectedFlyUp = maleFlyingUp; - selectedFly = maleFlying; - selectedFlyDown = maleFlyingDown; - selectedSideStepLeft = maleSideStepLeft; - selectedSideStepRight = maleSideStepRight; - Overlays.editOverlay(femaleBigButton, { visible: true } ); - Overlays.editOverlay(femaleBigButtonSelected, { visible: false } ); - Overlays.editOverlay(maleBigButtonSelected, { visible: true } ); - Overlays.editOverlay(maleBigButton, { visible: false } ); - return; - - - case strutWalkBigButton: - if(avatarGender===FEMALE) selectedWalk = femaleStrutWalk; - else selectedWalk = maleStrutWalk; - currentAnimation = selectedWalk; - showWalkStyleButtons(true); - return; - - case strutWalkBigButtonSelected: - - // toggle forwards / backwards walk display - if(principleDirection===DIRECTION_FORWARDS) { - principleDirection=DIRECTION_BACKWARDS; - } else principleDirection=DIRECTION_FORWARDS; - return; - - case sliderOne: - movingSliderOne = true; - return; - - case sliderTwo: - movingSliderTwo = true; - return; - - case sliderThree: - movingSliderThree = true; - return; - - case sliderFour: - movingSliderFour = true; - return; - - case sliderFive: - movingSliderFive = true; - return; - - case sliderSix: - movingSliderSix = true; - return; - - case sliderSeven: - movingSliderSeven = true; - return; - - case sliderEight: - movingSliderEight = true; - return; - - case sliderNine: - movingSliderNine = true; - return; - } - - if( INTERNAL_STATE===CONFIG_WALK_JOINTS || - INTERNAL_STATE===CONFIG_STANDING || - INTERNAL_STATE===CONFIG_FLYING || - INTERNAL_STATE===CONFIG_FLYING_UP || - INTERNAL_STATE===CONFIG_FLYING_DOWN || - INTERNAL_STATE===CONFIG_SIDESTEP_LEFT || - INTERNAL_STATE===CONFIG_SIDESTEP_RIGHT ) { - - // check for new joint selection and update display accordingly - var clickX = event.x - backgroundX - 75; - var clickY = event.y - backgroundY - 92; - - if(clickX>60&&clickX<120&&clickY>123&&clickY<155) { - initialiseJointsEditingPanel(0); - return; - } - else if(clickX>63&&clickX<132&&clickY>156&&clickY<202) { - initialiseJointsEditingPanel(1); - return; - } - else if(clickX>58&&clickX<137&&clickY>203&&clickY<250) { - initialiseJointsEditingPanel(2); - return; - } - else if(clickX>58&&clickX<137&&clickY>250&&clickY<265) { - initialiseJointsEditingPanel(3); - return; - } - else if(clickX>58&&clickX<137&&clickY>265&&clickY<280) { - initialiseJointsEditingPanel(4); - return; - } - else if(clickX>78&&clickX<121&&clickY>111&&clickY<128) { - initialiseJointsEditingPanel(5); - return; - } - else if(clickX>78&&clickX<128&&clickY>89&&clickY<111) { - initialiseJointsEditingPanel(6); - return; - } - else if(clickX>85&&clickX<118&&clickY>77&&clickY<94) { - initialiseJointsEditingPanel(7); - return; - } - else if(clickX>64&&clickX<125&&clickY>55&&clickY<77) { - initialiseJointsEditingPanel(8); - return; - } - else if((clickX>44&&clickX<73&&clickY>71&&clickY<94) - ||(clickX>125&&clickX<144&&clickY>71&&clickY<94)) { - initialiseJointsEditingPanel(9); - return; - } - else if((clickX>28&&clickX<57&&clickY>94&&clickY<119) - ||(clickX>137&&clickX<170&&clickY>97&&clickY<114)) { - initialiseJointsEditingPanel(10); - return; - } - else if((clickX>18&&clickX<37&&clickY>115&&clickY<136) - ||(clickX>157&&clickX<182&&clickY>115&&clickY<136)) { - initialiseJointsEditingPanel(11); - return; - } - else if(clickX>81&&clickX<116&&clickY>12&&clickY<53) { - initialiseJointsEditingPanel(12); - return; - } - } -} -function mouseMoveEvent(event) { - - // only need deal with slider changes - if(powerOn) { - - if( INTERNAL_STATE===CONFIG_WALK_JOINTS || - INTERNAL_STATE===CONFIG_STANDING || - INTERNAL_STATE===CONFIG_FLYING || - INTERNAL_STATE===CONFIG_FLYING_UP || - INTERNAL_STATE===CONFIG_FLYING_DOWN || - INTERNAL_STATE===CONFIG_SIDESTEP_LEFT || - INTERNAL_STATE===CONFIG_SIDESTEP_RIGHT ) { - - var thumbClickOffsetX = event.x - minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX; - if(thumbPositionNormalised<0) thumbPositionNormalised = 0; - if(thumbPositionNormalised>1) thumbPositionNormalised = 1; - var sliderX = thumbPositionNormalised * sliderRangeX ; // sets range - - if(movingSliderOne) { // currently selected joint pitch - Overlays.editOverlay(sliderOne, { x: sliderX + minSliderX} ); - currentAnimation.joints[selectedJointIndex].pitch = thumbPositionNormalised * sliderRanges.joints[selectedJointIndex].pitchRange; - } - else if(movingSliderTwo) { // currently selected joint yaw - Overlays.editOverlay(sliderTwo, { x: sliderX + minSliderX} ); - currentAnimation.joints[selectedJointIndex].yaw = thumbPositionNormalised * sliderRanges.joints[selectedJointIndex].yawRange; - } - else if(movingSliderThree) { // currently selected joint roll - Overlays.editOverlay(sliderThree, { x: sliderX + minSliderX} ); - currentAnimation.joints[selectedJointIndex].roll = thumbPositionNormalised * sliderRanges.joints[selectedJointIndex].rollRange; - } - else if(movingSliderFour) { // currently selected joint pitch phase - Overlays.editOverlay(sliderFour, { x: sliderX + minSliderX} ); - var newPhase = 360 * thumbPositionNormalised - 180; - currentAnimation.joints[selectedJointIndex].pitchPhase = newPhase; - } - else if(movingSliderFive) { // currently selected joint yaw phase; - Overlays.editOverlay(sliderFive, { x: sliderX + minSliderX} ); - var newPhase = 360 * thumbPositionNormalised - 180; - currentAnimation.joints[selectedJointIndex].yawPhase = newPhase; - } - else if(movingSliderSix) { // currently selected joint roll phase - Overlays.editOverlay(sliderSix, { x: sliderX + minSliderX} ); - var newPhase = 360 * thumbPositionNormalised - 180; - currentAnimation.joints[selectedJointIndex].rollPhase = newPhase; - } - else if(movingSliderSeven) { // currently selected joint pitch offset - Overlays.editOverlay(sliderSeven, { x: sliderX + minSliderX} ); // currently selected joint pitch offset - var newOffset = (thumbPositionNormalised-0.5) * 2 * sliderRanges.joints[selectedJointIndex].pitchOffsetRange; - currentAnimation.joints[selectedJointIndex].pitchOffset = newOffset; - } - else if(movingSliderEight) { // currently selected joint yaw offset - Overlays.editOverlay(sliderEight, { x: sliderX + minSliderX} ); // currently selected joint yaw offset - var newOffset = (thumbPositionNormalised-0.5) * 2 * sliderRanges.joints[selectedJointIndex].yawOffsetRange; - currentAnimation.joints[selectedJointIndex].yawOffset = newOffset; - } - else if(movingSliderNine) { // currently selected joint roll offset - Overlays.editOverlay(sliderNine, { x: sliderX + minSliderX} ); // currently selected joint roll offset - var newOffset = (thumbPositionNormalised-0.5) * 2 * sliderRanges.joints[selectedJointIndex].rollOffsetRange; - currentAnimation.joints[selectedJointIndex].rollOffset = newOffset; - } - } - else if(INTERNAL_STATE===CONFIG_WALK_TWEAKS) { - - var thumbClickOffsetX = event.x - minSliderX; - var thumbPositionNormalised = thumbClickOffsetX / sliderRangeX; - if(thumbPositionNormalised<0) thumbPositionNormalised = 0; - if(thumbPositionNormalised>1) thumbPositionNormalised = 1; - var sliderX = thumbPositionNormalised * sliderRangeX ; // sets range - - if(movingSliderOne) { // walk speed - paused = true; // avoid nasty jittering - Overlays.editOverlay(sliderOne, { x: sliderX + minSliderX} ); - currentAnimation.settings.baseFrequency = thumbPositionNormalised * MAX_WALK_SPEED; - } - else if(movingSliderTwo) { // take flight speed - Overlays.editOverlay(sliderTwo, { x: sliderX + minSliderX} ); - //currentAnimation.settings.takeFlightVelocity = thumbPositionNormalised * 300; - } - else if(movingSliderThree) { // hips sway - Overlays.editOverlay(sliderThree, { x: sliderX + minSliderX} ); - currentAnimation.joints[0].sway = thumbPositionNormalised * sliderRanges.joints[0].swayRange; - } - else if(movingSliderFour) { // hips bob - Overlays.editOverlay(sliderFour, { x: sliderX + minSliderX} ); - currentAnimation.joints[0].bob = thumbPositionNormalised * sliderRanges.joints[0].bobRange; - } - else if(movingSliderFive) { // hips thrust - Overlays.editOverlay(sliderFive, { x: sliderX + minSliderX} ); - currentAnimation.joints[0].thrust = thumbPositionNormalised * sliderRanges.joints[0].thrustRange; - } - else if(movingSliderSix) { // legs separation - Overlays.editOverlay(sliderSix, { x: sliderX + minSliderX} ); - currentAnimation.joints[1].rollOffset = (thumbPositionNormalised-0.5) * 2 * sliderRanges.joints[1].rollOffsetRange; - } - else if(movingSliderSeven) { // stride - Overlays.editOverlay(sliderSeven, { x: sliderX + minSliderX} ); - currentAnimation.joints[1].pitch = thumbPositionNormalised * sliderRanges.joints[1].pitchRange; - } - else if(movingSliderEight) { // arms swing = upper arms yaw - Overlays.editOverlay(sliderEight, { x: sliderX + minSliderX} ); - currentAnimation.joints[9].yaw = thumbPositionNormalised * sliderRanges.joints[9].yawRange; - } - else if(movingSliderNine) { // arms out = upper arms pitch offset - Overlays.editOverlay(sliderNine, { x: sliderX + minSliderX} ); - currentAnimation.joints[9].pitchOffset = (thumbPositionNormalised-0.5) * -2 * sliderRanges.joints[9].pitchOffsetRange; - } - } - } -} -function mouseReleaseEvent(event) { - - var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); - - if(paused) paused = false; - - if(clickedOverlay === offButton) { - powerOn = true; - Overlays.editOverlay(offButton, { visible: false } ); - Overlays.editOverlay(onButton, { visible: true } ); - stand(); - } - else if(clickedOverlay === hideButton || clickedOverlay === hideButtonSelected){ - Overlays.editOverlay(hideButton, { visible: true } ); - Overlays.editOverlay(hideButtonSelected, { visible: false } ); - minimised = true; - minimiseDialog(); - } - else if(clickedOverlay === controlsMinimisedTab) { - minimised = false; - minimiseDialog(); - } - else if(powerOn) { - - if(movingSliderOne) movingSliderOne = false; - else if(movingSliderTwo) movingSliderTwo = false; - else if(movingSliderThree) movingSliderThree = false; - else if(movingSliderFour) movingSliderFour = false; - else if(movingSliderFive) movingSliderFive = false; - else if(movingSliderSix) movingSliderSix = false; - else if(movingSliderSeven) movingSliderSeven = false; - else if(movingSliderEight) movingSliderEight = false; - else if(movingSliderNine) movingSliderNine = false; - else { - - switch(clickedOverlay) { - - case configWalkButtonSelected: - case configStandButtonSelected: - case configSideStepLeftButtonSelected: - case configSideStepRightButtonSelected: - case configFlyingButtonSelected: - case configFlyingUpButtonSelected: - case configFlyingDownButtonSelected: - case configWalkStylesButtonSelected: - case configWalkTweaksButtonSelected: - case configWalkJointsButtonSelected: - setInternalState(STANDING); - break; - - case onButton: - powerOn = false; - setInternalState(STANDING); - Overlays.editOverlay(offButton, { visible: true } ); - Overlays.editOverlay(onButton, { visible: false } ); - resetJoints(); - break; - - case backButton: - case backButtonSelected: - Overlays.editOverlay(backButton, { visible: false } ); - Overlays.editOverlay(backButtonSelected, { visible: false } ); - setInternalState(STANDING); - break; - - case configWalkStylesButton: - setInternalState(CONFIG_WALK_STYLES); - break; - - case configWalkTweaksButton: - setInternalState(CONFIG_WALK_TWEAKS); - break; - - case configWalkJointsButton: - setInternalState(CONFIG_WALK_JOINTS); - break; - - case configWalkButton: - setInternalState(CONFIG_WALK_STYLES); // set the default walk adjustment panel here (i.e. first panel shown when Walk button clicked) - break; - - case configStandButton: - setInternalState(CONFIG_STANDING); - break; - - case configSideStepLeftButton: - setInternalState(CONFIG_SIDESTEP_LEFT); - break; - - case configSideStepRightButton: - setInternalState(CONFIG_SIDESTEP_RIGHT); - break; - - case configFlyingButton: - setInternalState(CONFIG_FLYING); - break; - - case configFlyingUpButton: - setInternalState(CONFIG_FLYING_UP); - break; - - case configFlyingDownButton: - setInternalState(CONFIG_FLYING_DOWN); - break; - } - } - } -} -Controller.mouseMoveEvent.connect(mouseMoveEvent); -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - -// Script ending -Script.scriptEnding.connect(function() { - - // remove the background overlays - for(var i in backgroundOverlays) { - Overlays.deleteOverlay(backgroundOverlays[i]); - } - // remove the button overlays - for(var i in buttonOverlays) { - Overlays.deleteOverlay(buttonOverlays[i]); - } - // remove the slider thumb overlays - for(var i in sliderThumbOverlays) { - Overlays.deleteOverlay(sliderThumbOverlays[i]); - } - // remove the character joint control overlays - for(var i in bigButtonOverlays) { - Overlays.deleteOverlay(jointsControlOverlays[i]); - } - // remove the big button overlays - for(var i in bigButtonOverlays) { - Overlays.deleteOverlay(bigButtonOverlays[i]); - } - // remove the mimimised tab - Overlays.deleteOverlay(controlsMinimisedTab); - - // remove the walk wheel overlays - Overlays.deleteOverlay(walkWheelYLine); - Overlays.deleteOverlay(walkWheelZLine); - Overlays.deleteOverlay(walkWheelStats); - - // remove the debug stats overlays - Overlays.deleteOverlay(debugStats); - Overlays.deleteOverlay(debugStatsPeriodic); -}); - -var sideStep = 0.002; // i.e. 2mm increments whilst sidestepping - JS movement keys don't work well :-( -function keyPressEvent(event) { - - if (event.text == "q") { - // export currentAnimation as json string when q key is pressed. reformat result at http://www.freeformatter.com/json-formatter.html - print('\n'); - print('walk.js dumping animation: '+currentAnimation.name+'\n'); - print('\n'); - print(JSON.stringify(currentAnimation), null, '\t'); - } - else if (event.text == "t") { - statsOn = !statsOn; - Overlays.editOverlay(debugStats, {visible: statsOn}); - Overlays.editOverlay(debugStatsPeriodic, {visible: statsOn}); - Overlays.editOverlay(walkWheelStats, {visible: statsOn}); - Overlays.editOverlay(walkWheelYLine, {visible: statsOn}); - Overlays.editOverlay(walkWheelZLine, {visible: statsOn}); - } -} -Controller.keyPressEvent.connect(keyPressEvent); - -// get the list of joint names -var jointList = MyAvatar.getJointNames(); - -// clear the joint data so can calculate hips to feet distance -for(var i = 0 ; i < 5 ; i++) { - MyAvatar.setJointData(i, Quat.fromPitchYawRollDegrees(0,0,0)); -} -// used to position the visual representation of the walkwheel only -var hipsToFeetDistance = MyAvatar.getJointPosition("Hips").y - MyAvatar.getJointPosition("RightFoot").y; - -// This script is designed around the Finite State Machine (FSM) model, so to start things up we just select the STANDING state. -setInternalState(STANDING); \ No newline at end of file +// Begin by setting an internal state +state.setInternalState(state.STANDING); \ No newline at end of file diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 623631d5e5..53454d3d3b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -49,7 +49,7 @@ const float PITCH_SPEED = 100.0f; // degrees/sec const float COLLISION_RADIUS_SCALAR = 1.2f; // pertains to avatar-to-avatar collisions const float COLLISION_RADIUS_SCALE = 0.125f; -const float MAX_WALKING_SPEED = 4.5f; +const float MAX_WALKING_SPEED = 2.5f; // human walking speed const float MAX_BOOST_SPEED = 0.5f * MAX_WALKING_SPEED; // keyboard motor gets additive boost below this speed const float MIN_AVATAR_SPEED = 0.05f; // speed is set to zero below this