add rotate support to movable.js

This commit is contained in:
ZappoMan 2014-11-17 20:13:17 -08:00
parent 35b5dd520e
commit bc4e7ab662

View file

@ -13,6 +13,28 @@
this.entityID = null;
this.properties = null;
this.graboffset = null;
this.clickedAt = null;
this.firstHolding = true;
this.clickedX = -1;
this.clickedY = -1;
this.rotateOverlayTarget = null;
this.rotateOverlayInner = null;
this.rotateOverlayOuter = null;
this.rotateOverlayCurrent = null;
this.rotateMode = false;
this.originalRotation = null;
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 yawCenter;
var yawZero;
var rotationNormal;
var yawNormal;
var debug = true;
// Pr, Vr are respectively the Ray's Point of origin and Vector director
// Pp, Np are respectively the Plane's Point of origin and Normal vector
@ -40,7 +62,6 @@
var intersection = this.rayPlaneIntersection(pickRay.origin, pickRay.direction,
this.properties.position, upVector);
this.graboffset = Vec3.subtract(this.properties.position, intersection);
this.updatePosition(mouseEvent);
};
this.move = function(mouseEvent) {
@ -51,6 +72,56 @@
this.updatePosition(mouseEvent);
};
this.rotate = function(mouseEvent) {
var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y)
var result = Overlays.findRayIntersection(pickRay);
if (result.intersects) {
var center = yawCenter;
var zero = yawZero;
var centerToZero = Vec3.subtract(center, zero);
var centerToIntersect = Vec3.subtract(center, result.intersection);
var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal);
var distanceFromCenter = Vec3.distance(center, result.intersection);
var snapToInner = false;
// var innerRadius = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
if (distanceFromCenter < innerRadius) {
angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle;
snapToInner = true;
}
var yawChange = Quat.fromVec3Degrees({ x: 0, y: angleFromZero, z: 0 });
Entities.editEntity(this.entityID, { rotation: Quat.multiply(yawChange, this.originalRotation) });
// update the rotation display accordingly...
var startAtCurrent = 360-angleFromZero;
var endAtCurrent = 360;
var startAtRemainder = 0;
var endAtRemainder = 360-angleFromZero;
if (angleFromZero < 0) {
startAtCurrent = 0;
endAtCurrent = -angleFromZero;
startAtRemainder = -angleFromZero;
endAtRemainder = 360;
}
if (snapToInner) {
Overlays.editOverlay(this.rotateOverlayOuter, { startAt: 0, endAt: 360 });
Overlays.editOverlay(this.rotateOverlayInner, { startAt: startAtRemainder, endAt: endAtRemainder });
Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: innerRadius,
majorTickMarksAngle: innerSnapAngle, minorTickMarksAngle: 0,
majorTickMarksLength: -0.25, minorTickMarksLength: 0, });
} else {
Overlays.editOverlay(this.rotateOverlayInner, { startAt: 0, endAt: 360 });
Overlays.editOverlay(this.rotateOverlayOuter, { startAt: startAtRemainder, endAt: endAtRemainder });
Overlays.editOverlay(this.rotateOverlayCurrent, { startAt: startAtCurrent, endAt: endAtCurrent, size: outerRadius,
majorTickMarksAngle: 45.0, minorTickMarksAngle: 5,
majorTickMarksLength: 0.25, minorTickMarksLength: 0.1, });
}
}
};
// All callbacks start by updating the properties
this.updateProperties = function(entityID) {
if (this.entityID === null || !this.entityID.isKnownID) {
@ -58,7 +129,109 @@
}
this.properties = Entities.getEntityProperties(this.entityID);
};
this.cleanupRotateOverlay = function() {
Overlays.deleteOverlay(this.rotateOverlayTarget);
Overlays.deleteOverlay(this.rotateOverlayInner);
Overlays.deleteOverlay(this.rotateOverlayOuter);
Overlays.deleteOverlay(this.rotateOverlayCurrent);
this.rotateOverlayTarget = null;
this.rotateOverlayInner = null;
this.rotateOverlayOuter = null;
this.rotateOverlayCurrent = null;
}
this.displayRotateOverlay = function(mouseEvent) {
var yawOverlayAngles = { x: 90, y: 0, z: 0 };
var yawOverlayRotation = Quat.fromVec3Degrees(yawOverlayAngles);
yawNormal = { x: 0, y: 1, z: 0 };
yawCenter = this.properties.position;
rotationNormal = yawNormal;
// Size the overlays to the current selection size
var diagonal = (Vec3.length(this.properties.dimensions) / 2) * 1.1;
var halfDimensions = Vec3.multiply(this.properties.dimensions, 0.5);
innerRadius = diagonal;
outerRadius = diagonal * 1.15;
var innerAlpha = 0.2;
var outerAlpha = 0.2;
this.rotateOverlayTarget = Overlays.addOverlay("circle3d", {
position: this.properties.position,
size: 10000,
color: { red: 0, green: 0, blue: 0 },
alpha: 0.0,
solid: true,
visible: true,
rotation: yawOverlayRotation,
ignoreRayIntersection: false
});
this.rotateOverlayInner = Overlays.addOverlay("circle3d", {
position: this.properties.position,
size: innerRadius,
innerRadius: 0.9,
alpha: innerAlpha,
color: { red: 51, green: 152, blue: 203 },
solid: true,
visible: true,
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
});
this.rotateOverlayOuter = Overlays.addOverlay("circle3d", {
position: this.properties.position,
size: outerRadius,
innerRadius: 0.9,
startAt: 0,
endAt: 360,
alpha: outerAlpha,
color: { red: 51, green: 152, blue: 203 },
solid: true,
visible: true,
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
});
this.rotateOverlayCurrent = Overlays.addOverlay("circle3d", {
position: this.properties.position,
size: outerRadius,
startAt: 0,
endAt: 0,
innerRadius: 0.9,
color: { red: 224, green: 67, blue: 36},
alpha: 0.8,
solid: true,
visible: true,
rotation: yawOverlayRotation,
ignoreRayIntersection: true, // always ignore this
hasTickMarks: true,
majorTickMarksColor: { red: 0, green: 0, blue: 0 },
minorTickMarksColor: { red: 0, green: 0, blue: 0 },
});
var pickRay = Camera.computePickRay(mouseEvent.x, mouseEvent.y)
var result = Overlays.findRayIntersection(pickRay);
yawZero = result.intersection;
};
this.preload = function(entityID) {
this.updateProperties(entityID); // All callbacks start by updating the properties
};
@ -66,15 +239,56 @@
this.clickDownOnEntity = function(entityID, mouseEvent) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.grab(mouseEvent);
var d = new Date();
this.clickedAt = d.getTime();
this.firstHolding = true;
this.clickedX = mouseEvent.x;
this.clickedY = mouseEvent.y;
};
this.holdingClickOnEntity = function(entityID, mouseEvent) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.move(mouseEvent);
if (this.firstHolding) {
// if we haven't moved yet...
if (this.clickedX == mouseEvent.x && this.clickedY == mouseEvent.y) {
var d = new Date();
var now = d.getTime();
if (now - this.clickedAt > 500) {
this.displayRotateOverlay(mouseEvent);
this.firstHolding = false;
this.rotateMode = true;
this.originalRotation = this.properties.rotation;
}
} else {
this.firstHolding = false;
}
}
if (this.rotateMode) {
this.rotate(mouseEvent);
} else {
this.move(mouseEvent);
}
};
this.clickReleaseOnEntity = function(entityID, mouseEvent) {
this.updateProperties(entityID); // All callbacks start by updating the properties
this.release(mouseEvent);
if (this.rotateMode) {
this.rotate(mouseEvent);
} else {
this.release(mouseEvent);
}
if (this.rotateOverlayTarget != null) {
this.cleanupRotateOverlay();
this.rotateMode = false;
}
this.firstHolding = false;
};
})