mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-06 17:58:36 +02:00
This wraps the selections rotation update handling into common helper function utilized by all rotation handle tools (yaw,pitch,roll). This function is the generalized fix previously exclusive to yawHandle. This functions is now called within onMove for yaw, pitch, & rollHandle tools. NOTE(s): * Tested yaw, pitch, & roll rotation didn't see any aberrant behavior. ** Tested overlapping shapes and selecting the overlapping portions followed by a rotation handle. Only one took hold as a selection. ** Tested multiple selection and objects rotated & repositioned about the encapsulating bounding box's center point as expected. * Tested translation with multiple items selected and it behaved as expected. Reviewed-by: Leander Hasty <leander@1stplayable.com> Changes Committed: modified: scripts/system/libraries/entitySelectionTool.js
4827 lines
157 KiB
JavaScript
4827 lines
157 KiB
JavaScript
//
|
|
// entitySelectionToolClass.js
|
|
// examples
|
|
//
|
|
// Created by Brad hefta-Gaub on 10/1/14.
|
|
// Modified by Daniela Fontes @DanielaFifo and Tiago Andrade @TagoWill on 4/7/2017
|
|
// Copyright 2014 High Fidelity, Inc.
|
|
//
|
|
// This script implements a class useful for building tools for editing entities.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
/* global HIFI_PUBLIC_BUCKET, SPACE_LOCAL, Script, SelectionManager */
|
|
|
|
HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/";
|
|
|
|
SPACE_LOCAL = "local";
|
|
SPACE_WORLD = "world";
|
|
|
|
Script.include("./controllers.js");
|
|
|
|
function objectTranslationPlanePoint(position, dimensions) {
|
|
var newPosition = { x: position.x, y: position.y, z: position.z };
|
|
newPosition.y -= dimensions.y / 2.0;
|
|
return newPosition;
|
|
}
|
|
|
|
SelectionManager = (function() {
|
|
var that = {};
|
|
|
|
// FUNCTION: SUBSCRIBE TO UPDATE MESSAGES
|
|
function subscribeToUpdateMessages() {
|
|
Messages.subscribe("entityToolUpdates");
|
|
Messages.messageReceived.connect(handleEntitySelectionToolUpdates);
|
|
}
|
|
|
|
// FUNCTION: HANDLE ENTITY SELECTION TOOL UDPATES
|
|
function handleEntitySelectionToolUpdates(channel, message, sender) {
|
|
if (channel !== 'entityToolUpdates') {
|
|
return;
|
|
}
|
|
if (sender !== MyAvatar.sessionUUID) {
|
|
return;
|
|
}
|
|
|
|
var messageParsed;
|
|
try {
|
|
messageParsed = JSON.parse(message);
|
|
} catch (err) {
|
|
print("error -- entitySelectionTool got malformed message: " + message);
|
|
}
|
|
|
|
// if (message === 'callUpdate') {
|
|
// that._update();
|
|
// }
|
|
|
|
if (messageParsed.method === "selectEntity") {
|
|
print("setting selection to " + messageParsed.entityID);
|
|
that.setSelections([messageParsed.entityID]);
|
|
}
|
|
}
|
|
|
|
subscribeToUpdateMessages();
|
|
|
|
that.savedProperties = {};
|
|
that.selections = [];
|
|
var listeners = [];
|
|
|
|
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() {
|
|
that.savedProperties = {};
|
|
for (var i = 0; i < that.selections.length; i++) {
|
|
var entityID = that.selections[i];
|
|
that.savedProperties[entityID] = Entities.getEntityProperties(entityID);
|
|
}
|
|
};
|
|
|
|
that.addEventListener = function(func) {
|
|
listeners.push(func);
|
|
};
|
|
|
|
that.hasSelection = function() {
|
|
return that.selections.length > 0;
|
|
};
|
|
|
|
that.setSelections = function(entityIDs) {
|
|
that.selections = [];
|
|
for (var i = 0; i < entityIDs.length; i++) {
|
|
var entityID = entityIDs[i];
|
|
that.selections.push(entityID);
|
|
}
|
|
|
|
that._update(true);
|
|
};
|
|
|
|
that.addEntity = function(entityID, toggleSelection) {
|
|
if (entityID) {
|
|
var idx = -1;
|
|
for (var i = 0; i < that.selections.length; i++) {
|
|
if (entityID == that.selections[i]) {
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
if (idx == -1) {
|
|
that.selections.push(entityID);
|
|
} else if (toggleSelection) {
|
|
that.selections.splice(idx, 1);
|
|
}
|
|
}
|
|
|
|
that._update(true);
|
|
};
|
|
|
|
that.removeEntity = function(entityID) {
|
|
var idx = that.selections.indexOf(entityID);
|
|
if (idx >= 0) {
|
|
that.selections.splice(idx, 1);
|
|
}
|
|
that._update(true);
|
|
};
|
|
|
|
that.clearSelections = function() {
|
|
that.selections = [];
|
|
that._update(true);
|
|
};
|
|
|
|
that._update = function(selectionUpdated) {
|
|
var properties = null;
|
|
if (that.selections.length === 0) {
|
|
that.localDimensions = null;
|
|
that.localPosition = null;
|
|
that.worldDimensions = null;
|
|
that.worldPosition = null;
|
|
} else if (that.selections.length == 1) {
|
|
properties = Entities.getEntityProperties(that.selections[0]);
|
|
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;
|
|
|
|
SelectionDisplay.setSpaceMode(SPACE_LOCAL);
|
|
} else {
|
|
that.localRotation = null;
|
|
that.localDimensions = null;
|
|
that.localPosition = null;
|
|
|
|
properties = Entities.getEntityProperties(that.selections[0]);
|
|
|
|
var brn = properties.boundingBox.brn;
|
|
var tfl = properties.boundingBox.tfl;
|
|
|
|
for (var i = 1; i < that.selections.length; i++) {
|
|
properties = Entities.getEntityProperties(that.selections[i]);
|
|
var bb = properties.boundingBox;
|
|
brn.x = Math.min(bb.brn.x, brn.x);
|
|
brn.y = Math.min(bb.brn.y, brn.y);
|
|
brn.z = Math.min(bb.brn.z, brn.z);
|
|
tfl.x = Math.max(bb.tfl.x, tfl.x);
|
|
tfl.y = Math.max(bb.tfl.y, tfl.y);
|
|
tfl.z = Math.max(bb.tfl.z, tfl.z);
|
|
}
|
|
|
|
that.localDimensions = null;
|
|
that.localPosition = null;
|
|
that.worldDimensions = {
|
|
x: tfl.x - brn.x,
|
|
y: tfl.y - brn.y,
|
|
z: tfl.z - brn.z
|
|
};
|
|
that.worldPosition = {
|
|
x: brn.x + (that.worldDimensions.x / 2),
|
|
y: brn.y + (that.worldDimensions.y / 2),
|
|
z: brn.z + (that.worldDimensions.z / 2),
|
|
};
|
|
|
|
// For 1+ selections we can only modify selections in world space
|
|
SelectionDisplay.setSpaceMode(SPACE_WORLD);
|
|
}
|
|
|
|
for (var j = 0; j < listeners.length; j++) {
|
|
try {
|
|
listeners[j](selectionUpdated === true);
|
|
} catch (e) {
|
|
print("EntitySelectionTool got exception: " + JSON.stringify(e));
|
|
}
|
|
}
|
|
};
|
|
|
|
return that;
|
|
})();
|
|
|
|
// Normalize degrees to be in the range (-180, 180]
|
|
function normalizeDegrees(degrees) {
|
|
while (degrees > 180) degrees -= 360;
|
|
while (degrees <= -180) degrees += 360;
|
|
return degrees;
|
|
}
|
|
|
|
// FUNCTION: getRelativeCenterPosition
|
|
// 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)
|
|
};
|
|
}
|
|
|
|
// SELECTION DISPLAY DEFINITION
|
|
SelectionDisplay = (function() {
|
|
var that = {};
|
|
|
|
var MINIMUM_DIMENSION = 0.001;
|
|
|
|
var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.0075;
|
|
|
|
// These are multipliers for sizing the rotation degrees display while rotating an entity
|
|
var ROTATION_DISPLAY_DISTANCE_MULTIPLIER = 1.2;
|
|
var ROTATION_DISPLAY_SIZE_X_MULTIPLIER = 0.6;
|
|
var ROTATION_DISPLAY_SIZE_Y_MULTIPLIER = 0.18;
|
|
var ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER = 0.14;
|
|
|
|
var ROTATE_ARROW_WEST_NORTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-north.svg";
|
|
var ROTATE_ARROW_WEST_SOUTH_URL = HIFI_PUBLIC_BUCKET + "images/rotate-arrow-west-south.svg";
|
|
|
|
var showExtendedStretchHandles = false;
|
|
|
|
var spaceMode = SPACE_LOCAL;
|
|
var mode = "UNKNOWN";
|
|
var overlayNames = [];
|
|
var lastCameraPosition = Camera.getPosition();
|
|
var lastCameraOrientation = Camera.getOrientation();
|
|
var lastControllerPoses = [
|
|
getControllerWorldLocation(Controller.Standard.LeftHand, true),
|
|
getControllerWorldLocation(Controller.Standard.RightHand, true)
|
|
];
|
|
|
|
var handleHoverColor = {
|
|
red: 224,
|
|
green: 67,
|
|
blue: 36
|
|
};
|
|
var handleHoverAlpha = 1.0;
|
|
|
|
var rotateOverlayTargetSize = 10000; // really big target
|
|
var innerSnapAngle = 22.5; // the angle which we snap to on the inner rotation tool
|
|
var innerRadius;
|
|
var outerRadius;
|
|
var yawHandleRotation;
|
|
var pitchHandleRotation;
|
|
var rollHandleRotation;
|
|
var yawCenter;
|
|
var pitchCenter;
|
|
var rollCenter;
|
|
var yawZero;
|
|
var pitchZero;
|
|
var rollZero;
|
|
var yawNormal;
|
|
var pitchNormal;
|
|
var rollNormal;
|
|
var rotationNormal;
|
|
|
|
var originalRotation;
|
|
var originalPitch;
|
|
var originalYaw;
|
|
var originalRoll;
|
|
|
|
|
|
var handleColor = {
|
|
red: 255,
|
|
green: 255,
|
|
blue: 255
|
|
};
|
|
var handleAlpha = 0.7;
|
|
|
|
var highlightedHandleColor = {
|
|
red: 183,
|
|
green: 64,
|
|
blue: 44
|
|
};
|
|
var highlightedHandleAlpha = 0.9;
|
|
|
|
var previousHandle = false;
|
|
var previousHandleColor;
|
|
var previousHandleAlpha;
|
|
|
|
var grabberSizeCorner = 0.025; // These get resized by updateHandleSizes().
|
|
var grabberSizeEdge = 0.015;
|
|
var grabberSizeFace = 0.025;
|
|
var grabberAlpha = 1;
|
|
var grabberColorCorner = {
|
|
red: 120,
|
|
green: 120,
|
|
blue: 120
|
|
};
|
|
var grabberColorEdge = {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
};
|
|
var grabberColorFace = {
|
|
red: 120,
|
|
green: 120,
|
|
blue: 120
|
|
};
|
|
var grabberColorCloner = {
|
|
red: 0,
|
|
green: 155,
|
|
blue: 0
|
|
};
|
|
var grabberLineWidth = 0.5;
|
|
var grabberSolid = true;
|
|
var grabberMoveUpPosition = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
|
|
var lightOverlayColor = {
|
|
red: 255,
|
|
green: 153,
|
|
blue: 0
|
|
};
|
|
|
|
var grabberPropertiesCorner = {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: grabberSizeCorner,
|
|
color: grabberColorCorner,
|
|
alpha: 1,
|
|
solid: grabberSolid,
|
|
visible: false,
|
|
dashed: false,
|
|
lineWidth: grabberLineWidth,
|
|
drawInFront: true,
|
|
borderSize: 1.4,
|
|
};
|
|
|
|
var grabberPropertiesEdge = {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: grabberSizeEdge,
|
|
color: grabberColorEdge,
|
|
alpha: 1,
|
|
solid: grabberSolid,
|
|
visible: false,
|
|
dashed: false,
|
|
lineWidth: grabberLineWidth,
|
|
drawInFront: true,
|
|
borderSize: 1.4,
|
|
};
|
|
|
|
var grabberPropertiesFace = {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: grabberSizeFace,
|
|
color: grabberColorFace,
|
|
alpha: 1,
|
|
solid: grabberSolid,
|
|
visible: false,
|
|
dashed: false,
|
|
lineWidth: grabberLineWidth,
|
|
drawInFront: true,
|
|
borderSize: 1.4,
|
|
};
|
|
|
|
var grabberPropertiesCloner = {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: grabberSizeCorner,
|
|
color: grabberColorCloner,
|
|
alpha: 1,
|
|
solid: grabberSolid,
|
|
visible: false,
|
|
dashed: false,
|
|
lineWidth: grabberLineWidth,
|
|
drawInFront: true,
|
|
borderSize: 1.4,
|
|
};
|
|
|
|
var spotLightLineProperties = {
|
|
color: lightOverlayColor,
|
|
lineWidth: 1.5,
|
|
};
|
|
|
|
var highlightBox = Overlays.addOverlay("cube", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: 1,
|
|
color: {
|
|
red: 90,
|
|
green: 90,
|
|
blue: 90
|
|
},
|
|
alpha: 1,
|
|
solid: false,
|
|
visible: false,
|
|
dashed: true,
|
|
lineWidth: 2.0,
|
|
ignoreRayIntersection: true, // this never ray intersects
|
|
drawInFront: true
|
|
});
|
|
|
|
var selectionBox = Overlays.addOverlay("cube", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: 1,
|
|
color: {
|
|
red: 255,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
alpha: 1,
|
|
solid: false,
|
|
visible: false,
|
|
dashed: false,
|
|
lineWidth: 1.0,
|
|
});
|
|
|
|
var selectionBoxes = [];
|
|
|
|
var rotationDegreesDisplay = Overlays.addOverlay("text3d", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
text: "",
|
|
color: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
backgroundColor: {
|
|
red: 255,
|
|
green: 255,
|
|
blue: 255
|
|
},
|
|
alpha: 0.7,
|
|
backgroundAlpha: 0.7,
|
|
visible: false,
|
|
isFacingAvatar: true,
|
|
drawInFront: true,
|
|
ignoreRayIntersection: true,
|
|
dimensions: {
|
|
x: 0,
|
|
y: 0
|
|
},
|
|
lineHeight: 0.0,
|
|
topMargin: 0,
|
|
rightMargin: 0,
|
|
bottomMargin: 0,
|
|
leftMargin: 0,
|
|
});
|
|
|
|
var grabberMoveUp = Overlays.addOverlay("image3d", {
|
|
url: HIFI_PUBLIC_BUCKET + "images/up-arrow.svg",
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: handleColor,
|
|
alpha: handleAlpha,
|
|
visible: false,
|
|
size: 0.1,
|
|
scale: 0.1,
|
|
isFacingAvatar: true,
|
|
drawInFront: true,
|
|
});
|
|
|
|
// var normalLine = Overlays.addOverlay("line3d", {
|
|
// visible: true,
|
|
// lineWidth: 2.0,
|
|
// start: { x: 0, y: 0, z: 0 },
|
|
// end: { x: 0, y: 0, z: 0 },
|
|
// color: { red: 255, green: 255, blue: 0 },
|
|
// ignoreRayIntersection: true,
|
|
// });
|
|
|
|
var grabberLBN = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
var grabberRBN = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
var grabberLBF = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
var grabberRBF = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
var grabberLTN = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
var grabberRTN = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
var grabberLTF = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
var grabberRTF = Overlays.addOverlay("cube", grabberPropertiesCorner);
|
|
|
|
var grabberTOP = Overlays.addOverlay("cube", grabberPropertiesFace);
|
|
var grabberBOTTOM = Overlays.addOverlay("cube", grabberPropertiesFace);
|
|
var grabberLEFT = Overlays.addOverlay("cube", grabberPropertiesFace);
|
|
var grabberRIGHT = Overlays.addOverlay("cube", grabberPropertiesFace);
|
|
var grabberNEAR = Overlays.addOverlay("cube", grabberPropertiesFace);
|
|
var grabberFAR = Overlays.addOverlay("cube", grabberPropertiesFace);
|
|
|
|
var grabberEdgeTR = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeTL = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeTF = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeTN = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeBR = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeBL = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeBF = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeBN = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeNR = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeNL = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeFR = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberEdgeFL = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
|
|
var grabberSpotLightCircle = Overlays.addOverlay("circle3d", {
|
|
color: lightOverlayColor,
|
|
isSolid: false,
|
|
visible: false
|
|
});
|
|
var grabberSpotLightLineT = Overlays.addOverlay("line3d", spotLightLineProperties);
|
|
var grabberSpotLightLineB = Overlays.addOverlay("line3d", spotLightLineProperties);
|
|
var grabberSpotLightLineL = Overlays.addOverlay("line3d", spotLightLineProperties);
|
|
var grabberSpotLightLineR = Overlays.addOverlay("line3d", spotLightLineProperties);
|
|
|
|
var grabberSpotLightCenter = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberSpotLightRadius = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberSpotLightL = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberSpotLightR = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberSpotLightT = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberSpotLightB = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
|
|
var grabberPointLightCircleX = Overlays.addOverlay("circle3d", {
|
|
rotation: Quat.fromPitchYawRollDegrees(0, 90, 0),
|
|
color: lightOverlayColor,
|
|
isSolid: false,
|
|
visible: false
|
|
});
|
|
var grabberPointLightCircleY = Overlays.addOverlay("circle3d", {
|
|
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
|
color: lightOverlayColor,
|
|
isSolid: false,
|
|
visible: false
|
|
});
|
|
var grabberPointLightCircleZ = Overlays.addOverlay("circle3d", {
|
|
rotation: Quat.fromPitchYawRollDegrees(0, 0, 0),
|
|
color: lightOverlayColor,
|
|
isSolid: false,
|
|
visible: false
|
|
});
|
|
var grabberPointLightT = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberPointLightB = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberPointLightL = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberPointLightR = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberPointLightF = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
var grabberPointLightN = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
|
|
|
var grabberCloner = Overlays.addOverlay("cube", grabberPropertiesCloner);
|
|
|
|
var stretchHandles = [
|
|
grabberLBN,
|
|
grabberRBN,
|
|
grabberLBF,
|
|
grabberRBF,
|
|
grabberLTN,
|
|
grabberRTN,
|
|
grabberLTF,
|
|
grabberRTF,
|
|
grabberTOP,
|
|
grabberBOTTOM,
|
|
grabberLEFT,
|
|
grabberRIGHT,
|
|
grabberNEAR,
|
|
grabberFAR,
|
|
grabberEdgeTR,
|
|
grabberEdgeTL,
|
|
grabberEdgeTF,
|
|
grabberEdgeTN,
|
|
grabberEdgeBR,
|
|
grabberEdgeBL,
|
|
grabberEdgeBF,
|
|
grabberEdgeBN,
|
|
grabberEdgeNR,
|
|
grabberEdgeNL,
|
|
grabberEdgeFR,
|
|
grabberEdgeFL,
|
|
|
|
grabberSpotLightLineT,
|
|
grabberSpotLightLineB,
|
|
grabberSpotLightLineL,
|
|
grabberSpotLightLineR,
|
|
|
|
grabberSpotLightCenter,
|
|
grabberSpotLightRadius,
|
|
grabberSpotLightL,
|
|
grabberSpotLightR,
|
|
grabberSpotLightT,
|
|
grabberSpotLightB,
|
|
|
|
grabberPointLightT,
|
|
grabberPointLightB,
|
|
grabberPointLightL,
|
|
grabberPointLightR,
|
|
grabberPointLightF,
|
|
grabberPointLightN,
|
|
|
|
grabberCloner
|
|
];
|
|
|
|
|
|
var baseOverlayAngles = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
var baseOverlayRotation = Quat.fromVec3Degrees(baseOverlayAngles);
|
|
var baseOfEntityProjectionOverlay = Overlays.addOverlay("rectangle3d", {
|
|
position: {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: {
|
|
red: 51,
|
|
green: 152,
|
|
blue: 203
|
|
},
|
|
alpha: 0.5,
|
|
solid: true,
|
|
visible: false,
|
|
width: 300,
|
|
height: 200,
|
|
rotation: baseOverlayRotation,
|
|
ignoreRayIntersection: true, // always ignore this
|
|
});
|
|
|
|
var yawOverlayAngles = {
|
|
x: 90,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
var yawOverlayRotation = Quat.fromVec3Degrees(yawOverlayAngles);
|
|
var pitchOverlayAngles = {
|
|
x: 0,
|
|
y: 90,
|
|
z: 0
|
|
};
|
|
var pitchOverlayRotation = Quat.fromVec3Degrees(pitchOverlayAngles);
|
|
var rollOverlayAngles = {
|
|
x: 0,
|
|
y: 180,
|
|
z: 0
|
|
};
|
|
var rollOverlayRotation = Quat.fromVec3Degrees(rollOverlayAngles);
|
|
|
|
var xRailOverlay = Overlays.addOverlay("line3d", {
|
|
visible: false,
|
|
lineWidth: 1.0,
|
|
start: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
end: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: {
|
|
red: 255,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
ignoreRayIntersection: true // always ignore this
|
|
});
|
|
var yRailOverlay = Overlays.addOverlay("line3d", {
|
|
visible: false,
|
|
lineWidth: 1.0,
|
|
start: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
end: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: {
|
|
red: 0,
|
|
green: 255,
|
|
blue: 0
|
|
},
|
|
ignoreRayIntersection: true // always ignore this
|
|
});
|
|
var zRailOverlay = Overlays.addOverlay("line3d", {
|
|
visible: false,
|
|
lineWidth: 1.0,
|
|
start: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
end: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 255
|
|
},
|
|
ignoreRayIntersection: true // always ignore this
|
|
});
|
|
|
|
var rotateZeroOverlay = Overlays.addOverlay("line3d", {
|
|
visible: false,
|
|
lineWidth: 2.0,
|
|
start: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
end: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: {
|
|
red: 255,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
ignoreRayIntersection: true, // always ignore this
|
|
});
|
|
|
|
var rotateCurrentOverlay = Overlays.addOverlay("line3d", {
|
|
visible: false,
|
|
lineWidth: 2.0,
|
|
start: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
end: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 255
|
|
},
|
|
ignoreRayIntersection: true, // always ignore this
|
|
});
|
|
|
|
|
|
var rotateOverlayTarget = Overlays.addOverlay("circle3d", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: rotateOverlayTargetSize,
|
|
color: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
alpha: 0.0,
|
|
solid: true,
|
|
visible: false,
|
|
rotation: yawOverlayRotation,
|
|
});
|
|
|
|
var rotateOverlayInner = Overlays.addOverlay("circle3d", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: 1,
|
|
color: {
|
|
red: 51,
|
|
green: 152,
|
|
blue: 203
|
|
},
|
|
alpha: 0.2,
|
|
solid: true,
|
|
visible: false,
|
|
rotation: yawOverlayRotation,
|
|
hasTickMarks: true,
|
|
majorTickMarksAngle: innerSnapAngle,
|
|
minorTickMarksAngle: 0,
|
|
majorTickMarksLength: -0.25,
|
|
minorTickMarksLength: 0,
|
|
majorTickMarksColor: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
minorTickMarksColor: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
ignoreRayIntersection: true, // always ignore this
|
|
});
|
|
|
|
var rotateOverlayOuter = Overlays.addOverlay("circle3d", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: 1,
|
|
color: {
|
|
red: 51,
|
|
green: 152,
|
|
blue: 203
|
|
},
|
|
alpha: 0.2,
|
|
solid: true,
|
|
visible: false,
|
|
rotation: yawOverlayRotation,
|
|
|
|
hasTickMarks: true,
|
|
majorTickMarksAngle: 45.0,
|
|
minorTickMarksAngle: 5,
|
|
majorTickMarksLength: 0.25,
|
|
minorTickMarksLength: 0.1,
|
|
majorTickMarksColor: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
minorTickMarksColor: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
ignoreRayIntersection: true, // always ignore this
|
|
});
|
|
|
|
var rotateOverlayCurrent = Overlays.addOverlay("circle3d", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: 1,
|
|
color: {
|
|
red: 224,
|
|
green: 67,
|
|
blue: 36
|
|
},
|
|
alpha: 0.8,
|
|
solid: true,
|
|
visible: false,
|
|
rotation: yawOverlayRotation,
|
|
ignoreRayIntersection: true, // always ignore this
|
|
hasTickMarks: true,
|
|
majorTickMarksColor: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
minorTickMarksColor: {
|
|
red: 0,
|
|
green: 0,
|
|
blue: 0
|
|
},
|
|
});
|
|
|
|
var yawHandle = Overlays.addOverlay("image3d", {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL,
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: handleColor,
|
|
alpha: handleAlpha,
|
|
visible: false,
|
|
size: 0.1,
|
|
scale: 0.1,
|
|
isFacingAvatar: false,
|
|
drawInFront: true,
|
|
});
|
|
|
|
|
|
var pitchHandle = Overlays.addOverlay("image3d", {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL,
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: handleColor,
|
|
alpha: handleAlpha,
|
|
visible: false,
|
|
size: 0.1,
|
|
scale: 0.1,
|
|
isFacingAvatar: false,
|
|
drawInFront: true,
|
|
});
|
|
|
|
|
|
var rollHandle = Overlays.addOverlay("image3d", {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL,
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
color: handleColor,
|
|
alpha: handleAlpha,
|
|
visible: false,
|
|
size: 0.1,
|
|
scale: 0.1,
|
|
isFacingAvatar: false,
|
|
drawInFront: true,
|
|
});
|
|
|
|
var allOverlays = [
|
|
highlightBox,
|
|
selectionBox,
|
|
grabberMoveUp,
|
|
yawHandle,
|
|
pitchHandle,
|
|
rollHandle,
|
|
rotateOverlayTarget,
|
|
rotateOverlayInner,
|
|
rotateOverlayOuter,
|
|
rotateOverlayCurrent,
|
|
rotateZeroOverlay,
|
|
rotateCurrentOverlay,
|
|
rotationDegreesDisplay,
|
|
xRailOverlay,
|
|
yRailOverlay,
|
|
zRailOverlay,
|
|
baseOfEntityProjectionOverlay,
|
|
grabberSpotLightCircle,
|
|
grabberPointLightCircleX,
|
|
grabberPointLightCircleY,
|
|
grabberPointLightCircleZ,
|
|
|
|
].concat(stretchHandles);
|
|
|
|
overlayNames[highlightBox] = "highlightBox";
|
|
overlayNames[selectionBox] = "selectionBox";
|
|
overlayNames[baseOfEntityProjectionOverlay] = "baseOfEntityProjectionOverlay";
|
|
overlayNames[grabberMoveUp] = "grabberMoveUp";
|
|
overlayNames[grabberLBN] = "grabberLBN";
|
|
overlayNames[grabberLBF] = "grabberLBF";
|
|
overlayNames[grabberRBN] = "grabberRBN";
|
|
overlayNames[grabberRBF] = "grabberRBF";
|
|
overlayNames[grabberLTN] = "grabberLTN";
|
|
overlayNames[grabberLTF] = "grabberLTF";
|
|
overlayNames[grabberRTN] = "grabberRTN";
|
|
overlayNames[grabberRTF] = "grabberRTF";
|
|
|
|
overlayNames[grabberTOP] = "grabberTOP";
|
|
overlayNames[grabberBOTTOM] = "grabberBOTTOM";
|
|
overlayNames[grabberLEFT] = "grabberLEFT";
|
|
overlayNames[grabberRIGHT] = "grabberRIGHT";
|
|
overlayNames[grabberNEAR] = "grabberNEAR";
|
|
overlayNames[grabberFAR] = "grabberFAR";
|
|
|
|
overlayNames[grabberEdgeTR] = "grabberEdgeTR";
|
|
overlayNames[grabberEdgeTL] = "grabberEdgeTL";
|
|
overlayNames[grabberEdgeTF] = "grabberEdgeTF";
|
|
overlayNames[grabberEdgeTN] = "grabberEdgeTN";
|
|
overlayNames[grabberEdgeBR] = "grabberEdgeBR";
|
|
overlayNames[grabberEdgeBL] = "grabberEdgeBL";
|
|
overlayNames[grabberEdgeBF] = "grabberEdgeBF";
|
|
overlayNames[grabberEdgeBN] = "grabberEdgeBN";
|
|
overlayNames[grabberEdgeNR] = "grabberEdgeNR";
|
|
overlayNames[grabberEdgeNL] = "grabberEdgeNL";
|
|
overlayNames[grabberEdgeFR] = "grabberEdgeFR";
|
|
overlayNames[grabberEdgeFL] = "grabberEdgeFL";
|
|
|
|
overlayNames[yawHandle] = "yawHandle";
|
|
overlayNames[pitchHandle] = "pitchHandle";
|
|
overlayNames[rollHandle] = "rollHandle";
|
|
|
|
overlayNames[rotateOverlayTarget] = "rotateOverlayTarget";
|
|
overlayNames[rotateOverlayInner] = "rotateOverlayInner";
|
|
overlayNames[rotateOverlayOuter] = "rotateOverlayOuter";
|
|
overlayNames[rotateOverlayCurrent] = "rotateOverlayCurrent";
|
|
|
|
overlayNames[rotateZeroOverlay] = "rotateZeroOverlay";
|
|
overlayNames[rotateCurrentOverlay] = "rotateCurrentOverlay";
|
|
overlayNames[grabberCloner] = "grabberCloner";
|
|
var activeTool = null;
|
|
var grabberTools = {};
|
|
|
|
// We get mouseMoveEvents from the handControllers, via handControllerPointer.
|
|
// But we dont' get mousePressEvents.
|
|
that.triggerMapping = Controller.newMapping(Script.resolvePath('') + '-click');
|
|
Script.scriptEnding.connect(that.triggerMapping.disable);
|
|
that.TRIGGER_GRAB_VALUE = 0.85; // From handControllerGrab/Pointer.js. Should refactor.
|
|
that.TRIGGER_ON_VALUE = 0.4;
|
|
that.TRIGGER_OFF_VALUE = 0.15;
|
|
that.triggered = false;
|
|
var activeHand = Controller.Standard.RightHand;
|
|
function makeTriggerHandler(hand) {
|
|
return function (value) {
|
|
if (!that.triggered && (value > that.TRIGGER_GRAB_VALUE)) { // should we smooth?
|
|
that.triggered = true;
|
|
if (activeHand !== hand) {
|
|
// No switching while the other is already triggered, so no need to release.
|
|
activeHand = (activeHand === Controller.Standard.RightHand) ?
|
|
Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
|
}
|
|
if (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(Reticle.position)) {
|
|
return;
|
|
}
|
|
that.mousePressEvent({});
|
|
} else if (that.triggered && (value < that.TRIGGER_OFF_VALUE)) {
|
|
that.triggered = false;
|
|
that.mouseReleaseEvent({});
|
|
}
|
|
};
|
|
}
|
|
that.triggerMapping.from(Controller.Standard.RT).peek().to(makeTriggerHandler(Controller.Standard.RightHand));
|
|
that.triggerMapping.from(Controller.Standard.LT).peek().to(makeTriggerHandler(Controller.Standard.LeftHand));
|
|
|
|
|
|
function controllerComputePickRay() {
|
|
var controllerPose = getControllerWorldLocation(activeHand, true);
|
|
if (controllerPose.valid && that.triggered) {
|
|
var controllerPosition = controllerPose.translation;
|
|
// This gets point direction right, but if you want general quaternion it would be more complicated:
|
|
var controllerDirection = Quat.getUp(controllerPose.rotation);
|
|
return {origin: controllerPosition, direction: controllerDirection};
|
|
}
|
|
}
|
|
function generalComputePickRay(x, y) {
|
|
return controllerComputePickRay() || Camera.computePickRay(x, y);
|
|
}
|
|
function addGrabberTool(overlay, tool) {
|
|
grabberTools[overlay] = {
|
|
mode: tool.mode,
|
|
onBegin: tool.onBegin,
|
|
onMove: tool.onMove,
|
|
onEnd: tool.onEnd,
|
|
};
|
|
}
|
|
|
|
|
|
that.cleanup = function() {
|
|
for (var i = 0; i < allOverlays.length; i++) {
|
|
Overlays.deleteOverlay(allOverlays[i]);
|
|
}
|
|
for (var j = 0; j < selectionBoxes.length; j++) {
|
|
Overlays.deleteOverlay(selectionBoxes[j]);
|
|
}
|
|
};
|
|
|
|
that.highlightSelectable = function(entityID) {
|
|
var properties = Entities.getEntityProperties(entityID);
|
|
Overlays.editOverlay(highlightBox, {
|
|
visible: true,
|
|
position: properties.boundingBox.center,
|
|
dimensions: properties.dimensions,
|
|
rotation: properties.rotation
|
|
});
|
|
};
|
|
|
|
that.unhighlightSelectable = function(entityID) {
|
|
Overlays.editOverlay(highlightBox, {
|
|
visible: false
|
|
});
|
|
};
|
|
|
|
that.select = function(entityID, event) {
|
|
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
|
|
|
|
lastCameraPosition = Camera.getPosition();
|
|
lastCameraOrientation = Camera.getOrientation();
|
|
|
|
if (event !== false) {
|
|
pickRay = generalComputePickRay(event.x, event.y);
|
|
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("select() with EVENT...... ");
|
|
print(" event.y:" + event.y);
|
|
Vec3.print(" current position:", properties.position);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
Overlays.editOverlay(highlightBox, {
|
|
visible: false
|
|
});
|
|
|
|
that.updateHandles();
|
|
};
|
|
|
|
// FUNCTION: UPDATE ROTATION HANDLES
|
|
that.updateRotationHandles = function() {
|
|
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
|
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
|
var innerActive = false;
|
|
var innerAlpha = 0.2;
|
|
var outerAlpha = 0.2;
|
|
if (innerActive) {
|
|
innerAlpha = 0.5;
|
|
} else {
|
|
outerAlpha = 0.5;
|
|
}
|
|
|
|
var rotateHandleOffset = 0.05;
|
|
|
|
var top, far, left, bottom, near, right, boundsCenter, objectCenter, BLN, BRN, BLF, TLN, TRN, TLF, TRF;
|
|
|
|
var dimensions, rotation;
|
|
if (spaceMode == SPACE_LOCAL) {
|
|
rotation = SelectionManager.localRotation;
|
|
} else {
|
|
rotation = SelectionManager.worldRotation;
|
|
}
|
|
objectCenter = SelectionManager.worldPosition;
|
|
dimensions = SelectionManager.worldDimensions;
|
|
var position = objectCenter;
|
|
|
|
top = objectCenter.y + (dimensions.y / 2);
|
|
far = objectCenter.z + (dimensions.z / 2);
|
|
left = objectCenter.x + (dimensions.x / 2);
|
|
|
|
bottom = objectCenter.y - (dimensions.y / 2);
|
|
near = objectCenter.z - (dimensions.z / 2);
|
|
right = objectCenter.x - (dimensions.x / 2);
|
|
|
|
boundsCenter = objectCenter;
|
|
|
|
var yawCorner;
|
|
var pitchCorner;
|
|
var rollCorner;
|
|
|
|
// determine which bottom corner we are closest to
|
|
/*------------------------------
|
|
example:
|
|
|
|
BRF +--------+ BLF
|
|
| |
|
|
| |
|
|
BRN +--------+ BLN
|
|
|
|
*
|
|
|
|
------------------------------*/
|
|
|
|
var cameraPosition = Camera.getPosition();
|
|
if (cameraPosition.x > objectCenter.x) {
|
|
// must be BRF or BRN
|
|
if (cameraPosition.z < objectCenter.z) {
|
|
|
|
yawHandleRotation = Quat.fromVec3Degrees({
|
|
x: 270,
|
|
y: 90,
|
|
z: 0
|
|
});
|
|
pitchHandleRotation = Quat.fromVec3Degrees({
|
|
x: 0,
|
|
y: 90,
|
|
z: 0
|
|
});
|
|
rollHandleRotation = Quat.fromVec3Degrees({
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
});
|
|
|
|
yawNormal = {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
};
|
|
pitchNormal = {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
rollNormal = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
};
|
|
|
|
yawCorner = {
|
|
x: left + rotateHandleOffset,
|
|
y: bottom - rotateHandleOffset,
|
|
z: near - rotateHandleOffset
|
|
};
|
|
|
|
pitchCorner = {
|
|
x: right - rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: near - rotateHandleOffset
|
|
};
|
|
|
|
rollCorner = {
|
|
x: left + rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: far + rotateHandleOffset
|
|
};
|
|
|
|
yawCenter = {
|
|
x: boundsCenter.x,
|
|
y: bottom,
|
|
z: boundsCenter.z
|
|
};
|
|
pitchCenter = {
|
|
x: right,
|
|
y: boundsCenter.y,
|
|
z: boundsCenter.z
|
|
};
|
|
rollCenter = {
|
|
x: boundsCenter.x,
|
|
y: boundsCenter.y,
|
|
z: far
|
|
};
|
|
|
|
|
|
Overlays.editOverlay(pitchHandle, {
|
|
url: ROTATE_ARROW_WEST_SOUTH_URL
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
url: ROTATE_ARROW_WEST_SOUTH_URL
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
yawHandleRotation = Quat.fromVec3Degrees({
|
|
x: 270,
|
|
y: 0,
|
|
z: 0
|
|
});
|
|
pitchHandleRotation = Quat.fromVec3Degrees({
|
|
x: 180,
|
|
y: 270,
|
|
z: 0
|
|
});
|
|
rollHandleRotation = Quat.fromVec3Degrees({
|
|
x: 0,
|
|
y: 0,
|
|
z: 90
|
|
});
|
|
|
|
yawNormal = {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
};
|
|
pitchNormal = {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
rollNormal = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
};
|
|
|
|
|
|
yawCorner = {
|
|
x: left + rotateHandleOffset,
|
|
y: bottom - rotateHandleOffset,
|
|
z: far + rotateHandleOffset
|
|
};
|
|
|
|
pitchCorner = {
|
|
x: right - rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: far + rotateHandleOffset
|
|
};
|
|
|
|
rollCorner = {
|
|
x: left + rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: near - rotateHandleOffset
|
|
};
|
|
|
|
|
|
yawCenter = {
|
|
x: boundsCenter.x,
|
|
y: bottom,
|
|
z: boundsCenter.z
|
|
};
|
|
pitchCenter = {
|
|
x: right,
|
|
y: boundsCenter.y,
|
|
z: boundsCenter.z
|
|
};
|
|
rollCenter = {
|
|
x: boundsCenter.x,
|
|
y: boundsCenter.y,
|
|
z: near
|
|
};
|
|
|
|
Overlays.editOverlay(pitchHandle, {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL
|
|
});
|
|
}
|
|
} else {
|
|
|
|
// must be BLF or BLN
|
|
if (cameraPosition.z < objectCenter.z) {
|
|
|
|
yawHandleRotation = Quat.fromVec3Degrees({
|
|
x: 270,
|
|
y: 180,
|
|
z: 0
|
|
});
|
|
pitchHandleRotation = Quat.fromVec3Degrees({
|
|
x: 90,
|
|
y: 0,
|
|
z: 90
|
|
});
|
|
rollHandleRotation = Quat.fromVec3Degrees({
|
|
x: 0,
|
|
y: 0,
|
|
z: 180
|
|
});
|
|
|
|
yawNormal = {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
};
|
|
pitchNormal = {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
rollNormal = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
};
|
|
|
|
yawCorner = {
|
|
x: right - rotateHandleOffset,
|
|
y: bottom - rotateHandleOffset,
|
|
z: near - rotateHandleOffset
|
|
};
|
|
|
|
pitchCorner = {
|
|
x: left + rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: near - rotateHandleOffset
|
|
};
|
|
|
|
rollCorner = {
|
|
x: right - rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: far + rotateHandleOffset
|
|
};
|
|
|
|
yawCenter = {
|
|
x: boundsCenter.x,
|
|
y: bottom,
|
|
z: boundsCenter.z
|
|
};
|
|
pitchCenter = {
|
|
x: left,
|
|
y: boundsCenter.y,
|
|
z: boundsCenter.z
|
|
};
|
|
rollCenter = {
|
|
x: boundsCenter.x,
|
|
y: boundsCenter.y,
|
|
z: far
|
|
};
|
|
|
|
Overlays.editOverlay(pitchHandle, {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL
|
|
});
|
|
|
|
} else {
|
|
|
|
yawHandleRotation = Quat.fromVec3Degrees({
|
|
x: 270,
|
|
y: 270,
|
|
z: 0
|
|
});
|
|
pitchHandleRotation = Quat.fromVec3Degrees({
|
|
x: 180,
|
|
y: 270,
|
|
z: 0
|
|
});
|
|
rollHandleRotation = Quat.fromVec3Degrees({
|
|
x: 0,
|
|
y: 0,
|
|
z: 180
|
|
});
|
|
|
|
yawNormal = {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
};
|
|
rollNormal = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
};
|
|
pitchNormal = {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
|
|
yawCorner = {
|
|
x: right - rotateHandleOffset,
|
|
y: bottom - rotateHandleOffset,
|
|
z: far + rotateHandleOffset
|
|
};
|
|
|
|
rollCorner = {
|
|
x: right - rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: near - rotateHandleOffset
|
|
};
|
|
|
|
pitchCorner = {
|
|
x: left + rotateHandleOffset,
|
|
y: top + rotateHandleOffset,
|
|
z: far + rotateHandleOffset
|
|
};
|
|
|
|
yawCenter = {
|
|
x: boundsCenter.x,
|
|
y: bottom,
|
|
z: boundsCenter.z
|
|
};
|
|
rollCenter = {
|
|
x: boundsCenter.x,
|
|
y: boundsCenter.y,
|
|
z: near
|
|
};
|
|
pitchCenter = {
|
|
x: left,
|
|
y: boundsCenter.y,
|
|
z: boundsCenter.z
|
|
};
|
|
|
|
Overlays.editOverlay(pitchHandle, {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
url: ROTATE_ARROW_WEST_NORTH_URL
|
|
});
|
|
|
|
}
|
|
}
|
|
|
|
var rotateHandlesVisible = true;
|
|
var rotationOverlaysVisible = false;
|
|
var translateHandlesVisible = true;
|
|
var selectionBoxVisible = true;
|
|
var isPointLight = false;
|
|
|
|
if (selectionManager.selections.length == 1) {
|
|
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
|
|
isPointLight = properties.type == "Light" && !properties.isSpotlight;
|
|
}
|
|
|
|
if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL" || mode == "TRANSLATE_X in case they Z") {
|
|
rotationOverlaysVisible = true;
|
|
rotateHandlesVisible = false;
|
|
translateHandlesVisible = false;
|
|
selectionBoxVisible = false;
|
|
} else if (mode == "TRANSLATE_UP_DOWN" || isPointLight) {
|
|
rotateHandlesVisible = false;
|
|
} else if (mode != "UNKNOWN") {
|
|
// every other mode is a stretch mode...
|
|
rotateHandlesVisible = false;
|
|
translateHandlesVisible = false;
|
|
}
|
|
|
|
Overlays.editOverlay(rotateOverlayTarget, {
|
|
visible: rotationOverlaysVisible
|
|
});
|
|
Overlays.editOverlay(rotateZeroOverlay, {
|
|
visible: rotationOverlaysVisible
|
|
});
|
|
Overlays.editOverlay(rotateCurrentOverlay, {
|
|
visible: rotationOverlaysVisible
|
|
});
|
|
|
|
Overlays.editOverlay(yawHandle, {
|
|
visible: rotateHandlesVisible,
|
|
position: yawCorner,
|
|
rotation: yawHandleRotation
|
|
});
|
|
Overlays.editOverlay(pitchHandle, {
|
|
visible: rotateHandlesVisible,
|
|
position: pitchCorner,
|
|
rotation: pitchHandleRotation
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
visible: rotateHandlesVisible,
|
|
position: rollCorner,
|
|
rotation: rollHandleRotation
|
|
});
|
|
};
|
|
|
|
// FUNCTION: SET SPACE MODE
|
|
that.setSpaceMode = function(newSpaceMode) {
|
|
print("======> SetSpaceMode called. ========");
|
|
if (spaceMode != newSpaceMode) {
|
|
print(" Updating SpaceMode From: " + spaceMode + " To: " + newSpaceMode);
|
|
spaceMode = newSpaceMode;
|
|
that.updateHandles();
|
|
} else {
|
|
print(" Can't update SpaceMode. CurrentMode: " + spaceMode + " DesiredMode: " + newSpaceMode);
|
|
}
|
|
print("====== SetSpaceMode called. <========");
|
|
};
|
|
|
|
// FUNCTION: TOGGLE SPACE MODE
|
|
that.toggleSpaceMode = function() {
|
|
print("========> ToggleSpaceMode called. =========");
|
|
if (spaceMode == SPACE_WORLD && SelectionManager.selections.length > 1) {
|
|
print("Local space editing is not available with multiple selections");
|
|
return;
|
|
}
|
|
print( "PreToggle: " + spaceMode);
|
|
spaceMode = spaceMode == SPACE_LOCAL ? SPACE_WORLD : SPACE_LOCAL;
|
|
print( "PostToggle: " + spaceMode);
|
|
that.updateHandles();
|
|
print("======== ToggleSpaceMode called. <=========");
|
|
};
|
|
|
|
// FUNCTION: UNSELECT ALL
|
|
// TODO?: Needs implementation
|
|
that.unselectAll = function() {};
|
|
|
|
// FUNCTION: UPDATE HANDLES
|
|
that.updateHandles = function() {
|
|
print( "======> Update Handles =======" );
|
|
print( " Selections Count: " + SelectionManager.selections.length );
|
|
print( " SpaceMode: " + spaceMode );
|
|
if (SelectionManager.selections.length === 0) {
|
|
that.setOverlaysVisible(false);
|
|
return;
|
|
}
|
|
|
|
//print( " Triggering updateRotationHandles");
|
|
that.updateRotationHandles();
|
|
|
|
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 registrationPointDimensions = {
|
|
x: dimensions.x * registrationPoint.x,
|
|
y: dimensions.y * registrationPoint.y,
|
|
z: dimensions.z * registrationPoint.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 far = dimensions.z - registrationPointDimensions.z;
|
|
var front = far;
|
|
|
|
var worldTop = SelectionManager.worldDimensions.y / 2;
|
|
|
|
var LBN = {
|
|
x: left,
|
|
y: bottom,
|
|
z: near
|
|
};
|
|
var RBN = {
|
|
x: right,
|
|
y: bottom,
|
|
z: near
|
|
};
|
|
var LBF = {
|
|
x: left,
|
|
y: bottom,
|
|
z: far
|
|
};
|
|
var RBF = {
|
|
x: right,
|
|
y: bottom,
|
|
z: far
|
|
};
|
|
var LTN = {
|
|
x: left,
|
|
y: top,
|
|
z: near
|
|
};
|
|
var RTN = {
|
|
x: right,
|
|
y: top,
|
|
z: near
|
|
};
|
|
var LTF = {
|
|
x: left,
|
|
y: top,
|
|
z: far
|
|
};
|
|
var RTF = {
|
|
x: right,
|
|
y: top,
|
|
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: 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);
|
|
LBF = Vec3.multiplyQbyV(rotation, LBF);
|
|
RBF = Vec3.multiplyQbyV(rotation, RBF);
|
|
LTN = Vec3.multiplyQbyV(rotation, LTN);
|
|
RTN = Vec3.multiplyQbyV(rotation, RTN);
|
|
LTF = Vec3.multiplyQbyV(rotation, LTF);
|
|
RTF = Vec3.multiplyQbyV(rotation, RTF);
|
|
|
|
TOP = Vec3.multiplyQbyV(rotation, TOP);
|
|
BOTTOM = Vec3.multiplyQbyV(rotation, BOTTOM);
|
|
LEFT = Vec3.multiplyQbyV(rotation, LEFT);
|
|
RIGHT = Vec3.multiplyQbyV(rotation, RIGHT);
|
|
NEAR = Vec3.multiplyQbyV(rotation, NEAR);
|
|
FAR = Vec3.multiplyQbyV(rotation, FAR);
|
|
|
|
EdgeTR = Vec3.multiplyQbyV(rotation, EdgeTR);
|
|
EdgeTL = Vec3.multiplyQbyV(rotation, EdgeTL);
|
|
EdgeTF = Vec3.multiplyQbyV(rotation, EdgeTF);
|
|
EdgeTN = Vec3.multiplyQbyV(rotation, EdgeTN);
|
|
EdgeBR = Vec3.multiplyQbyV(rotation, EdgeBR);
|
|
EdgeBL = Vec3.multiplyQbyV(rotation, EdgeBL);
|
|
EdgeBF = Vec3.multiplyQbyV(rotation, EdgeBF);
|
|
EdgeBN = Vec3.multiplyQbyV(rotation, EdgeBN);
|
|
EdgeNR = Vec3.multiplyQbyV(rotation, EdgeNR);
|
|
EdgeNL = Vec3.multiplyQbyV(rotation, EdgeNL);
|
|
EdgeFR = Vec3.multiplyQbyV(rotation, EdgeFR);
|
|
EdgeFL = Vec3.multiplyQbyV(rotation, EdgeFL);
|
|
|
|
LBN = Vec3.sum(position, LBN);
|
|
RBN = Vec3.sum(position, RBN);
|
|
LBF = Vec3.sum(position, LBF);
|
|
RBF = Vec3.sum(position, RBF);
|
|
LTN = Vec3.sum(position, LTN);
|
|
RTN = Vec3.sum(position, RTN);
|
|
LTF = Vec3.sum(position, LTF);
|
|
RTF = Vec3.sum(position, RTF);
|
|
|
|
TOP = Vec3.sum(position, TOP);
|
|
BOTTOM = Vec3.sum(position, BOTTOM);
|
|
LEFT = Vec3.sum(position, LEFT);
|
|
RIGHT = Vec3.sum(position, RIGHT);
|
|
NEAR = Vec3.sum(position, NEAR);
|
|
FAR = Vec3.sum(position, FAR);
|
|
|
|
EdgeTR = Vec3.sum(position, EdgeTR);
|
|
EdgeTL = Vec3.sum(position, EdgeTL);
|
|
EdgeTF = Vec3.sum(position, EdgeTF);
|
|
EdgeTN = Vec3.sum(position, EdgeTN);
|
|
EdgeBR = Vec3.sum(position, EdgeBR);
|
|
EdgeBL = Vec3.sum(position, EdgeBL);
|
|
EdgeBF = Vec3.sum(position, EdgeBF);
|
|
EdgeBN = Vec3.sum(position, EdgeBN);
|
|
EdgeNR = Vec3.sum(position, EdgeNR);
|
|
EdgeNL = Vec3.sum(position, EdgeNL);
|
|
EdgeFR = Vec3.sum(position, EdgeFR);
|
|
EdgeFL = Vec3.sum(position, EdgeFL);
|
|
|
|
var inModeRotate = (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL");
|
|
var stretchHandlesVisible = !inModeRotate && (spaceMode == SPACE_LOCAL);
|
|
var extendedStretchHandlesVisible = (stretchHandlesVisible && showExtendedStretchHandles);
|
|
var cloneHandleVisible = !inModeRotate;
|
|
//print(" Set Non-Light Grabbers Visible - Norm: " + stretchHandlesVisible + " Ext: " + extendedStretchHandlesVisible);
|
|
var isSingleSelection = (selectionManager.selections.length == 1);
|
|
|
|
if (isSingleSelection) {
|
|
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
|
|
var isLightSelection = (properties.type == "Light");
|
|
if ( isLightSelection ) {
|
|
//print(" Light Selection revoking Non-Light Grabbers Visibility!");
|
|
stretchHandlesVisible = false;
|
|
extendedStretchHandlesVisible = false;
|
|
cloneHandleVisible = false;
|
|
if(properties.isSpotlight) {
|
|
//print(" Trying to show all SpotLight related grabbers");
|
|
Overlays.editOverlay(grabberSpotLightCenter, {
|
|
position: position,
|
|
visible: false,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightRadius, {
|
|
position: NEAR,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
var distance = (properties.dimensions.z / 2) * Math.sin(properties.cutoff * (Math.PI / 180));
|
|
|
|
Overlays.editOverlay(grabberSpotLightL, {
|
|
position: EdgeNL,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightR, {
|
|
position: EdgeNR,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightT, {
|
|
position: EdgeTN,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightB, {
|
|
position: EdgeBN,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightCircle, {
|
|
position: NEAR,
|
|
dimensions: {
|
|
x: distance,
|
|
y: distance,
|
|
z: 1
|
|
},
|
|
lineWidth: 1.5,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
|
|
Overlays.editOverlay(grabberSpotLightLineT, {
|
|
start: position,
|
|
end: EdgeTN,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineB, {
|
|
start: position,
|
|
end: EdgeBN,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineR, {
|
|
start: position,
|
|
end: EdgeNR,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineL, {
|
|
start: position,
|
|
end: EdgeNL,
|
|
visible: true,
|
|
});
|
|
|
|
//print(" Trying to hide all PointLight related grabbers");
|
|
Overlays.editOverlay(grabberPointLightCircleX, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightCircleY, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightCircleZ, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightB, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightF, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightN, {
|
|
visible: false
|
|
});
|
|
} else { //..it's a PointLight
|
|
//print(" Trying to show all PointLight related grabbers");
|
|
Overlays.editOverlay(grabberPointLightT, {
|
|
position: TOP,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightB, {
|
|
position: BOTTOM,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightL, {
|
|
position: LEFT,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightR, {
|
|
position: RIGHT,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightF, {
|
|
position: FAR,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightN, {
|
|
position: NEAR,
|
|
rotation: rotation,
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightCircleX, {
|
|
position: position,
|
|
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(0, 90, 0)),
|
|
dimensions: {
|
|
x: properties.dimensions.z / 2.0,
|
|
y: properties.dimensions.z / 2.0,
|
|
z: 1
|
|
},
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightCircleY, {
|
|
position: position,
|
|
rotation: Quat.multiply(rotation, Quat.fromPitchYawRollDegrees(90, 0, 0)),
|
|
dimensions: {
|
|
x: properties.dimensions.z / 2.0,
|
|
y: properties.dimensions.z / 2.0,
|
|
z: 1
|
|
},
|
|
visible: true,
|
|
});
|
|
Overlays.editOverlay(grabberPointLightCircleZ, {
|
|
position: position,
|
|
rotation: rotation,
|
|
dimensions: {
|
|
x: properties.dimensions.z / 2.0,
|
|
y: properties.dimensions.z / 2.0,
|
|
z: 1
|
|
},
|
|
visible: true,
|
|
});
|
|
|
|
//print(" Trying to hide all SpotLight related grabbers");
|
|
Overlays.editOverlay(grabberSpotLightRadius, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightB, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightCircle, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineB, {
|
|
visible: false
|
|
});
|
|
}
|
|
} else { //..it's not a light at all
|
|
//print(" Trying to hide all Light related grabbers");
|
|
Overlays.editOverlay(grabberSpotLightCenter, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightRadius, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightB, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightCircle, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberSpotLightLineB, {
|
|
visible: false
|
|
});
|
|
|
|
Overlays.editOverlay(grabberPointLightCircleX, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightCircleY, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightCircleZ, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightB, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightF, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberPointLightN, {
|
|
visible: false
|
|
});
|
|
}
|
|
}//--end of isSingleSelection
|
|
|
|
|
|
|
|
Overlays.editOverlay(grabberLBN, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: LBN
|
|
});
|
|
Overlays.editOverlay(grabberRBN, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: RBN
|
|
});
|
|
Overlays.editOverlay(grabberLBF, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: LBF
|
|
});
|
|
Overlays.editOverlay(grabberRBF, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: RBF
|
|
});
|
|
|
|
Overlays.editOverlay(grabberLTN, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: LTN
|
|
});
|
|
Overlays.editOverlay(grabberRTN, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: RTN
|
|
});
|
|
Overlays.editOverlay(grabberLTF, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: LTF
|
|
});
|
|
Overlays.editOverlay(grabberRTF, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: RTF
|
|
});
|
|
|
|
Overlays.editOverlay(grabberTOP, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: TOP
|
|
});
|
|
Overlays.editOverlay(grabberBOTTOM, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: BOTTOM
|
|
});
|
|
Overlays.editOverlay(grabberLEFT, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: LEFT
|
|
});
|
|
Overlays.editOverlay(grabberRIGHT, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: RIGHT
|
|
});
|
|
Overlays.editOverlay(grabberNEAR, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: NEAR
|
|
});
|
|
Overlays.editOverlay(grabberFAR, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: FAR
|
|
});
|
|
|
|
Overlays.editOverlay(grabberCloner, {
|
|
visible: cloneHandleVisible,
|
|
rotation: rotation,
|
|
position: EdgeTR
|
|
});
|
|
|
|
var selectionBoxPosition = Vec3.multiplyQbyV(rotation, center);
|
|
selectionBoxPosition = Vec3.sum(position, selectionBoxPosition);
|
|
Overlays.editOverlay(selectionBox, {
|
|
position: selectionBoxPosition,
|
|
dimensions: dimensions,
|
|
rotation: rotation,
|
|
visible: !inModeRotate,
|
|
});
|
|
|
|
// Create more selection box overlays if we don't have enough
|
|
var overlaysNeeded = selectionManager.selections.length - selectionBoxes.length;
|
|
for (var i = 0; i < overlaysNeeded; i++) {
|
|
selectionBoxes.push(
|
|
Overlays.addOverlay("cube", {
|
|
position: {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
},
|
|
size: 1,
|
|
color: {
|
|
red: 255,
|
|
green: 153,
|
|
blue: 0
|
|
},
|
|
alpha: 1,
|
|
solid: false,
|
|
visible: false,
|
|
dashed: false,
|
|
lineWidth: 1.0,
|
|
ignoreRayIntersection: true,
|
|
}));
|
|
}
|
|
|
|
i = 0;
|
|
// Only show individual selections boxes if there is more than 1 selection
|
|
if (selectionManager.selections.length > 1) {
|
|
for (; i < selectionManager.selections.length; i++) {
|
|
var props = 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(props.registrationPoint, {
|
|
x: 0.5,
|
|
y: 0.5,
|
|
z: 0.5
|
|
});
|
|
var offset = vec3Mult(props.dimensions, centeredRP);
|
|
offset = Vec3.multiply(-1, offset);
|
|
offset = Vec3.multiplyQbyV(props.rotation, offset);
|
|
var curBoxPosition = Vec3.sum(props.position, offset);
|
|
|
|
var color = {red: 255, green: 128, blue: 0};
|
|
if (i >= selectionManager.selections.length - 1) color = {red: 255, green: 255, blue: 64};
|
|
|
|
Overlays.editOverlay(selectionBoxes[i], {
|
|
position: curBoxPosition,
|
|
color: color,
|
|
rotation: props.rotation,
|
|
dimensions: props.dimensions,
|
|
visible: true,
|
|
});
|
|
}
|
|
}
|
|
// Hide any remaining selection boxes
|
|
for (; i < selectionBoxes.length; i++) {
|
|
Overlays.editOverlay(selectionBoxes[i], {
|
|
visible: false
|
|
});
|
|
}
|
|
|
|
Overlays.editOverlay(grabberEdgeTR, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeTR
|
|
});
|
|
Overlays.editOverlay(grabberEdgeTL, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeTL
|
|
});
|
|
Overlays.editOverlay(grabberEdgeTF, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeTF
|
|
});
|
|
Overlays.editOverlay(grabberEdgeTN, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeTN
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBR, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeBR
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBL, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeBL
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBF, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeBF
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBN, {
|
|
visible: stretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeBN
|
|
});
|
|
Overlays.editOverlay(grabberEdgeNR, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeNR
|
|
});
|
|
Overlays.editOverlay(grabberEdgeNL, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeNL
|
|
});
|
|
Overlays.editOverlay(grabberEdgeFR, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeFR
|
|
});
|
|
Overlays.editOverlay(grabberEdgeFL, {
|
|
visible: extendedStretchHandlesVisible,
|
|
rotation: rotation,
|
|
position: EdgeFL
|
|
});
|
|
|
|
var grabberMoveUpOffset = 0.1;
|
|
grabberMoveUpPosition = {
|
|
x: position.x,
|
|
y: position.y + worldTop + grabberMoveUpOffset,
|
|
z: position.z
|
|
};
|
|
Overlays.editOverlay(grabberMoveUp, {
|
|
visible: (activeTool === null) || (mode == "TRANSLATE_UP_DOWN")
|
|
});
|
|
|
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, {
|
|
visible: !inModeRotate,
|
|
solid: true,
|
|
position: {
|
|
x: selectionManager.worldPosition.x,
|
|
y: grid.getOrigin().y,
|
|
z: selectionManager.worldPosition.z
|
|
},
|
|
dimensions: {
|
|
x: selectionManager.worldDimensions.x,
|
|
y: selectionManager.worldDimensions.z
|
|
},
|
|
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
|
});
|
|
|
|
print( "====== Update Handles <=======" );
|
|
|
|
};
|
|
|
|
// FUNCTION: SET OVERLAYS VISIBLE
|
|
that.setOverlaysVisible = function(isVisible) {
|
|
var length = allOverlays.length;
|
|
for (var overlayIndex = 0; overlayIndex < length; overlayIndex++) {
|
|
Overlays.editOverlay(allOverlays[overlayIndex], {
|
|
visible: isVisible
|
|
});
|
|
}
|
|
length = selectionBoxes.length;
|
|
for (var boxIndex = 0; boxIndex < length; boxIndex++) {
|
|
Overlays.editOverlay(selectionBoxes[boxIndex], {
|
|
visible: isVisible
|
|
});
|
|
}
|
|
};
|
|
|
|
// FUNCTION: UNSELECT
|
|
// TODO?: Needs implementation
|
|
that.unselect = function(entityID) {};
|
|
|
|
var initialXZPick = null;
|
|
var isConstrained = false;
|
|
var constrainMajorOnly = false;
|
|
var startPosition = null;
|
|
var duplicatedEntityIDs = null;
|
|
|
|
// TOOL DEFINITION: TRANSLATE XZ TOOL
|
|
var translateXZTool = {
|
|
mode: 'TRANSLATE_XZ',
|
|
pickPlanePosition: { x: 0, y: 0, z: 0 },
|
|
greatestDimension: 0.0,
|
|
startingDistance: 0.0,
|
|
startingElevation: 0.0,
|
|
onBegin: function(event,isAltFromGrab, intersectInfo) {
|
|
var wantDebug = false;
|
|
if(wantDebug){
|
|
print("================== TRANSLATE_XZ(Beg) -> =======================");
|
|
Vec3.print(" intersectInfo.queryRay", intersectInfo.queryRay);
|
|
Vec3.print(" intersectInfo.queryRay.origin", intersectInfo.queryRay.origin);
|
|
Vec3.print(" intersectInfo.results.intersection", intersectInfo.results.intersection);
|
|
}
|
|
|
|
SelectionManager.saveProperties();
|
|
startPosition = SelectionManager.worldPosition;
|
|
mode = translateXZTool.mode;
|
|
|
|
translateXZTool.pickPlanePosition = intersectInfo.results.intersection;
|
|
translateXZTool.greatestDimension = Math.max(Math.max(SelectionManager.worldDimensions.x, SelectionManager.worldDimensions.y), SelectionManager.worldDimensions.z);
|
|
translateXZTool.startingDistance = Vec3.distance(intersectInfo.queryRay.origin, SelectionManager.position);
|
|
translateXZTool.startingElevation = translateXZTool.elevation(intersectInfo.queryRay.origin, translateXZTool.pickPlanePosition);
|
|
if (wantDebug) {
|
|
print(" longest dimension: " + translateXZTool.greatestDimension);
|
|
print(" starting distance: " + translateXZTool.startingDistance);
|
|
print(" starting elevation: " + translateXZTool.startingElevation);
|
|
}
|
|
|
|
initialXZPick = rayPlaneIntersection(intersectInfo.queryRay, translateXZTool.pickPlanePosition, {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
});
|
|
|
|
// Duplicate entities if alt is pressed. This will make a
|
|
// copy of the selected entities and move the _original_ entities, not
|
|
// the new ones.
|
|
if (event.isAlt || isAltFromGrab) {
|
|
duplicatedEntityIDs = [];
|
|
for (var otherEntityID in SelectionManager.savedProperties) {
|
|
var properties = SelectionManager.savedProperties[otherEntityID];
|
|
if (!properties.locked) {
|
|
var entityID = Entities.addEntity(properties);
|
|
duplicatedEntityIDs.push({
|
|
entityID: entityID,
|
|
properties: properties,
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
duplicatedEntityIDs = null;
|
|
}
|
|
|
|
isConstrained = false;
|
|
if(wantDebug){
|
|
print("================== TRANSLATE_XZ(End) <- =======================");
|
|
}
|
|
},
|
|
onEnd: function(event, reason) {
|
|
pushCommandForSelections(duplicatedEntityIDs);
|
|
|
|
Overlays.editOverlay(xRailOverlay, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(zRailOverlay, {
|
|
visible: false
|
|
});
|
|
},
|
|
elevation: function(origin, intersection) {
|
|
return (origin.y - intersection.y) / Vec3.distance(origin, intersection);
|
|
},
|
|
onMove: function(event) {
|
|
var wantDebug = false;
|
|
pickRay = generalComputePickRay(event.x, event.y);
|
|
|
|
var pick = rayPlaneIntersection2(pickRay, translateXZTool.pickPlanePosition, {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
});
|
|
|
|
// If the pick ray doesn't hit the pick plane in this direction, do nothing.
|
|
// this will happen when someone drags across the horizon from the side they started on.
|
|
if (!pick) {
|
|
if (wantDebug) {
|
|
print(" "+ translateXZTool.mode + "Pick ray does not intersect XZ plane.");
|
|
}
|
|
|
|
//--EARLY EXIT--( Invalid ray detected. )
|
|
return;
|
|
}
|
|
|
|
var vector = Vec3.subtract(pick, initialXZPick);
|
|
|
|
// If the mouse is too close to the horizon of the pick plane, stop moving
|
|
var MIN_ELEVATION = 0.02; // largest dimension of object divided by distance to it
|
|
var elevation = translateXZTool.elevation(pickRay.origin, pick);
|
|
if (wantDebug) {
|
|
print("Start Elevation: " + translateXZTool.startingElevation + ", elevation: " + elevation);
|
|
}
|
|
if ((translateXZTool.startingElevation > 0.0 && elevation < MIN_ELEVATION) ||
|
|
(translateXZTool.startingElevation < 0.0 && elevation > -MIN_ELEVATION)) {
|
|
if (wantDebug) {
|
|
print(" "+ translateXZTool.mode + " - too close to horizon!");
|
|
}
|
|
|
|
//--EARLY EXIT--( Don't proceed past the reached limit. )
|
|
return;
|
|
}
|
|
|
|
// If the angular size of the object is too small, stop moving
|
|
var MIN_ANGULAR_SIZE = 0.01; // Radians
|
|
if (translateXZTool.greatestDimension > 0) {
|
|
var angularSize = Math.atan(translateXZTool.greatestDimension / Vec3.distance(pickRay.origin, pick));
|
|
if (wantDebug) {
|
|
print("Angular size = " + angularSize);
|
|
}
|
|
if (angularSize < MIN_ANGULAR_SIZE) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If shifted, constrain to one axis
|
|
if (event.isShifted) {
|
|
if (Math.abs(vector.x) > Math.abs(vector.z)) {
|
|
vector.z = 0;
|
|
} else {
|
|
vector.x = 0;
|
|
}
|
|
if (!isConstrained) {
|
|
Overlays.editOverlay(xRailOverlay, {
|
|
visible: true
|
|
});
|
|
var xStart = Vec3.sum(startPosition, {
|
|
x: -10000,
|
|
y: 0,
|
|
z: 0
|
|
});
|
|
var xEnd = Vec3.sum(startPosition, {
|
|
x: 10000,
|
|
y: 0,
|
|
z: 0
|
|
});
|
|
var zStart = Vec3.sum(startPosition, {
|
|
x: 0,
|
|
y: 0,
|
|
z: -10000
|
|
});
|
|
var zEnd = Vec3.sum(startPosition, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 10000
|
|
});
|
|
Overlays.editOverlay(xRailOverlay, {
|
|
start: xStart,
|
|
end: xEnd,
|
|
visible: true
|
|
});
|
|
Overlays.editOverlay(zRailOverlay, {
|
|
start: zStart,
|
|
end: zEnd,
|
|
visible: true
|
|
});
|
|
isConstrained = true;
|
|
}
|
|
} else {
|
|
if (isConstrained) {
|
|
Overlays.editOverlay(xRailOverlay, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(zRailOverlay, {
|
|
visible: false
|
|
});
|
|
isConstrained = false;
|
|
}
|
|
}
|
|
|
|
constrainMajorOnly = event.isControl;
|
|
var cornerPosition = Vec3.sum(startPosition, Vec3.multiply(-0.5, selectionManager.worldDimensions));
|
|
vector = Vec3.subtract(
|
|
grid.snapToGrid(Vec3.sum(cornerPosition, vector), constrainMajorOnly),
|
|
cornerPosition);
|
|
|
|
|
|
|
|
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
|
var properties = SelectionManager.savedProperties[SelectionManager.selections[i]];
|
|
if (!properties) {
|
|
continue;
|
|
}
|
|
var newPosition = Vec3.sum(properties.position, {
|
|
x: vector.x,
|
|
y: 0,
|
|
z: vector.z
|
|
});
|
|
Entities.editEntity(SelectionManager.selections[i], {
|
|
position: newPosition,
|
|
});
|
|
|
|
if (wantDebug) {
|
|
print("translateXZ... ");
|
|
Vec3.print(" vector:", vector);
|
|
Vec3.print(" newPosition:", properties.position);
|
|
Vec3.print(" newPosition:", newPosition);
|
|
}
|
|
}
|
|
|
|
SelectionManager._update();
|
|
}
|
|
};
|
|
|
|
// GRABBER TOOL: GRABBER MOVE UP
|
|
var lastXYPick = null;
|
|
var upDownPickNormal = null;
|
|
addGrabberTool(grabberMoveUp, {
|
|
mode: "TRANSLATE_UP_DOWN",
|
|
onBegin: function(event) {
|
|
pickRay = generalComputePickRay(event.x, event.y);
|
|
|
|
upDownPickNormal = Quat.getForward(lastCameraOrientation);
|
|
// Remove y component so the y-axis lies along the plane we picking on - this will
|
|
// give movements that follow the mouse.
|
|
upDownPickNormal.y = 0;
|
|
lastXYPick = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, upDownPickNormal);
|
|
|
|
SelectionManager.saveProperties();
|
|
|
|
// Duplicate entities if alt is pressed. This will make a
|
|
// copy of the selected entities and move the _original_ entities, not
|
|
// the new ones.
|
|
if (event.isAlt) {
|
|
duplicatedEntityIDs = [];
|
|
for (var otherEntityID in SelectionManager.savedProperties) {
|
|
var properties = SelectionManager.savedProperties[otherEntityID];
|
|
if (!properties.locked) {
|
|
var entityID = Entities.addEntity(properties);
|
|
duplicatedEntityIDs.push({
|
|
entityID: entityID,
|
|
properties: properties,
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
duplicatedEntityIDs = null;
|
|
}
|
|
},
|
|
onEnd: function(event, reason) {
|
|
pushCommandForSelections(duplicatedEntityIDs);
|
|
},
|
|
onMove: function(event) {
|
|
pickRay = generalComputePickRay(event.x, event.y);
|
|
|
|
// translate mode left/right based on view toward entity
|
|
var newIntersection = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, upDownPickNormal);
|
|
|
|
var vector = Vec3.subtract(newIntersection, lastXYPick);
|
|
vector = grid.snapToGrid(vector);
|
|
|
|
// we only care about the Y axis
|
|
vector.x = 0;
|
|
vector.z = 0;
|
|
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("translateUpDown... ");
|
|
print(" event.y:" + event.y);
|
|
Vec3.print(" newIntersection:", newIntersection);
|
|
Vec3.print(" vector:", vector);
|
|
//Vec3.print(" newPosition:", newPosition);
|
|
}
|
|
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
|
var id = SelectionManager.selections[i];
|
|
var properties = selectionManager.savedProperties[id];
|
|
|
|
var original = properties.position;
|
|
var newPosition = Vec3.sum(properties.position, vector);
|
|
|
|
Entities.editEntity(id, {
|
|
position: newPosition,
|
|
});
|
|
}
|
|
|
|
SelectionManager._update();
|
|
},
|
|
});
|
|
|
|
// GRABBER TOOL: GRABBER CLONER
|
|
addGrabberTool(grabberCloner, {
|
|
mode: "CLONE",
|
|
onBegin: function(event) {
|
|
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
var result = Overlays.findRayIntersection(pickRay);
|
|
translateXZTool.pickPlanePosition = result.intersection;
|
|
translateXZTool.greatestDimension = Math.max(Math.max(SelectionManager.worldDimensions.x, SelectionManager.worldDimensions.y),
|
|
SelectionManager.worldDimensions.z);
|
|
|
|
translateXZTool.onBegin(event,true);
|
|
},
|
|
elevation: function (event) {
|
|
translateXZTool.elevation(event);
|
|
},
|
|
|
|
onEnd: function (event) {
|
|
translateXZTool.onEnd(event);
|
|
},
|
|
|
|
onMove: function (event) {
|
|
translateXZTool.onMove(event);
|
|
}
|
|
});
|
|
|
|
|
|
|
|
// FUNCTION: VEC 3 MULT
|
|
var vec3Mult = function(v1, v2) {
|
|
return {
|
|
x: v1.x * v2.x,
|
|
y: v1.y * v2.y,
|
|
z: v1.z * v2.z
|
|
};
|
|
};
|
|
|
|
// FUNCTION: MAKE STRETCH TOOL
|
|
// stretchMode - name of mode
|
|
// direction - direction to stretch in
|
|
// pivot - point to use as a pivot
|
|
// offset - the position of the overlay tool relative to the selections center position
|
|
var makeStretchTool = function(stretchMode, direction, pivot, offset, customOnMove) {
|
|
// directionFor3DStretch - direction and pivot for 3D stretch
|
|
// distanceFor3DStretch - distance from the intersection point and the handController
|
|
// used to increase the scale taking into account the distance to the object
|
|
// DISTANCE_INFLUENCE_THRESHOLD - constant that holds the minimum distance where the
|
|
// distance to the object will influence the stretch/resize/scale
|
|
var directionFor3DStretch = getDirectionsFor3DStretch(stretchMode);
|
|
var distanceFor3DStretch = 0;
|
|
var DISTANCE_INFLUENCE_THRESHOLD = 1.2;
|
|
|
|
|
|
var signs = {
|
|
x: direction.x < 0 ? -1 : (direction.x > 0 ? 1 : 0),
|
|
y: direction.y < 0 ? -1 : (direction.y > 0 ? 1 : 0),
|
|
z: direction.z < 0 ? -1 : (direction.z > 0 ? 1 : 0),
|
|
};
|
|
|
|
var mask = {
|
|
x: Math.abs(direction.x) > 0 ? 1 : 0,
|
|
y: Math.abs(direction.y) > 0 ? 1 : 0,
|
|
z: Math.abs(direction.z) > 0 ? 1 : 0,
|
|
};
|
|
|
|
|
|
|
|
var numDimensions = mask.x + mask.y + mask.z;
|
|
|
|
var planeNormal = null;
|
|
var lastPick = null;
|
|
var lastPick3D = null;
|
|
var initialPosition = null;
|
|
var initialDimensions = null;
|
|
var initialIntersection = null;
|
|
var initialProperties = null;
|
|
var registrationPoint = null;
|
|
var deltaPivot = null;
|
|
var deltaPivot3D = null;
|
|
var pickRayPosition = null;
|
|
var pickRayPosition3D = null;
|
|
var rotation = null;
|
|
|
|
var onBegin = function(event) {
|
|
var properties = Entities.getEntityProperties(SelectionManager.selections[0]);
|
|
initialProperties = properties;
|
|
rotation = spaceMode == SPACE_LOCAL ? properties.rotation : Quat.fromPitchYawRollDegrees(0, 0, 0);
|
|
|
|
if (spaceMode == SPACE_LOCAL) {
|
|
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;
|
|
}
|
|
|
|
// 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 (directionFor3DStretch) {
|
|
// pivot, offset and pickPlanePosition for 3D manipulation
|
|
var scaledPivot3D = Vec3.multiply(0.5, Vec3.multiply(1.0, directionFor3DStretch));
|
|
deltaPivot3D = Vec3.subtract(centeredRP, scaledPivot3D);
|
|
|
|
var scaledOffsetWorld3D = vec3Mult(initialDimensions,
|
|
Vec3.subtract(Vec3.multiply(0.5, Vec3.multiply(-1.0, directionFor3DStretch)),
|
|
centeredRP));
|
|
|
|
pickRayPosition3D = Vec3.sum(initialPosition, Vec3.multiplyQbyV(rotation, scaledOffsetWorld));
|
|
}
|
|
var start = null;
|
|
var end = null;
|
|
if (numDimensions == 1 && mask.x) {
|
|
start = Vec3.multiplyQbyV(rotation, {
|
|
x: -10000,
|
|
y: 0,
|
|
z: 0
|
|
});
|
|
start = Vec3.sum(start, properties.position);
|
|
end = Vec3.multiplyQbyV(rotation, {
|
|
x: 10000,
|
|
y: 0,
|
|
z: 0
|
|
});
|
|
end = Vec3.sum(end, properties.position);
|
|
Overlays.editOverlay(xRailOverlay, {
|
|
start: start,
|
|
end: end,
|
|
visible: true,
|
|
});
|
|
}
|
|
if (numDimensions == 1 && mask.y) {
|
|
start = Vec3.multiplyQbyV(rotation, {
|
|
x: 0,
|
|
y: -10000,
|
|
z: 0
|
|
});
|
|
start = Vec3.sum(start, properties.position);
|
|
end = Vec3.multiplyQbyV(rotation, {
|
|
x: 0,
|
|
y: 10000,
|
|
z: 0
|
|
});
|
|
end = Vec3.sum(end, properties.position);
|
|
Overlays.editOverlay(yRailOverlay, {
|
|
start: start,
|
|
end: end,
|
|
visible: true,
|
|
});
|
|
}
|
|
if (numDimensions == 1 && mask.z) {
|
|
start = Vec3.multiplyQbyV(rotation, {
|
|
x: 0,
|
|
y: 0,
|
|
z: -10000
|
|
});
|
|
start = Vec3.sum(start, properties.position);
|
|
end = Vec3.multiplyQbyV(rotation, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 10000
|
|
});
|
|
end = Vec3.sum(end, properties.position);
|
|
Overlays.editOverlay(zRailOverlay, {
|
|
start: start,
|
|
end: end,
|
|
visible: true,
|
|
});
|
|
}
|
|
if (numDimensions == 1) {
|
|
if (mask.x == 1) {
|
|
planeNormal = {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
};
|
|
} else if (mask.y == 1) {
|
|
planeNormal = {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
} else {
|
|
planeNormal = {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
};
|
|
}
|
|
} else if (numDimensions == 2) {
|
|
if (mask.x === 0) {
|
|
planeNormal = {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
} else if (mask.y === 0) {
|
|
planeNormal = {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
};
|
|
} else {
|
|
planeNormal = {
|
|
x: 0,
|
|
y: 0,
|
|
z: z
|
|
};
|
|
}
|
|
}
|
|
|
|
planeNormal = Vec3.multiplyQbyV(rotation, planeNormal);
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
lastPick = rayPlaneIntersection(pickRay,
|
|
pickRayPosition,
|
|
planeNormal);
|
|
|
|
var planeNormal3D = {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
};
|
|
if (directionFor3DStretch) {
|
|
lastPick3D = rayPlaneIntersection(pickRay,
|
|
pickRayPosition3D,
|
|
planeNormal3D);
|
|
distanceFor3DStretch = Vec3.length(Vec3.subtract(pickRayPosition3D, pickRay.origin));
|
|
}
|
|
|
|
SelectionManager.saveProperties();
|
|
};
|
|
|
|
var onEnd = function(event, reason) {
|
|
Overlays.editOverlay(xRailOverlay, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(yRailOverlay, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(zRailOverlay, {
|
|
visible: false
|
|
});
|
|
|
|
pushCommandForSelections();
|
|
};
|
|
|
|
var onMove = function(event) {
|
|
var proportional = spaceMode == SPACE_WORLD || event.isShifted || activeTool.mode == "STRETCH_RADIUS";
|
|
|
|
var position, dimensions, rotation;
|
|
if (spaceMode == SPACE_LOCAL) {
|
|
position = SelectionManager.localPosition;
|
|
dimensions = SelectionManager.localDimensions;
|
|
rotation = SelectionManager.localRotation;
|
|
} else {
|
|
position = SelectionManager.worldPosition;
|
|
dimensions = SelectionManager.worldDimensions;
|
|
rotation = SelectionManager.worldRotation;
|
|
}
|
|
|
|
var localDeltaPivot = deltaPivot;
|
|
var localSigns = signs;
|
|
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
|
|
// Are we using handControllers or Mouse - only relevant for 3D tools
|
|
var controllerPose = getControllerWorldLocation(activeHand, true);
|
|
var vector = null;
|
|
if (HMD.isHMDAvailable() && HMD.isHandControllerAvailable() &&
|
|
controllerPose.valid && that.triggered && directionFor3DStretch) {
|
|
localDeltaPivot = deltaPivot3D;
|
|
|
|
newPick = pickRay.origin;
|
|
|
|
vector = Vec3.subtract(newPick, lastPick3D);
|
|
|
|
vector = Vec3.multiplyQbyV(Quat.inverse(rotation), vector);
|
|
|
|
if (distanceFor3DStretch > DISTANCE_INFLUENCE_THRESHOLD) {
|
|
// Range of Motion
|
|
vector = Vec3.multiply(distanceFor3DStretch , vector);
|
|
}
|
|
|
|
localSigns = directionFor3DStretch;
|
|
|
|
} else {
|
|
newPick = rayPlaneIntersection(pickRay,
|
|
pickRayPosition,
|
|
planeNormal);
|
|
vector = Vec3.subtract(newPick, lastPick);
|
|
|
|
vector = Vec3.multiplyQbyV(Quat.inverse(rotation), vector);
|
|
|
|
vector = vec3Mult(mask, vector);
|
|
|
|
}
|
|
|
|
if (customOnMove) {
|
|
var change = Vec3.multiply(-1, vec3Mult(localSigns, vector));
|
|
customOnMove(vector, change);
|
|
} else {
|
|
vector = grid.snapToSpacing(vector);
|
|
|
|
var changeInDimensions = Vec3.multiply(-1, vec3Mult(localSigns, vector));
|
|
var newDimensions;
|
|
if (proportional) {
|
|
var absX = Math.abs(changeInDimensions.x);
|
|
var absY = Math.abs(changeInDimensions.y);
|
|
var absZ = Math.abs(changeInDimensions.z);
|
|
var pctChange = 0;
|
|
if (absX > absY && absX > absZ) {
|
|
pctChange = changeInDimensions.x / initialProperties.dimensions.x;
|
|
pctChange = changeInDimensions.x / initialDimensions.x;
|
|
} else if (absY > absZ) {
|
|
pctChange = changeInDimensions.y / initialProperties.dimensions.y;
|
|
pctChange = changeInDimensions.y / initialDimensions.y;
|
|
} else {
|
|
pctChange = changeInDimensions.z / initialProperties.dimensions.z;
|
|
pctChange = changeInDimensions.z / initialDimensions.z;
|
|
}
|
|
pctChange += 1.0;
|
|
newDimensions = Vec3.multiply(pctChange, initialDimensions);
|
|
} else {
|
|
newDimensions = Vec3.sum(initialDimensions, changeInDimensions);
|
|
}
|
|
|
|
newDimensions.x = Math.max(newDimensions.x, MINIMUM_DIMENSION);
|
|
newDimensions.y = Math.max(newDimensions.y, MINIMUM_DIMENSION);
|
|
newDimensions.z = Math.max(newDimensions.z, MINIMUM_DIMENSION);
|
|
|
|
var changeInPosition = Vec3.multiplyQbyV(rotation, vec3Mult(localDeltaPivot, changeInDimensions));
|
|
var newPosition = Vec3.sum(initialPosition, changeInPosition);
|
|
|
|
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
|
Entities.editEntity(SelectionManager.selections[i], {
|
|
position: newPosition,
|
|
dimensions: newDimensions,
|
|
});
|
|
}
|
|
|
|
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print(stretchMode);
|
|
//Vec3.print(" newIntersection:", newIntersection);
|
|
Vec3.print(" vector:", vector);
|
|
//Vec3.print(" oldPOS:", oldPOS);
|
|
//Vec3.print(" newPOS:", newPOS);
|
|
Vec3.print(" changeInDimensions:", changeInDimensions);
|
|
Vec3.print(" newDimensions:", newDimensions);
|
|
|
|
Vec3.print(" changeInPosition:", changeInPosition);
|
|
Vec3.print(" newPosition:", newPosition);
|
|
}
|
|
}
|
|
|
|
SelectionManager._update();
|
|
};//--End of onMove def
|
|
|
|
return {
|
|
mode: stretchMode,
|
|
onBegin: onBegin,
|
|
onMove: onMove,
|
|
onEnd: onEnd
|
|
};
|
|
};
|
|
|
|
// Direction for the stretch tool when using hand controller
|
|
var directionsFor3DGrab = {
|
|
LBN: {
|
|
x: 1,
|
|
y: 1,
|
|
z: 1
|
|
},
|
|
RBN: {
|
|
x: -1,
|
|
y: 1,
|
|
z: 1
|
|
},
|
|
LBF: {
|
|
x: 1,
|
|
y: 1,
|
|
z: -1
|
|
},
|
|
RBF: {
|
|
x: -1,
|
|
y: 1,
|
|
z: -1
|
|
},
|
|
LTN: {
|
|
x: 1,
|
|
y: -1,
|
|
z: 1
|
|
},
|
|
RTN: {
|
|
x: -1,
|
|
y: -1,
|
|
z: 1
|
|
},
|
|
LTF: {
|
|
x: 1,
|
|
y: -1,
|
|
z: -1
|
|
},
|
|
RTF: {
|
|
x: -1,
|
|
y: -1,
|
|
z: -1
|
|
}
|
|
};
|
|
|
|
// FUNCTION: GET DIRECTION FOR 3D STRETCH
|
|
// Returns a vector with directions for the stretch tool in 3D using hand controllers
|
|
function getDirectionsFor3DStretch(mode) {
|
|
if (mode === "STRETCH_LBN") {
|
|
return directionsFor3DGrab.LBN;
|
|
} else if (mode === "STRETCH_RBN") {
|
|
return directionsFor3DGrab.RBN;
|
|
} else if (mode === "STRETCH_LBF") {
|
|
return directionsFor3DGrab.LBF;
|
|
} else if (mode === "STRETCH_RBF") {
|
|
return directionsFor3DGrab.RBF;
|
|
} else if (mode === "STRETCH_LTN") {
|
|
return directionsFor3DGrab.LTN;
|
|
} else if (mode === "STRETCH_RTN") {
|
|
return directionsFor3DGrab.RTN;
|
|
} else if (mode === "STRETCH_LTF") {
|
|
return directionsFor3DGrab.LTF;
|
|
} else if (mode === "STRETCH_RTF") {
|
|
return directionsFor3DGrab.RTF;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
// FUNCTION: ADD STRETCH TOOL
|
|
function addStretchTool(overlay, mode, pivot, direction, offset, handleMove) {
|
|
if (!pivot) {
|
|
pivot = direction;
|
|
}
|
|
var tool = makeStretchTool(mode, direction, pivot, offset, handleMove);
|
|
|
|
addGrabberTool(overlay, tool);
|
|
}
|
|
|
|
// FUNCTION: CUTOFF STRETCH FUNC
|
|
function cutoffStretchFunc(vector, change) {
|
|
vector = change;
|
|
Vec3.print("Radius stretch: ", vector);
|
|
var length = vector.x + vector.y + vector.z;
|
|
var props = selectionManager.savedProperties[selectionManager.selections[0]];
|
|
|
|
var radius = props.dimensions.z / 2;
|
|
var originalCutoff = props.cutoff;
|
|
|
|
var originalSize = radius * Math.tan(originalCutoff * (Math.PI / 180));
|
|
var newSize = originalSize + length;
|
|
var cutoff = Math.atan2(newSize, radius) * 180 / Math.PI;
|
|
|
|
Entities.editEntity(selectionManager.selections[0], {
|
|
cutoff: cutoff,
|
|
});
|
|
|
|
SelectionManager._update();
|
|
}
|
|
|
|
// FUNCTION: RADIUS STRETCH FUNC
|
|
function radiusStretchFunc(vector, change) {
|
|
var props = selectionManager.savedProperties[selectionManager.selections[0]];
|
|
|
|
// Find the axis being adjusted
|
|
var size;
|
|
if (Math.abs(change.x) > 0) {
|
|
size = props.dimensions.x + change.x;
|
|
} else if (Math.abs(change.y) > 0) {
|
|
size = props.dimensions.y + change.y;
|
|
} else if (Math.abs(change.z) > 0) {
|
|
size = props.dimensions.z + change.z;
|
|
}
|
|
|
|
var newDimensions = {
|
|
x: size,
|
|
y: size,
|
|
z: size
|
|
};
|
|
|
|
Entities.editEntity(selectionManager.selections[0], {
|
|
dimensions: newDimensions,
|
|
});
|
|
|
|
SelectionManager._update();
|
|
}
|
|
|
|
// STRETCH TOOL DEF SECTION
|
|
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(grabberSpotLightRadius, "STRETCH_RADIUS", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: -1
|
|
});
|
|
addStretchTool(grabberSpotLightT, "STRETCH_CUTOFF_T", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: -1,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
}, cutoffStretchFunc);
|
|
addStretchTool(grabberSpotLightB, "STRETCH_CUTOFF_B", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: -1,
|
|
z: 0
|
|
}, cutoffStretchFunc);
|
|
addStretchTool(grabberSpotLightL, "STRETCH_CUTOFF_L", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: -1,
|
|
y: 0,
|
|
z: 0
|
|
}, cutoffStretchFunc);
|
|
addStretchTool(grabberSpotLightR, "STRETCH_CUTOFF_R", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: -1,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
}, cutoffStretchFunc);
|
|
|
|
addStretchTool(grabberPointLightT, "STRETCH_RADIUS_T", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: -1,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, radiusStretchFunc);
|
|
addStretchTool(grabberPointLightB, "STRETCH_RADIUS_B", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 1,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, radiusStretchFunc);
|
|
addStretchTool(grabberPointLightL, "STRETCH_RADIUS_L", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, radiusStretchFunc);
|
|
addStretchTool(grabberPointLightR, "STRETCH_RADIUS_R", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: -1,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, radiusStretchFunc);
|
|
addStretchTool(grabberPointLightF, "STRETCH_RADIUS_F", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, radiusStretchFunc);
|
|
addStretchTool(grabberPointLightN, "STRETCH_RADIUS_N", {
|
|
x: 0,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, {
|
|
x: 0,
|
|
y: 0,
|
|
z: -1
|
|
}, radiusStretchFunc);
|
|
|
|
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
|
|
});
|
|
addStretchTool(grabberLBF, "STRETCH_LBF", null, {
|
|
x: 1,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: -1,
|
|
y: -1,
|
|
z: 1
|
|
});
|
|
addStretchTool(grabberRBF, "STRETCH_RBF", null, {
|
|
x: -1,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: 1,
|
|
y: -1,
|
|
z: 1
|
|
});
|
|
addStretchTool(grabberLTN, "STRETCH_LTN", null, {
|
|
x: 1,
|
|
y: 0,
|
|
z: 1
|
|
}, {
|
|
x: -1,
|
|
y: 1,
|
|
z: -1
|
|
});
|
|
addStretchTool(grabberRTN, "STRETCH_RTN", null, {
|
|
x: -1,
|
|
y: 0,
|
|
z: 1
|
|
}, {
|
|
x: 1,
|
|
y: 1,
|
|
z: -1
|
|
});
|
|
addStretchTool(grabberLTF, "STRETCH_LTF", null, {
|
|
x: 1,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: -1,
|
|
y: 1,
|
|
z: 1
|
|
});
|
|
addStretchTool(grabberRTF, "STRETCH_RTF", null, {
|
|
x: -1,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: 1,
|
|
y: 1,
|
|
z: 1
|
|
});
|
|
|
|
addStretchTool(grabberEdgeTR, "STRETCH_EdgeTR", null, {
|
|
x: 1,
|
|
y: 1,
|
|
z: 0
|
|
}, {
|
|
x: 1,
|
|
y: 1,
|
|
z: 0
|
|
});
|
|
addStretchTool(grabberEdgeTL, "STRETCH_EdgeTL", null, {
|
|
x: -1,
|
|
y: 1,
|
|
z: 0
|
|
}, {
|
|
x: -1,
|
|
y: 1,
|
|
z: 0
|
|
});
|
|
addStretchTool(grabberEdgeTF, "STRETCH_EdgeTF", null, {
|
|
x: 0,
|
|
y: 1,
|
|
z: -1
|
|
}, {
|
|
x: 0,
|
|
y: 1,
|
|
z: -1
|
|
});
|
|
addStretchTool(grabberEdgeTN, "STRETCH_EdgeTN", null, {
|
|
x: 0,
|
|
y: 1,
|
|
z: 1
|
|
}, {
|
|
x: 0,
|
|
y: 1,
|
|
z: 1
|
|
});
|
|
addStretchTool(grabberEdgeBR, "STRETCH_EdgeBR", null, {
|
|
x: -1,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: 1,
|
|
y: -1,
|
|
z: 0
|
|
});
|
|
addStretchTool(grabberEdgeBL, "STRETCH_EdgeBL", null, {
|
|
x: 1,
|
|
y: 0,
|
|
z: 0
|
|
}, {
|
|
x: -1,
|
|
y: -1,
|
|
z: 0
|
|
});
|
|
addStretchTool(grabberEdgeBF, "STRETCH_EdgeBF", null, {
|
|
x: 0,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: 0,
|
|
y: -1,
|
|
z: -1
|
|
});
|
|
addStretchTool(grabberEdgeBN, "STRETCH_EdgeBN", null, {
|
|
x: 0,
|
|
y: 0,
|
|
z: 1
|
|
}, {
|
|
x: 0,
|
|
y: -1,
|
|
z: 1
|
|
});
|
|
addStretchTool(grabberEdgeNR, "STRETCH_EdgeNR", null, {
|
|
x: -1,
|
|
y: 0,
|
|
z: 1
|
|
}, {
|
|
x: 1,
|
|
y: 0,
|
|
z: -1
|
|
});
|
|
addStretchTool(grabberEdgeNL, "STRETCH_EdgeNL", null, {
|
|
x: 1,
|
|
y: 0,
|
|
z: 1
|
|
}, {
|
|
x: -1,
|
|
y: 0,
|
|
z: -1
|
|
});
|
|
addStretchTool(grabberEdgeFR, "STRETCH_EdgeFR", null, {
|
|
x: -1,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: 1,
|
|
y: 0,
|
|
z: 1
|
|
});
|
|
addStretchTool(grabberEdgeFL, "STRETCH_EdgeFL", null, {
|
|
x: 1,
|
|
y: 0,
|
|
z: -1
|
|
}, {
|
|
x: -1,
|
|
y: 0,
|
|
z: 1
|
|
});
|
|
|
|
// FUNCTION: UPDATE ROTATION DEGREES OVERLAY
|
|
function updateRotationDegreesOverlay(angleFromZero, handleRotation, centerPosition) {
|
|
print( "---> updateRotationDegreesOverlay ---" );
|
|
print(" AngleFromZero: " + angleFromZero );
|
|
print(" HandleRotation - X: " + handleRotation.x + " Y: " + handleRotation.y + " Z: " + handleRotation.z );
|
|
print(" CenterPos - " + centerPosition.x + " Y: " + centerPosition.y + " Z: " + centerPosition.z );
|
|
var angle = angleFromZero * (Math.PI / 180);
|
|
var position = {
|
|
x: Math.cos(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER,
|
|
y: Math.sin(angle) * outerRadius * ROTATION_DISPLAY_DISTANCE_MULTIPLIER,
|
|
z: 0,
|
|
};
|
|
print(" Angle: " + angle );
|
|
print(" InitialPos: " + position.x + ", " + position.y + ", " + position.z);
|
|
position = Vec3.multiplyQbyV(handleRotation, position);
|
|
position = Vec3.sum(centerPosition, position);
|
|
print(" TranslatedPos: " + position.x + ", " + position.y + ", " + position.z);
|
|
var overlayProps = {
|
|
position: position,
|
|
dimensions: {
|
|
x: innerRadius * ROTATION_DISPLAY_SIZE_X_MULTIPLIER,
|
|
y: innerRadius * ROTATION_DISPLAY_SIZE_Y_MULTIPLIER
|
|
},
|
|
lineHeight: innerRadius * ROTATION_DISPLAY_LINE_HEIGHT_MULTIPLIER,
|
|
text: normalizeDegrees(angleFromZero) + "°",
|
|
};
|
|
print(" OverlayDim - X: " + overlayProps.dimensions.x + " Y: " + overlayProps.dimensions.y + " Z: " + overlayProps.dimensions.z );
|
|
print(" OverlayLineHeight: " + overlayProps.lineHeight );
|
|
print(" OverlayText: " + overlayProps.text );
|
|
Overlays.editOverlay(rotationDegreesDisplay, overlayProps);
|
|
print( "<--- updateRotationDegreesOverlay ---" );
|
|
}
|
|
|
|
// FUNCTION DEF: updateSelectionsRotation
|
|
// Helper func used by rotation grabber tools
|
|
function updateSelectionsRotation( rotationChange ) {
|
|
if ( ! rotationChange ) {
|
|
print("ERROR( updateSelectionsRotation ) - Invalid arg specified!!");
|
|
|
|
//--EARLY EXIT--
|
|
return;
|
|
}
|
|
|
|
// 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 initialProperties = SelectionManager.savedProperties[entityID];
|
|
|
|
var newProperties = {
|
|
rotation: Quat.multiply(rotationChange, initialProperties.rotation),
|
|
};
|
|
|
|
if (reposition) {
|
|
var dPos = Vec3.subtract(initialProperties.position, initialPosition);
|
|
dPos = Vec3.multiplyQbyV(rotationChange, dPos);
|
|
newProperties.position = Vec3.sum(initialPosition, dPos);
|
|
}
|
|
|
|
Entities.editEntity(entityID, newProperties);
|
|
}
|
|
}
|
|
|
|
// YAW GRABBER TOOL DEFINITION
|
|
var initialPosition = SelectionManager.worldPosition;
|
|
addGrabberTool(yawHandle, {
|
|
mode: "ROTATE_YAW",
|
|
onBegin: function(event) {
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("================== HANDLE_YAW(Beg) -> =======================");
|
|
}
|
|
SelectionManager.saveProperties();
|
|
initialPosition = SelectionManager.worldPosition;
|
|
mode = "ROTATE_YAW";
|
|
rotationNormal = yawNormal;
|
|
//note: It's expected that the intersection is passed when this is called.
|
|
if (arguments.length >= 2 ) {
|
|
yawZero = arguments[ 1 ];
|
|
} else {
|
|
print("ERROR( yawHandle.onBegin ) - Intersection wasn't passed!");
|
|
}
|
|
|
|
if (wantDebug) {
|
|
Vec3.print(" yawZero: ", yawZero);
|
|
}
|
|
|
|
// Size the overlays to the current selection size
|
|
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
|
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
|
innerRadius = diagonal;
|
|
outerRadius = diagonal * 1.15;
|
|
var innerAlpha = 0.2;
|
|
var outerAlpha = 0.2;
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: true,
|
|
rotation: yawHandleRotation,
|
|
position: yawCenter,
|
|
size: innerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: innerAlpha,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: true,
|
|
rotation: yawHandleRotation,
|
|
position: yawCenter,
|
|
size: outerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: outerAlpha,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: true,
|
|
rotation: yawHandleRotation,
|
|
position: yawCenter,
|
|
size: outerRadius,
|
|
startAt: 0,
|
|
endAt: 0,
|
|
innerRadius: 0.9,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayTarget, {
|
|
visible: true,
|
|
rotation: yawHandleRotation,
|
|
position: yawCenter
|
|
});
|
|
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: true,
|
|
});
|
|
|
|
updateRotationDegreesOverlay(0, yawHandleRotation, yawCenter);
|
|
if(wantDebug){
|
|
print("================== HANDLE_YAW(Beg) <- =======================");
|
|
}
|
|
},
|
|
onEnd: function(event, reason) {
|
|
print("================== HANDLE_YAW(End) -> =======================");
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: false
|
|
});
|
|
|
|
pushCommandForSelections();
|
|
print("================== HANDLE_YAW(End) <- =======================");
|
|
},
|
|
onMove: function(event) {
|
|
print("================== HANDLE_YAW(Mve) -> =======================");
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
Overlays.editOverlay(selectionBox, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, {
|
|
visible: false
|
|
});
|
|
|
|
var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]);
|
|
|
|
if (result.intersects) {
|
|
var center = yawCenter;
|
|
var zero = yawZero;
|
|
var centerToZero = Vec3.subtract(zero, center);
|
|
var centerToIntersect = Vec3.subtract(result.intersection, center);
|
|
// Note: orientedAngle which wants normalized centerToZero and centerToIntersect
|
|
// handles that internally, so it's to pass unnormalized vectors here.
|
|
print(" RotNormal - X: " + rotationNormal.x + " Y: " + rotationNormal.y + " Z: " + rotationNormal.z);
|
|
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
|
|
var distanceFromCenter = Vec3.distance(center, result.intersection);
|
|
var snapToInner = distanceFromCenter < innerRadius;
|
|
var snapAngle = snapToInner ? innerSnapAngle : 1.0;
|
|
angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle;
|
|
var yawChange = Quat.fromVec3Degrees({
|
|
x: 0,
|
|
y: angleFromZero,
|
|
z: 0
|
|
});
|
|
|
|
updateSelectionsRotation( yawChange );
|
|
|
|
updateRotationDegreesOverlay(angleFromZero, yawHandleRotation, yawCenter);
|
|
|
|
// update the rotation display accordingly...
|
|
var startAtCurrent = 0;
|
|
var endAtCurrent = angleFromZero;
|
|
var startAtRemainder = angleFromZero;
|
|
var endAtRemainder = 360;
|
|
if (angleFromZero < 0) {
|
|
startAtCurrent = 360 + angleFromZero;
|
|
endAtCurrent = 360;
|
|
startAtRemainder = 0;
|
|
endAtRemainder = startAtCurrent;
|
|
}
|
|
if (snapToInner) {
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
startAt: 0,
|
|
endAt: 360
|
|
});
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
startAt: startAtRemainder,
|
|
endAt: endAtRemainder
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
startAt: startAtCurrent,
|
|
endAt: endAtCurrent,
|
|
size: innerRadius,
|
|
majorTickMarksAngle: innerSnapAngle,
|
|
minorTickMarksAngle: 0,
|
|
majorTickMarksLength: -0.25,
|
|
minorTickMarksLength: 0,
|
|
});
|
|
} else {
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
startAt: 0,
|
|
endAt: 360
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
startAt: startAtRemainder,
|
|
endAt: endAtRemainder
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
startAt: startAtCurrent,
|
|
endAt: endAtCurrent,
|
|
size: outerRadius,
|
|
majorTickMarksAngle: 45.0,
|
|
minorTickMarksAngle: 5,
|
|
majorTickMarksLength: 0.25,
|
|
minorTickMarksLength: 0.1,
|
|
});
|
|
}
|
|
|
|
}
|
|
print("================== HANDLE_YAW(Mve) <- =======================");
|
|
}
|
|
});
|
|
|
|
// PITCH GRABBER TOOL DEFINITION
|
|
addGrabberTool(pitchHandle, {
|
|
mode: "ROTATE_PITCH",
|
|
onBegin: function (event) {
|
|
var wantDebug = false;
|
|
if (wantDebug){
|
|
print("================== HANDLE_PITCH(Beg) -> =======================");
|
|
}
|
|
SelectionManager.saveProperties();
|
|
initialPosition = SelectionManager.worldPosition;
|
|
mode = "ROTATE_PITCH";
|
|
rotationNormal = pitchNormal;
|
|
//note: It's expected that the intersection is passed when this is called.
|
|
if (arguments.length >= 2 ) {
|
|
pitchZero = arguments[ 1 ];
|
|
} else {
|
|
print("ERROR( pitchHandle.onBegin ) - Intersection wasn't passed!");
|
|
}
|
|
|
|
if (wantDebug) {
|
|
Vec3.print(" pitchZero: ", pitchZero);
|
|
}
|
|
|
|
// Size the overlays to the current selection size
|
|
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
|
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
|
innerRadius = diagonal;
|
|
outerRadius = diagonal * 1.15;
|
|
var innerAlpha = 0.2;
|
|
var outerAlpha = 0.2;
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: true,
|
|
rotation: pitchHandleRotation,
|
|
position: pitchCenter,
|
|
size: innerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: innerAlpha
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: true,
|
|
rotation: pitchHandleRotation,
|
|
position: pitchCenter,
|
|
size: outerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: outerAlpha,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: true,
|
|
rotation: pitchHandleRotation,
|
|
position: pitchCenter,
|
|
size: outerRadius,
|
|
startAt: 0,
|
|
endAt: 0,
|
|
innerRadius: 0.9,
|
|
});
|
|
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: true,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayTarget, {
|
|
visible: true,
|
|
rotation: pitchHandleRotation,
|
|
position: pitchCenter
|
|
});
|
|
|
|
updateRotationDegreesOverlay(0, pitchHandleRotation, pitchCenter);
|
|
if(wantDebug){
|
|
print("================== HANDLE_PITCH(Beg) <- =======================");
|
|
}
|
|
},
|
|
onEnd: function(event, reason) {
|
|
print("================== HANDLE_PITCH(End) -> =======================");
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: false
|
|
});
|
|
|
|
pushCommandForSelections();
|
|
print("================== HANDLE_PITCH(End) <- =======================");
|
|
},
|
|
onMove: function (event) {
|
|
print("================== HANDLE_PITCH(Mve) -> =======================");
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
Overlays.editOverlay(selectionBox, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, {
|
|
visible: false
|
|
});
|
|
var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]);
|
|
|
|
if (result.intersects) {
|
|
var center = pitchCenter;
|
|
var zero = pitchZero;
|
|
var centerToZero = Vec3.subtract(zero, center);
|
|
var centerToIntersect = Vec3.subtract(result.intersection, center);
|
|
// Note: orientedAngle which wants normalized centerToZero & centerToIntersect, handles
|
|
// this internally, so it's fine to pass non-normalized versions here.
|
|
print(" RotNormal - X: " + rotationNormal.x + " Y: " + rotationNormal.y + " Z: " + rotationNormal.z);
|
|
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
|
|
|
|
var distanceFromCenter = Vec3.distance(center, result.intersection);
|
|
var snapToInner = distanceFromCenter < innerRadius;
|
|
var snapAngle = snapToInner ? innerSnapAngle : 1.0;
|
|
angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle;
|
|
|
|
var pitchChange = Quat.fromVec3Degrees({
|
|
x: angleFromZero,
|
|
y: 0,
|
|
z: 0
|
|
});
|
|
|
|
updateSelectionsRotation( pitchChange );
|
|
|
|
updateRotationDegreesOverlay(angleFromZero, pitchHandleRotation, pitchCenter);
|
|
|
|
// update the rotation display accordingly...
|
|
var startAtCurrent = 0;
|
|
var endAtCurrent = angleFromZero;
|
|
var startAtRemainder = angleFromZero;
|
|
var endAtRemainder = 360;
|
|
if (angleFromZero < 0) {
|
|
startAtCurrent = 360 + angleFromZero;
|
|
endAtCurrent = 360;
|
|
startAtRemainder = 0;
|
|
endAtRemainder = startAtCurrent;
|
|
}
|
|
if (snapToInner) {
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
startAt: 0,
|
|
endAt: 360
|
|
});
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
startAt: startAtRemainder,
|
|
endAt: endAtRemainder
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
startAt: startAtCurrent,
|
|
endAt: endAtCurrent,
|
|
size: innerRadius,
|
|
majorTickMarksAngle: innerSnapAngle,
|
|
minorTickMarksAngle: 0,
|
|
majorTickMarksLength: -0.25,
|
|
minorTickMarksLength: 0,
|
|
});
|
|
} else {
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
startAt: 0,
|
|
endAt: 360
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
startAt: startAtRemainder,
|
|
endAt: endAtRemainder
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
startAt: startAtCurrent,
|
|
endAt: endAtCurrent,
|
|
size: outerRadius,
|
|
majorTickMarksAngle: 45.0,
|
|
minorTickMarksAngle: 5,
|
|
majorTickMarksLength: 0.25,
|
|
minorTickMarksLength: 0.1,
|
|
});
|
|
}
|
|
}
|
|
print("================== HANDLE_PITCH(Mve) <- =======================");
|
|
}
|
|
});
|
|
|
|
// ROLL GRABBER TOOL DEFINITION
|
|
addGrabberTool(rollHandle, {
|
|
mode: "ROTATE_ROLL",
|
|
onBegin: function (event) {
|
|
var wantDebug = false;
|
|
if(wantDebug){
|
|
print("================== HANDLE_ROLL(Beg) -> =======================");
|
|
}
|
|
SelectionManager.saveProperties();
|
|
initialPosition = SelectionManager.worldPosition;
|
|
mode = "ROTATE_ROLL";
|
|
rotationNormal = rollNormal;
|
|
//note: It's expected that the intersection is passed when this is called.
|
|
if (arguments.length >= 2 ) {
|
|
rollZero = arguments[ 1 ];
|
|
} else {
|
|
print("ERROR( rollHandle.onBegin ) - Intersection wasn't passed!");
|
|
}
|
|
|
|
if (wantDebug) {
|
|
Vec3.print(" rollZero: ", rollZero);
|
|
}
|
|
|
|
// Size the overlays to the current selection size
|
|
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
|
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
|
innerRadius = diagonal;
|
|
outerRadius = diagonal * 1.15;
|
|
var innerAlpha = 0.2;
|
|
var outerAlpha = 0.2;
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: true,
|
|
rotation: rollHandleRotation,
|
|
position: rollCenter,
|
|
size: innerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: innerAlpha
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: true,
|
|
rotation: rollHandleRotation,
|
|
position: rollCenter,
|
|
size: outerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: outerAlpha,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: true,
|
|
rotation: rollHandleRotation,
|
|
position: rollCenter,
|
|
size: outerRadius,
|
|
startAt: 0,
|
|
endAt: 0,
|
|
innerRadius: 0.9,
|
|
});
|
|
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: true,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayTarget, {
|
|
visible: true,
|
|
rotation: rollHandleRotation,
|
|
position: rollCenter
|
|
});
|
|
|
|
updateRotationDegreesOverlay(0, rollHandleRotation, rollCenter);
|
|
if(wantDebug){
|
|
print("================== HANDLE_ROLL(Beg) <- =======================");
|
|
}
|
|
},
|
|
onEnd: function (event, reason) {
|
|
print("================== HANDLE_ROLL(End) -> =======================");
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: false
|
|
});
|
|
|
|
pushCommandForSelections();
|
|
print("================== HANDLE_ROLL(End) <- =======================");
|
|
},
|
|
onMove: function(event) {
|
|
print("================== HANDLE_ROLL(Mve) -> =======================");
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
Overlays.editOverlay(selectionBox, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, {
|
|
visible: false
|
|
});
|
|
var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]);
|
|
|
|
if (result.intersects) {
|
|
var center = rollCenter;
|
|
var zero = rollZero;
|
|
var centerToZero = Vec3.subtract(zero, center);
|
|
var centerToIntersect = Vec3.subtract(result.intersection, center);
|
|
// Note: orientedAngle which wants normalized centerToZero & centerToIntersect, handles
|
|
// this internally, so it's fine to pass non-normalized versions here.
|
|
print(" RotNormal - X: " + rotationNormal.x + " Y: " + rotationNormal.y + " Z: " + rotationNormal.z);
|
|
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
|
|
|
|
var distanceFromCenter = Vec3.distance(center, result.intersection);
|
|
var snapToInner = distanceFromCenter < innerRadius;
|
|
var snapAngle = snapToInner ? innerSnapAngle : 1.0;
|
|
angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle;
|
|
|
|
var rollChange = Quat.fromVec3Degrees({
|
|
x: 0,
|
|
y: 0,
|
|
z: angleFromZero
|
|
});
|
|
|
|
updateSelectionsRotation( rollChange );
|
|
|
|
updateRotationDegreesOverlay(angleFromZero, rollHandleRotation, rollCenter);
|
|
|
|
// update the rotation display accordingly...
|
|
var startAtCurrent = 0;
|
|
var endAtCurrent = angleFromZero;
|
|
var startAtRemainder = angleFromZero;
|
|
var endAtRemainder = 360;
|
|
if (angleFromZero < 0) {
|
|
startAtCurrent = 360 + angleFromZero;
|
|
endAtCurrent = 360;
|
|
startAtRemainder = 0;
|
|
endAtRemainder = startAtCurrent;
|
|
}
|
|
if (snapToInner) {
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
startAt: 0,
|
|
endAt: 360
|
|
});
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
startAt: startAtRemainder,
|
|
endAt: endAtRemainder
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
startAt: startAtCurrent,
|
|
endAt: endAtCurrent,
|
|
size: innerRadius,
|
|
majorTickMarksAngle: innerSnapAngle,
|
|
minorTickMarksAngle: 0,
|
|
majorTickMarksLength: -0.25,
|
|
minorTickMarksLength: 0,
|
|
});
|
|
} else {
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
startAt: 0,
|
|
endAt: 360
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
startAt: startAtRemainder,
|
|
endAt: endAtRemainder
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
startAt: startAtCurrent,
|
|
endAt: endAtCurrent,
|
|
size: outerRadius,
|
|
majorTickMarksAngle: 45.0,
|
|
minorTickMarksAngle: 5,
|
|
majorTickMarksLength: 0.25,
|
|
minorTickMarksLength: 0.1,
|
|
});
|
|
}
|
|
}
|
|
print("================== HANDLE_ROLL(Mve) <- =======================");
|
|
|
|
}
|
|
});
|
|
|
|
// FUNCTION: CHECK MOVE
|
|
that.checkMove = function() {
|
|
if (SelectionManager.hasSelection()) {
|
|
|
|
// FIXME - this cause problems with editing in the entity properties window
|
|
//SelectionManager._update();
|
|
|
|
if (!Vec3.equal(Camera.getPosition(), lastCameraPosition) ||
|
|
!Quat.equal(Camera.getOrientation(), lastCameraOrientation)) {
|
|
|
|
that.updateRotationHandles();
|
|
}
|
|
}
|
|
};
|
|
|
|
that.checkControllerMove = function() {
|
|
if (SelectionManager.hasSelection()) {
|
|
var controllerPose = getControllerWorldLocation(activeHand, true);
|
|
var hand = (activeHand === Controller.Standard.LeftHand) ? 0 : 1;
|
|
if (controllerPose.valid && lastControllerPoses[hand].valid) {
|
|
if (!Vec3.equal(controllerPose.position, lastControllerPoses[hand].position) ||
|
|
!Vec3.equal(controllerPose.rotation, lastControllerPoses[hand].rotation)) {
|
|
print("setting controller pose");
|
|
that.mouseMoveEvent({});
|
|
}
|
|
}
|
|
lastControllerPoses[hand] = controllerPose;
|
|
}
|
|
};
|
|
|
|
|
|
// FUNCTION DEF(s): Intersection Check Helpers
|
|
function testRayIntersect(queryRay, overlayIncludes, overlayExcludes) {
|
|
var wantDebug = false;
|
|
if ((queryRay === undefined) || (queryRay === null)) {
|
|
if (wantDebug) {
|
|
print("testRayIntersect - EARLY EXIT -> queryRay is undefined OR null!");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
var intersectObj = Overlays.findRayIntersection(queryRay, true, overlayIncludes, overlayExcludes);
|
|
|
|
if (wantDebug) {
|
|
if ( ! overlayIncludes ){
|
|
print("testRayIntersect - no overlayIncludes provided.");
|
|
}
|
|
if ( ! overlayExcludes ){
|
|
print("testRayIntersect - no overlayExcludes provided.");
|
|
}
|
|
print("testRayIntersect - Hit: " + intersectObj.intersects);
|
|
print(" intersectObj.overlayID:" + intersectObj.overlayID + "[" + overlayNames[intersectObj.overlayID] + "]");
|
|
print(" OverlayName: " + overlayNames[intersectObj.overlayID]);
|
|
print(" intersectObj.distance:" + intersectObj.distance);
|
|
print(" intersectObj.face:" + intersectObj.face);
|
|
Vec3.print(" intersectObj.intersection:", intersectObj.intersection);
|
|
}
|
|
|
|
return intersectObj;
|
|
}
|
|
|
|
function checkIntersectWithHUD(queryRay) {
|
|
var intersectObj = testRayIntersect(queryRay, [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID]);
|
|
|
|
return intersectObj;
|
|
}
|
|
|
|
function checkIntersectWithNonSelectionItems(queryRay) {
|
|
var intersectObj = testRayIntersect(queryRay, null, [yawHandle, pitchHandle, rollHandle, selectionBox]);
|
|
|
|
return intersectObj;
|
|
}
|
|
|
|
function checkIntersectWithRotationHandles(queryRay) {
|
|
var intersectObj = testRayIntersect(queryRay, [yawHandle, pitchHandle, rollHandle]);
|
|
|
|
return intersectObj;
|
|
}
|
|
|
|
function checkIntersectWithSelectionBox(queryRay) {
|
|
var intersectObj = testRayIntersect(queryRay, [selectionBox]);
|
|
|
|
return intersectObj;
|
|
}
|
|
|
|
// FUNCTION: MOUSE PRESS EVENT
|
|
that.mousePressEvent = function (event) {
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("=============== eST::MousePressEvent BEG =======================");
|
|
}
|
|
if (!event.isLeftButton && !that.triggered) {
|
|
// if another mouse button than left is pressed ignore it
|
|
return false;
|
|
}
|
|
|
|
var somethingClicked = false;
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
|
|
var results_checkHUD = checkIntersectWithHUD(pickRay);
|
|
if (results_checkHUD.intersects) {
|
|
// mouse clicks on the tablet should override the edit affordances
|
|
return false;
|
|
}
|
|
|
|
entityIconOverlayManager.setIconsSelectable(selectionManager.selections, true);
|
|
|
|
// ignore ray intersection for our selection box and yaw/pitch/roll
|
|
var results_checkNonSelection = checkIntersectWithNonSelectionItems(pickRay);
|
|
if (results_checkNonSelection.intersects) {
|
|
var tool = grabberTools[results_checkNonSelection.overlayID];
|
|
if (tool) {
|
|
if (wantDebug) {
|
|
print("Intersected with known table tool( mode: " + tool.mode + " )");
|
|
}
|
|
activeTool = tool;
|
|
mode = tool.mode;
|
|
somethingClicked = 'tool';
|
|
if (activeTool.onBegin) {
|
|
activeTool.onBegin(event);
|
|
} else if (wantDebug) {
|
|
print(" ActiveTool( " + activeTool.mode + " ) missing onBegin");
|
|
}
|
|
} else {
|
|
mode = "UNKNOWN";
|
|
}//--End_if(tool)
|
|
}//--End_if(results_checkNonSelection.intersects)
|
|
|
|
// if one of the items above was clicked, then we know we are in translate or stretch mode, and we
|
|
// should hide our rotate handles...
|
|
if (somethingClicked) {
|
|
if (wantDebug) {
|
|
print(" Trying to hide PitchYawRoll Handles");
|
|
}
|
|
Overlays.editOverlay(yawHandle, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(pitchHandle, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
visible: false
|
|
});
|
|
|
|
if (mode != "TRANSLATE_UP_DOWN") {
|
|
if(wantDebug){
|
|
print(" Trying to hide GrabberMoveUp");
|
|
}
|
|
Overlays.editOverlay(grabberMoveUp, {
|
|
visible: false
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!somethingClicked) {
|
|
|
|
if (wantDebug) {
|
|
print("rotate handle case...");
|
|
}
|
|
|
|
|
|
// Only intersect versus yaw/pitch/roll.
|
|
var results_checkRotationHandles = checkIntersectWithRotationHandles(pickRay);
|
|
var properties = Entities.getEntityProperties(selectionManager.selections[0]);
|
|
var angles = Quat.safeEulerAngles(properties.rotation);
|
|
var pitch = angles.x;
|
|
var yaw = angles.y;
|
|
var roll = angles.z;
|
|
|
|
//TODO_Case6491: Should these only be updated when we actually touched
|
|
// a handle. (The answer is most likley: Yes) Potentially move chunk
|
|
// to either tool's onBegin or before rayCast here when refactored.
|
|
originalRotation = properties.rotation;
|
|
originalPitch = pitch;
|
|
originalYaw = yaw;
|
|
originalRoll = roll;
|
|
|
|
if (results_checkRotationHandles.intersects) {
|
|
var resultTool = grabberTools[results_checkRotationHandles.overlayID];
|
|
if (wantDebug) {
|
|
print("Intersection detected with handle...");
|
|
}
|
|
if (resultTool) {
|
|
if (wantDebug) {
|
|
print(" " + resultTool.mode);
|
|
}
|
|
activeTool = resultTool;
|
|
somethingClicked = resultTool.mode;
|
|
if(activeTool.onBegin) {
|
|
activeTool.onBegin(event, results_checkRotationHandles.intersection);
|
|
} else if (wantDebug) {
|
|
print(" ActiveTool( " + activeTool.mode + " ) missing onBegin");
|
|
}
|
|
}//--End_If(resultTool)
|
|
}//--End_If(results_checkRotationHandles.intersects)
|
|
|
|
if (somethingClicked) {
|
|
|
|
if (wantDebug) {
|
|
print(" somethingClicked:" + somethingClicked);
|
|
print(" mode:" + mode);
|
|
print(" Trying to hide PitchYawRoll Handles");
|
|
}
|
|
Overlays.editOverlay(yawHandle, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(pitchHandle, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
visible: false
|
|
});
|
|
|
|
if(wantDebug){
|
|
print(" Trying to hide Non-Light GrabberHandles");
|
|
}
|
|
|
|
Overlays.editOverlay(grabberCloner, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberMoveUp, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberLBN, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberLBF, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberRBN, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberRBF, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberLTN, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberLTF, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberRTN, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberRTF, {
|
|
visible: false
|
|
});
|
|
|
|
Overlays.editOverlay(grabberTOP, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberBOTTOM, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberLEFT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberRIGHT, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberNEAR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberFAR, {
|
|
visible: false
|
|
});
|
|
|
|
Overlays.editOverlay(grabberEdgeTR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeTL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeTF, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeTN, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBF, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeBN, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeNR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeNL, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeFR, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(grabberEdgeFL, {
|
|
visible: false
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!somethingClicked) {
|
|
// Only intersect versus selectionBox.
|
|
var results_checkSelectionBox = checkIntersectWithSelectionBox( pickRay );
|
|
if (results_checkSelectionBox.intersects) {
|
|
activeTool = translateXZTool;
|
|
if(wantDebug){
|
|
print("Clicked selectionBox, Activating Tool: " + activeTool.mode );
|
|
}
|
|
var intersectInfo = {
|
|
queryRay: pickRay,
|
|
results: results_checkSelectionBox
|
|
};
|
|
activeTool.onBegin(event, null, intersectInfo);
|
|
somethingClicked = 'selectionBox';
|
|
}
|
|
}
|
|
|
|
if (somethingClicked) {
|
|
if (wantDebug) {
|
|
print("mousePressEvent()...... " + somethingClicked);
|
|
print(" mode: " + mode);
|
|
}
|
|
}
|
|
|
|
// reset everything as intersectable...
|
|
// TODO: we could optimize this since some of these were already flipped back(i.e: just get rid of this)
|
|
if (wantDebug) {
|
|
print("Trying to set SelectionBox & PitchYawRoll Handles to NOT_IGNORE Rays");
|
|
}
|
|
Overlays.editOverlay(selectionBox, {
|
|
ignoreRayIntersection: false
|
|
});
|
|
Overlays.editOverlay(yawHandle, {
|
|
ignoreRayIntersection: false
|
|
});
|
|
Overlays.editOverlay(pitchHandle, {
|
|
ignoreRayIntersection: false
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
ignoreRayIntersection: false
|
|
});
|
|
|
|
if (wantDebug) {
|
|
print("=============== eST::MousePressEvent END =======================");
|
|
}
|
|
|
|
return somethingClicked;
|
|
};
|
|
|
|
// FUNCTION: MOUSE MOVE EVENT
|
|
that.mouseMoveEvent = function(event) {
|
|
var wantDebug = false;
|
|
if(wantDebug){
|
|
print( "=============== eST::MouseMoveEvent BEG =======================");
|
|
}
|
|
if (activeTool) {
|
|
if (wantDebug) {
|
|
print(" Trigger ActiveTool( " + activeTool.mode + " )'s onMove");
|
|
}
|
|
activeTool.onMove(event);
|
|
|
|
if (wantDebug) {
|
|
print(" Trigger SelectionManager::update");
|
|
}
|
|
SelectionManager._update();
|
|
|
|
if (wantDebug) {
|
|
print("=============== eST::MouseMoveEvent END =======================");
|
|
}
|
|
//--EARLY EXIT--( Move handled via active tool)
|
|
return true;
|
|
}
|
|
|
|
// if no tool is active, then just look for handles to highlight...
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
var result = Overlays.findRayIntersection(pickRay);
|
|
var pickedColor;
|
|
var pickedAlpha;
|
|
var highlightNeeded = false;
|
|
|
|
if (result.intersects) {
|
|
switch (result.overlayID) {
|
|
case yawHandle:
|
|
case pitchHandle:
|
|
case rollHandle:
|
|
pickedColor = handleColor;
|
|
pickedAlpha = handleAlpha;
|
|
highlightNeeded = true;
|
|
break;
|
|
|
|
case grabberMoveUp:
|
|
pickedColor = handleColor;
|
|
pickedAlpha = handleAlpha;
|
|
highlightNeeded = true;
|
|
break;
|
|
|
|
case grabberLBN:
|
|
case grabberLBF:
|
|
case grabberRBN:
|
|
case grabberRBF:
|
|
case grabberLTN:
|
|
case grabberLTF:
|
|
case grabberRTN:
|
|
case grabberRTF:
|
|
pickedColor = grabberColorCorner;
|
|
pickedAlpha = grabberAlpha;
|
|
highlightNeeded = true;
|
|
break;
|
|
|
|
case grabberTOP:
|
|
case grabberBOTTOM:
|
|
case grabberLEFT:
|
|
case grabberRIGHT:
|
|
case grabberNEAR:
|
|
case grabberFAR:
|
|
pickedColor = grabberColorFace;
|
|
pickedAlpha = grabberAlpha;
|
|
highlightNeeded = true;
|
|
break;
|
|
|
|
case grabberEdgeTR:
|
|
case grabberEdgeTL:
|
|
case grabberEdgeTF:
|
|
case grabberEdgeTN:
|
|
case grabberEdgeBR:
|
|
case grabberEdgeBL:
|
|
case grabberEdgeBF:
|
|
case grabberEdgeBN:
|
|
case grabberEdgeNR:
|
|
case grabberEdgeNL:
|
|
case grabberEdgeFR:
|
|
case grabberEdgeFL:
|
|
case grabberSpotLightRadius:
|
|
case grabberSpotLightT:
|
|
case grabberSpotLightB:
|
|
case grabberSpotLightL:
|
|
case grabberSpotLightR:
|
|
case grabberPointLightT:
|
|
case grabberPointLightB:
|
|
case grabberPointLightR:
|
|
case grabberPointLightL:
|
|
case grabberPointLightN:
|
|
case grabberPointLightF:
|
|
pickedColor = grabberColorEdge;
|
|
pickedAlpha = grabberAlpha;
|
|
highlightNeeded = true;
|
|
break;
|
|
|
|
case grabberCloner:
|
|
pickedColor = grabberColorCloner;
|
|
pickedAlpha = grabberAlpha;
|
|
highlightNeeded = true;
|
|
break;
|
|
|
|
default:
|
|
if (previousHandle) {
|
|
Overlays.editOverlay(previousHandle, {
|
|
color: previousHandleColor,
|
|
alpha: previousHandleAlpha
|
|
});
|
|
previousHandle = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (highlightNeeded) {
|
|
if (previousHandle) {
|
|
Overlays.editOverlay(previousHandle, {
|
|
color: previousHandleColor,
|
|
alpha: previousHandleAlpha
|
|
});
|
|
previousHandle = false;
|
|
}
|
|
Overlays.editOverlay(result.overlayID, {
|
|
color: highlightedHandleColor,
|
|
alpha: highlightedHandleAlpha
|
|
});
|
|
previousHandle = result.overlayID;
|
|
previousHandleColor = pickedColor;
|
|
previousHandleAlpha = pickedAlpha;
|
|
}
|
|
|
|
} else {
|
|
if (previousHandle) {
|
|
Overlays.editOverlay(previousHandle, {
|
|
color: previousHandleColor,
|
|
alpha: previousHandleAlpha
|
|
});
|
|
previousHandle = false;
|
|
}
|
|
}
|
|
|
|
if(wantDebug){
|
|
print("=============== eST::MouseMoveEvent END =======================");
|
|
}
|
|
return false;
|
|
};
|
|
|
|
// FUNCTION: UPDATE HANDLE SIZES
|
|
that.updateHandleSizes = function() {
|
|
if (selectionManager.hasSelection()) {
|
|
var diff = Vec3.subtract(selectionManager.worldPosition, Camera.getPosition());
|
|
var grabberSize = Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 5;
|
|
var dimensions = SelectionManager.worldDimensions;
|
|
var avgDimension = (dimensions.x + dimensions.y + dimensions.z) / 3;
|
|
grabberSize = Math.min(grabberSize, avgDimension / 10);
|
|
|
|
for (var i = 0; i < stretchHandles.length; i++) {
|
|
Overlays.editOverlay(stretchHandles[i], {
|
|
size: grabberSize,
|
|
});
|
|
}
|
|
var handleSize = Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 7;
|
|
handleSize = Math.min(handleSize, avgDimension / 3);
|
|
|
|
Overlays.editOverlay(yawHandle, {
|
|
scale: handleSize,
|
|
});
|
|
Overlays.editOverlay(pitchHandle, {
|
|
scale: handleSize,
|
|
});
|
|
Overlays.editOverlay(rollHandle, {
|
|
scale: handleSize,
|
|
});
|
|
var pos = Vec3.sum(grabberMoveUpPosition, {
|
|
x: 0,
|
|
y: Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO * 3,
|
|
z: 0
|
|
});
|
|
Overlays.editOverlay(grabberMoveUp, {
|
|
position: pos,
|
|
scale: handleSize / 1.25,
|
|
});
|
|
}
|
|
};
|
|
Script.update.connect(that.updateHandleSizes);
|
|
|
|
// FUNCTION: MOUSE RELEASE EVENT
|
|
that.mouseReleaseEvent = function(event) {
|
|
var wantDebug = false;
|
|
if(wantDebug){
|
|
print("=============== eST::MouseReleaseEvent BEG =======================");
|
|
}
|
|
var showHandles = false;
|
|
if (activeTool) {
|
|
if( activeTool.onEnd ) {
|
|
if(wantDebug){
|
|
print(" Triggering ActiveTool( " + activeTool.mode + " )'s onEnd");
|
|
}
|
|
activeTool.onEnd(event);
|
|
}else if(wantDebug){
|
|
print(" ActiveTool( " + activeTool.mode + " )'s missing onEnd");
|
|
}
|
|
}
|
|
|
|
// hide our rotation overlays..., and show our handles
|
|
if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL") {
|
|
if(wantDebug){
|
|
print(" Triggering hide of RotateOverlays");
|
|
}
|
|
Overlays.editOverlay(rotateOverlayTarget, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: false
|
|
});
|
|
|
|
}
|
|
|
|
showHandles = (mode != "UNKNOWN");//<base on prior mode
|
|
mode = "UNKNOWN";
|
|
activeTool = null;
|
|
|
|
// if something is selected, then reset the "original" properties for any potential next click+move operation
|
|
if (SelectionManager.hasSelection()) {
|
|
if (showHandles) {
|
|
if(wantDebug){
|
|
print(" Triggering that.select");
|
|
}
|
|
that.select(SelectionManager.selections[0], event);
|
|
}
|
|
}
|
|
|
|
if(wantDebug){
|
|
print("=============== eST::MouseReleaseEvent END =======================");
|
|
}
|
|
};
|
|
|
|
// NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these:
|
|
// Controller.mousePressEvent.connect(that.mousePressEvent);
|
|
// Controller.mouseMoveEvent.connect(that.mouseMoveEvent);
|
|
Controller.mouseReleaseEvent.connect(that.mouseReleaseEvent);
|
|
|
|
|
|
|
|
return that;
|
|
|
|
}());
|