diff --git a/examples/editModels.js b/examples/editModels.js index 3f1863fef2..8e3503b9b2 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -2807,6 +2807,7 @@ function mouseReleaseEvent(event) { // exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that // added it. var modelMenuAddedDelete = false; +var originalLightsArePickable = Entities.getLightsArePickable(); function setupModelMenus() { print("setupModelMenus()"); // adj our menuitems @@ -2824,15 +2825,18 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", afterItem: "Paste Models", isCheckable: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S", - afterItem: "Allow Select Large Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", + afterItem: "Allow Selecting of Large Models", isCheckable: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", + afterItem: "Allow Selecting of Small Models", isCheckable: true }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); + Entities.setLightsArePickable(false); } @@ -2846,8 +2850,9 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Model List..."); Menu.removeMenuItem("Edit", "Paste Models"); - Menu.removeMenuItem("Edit", "Allow Select Large Models"); - Menu.removeMenuItem("Edit", "Allow Select Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); Menu.removeSeparator("File", "Models"); Menu.removeMenuItem("File", "Export Models"); @@ -2865,6 +2870,7 @@ function scriptEnding() { if (exportMenu) { exportMenu.close(); } + Entities.setLightsArePickable(originalLightsArePickable); } Script.scriptEnding.connect(scriptEnding); @@ -2890,10 +2896,12 @@ function showPropertiesForm(editModelID) { function handeMenuEvent(menuItem) { print("menuItemEvent() in JS... menuItem=" + menuItem); - if (menuItem == "Allow Select Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Select Small Models"); - } else if (menuItem == "Allow Select Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Select Large Models"); + if (menuItem == "Allow Selecting of Small Models") { + allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); + } else if (menuItem == "Allow Selecting of Large Models") { + allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); + } else if (menuItem == "Allow Selecting of Lights") { + Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); } else if (menuItem == "Delete") { if (leftController.grabbing) { print(" Delete Entity.... leftController.entityID="+ leftController.entityID); diff --git a/examples/gamepad.js b/examples/gamepad.js index a2f1034e26..cc275e6267 100644 --- a/examples/gamepad.js +++ b/examples/gamepad.js @@ -16,11 +16,15 @@ var AXIS_STRAFE = Joysticks.AXIS_LEFT_X; var AXIS_FORWARD = Joysticks.AXIS_LEFT_Y; var AXIS_ROTATE = Joysticks.AXIS_RIGHT_X; +var BUTTON_SPRINT = Joysticks.BUTTON_LEFT_STICK; + +var BUTTON_TOGGLE_MIRROR = Joysticks.BUTTON_FACE_LEFT; + var BUTTON_TURN_AROUND = Joysticks.BUTTON_RIGHT_STICK; var BUTTON_FLY_UP = Joysticks.BUTTON_RIGHT_SHOULDER; var BUTTON_FLY_DOWN = Joysticks.BUTTON_LEFT_SHOULDER; -var BUTTON_WARP = Joysticks.BUTTON_FACE_RIGHT; +var BUTTON_WARP = null; // Disable for now var BUTTON_WARP_FORWARD = Joysticks.BUTTON_DPAD_UP; var BUTTON_WARP_BACKWARD = Joysticks.BUTTON_DPAD_DOWN; @@ -31,7 +35,8 @@ var BUTTON_WARP_RIGHT = Joysticks.BUTTON_DPAD_RIGHT; var WARP_DISTANCE = 1; // Walk speed in m/s -var MOVE_SPEED = 2; +var MOVE_SPEED = 0.5; +var MOVE_SPRINT_SPEED = 2; // Amount to rotate in radians var ROTATE_INCREMENT = Math.PI / 8; @@ -46,9 +51,14 @@ var WARP_PICK_MAX_DISTANCE = 100; var flyDownButtonState = false; var flyUpButtonState = false; +// When toggling to mirror mode, this stores the mode the user was previously in +// so it can be toggled back to. +var toggledFromCameraMode = 'first person'; + // Current move direction, axis aligned - that is, looking down and moving forward // will not move you into the ground, but instead will keep you on the horizontal plane. var moveDirection = { x: 0, y: 0, z: 0 }; +var sprintButtonState = false; var warpActive = false; var warpPosition = { x: 0, y: 0, z: 0 }; @@ -173,6 +183,18 @@ function reportButtonValue(button, newValue, oldValue) { MyAvatar.orientation = Quat.multiply( Quat.fromPitchYawRollRadians(0, Math.PI, 0), MyAvatar.orientation); } + } else if (button == BUTTON_SPRINT) { + sprintButtonState = newValue; + } else if (button == BUTTON_TOGGLE_MIRROR) { + if (newValue) { + var currentMode = Camera.mode; + if (currentMode != "mirror") { + toggledFromCameraMode = currentMode; + } + Camera.mode = "mirror"; + } else { + Camera.mode = toggledFromCameraMode; + } } else if (newValue) { var direction = null; @@ -209,9 +231,10 @@ function update(dt) { var move = copyVec3(moveDirection); move.y = 0; if (Vec3.length(move) > 0) { + speed = sprintButtonState ? MOVE_SPRINT_SPEED : MOVE_SPEED; velocity = Vec3.multiplyQbyV(Camera.getOrientation(), move); velocity.y = 0; - velocity = Vec3.multiply(Vec3.normalize(velocity), MOVE_SPEED); + velocity = Vec3.multiply(Vec3.normalize(velocity), speed); } if (moveDirection.y != 0) { diff --git a/examples/libraries/entitySelectionTool.js b/examples/libraries/entitySelectionTool.js index 40b5b78a31..fa97e9351f 100644 --- a/examples/libraries/entitySelectionTool.js +++ b/examples/libraries/entitySelectionTool.js @@ -33,10 +33,12 @@ SelectionManager = (function() { that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); that.localPosition = { x: 0, y: 0, z: 0 }; that.localDimensions = { x: 0, y: 0, z: 0 }; + that.localRegistrationPoint = { x: 0.5, y: 0.5, z: 0.5 }; that.worldRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); that.worldPosition = { x: 0, y: 0, z: 0 }; that.worldDimensions = { x: 0, y: 0, z: 0 }; + that.worldRegistrationPoint = { x: 0.5, y: 0.5, z: 0.5 }; that.centerPosition = { x: 0, y: 0, z: 0 }; that.saveProperties = function() { @@ -153,6 +155,7 @@ SelectionManager = (function() { that.localDimensions = properties.dimensions; that.localPosition = properties.position; that.localRotation = properties.rotation; + that.localRegistrationPoint = properties.registrationPoint; that.worldDimensions = properties.boundingBox.dimensions; that.worldPosition = properties.boundingBox.center; @@ -215,6 +218,17 @@ function normalizeDegrees(degrees) { return degrees; } +// Return the enter position of an entity relative to it's registrationPoint +// A registration point of (0.5, 0.5, 0.5) will have an offset of (0, 0, 0) +// A registration point of (1.0, 1.0, 1.0) will have an offset of (-dimensions.x / 2, -dimensions.y / 2, -dimensions.z / 2) +function getRelativeCenterPosition(dimensions, registrationPoint) { + return { + x: -dimensions.x * (registrationPoint.x - 0.5), + y: -dimensions.y * (registrationPoint.y - 0.5), + z: -dimensions.z * (registrationPoint.z - 0.5), + } +} + SelectionDisplay = (function () { var that = {}; @@ -982,26 +996,36 @@ SelectionDisplay = (function () { that.updateRotationHandles(); that.highlightSelectable(); - var rotation, dimensions, position; + var rotation, dimensions, position, registrationPoint; if (spaceMode == SPACE_LOCAL) { rotation = SelectionManager.localRotation; dimensions = SelectionManager.localDimensions; position = SelectionManager.localPosition; + registrationPoint = SelectionManager.localRegistrationPoint; } else { rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); dimensions = SelectionManager.worldDimensions; position = SelectionManager.worldPosition; + registrationPoint = SelectionManager.worldRegistrationPoint; } - var halfDimensions = Vec3.multiply(0.5, dimensions); + var registrationPointDimensions = { + x: dimensions.x * registrationPoint.x, + y: dimensions.y * registrationPoint.y, + z: dimensions.z * registrationPoint.z, + }; - var left = -halfDimensions.x; - var right = halfDimensions.x; - var top = halfDimensions.y; - var bottom = -halfDimensions.y; - var front = far = halfDimensions.z; - var near = -halfDimensions.z; + // Center of entity, relative to registration point + center = getRelativeCenterPosition(dimensions, registrationPoint); + + // Distances in world coordinates relative to the registration point + var left = -registrationPointDimensions.x; + var right = dimensions.x - registrationPointDimensions.x; + var bottom = -registrationPointDimensions.y; + var top = dimensions.y - registrationPointDimensions.y; + var near = -registrationPointDimensions.z; + var front = far = dimensions.z - registrationPointDimensions.z; var worldTop = SelectionManager.worldDimensions.y / 2; @@ -1014,25 +1038,25 @@ SelectionDisplay = (function () { var LTF = { x: left, y: top, z: far }; var RTF = { x: right, y: top, z: far }; - var TOP = { x: 0, y: top, z: 0 }; - var BOTTOM = { x: 0, y: bottom, z: 0 }; - var LEFT = { x: left, y: 0, z: 0 }; - var RIGHT = { x: right, y: 0, z: 0 }; - var NEAR = { x: 0, y: 0, z: near }; - var FAR = { x: 0, y: 0, z: far }; + var TOP = { x: center.x, y: top, z: center.z }; + var BOTTOM = { x: center.x, y: bottom, z: center.z }; + var LEFT = { x: left, y: center.y, z: center.z }; + var RIGHT = { x: right, y: center.y, z: center.z }; + var NEAR = { x: center.x, y: center.y, z: near }; + var FAR = { x: center.x, y: center.y, z: far }; - var EdgeTR = { x: right, y: top, z: 0 }; - var EdgeTL = { x: left, y: top, z: 0 }; - var EdgeTF = { x: 0, y: top, z: front }; - var EdgeTN = { x: 0, y: top, z: near }; - var EdgeBR = { x: right, y: bottom, z: 0 }; - var EdgeBL = { x: left, y: bottom, z: 0 }; - var EdgeBF = { x: 0, y: bottom, z: front }; - var EdgeBN = { x: 0, y: bottom, z: near }; - var EdgeNR = { x: right, y: 0, z: near }; - var EdgeNL = { x: left, y: 0, z: near }; - var EdgeFR = { x: right, y: 0, z: front }; - var EdgeFL = { x: left, y: 0, z: front }; + var EdgeTR = { x: right, y: top, z: center.z }; + var EdgeTL = { x: left, y: top, z: center.z }; + var EdgeTF = { x: center.x, y: top, z: front }; + var EdgeTN = { x: center.x, y: top, z: near }; + var EdgeBR = { x: right, y: bottom, z: center.z }; + var EdgeBL = { x: left, y: bottom, z: center.z }; + var EdgeBF = { x: center.x, y: bottom, z: front }; + var EdgeBN = { x: center.x, y: bottom, z: near }; + var EdgeNR = { x: right, y: center.y, z: near }; + var EdgeNL = { x: left, y: center.y, z: near }; + var EdgeFR = { x: right, y: center.y, z: front }; + var EdgeFL = { x: left, y: center.y, z: front }; LBN = Vec3.multiplyQbyV(rotation, LBN); RBN = Vec3.multiplyQbyV(rotation, RBN); @@ -1111,8 +1135,10 @@ SelectionDisplay = (function () { Overlays.editOverlay(grabberNEAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: NEAR }); Overlays.editOverlay(grabberFAR, { visible: extendedStretchHandlesVisible, rotation: rotation, position: FAR }); + var boxPosition = Vec3.multiplyQbyV(rotation, center); + boxPosition = Vec3.sum(position, boxPosition); Overlays.editOverlay(selectionBox, { - position: position, + position: boxPosition, dimensions: dimensions, rotation: rotation, visible: !(mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL"), @@ -1140,8 +1166,17 @@ SelectionDisplay = (function () { if (selectionManager.selections.length > 1) { for (; i < selectionManager.selections.length; i++) { var properties = Entities.getEntityProperties(selectionManager.selections[i]); + + // Adjust overlay position to take registrationPoint into account + // centeredRP = registrationPoint with range [-0.5, 0.5] + var centeredRP = Vec3.subtract(properties.registrationPoint, { x: 0.5, y: 0.5, z: 0.5 }); + var offset = vec3Mult(properties.dimensions, centeredRP); + offset = Vec3.multiply(-1, offset); + offset = Vec3.multiplyQbyV(properties.rotation, offset); + var boxPosition = Vec3.sum(properties.position, offset); + Overlays.editOverlay(selectionBoxes[i], { - position: properties.position, + position: boxPosition, rotation: properties.rotation, dimensions: properties.dimensions, visible: true, @@ -1400,6 +1435,8 @@ SelectionDisplay = (function () { var initialDimensions = null; var initialIntersection = null; var initialProperties = null; + var registrationPoint = null; + var deltaPivot = null; var pickRayPosition = null; var rotation = null; @@ -1412,18 +1449,29 @@ SelectionDisplay = (function () { rotation = SelectionManager.localRotation; initialPosition = SelectionManager.localPosition; initialDimensions = SelectionManager.localDimensions; + registrationPoint = SelectionManager.localRegistrationPoint; } else { rotation = SelectionManager.worldRotation; initialPosition = SelectionManager.worldPosition; initialDimensions = SelectionManager.worldDimensions; + registrationPoint = SelectionManager.worldRegistrationPoint; } - var scaledOffset = { - x: initialDimensions.x * offset.x * 0.5, - y: initialDimensions.y * offset.y * 0.5, - z: initialDimensions.z * offset.z * 0.5, - }; - pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffset)); + // Modify range of registrationPoint to be [-0.5, 0.5] + var centeredRP = Vec3.subtract(registrationPoint, { x: 0.5, y: 0.5, z: 0.5 }); + + // Scale pivot to be in the same range as registrationPoint + var scaledPivot = Vec3.multiply(0.5, pivot) + deltaPivot = Vec3.subtract(centeredRP, scaledPivot); + + var scaledOffset = Vec3.multiply(0.5, offset); + + // Offset from the registration point + offsetRP = Vec3.subtract(scaledOffset, centeredRP); + + // Scaled offset in world coordinates + var scaledOffsetWorld = vec3Mult(initialDimensions, offsetRP); + pickRayPosition = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld)); if (numDimensions == 1 && mask.x) { var start = Vec3.multiplyQbyV(rotation, { x: -10000, y: 0, z: 0 }); @@ -1550,8 +1598,7 @@ SelectionDisplay = (function () { newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION); newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION); - var p = Vec3.multiply(0.5, pivot); - var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(p, changeInDimensions)); + var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(deltaPivot, changeInDimensions)); var newPosition = Vec3.sum(initialPosition, changeInPosition); for (var i = 0; i < SelectionManager.selections.length; i++) { @@ -1589,20 +1636,19 @@ SelectionDisplay = (function () { function addStretchTool(overlay, mode, pivot, direction, offset) { if (!pivot) { - pivot = Vec3.multiply(-1, direction); - pivot.y = direction.y; + pivot = direction; } var tool = makeStretchTool(mode, direction, pivot, offset); addGrabberTool(overlay, tool); } - addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); - addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); - addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); - addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); - addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); - addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); + addStretchTool(grabberNEAR, "STRETCH_NEAR", { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: 1 }, { x: 0, y: 0, z: -1 }); + addStretchTool(grabberFAR, "STRETCH_FAR", { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: -1 }, { x: 0, y: 0, z: 1 }); + addStretchTool(grabberTOP, "STRETCH_TOP", { x: 0, y: -1, z: 0 }, { x: 0, y: -1, z: 0 }, { x: 0, y: 1, z: 0 }); + addStretchTool(grabberBOTTOM, "STRETCH_BOTTOM", { x: 0, y: 1, z: 0 }, { x: 0, y: 1, z: 0 }, { x: 0, y: -1, z: 0 }); + addStretchTool(grabberRIGHT, "STRETCH_RIGHT", { x: -1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }); + addStretchTool(grabberLEFT, "STRETCH_LEFT", { x: 1, y: 0, z: 0 }, { x: 1, y: 0, z: 0 }, { x: -1, y: 0, z: 0 }); addStretchTool(grabberLBN, "STRETCH_LBN", null, {x: 1, y: 0, z: 1}, { x: -1, y: -1, z: -1 }); addStretchTool(grabberRBN, "STRETCH_RBN", null, {x: -1, y: 0, z: 1}, { x: 1, y: -1, z: -1 }); @@ -1740,17 +1786,27 @@ SelectionDisplay = (function () { } var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 }); + + // Entities should only reposition if we are rotating multiple selections around + // the selections center point. Otherwise, the rotation will be around the entities + // registration point which does not need repositioning. + var reposition = SelectionManager.selections.length > 1; for (var i = 0; i < SelectionManager.selections.length; i++) { var entityID = SelectionManager.selections[i]; var properties = Entities.getEntityProperties(entityID); var initialProperties = SelectionManager.savedProperties[entityID.id]; - var dPos = Vec3.subtract(initialProperties.position, initialPosition); - dPos = Vec3.multiplyQbyV(yawChange, dPos); - Entities.editEntity(entityID, { - position: Vec3.sum(initialPosition, dPos), + var newProperties = { rotation: Quat.multiply(yawChange, initialProperties.rotation), - }); + }; + + if (reposition) { + var dPos = Vec3.subtract(initialProperties.position, initialPosition); + dPos = Vec3.multiplyQbyV(yawChange, dPos); + newProperties.position = Vec3.sum(initialPosition, dPos); + } + + Entities.editEntity(entityID, newProperties); } updateRotationDegreesOverlay(angleFromZero, yawHandleRotation, yawCenter); diff --git a/examples/libraries/gridTool.js b/examples/libraries/gridTool.js index aa412b1a76..7d98befec8 100644 --- a/examples/libraries/gridTool.js +++ b/examples/libraries/gridTool.js @@ -90,7 +90,6 @@ Grid = function(opts) { } that.snapToSpacing = function(delta, majorOnly) { - print('snaptogrid? ' + snapToGrid); if (!snapToGrid) { return delta; } diff --git a/examples/libraries/walkApi.js b/examples/libraries/walkApi.js index e61335f6f0..d2622d5833 100644 --- a/examples/libraries/walkApi.js +++ b/examples/libraries/walkApi.js @@ -1,412 +1,606 @@ -// -// 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(SoundCache.getSound(_pathToSounds+"FootstepW2Left-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW2Right-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Left-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW3Right-12db.wav")); - _footsteps.push(SoundCache.getSound(_pathToSounds+"FootstepW5Left-12db.wav")); - _footsteps.push(SoundCache.getSound(_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, - } +// +// walkObjects.js +// +// version 1.003 +// +// Created by David Wooldridge, Autumn 2014 +// +// Motion, state and Transition objects for use by the walk.js script v1.12 +// +// 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() { + + // selected animations + this.selectedWalk = undefined; + this.selectedStand = undefined; + this.selectedFly = undefined; + this.selectedFlyUp = undefined; + this.selectedFlyDown = undefined; + this.selectedFlyBlend = undefined; + this.selectedHovering = undefined; + this.selectedSideStepLeft = undefined; + this.selectedSideStepRight = undefined; + + // if Hydras are connected, the only way to enable use is by never setting any rotations on the arm joints + 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 = undefined; + this.setGender = function(gender) { + + this.avatarGender = gender; + + switch(this.avatarGender) { + + case MALE: + + this.selectedWalk = walkAssets.maleStandardWalk; + this.selectedStand = walkAssets.maleStandOne; + this.selectedFlyUp = walkAssets.maleFlyingUp; + this.selectedFly = walkAssets.maleFlying; + this.selectedFlyDown = walkAssets.maleFlyingDown; + this.selectedFlyBlend = walkAssets.maleFlyingBlend; + this.selectedHovering = walkAssets.maleHovering; + this.selectedSideStepLeft = walkAssets.maleSideStepLeft; + this.selectedSideStepRight = walkAssets.maleSideStepRight; + this.currentAnimation = this.selectedStand; + return; + + case FEMALE: + + this.selectedWalk = walkAssets.femaleStandardWalk; + this.selectedStand = walkAssets.femaleStandOne; + this.selectedFlyUp = walkAssets.femaleFlyingUp; + this.selectedFly = walkAssets.femaleFlying; + this.selectedFlyDown = walkAssets.femaleFlyingDown; + this.selectedFlyBlend = walkAssets.femaleFlyingBlend; + this.selectedHovering = walkAssets.femaleHovering; + this.selectedSideStepLeft = walkAssets.femaleSideStepLeft; + this.selectedSideStepRight = walkAssets.femaleSideStepRight; + this.currentAnimation = this.selectedStand; + return; + } + } + this.setGender(MALE); + + // calibration + this.calibration = { + + pitchMax: 8, + maxWalkAcceleration: 5, + maxWalkDeceleration: 25, + rollMax: 80, + angularVelocityMax: 70, + hipsToFeet: MyAvatar.getJointPosition("Hips").y - MyAvatar.getJointPosition("RightFoot").y, + } + + // used to make sure at least one step has been taken when transitioning from a walk cycle + this.elapsedFTDegrees = 0; + + // the current animation and transition + this.currentAnimation = this.selectedStand; + this.currentTransition = null; + + // zero out avi's joints and pose the fingers + this.avatarJointNames = MyAvatar.getJointNames(); + this.poseFingers = function() { + + 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)); + } + } + }; + if (!this.armsFree) { + this.poseFingers(); + } + + // frequency time wheel (foot / ground speed matching) + this.direction = FORWARDS; + this.strideLength = this.selectedWalk.calibration.strideLengthForwards; + this.frequencyTimeWheelPos = 0; + this.frequencyTimeWheelRadius = 0.5; + this.recentFrequencyTimeIncrements = []; + for(var i = 0; i < 8; i++) { + + this.recentFrequencyTimeIncrements.push(0); + } + this.averageFrequencyTimeIncrement = 0; + + this.advanceFrequencyTimeWheel = function(angle){ + + this.elapsedFTDegrees += angle; + + this.recentFrequencyTimeIncrements.push(angle); + this.recentFrequencyTimeIncrements.shift(); + for(increment in this.recentFrequencyTimeIncrements) { + this.averageFrequencyTimeIncrement += this.recentFrequencyTimeIncrements[increment]; + } + this.averageFrequencyTimeIncrement /= this.recentFrequencyTimeIncrements.length; + + this.frequencyTimeWheelPos += angle; + if (this.frequencyTimeWheelPos >= 360) { + this.frequencyTimeWheelPos = this.frequencyTimeWheelPos % 360; + } + } + + // currently disabled due to breaking changes in js audio native objects + this.playFootStepSound = function(side) { + + //var options = new AudioInjectionOptions(); + //options.position = Camera.getPosition(); + //options.volume = 0.3; + //var soundNumber = 2; // 0 to 2 + //if (side === RIGHT && motion.makesFootStepSounds) { + // Audio.playS ound(walkAssets.footsteps[soundNumber + 1], options); + //} else if (side === LEFT && motion.makesFootStepSounds) { + // Audio.playSound(walkAssets.footsteps[soundNumber], options); + //} + } + + // history + this.lastDirection = 0; + this.lastSpeed = 0; + this.transitionCount = 0; + this.lastDistanceToVoxels = 0; + +}; // end Motion constructor + + +spatialInformation = (function() { + + return { + + distanceToVoxels: function() { + + // use the blocking version of findRayIntersection to avoid errors + var pickRay = {origin: MyAvatar.position, direction: {x:0, y:-1, z:0}}; + return Voxels.findRayIntersectionBlocking(pickRay).distance - motion.calibration.hipsToFeet;; + } + } + +})(); // end spatialInformation object literal + + +// animation file manipulation +animation = (function() { + + return { + + zeroAnimation: function(animation) { + + for (i in animation.joints) { + + animation.joints[i].pitch = 0; + animation.joints[i].yaw = 0; + animation.joints[i].roll = 0; + animation.joints[i].pitchPhase = 0; + animation.joints[i].yawPhase = 0; + animation.joints[i].rollPhase = 0; + animation.joints[i].pitchOffset = 0; + animation.joints[i].yawOffset = 0; + animation.joints[i].rollOffset = 0; + if (i === 0) { + // Hips only + animation.joints[i].thrust = 0; + animation.joints[i].sway = 0; + animation.joints[i].bob = 0; + animation.joints[i].thrustPhase = 0; + animation.joints[i].swayPhase = 0; + animation.joints[i].bobPhase = 0; + } + } + }, + + blendAnimation: function(sourceAnimation, targetAnimation, percent) { + + for (i in targetAnimation.joints) { + + targetAnimation.joints[i].pitch += percent * sourceAnimation.joints[i].pitch; + targetAnimation.joints[i].yaw += percent * sourceAnimation.joints[i].yaw; + targetAnimation.joints[i].roll += percent * sourceAnimation.joints[i].roll; + targetAnimation.joints[i].pitchPhase += percent * sourceAnimation.joints[i].pitchPhase; + targetAnimation.joints[i].yawPhase += percent * sourceAnimation.joints[i].yawPhase; + targetAnimation.joints[i].rollPhase += percent * sourceAnimation.joints[i].rollPhase; + targetAnimation.joints[i].pitchOffset += percent * sourceAnimation.joints[i].pitchOffset; + targetAnimation.joints[i].yawOffset += percent * sourceAnimation.joints[i].yawOffset; + targetAnimation.joints[i].rollOffset += percent * sourceAnimation.joints[i].rollOffset; + if (i === 0) { + // Hips only + targetAnimation.joints[i].thrust += percent * sourceAnimation.joints[i].thrust; + targetAnimation.joints[i].sway += percent * sourceAnimation.joints[i].sway; + targetAnimation.joints[i].bob += percent * sourceAnimation.joints[i].bob; + targetAnimation.joints[i].thrustPhase += percent * sourceAnimation.joints[i].thrustPhase; + targetAnimation.joints[i].swayPhase += percent * sourceAnimation.joints[i].swayPhase; + targetAnimation.joints[i].bobPhase += percent * sourceAnimation.joints[i].bobPhase; + } + } + } + } +})(); // end animation object literal + +// finite state machine. Avatar locomotion modes represent states in the FSM +state = (function () { + + return { + + // the finite list of states + STANDING: 1, + WALKING: 2, + SIDE_STEP: 3, + FLYING: 4, + currentState: this.STANDING, + + // status vars + powerOn: true, + + setInternalState: function(newInternalState) { + + motion.elapsedFTDegrees = 0; + + switch (newInternalState) { + + case this.WALKING: + + this.currentState = this.WALKING; + return; + + case this.FLYING: + + this.currentState = this.FLYING; + return; + + case this.SIDE_STEP: + + this.currentState = this.SIDE_STEP; + return; + + case this.STANDING: + default: + + this.currentState = this.STANDING; + return; + } + } + } +})(); // end state object literal + +// constructor for animation Transition +Transition = function(nextAnimation, lastAnimation, lastTransition) { + + // record the current state of animation + this.nextAnimation = nextAnimation; + this.lastAnimation = lastAnimation; + this.lastTransition = lastTransition; + + // deal with transition recursion (overlapping transitions) + this.id = motion.transitionCount++; // serial number for this transition + this.recursionDepth = 0; + this.incrementRecursion = function() { + + this.recursionDepth += 1; + + if(this.lastTransition !== nullTransition) { + + this.lastTransition.incrementRecursion(); + if(this.lastTransition.recursionDepth > 5) { + + delete this.lastTransition; + this.lastTransition = nullTransition; + } + } + } + if(lastTransition !== nullTransition) { + + this.lastTransition.incrementRecursion(); + } + + this.reachPoses = []; // placeholder / stub: work in progress - array of reach poses for squash and stretch techniques + this.transitionDuration = 0.5; // length of transition (seconds) + this.easingLower = {x:0.60, y:0.03}; // Bezier curve handle + this.easingUpper = {x:0.87, y:1.35}; // Bezier curve handle + this.startTime = new Date().getTime(); // Starting timestamp (seconds) + this.progress = 0; // how far are we through the transition? + this.lastDirection = motion.lastDirection; + + // collect information about the currently playing animation + this.lastDirection = motion.lastDirection; + this.lastFrequencyTimeWheelPos = motion.frequencyTimeWheelPos; + this.lastFrequencyTimeIncrement = motion.averageFrequencyTimeIncrement; + this.lastFrequencyTimeWheelRadius = motion.frequencyTimeWheelRadius; + this.stopAngle = 0; // what angle should we stop turning this frequency time wheel? + this.percentToMove = 0; // if we need to keep moving to complete a step, this will be set to 100 + this.lastElapsedFTDegrees = motion.elapsedFTDegrees; + this.advancePreviousFrequencyTimeWheel = function() { + + this.lastFrequencyTimeWheelPos += this.lastFrequencyTimeIncrement; + + if (this.lastFrequencyTimeWheelPos >= 360) { + + this.lastFrequencyTimeWheelPos = this.lastFrequencyTimeWheelPos % 360; + } + + if(this.lastTransition !== nullTransition) { + + this.lastTransition.advancePreviousFrequencyTimeWheel(); + } + }; + + this.updateProgress = function() { + + var elapasedTime = (new Date().getTime() - this.startTime) / 1000; + this.progress = elapasedTime / this.transitionDuration; + + this.progress = filter.bezier((1 - this.progress), + {x: 0, y: 0}, + this.easingLower, + this.easingUpper, + {x: 1, y: 1}).y; + + // ensure there is at least some progress + if(this.progress <= 0) { + + this.progress = VERY_SHORT_TIME; + } + if(this.lastTransition !== nullTransition) { + + if(this.lastTransition.updateProgress() >= 1) { + + // the previous transition is now complete + delete this.lastTransition; + this.lastTransition = nullTransition; + } + } + return this.progress; + }; + + this.blendTranslations = function(frequencyTimeWheelPos, direction) { + + var lastTranslations = {x:0, y:0, z:0}; + if(!isDefined(this.nextAnimation)) { + + return lastTranslations; + } + var nextTranslations = calculateTranslations(this.nextAnimation, + frequencyTimeWheelPos, + direction); + + // are we blending with a previous, still live transition? + if(this.lastTransition !== nullTransition) { + + lastTranslations = this.lastTransition.blendTranslations(this.lastFrequencyTimeWheelPos, + this.lastDirection); + + } else { + + lastTranslations = calculateTranslations(this.lastAnimation, + this.lastFrequencyTimeWheelPos, + this.lastDirection); + } + + nextTranslations.x = this.progress * nextTranslations.x + + (1 - this.progress) * lastTranslations.x; + + nextTranslations.y = this.progress * nextTranslations.y + + (1 - this.progress) * lastTranslations.y; + + nextTranslations.z = this.progress * nextTranslations.z + + (1 - this.progress) * lastTranslations.z; + + return nextTranslations; + }; + + this.blendRotations = function(jointName, frequencyTimeWheelPos, direction) { + + var lastRotations = {x:0, y:0, z:0}; + var nextRotations = calculateRotations(jointName, + this.nextAnimation, + frequencyTimeWheelPos, + direction); + + // are we blending with a previous, still live transition? + if(this.lastTransition !== nullTransition) { + + lastRotations = this.lastTransition.blendRotations(jointName, + this.lastFrequencyTimeWheelPos, + this.lastDirection); + } else { + + lastRotations = calculateRotations(jointName, + this.lastAnimation, + this.lastFrequencyTimeWheelPos, + this.lastDirection); + } + + nextRotations.x = this.progress * nextRotations.x + + (1 - this.progress) * lastRotations.x; + + nextRotations.y = this.progress * nextRotations.y + + (1 - this.progress) * lastRotations.y; + + nextRotations.z = this.progress * nextRotations.z + + (1 - this.progress) * lastRotations.z; + + return nextRotations; + }; + +}; // end Transition constructor + + +// individual joint modiers (mostly used to provide symmetry between left and right limbs) +JointModifiers = function(joint, direction) { + + // gather modifiers and multipliers + this.pitchFrequencyMultiplier = 1; + this.pitchPhaseModifier = 0; + this.pitchReverseModifier = 0; + this.yawReverseModifier = 0; + this.rollReverseModifier = 0; + this.pitchSign = 1; // for sidestepping and incorrectly rigged Ron ToeBases + this.yawSign = 1; + this.rollSign = 1; + this.pitchReverseInvert = 1; + this.pitchOffsetSign = 1; + this.yawOffsetSign = 1; + this.rollOffsetSign = 1; + this.bobReverseModifier = 0; + this.bobFrequencyMultiplier = 1; + this.thrustFrequencyMultiplier = 1; + + if (isDefined(joint.pitchFrequencyMultiplier)) { + this.pitchFrequencyMultiplier = joint.pitchFrequencyMultiplier; + } + if (isDefined(joint.pitchPhaseModifier)) { + this.pitchPhaseModifier = joint.pitchPhaseModifier; + } + if (isDefined(joint.pitchSign)) { + this.pitchSign = joint.pitchSign; + } + if (isDefined(joint.yawSign)) { + this.yawSign = joint.yawSign; + } + if (isDefined(joint.rollSign)) { + this.rollSign = joint.rollSign; + } + if (isDefined(joint.pitchReverseInvert) && direction === BACKWARDS) { + this.pitchReverseInvert = joint.pitchReverseInvert; + } + if (isDefined(joint.pitchReverseModifier) && direction === BACKWARDS) { + this.pitchReverseModifier = joint.pitchReverseModifier; + } + if (isDefined(joint.yawReverseModifier) && direction === BACKWARDS) { + this.yawReverseModifier = joint.yawReverseModifier; + } + if (isDefined(joint.rollReverseModifier) && direction === BACKWARDS) { + this.rollReverseModifier = joint.rollReverseModifier; + } + if (isDefined(joint.pitchOffsetSign)) { + this.pitchOffsetSign = joint.pitchOffsetSign; + } + if (isDefined(joint.yawOffsetSign)) { + this.yawOffsetSign = joint.yawOffsetSign; + } + if (isDefined(joint.rollOffsetSign)) { + this.rollOffsetSign = joint.rollOffsetSign; + } + if (isDefined(joint.bobReverseModifier) && direction === BACKWARDS) { + this.bobReverseModifier = joint.bobReverseModifier; + } + if (isDefined(joint.bobFrequencyMultiplier)) { + this.bobFrequencyMultiplier = joint.bobFrequencyMultiplier; + } + if (isDefined(joint.thrustFrequencyMultiplier)) { + this.thrustFrequencyMultiplier = joint.thrustFrequencyMultiplier; + } +}; + +walkAssets = (function () { + + // load the sounds - currently disabled due to breaking changes in js audio native objects + //var _pathToSounds = 'https://s3.amazonaws.com/hifi-public/sounds/Footsteps/'; + + //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-standing-one-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-flying-blend-animation.js"); + Script.include(pathToAssets+"animations/dd-female-hovering-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-standing-one-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-flying-blend-animation.js"); + Script.include(pathToAssets+"animations/dd-male-hovering-animation.js"); + Script.include(pathToAssets+"animations/dd-male-sidestep-left-animation.js"); + Script.include(pathToAssets+"animations/dd-male-sidestep-right-animation.js"); + Script.include(pathToAssets+"animations/dd-animation-reference.js"); + + var _femaleStandardWalk = new FemaleStandardWalk(); + var _femaleFlyingUp = new FemaleFlyingUp(); + var _femaleFlying = new FemaleFlying(); + var _femaleFlyingDown = new FemaleFlyingDown(); + var _femaleStandOne = new FemaleStandingOne(); + var _femaleSideStepLeft = new FemaleSideStepLeft(); + var _femaleSideStepRight = new FemaleSideStepRight(); + var _femaleFlyingBlend = new FemaleFlyingBlend(); + var _femaleHovering = new FemaleHovering(); + + var _maleStandardWalk = new MaleStandardWalk(filter); + var _maleStandOne = new MaleStandingOne(); + var _maleSideStepLeft = new MaleSideStepLeft(); + var _maleSideStepRight = new MaleSideStepRight(); + var _maleFlying = new MaleFlying(); + var _maleFlyingDown = new MaleFlyingDown(); + var _maleFlyingUp = new MaleFlyingUp(); + var _maleFlyingBlend = new MaleFlyingBlend(); + var _maleHovering = new MaleHovering(); + + var _animationReference = new AnimationReference(); + + return { + + // expose the sound assets + //footsteps: _footsteps, + + // expose the animation assets + femaleStandardWalk: _femaleStandardWalk, + femaleFlyingUp: _femaleFlyingUp, + femaleFlying: _femaleFlying, + femaleFlyingDown: _femaleFlyingDown, + femaleFlyingBlend: _femaleFlyingBlend, + femaleHovering: _femaleHovering, + femaleStandOne: _femaleStandOne, + femaleSideStepLeft: _femaleSideStepLeft, + femaleSideStepRight: _femaleSideStepRight, + maleStandardWalk: _maleStandardWalk, + maleFlyingUp: _maleFlyingUp, + maleFlying: _maleFlying, + maleFlyingDown: _maleFlyingDown, + maleFlyingBlend: _maleFlyingBlend, + maleHovering: _maleHovering, + maleStandOne: _maleStandOne, + maleSideStepLeft: _maleSideStepLeft, + maleSideStepRight: _maleSideStepRight, + animationReference: _animationReference, + } + })(); \ No newline at end of file diff --git a/examples/libraries/walkFilters.js b/examples/libraries/walkFilters.js index 98a7562bb4..4e77fe6ec7 100644 --- a/examples/libraries/walkFilters.js +++ b/examples/libraries/walkFilters.js @@ -1,225 +1,277 @@ -// -// walkFilters.js -// -// version 1.001 -// -// 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) { - - // cut off frequency = 5Hz - this.gain = 20.20612010; - this.coeffOne = -0.4775922501; - this.coeffTwo = 1.2796324250; - - // 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 (4n-1)th harmonics 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 (clips bottom of wave only, special case for hips y-axis skeleton offset) - clipTrough: function(inputValue, peak, strength) { - - var outputValue = inputValue * strength; - if (outputValue < -peak) { - outputValue = -peak; - } - return outputValue; - } - } - +// +// walkFilters.js +// +// version 1.002 +// +// Created by David Wooldridge, Autumn 2014 +// +// Provides a variety of filters for use by the walk.js script v1.12 +// +// 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] !== null) { + + // 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; + } + }; +}; + + +// 1st order Butterworth 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 (-3 dB @ 3 Hz) +ButterworthFilter1 = function() { + + this.gain = 7.313751515; + this.coeff = 0.7265425280; + + // initialise the arrays + this.xv = []; + this.yv = []; + + for(var i = 0; i < 2; i++) { + + this.xv.push(0); + this.yv.push(0); + } + + // process values + this.process = function(nextInputValue) { + + this.xv[0] = this.xv[1]; + this.xv[1] = nextInputValue / this.gain; + + this.yv[0] = this.yv[1]; + this.yv[1] = this.xv[0] + this.xv[1] + this.coeff * this.yv[0]; + + return this.yv[1]; + }; + +}; // end Butterworth filter constructor + +// 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 +ButterworthFilter2 = function(cutOff) { + + switch(cutOff) { + + case 5: + default: + + 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 constructor + + +// 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.smoothingFilter = new AveragingFilter(smoothing); + + // NB: frequency in radians + this.calculate = 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 = 1; 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 (4n-1)th harmonics 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.smoothingFilter.process(harmonics); + }; +}; + +// Create a motion wave 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 +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; + }, + + createButterworthFilter1: function() { + + var newButterworthFilter = new ButterworthFilter1(); + return newButterworthFilter; + }, + + createButterworthFilter2: function(cutoff) { + + var newButterworthFilter = new ButterworthFilter2(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 (clips bottom of wave only) + 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 index aa0b533101..0375fb7bea 100644 --- a/examples/libraries/walkInterface.js +++ b/examples/libraries/walkInterface.js @@ -1,2690 +1,340 @@ -// -// walkInterface.js -// -// version 1.001 -// -// 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: - case _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); - return; - - case _onButton: - - _state.powerOn = false; - _state.setInternalState(state.STANDING); - Overlays.editOverlay(_offButton, { - visible: true - }); - Overlays.editOverlay(_onButton, { - visible: false - }); - return; - - case _backButton: - case _backButtonSelected: - - Overlays.editOverlay(_backButton, { - visible: false - }); - Overlays.editOverlay(_backButtonSelected, { - visible: false - }); - _state.setInternalState(_state.STANDING); - return; - - case _configWalkStylesButton: - - _state.setInternalState(_state.EDIT_WALK_STYLES); - return; - - case _configWalkTweaksButton: - - _state.setInternalState(_state.EDIT_WALK_TWEAKS); - return; - - case _configWalkJointsButton: - - _state.setInternalState(_state.EDIT_WALK_JOINTS); - return; - - case _configWalkButton: - - _state.setInternalState(_state.EDIT_WALK_STYLES); - return; - - case _configStandButton: - - _state.setInternalState(_state.EDIT_STANDING); - return; - - case _configSideStepLeftButton: - - _state.setInternalState(_state.EDIT_SIDESTEP_LEFT); - return; - - case _configSideStepRightButton: - - _state.setInternalState(_state.EDIT_SIDESTEP_RIGHT); - return; - - case _configFlyingButton: - - _state.setInternalState(_state.EDIT_FLYING); - return; - - case _configFlyingUpButton: - - _state.setInternalState(_state.EDIT_FLYING_UP); - return; - - case _configFlyingDownButton: - - _state.setInternalState(_state.EDIT_FLYING_DOWN); - return; - } - }; - - 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; - } else 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) +// +// walkInterface.js +// +// version 2.0 +// +// Created by David Wooldridge, Autumn 2014 +// +// Presents the UI for the walk.js script v1.12 +// +// 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() { + + // references to walk.js objects + var _motion = null; + var _walkAssets = null; + + // controller UI element positions and dimensions + var _backgroundWidth = 350; + var _backgroundHeight = 700; + var _backgroundX = Window.innerWidth - _backgroundWidth - 58; + var _backgroundY = Window.innerHeight / 2 - _backgroundHeight / 2; + var _bigButtonsY = 348; + + // Load up the overlays + var _buttonOverlays = []; + + // ui minimised tab + var _controlsMinimisedTab = Overlays.addOverlay("image", { + x: Window.innerWidth - 58, + y: Window.innerHeight - 145, + width: 50, height: 50, + imageURL: pathToAssets + 'overlay-images/minimised-tab.png', + visible: true, alpha: 0.9 + }); + + // ui background + var _controlsBackground = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX, + y: _backgroundY, + width: _backgroundWidth, + height: _backgroundHeight + }, + imageURL: pathToAssets + "overlay-images/background.png", + alpha: 1, visible: false + }); + + // button overlays + var _controlsMinimiseButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth - 62, + y: _backgroundY + 40, + width: 25, height: 25 + }, + imageURL: pathToAssets + "overlay-images/minimise-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_controlsMinimiseButton); + + var _onButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/power-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_onButton); + + var _offButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/power-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_offButton); + + var _femaleButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 60, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/female-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_femaleButton); + + var _femaleButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 60, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/female-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_femaleButtonSelected); + + var _maleButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 120, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/male-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_maleButton); + + var _maleButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 120, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/male-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_maleButtonSelected); + + var _armsFreeButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 180, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/arms-free-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_armsFreeButton); + + var _armsFreeButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 180, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/arms-free-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_armsFreeButtonSelected); + + var _footstepsButton = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 240, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/footstep-sounds-button.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_footstepsButton); + + var _footstepsButtonSelected = Overlays.addOverlay("image", { + bounds: { + x: _backgroundX + _backgroundWidth / 2 - 115, + y: _backgroundY + _bigButtonsY + 240, + width: 230, height: 36 + }, + imageURL: pathToAssets + "overlay-images/footstep-sounds-button-selected.png", + alpha: 1, visible: false + }); + _buttonOverlays.push(_footstepsButtonSelected); + + + function minimiseDialog(minimise) { + + Overlays.editOverlay(_controlsBackground, {visible: !minimise}); + Overlays.editOverlay(_controlsMinimisedTab, {visible: minimise}); + Overlays.editOverlay(_controlsMinimiseButton, {visible: !minimise}); + + if(_state.powerOn) { + + Overlays.editOverlay(_onButton, {visible: !minimise}); + Overlays.editOverlay(_offButton, {visible: false}); + + } else { + + Overlays.editOverlay(_onButton, {visible: false}); + Overlays.editOverlay(_offButton, {visible: !minimise}); + + } + if (_motion.avatarGender === FEMALE) { + + Overlays.editOverlay(_femaleButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_femaleButton, {visible: false}); + Overlays.editOverlay(_maleButtonSelected, {visible: false}); + Overlays.editOverlay(_maleButton, {visible: !minimise}); + + } else { + + Overlays.editOverlay(_femaleButtonSelected, {visible: false}); + Overlays.editOverlay(_femaleButton, {visible: !minimise}); + Overlays.editOverlay(_maleButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_maleButton, {visible: false}); + } + if (_motion.armsFree) { + + Overlays.editOverlay(_armsFreeButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_armsFreeButton, {visible: false}); + + } else { + + Overlays.editOverlay(_armsFreeButtonSelected, {visible: false}); + Overlays.editOverlay(_armsFreeButton, {visible: !minimise}); + } + if (_motion.makesFootStepSounds) { + + Overlays.editOverlay(_footstepsButtonSelected, {visible: !minimise}); + Overlays.editOverlay(_footstepsButton, {visible: false}); + + } else { + + Overlays.editOverlay(_footstepsButtonSelected, {visible: false}); + Overlays.editOverlay(_footstepsButton, {visible: !minimise}); + } + }; + + // mouse event handler + function mousePressEvent(event) { + + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + + switch (clickedOverlay) { + + case _controlsMinimiseButton: + + minimiseDialog(true); + _state.setInternalState(_state.STANDING); + return; + + case _controlsMinimisedTab: + + minimiseDialog(false); + _state.setInternalState(_state.STANDING); + return; + + case _onButton: + + _state.powerOn = false; + Overlays.editOverlay(_offButton, {visible: true}); + Overlays.editOverlay(_onButton, {visible: false}); + _state.setInternalState(state.STANDING); + return; + + case _offButton: + + _state.powerOn = true; + Overlays.editOverlay(_offButton, {visible: false}); + Overlays.editOverlay(_onButton, {visible: true}); + _state.setInternalState(state.STANDING); + return; + + + case _footstepsButton: + + _motion.makesFootStepSounds = true; + Overlays.editOverlay(_footstepsButtonSelected, {visible: true}); + Overlays.editOverlay(_footstepsButton, {visible: false}); + return; + + case _footstepsButtonSelected: + + _motion.makesFootStepSounds = false; + Overlays.editOverlay(_footstepsButton, {visible: true}); + Overlays.editOverlay(_footstepsButtonSelected, {visible: false}); + return; + + case _femaleButton: + case _maleButtonSelected: + + _motion.setGender(FEMALE); + Overlays.editOverlay(_femaleButtonSelected, {visible: true}); + Overlays.editOverlay(_femaleButton, {visible: false}); + Overlays.editOverlay(_maleButton, {visible: true}); + Overlays.editOverlay(_maleButtonSelected, {visible: false}); + return; + + case _maleButton: + case _femaleButtonSelected: + + _motion.setGender(MALE); + Overlays.editOverlay(_femaleButton, {visible: true}); + Overlays.editOverlay(_femaleButtonSelected, {visible: false}); + Overlays.editOverlay(_maleButtonSelected, {visible: true}); + Overlays.editOverlay(_maleButton, {visible: false}); + return; + + case _armsFreeButton: + + _motion.armsFree = true; + Overlays.editOverlay(_armsFreeButtonSelected, {visible: true}); + Overlays.editOverlay(_armsFreeButton, {visible: false}); + return; + + case _armsFreeButtonSelected: + + _motion.armsFree = false; + _motion.poseFingers(); + Overlays.editOverlay(_armsFreeButtonSelected, {visible: false}); + Overlays.editOverlay(_armsFreeButton, {visible: true}); + return; + } + }; + + Controller.mousePressEvent.connect(mousePressEvent); + + // delete overlays on script ending + Script.scriptEnding.connect(function() { + + // delete overlays + Overlays.deleteOverlay(_controlsBackground); + Overlays.deleteOverlay(_controlsMinimisedTab); + for (var i in _buttonOverlays) { + Overlays.deleteOverlay(_buttonOverlays[i]); + } + }); + + // public method + return { + + // gather references to objects from the walk.js script + initialise: function(state, motion, walkAssets) { + + _state = state; + _motion = motion; + _walkAssets = walkAssets; + } + + }; // end public methods (return) + })(); \ No newline at end of file diff --git a/examples/newEditEntities.js b/examples/newEditEntities.js index 92db9daab5..ef1be8fef9 100644 --- a/examples/newEditEntities.js +++ b/examples/newEditEntities.js @@ -566,6 +566,10 @@ function mouseReleaseEvent(event) { } function mouseClickEvent(event) { + if (!isActive) { + return; + } + var result = findClickedEntity(event); if (result === null) { if (!event.isShifted) { @@ -636,6 +640,7 @@ Controller.mouseReleaseEvent.connect(mouseReleaseEvent); // exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that // added it. var modelMenuAddedDelete = false; +var originalLightsArePickable = Entities.getLightsArePickable(); function setupModelMenus() { print("setupModelMenus()"); // adj our menuitems @@ -653,10 +658,12 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List...", afterItem: "Models" }); Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L", + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Large Models", shortcutKey: "CTRL+META+L", afterItem: "Paste Models", isCheckable: true, isChecked: true }); - Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S", - afterItem: "Allow Select Large Models", isCheckable: true, isChecked: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Small Models", shortcutKey: "CTRL+META+S", + afterItem: "Allow Selecting of Large Models", isCheckable: true, isChecked: true }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Selecting of Lights", shortcutKey: "CTRL+SHIFT+META+L", + afterItem: "Allow Selecting of Small Models", isCheckable: true }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); @@ -665,6 +672,8 @@ function setupModelMenus() { Menu.addMenuItem({ menuName: "View", menuItemName: MENU_EASE_ON_FOCUS, afterItem: MENU_INSPECT_TOOL_ENABLED, isCheckable: true, isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true" }); + + Entities.setLightsArePickable(false); } setupModelMenus(); // do this when first running our script. @@ -679,8 +688,9 @@ function cleanupModelMenus() { Menu.removeMenuItem("Edit", "Model List..."); Menu.removeMenuItem("Edit", "Paste Models"); - Menu.removeMenuItem("Edit", "Allow Select Large Models"); - Menu.removeMenuItem("Edit", "Allow Select Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); Menu.removeSeparator("File", "Models"); Menu.removeMenuItem("File", "Export Models"); @@ -704,6 +714,7 @@ Script.scriptEnding.connect(function() { if (exportMenu) { exportMenu.close(); } + Entities.setLightsArePickable(originalLightsArePickable); }); // Do some stuff regularly, like check for placement of various overlays @@ -714,10 +725,12 @@ Script.update.connect(function (deltaTime) { }); function handeMenuEvent(menuItem) { - if (menuItem == "Allow Select Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Select Small Models"); - } else if (menuItem == "Allow Select Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Select Large Models"); + if (menuItem == "Allow Selecting of Small Models") { + allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); + } else if (menuItem == "Allow Selecting of Large Models") { + allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); + } else if (menuItem == "Allow Selecting of Lights") { + Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); } else if (menuItem == "Delete") { if (SelectionManager.hasSelection()) { print(" Delete Entities"); diff --git a/examples/walk.js b/examples/walk.js index 5a0df72f26..be2a1584d4 100644 --- a/examples/walk.js +++ b/examples/walk.js @@ -1,2613 +1,852 @@ -// -// walk.js -// -// version 1.1 -// -// 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 -// - -// constants -var MALE = 1; -var FEMALE = 2; -var MAX_WALK_SPEED = 2.5;//3.919; -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; - -// location of animation files and overlay images -var pathToAssets = 'http://s3.amazonaws.com/hifi-public/WalkScript/'; - -// load the UI -Script.include("./libraries/walkInterface.js"); - -// load filters (Bezier, Butterworth, add harmonics, averaging) -Script.include("./libraries/walkFilters.js"); - -// load objects, constructors and assets (state, Motion, Transition, walkAssets) -Script.include("./libraries/walkApi.js"); - -// initialise the motion state / history object -var motion = new Motion(); - -// initialise Transitions -var nullTransition = new Transition(); -motion.curTransition = nullTransition; - -// initialise the UI -walkInterface.initialise(state, motion, walkAssets); - -// wave shapes -var SAWTOOTH = 1; -var TRIANGLE = 2; -var SQUARE = 4; - -// various 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); - - -// Main loop -Script.update.connect(function(deltaTime) { - - if (state.powerOn) { - - motion.frameStartTime = new Date().getTime(); - motion.cumulativeTime += deltaTime; - motion.nFrames++; - var speed = 0; - - // check for editing modes first, as these require no positioning calculations - switch (state.currentState) { - - case state.EDIT_WALK_STYLES: { - motion.curAnim = motion.selWalk; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_WALK_TWEAKS: { - motion.curAnim = motion.selWalk; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_WALK_JOINTS: { - motion.curAnim = motion.selWalk; - animateAvatar(deltaTime, speed); - break; - } - case state.EDIT_STANDING: { - motion.curAnim = motion.selStand; - motion.direction = FORWARDS; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_SIDESTEP_LEFT: { - motion.curAnim = motion.selSideStepLeft; - motion.direction = LEFT; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_SIDESTEP_RIGHT: { - motion.curAnim = motion.selSideStepRight; - motion.direction = RIGHT; - animateAvatar(deltaTime, speed); - break; - } - - case state.EDIT_FLYING: { - motion.curAnim = motion.selFly; - motion.direction = FORWARDS; - animateAvatar(deltaTime, speed); - break; - } - - 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; - } 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(localVelocity.x) > Math.abs(localVelocity.y) && - Math.abs(localVelocity.x) > Math.abs(localVelocity.z)) { - - 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 === 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 - // note: The transitions are not compete, and are the most likely - // candidate for the next worklist item - switch (actionToTake) { - - case state.STANDING: { - - // do we need to change state? - if (state.currentState !== state.STANDING) { - - switch (motion.curAnim) { - - case motion.selWalk: { - - // 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; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - // Flying to Standing - motion.curTransition = new Transition( - motion.curAnim, - motion.selStand, - [], 0.5, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - break; - } - state.setInternalState(state.STANDING); - motion.curAnim = motion.selStand; - } - animateAvatar(deltaTime, speed); - break; - } - - case state.WALKING: { - - if (state.currentState !== state.WALKING) { - - 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.25, - {x: 0.5, y: 0.5}, - {x: 0.5, y: 0.5}); - break; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - // 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; - } - - default: - - 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; - } else { - motion.walkWheelPos = motion.selSideStepRight.calibration.cycleStart; - } - 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.35, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - case motion.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFlyUp, - [], 0.35, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - 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.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFlyDown, - [], 0.45, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - 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.selFly: - case motion.selFlyUp: - case motion.selFlyDown: { - - motion.curTransition = new Transition( - motion.curAnim, - motion.selFly, - [], 0.75, - {x: 0.5, y: 0.08}, - {x: 0.28, y: 1}); - break; - } - - default: - - break; - } - motion.curAnim = motion.selFly; - } - } - animateAvatar(deltaTime, speed); - break; - }// end case state.FLYING - - } // end switch(actionToTake) - - } // 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) { - - options = { - position: Camera.getPosition(), - volume: 0.3 - } - - 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; - } - - motion.curTransition.walkWheelIncrement = 3; - - // keep the walkwheel turning by setting the walkWheelIncrement - // until our feet are tucked nicely underneath us. - if (angleToLeftStop < angleToRightStop) { - motion.curTransition.walkStopAngle = leftStop; - } else { - motion.curTransition.walkStopAngle = rightStop; - } - - } else { - - // 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); - - } 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) { - - // 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) { - - if (motion.walkWheelPos < motion.curAnim.calibration.strideMaxAt + tolerance && - motion.walkWheelPos > motion.curAnim.calibration.strideMaxAt - tolerance) { - - 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; - - } else if (motion.direction === RIGHT) { - - if (motion.walkWheelPos < motion.curAnim.calibration.strideMaxAt + tolerance && - motion.walkWheelPos > motion.curAnim.calibration.strideMaxAt - tolerance) { - - 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.selSideStepRight.calibration.strideLength; - } - } // end get sidestep stride length - - // turn the walk wheel - if (motion.curAnim === motion.selWalk || - motion.curAnim === motion.selSideStepLeft || - motion.curAnim === motion.selSideStepRight || - motion.curTransition.walkingAtStart) { - - // 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; - - // calculate the degrees turned (at this angular speed) since last frame - var radiansTurnedSinceLastFrame = deltaTime * angularVelocity; - var degreesTurnedSinceLastFrame = filter.radToDeg(radiansTurnedSinceLastFrame); - - // 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; - } - - // advance the walk wheel the appropriate amount - motion.advanceWalkWheel(degreesTurnedSinceLastFrame); - - // set the new values for the exact correct walk cycle speed - adjFreq = 1; - cycle = motion.walkWheelPos; - - } // end of walk wheel and stride length calculation - - // 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; - - // 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; - - // feet - var sideStepFootPitchModifier = 1; - var sideStepHandPitchSign = 1; - - // calculate hips translation - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - 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 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; - - 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; - - 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; - - // end if walking at start of transition - - } else { - - swayOsc = motion.curAnim.joints[0].sway * - Math.sin(filter.degToRad(cycle * adjFreq + motion.curAnim.joints[0].swayPhase)) + - motion.curAnim.joints[0].swayOffset; - - 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) { - - // 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; - - thrustOsc = motion.curAnim.joints[0].thrust * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + - motion.curAnim.joints[0].thrustPhase)) + - motion.curAnim.joints[0].thrustOffset; - - 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; - - 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; - - 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; - } - - swayOsc = (transProgress * swayOsc) + ((1 - transProgress) * swayOscLast); - bobOsc = (transProgress * bobOsc) + ((1 - transProgress) * bobOscLast); - thrustOsc = (transProgress * thrustOsc) + ((1 - transProgress) * thrustOscLast); - - // end if walking at start of transition - - } else { - - swayOsc = motion.curAnim.joints[0].sway * - Math.sin(filter.degToRad(cycle * adjFreq + motion.curAnim.joints[0].swayPhase)) + - motion.curAnim.joints[0].swayOffset; - - 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) { - - // 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; - - thrustOsc = motion.curAnim.joints[0].thrust * - Math.sin(filter.degToRad(cycle * adjFreq * 2 + - motion.curAnim.joints[0].thrustPhase)) + - motion.curAnim.joints[0].thrustOffset; - } - - // 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}; - - aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviFront); - aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviRight); - aviTranslationOffset = Vec3.sum(aviTranslationOffset, aviUp); - - MyAvatar.setSkeletonOffset({ - x: aviTranslationOffset.x, - y: aviTranslationOffset.y, - z: aviTranslationOffset.z - }); - - // hips rotation - if (motion.curTransition !== nullTransition) { - - if (motion.curTransition.walkingAtStart) { - - 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; - - 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; - - 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); - - } 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)); - - 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); - } - - // 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 { - - 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; - } - - // 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 { - - 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; - } - - // apply toe rotations - MyAvatar.setJointData("RightToeBase", Quat.fromPitchYawRollDegrees( - pitchOsc + pitchOffset, - yawOsc + yawOffset, - rollOsc + rollOffset)); - - 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; - } - - // 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)); -} - -// Begin by setting an internal state -state.setInternalState(state.STANDING); +// +// walk.js +// +// version 1.12 +// +// 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 +// + +// constants +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; +var PITCH = 64; +var YAW = 128; +var ROLL = 256; +var SAWTOOTH = 1; +var TRIANGLE = 2; +var SQUARE = 4; +var VERY_LONG_TIME = 1000000.0; +var VERY_SHORT_TIME = 0.000001; + +// ovelay images location +var pathToAssets = 'http://s3.amazonaws.com/hifi-public/procedural-animator/'; + +// load the UI +Script.include("./libraries/walkInterface.js"); + +// load filters (Bezier, Butterworth, add harmonics, averaging) +Script.include("./libraries/walkFilters.js"); + +// load objects, constructors and assets (state, Motion, Transition, walkAssets) +Script.include("./libraries/walkApi.js"); + +// initialise the motion properties and history object +var motion = new Motion(); + +// initialise Transitions +var nullTransition = new Transition(); +motion.currentTransition = nullTransition; + +// initialise the UI +walkInterface.initialise(state, motion, walkAssets); + +// Begin by setting the STANDING internal state +state.setInternalState(state.STANDING); + +// smoothing filters +var leanPitchFilter = filter.createButterworthFilter1(); +var leanPitchSmoothingFilter = filter.createAveragingFilter(10); +var leanRollSmoothingFilter = filter.createAveragingFilter(10); +var flyUpFilter = filter.createAveragingFilter(30); +var flyFilter = filter.createAveragingFilter(30); + +// Main loop +Script.update.connect(function(deltaTime) { + + if (state.powerOn) { + + // calculate avi linear speed + var speed = Vec3.length(MyAvatar.getVelocity()); + + // decide which animation should be playing + selectAnimation(deltaTime, speed); + + // turn the frequency time wheels + turnFrequencyTimeWheels(deltaTime, speed); + + // calculate (or fetch pre-calculated) stride length for this avi + setStrideLength(speed); + + // update the progress of any live transition + updateTransition(); + + // apply translation and rotations + animateAvatar(deltaTime, speed); + } +}); + +// helper function for selectAnimation() +function determineLocomotionMode(speed) { + + var locomotionMode = undefined; + + if (speed < 0.1 && motion.currentAnimation !== motion.selectedFlyBlend) { + + locomotionMode = state.STANDING; + + } else if (speed === 0 && motion.currentAnimation === motion.selectedFlyBlend) { + + locomotionMode = state.STANDING; + + } else if (speed < TAKE_FLIGHT_SPEED) { + + locomotionMode = state.WALKING; + + } else if (speed >= TAKE_FLIGHT_SPEED) { + + locomotionMode = state.FLYING; + } + + // maybe travelling at walking speed, but sideways? + if (locomotionMode === state.WALKING && + (motion.direction === LEFT || + motion.direction === RIGHT)) { + + locomotionMode = state.SIDE_STEP; + } + + // maybe completing a final step during a walking to standing transition? + if (locomotionMode === state.WALKING && + motion.currentTransition.percentToMove > 0) { + + locomotionMode = state.STANDING; + } + + // maybe starting to fly up or down? + if (locomotionMode === state.WALKING && + motion.direction === UP || motion.direction === DOWN) { + + locomotionMode = state.FLYING; + } + + // are we on a voxel surface? + if(spatialInformation.distanceToVoxels() > 0.2 && speed > 0.1) { + + locomotionMode = state.FLYING; + } + + return locomotionMode; +} + +// helper function for selectAnimation() +function determineDirection(localVelocity) { + + if (Math.abs(localVelocity.x) > Math.abs(localVelocity.y) && + Math.abs(localVelocity.x) > Math.abs(localVelocity.z)) { + + if (localVelocity.x < 0) { + return LEFT; + } else { + return RIGHT; + } + + } else if (Math.abs(localVelocity.y) > Math.abs(localVelocity.x) && + Math.abs(localVelocity.y) > Math.abs(localVelocity.z)) { + + if (localVelocity.y > 0) { + return UP; + } else { + return DOWN; + } + + } else if (Math.abs(localVelocity.z) > Math.abs(localVelocity.x) && + Math.abs(localVelocity.z) > Math.abs(localVelocity.y)) { + + if (localVelocity.z < 0) { + return FORWARDS; + } else { + return BACKWARDS; + } + } +} + +// advance the animation's frequency time wheels. advance frequency time wheels for any live transitions also +function turnFrequencyTimeWheels(deltaTime, speed) { + + var wheelAdvance = 0; + + // turn the frequency time wheel + if (motion.currentAnimation === motion.selectedWalk || + motion.currentAnimation === motion.selectedSideStepLeft || + motion.currentAnimation === motion.selectedSideStepRight) { + + // Using technique described here: http://www.gdcvault.com/play/1020583/Animation-Bootcamp-An-Indie-Approach + // 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 + motion.frequencyTimeWheelRadius = motion.strideLength / Math.PI; + var angularVelocity = speed / motion.frequencyTimeWheelRadius; + + // calculate the degrees turned (at this angular speed) since last frame + wheelAdvance = filter.radToDeg(deltaTime * angularVelocity); + + } else { + + // turn the frequency time wheel by the amount specified for this animation + wheelAdvance = filter.radToDeg(motion.currentAnimation.calibration.frequency * deltaTime); + } + + if(motion.currentTransition !== nullTransition) { + + // the last animation is still playing so we turn it's frequency time wheel to maintain the animation + if (motion.currentTransition.lastAnimation === motion.selectedWalk) { + + // if at a stop angle (i.e. feet now under the avi) hold the wheel position for remainder of transition + var tolerance = motion.currentTransition.lastFrequencyTimeIncrement + 0.1; + if ((motion.currentTransition.lastFrequencyTimeWheelPos > + (motion.currentTransition.stopAngle - tolerance)) && + (motion.currentTransition.lastFrequencyTimeWheelPos < + (motion.currentTransition.stopAngle + tolerance))) { + + motion.currentTransition.lastFrequencyTimeIncrement = 0; + } + } + motion.currentTransition.advancePreviousFrequencyTimeWheel(); + } + + // advance the walk wheel the appropriate amount + motion.advanceFrequencyTimeWheel(wheelAdvance); +} + +// helper function for selectAnimation() +function setTransition(nextAnimation) { + + var lastTransition = motion.currentTransition; + motion.currentTransition = new Transition(nextAnimation, + motion.currentAnimation, + motion.currentTransition); + + if(motion.currentTransition.recursionDepth > 5) { + + delete motion.currentTransition; + motion.currentTransition = lastTransition; + } +} + +// select which animation should be played based on speed, mode of locomotion and direction of travel +function selectAnimation(deltaTime, speed) { + + var localVelocity = {x: 0, y: 0, z: 0}; + if (speed > 0) { + localVelocity = Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), MyAvatar.getVelocity()); + } + + // determine principle direction of movement + motion.direction = determineDirection(localVelocity); + + // determine mode of locomotion + var locomotionMode = determineLocomotionMode(speed); + + // select appropriate animation. If changing animation, initiate a new transition + // note: The transitions are work in progress: https://worklist.net/20186 + switch (locomotionMode) { + + case state.STANDING: { + + var onVoxelSurface = spatialInformation.distanceToVoxels() < 0.3 ? true : false; + + if (state.currentState !== state.STANDING) { + + if (onVoxelSurface) { + + setTransition(motion.selectedStand); + + } else { + + setTransition(motion.selectedHovering); + } + state.setInternalState(state.STANDING); + } + if (onVoxelSurface) { + + motion.currentAnimation = motion.selectedStand; + + } else { + + motion.currentAnimation = motion.selectedHovering; + } + break; + } + + case state.WALKING: { + + if (state.currentState !== state.WALKING) { + + setTransition(motion.selectedWalk); + // set the walk wheel to it's starting point for this animation + if (motion.direction === BACKWARDS) { + + motion.frequencyTimeWheelPos = motion.selectedWalk.calibration.startAngleBackwards; + + } else { + + motion.frequencyTimeWheelPos = motion.selectedWalk.calibration.startAngleForwards; + } + state.setInternalState(state.WALKING); + } + motion.currentAnimation = motion.selectedWalk; + break; + } + + case state.SIDE_STEP: { + + var selSideStep = undefined; + + if (state.currentState !== state.SIDE_STEP) { + + if (motion.direction === LEFT) { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepLeft.calibration.startAngle; + selSideStep = motion.selectedSideStepLeft; + + } else { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepRight.calibration.startAngle; + selSideStep = motion.selectedSideStepRight; + } + setTransition(selSideStep); + state.setInternalState(state.SIDE_STEP); + + } else if (motion.direction === LEFT) { + + if (motion.lastDirection !== LEFT) { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepLeft.calibration.startAngle; + setTransition(motion.selectedSideStepLeft); + } + selSideStep = motion.selectedSideStepLeft; + + } else { + + if (motion.lastDirection !== RIGHT) { + // set the walk wheel to it's starting point for this animation + motion.frequencyTimeWheelPos = motion.selectedSideStepRight.calibration.startAngle; + setTransition(motion.selectedSideStepRight); + } + selSideStep = motion.selectedSideStepRight; + } + motion.currentAnimation = selSideStep; + break; + } + + case state.FLYING: { + + // blend the up, down and forward flying animations relative to motion direction + animation.zeroAnimation(motion.selectedFlyBlend); + + var upVector = 0; + var forwardVector = 0; + + if (speed > 0) { + + // calculate directionals + upVector = localVelocity.y / speed; + forwardVector = -localVelocity.z / speed; + + // add damping + upVector = flyUpFilter.process(upVector); + forwardVector = flyFilter.process(forwardVector); + + // normalise + var denominator = Math.abs(upVector) + Math.abs(forwardVector); + upVector = upVector / denominator; + forwardVector = forwardVector / denominator; + } + + if (upVector > 0) { + + animation.blendAnimation(motion.selectedFlyUp, + motion.selectedFlyBlend, + upVector); + + } else if (upVector < 0) { + + animation.blendAnimation(motion.selectedFlyDown, + motion.selectedFlyBlend, + -upVector); + } else { + + forwardVector = 1; + } + animation.blendAnimation(motion.selectedFly, + motion.selectedFlyBlend, + Math.abs(forwardVector)); + + if (state.currentState !== state.FLYING) { + + state.setInternalState(state.FLYING); + setTransition(motion.selectedFlyBlend); + } + motion.currentAnimation = motion.selectedFlyBlend; + break; + } + + } // end switch(locomotionMode) + + // record frame details for future reference + motion.lastDirection = motion.direction; + motion.lastSpeed = localVelocity; + motion.lastDistanceToVoxels = motion.calibration.distanceToVoxels; + + return; +} + +// if the timing's right, recalculate the stride length. if not, fetch the previously calculated value +function setStrideLength(speed) { + + // if not at full speed the calculation could be wrong, as we may still be transitioning + var atMaxSpeed = speed / MAX_WALK_SPEED < 0.97 ? false : true; + + // walking? then get the stride length + if (motion.currentAnimation === motion.selectedWalk) { + + var strideMaxAt = motion.currentAnimation.calibration.forwardStrideMaxAt; + if (motion.direction === BACKWARDS) { + strideMaxAt = motion.currentAnimation.calibration.backwardsStrideMaxAt; + } + + var tolerance = 1.0; + if (motion.frequencyTimeWheelPos < (strideMaxAt + tolerance) && + motion.frequencyTimeWheelPos > (strideMaxAt - tolerance) && + atMaxSpeed && motion.currentTransition === nullTransition) { + + // 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.currentAnimation.calibration.strideLengthForwards = motion.strideLength; + } else if (motion.direction === BACKWARDS) { + motion.currentAnimation.calibration.strideLengthBackwards = motion.strideLength; + } + + } else { + + // use the previously saved value for stride length + if (motion.direction === FORWARDS) { + motion.strideLength = motion.currentAnimation.calibration.strideLengthForwards; + } else if (motion.direction === BACKWARDS) { + motion.strideLength = motion.currentAnimation.calibration.strideLengthBackwards; + } + } + } // end get walk stride length + + // sidestepping? get the stride length + if (motion.currentAnimation === motion.selectedSideStepLeft || + motion.currentAnimation === motion.selectedSideStepRight) { + + // 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) { + + if (motion.frequencyTimeWheelPos < motion.currentAnimation.calibration.strideMaxAt + tolerance && + motion.frequencyTimeWheelPos > motion.currentAnimation.calibration.strideMaxAt - tolerance && + atMaxSpeed && motion.currentTransition === nullTransition) { + + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + motion.currentAnimation.calibration.strideLength = motion.strideLength; + + } else { + + motion.strideLength = motion.selectedSideStepLeft.calibration.strideLength; + } + + } else if (motion.direction === RIGHT) { + + if (motion.frequencyTimeWheelPos < motion.currentAnimation.calibration.strideMaxAt + tolerance && + motion.frequencyTimeWheelPos > motion.currentAnimation.calibration.strideMaxAt - tolerance && + atMaxSpeed && motion.currentTransition === nullTransition) { + + var footRPos = MyAvatar.getJointPosition("RightFoot"); + var footLPos = MyAvatar.getJointPosition("LeftFoot"); + motion.strideLength = Vec3.distance(footRPos, footLPos); + motion.currentAnimation.calibration.strideLength = motion.strideLength; + + } else { + + motion.strideLength = motion.selectedSideStepRight.calibration.strideLength; + } + } + } // end get sidestep stride length +} + +// initialise a new transition. update progress of a live transition +function updateTransition() { + + if (motion.currentTransition !== nullTransition) { + + // new transition? + if (motion.currentTransition.progress === 0) { + + // overlapping transitions? + if (motion.currentTransition.lastTransition !== nullTransition) { + + // is the last animation for the nested transition the same as the new animation? + if (motion.currentTransition.lastTransition.lastAnimation === motion.currentAnimation) { + + // sync the nested transitions's frequency time wheel for a smooth animation blend + motion.frequencyTimeWheelPos = motion.currentTransition.lastTransition.lastFrequencyTimeWheelPos; + } + } + + if (motion.currentTransition.lastAnimation === motion.selectedWalk) { + + // decide at which angle we should stop the frequency time wheel + var stopAngle = motion.selectedWalk.calibration.stopAngleForwards; + var percentToMove = 0; + var lastFrequencyTimeWheelPos = motion.currentTransition.lastFrequencyTimeWheelPos; + var lastElapsedFTDegrees = motion.currentTransition.lastElapsedFTDegrees; + + // set the stop angle depending on which quadrant of the walk cycle we are currently in + // and decide whether we need to take an extra step to complete the walk cycle or not + // - currently work in progress + if(lastFrequencyTimeWheelPos <= stopAngle && lastElapsedFTDegrees < 180) { + + // we have not taken a complete step yet, so we do need to do so before stopping + percentToMove = 100; + stopAngle += 180; + + } else if(lastFrequencyTimeWheelPos > stopAngle && lastFrequencyTimeWheelPos <= stopAngle + 90) { + + // take an extra step to complete the walk cycle and stop at the second stop angle + percentToMove = 100; + stopAngle += 180; + + } else if(lastFrequencyTimeWheelPos > stopAngle + 90 && lastFrequencyTimeWheelPos <= stopAngle + 180) { + + // stop on the other foot at the second stop angle for this walk cycle + percentToMove = 0; + if (motion.currentTransition.lastDirection === BACKWARDS) { + + percentToMove = 100; + + } else { + + stopAngle += 180; + } + + } else if(lastFrequencyTimeWheelPos > stopAngle + 180 && lastFrequencyTimeWheelPos <= stopAngle + 270) { + + // take an extra step to complete the walk cycle and stop at the first stop angle + percentToMove = 100; + } + + // set it all in motion + motion.currentTransition.stopAngle = stopAngle; + motion.currentTransition.percentToMove = percentToMove; + } + + } // end if new transition + + // update the Transition progress + if (motion.currentTransition.updateProgress() >= 1) { + + // it's time to kill off this transition + delete motion.currentTransition; + motion.currentTransition = nullTransition; + } + } +} + +// helper function for animateAvatar(). calculate the amount to lean forwards (or backwards) based on the avi's acceleration +function getLeanPitch(speed) { + + var leanProgress = undefined; + + if (motion.direction === LEFT || + motion.direction === RIGHT || + motion.direction === UP) { + + leanProgress = 0; + + } else { + + // boost lean for flying (leaning whilst walking is work in progress) + var signedSpeed = -Vec3.multiplyQbyV(Quat.inverse(MyAvatar.orientation), MyAvatar.getVelocity()).z; + var reverseMod = 1; + var BOOST = 6; + + if (signedSpeed < 0) { + + reverseMod = -1.9; + if (motion.direction === DOWN) { + + reverseMod *= -1; + } + } + leanProgress = reverseMod * BOOST * speed / TOP_SPEED; + } + + // use filters to shape the walking acceleration response + leanProgress = leanPitchFilter.process(leanProgress); + leanProgress = leanPitchSmoothingFilter.process(leanProgress); + return motion.calibration.pitchMax * leanProgress; +} + +// helper function for animateAvatar(). calculate the angle at which to bank into corners whilst turning +function getLeanRoll(deltaTime, speed) { + + var leanRollProgress = 0; + var angularVelocity = filter.radToDeg(MyAvatar.getAngularVelocity().y); + + leanRollProgress = speed / TOP_SPEED; + leanRollProgress *= Math.abs(angularVelocity) / motion.calibration.angularVelocityMax; + + // shape the response curve + leanRollProgress = filter.bezier((1 - leanRollProgress), + {x: 0, y: 0}, {x: 0, y: 1.3}, {x: 0.25, y: 0.5}, {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; + } + + // add damping with averaging filter + leanRollProgress = leanRollSmoothingFilter.process(turnSign * leanRollProgress); + return motion.calibration.rollMax * leanRollProgress; +} + +// check for existence of object property (e.g. animation waveform synthesis filters) +function isDefined(value) { + + try { + if (typeof value != 'undefined') return true; + } catch (e) { + return false; + } +} + +// helper function for animateAvatar(). calculate joint translations based on animation file settings and frequency * time +function calculateTranslations(animation, ft, direction) { + + var jointName = "Hips"; + var joint = animation.joints[jointName]; + var jointTranslations = {x:0, y:0, z:0}; + + // gather modifiers and multipliers + modifiers = new JointModifiers(joint, direction); + + // calculate translations. Use synthesis filters where specified by the animation file. + + // sway (oscillation on the x-axis) + if(animation.filters.hasOwnProperty(jointName) && + 'swayFilter' in animation.filters[jointName]) { + + jointTranslations.x = joint.sway * + animation.filters[jointName].swayFilter. + calculate(filter.degToRad(ft + joint.swayPhase)) + + joint.swayOffset; + + } else { + + jointTranslations.x = joint.sway * + Math.sin(filter.degToRad(ft + joint.swayPhase)) + + joint.swayOffset; + } + + // bob (oscillation on the y-axis) + if(animation.filters.hasOwnProperty(jointName) && + 'bobFilter' in animation.filters[jointName]) { + + jointTranslations.y = joint.bob * + animation.filters[jointName].bobFilter.calculate + (filter.degToRad(modifiers.bobFrequencyMultiplier * ft + + joint.bobPhase + modifiers.bobReverseModifier)) + + joint.bobOffset; + + } else { + + jointTranslations.y = joint.bob * + Math.sin(filter.degToRad(modifiers.bobFrequencyMultiplier * ft + + joint.bobPhase + modifiers.bobReverseModifier)) + + joint.bobOffset; + + // check for specified low pass filter for this joint (currently Hips bob only) + if(animation.filters.hasOwnProperty(jointName) && + 'bobLPFilter' in animation.filters[jointName]) { + + jointTranslations.y = filter.clipTrough(jointTranslations.y, joint, 2); + jointTranslations.y = animation.filters[jointName].bobLPFilter.process(jointTranslations.y); + } + } + + // thrust (oscillation on the z-axis) + if(animation.filters.hasOwnProperty(jointName) && + 'thrustFilter' in animation.filters[jointName]) { + + jointTranslations.z = joint.thrust * + animation.filters[jointName].thrustFilter. + calculate(filter.degToRad(modifiers.thrustFrequencyMultiplier * ft + + joint.thrustPhase)) + + joint.thrustOffset; + + } else { + + jointTranslations.z = joint.thrust * + Math.sin(filter.degToRad(modifiers.thrustFrequencyMultiplier * ft + + joint.thrustPhase)) + + joint.thrustOffset; + } + + return jointTranslations; +} + +// helper function for animateAvatar(). calculate joint rotations based on animation file settings and frequency * time +function calculateRotations(jointName, animation, ft, direction) { + + var joint = animation.joints[jointName]; + var jointRotations = {x:0, y:0, z:0}; + + // gather modifiers and multipliers for this joint + modifiers = new JointModifiers(joint, direction); + + // calculate rotations. Use synthesis filters where specified by the animation file. + + // calculate pitch + if(animation.filters.hasOwnProperty(jointName) && + 'pitchFilter' in animation.filters[jointName]) { + + jointRotations.x = modifiers.pitchReverseInvert * (modifiers.pitchSign * joint.pitch * + animation.filters[jointName].pitchFilter.calculate + (filter.degToRad(ft * modifiers.pitchFrequencyMultiplier + + joint.pitchPhase + modifiers.pitchPhaseModifier + modifiers.pitchReverseModifier)) + + modifiers.pitchOffsetSign * joint.pitchOffset); + + } else { + + jointRotations.x = modifiers.pitchReverseInvert * (modifiers.pitchSign * joint.pitch * + Math.sin(filter.degToRad(ft * modifiers.pitchFrequencyMultiplier + + joint.pitchPhase + modifiers.pitchPhaseModifier + modifiers.pitchReverseModifier)) + + modifiers.pitchOffsetSign * joint.pitchOffset); + } + + // calculate yaw + if(animation.filters.hasOwnProperty(jointName) && + 'yawFilter' in animation.filters[jointName]) { + + jointRotations.y = modifiers.yawSign * joint.yaw * + animation.filters[jointName].yawFilter.calculate + (filter.degToRad(ft + joint.yawPhase + modifiers.yawReverseModifier)) + + modifiers.yawOffsetSign * joint.yawOffset; + + } else { + + jointRotations.y = modifiers.yawSign * joint.yaw * + Math.sin(filter.degToRad(ft + joint.yawPhase + modifiers.yawReverseModifier)) + + modifiers.yawOffsetSign * joint.yawOffset; + } + + // calculate roll + if(animation.filters.hasOwnProperty(jointName) && + 'rollFilter' in animation.filters[jointName]) { + + jointRotations.z = modifiers.rollSign * joint.roll * + animation.filters[jointName].rollFilter.calculate + (filter.degToRad(ft + joint.rollPhase + modifiers.rollReverseModifier)) + + modifiers.rollOffsetSign * joint.rollOffset; + + } else { + + jointRotations.z = modifiers.rollSign * joint.roll * + Math.sin(filter.degToRad(ft + joint.rollPhase + modifiers.rollReverseModifier)) + + modifiers.rollOffsetSign * joint.rollOffset; + } + return jointRotations; +} + +// animate the avatar using sine waves, geometric waveforms and harmonic generators +function animateAvatar(deltaTime, speed) { + + // adjust leaning direction for flying + var flyingModifier = 1; + if (state.currentState.FLYING) { + + flyingModifier = -1; + } + + // leaning in response to speed and acceleration (affects Hips pitch and z-axis acceleration driven offset) + var leanPitch = getLeanPitch(speed); + + // hips translations + var hipsTranslations = undefined; + if (motion.currentTransition !== nullTransition) { + + hipsTranslations = motion.currentTransition.blendTranslations(motion.frequencyTimeWheelPos, motion.direction); + + } else { + + hipsTranslations = calculateTranslations(motion.currentAnimation, + motion.frequencyTimeWheelPos, + motion.direction); + } + + // factor in any acceleration driven leaning + hipsTranslations.z += motion.calibration.hipsToFeet * Math.sin(filter.degToRad(leanPitch)); + + // apply translations + MyAvatar.setSkeletonOffset(hipsTranslations); + + // joint rotations + for (jointName in walkAssets.animationReference.joints) { + + // ignore arms rotations if 'arms free' is selected for Leap / Hydra use + if((walkAssets.animationReference.joints[jointName].IKChain === "LeftArm" || + walkAssets.animationReference.joints[jointName].IKChain === "RightArm") && + motion.armsFree) { + + continue; + } + + if (isDefined(motion.currentAnimation.joints[jointName])) { + + var jointRotations = undefined; + + // if there's a live transition, blend the rotations with the last animation's rotations for this joint + if (motion.currentTransition !== nullTransition) { + + jointRotations = motion.currentTransition.blendRotations(jointName, + motion.frequencyTimeWheelPos, + motion.direction); + } else { + + jointRotations = calculateRotations(jointName, + motion.currentAnimation, + motion.frequencyTimeWheelPos, + motion.direction); + } + + // apply lean + if (jointName === "Hips") { + + jointRotations.x += leanPitch; + jointRotations.z += getLeanRoll(deltaTime, speed); + } + + // apply rotation + MyAvatar.setJointData(jointName, Quat.fromVec3Degrees(jointRotations)); + } + } +} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 06965df947..fe6e81bd79 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -896,6 +896,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Greater: case Qt::Key_Comma: case Qt::Key_Period: + case Qt::Key_QuoteDbl: Menu::getInstance()->handleViewFrustumOffsetKeyModifier(event->key()); break; case Qt::Key_L: @@ -2090,12 +2091,6 @@ void Application::updateMouseRay() { _mouseRayDirection -= 2.0f * (_viewFrustum.getDirection() * glm::dot(_viewFrustum.getDirection(), _mouseRayDirection) + _viewFrustum.getRight() * glm::dot(_viewFrustum.getRight(), _mouseRayDirection)); } - - // tell my avatar if the mouse is being pressed... - _myAvatar->setMousePressed(_mousePressed); - - // tell my avatar the posiion and direction of the ray projected ino the world based on the mouse position - _myAvatar->setMouseRay(_mouseRayOrigin, _mouseRayDirection); } void Application::updateFaceshift() { @@ -2916,7 +2911,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly, RenderAr // transform by eye offset // load the view frustum - loadViewFrustum(whichCamera, _displayViewFrustum); + loadViewFrustum(whichCamera, _viewFrustum); // flip x if in mirror mode (also requires reversing winding order for backface culling) if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -3190,7 +3185,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { // allow 3DTV/Oculus to override parameters from camera - _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + _viewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); if (OculusManager::isConnected()) { OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); diff --git a/interface/src/Application.h b/interface/src/Application.h index e432f7fdf0..b737141b40 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -196,7 +196,6 @@ public: const AudioReflector* getAudioReflector() const { return &_audioReflector; } Camera* getCamera() { return &_myCamera; } ViewFrustum* getViewFrustum() { return &_viewFrustum; } - ViewFrustum* getDisplayViewFrustum() { return &_displayViewFrustum; } ViewFrustum* getShadowViewFrustum() { return &_shadowViewFrustum; } VoxelImporter* getVoxelImporter() { return &_voxelImporter; } VoxelSystem* getVoxels() { return &_voxels; } @@ -518,7 +517,6 @@ private: ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) - ViewFrustum _displayViewFrustum; ViewFrustum _shadowViewFrustum; quint64 _lastQueriedTime; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6cfb3db35a..ae12b5ff26 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -835,6 +835,14 @@ void Menu::handleViewFrustumOffsetKeyModifier(int key) { const float VIEW_FRUSTUM_OFFSET_UP_DELTA = 0.05f; switch (key) { + case Qt::Key_QuoteDbl: + _viewFrustumOffset.yaw = 0.0f; + _viewFrustumOffset.pitch = 0.0f; + _viewFrustumOffset.roll = 0.0f; + _viewFrustumOffset.up = 0.0f; + _viewFrustumOffset.distance = 0.0f; + break; + case Qt::Key_BracketLeft: _viewFrustumOffset.yaw -= VIEW_FRUSTUM_OFFSET_DELTA; break; diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b98fea8eca..996b92e22d 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -192,7 +192,7 @@ static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM; void MetavoxelSystem::render() { // update the frustum - ViewFrustum* viewFrustum = Application::getInstance()->getDisplayViewFrustum(); + ViewFrustum* viewFrustum = Application::getInstance()->getViewFrustum(); _frustum.set(viewFrustum->getFarTopLeft(), viewFrustum->getFarTopRight(), viewFrustum->getFarBottomLeft(), viewFrustum->getFarBottomRight(), viewFrustum->getNearTopLeft(), viewFrustum->getNearTopRight(), viewFrustum->getNearBottomLeft(), viewFrustum->getNearBottomRight()); @@ -1896,7 +1896,7 @@ private: SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : SpannerVisitor(QVector() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector(), QVector(), lod, - encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } @@ -1932,7 +1932,7 @@ private: BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) : MetavoxelVisitor(QVector() << attribute), - _order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())), + _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())), _containmentDepth(INT_MAX) { } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 03243c1a83..c680c75056 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -66,8 +66,6 @@ Avatar::Avatar() : _leanScale(0.5f), _scale(1.0f), _worldUpDirection(DEFAULT_UP_DIRECTION), - _mouseRayOrigin(0.0f, 0.0f, 0.0f), - _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), _collisionGroups(0), _initialized(false), @@ -250,11 +248,6 @@ void Avatar::measureMotionDerivatives(float deltaTime) { _lastOrientation = getOrientation(); } -void Avatar::setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction) { - _mouseRayOrigin = origin; - _mouseRayDirection = direction; -} - enum TextRendererType { CHAT, DISPLAYNAME diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 2d1a44403f..88ab3b12ca 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -85,7 +85,6 @@ public: //setters void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); } - void setMouseRay(const glm::vec3 &origin, const glm::vec3 &direction); void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; } bool getIsLookAtTarget() const { return _isLookAtTarget; } //getters @@ -213,8 +212,6 @@ protected: float _leanScale; float _scale; glm::vec3 _worldUpDirection; - glm::vec3 _mouseRayOrigin; - glm::vec3 _mouseRayDirection; float _stringLength; bool _moving; ///< set when position is changing diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index ba5ba8141d..25916d761c 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -87,7 +87,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { if (!shouldKillAvatar(sharedAvatar)) { // this avatar's mixer is still around, go ahead and simulate it avatar->simulate(deltaTime); - avatar->setMouseRay(mouseOrigin, mouseDirection); ++avatarIterator; } else { // the mixer that owned this avatar is gone, give it to the vector of fades and kill it diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9f3309ece2..32053ea076 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -67,7 +67,6 @@ const int SCRIPTED_MOTOR_WORLD_FRAME = 2; MyAvatar::MyAvatar() : Avatar(), - _mousePressed(false), _turningKeyPressTime(0.0f), _gravity(0.0f, 0.0f, 0.0f), _distanceToNearestAvatar(std::numeric_limits::max()), diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 37b93e2f04..12ad4474c9 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -55,15 +55,12 @@ public: void renderHeadMouse(int screenWidth, int screenHeight) const; // setters - void setMousePressed(bool mousePressed) { _mousePressed = mousePressed; } void setLeanScale(float scale) { _leanScale = scale; } void setLocalGravity(glm::vec3 gravity); void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; } // getters float getLeanScale() const { return _leanScale; } - const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } - const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } glm::vec3 getGravity() const { return _gravity; } glm::vec3 getDefaultEyePosition() const; bool getShouldRenderLocally() const { return _shouldRender; } @@ -203,7 +200,6 @@ protected: virtual void renderAttachments(RenderMode renderMode); private: - bool _mousePressed; float _turningKeyPressTime; glm::vec3 _gravity; float _distanceToNearestAvatar; // How close is the nearest avatar? diff --git a/interface/src/entities/RenderableLightEntityItem.cpp b/interface/src/entities/RenderableLightEntityItem.cpp index e3e8f61e58..91b2d35106 100644 --- a/interface/src/entities/RenderableLightEntityItem.cpp +++ b/interface/src/entities/RenderableLightEntityItem.cpp @@ -90,3 +90,14 @@ void RenderableLightEntityItem::render(RenderArgs* args) { glPopMatrix(); } }; + +bool RenderableLightEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + // TODO: this isn't really correct because we don't know if we actually live in the main tree of the applications's + // EntityTreeRenderer. But we probably do. Technically we could be on the clipboard and someone might be trying to + // use the ray intersection API there. Anyway... if you ever try to do ray intersection testing off of trees other + // than the main tree of the main entity renderer, then you'll need to fix this mechanism. + return Application::getInstance()->getEntities()->getTree()->getLightsArePickable(); +} diff --git a/interface/src/entities/RenderableLightEntityItem.h b/interface/src/entities/RenderableLightEntityItem.h index cecd9b761e..40fa31a4ce 100644 --- a/interface/src/entities/RenderableLightEntityItem.h +++ b/interface/src/entities/RenderableLightEntityItem.h @@ -34,6 +34,10 @@ public: { } virtual void render(RenderArgs* args); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; }; diff --git a/interface/src/renderer/DeferredLightingEffect.cpp b/interface/src/renderer/DeferredLightingEffect.cpp index be4e457131..63d874cda7 100644 --- a/interface/src/renderer/DeferredLightingEffect.cpp +++ b/interface/src/renderer/DeferredLightingEffect.cpp @@ -232,8 +232,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, Application::getInstance()->getDisplayViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = Application::getInstance()->getViewFrustum()->getPosition(); + float nearRadius = glm::distance(eyePoint, Application::getInstance()->getViewFrustum()->getNearTopLeft()); if (!_pointLights.isEmpty()) { _pointLight.bind(); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index c1b1f243ef..7dbcaed8fc 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -134,6 +134,11 @@ public: virtual SimulationState computeSimulationState() const; virtual void debugDump() const; + + virtual bool supportsDetailedRayIntersection() const { return false; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { return true; } // attributes applicable to all entity types EntityTypes::EntityType getType() const { return _type; } diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 29c4a8b19a..575a6c1a78 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -221,6 +221,19 @@ RayToEntityIntersectionResult EntityScriptingInterface::findRayIntersectionWorke return result; } +void EntityScriptingInterface::setLightsArePickable(bool value) { + if (_entityTree) { + _entityTree->setLightsArePickable(value); + } +} + +bool EntityScriptingInterface::getLightsArePickable() const { + if (_entityTree) { + return _entityTree->getLightsArePickable(); + } + return false; +} + RayToEntityIntersectionResult::RayToEntityIntersectionResult() : intersects(false), diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 2150fa51da..da0c6c9f1a 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -96,6 +96,8 @@ public slots: /// order to return an accurate result Q_INVOKABLE RayToEntityIntersectionResult findRayIntersectionBlocking(const PickRay& ray); + Q_INVOKABLE void setLightsArePickable(bool value); + Q_INVOKABLE bool getLightsArePickable() const; Q_INVOKABLE void dumpTree() const; diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 6ac3c31939..d3d9e2da53 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -21,6 +21,7 @@ EntityTree::EntityTree(bool shouldReaverage) : Octree(shouldReaverage), _simulation(NULL) { _rootElement = createNewElement(); + _lightsArePickable = true; // assume they are by default } EntityTree::~EntityTree() { diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 5dccfd7709..eeb0182042 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -144,6 +144,8 @@ public: void emitEntityScriptChanging(const EntityItemID& entityItemID); + bool getLightsArePickable() const { return _lightsArePickable; } + void setLightsArePickable(bool value) { _lightsArePickable = value; } void setSimulation(EntitySimulation* simulation); signals: @@ -169,6 +171,8 @@ private: EntityItemFBXService* _fbxService; QHash _entityToElementMap; + + bool _lightsArePickable; EntitySimulation* _simulation; }; diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index f0eeb40ede..e18f79276e 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -511,10 +511,28 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con // and testing intersection there. if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, localFace)) { if (localDistance < distance) { - distance = localDistance; - face = localFace; - *intersectedObject = (void*)entity; - somethingIntersected = true; + // now ask the entity if we actually intersect + if (entity->supportsDetailedRayIntersection()) { + + if (entity->findDetailedRayIntersection(origin, direction, keepSearching, element, localDistance, + localFace, intersectedObject)) { + + if (localDistance < distance) { + distance = localDistance; + face = localFace; + *intersectedObject = (void*)entity; + somethingIntersected = true; + } + } + } else { + // if the entity type doesn't support a detailed intersection, then just return the non-AABox results + if (localDistance < distance) { + distance = localDistance; + face = localFace; + *intersectedObject = (void*)entity; + somethingIntersected = true; + } + } } } } diff --git a/libraries/entities/src/SphereEntityItem.cpp b/libraries/entities/src/SphereEntityItem.cpp index f5b8eb27e9..12fdd7a8c4 100644 --- a/libraries/entities/src/SphereEntityItem.cpp +++ b/libraries/entities/src/SphereEntityItem.cpp @@ -93,3 +93,26 @@ void SphereEntityItem::recalculateCollisionShape() { float largestDiameter = glm::max(dimensionsInMeters.x, dimensionsInMeters.y, dimensionsInMeters.z); _sphereShape.setRadius(largestDiameter / 2.0f); } + +bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + // NOTE: origin and direction are in tree units. But our _sphereShape is in meters, so we need to + // do a little math to make these match each other. + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin * (float)TREE_SCALE; + rayInfo._rayDirection = direction; + + // TODO: Note this is really doing ray intersections against a sphere, which is fine except in cases + // where our dimensions actually make us an ellipsoid. But we'll live with this for now until we + // get a more full fledged physics library + if (_sphereShape.findRayIntersection(rayInfo)) { + distance = rayInfo._hitDistance / (float)TREE_SCALE; + return true; + } + return false; +} + + + diff --git a/libraries/entities/src/SphereEntityItem.h b/libraries/entities/src/SphereEntityItem.h index 21cb58223b..bb4f41726c 100644 --- a/libraries/entities/src/SphereEntityItem.h +++ b/libraries/entities/src/SphereEntityItem.h @@ -56,6 +56,11 @@ public: // TODO: implement proper contains for 3D ellipsoid //virtual bool contains(const glm::vec3& point) const; + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + protected: virtual void recalculateCollisionShape(); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 491240c178..17ef33ee1c 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -10,9 +10,12 @@ // +#include + #include #include +#include #include "EntityTree.h" #include "EntityTreeElement.h" @@ -110,4 +113,48 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, appendValue, getLineHeight()); APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, appendColor, getTextColor()); APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, appendColor, getBackgroundColor()); -} \ No newline at end of file +} + + +bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const { + + RayIntersectionInfo rayInfo; + rayInfo._rayStart = origin; + rayInfo._rayDirection = direction; + rayInfo._rayLength = std::numeric_limits::max(); + + PlaneShape plane; + + const glm::vec3 UNROTATED_NORMAL(0.0f, 0.0f, -1.0f); + glm::vec3 normal = _rotation * UNROTATED_NORMAL; + plane.setNormal(normal); + plane.setPoint(_position); // the position is definitely a point on our plane + + bool intersects = plane.findRayIntersection(rayInfo); + + if (intersects) { + glm::vec3 hitAt = origin + (direction * rayInfo._hitDistance); + // now we know the point the ray hit our plane + + glm::mat4 rotation = glm::mat4_cast(getRotation()); + glm::mat4 translation = glm::translate(getPosition()); + glm::mat4 entityToWorldMatrix = translation * rotation; + glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); + + glm::vec3 dimensions = getDimensions(); + glm::vec3 registrationPoint = getRegistrationPoint(); + glm::vec3 corner = -(dimensions * registrationPoint); + AABox entityFrameBox(corner, dimensions); + + glm::vec3 entityFrameHitAt = glm::vec3(worldToEntityMatrix * glm::vec4(hitAt, 1.0f)); + + intersects = entityFrameBox.contains(entityFrameHitAt); + } + + if (intersects) { + distance = rayInfo._hitDistance; + } + return intersects; +} diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 019d230c36..a3d323aefd 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -41,6 +41,11 @@ public: ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData); + virtual bool supportsDetailedRayIntersection() const { return true; } + virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, + bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face, + void** intersectedObject) const; + static const QString DEFAULT_TEXT; void setText(const QString& value) { _text = value; } const QString& getText() const { return _text; }