mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 21:36:45 +02:00
Rotation tools' onMove methods now use rayPlaneIntersection rather than using the giant invisible rotateOverlayTarget. It can likely be entirely removed in the next commit. tool.onBegin's signature is now (event, pickRay, pickResult, ...) -- this allows us to avoid recomputing the ray or intersection when unnecessary. translateXZTool is now a part of the grabberTools array; addGrabberTool and addStretchTool have been modified to return the tool reference (and not disassemble and reassemble the tools, so they can keep their own local functions and state). This does make the array potentially less type-uniform, which may (?) undo some javascript optimizations, but allows us to eventually remove some state -- and they're only 1x/frame methods. We now compute rotationNormal in rotation tool onBegin, rather than having many different normals lying around. Merged the final branches in mousePressEvent. Also fixed issue with mode TRANSLATE_XZ test within updateRotationHandles. Reviewed-by: LaShonda Hopper <lashonda@1stplayable.com>
4232 lines
135 KiB
JavaScript
4232 lines
135 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 rotZero;
|
|
var rotationNormal;
|
|
|
|
|
|
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] = tool;
|
|
return tool;
|
|
}
|
|
|
|
|
|
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
|
|
});
|
|
|
|
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
|
|
});
|
|
|
|
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
|
|
});
|
|
|
|
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
|
|
});
|
|
|
|
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_XZ") {
|
|
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: SET ROTATION HANDLES VISIBLE
|
|
that.setRotationHandlesVisible = function(isVisible) {
|
|
var visibilityUpdate = { visible: isVisible };
|
|
Overlays.editOverlay(yawHandle, visibilityUpdate);
|
|
Overlays.editOverlay(pitchHandle, visibilityUpdate);
|
|
Overlays.editOverlay(rollHandle, visibilityUpdate);
|
|
};
|
|
|
|
// FUNCTION: SET STRETCH HANDLES VISIBLE
|
|
that.setStretchHandlesVisible = function(isVisible) {
|
|
var numHandles = stretchHandles.length;
|
|
var visibilityUpdate = { visible: isVisible };
|
|
for (var handleIndex = 0; handleIndex < numHandles; ++handleIndex) {
|
|
Overlays.editOverlay(stretchHandles[ handleIndex ], visibilityUpdate);
|
|
}
|
|
};
|
|
|
|
// FUNCTION: SET GRABBER MOVE UP VISIBLE
|
|
that.setGrabberMoveUpVisible = function(isVisible) {
|
|
Overlays.editOverlay(grabberMoveUp, { 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 = addGrabberTool(selectionBox,{
|
|
mode: 'TRANSLATE_XZ',
|
|
pickPlanePosition: { x: 0, y: 0, z: 0 },
|
|
greatestDimension: 0.0,
|
|
startingDistance: 0.0,
|
|
startingElevation: 0.0,
|
|
onBegin: function(event, pickRay, pickResult, doClone) {
|
|
var wantDebug = false;
|
|
if(wantDebug){
|
|
print("================== TRANSLATE_XZ(Beg) -> =======================");
|
|
Vec3.print(" pickRay", pickRay);
|
|
Vec3.print(" pickRay.origin", pickRay.origin);
|
|
Vec3.print(" pickResult.intersection", pickResult.intersection);
|
|
}
|
|
|
|
SelectionManager.saveProperties();
|
|
that.setRotationHandlesVisible( false );
|
|
that.setGrabberMoveUpVisible( false );
|
|
|
|
startPosition = SelectionManager.worldPosition;
|
|
mode = translateXZTool.mode; // Note this overrides mode = "CLONE"
|
|
|
|
translateXZTool.pickPlanePosition = pickResult.intersection;
|
|
translateXZTool.greatestDimension = Math.max(Math.max(SelectionManager.worldDimensions.x, SelectionManager.worldDimensions.y), SelectionManager.worldDimensions.z);
|
|
translateXZTool.startingDistance = Vec3.distance(pickRay.origin, SelectionManager.position);
|
|
translateXZTool.startingElevation = translateXZTool.elevation(pickRay.origin, translateXZTool.pickPlanePosition);
|
|
if (wantDebug) {
|
|
print(" longest dimension: " + translateXZTool.greatestDimension);
|
|
print(" starting distance: " + translateXZTool.startingDistance);
|
|
print(" starting elevation: " + translateXZTool.startingElevation);
|
|
}
|
|
|
|
initialXZPick = rayPlaneIntersection(pickRay, 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 || doClone) {
|
|
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, pickResult) {
|
|
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();
|
|
that.setGrabberMoveUpVisible( true );
|
|
that.setRotationHandlesVisible( false );
|
|
|
|
// 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, pickRay, pickResult) {
|
|
var doClone = true;
|
|
translateXZTool.onBegin(event,pickRay,pickResult,doClone);
|
|
},
|
|
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
|
|
// @return: tool obj
|
|
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, pickRay, pickResult) {
|
|
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);
|
|
|
|
return 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);
|
|
}
|
|
}
|
|
|
|
function helperRotationHandleOnBegin( event, pickRay, rotAroundAxis, rotCenter, handleRotation ) {
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("================== " + mode + "(rotation helper onBegin) -> =======================");
|
|
}
|
|
|
|
SelectionManager.saveProperties();
|
|
that.setRotationHandlesVisible( false );
|
|
that.setStretchHandlesVisible( false );
|
|
that.setGrabberMoveUpVisible( false );
|
|
|
|
initialPosition = SelectionManager.worldPosition;
|
|
rotationNormal = { x: 0, y: 0, z: 0 };
|
|
rotationNormal[rotAroundAxis] = 1;
|
|
|
|
// 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: handleRotation,
|
|
position: rotCenter,
|
|
size: innerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: innerAlpha,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: true,
|
|
rotation: handleRotation,
|
|
position: rotCenter,
|
|
size: outerRadius,
|
|
innerRadius: 0.9,
|
|
startAt: 0,
|
|
endAt: 360,
|
|
alpha: outerAlpha,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: true,
|
|
rotation: handleRotation,
|
|
position: rotCenter,
|
|
size: outerRadius,
|
|
startAt: 0,
|
|
endAt: 0,
|
|
innerRadius: 0.9,
|
|
});
|
|
|
|
Overlays.editOverlay(rotateOverlayTarget, {
|
|
visible: true,
|
|
rotation: handleRotation,
|
|
position: rotCenter
|
|
});
|
|
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: true,
|
|
});
|
|
|
|
updateRotationDegreesOverlay(0, handleRotation, rotCenter);
|
|
|
|
// editOverlays may not have committed rotation changes.
|
|
// Compute zero position based on where the overlay will be eventually.
|
|
var result = rayPlaneIntersection( pickRay, rotCenter, rotationNormal );
|
|
// In case of a parallel ray, this will be null, which will cause early-out
|
|
// in the onMove helper.
|
|
rotZero = result;
|
|
|
|
if (wantDebug) {
|
|
print("================== " + mode + "(rotation helper onBegin) <- =======================");
|
|
}
|
|
}//--End_Function( helperRotationHandleOnBegin )
|
|
|
|
function helperRotationHandleOnMove( event, rotAroundAxis, rotCenter, handleRotation ) {
|
|
|
|
if ( ! rotZero ) {
|
|
print("ERROR( handleRotationHandleOnMove ) - Invalid RotationZero Specified (missed rotation target plane?)" );
|
|
|
|
//--EARLY EXIT--
|
|
return;
|
|
}
|
|
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("================== "+ mode + "(rotation helper onMove) -> =======================");
|
|
Vec3.print(" rotZero: ", rotZero);
|
|
}
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
Overlays.editOverlay(selectionBox, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(baseOfEntityProjectionOverlay, {
|
|
visible: false
|
|
});
|
|
|
|
var result = rayPlaneIntersection( pickRay, rotCenter, rotationNormal );
|
|
if (result) {
|
|
var centerToZero = Vec3.subtract(rotZero, rotCenter);
|
|
var centerToIntersect = Vec3.subtract(result, rotCenter);
|
|
if (wantDebug) {
|
|
Vec3.print(" RotationNormal: ", rotationNormal);
|
|
Vec3.print(" rotZero: ", rotZero);
|
|
Vec3.print(" rotCenter: ", rotCenter);
|
|
Vec3.print(" intersect: ", result);
|
|
Vec3.print(" centerToZero: ", centerToZero);
|
|
Vec3.print(" centerToIntersect: ", centerToIntersect);
|
|
}
|
|
// Note: orientedAngle which wants normalized centerToZero and centerToIntersect
|
|
// handles that internally, so it's to pass unnormalized vectors here.
|
|
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
|
|
|
|
var distanceFromCenter = Vec3.length(centerToIntersect);
|
|
var snapToInner = distanceFromCenter < innerRadius;
|
|
var snapAngle = snapToInner ? innerSnapAngle : 1.0;
|
|
angleFromZero = Math.floor(angleFromZero / snapAngle) * snapAngle;
|
|
|
|
var vec3Degrees = { x: 0, y: 0, z: 0 };
|
|
vec3Degrees[rotAroundAxis] = angleFromZero;
|
|
var rotChange = Quat.fromVec3Degrees( vec3Degrees );
|
|
updateSelectionsRotation( rotChange );
|
|
|
|
updateRotationDegreesOverlay(angleFromZero, handleRotation, rotCenter);
|
|
|
|
// 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,
|
|
});
|
|
}
|
|
}//--End_If( results.intersects )
|
|
|
|
if (wantDebug) {
|
|
print("================== "+ mode + "(rotation helper onMove) <- =======================");
|
|
}
|
|
}//--End_Function( helperRotationHandleOnMove )
|
|
|
|
function helperRotationHandleOnEnd() {
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("================== " + mode + "(onEnd) -> =======================");
|
|
}
|
|
Overlays.editOverlay(rotateOverlayInner, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayOuter, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotateOverlayCurrent, {
|
|
visible: false
|
|
});
|
|
Overlays.editOverlay(rotationDegreesDisplay, {
|
|
visible: false
|
|
});
|
|
|
|
pushCommandForSelections();
|
|
|
|
if (wantDebug) {
|
|
print("================== " + mode + "(onEnd) <- =======================");
|
|
}
|
|
}//--End_Function( helperRotationHandleOnEnd )
|
|
|
|
|
|
// YAW GRABBER TOOL DEFINITION
|
|
var initialPosition = SelectionManager.worldPosition;
|
|
addGrabberTool(yawHandle, {
|
|
mode: "ROTATE_YAW",
|
|
onBegin: function(event, pickRay, pickResult) {
|
|
helperRotationHandleOnBegin( event, pickRay, "y", yawCenter, yawHandleRotation );
|
|
},
|
|
onEnd: function(event, reason) {
|
|
helperRotationHandleOnEnd();
|
|
},
|
|
onMove: function(event) {
|
|
helperRotationHandleOnMove( event, "y", yawCenter, yawHandleRotation );
|
|
}
|
|
});
|
|
|
|
|
|
// PITCH GRABBER TOOL DEFINITION
|
|
addGrabberTool(pitchHandle, {
|
|
mode: "ROTATE_PITCH",
|
|
onBegin: function(event, pickRay, pickResult) {
|
|
helperRotationHandleOnBegin( event, pickRay, "x", pitchCenter, pitchHandleRotation );
|
|
},
|
|
onEnd: function(event, reason) {
|
|
helperRotationHandleOnEnd();
|
|
},
|
|
onMove: function (event) {
|
|
helperRotationHandleOnMove( event, "x", pitchCenter, pitchHandleRotation );
|
|
}
|
|
});
|
|
|
|
|
|
// ROLL GRABBER TOOL DEFINITION
|
|
addGrabberTool(rollHandle, {
|
|
mode: "ROTATE_ROLL",
|
|
onBegin: function(event, pickRay, pickResult) {
|
|
helperRotationHandleOnBegin( event, pickRay, "z", rollCenter, rollHandleRotation );
|
|
},
|
|
onEnd: function (event, reason) {
|
|
helperRotationHandleOnEnd();
|
|
},
|
|
onMove: function(event) {
|
|
helperRotationHandleOnMove( event, "z", rollCenter, rollHandleRotation );
|
|
}
|
|
});
|
|
|
|
// 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: MOUSE PRESS EVENT
|
|
that.mousePressEvent = function (event) {
|
|
var wantDebug = false;
|
|
if (wantDebug) {
|
|
print("=============== eST::MousePressEvent BEG =======================");
|
|
}
|
|
if (!event.isLeftButton && !that.triggered) {
|
|
//--EARLY EXIT-(if another mouse button than left is pressed ignore it)
|
|
return false;
|
|
}
|
|
|
|
var pickRay = generalComputePickRay(event.x, event.y);
|
|
//TODO_Case6491: Move this out to setup just to make it once
|
|
var interactiveOverlays = [HMD.tabletID, HMD.tabletScreenID, HMD.homeButtonID, selectionBox];
|
|
for (var key in grabberTools) {
|
|
if (grabberTools.hasOwnProperty(key)) {
|
|
interactiveOverlays.push( key );
|
|
}
|
|
}
|
|
|
|
// Start with unknown mode, in case no tool can handle this.
|
|
mode = "UNKNOWN";
|
|
|
|
var results = testRayIntersect( pickRay, interactiveOverlays );
|
|
if ( results.intersects ){
|
|
var hitOverlayID = results.overlayID;
|
|
if ( (hitOverlayID == HMD.tabletID) || (hitOverlayID == HMD.tabletScreenID) || (hitOverlayID == HMD.homeButtonID) ) {
|
|
//--EARLY EXIT-(mouse clicks on the tablet should override the edit affordances)
|
|
return false;
|
|
}
|
|
|
|
entityIconOverlayManager.setIconsSelectable(selectionManager.selections, true);
|
|
//TODO_Case6491: Merge if..else( selectionBox ) when onBegin of transXZ is normalized.
|
|
|
|
var hitTool = grabberTools[ hitOverlayID ];
|
|
if ( hitTool ) {
|
|
activeTool = hitTool;
|
|
mode = activeTool.mode;
|
|
if (activeTool.onBegin) {
|
|
activeTool.onBegin(event, pickRay, results);
|
|
} else {
|
|
print("ERROR: entitySelectionTool.mousePressEvent - ActiveTool( " + activeTool.mode + " ) missing onBegin");
|
|
}
|
|
} else {
|
|
print("ERROR: entitySelectionTool.mousePressEvent - Hit unexpected object, check interactiveOverlays");
|
|
}//--End_if( hitTool )
|
|
}//--End_If( results.intersects )
|
|
|
|
if (wantDebug) {
|
|
print(" SelectionDisplay.mode: " + mode );
|
|
print("=============== eST::MousePressEvent END =======================");
|
|
}
|
|
|
|
// If mode is known then we successfully handled this;
|
|
// otherwise, we're missing a tool or a tool.onBegin.
|
|
return (mode != "UNKNOWN");
|
|
};
|
|
|
|
// 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;
|
|
|
|
}());
|