mirror of
https://github.com/overte-org/overte.git
synced 2025-06-17 14:20:43 +02:00
First pass at controller interaction with 3D Web overlay
This commit is contained in:
parent
367e758dc6
commit
f749c76ced
5 changed files with 267 additions and 18 deletions
|
@ -3981,6 +3981,10 @@ void Application::setKeyboardFocusEntity(EntityItemID entityItemID) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int Application::getKeyboardFocusOverlay() {
|
||||||
|
return _keyboardFocusedOverlay.get();
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setKeyboardFocusOverlay(unsigned int overlayID) {
|
void Application::setKeyboardFocusOverlay(unsigned int overlayID) {
|
||||||
if (overlayID != _keyboardFocusedOverlay.get()) {
|
if (overlayID != _keyboardFocusedOverlay.get()) {
|
||||||
_keyboardFocusedOverlay.set(overlayID);
|
_keyboardFocusedOverlay.set(overlayID);
|
||||||
|
|
|
@ -374,6 +374,7 @@ public slots:
|
||||||
void setKeyboardFocusEntity(QUuid id);
|
void setKeyboardFocusEntity(QUuid id);
|
||||||
void setKeyboardFocusEntity(EntityItemID entityItemID);
|
void setKeyboardFocusEntity(EntityItemID entityItemID);
|
||||||
|
|
||||||
|
unsigned int getKeyboardFocusOverlay();
|
||||||
void setKeyboardFocusOverlay(unsigned int overlayID);
|
void setKeyboardFocusOverlay(unsigned int overlayID);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
|
@ -604,6 +604,38 @@ bool Overlays::isAddedOverlay(unsigned int id) {
|
||||||
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
|
return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overlays::sendMousePressOnOverlay(unsigned int overlayID, const PointerEvent& event) {
|
||||||
|
emit mousePressOnOverlay(overlayID, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::sendMouseReleaseOnOverlay(unsigned int overlayID, const PointerEvent& event) {
|
||||||
|
emit mouseReleaseOnOverlay(overlayID, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::sendMouseMoveOnOverlay(unsigned int overlayID, const PointerEvent& event) {
|
||||||
|
emit mouseMoveOnOverlay(overlayID, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::sendHoverEnterOverlay(unsigned int id, PointerEvent event) {
|
||||||
|
emit hoverEnterOverlay(id, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::sendHoverOverOverlay(unsigned int id, PointerEvent event) {
|
||||||
|
emit hoverOverOverlay(id, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::sendHoverLeaveOverlay(unsigned int id, PointerEvent event) {
|
||||||
|
emit hoverLeaveOverlay(id, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Overlays::getKeyboardFocusOverlay() const {
|
||||||
|
return qApp->getKeyboardFocusOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overlays::setKeyboardFocusOverlay(unsigned int id) {
|
||||||
|
qApp->setKeyboardFocusOverlay(id);
|
||||||
|
}
|
||||||
|
|
||||||
float Overlays::width() const {
|
float Overlays::width() const {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
return offscreenUi->getWindow()->size().width();
|
return offscreenUi->getWindow()->size().width();
|
||||||
|
|
|
@ -82,6 +82,8 @@ const unsigned int UNKNOWN_OVERLAY_ID = 0;
|
||||||
class Overlays : public QObject {
|
class Overlays : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(unsigned int keyboardFocusOverlay READ getKeyboardFocusOverlay WRITE setKeyboardFocusOverlay)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Overlays();
|
Overlays();
|
||||||
|
|
||||||
|
@ -256,6 +258,17 @@ public slots:
|
||||||
/// return true if there is a panel with that id else false
|
/// return true if there is a panel with that id else false
|
||||||
bool isAddedPanel(unsigned int id) { return _panels.contains(id); }
|
bool isAddedPanel(unsigned int id) { return _panels.contains(id); }
|
||||||
|
|
||||||
|
void sendMousePressOnOverlay(unsigned int overlayID, const PointerEvent& event);
|
||||||
|
void sendMouseReleaseOnOverlay(unsigned int overlayID, const PointerEvent& event);
|
||||||
|
void sendMouseMoveOnOverlay(unsigned int overlayID, const PointerEvent& event);
|
||||||
|
|
||||||
|
void sendHoverEnterOverlay(unsigned int id, PointerEvent event);
|
||||||
|
void sendHoverOverOverlay(unsigned int id, PointerEvent event);
|
||||||
|
void sendHoverLeaveOverlay(unsigned int id, PointerEvent event);
|
||||||
|
|
||||||
|
unsigned int getKeyboardFocusOverlay() const;
|
||||||
|
void setKeyboardFocusOverlay(unsigned int id);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
* Emitted when an overlay is deleted
|
* Emitted when an overlay is deleted
|
||||||
|
|
|
@ -186,6 +186,7 @@ var STATE_NEAR_TRIGGER = 4;
|
||||||
var STATE_FAR_TRIGGER = 5;
|
var STATE_FAR_TRIGGER = 5;
|
||||||
var STATE_HOLD = 6;
|
var STATE_HOLD = 6;
|
||||||
var STATE_ENTITY_TOUCHING = 7;
|
var STATE_ENTITY_TOUCHING = 7;
|
||||||
|
var STATE_OVERLAY_TOUCHING = 8;
|
||||||
|
|
||||||
var holdEnabled = true;
|
var holdEnabled = true;
|
||||||
var nearGrabEnabled = true;
|
var nearGrabEnabled = true;
|
||||||
|
@ -208,6 +209,8 @@ var mostRecentSearchingHand = RIGHT_HAND;
|
||||||
|
|
||||||
var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/equip-Fresnel-3.fbx";
|
var DEFAULT_SPHERE_MODEL_URL = "http://hifi-content.s3.amazonaws.com/alan/dev/equip-Fresnel-3.fbx";
|
||||||
|
|
||||||
|
var HARDWARE_MOUSE_ID = 0; // Value reserved for hardware mouse.
|
||||||
|
|
||||||
CONTROLLER_STATE_MACHINE[STATE_OFF] = {
|
CONTROLLER_STATE_MACHINE[STATE_OFF] = {
|
||||||
name: "off",
|
name: "off",
|
||||||
enterMethod: "offEnter",
|
enterMethod: "offEnter",
|
||||||
|
@ -249,6 +252,12 @@ CONTROLLER_STATE_MACHINE[STATE_ENTITY_TOUCHING] = {
|
||||||
exitMethod: "entityTouchingExit",
|
exitMethod: "entityTouchingExit",
|
||||||
updateMethod: "entityTouching"
|
updateMethod: "entityTouching"
|
||||||
};
|
};
|
||||||
|
CONTROLLER_STATE_MACHINE[STATE_OVERLAY_TOUCHING] = {
|
||||||
|
name: "overlayTouching",
|
||||||
|
enterMethod: "overlayTouchingEnter",
|
||||||
|
exitMethod: "overlayTouchingExit",
|
||||||
|
updateMethod: "overlayTouching"
|
||||||
|
};
|
||||||
|
|
||||||
function distanceBetweenPointAndEntityBoundingBox(point, entityProps) {
|
function distanceBetweenPointAndEntityBoundingBox(point, entityProps) {
|
||||||
var entityXform = new Xform(entityProps.rotation, entityProps.position);
|
var entityXform = new Xform(entityProps.rotation, entityProps.position);
|
||||||
|
@ -273,27 +282,40 @@ function angleBetween(a, b) {
|
||||||
return Math.acos(Vec3.dot(Vec3.normalize(a), Vec3.normalize(b)));
|
return Math.acos(Vec3.dot(Vec3.normalize(a), Vec3.normalize(b)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function projectOntoEntityXYPlane(entityID, worldPos) {
|
function projectOntoXYPlane(worldPos, position, rotation, dimensions, registrationPoint) {
|
||||||
var props = entityPropertiesCache.getProps(entityID);
|
var invRot = Quat.inverse(rotation);
|
||||||
var invRot = Quat.inverse(props.rotation);
|
var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(worldPos, position));
|
||||||
var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(worldPos, props.position));
|
var invDimensions = { x: 1 / dimensions.x,
|
||||||
var invDimensions = { x: 1 / props.dimensions.x,
|
y: 1 / dimensions.y,
|
||||||
y: 1 / props.dimensions.y,
|
z: 1 / dimensions.z };
|
||||||
z: 1 / props.dimensions.z };
|
var normalizedPos = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), registrationPoint);
|
||||||
var normalizedPos = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), props.registrationPoint);
|
return { x: normalizedPos.x * dimensions.x,
|
||||||
return { x: normalizedPos.x * props.dimensions.x,
|
y: (1 - normalizedPos.y) * dimensions.y }; // flip y-axis
|
||||||
y: (1 - normalizedPos.y) * props.dimensions.y }; // flip y-axis
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handLaserIntersectEntity(entityID, start) {
|
function projectOntoEntityXYPlane(entityID, worldPos) {
|
||||||
|
var props = entityPropertiesCache.getProps(entityID);
|
||||||
|
return projectOntoXYPlane(worldPos, props.position, props.rotation, props.dimensions, props.registrationPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
function projectOntoOverlayXYPlane(overlayID, worldPos) {
|
||||||
|
var position = Overlays.getProperty(overlayID, "position");
|
||||||
|
var rotation = Overlays.getProperty(overlayID, "rotation");
|
||||||
|
var dimensions = Overlays.getProperty(overlayID, "dimensions");
|
||||||
|
if (!dimensions.z) {
|
||||||
|
dimensions.z = 0;
|
||||||
|
}
|
||||||
|
var registrationPoint = { x: 0.5, y: 0.5, z: 0.5 };
|
||||||
|
return projectOntoXYPlane(worldPos, position, rotation, dimensions, registrationPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handLaserIntersectItem(position, rotation, start) {
|
||||||
var worldHandPosition = start.position;
|
var worldHandPosition = start.position;
|
||||||
var worldHandRotation = start.orientation;
|
var worldHandRotation = start.orientation;
|
||||||
|
|
||||||
var props = entityPropertiesCache.getProps(entityID);
|
if (position) {
|
||||||
|
var planePosition = position;
|
||||||
if (props.position) {
|
var planeNormal = Vec3.multiplyQbyV(rotation, {x: 0, y: 0, z: 1.0});
|
||||||
var planePosition = props.position;
|
|
||||||
var planeNormal = Vec3.multiplyQbyV(props.rotation, {x: 0, y: 0, z: 1.0});
|
|
||||||
var rayStart = worldHandPosition;
|
var rayStart = worldHandPosition;
|
||||||
var rayDirection = Quat.getUp(worldHandRotation);
|
var rayDirection = Quat.getUp(worldHandRotation);
|
||||||
var intersectionInfo = rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection);
|
var intersectionInfo = rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection);
|
||||||
|
@ -318,6 +340,17 @@ function handLaserIntersectEntity(entityID, start) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handLaserIntersectEntity(entityID, start) {
|
||||||
|
var props = entityPropertiesCache.getProps(entityID);
|
||||||
|
return handLaserIntersectItem(props.position, props.rotation, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handLaserIntersectOverlay(overlayID, start) {
|
||||||
|
var position = Overlays.getProperty(overlayID, "position");
|
||||||
|
var rotation = Overlays.getProperty(overlayID, "rotation");
|
||||||
|
return handLaserIntersectItem(position, rotation, start);
|
||||||
|
}
|
||||||
|
|
||||||
function rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection) {
|
function rayIntersectPlane(planePosition, planeNormal, rayStart, rayDirection) {
|
||||||
var rayDirectionDotPlaneNormal = Vec3.dot(rayDirection, planeNormal);
|
var rayDirectionDotPlaneNormal = Vec3.dot(rayDirection, planeNormal);
|
||||||
if (rayDirectionDotPlaneNormal > 0.00001 || rayDirectionDotPlaneNormal < -0.00001) {
|
if (rayDirectionDotPlaneNormal > 0.00001 || rayDirectionDotPlaneNormal < -0.00001) {
|
||||||
|
@ -727,6 +760,7 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.actionID = null; // action this script created...
|
this.actionID = null; // action this script created...
|
||||||
this.grabbedEntity = null; // on this entity.
|
this.grabbedEntity = null; // on this entity.
|
||||||
|
this.grabbedOverlay = null;
|
||||||
this.state = STATE_OFF;
|
this.state = STATE_OFF;
|
||||||
this.pointer = null; // entity-id of line object
|
this.pointer = null; // entity-id of line object
|
||||||
this.entityActivated = false;
|
this.entityActivated = false;
|
||||||
|
@ -1159,6 +1193,7 @@ function MyController(hand) {
|
||||||
|
|
||||||
var result = {
|
var result = {
|
||||||
entityID: null,
|
entityID: null,
|
||||||
|
overlayID: null,
|
||||||
searchRay: pickRay,
|
searchRay: pickRay,
|
||||||
distance: PICK_MAX_DISTANCE
|
distance: PICK_MAX_DISTANCE
|
||||||
};
|
};
|
||||||
|
@ -1427,6 +1462,7 @@ function MyController(hand) {
|
||||||
var name;
|
var name;
|
||||||
|
|
||||||
this.grabbedEntity = null;
|
this.grabbedEntity = null;
|
||||||
|
this.grabbedOverlay = null;
|
||||||
this.isInitialGrab = false;
|
this.isInitialGrab = false;
|
||||||
this.shouldResetParentOnRelease = false;
|
this.shouldResetParentOnRelease = false;
|
||||||
|
|
||||||
|
@ -1539,7 +1575,8 @@ function MyController(hand) {
|
||||||
// send mouse events for button highlights and tooltips.
|
// send mouse events for button highlights and tooltips.
|
||||||
if (this.hand == mostRecentSearchingHand || (this.hand !== mostRecentSearchingHand &&
|
if (this.hand == mostRecentSearchingHand || (this.hand !== mostRecentSearchingHand &&
|
||||||
this.getOtherHandController().state !== STATE_SEARCHING &&
|
this.getOtherHandController().state !== STATE_SEARCHING &&
|
||||||
this.getOtherHandController().state !== STATE_ENTITY_TOUCHING)) {
|
this.getOtherHandController().state !== STATE_ENTITY_TOUCHING &&
|
||||||
|
this.getOtherHandController().state !== STATE_OVERLAY_TOUCHING)) {
|
||||||
|
|
||||||
// most recently searching hand has priority over other hand, for the purposes of button highlighting.
|
// most recently searching hand has priority over other hand, for the purposes of button highlighting.
|
||||||
pointerEvent = {
|
pointerEvent = {
|
||||||
|
@ -1592,6 +1629,64 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var overlay;
|
||||||
|
|
||||||
|
if (rayPickInfo.overlayID) {
|
||||||
|
overlay = rayPickInfo.overlayID;
|
||||||
|
|
||||||
|
if (Overlays.keyboardFocusOverlay != overlay) {
|
||||||
|
Overlays.keyboardFocusOverlay = overlay;
|
||||||
|
|
||||||
|
pointerEvent = {
|
||||||
|
type: "Move",
|
||||||
|
id: HARDWARE_MOUSE_ID,
|
||||||
|
pos2D: projectOntoOverlayXYPlane(overlay, rayPickInfo.intersection),
|
||||||
|
pos3D: rayPickInfo.intersection,
|
||||||
|
normal: rayPickInfo.normal,
|
||||||
|
direction: rayPickInfo.searchRay.direction,
|
||||||
|
button: "None"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.hoverOverlay = overlay;
|
||||||
|
Overlays.sendHoverEnterOverlay(overlay, pointerEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send mouse events for button highlights and tooltips.
|
||||||
|
if (this.hand == mostRecentSearchingHand || (this.hand !== mostRecentSearchingHand &&
|
||||||
|
this.getOtherHandController().state !== STATE_SEARCHING &&
|
||||||
|
this.getOtherHandController().state !== STATE_ENTITY_TOUCHING &&
|
||||||
|
this.getOtherHandController().state !== STATE_OVERLAY_TOUCHING)) {
|
||||||
|
|
||||||
|
// most recently searching hand has priority over other hand, for the purposes of button highlighting.
|
||||||
|
pointerEvent = {
|
||||||
|
type: "Move",
|
||||||
|
id: HARDWARE_MOUSE_ID,
|
||||||
|
pos2D: projectOntoOverlayXYPlane(overlay, rayPickInfo.intersection),
|
||||||
|
pos3D: rayPickInfo.intersection,
|
||||||
|
normal: rayPickInfo.normal,
|
||||||
|
direction: rayPickInfo.searchRay.direction,
|
||||||
|
button: "None"
|
||||||
|
};
|
||||||
|
|
||||||
|
Overlays.sendMouseMoveOnOverlay(overlay, pointerEvent);
|
||||||
|
Overlays.sendHoverOverOverlay(overlay, pointerEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.triggerSmoothedGrab() && !isEditing()) {
|
||||||
|
this.grabbedOverlay = overlay;
|
||||||
|
this.setState(STATE_OVERLAY_TOUCHING, "begin touching overlay '" + overlay + "'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (this.hoverOverlay) {
|
||||||
|
pointerEvent = {
|
||||||
|
type: "Move",
|
||||||
|
id: HARDWARE_MOUSE_ID
|
||||||
|
};
|
||||||
|
Overlays.sendHoverLeaveOverlay(this.hoverOverlay, pointerEvent);
|
||||||
|
this.hoverOverlay = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.updateEquipHaptics(potentialEquipHotspot, handPosition);
|
this.updateEquipHaptics(potentialEquipHotspot, handPosition);
|
||||||
|
|
||||||
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
var nearEquipHotspots = this.chooseNearEquipHotspots(candidateEntities, EQUIP_HOTSPOT_RENDER_RADIUS);
|
||||||
|
@ -2342,7 +2437,6 @@ function MyController(hand) {
|
||||||
Entities.sendClickReleaseOnEntity(this.grabbedEntity, pointerEvent);
|
Entities.sendClickReleaseOnEntity(this.grabbedEntity, pointerEvent);
|
||||||
Entities.sendHoverLeaveEntity(this.grabbedEntity, pointerEvent);
|
Entities.sendHoverLeaveEntity(this.grabbedEntity, pointerEvent);
|
||||||
}
|
}
|
||||||
this.focusedEntity = null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.entityTouching = function(dt) {
|
this.entityTouching = function(dt) {
|
||||||
|
@ -2396,6 +2490,110 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.overlayTouchingEnter = function () {
|
||||||
|
// Test for intersection between controller laser and Web overlay plane.
|
||||||
|
var intersectInfo =
|
||||||
|
handLaserIntersectOverlay(this.grabbedOverlay, getControllerWorldLocation(this.handToController(), true));
|
||||||
|
if (intersectInfo) {
|
||||||
|
var pointerEvent = {
|
||||||
|
type: "Press",
|
||||||
|
id: HARDWARE_MOUSE_ID,
|
||||||
|
pos2D: projectOntoOverlayXYPlane(this.grabbedOverlay, intersectInfo.point),
|
||||||
|
pos3D: intersectInfo.point,
|
||||||
|
normal: intersectInfo.normal,
|
||||||
|
direction: intersectInfo.searchRay.direction,
|
||||||
|
button: "Primary",
|
||||||
|
isPrimaryHeld: true
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: post2D isn't calculated correctly; use dummy values to prevent crash.
|
||||||
|
pointerEvent.pos2D.x = 50;
|
||||||
|
pointerEvent.pos2D.y = 50;
|
||||||
|
|
||||||
|
Overlays.sendMousePressOnOverlay(this.grabbedOverlay, pointerEvent);
|
||||||
|
|
||||||
|
this.touchingEnterTimer = 0;
|
||||||
|
this.touchingEnterPointerEvent = pointerEvent;
|
||||||
|
this.touchingEnterPointerEvent.button = "None";
|
||||||
|
this.deadspotExpired = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.overlayTouchingExit = function () {
|
||||||
|
// Test for intersection between controller laser and Web overlay plane.
|
||||||
|
var intersectInfo =
|
||||||
|
handLaserIntersectOverlay(this.grabbedOverlay, getControllerWorldLocation(this.handToController(), true));
|
||||||
|
if (intersectInfo) {
|
||||||
|
var pointerEvent;
|
||||||
|
if (this.deadspotExpired) {
|
||||||
|
pointerEvent = {
|
||||||
|
type: "Release",
|
||||||
|
id: HARDWARE_MOUSE_ID,
|
||||||
|
pos2D: projectOntoOverlayXYPlane(this.grabbedOverlay, intersectInfo.point),
|
||||||
|
pos3D: intersectInfo.point,
|
||||||
|
normal: intersectInfo.normal,
|
||||||
|
direction: intersectInfo.searchRay.direction,
|
||||||
|
button: "Primary"
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
pointerEvent = this.touchingEnterPointerEvent;
|
||||||
|
pointerEvent.type = "Release";
|
||||||
|
pointerEvent.button = "Primary";
|
||||||
|
pointerEvent.isPrimaryHeld = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Overlays.sendMouseReleaseOnOverlay(this.grabbedOverlay, pointerEvent);
|
||||||
|
Overlays.sendHoverLeaveOverlay(this.grabbedOverlay, pointerEvent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.overlayTouching = function (dt) {
|
||||||
|
this.touchingEnterTimer += dt;
|
||||||
|
|
||||||
|
if (!this.triggerSmoothedGrab()) {
|
||||||
|
this.setState(STATE_OFF, "released trigger");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test for intersection between controller laser and Web overlay plane.
|
||||||
|
var intersectInfo =
|
||||||
|
handLaserIntersectOverlay(this.grabbedOverlay, getControllerWorldLocation(this.handToController(), true));
|
||||||
|
if (intersectInfo) {
|
||||||
|
|
||||||
|
if (Overlays.keyboardFocusOverlay != this.grabbedOverlay) {
|
||||||
|
Overlays.keyboardFocusOverlay = this.grabbedOverlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pointerEvent = {
|
||||||
|
type: "Move",
|
||||||
|
id: HARDWARE_MOUSE_ID,
|
||||||
|
pos2D: projectOntoOverlayXYPlane(this.grabbedOverlay, intersectInfo.point),
|
||||||
|
pos3D: intersectInfo.point,
|
||||||
|
normal: intersectInfo.normal,
|
||||||
|
direction: intersectInfo.searchRay.direction,
|
||||||
|
button: "NoButtons",
|
||||||
|
isPrimaryHeld: true
|
||||||
|
};
|
||||||
|
|
||||||
|
var POINTER_PRESS_TO_MOVE_DELAY = 0.15; // seconds
|
||||||
|
var POINTER_PRESS_TO_MOVE_DEADSPOT_ANGLE = 0.05; // radians ~ 3 degrees
|
||||||
|
if (this.deadspotExpired || this.touchingEnterTimer > POINTER_PRESS_TO_MOVE_DELAY ||
|
||||||
|
angleBetween(pointerEvent.direction, this.touchingEnterPointerEvent.direction) > POINTER_PRESS_TO_MOVE_DEADSPOT_ANGLE) {
|
||||||
|
Overlays.sendMouseMoveOnOverlay(this.grabbedOverlay, pointerEvent);
|
||||||
|
this.deadspotExpired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.intersectionDistance = intersectInfo.distance;
|
||||||
|
if (farGrabEnabled) {
|
||||||
|
this.searchIndicatorOn(intersectInfo.searchRay);
|
||||||
|
}
|
||||||
|
Reticle.setVisible(false);
|
||||||
|
} else {
|
||||||
|
this.setState(STATE_OFF, "grabbed overlay was destroyed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.release = function() {
|
this.release = function() {
|
||||||
this.turnOffVisualizations();
|
this.turnOffVisualizations();
|
||||||
|
|
||||||
|
@ -2437,6 +2635,7 @@ function MyController(hand) {
|
||||||
|
|
||||||
this.actionID = null;
|
this.actionID = null;
|
||||||
this.grabbedEntity = null;
|
this.grabbedEntity = null;
|
||||||
|
this.grabbedOverlay = null;
|
||||||
this.grabbedHotspot = null;
|
this.grabbedHotspot = null;
|
||||||
|
|
||||||
if (this.triggerSmoothedGrab()) {
|
if (this.triggerSmoothedGrab()) {
|
||||||
|
|
Loading…
Reference in a new issue