mirror of
https://github.com/lubosz/overte.git
synced 2025-04-19 17:03:43 +02:00
Merge pull request #12087 from ctrlaltdavid/21661
Laser auto-on with tablet and Web overlays
This commit is contained in:
commit
b28684f15e
22 changed files with 265 additions and 108 deletions
|
@ -738,6 +738,7 @@ const float DEFAULT_HMD_TABLET_SCALE_PERCENT = 100.0f;
|
|||
const float DEFAULT_DESKTOP_TABLET_SCALE_PERCENT = 75.0f;
|
||||
const bool DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR = true;
|
||||
const bool DEFAULT_HMD_TABLET_BECOMES_TOOLBAR = false;
|
||||
const bool DEFAULT_PREFER_STYLUS_OVER_LASER = false;
|
||||
const bool DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS = false;
|
||||
const QString DEFAULT_CURSOR_NAME = "DEFAULT";
|
||||
|
||||
|
@ -757,6 +758,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
_desktopTabletScale("desktopTabletScale", DEFAULT_DESKTOP_TABLET_SCALE_PERCENT),
|
||||
_desktopTabletBecomesToolbarSetting("desktopTabletBecomesToolbar", DEFAULT_DESKTOP_TABLET_BECOMES_TOOLBAR),
|
||||
_hmdTabletBecomesToolbarSetting("hmdTabletBecomesToolbar", DEFAULT_HMD_TABLET_BECOMES_TOOLBAR),
|
||||
_preferStylusOverLaserSetting("preferStylusOverLaser", DEFAULT_PREFER_STYLUS_OVER_LASER),
|
||||
_preferAvatarFingerOverStylusSetting("preferAvatarFingerOverStylus", DEFAULT_PREFER_AVATAR_FINGER_OVER_STYLUS),
|
||||
_constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true),
|
||||
_preferredCursor("preferredCursor", DEFAULT_CURSOR_NAME),
|
||||
|
@ -2580,6 +2582,10 @@ void Application::setHmdTabletBecomesToolbarSetting(bool value) {
|
|||
updateSystemTabletMode();
|
||||
}
|
||||
|
||||
void Application::setPreferStylusOverLaser(bool value) {
|
||||
_preferStylusOverLaserSetting.set(value);
|
||||
}
|
||||
|
||||
void Application::setPreferAvatarFingerOverStylus(bool value) {
|
||||
_preferAvatarFingerOverStylusSetting.set(value);
|
||||
}
|
||||
|
|
|
@ -207,7 +207,11 @@ public:
|
|||
void setDesktopTabletBecomesToolbarSetting(bool value);
|
||||
bool getHmdTabletBecomesToolbarSetting() { return _hmdTabletBecomesToolbarSetting.get(); }
|
||||
void setHmdTabletBecomesToolbarSetting(bool value);
|
||||
bool getPreferAvatarFingerOverStylus() { return _preferAvatarFingerOverStylusSetting.get(); }
|
||||
bool getPreferStylusOverLaser() { return _preferStylusOverLaserSetting.get(); }
|
||||
void setPreferStylusOverLaser(bool value);
|
||||
// FIXME: Remove setting completely or make available through JavaScript API?
|
||||
//bool getPreferAvatarFingerOverStylus() { return _preferAvatarFingerOverStylusSetting.get(); }
|
||||
bool getPreferAvatarFingerOverStylus() { return false; }
|
||||
void setPreferAvatarFingerOverStylus(bool value);
|
||||
|
||||
float getSettingConstrainToolbarPosition() { return _constrainToolbarPosition.get(); }
|
||||
|
@ -551,6 +555,7 @@ private:
|
|||
Setting::Handle<float> _desktopTabletScale;
|
||||
Setting::Handle<bool> _desktopTabletBecomesToolbarSetting;
|
||||
Setting::Handle<bool> _hmdTabletBecomesToolbarSetting;
|
||||
Setting::Handle<bool> _preferStylusOverLaserSetting;
|
||||
Setting::Handle<bool> _preferAvatarFingerOverStylusSetting;
|
||||
Setting::Handle<bool> _constrainToolbarPosition;
|
||||
Setting::Handle<QString> _preferredCursor;
|
||||
|
|
|
@ -218,14 +218,40 @@ Pointer::PickedObject LaserPointer::getHoveredObject(const PickResultPointer& pi
|
|||
return PickedObject(rayPickResult->objectID, rayPickResult->type);
|
||||
}
|
||||
|
||||
Pointer::Buttons LaserPointer::getPressedButtons() {
|
||||
Pointer::Buttons LaserPointer::getPressedButtons(const PickResultPointer& pickResult) {
|
||||
std::unordered_set<std::string> toReturn;
|
||||
for (const PointerTrigger& trigger : _triggers) {
|
||||
// TODO: right now, LaserPointers don't support axes, only on/off buttons
|
||||
if (trigger.getEndpoint()->peek() >= 1.0f) {
|
||||
toReturn.insert(trigger.getButton());
|
||||
auto rayPickResult = std::static_pointer_cast<const RayPickResult>(pickResult);
|
||||
|
||||
if (rayPickResult) {
|
||||
for (const PointerTrigger& trigger : _triggers) {
|
||||
std::string button = trigger.getButton();
|
||||
TriggerState& state = _states[button];
|
||||
// TODO: right now, LaserPointers don't support axes, only on/off buttons
|
||||
if (trigger.getEndpoint()->peek() >= 1.0f) {
|
||||
toReturn.insert(button);
|
||||
|
||||
if (_previousButtons.find(button) == _previousButtons.end()) {
|
||||
// start triggering for buttons that were just pressed
|
||||
state.triggeredObject = PickedObject(rayPickResult->objectID, rayPickResult->type);
|
||||
state.intersection = rayPickResult->intersection;
|
||||
state.triggerPos2D = findPos2D(state.triggeredObject, rayPickResult->intersection);
|
||||
state.triggerStartTime = usecTimestampNow();
|
||||
state.surfaceNormal = rayPickResult->surfaceNormal;
|
||||
state.deadspotExpired = false;
|
||||
state.wasTriggering = true;
|
||||
state.triggering = true;
|
||||
_latestState = state;
|
||||
}
|
||||
} else {
|
||||
// stop triggering for buttons that aren't pressed
|
||||
state.wasTriggering = state.triggering;
|
||||
state.triggering = false;
|
||||
_latestState = state;
|
||||
}
|
||||
}
|
||||
_previousButtons = toReturn;
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
|
@ -303,7 +329,7 @@ RenderState LaserPointer::buildRenderState(const QVariantMap& propMap) {
|
|||
return RenderState(startID, pathID, endID);
|
||||
}
|
||||
|
||||
PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover) const {
|
||||
PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button, bool hover) {
|
||||
QUuid pickedID;
|
||||
glm::vec3 intersection, surfaceNormal, direction, origin;
|
||||
auto rayPickResult = std::static_pointer_cast<RayPickResult>(pickResult);
|
||||
|
@ -316,20 +342,48 @@ PointerEvent LaserPointer::buildPointerEvent(const PickedObject& target, const P
|
|||
pickedID = rayPickResult->objectID;
|
||||
}
|
||||
|
||||
glm::vec2 pos2D;
|
||||
if (pickedID != target.objectID) {
|
||||
if (target.type == ENTITY) {
|
||||
intersection = RayPick::intersectRayWithEntityXYPlane(target.objectID, origin, direction);
|
||||
} else if (target.type == OVERLAY) {
|
||||
intersection = RayPick::intersectRayWithOverlayXYPlane(target.objectID, origin, direction);
|
||||
}
|
||||
intersection = findIntersection(target, origin, direction);
|
||||
}
|
||||
if (target.type == ENTITY) {
|
||||
pos2D = RayPick::projectOntoEntityXYPlane(target.objectID, intersection);
|
||||
} else if (target.type == OVERLAY) {
|
||||
pos2D = RayPick::projectOntoOverlayXYPlane(target.objectID, intersection);
|
||||
} else if (target.type == HUD) {
|
||||
pos2D = DependencyManager::get<PickManager>()->calculatePos2DFromHUD(intersection);
|
||||
glm::vec2 pos2D = findPos2D(target, intersection);
|
||||
|
||||
// If we just started triggering and we haven't moved too much, don't update intersection and pos2D
|
||||
TriggerState& state = hover ? _latestState : _states[button];
|
||||
float sensorToWorldScale = DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
|
||||
float deadspotSquared = TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED * sensorToWorldScale * sensorToWorldScale;
|
||||
bool withinDeadspot = usecTimestampNow() - state.triggerStartTime < POINTER_MOVE_DELAY && glm::distance2(pos2D, state.triggerPos2D) < deadspotSquared;
|
||||
if ((state.triggering || state.wasTriggering) && !state.deadspotExpired && withinDeadspot) {
|
||||
pos2D = state.triggerPos2D;
|
||||
intersection = state.intersection;
|
||||
surfaceNormal = state.surfaceNormal;
|
||||
}
|
||||
if (!withinDeadspot) {
|
||||
state.deadspotExpired = true;
|
||||
}
|
||||
|
||||
return PointerEvent(pos2D, intersection, surfaceNormal, direction);
|
||||
}
|
||||
|
||||
glm::vec3 LaserPointer::findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction) {
|
||||
switch (pickedObject.type) {
|
||||
case ENTITY:
|
||||
return RayPick::intersectRayWithEntityXYPlane(pickedObject.objectID, origin, direction);
|
||||
case OVERLAY:
|
||||
return RayPick::intersectRayWithOverlayXYPlane(pickedObject.objectID, origin, direction);
|
||||
default:
|
||||
return glm::vec3(NAN);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec2 LaserPointer::findPos2D(const PickedObject& pickedObject, const glm::vec3& origin) {
|
||||
switch (pickedObject.type) {
|
||||
case ENTITY:
|
||||
return RayPick::projectOntoEntityXYPlane(pickedObject.objectID, origin);
|
||||
case OVERLAY:
|
||||
return RayPick::projectOntoOverlayXYPlane(pickedObject.objectID, origin);
|
||||
case HUD:
|
||||
return DependencyManager::get<PickManager>()->calculatePos2DFromHUD(origin);
|
||||
default:
|
||||
return glm::vec2(NAN);
|
||||
}
|
||||
}
|
|
@ -80,10 +80,10 @@ public:
|
|||
static RenderState buildRenderState(const QVariantMap& propMap);
|
||||
|
||||
protected:
|
||||
PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover = true) const override;
|
||||
PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button = "", bool hover = true) override;
|
||||
|
||||
PickedObject getHoveredObject(const PickResultPointer& pickResult) override;
|
||||
Pointer::Buttons getPressedButtons() override;
|
||||
Pointer::Buttons getPressedButtons(const PickResultPointer& pickResult) override;
|
||||
|
||||
bool shouldHover(const PickResultPointer& pickResult) override { return _currentRenderState != ""; }
|
||||
bool shouldTrigger(const PickResultPointer& pickResult) override { return _currentRenderState != ""; }
|
||||
|
@ -105,6 +105,23 @@ private:
|
|||
void updateRenderState(const RenderState& renderState, const IntersectionType type, float distance, const QUuid& objectID, const PickRay& pickRay, bool defaultState);
|
||||
void disableRenderState(const RenderState& renderState);
|
||||
|
||||
struct TriggerState {
|
||||
PickedObject triggeredObject;
|
||||
glm::vec3 intersection { NAN };
|
||||
glm::vec3 surfaceNormal { NAN };
|
||||
glm::vec2 triggerPos2D { NAN };
|
||||
quint64 triggerStartTime { 0 };
|
||||
bool deadspotExpired { true };
|
||||
bool triggering { false };
|
||||
bool wasTriggering { false };
|
||||
};
|
||||
|
||||
Pointer::Buttons _previousButtons;
|
||||
std::unordered_map<std::string, TriggerState> _states;
|
||||
TriggerState _latestState;
|
||||
static glm::vec3 findIntersection(const PickedObject& pickedObject, const glm::vec3& origin, const glm::vec3& direction);
|
||||
static glm::vec2 findPos2D(const PickedObject& pickedObject, const glm::vec3& origin);
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_LaserPointer_h
|
||||
|
|
|
@ -92,4 +92,4 @@ glm::vec2 RayPick::projectOntoOverlayXYPlane(const QUuid& overlayID, const glm::
|
|||
glm::vec2 RayPick::projectOntoEntityXYPlane(const QUuid& entityID, const glm::vec3& worldPos, bool unNormalized) {
|
||||
auto props = DependencyManager::get<EntityScriptingInterface>()->getEntityProperties(entityID);
|
||||
return projectOntoXYPlane(worldPos, props.getPosition(), props.getRotation(), props.getDimensions(), props.getRegistrationPoint(), unNormalized);
|
||||
}
|
||||
}
|
|
@ -28,10 +28,6 @@ static const float TABLET_MAX_TOUCH_DISTANCE = 0.005f;
|
|||
static const float HOVER_HYSTERESIS = 0.01f;
|
||||
static const float TOUCH_HYSTERESIS = 0.001f;
|
||||
|
||||
static const float STYLUS_MOVE_DELAY = 0.33f * USECS_PER_SECOND;
|
||||
static const float TOUCH_PRESS_TO_MOVE_DEADSPOT = 0.0481f;
|
||||
static const float TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED = TOUCH_PRESS_TO_MOVE_DEADSPOT * TOUCH_PRESS_TO_MOVE_DEADSPOT;
|
||||
|
||||
StylusPointer::StylusPointer(const QVariant& props, const OverlayID& stylusOverlay, bool hover, bool enabled) :
|
||||
Pointer(DependencyManager::get<PickScriptingInterface>()->createStylusPick(props), enabled, hover),
|
||||
_stylusOverlay(stylusOverlay)
|
||||
|
@ -112,37 +108,37 @@ bool StylusPointer::shouldHover(const PickResultPointer& pickResult) {
|
|||
|
||||
bool StylusPointer::shouldTrigger(const PickResultPointer& pickResult) {
|
||||
auto stylusPickResult = std::static_pointer_cast<const StylusPickResult>(pickResult);
|
||||
bool wasTriggering = false;
|
||||
if (_renderState == EVENTS_ON && stylusPickResult) {
|
||||
auto sensorScaleFactor = DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
|
||||
float distance = stylusPickResult->distance;
|
||||
|
||||
// If we're triggering on an object, recalculate the distance instead of using the pickResult
|
||||
glm::vec3 origin = vec3FromVariant(stylusPickResult->pickVariant["position"]);
|
||||
glm::vec3 direction = -_state.surfaceNormal;
|
||||
if (!_state.triggeredObject.objectID.isNull() && stylusPickResult->objectID != _state.triggeredObject.objectID) {
|
||||
glm::vec3 direction = _state.triggering ? -_state.surfaceNormal : -stylusPickResult->surfaceNormal;
|
||||
if ((_state.triggering || _state.wasTriggering) && stylusPickResult->objectID != _state.triggeredObject.objectID) {
|
||||
distance = glm::dot(findIntersection(_state.triggeredObject, origin, direction) - origin, direction);
|
||||
}
|
||||
|
||||
float hysteresis = _state.triggering ? TOUCH_HYSTERESIS * sensorScaleFactor : 0.0f;
|
||||
if (isWithinBounds(distance, TABLET_MIN_TOUCH_DISTANCE * sensorScaleFactor,
|
||||
TABLET_MAX_TOUCH_DISTANCE * sensorScaleFactor, hysteresis)) {
|
||||
if (_state.triggeredObject.objectID.isNull()) {
|
||||
TABLET_MAX_TOUCH_DISTANCE * sensorScaleFactor, hysteresis)) {
|
||||
_state.wasTriggering = _state.triggering;
|
||||
if (!_state.triggering) {
|
||||
_state.triggeredObject = PickedObject(stylusPickResult->objectID, stylusPickResult->type);
|
||||
_state.intersection = findIntersection(_state.triggeredObject, origin, direction);
|
||||
_state.intersection = stylusPickResult->intersection;
|
||||
_state.triggerPos2D = findPos2D(_state.triggeredObject, origin);
|
||||
_state.triggerStartTime = usecTimestampNow();
|
||||
_state.surfaceNormal = stylusPickResult->surfaceNormal;
|
||||
_state.deadspotExpired = false;
|
||||
_state.triggering = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
wasTriggering = _state.triggering;
|
||||
}
|
||||
|
||||
_state.triggeredObject = PickedObject();
|
||||
_state.intersection = glm::vec3(NAN);
|
||||
_state.triggerPos2D = glm::vec2(NAN);
|
||||
_state.triggerStartTime = 0;
|
||||
_state.surfaceNormal = glm::vec3(NAN);
|
||||
_state.wasTriggering = wasTriggering;
|
||||
_state.triggering = false;
|
||||
return false;
|
||||
}
|
||||
|
@ -155,13 +151,13 @@ Pointer::PickedObject StylusPointer::getHoveredObject(const PickResultPointer& p
|
|||
return PickedObject(stylusPickResult->objectID, stylusPickResult->type);
|
||||
}
|
||||
|
||||
Pointer::Buttons StylusPointer::getPressedButtons() {
|
||||
Pointer::Buttons StylusPointer::getPressedButtons(const PickResultPointer& pickResult) {
|
||||
// TODO: custom buttons for styluses
|
||||
Pointer::Buttons toReturn({ "Primary", "Focus" });
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
PointerEvent StylusPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover) const {
|
||||
PointerEvent StylusPointer::buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button, bool hover) {
|
||||
QUuid pickedID;
|
||||
glm::vec2 pos2D;
|
||||
glm::vec3 intersection, surfaceNormal, direction, origin;
|
||||
|
@ -177,18 +173,22 @@ PointerEvent StylusPointer::buildPointerEvent(const PickedObject& target, const
|
|||
}
|
||||
|
||||
// If we just started triggering and we haven't moved too much, don't update intersection and pos2D
|
||||
if (!_state.triggeredObject.objectID.isNull() && usecTimestampNow() - _state.triggerStartTime < STYLUS_MOVE_DELAY &&
|
||||
glm::distance2(pos2D, _state.triggerPos2D) < TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED) {
|
||||
float sensorToWorldScale = DependencyManager::get<AvatarManager>()->getMyAvatar()->getSensorToWorldScale();
|
||||
float deadspotSquared = TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED * sensorToWorldScale * sensorToWorldScale;
|
||||
bool withinDeadspot = usecTimestampNow() - _state.triggerStartTime < POINTER_MOVE_DELAY && glm::distance2(pos2D, _state.triggerPos2D) < deadspotSquared;
|
||||
if ((_state.triggering || _state.wasTriggering) && !_state.deadspotExpired && withinDeadspot) {
|
||||
pos2D = _state.triggerPos2D;
|
||||
intersection = _state.intersection;
|
||||
} else if (pickedID != target.objectID) {
|
||||
intersection = findIntersection(target, origin, direction);
|
||||
}
|
||||
if (!withinDeadspot) {
|
||||
_state.deadspotExpired = true;
|
||||
}
|
||||
|
||||
return PointerEvent(pos2D, intersection, surfaceNormal, direction);
|
||||
}
|
||||
|
||||
|
||||
bool StylusPointer::isWithinBounds(float distance, float min, float max, float hysteresis) {
|
||||
return (distance == glm::clamp(distance, min - hysteresis, max + hysteresis));
|
||||
}
|
||||
|
|
|
@ -37,11 +37,11 @@ public:
|
|||
|
||||
protected:
|
||||
PickedObject getHoveredObject(const PickResultPointer& pickResult) override;
|
||||
Buttons getPressedButtons() override;
|
||||
Buttons getPressedButtons(const PickResultPointer& pickResult) override;
|
||||
bool shouldHover(const PickResultPointer& pickResult) override;
|
||||
bool shouldTrigger(const PickResultPointer& pickResult) override;
|
||||
|
||||
PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover = true) const override;
|
||||
PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button = "", bool hover = true) override;
|
||||
|
||||
private:
|
||||
void show(const StylusTip& tip);
|
||||
|
@ -53,7 +53,9 @@ private:
|
|||
glm::vec2 triggerPos2D { NAN };
|
||||
glm::vec3 surfaceNormal { NAN };
|
||||
quint64 triggerStartTime { 0 };
|
||||
bool deadspotExpired { true };
|
||||
bool triggering { false };
|
||||
bool wasTriggering { false };
|
||||
|
||||
bool hovering { false };
|
||||
};
|
||||
|
|
|
@ -90,11 +90,19 @@ void setupPreferences() {
|
|||
preference->setMax(500);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = []()->bool { return qApp->getPreferStylusOverLaser(); };
|
||||
auto setter = [](bool value) { qApp->setPreferStylusOverLaser(value); };
|
||||
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Stylus Over Laser", getter, setter));
|
||||
}
|
||||
// FIXME: Remove setting completely or make available through JavaScript API?
|
||||
/*
|
||||
{
|
||||
auto getter = []()->bool { return qApp->getPreferAvatarFingerOverStylus(); };
|
||||
auto setter = [](bool value) { qApp->setPreferAvatarFingerOverStylus(value); };
|
||||
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Avatar Finger Over Stylus", getter, setter));
|
||||
}
|
||||
*/
|
||||
{
|
||||
static const QString RETICLE_ICON_NAME = { Cursor::Manager::getIconName(Cursor::Icon::RETICLE) };
|
||||
auto getter = []()->bool { return qApp->getPreferredCursor() == RETICLE_ICON_NAME; };
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
#include "PickManager.h"
|
||||
#include "PointerManager.h"
|
||||
|
||||
#include "NumericalConstants.h"
|
||||
|
||||
const float Pointer::POINTER_MOVE_DELAY = 0.33f * USECS_PER_SECOND;
|
||||
const float TOUCH_PRESS_TO_MOVE_DEADSPOT = 0.0481f;
|
||||
const float Pointer::TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED = TOUCH_PRESS_TO_MOVE_DEADSPOT * TOUCH_PRESS_TO_MOVE_DEADSPOT;
|
||||
|
||||
Pointer::~Pointer() {
|
||||
DependencyManager::get<PickManager>()->removePick(_pickUID);
|
||||
}
|
||||
|
@ -77,7 +83,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
|
|||
Buttons newButtons;
|
||||
Buttons sameButtons;
|
||||
if (_enabled && shouldTrigger(pickResult)) {
|
||||
buttons = getPressedButtons();
|
||||
buttons = getPressedButtons(pickResult);
|
||||
for (const std::string& button : buttons) {
|
||||
if (_prevButtons.find(button) == _prevButtons.end()) {
|
||||
newButtons.insert(button);
|
||||
|
@ -175,17 +181,6 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
|
|||
}
|
||||
}
|
||||
|
||||
// send hoverEnd events if we disable the pointer or disable hovering
|
||||
if (_hover && ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover))) {
|
||||
if (_prevHoveredObject.type == ENTITY) {
|
||||
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
|
||||
} else if (_prevHoveredObject.type == OVERLAY) {
|
||||
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
|
||||
} else if (_prevHoveredObject.type == HUD) {
|
||||
emit pointerManager->hoverEndHUD(hoveredEvent);
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger begin
|
||||
const std::string SHOULD_FOCUS_BUTTON = "Focus";
|
||||
for (const std::string& button : newButtons) {
|
||||
|
@ -204,7 +199,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
|
|||
|
||||
// Trigger continue
|
||||
for (const std::string& button : sameButtons) {
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, false);
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, button, false);
|
||||
triggeredEvent.setID(pointerID);
|
||||
triggeredEvent.setType(PointerEvent::Move);
|
||||
triggeredEvent.setButton(chooseButton(button));
|
||||
|
@ -219,7 +214,7 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
|
|||
|
||||
// Trigger end
|
||||
for (const std::string& button : _prevButtons) {
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, false);
|
||||
PointerEvent triggeredEvent = buildPointerEvent(_triggeredObjects[button], pickResult, button, false);
|
||||
triggeredEvent.setID(pointerID);
|
||||
triggeredEvent.setType(PointerEvent::Release);
|
||||
triggeredEvent.setButton(chooseButton(button));
|
||||
|
@ -233,6 +228,17 @@ void Pointer::generatePointerEvents(unsigned int pointerID, const PickResultPoin
|
|||
_triggeredObjects.erase(button);
|
||||
}
|
||||
|
||||
// if we disable the pointer or disable hovering, send hoverEnd events after triggerEnd
|
||||
if (_hover && ((!_enabled && _prevEnabled) || (!doHover && _prevDoHover))) {
|
||||
if (_prevHoveredObject.type == ENTITY) {
|
||||
emit pointerManager->hoverEndEntity(_prevHoveredObject.objectID, hoveredEvent);
|
||||
} else if (_prevHoveredObject.type == OVERLAY) {
|
||||
emit pointerManager->hoverEndOverlay(_prevHoveredObject.objectID, hoveredEvent);
|
||||
} else if (_prevHoveredObject.type == HUD) {
|
||||
emit pointerManager->hoverEndHUD(hoveredEvent);
|
||||
}
|
||||
}
|
||||
|
||||
_prevHoveredObject = hoveredObject;
|
||||
_prevButtons = buttons;
|
||||
_prevEnabled = _enabled;
|
||||
|
|
|
@ -82,14 +82,17 @@ protected:
|
|||
bool _enabled;
|
||||
bool _hover;
|
||||
|
||||
virtual PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, bool hover = true) const = 0;
|
||||
virtual PointerEvent buildPointerEvent(const PickedObject& target, const PickResultPointer& pickResult, const std::string& button = "", bool hover = true) = 0;
|
||||
|
||||
virtual PickedObject getHoveredObject(const PickResultPointer& pickResult) = 0;
|
||||
virtual Buttons getPressedButtons() = 0;
|
||||
virtual Buttons getPressedButtons(const PickResultPointer& pickResult) = 0;
|
||||
|
||||
virtual bool shouldHover(const PickResultPointer& pickResult) { return true; }
|
||||
virtual bool shouldTrigger(const PickResultPointer& pickResult) { return true; }
|
||||
|
||||
static const float POINTER_MOVE_DELAY;
|
||||
static const float TOUCH_PRESS_TO_MOVE_DEADSPOT_SQUARED;
|
||||
|
||||
private:
|
||||
PickedObject _prevHoveredObject;
|
||||
Buttons _prevButtons;
|
||||
|
|
|
@ -145,11 +145,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
return deltaTime;
|
||||
};
|
||||
|
||||
this.setIgnoreTablet = function() {
|
||||
this.setIgnorePointerItems = function() {
|
||||
if (HMD.tabletID !== this.tabletID) {
|
||||
this.tabletID = HMD.tabletID;
|
||||
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist.concat([HMD.tabletID]));
|
||||
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist.concat([HMD.tabletID]));
|
||||
Pointers.setIgnoreItems(_this.leftPointer, _this.blacklist);
|
||||
Pointers.setIgnoreItems(_this.rightPointer, _this.blacklist);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -168,7 +168,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
}
|
||||
var sensorScaleFactor = MyAvatar.sensorToWorldScale;
|
||||
var deltaTime = _this.updateTimings();
|
||||
_this.setIgnoreTablet();
|
||||
_this.setIgnorePointerItems();
|
||||
|
||||
if (controllerDispatcherPluginsNeedSort) {
|
||||
_this.orderedPluginNames = [];
|
||||
|
@ -182,16 +182,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
controllerDispatcherPlugins[b].parameters.priority;
|
||||
});
|
||||
|
||||
var output = "controllerDispatcher -- new plugin order: ";
|
||||
for (var k = 0; k < _this.orderedPluginNames.length; k++) {
|
||||
var dbgPluginName = _this.orderedPluginNames[k];
|
||||
var priority = controllerDispatcherPlugins[dbgPluginName].parameters.priority;
|
||||
output += dbgPluginName + ":" + priority;
|
||||
if (k + 1 < _this.orderedPluginNames.length) {
|
||||
output += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
controllerDispatcherPluginsNeedSort = false;
|
||||
}
|
||||
|
||||
|
@ -388,8 +378,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
};
|
||||
|
||||
this.setBlacklist = function() {
|
||||
RayPick.setIgnoreItems(_this.leftControllerRayPick, this.blacklist.concat(HMD.tabletID));
|
||||
RayPick.setIgnoreItems(_this.rightControllerRayPick, this.blacklist.concat(HMD.tabletID));
|
||||
RayPick.setIgnoreItems(_this.leftControllerRayPick, this.blacklist);
|
||||
RayPick.setIgnoreItems(_this.rightControllerRayPick, this.blacklist);
|
||||
};
|
||||
|
||||
var MAPPING_NAME = "com.highfidelity.controllerDispatcher";
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
|
||||
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI
|
||||
Picks, makeLaserLockInfo Xform
|
||||
Picks, makeLaserLockInfo Xform, makeLaserParams
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -119,7 +119,7 @@ Script.include("/~/system/libraries/Xform.js");
|
|||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100,
|
||||
this.hand);
|
||||
makeLaserParams(this.hand, false));
|
||||
|
||||
|
||||
this.handToController = function() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/* global Script, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, MyAvatar, getGrabPointSphereOffset,
|
||||
makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters,
|
||||
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||
DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData
|
||||
DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData, makeLaserParams
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -34,7 +34,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100,
|
||||
this.hand);
|
||||
makeLaserParams(this.hand, false));
|
||||
|
||||
this.getTargetProps = function (controllerData) {
|
||||
// nearbyEntityProperties is already sorted by length from controller
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION,
|
||||
PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD,
|
||||
DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic,
|
||||
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI
|
||||
getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI,
|
||||
makeLaserParams
|
||||
|
||||
*/
|
||||
(function() {
|
||||
|
@ -36,7 +37,7 @@
|
|||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100,
|
||||
(this.hand + HUD_LASER_OFFSET));
|
||||
makeLaserParams((this.hand + HUD_LASER_OFFSET), false));
|
||||
|
||||
this.getOtherHandController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
/* global Script, Controller, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule, makeRunningValues,
|
||||
Messages, makeDispatcherModuleParameters, HMD, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE,
|
||||
getEnabledModuleByName, PICK_MAX_DISTANCE, isInEditMode, LaserPointers, RayPick, Picks
|
||||
getEnabledModuleByName, PICK_MAX_DISTANCE, isInEditMode, LaserPointers, RayPick, Picks, makeLaserParams
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -28,7 +28,7 @@ Script.include("/~/system/libraries/utils.js");
|
|||
this.hand === RIGHT_HAND ? ["rightHand", "rightHandEquip", "rightHandTrigger"] : ["leftHand", "leftHandEquip", "leftHandTrigger"],
|
||||
[],
|
||||
100,
|
||||
this.hand);
|
||||
makeLaserParams(this.hand, false));
|
||||
|
||||
this.nearTablet = function(overlays) {
|
||||
for (var i = 0; i < overlays.length; i++) {
|
||||
|
@ -44,10 +44,7 @@ Script.include("/~/system/libraries/utils.js");
|
|||
};
|
||||
|
||||
this.pointingAtTablet = function(objectID) {
|
||||
if (objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID;
|
||||
};
|
||||
|
||||
this.sendPickData = function(controllerData) {
|
||||
|
@ -99,8 +96,8 @@ Script.include("/~/system/libraries/utils.js");
|
|||
var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightWebSurfaceLaserInput" : "LeftWebSurfaceLaserInput");
|
||||
if (overlayLaser) {
|
||||
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
||||
|
||||
if (overlayLaserReady.active && this.pointingAtTablet(overlayLaser.target)) {
|
||||
var target = controllerData.rayPicks[this.hand].objectID;
|
||||
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
|
||||
return this.exitModule();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* global Script, MyAvatar, RIGHT_HAND, LEFT_HAND, enableDispatcherModule, disableDispatcherModule,
|
||||
makeDispatcherModuleParameters, makeRunningValues, getEnabledModuleByName
|
||||
makeDispatcherModuleParameters, makeRunningValues, getEnabledModuleByName, makeLaserParams
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -19,15 +19,21 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
function InVREditMode(hand) {
|
||||
this.hand = hand;
|
||||
this.disableModules = false;
|
||||
var NO_HAND_LASER = -1; // Invalid hand parameter so that default laser is not displayed.
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
200, // Not too high otherwise the tablet laser doesn't work.
|
||||
this.hand === RIGHT_HAND
|
||||
? ["rightHand", "rightHandEquip", "rightHandTrigger"]
|
||||
: ["leftHand", "leftHandEquip", "leftHandTrigger"],
|
||||
[],
|
||||
100
|
||||
100,
|
||||
makeLaserParams(NO_HAND_LASER, false)
|
||||
);
|
||||
|
||||
this.pointingAtTablet = function (objectID) {
|
||||
return objectID === HMD.tabletScreenID || objectID === HMD.homeButtonID;
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
if (this.disableModules) {
|
||||
return makeRunningValues(true, [], []);
|
||||
|
@ -42,7 +48,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
}
|
||||
|
||||
// Tablet stylus.
|
||||
// Includes the tablet laser.
|
||||
var tabletStylusInput = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||
? "RightTabletStylusInput"
|
||||
: "LeftTabletStylusInput");
|
||||
|
@ -53,6 +58,18 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
|||
}
|
||||
}
|
||||
|
||||
// Tablet surface.
|
||||
var overlayLaser = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||
? "RightWebSurfaceLaserInput"
|
||||
: "LeftWebSurfaceLaserInput");
|
||||
if (overlayLaser) {
|
||||
var overlayLaserReady = overlayLaser.isReady(controllerData);
|
||||
var target = controllerData.rayPicks[this.hand].objectID;
|
||||
if (overlayLaserReady.active && this.pointingAtTablet(target)) {
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
}
|
||||
|
||||
// Tablet grabbing.
|
||||
var nearOverlay = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||
? "RightNearParentingGrabOverlay"
|
||||
|
|
|
@ -142,7 +142,10 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
if (this.processStylus(controllerData)) {
|
||||
var PREFER_STYLUS_OVER_LASER = "preferStylusOverLaser";
|
||||
var isUsingStylus = Settings.getValue(PREFER_STYLUS_OVER_LASER, false);
|
||||
|
||||
if (isUsingStylus && this.processStylus(controllerData)) {
|
||||
Pointers.enablePointer(this.pointer);
|
||||
return makeRunningValues(true, [], []);
|
||||
} else {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
makeRunningValues, Messages, Quat, Vec3, makeDispatcherModuleParameters, Overlays, ZERO_VEC, HMD,
|
||||
INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, getGrabPointSphereOffset, COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
|
||||
COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_ON_VALUE,
|
||||
TRIGGER_OFF_VALUE, getEnabledModuleByName, PICK_MAX_DISTANCE, LaserPointers, RayPick, ContextOverlay, Picks
|
||||
TRIGGER_OFF_VALUE, getEnabledModuleByName, PICK_MAX_DISTANCE, LaserPointers, RayPick, ContextOverlay, Picks, makeLaserParams
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -18,6 +18,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
(function() {
|
||||
function WebSurfaceLaserInput(hand) {
|
||||
this.hand = hand;
|
||||
this.otherHand = this.hand === RIGHT_HAND ? LEFT_HAND : RIGHT_HAND;
|
||||
this.running = false;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
|
@ -25,7 +26,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100,
|
||||
this.hand);
|
||||
makeLaserParams(hand, true));
|
||||
|
||||
this.grabModuleWantsNearbyOverlay = function(controllerData) {
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
|
@ -65,7 +66,8 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
};
|
||||
|
||||
this.deleteContextOverlay = function() {
|
||||
var farGrabModule = getEnabledModuleByName(this.hand === RIGHT_HAND ? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity");
|
||||
var farGrabModule = getEnabledModuleByName(this.hand === RIGHT_HAND
|
||||
? "RightFarActionGrabEntity" : "LeftFarActionGrabEntity");
|
||||
if (farGrabModule) {
|
||||
var entityWithContextOverlay = farGrabModule.entityWithContextOverlay;
|
||||
|
||||
|
@ -76,25 +78,50 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
}
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
this.updateAllwaysOn = function() {
|
||||
var PREFER_STYLUS_OVER_LASER = "preferStylusOverLaser";
|
||||
this.parameters.handLaser.allwaysOn = !Settings.getValue(PREFER_STYLUS_OVER_LASER, false);
|
||||
};
|
||||
|
||||
this.getDominantHand = function() {
|
||||
return MyAvatar.getDominantHand() === "right" ? 1 : 0;
|
||||
};
|
||||
|
||||
this.dominantHandOverride = false;
|
||||
|
||||
this.isReady = function(controllerData) {
|
||||
var otherModuleRunning = this.getOtherModule().running;
|
||||
if ((this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData)) &&
|
||||
!otherModuleRunning) {
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE) {
|
||||
otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand.
|
||||
var isTriggerPressed = controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE
|
||||
&& controllerData.triggerValues[this.otherHand] <= TRIGGER_OFF_VALUE;
|
||||
if ((!otherModuleRunning || isTriggerPressed)
|
||||
&& (this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData))) {
|
||||
this.updateAllwaysOn();
|
||||
if (isTriggerPressed) {
|
||||
this.dominantHandOverride = true; // Override dominant hand.
|
||||
this.getOtherModule().dominantHandOverride = false;
|
||||
}
|
||||
if (this.parameters.handLaser.allwaysOn || isTriggerPressed) {
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
}
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function (controllerData, deltaTime) {
|
||||
this.run = function(controllerData, deltaTime) {
|
||||
var otherModuleRunning = this.getOtherModule().running;
|
||||
otherModuleRunning = otherModuleRunning && this.getDominantHand() !== this.hand; // Auto-swap to dominant hand.
|
||||
otherModuleRunning = otherModuleRunning || this.getOtherModule().dominantHandOverride; // Override dominant hand.
|
||||
var grabModuleNeedsToRun = this.grabModuleWantsNearbyOverlay(controllerData);
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE && !grabModuleNeedsToRun) {
|
||||
if (!otherModuleRunning && !grabModuleNeedsToRun && (controllerData.triggerValues[this.hand] > TRIGGER_OFF_VALUE
|
||||
|| this.parameters.handLaser.allwaysOn
|
||||
&& (this.isPointingAtOverlay(controllerData) || this.isPointingAtWebEntity(controllerData)))) {
|
||||
this.running = true;
|
||||
return makeRunningValues(true, [], []);
|
||||
}
|
||||
this.deleteContextOverlay();
|
||||
this.running = false;
|
||||
this.dominantHandOverride = false;
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -118,7 +118,8 @@ WebTablet = function (url, width, dpi, hand, clientOnly, location, visible) {
|
|||
Overlays.deleteOverlay(this.webOverlayID);
|
||||
}
|
||||
|
||||
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.0) / sensorScaleFactor;
|
||||
var RAYPICK_OFFSET = 0.0001; // Sufficient for raypick to reliably intersect tablet screen before tablet model.
|
||||
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.0) / sensorScaleFactor + RAYPICK_OFFSET;
|
||||
var WEB_ENTITY_Y_OFFSET = 0.004;
|
||||
var screenWidth = 0.82 * tabletWidth;
|
||||
var screenHeight = 0.81 * tabletHeight;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
BUMPER_ON_VALUE:true,
|
||||
getEntityParents:true,
|
||||
findHandChildEntities:true,
|
||||
makeLaserParams:true,
|
||||
TEAR_AWAY_DISTANCE:true,
|
||||
TEAR_AWAY_COUNT:true,
|
||||
TEAR_AWAY_CHECK_TIME:true,
|
||||
|
@ -134,6 +135,17 @@ makeLaserLockInfo = function(targetID, isOverlay, hand, offset) {
|
|||
};
|
||||
};
|
||||
|
||||
makeLaserParams = function(hand, allwaysOn) {
|
||||
if (allwaysOn === undefined) {
|
||||
allwaysOn = false;
|
||||
}
|
||||
|
||||
return {
|
||||
hand: hand,
|
||||
allwaysOn: allwaysOn
|
||||
};
|
||||
};
|
||||
|
||||
makeRunningValues = function (active, targets, requiredDataForRun, laserLockInfo) {
|
||||
return {
|
||||
active: active,
|
||||
|
|
|
@ -95,6 +95,7 @@ Pointer = function(hudLayer, pickType, pointerData) {
|
|||
this.pointerID = null;
|
||||
this.visible = false;
|
||||
this.locked = false;
|
||||
this.allwaysOn = false;
|
||||
this.hand = pointerData.hand;
|
||||
delete pointerData.hand;
|
||||
|
||||
|
@ -150,7 +151,7 @@ Pointer = function(hudLayer, pickType, pointerData) {
|
|||
mode = "hold";
|
||||
} else if (triggerClicks[this.hand]) {
|
||||
mode = "full";
|
||||
} else if (triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
} else if (triggerValues[this.hand] > TRIGGER_ON_VALUE || this.allwaysOn) {
|
||||
mode = "half";
|
||||
}
|
||||
}
|
||||
|
@ -172,19 +173,23 @@ PointerManager = function() {
|
|||
return pointer.pointerID;
|
||||
};
|
||||
|
||||
this.makePointerVisible = function(index) {
|
||||
this.makePointerVisible = function(laserParams) {
|
||||
var index = laserParams.hand;
|
||||
if (index < this.pointers.length && index >= 0) {
|
||||
this.pointers[index].makeVisible();
|
||||
this.pointers[index].allwaysOn = laserParams.allwaysOn;
|
||||
}
|
||||
};
|
||||
|
||||
this.makePointerInvisible = function(index) {
|
||||
this.makePointerInvisible = function(laserParams) {
|
||||
var index = laserParams.hand;
|
||||
if (index < this.pointers.length && index >= 0) {
|
||||
this.pointers[index].makeInvisible();
|
||||
}
|
||||
};
|
||||
|
||||
this.lockPointerEnd = function(index, lockData) {
|
||||
this.lockPointerEnd = function(laserParams, lockData) {
|
||||
var index = laserParams.hand;
|
||||
if (index < this.pointers.length && index >= 0) {
|
||||
this.pointers[index].lockEnd(lockData);
|
||||
}
|
||||
|
|
|
@ -400,7 +400,8 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
|
|||
});
|
||||
|
||||
// update webOverlay
|
||||
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.0) * sensorScaleOffsetOverride;
|
||||
var RAYPICK_OFFSET = 0.0001; // Sufficient for raypick to reliably intersect tablet screen before tablet model.
|
||||
var WEB_ENTITY_Z_OFFSET = (tabletDepth / 2.0) * sensorScaleOffsetOverride + RAYPICK_OFFSET;
|
||||
var WEB_ENTITY_Y_OFFSET = 0.004 * sensorScaleFactor * sensorScaleOffsetOverride;
|
||||
var screenWidth = 0.82 * tabletWidth;
|
||||
var screenHeight = 0.81 * tabletHeight;
|
||||
|
@ -417,11 +418,13 @@ resizeTablet = function (width, newParentJointIndex, sensorToWorldScaleOverride)
|
|||
var homeButtonDim = 4.0 * tabletScaleFactor / 3.0;
|
||||
Overlays.editOverlay(HMD.homeButtonID, {
|
||||
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
|
||||
localRotation: Quat.angleAxis(180, Vec3.UNIT_Y),
|
||||
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
||||
});
|
||||
|
||||
Overlays.editOverlay(HMD.homeButtonHighlightID, {
|
||||
localPosition: { x: 0, y: -HOME_BUTTON_Y_OFFSET, z: -WEB_ENTITY_Z_OFFSET },
|
||||
localRotation: Quat.angleAxis(180, Vec3.UNIT_Y),
|
||||
dimensions: { x: homeButtonDim, y: homeButtonDim, z: homeButtonDim }
|
||||
});
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue