mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 12:23:24 +02:00
Merge pull request #3596 from huffman/entity-tools
Camera functionality for entity edit tools
This commit is contained in:
commit
102d02d396
3 changed files with 255 additions and 3 deletions
172
examples/libraries/entityCameraTool.js
Normal file
172
examples/libraries/entityCameraTool.js
Normal file
|
@ -0,0 +1,172 @@
|
|||
var MOUSE_SENSITIVITY = 0.5;
|
||||
var SCROLL_SENSITIVITY = 0.05;
|
||||
var PAN_ZOOM_SCALE_RATIO = 0.1;
|
||||
var ZOOM_SCALING = 0.02;
|
||||
|
||||
var MIN_ZOOM_DISTANCE = 0.01;
|
||||
var MAX_ZOOM_DISTANCE = 100;
|
||||
|
||||
var MODE_INACTIVE = null;
|
||||
var MODE_ORBIT = 'orbit';
|
||||
var MODE_PAN = 'pan';
|
||||
|
||||
var INITIAL_ZOOM_DISTANCE = 4;
|
||||
|
||||
EntityCameraTool = function() {
|
||||
var that = {};
|
||||
|
||||
that.enabled = false;
|
||||
that.mode = MODE_INACTIVE;
|
||||
|
||||
that.zoomDistance = INITIAL_ZOOM_DISTANCE;
|
||||
that.yaw = 0;
|
||||
that.pitch = 0;
|
||||
that.focalPoint = { x: 0, y: 0, z: 0 };
|
||||
|
||||
that.previousCameraMode = null;
|
||||
|
||||
that.lastMousePosition = { x: 0, y: 0 };
|
||||
|
||||
that.enable = function() {
|
||||
if (that.enabled) return;
|
||||
that.enabled = true;
|
||||
that.mode = MODE_INACTIVE;
|
||||
|
||||
// Pick a point INITIAL_ZOOM_DISTANCE in front of the camera to use
|
||||
// as a focal point
|
||||
that.zoomDistance = INITIAL_ZOOM_DISTANCE;
|
||||
var focalPoint = Vec3.sum(Camera.getPosition(),
|
||||
Vec3.multiply(that.zoomDistance, Quat.getFront(Camera.getOrientation())));
|
||||
|
||||
// Determine the correct yaw and pitch to keep the camera in the same location
|
||||
var dPos = Vec3.subtract(focalPoint, Camera.getPosition());
|
||||
var xzDist = Math.sqrt(dPos.x * dPos.x + dPos.z * dPos.z);
|
||||
|
||||
that.pitch = -Math.atan2(dPos.y, xzDist) * 180 / Math.PI;
|
||||
that.yaw = Math.atan2(dPos.x, dPos.z) * 180 / Math.PI;
|
||||
|
||||
that.setFocalPoint(focalPoint);
|
||||
that.previousCameraMode = Camera.getMode();
|
||||
Camera.setMode("independent");
|
||||
|
||||
that.updateCamera();
|
||||
}
|
||||
|
||||
that.disable = function() {
|
||||
if (!that.enabled) return;
|
||||
that.enabled = false;
|
||||
that.mode = MODE_INACTIVE;
|
||||
|
||||
Camera.setMode(that.previousCameraMode);
|
||||
}
|
||||
|
||||
that.focus = function(entityProperties) {
|
||||
that.setFocalPoint(entityProperties.position);
|
||||
|
||||
that.updateCamera();
|
||||
}
|
||||
|
||||
that.moveFocalPoint = function(dPos) {
|
||||
that.setFocalPoint(Vec3.sum(that.focalPoint, dPos));
|
||||
}
|
||||
|
||||
that.setFocalPoint = function(pos) {
|
||||
that.focalPoint = pos
|
||||
that.updateCamera();
|
||||
}
|
||||
|
||||
that.mouseMoveEvent = function(event) {
|
||||
if (that.enabled && that.mode != MODE_INACTIVE) {
|
||||
if (that.mode == MODE_ORBIT) {
|
||||
var diffX = event.x - that.lastMousePosition.x;
|
||||
var diffY = event.y - that.lastMousePosition.y;
|
||||
that.yaw -= MOUSE_SENSITIVITY * (diffX / 5.0)
|
||||
that.pitch += MOUSE_SENSITIVITY * (diffY / 10.0)
|
||||
|
||||
while (that.yaw > 180.0) that.yaw -= 360;
|
||||
while (that.yaw < -180.0) that.yaw += 360;
|
||||
|
||||
if (that.pitch > 90) that.pitch = 90;
|
||||
if (that.pitch < -90) that.pitch = -90;
|
||||
|
||||
that.updateCamera();
|
||||
} else if (that.mode == MODE_PAN) {
|
||||
var diffX = event.x - that.lastMousePosition.x;
|
||||
var diffY = event.y - that.lastMousePosition.y;
|
||||
|
||||
var up = Quat.getUp(Camera.getOrientation());
|
||||
var right = Quat.getRight(Camera.getOrientation());
|
||||
|
||||
up = Vec3.multiply(up, diffY * 0.01 * PAN_ZOOM_SCALE_RATIO * that.zoomDistance);
|
||||
right = Vec3.multiply(right, -diffX * 0.01 * PAN_ZOOM_SCALE_RATIO * that.zoomDistance);
|
||||
|
||||
var dPosition = Vec3.sum(up, right);
|
||||
|
||||
that.moveFocalPoint(dPosition);
|
||||
}
|
||||
that.lastMousePosition.x = event.x;
|
||||
that.lastMousePosition.y = event.y;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
that.mousePressEvent = function(event) {
|
||||
if (!that.enabled) return;
|
||||
|
||||
if (event.isRightButton || (event.isLeftButton && event.isControl && !event.isShifted)) {
|
||||
that.mode = MODE_ORBIT;
|
||||
that.lastMousePosition.x = event.x;
|
||||
that.lastMousePosition.y = event.y;
|
||||
return true;
|
||||
} else if (event.isMiddleButton || (event.isLeftButton && event.isControl && event.isShifted)) {
|
||||
that.mode = MODE_PAN;
|
||||
that.lastMousePosition.x = event.x;
|
||||
that.lastMousePosition.y = event.y;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
that.mouseReleaseEvent = function(event) {
|
||||
if (!that.enabled) return;
|
||||
|
||||
that.mode = MODE_INACTIVE;
|
||||
}
|
||||
|
||||
that.wheelEvent = function(event) {
|
||||
if (!that.enabled) return;
|
||||
|
||||
var dZoom = -event.delta * SCROLL_SENSITIVITY;
|
||||
|
||||
// Scale based on current zoom level
|
||||
dZoom *= that.zoomDistance * ZOOM_SCALING;
|
||||
|
||||
that.zoomDistance = Math.max(Math.min(that.zoomDistance + dZoom, MAX_ZOOM_DISTANCE), MIN_ZOOM_DISTANCE);
|
||||
|
||||
that.updateCamera();
|
||||
}
|
||||
|
||||
that.updateCamera = function() {
|
||||
if (!that.enabled) return;
|
||||
|
||||
var yRot = Quat.angleAxis(that.yaw, { x: 0, y: 1, z: 0 });
|
||||
var xRot = Quat.angleAxis(that.pitch, { x: 1, y: 0, z: 0 });
|
||||
var q = Quat.multiply(yRot, xRot);
|
||||
|
||||
var pos = Vec3.multiply(Quat.getFront(q), that.zoomDistance);
|
||||
Camera.setPosition(Vec3.sum(that.focalPoint, pos));
|
||||
|
||||
yRot = Quat.angleAxis(that.yaw - 180, { x: 0, y: 1, z: 0 });
|
||||
xRot = Quat.angleAxis(-that.pitch, { x: 1, y: 0, z: 0 });
|
||||
q = Quat.multiply(yRot, xRot);
|
||||
|
||||
Camera.setOrientation(q);
|
||||
}
|
||||
|
||||
Controller.wheelEvent.connect(that.wheelEvent);
|
||||
|
||||
return that;
|
||||
}
|
|
@ -17,6 +17,8 @@ SelectionDisplay = (function () {
|
|||
var that = {};
|
||||
|
||||
var MINIMUM_DIMENSION = 0.001;
|
||||
|
||||
var GRABBER_DISTANCE_TO_SIZE_RATIO = 0.015;
|
||||
|
||||
var mode = "UNKNOWN";
|
||||
var overlayNames = new Array();
|
||||
|
@ -174,6 +176,34 @@ SelectionDisplay = (function () {
|
|||
var grabberEdgeFR = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
||||
var grabberEdgeFL = Overlays.addOverlay("cube", grabberPropertiesEdge);
|
||||
|
||||
var cornerEdgeFaceGrabbers = [
|
||||
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,
|
||||
];
|
||||
|
||||
var baseOverlayAngles = { x: 0, y: 0, z: 0 };
|
||||
var baseOverlayRotation = Quat.fromVec3Degrees(baseOverlayAngles);
|
||||
|
@ -2423,6 +2453,19 @@ SelectionDisplay = (function () {
|
|||
return true;
|
||||
};
|
||||
|
||||
that.updateHandleSizes = function() {
|
||||
if (selectedEntityProperties) {
|
||||
var diff = Vec3.subtract(selectedEntityProperties.position, Camera.getPosition());
|
||||
var grabberSize = Vec3.length(diff) * GRABBER_DISTANCE_TO_SIZE_RATIO;
|
||||
for (var i = 0; i < cornerEdgeFaceGrabbers.length; i++) {
|
||||
Overlays.editOverlay(cornerEdgeFaceGrabbers[i], {
|
||||
size: grabberSize,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Script.update.connect(that.updateHandleSizes);
|
||||
|
||||
that.mouseReleaseEvent = function(event) {
|
||||
var showHandles = false;
|
||||
// hide our rotation overlays..., and show our handles
|
||||
|
|
|
@ -31,6 +31,9 @@ Script.include("libraries/ToolTip.js");
|
|||
Script.include("libraries/entityPropertyDialogBox.js");
|
||||
var entityPropertyDialogBox = EntityPropertyDialogBox;
|
||||
|
||||
Script.include("libraries/entityCameraTool.js");
|
||||
var entityCameraTool = new EntityCameraTool();
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
var toolIconUrl = HIFI_PUBLIC_BUCKET + "images/tools/";
|
||||
var toolHeight = 50;
|
||||
|
@ -163,6 +166,9 @@ var toolBar = (function () {
|
|||
Overlays.editOverlay(loadFileMenuItem, { visible: active });
|
||||
}
|
||||
|
||||
var RESIZE_INTERVAL = 50;
|
||||
var RESIZE_TIMEOUT = 20000;
|
||||
var RESIZE_MAX_CHECKS = RESIZE_TIMEOUT / RESIZE_INTERVAL;
|
||||
function addModel(url) {
|
||||
var position;
|
||||
|
||||
|
@ -176,6 +182,27 @@ var toolBar = (function () {
|
|||
modelURL: url
|
||||
});
|
||||
print("Model added: " + url);
|
||||
|
||||
var checkCount = 0;
|
||||
function resize() {
|
||||
var entityProperties = Entities.getEntityProperties(entityId);
|
||||
var naturalDimensions = entityProperties.naturalDimensions;
|
||||
|
||||
checkCount++;
|
||||
|
||||
if (naturalDimensions.x == 0 && naturalDimensions.y == 0 && naturalDimensions.z == 0) {
|
||||
if (checkCount < RESIZE_MAX_CHECKS) {
|
||||
Script.setTimeout(resize, RESIZE_INTERVAL);
|
||||
} else {
|
||||
print("Resize failed: timed out waiting for model (" + url + ") to load");
|
||||
}
|
||||
} else {
|
||||
entityProperties.dimensions = naturalDimensions;
|
||||
Entities.editEntity(entityId, entityProperties);
|
||||
}
|
||||
}
|
||||
|
||||
Script.setTimeout(resize, RESIZE_INTERVAL);
|
||||
} else {
|
||||
print("Can't add model: Model would be out of bounds.");
|
||||
}
|
||||
|
@ -217,6 +244,9 @@ var toolBar = (function () {
|
|||
isActive = !isActive;
|
||||
if (!isActive) {
|
||||
selectionDisplay.unselectAll();
|
||||
entityCameraTool.disable();
|
||||
} else {
|
||||
entityCameraTool.enable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -292,6 +322,7 @@ var toolBar = (function () {
|
|||
}
|
||||
|
||||
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
@ -339,7 +370,8 @@ function mousePressEvent(event) {
|
|||
mouseLastPosition = { x: event.x, y: event.y };
|
||||
var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y });
|
||||
|
||||
if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) {
|
||||
if (toolBar.mousePressEvent(event) || progressDialog.mousePressEvent(event)
|
||||
|| entityCameraTool.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) {
|
||||
// Event handled; do nothing.
|
||||
return;
|
||||
} else {
|
||||
|
@ -442,8 +474,8 @@ function mouseMoveEvent(event) {
|
|||
return;
|
||||
}
|
||||
|
||||
// allow the selectionDisplay to handle the event first, if it doesn't handle it, then do our own thing
|
||||
if (selectionDisplay.mouseMoveEvent(event)) {
|
||||
// allow the selectionDisplay and entityCameraTool to handle the event first, if it doesn't handle it, then do our own thing
|
||||
if (selectionDisplay.mouseMoveEvent(event) || entityCameraTool.mouseMoveEvent(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -482,6 +514,7 @@ function mouseReleaseEvent(event) {
|
|||
if (entitySelected) {
|
||||
tooltip.show(false);
|
||||
}
|
||||
entityCameraTool.mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
Controller.mousePressEvent.connect(mousePressEvent);
|
||||
|
@ -613,6 +646,10 @@ Controller.keyReleaseEvent.connect(function (event) {
|
|||
}
|
||||
if (event.text == "BACKSPACE") {
|
||||
handeMenuEvent("Delete");
|
||||
} else if (event.text == "f") {
|
||||
if (entitySelected) {
|
||||
entityCameraTool.focus(selectedEntityProperties);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue