// // walkObjects.js // // version 1.001 // // 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; this.lastStrideLength = 0; // kept for use during transitions }; // 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 this.nextAnimation = nextAnimation; // name of next animation if (lastAnimation === motion.selWalk || nextAnimation === motion.selSideStepLeft || nextAnimation === motion.selSideStepRight) { // boolean - is the last animation a walking animation? this.walkingAtStart = true; } else { this.walkingAtStart = false; } if (nextAnimation === motion.selWalk || nextAnimation === motion.selSideStepLeft || nextAnimation === motion.selSideStepRight) { // boolean - is the next animation a walking animation? this.walkingAtEnd = true; } else { this.walkingAtEnd = false; } 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 = 3; // 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, } })();