overte/scripts/system/libraries/touchEventUtils.js
pull[bot] 2f359cc15f
[pull] master from overte-org:master (#93)
* mirrors wip

* fix view + projection, texture flipping, billboarding

* wip portals

* wip

* fix cpu frustum culling (hacky?)

* fix mirrors in deferred

* mirrors on models + text

* portals use exit as ignoreItem

* cleanup

* entity tags

* wild guess to handle view correction, hide portalExitID in create when mirrorMode != portal

* let's try this??

* plz

* promising

* fix paramsOffset and view flipping

* portals shouldn't flip

* break when tag found

* fix portal view calculation

* Revert "Mirrors + Portals"

* Revert "Revert "Mirrors + Portals""

* web entity wantsKeyboardFocus property

* fix typo

* move audio zones to zone entity properties

* fix audio zones in create

* set dynamic factory

* new procecural particle entity type

* fix particle intersection

* shorten create labels

* fix 0 update props case

* Ability to smooth model animations

* sound entities

* fix layered simulate items

* fix stereo sound speed

* support non-localOnly sound avatar entities

* add sound url prompt

* support registration point, improve locking

* remove keyboardRasied

* locking attempt #2

* fix keyboardRasied typo

* add default particle props

* add unlit property for shapes

* Merge branch master into protocol_changes

* add ambient light color

* fix create issue

* fix create issue

* add tonemapping props to zones, wip ambient occlusion

* wip ambient occlusion

* it's working!

* remove attachments

* fix non-localOnly positional sounds not updating

* change AO default to HBAO, remove from create

* more graphics options

* fix AO setting + effects in mirrors

* fix AA in mirrors

* alezia's fixes

* fix haze in mirrors

* add comment for SKYBOX_DISTANCE

* new line

* model loading priority updates over time, takes into account out of bounds, avatar entities have higher priority, and fsts can specify to wait for wearables to load before rendering

* add loadPriority to model entities, working on other avatars waitForWearables

* fix build error

* try to fix isServer assert

* fix stats + waitForWearables

* Listen for click instead of release.

* Reverted initial commit. Implemented hack to listen for menu click events.

* Missed some reverts.

* Missed another one.

* Prevent duplicate actions.

* Added extra needed checks.

* Fix without formatting? (#91)

* Hopefully fixed formatting.

* Things can't be too easy.

* Remove google poly

* automated entity property serialization

* cleanup + automate EntityPropertyFlags

* text vertical alignment, use uint8_t for entity property enums, fix text recalculating too often

* fix text size

* Update interface/resources/controllers/keyboardMouse.json

Co-authored-by: HifiExperiments <53453710+HifiExperiments@users.noreply.github.com>

* fix component mode serialization

* Fixed mouse look in selfie mode.

* fix text debug assert on invalid or unloaded font

* missed some enums

* fix ADD_GROUP_PROPERTY_TO_MAP

* fix PROP_GRAB_EQUIPPABLE_INDICATOR_URL missing urlPermission

* fix KeyLightPropertyGroup legacy properties

* fix PolyLineEntityItem::getEntityProperties

* comment cmake script

* fix copyright

* Replaced key value with key text.
Added additional comment about the specific delete key used.

* weekly promoted place

Highlight the first place in the list as the weekly promoted place

* Fixed lingering references to `avatarIcon`.

Signed-off-by: armored-dragon <publicmail@armoreddragon.com>

* Adding icon for "Grab And Equip" section

Adding icon for "Grab And Equip" section

* Add "Grab And Equip" section

Add "Grab And Equip" section for the grabbale and Equipable groups of properties.

* Add files via upload

* Add tooltips for the "Grab and Equip" properties

Add the tooltips for the "Grab and Equip" properties

* Text adjustments for grab.equippable

Text adjustments for grab.equippable

* Make Maturity Filter persisted

Make Maturity Filter persisted and with a default value (Teen & Everyone)

* Adjust the default value for maturity

Adjust the default value for maturity

* move "triggerable" under GRAB & EQUIP

move "triggerable" under GRAB & EQUIP

* Remove hifi-screenshare
Cherry picked and updated from Tivoli dd5b6ea6ee5597a06603e16509640e7ed18106bb

Co-authored-by: Julian Groß <julian.g@posteo.de>

* Insert placeholder to not break protocol yet.

* Fix incorrectly resolved merge conflict, left too much code.

* Fixes based on review comments on previous PR

* Remove code accidentally re-added during a conflict fix

* bump protocol

* rebuild fonts with full charset (NOT -allglyphs)

* Attempt at fixing Windows master branch builds

* Change minimum angular velocity to a lower one

* Fix Uuid.NULL behavior

---------

Signed-off-by: armored-dragon <publicmail@armoreddragon.com>
Co-authored-by: HifiExperiments <thingsandstuffblog@gmail.com>
Co-authored-by: ksuprynowicz <ksuprynowicz@post.pl>
Co-authored-by: Dale Glass <51060919+daleglass@users.noreply.github.com>
Co-authored-by: HifiExperiments <53453710+HifiExperiments@users.noreply.github.com>
Co-authored-by: Julian Groß <julian.g@posteo.de>
Co-authored-by: armored-dragon <publicmail@armoreddragon.com>
Co-authored-by: Armored-Dragon <github56254@armoreddragon.com>
Co-authored-by: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com>
Co-authored-by: Maki <mxmcube@gmail.com>
Co-authored-by: Dale Glass <dale@daleglass.net>
2024-10-24 06:32:53 +00:00

251 lines
10 KiB
JavaScript

"use strict";
// touchEventUtils.js
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
enableDispatcherModule, disableDispatcherModule, makeRunningValues,
Messages, Quat, Vec3, getControllerWorldLocation, makeDispatcherModuleParameters, Overlays, controllerDispatcher.ZERO_VEC,
HMD, INCHES_TO_METERS, DEFAULT_REGISTRATION_POINT, Settings, getGrabPointSphereOffset
*/
var controllerDispatcher = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
function touchTargetHasKeyboardFocus(touchTarget) {
if (touchTarget.entityID && touchTarget.entityID !== Uuid.NONE) {
return Entities.keyboardFocusEntity === touchTarget.entityID;
} else if (touchTarget.overlayID && touchTarget.overlayID !== Uuid.NONE) {
return Overlays.keyboardFocusOverlay === touchTarget.overlayID;
}
}
function setKeyboardFocusOnTouchTarget(touchTarget) {
if (touchTarget.entityID && touchTarget.entityID !== Uuid.NONE &&
Entities.wantsHandControllerPointerEvents(touchTarget.entityID)) {
Overlays.keyboardFocusOverlay = Uuid.NONE;
Entities.keyboardFocusEntity = touchTarget.entityID;
} else if (touchTarget.overlayID && touchTarget.overlayID !== Uuid.NONE) {
Overlays.keyboardFocusOverlay = touchTarget.overlayID;
Entities.keyboardFocusEntity = Uuid.NONE;
}
}
function sendHoverEnterEventToTouchTarget(hand, touchTarget) {
var pointerEvent = {
type: "Move",
id: hand + 1, // 0 is reserved for hardware mouse
pos2D: touchTarget.position2D,
pos3D: touchTarget.position,
normal: touchTarget.normal,
direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal),
button: "None"
};
if (touchTarget.entityID && touchTarget.entityID !== Uuid.NONE) {
Entities.sendHoverEnterEntity(touchTarget.entityID, pointerEvent);
} else if (touchTarget.overlayID && touchTarget.overlayID !== Uuid.NONE) {
Overlays.sendHoverEnterOverlay(touchTarget.overlayID, pointerEvent);
}
}
function sendHoverOverEventToTouchTarget(hand, touchTarget) {
var pointerEvent = {
type: "Move",
id: hand + 1, // 0 is reserved for hardware mouse
pos2D: touchTarget.position2D,
pos3D: touchTarget.position,
normal: touchTarget.normal,
direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal),
button: "None"
};
if (touchTarget.entityID && touchTarget.entityID !== Uuid.NONE) {
Entities.sendMouseMoveOnEntity(touchTarget.entityID, pointerEvent);
Entities.sendHoverOverEntity(touchTarget.entityID, pointerEvent);
} else if (touchTarget.overlayID && touchTarget.overlayID !== Uuid.NONE) {
Overlays.sendMouseMoveOnOverlay(touchTarget.overlayID, pointerEvent);
Overlays.sendHoverOverOverlay(touchTarget.overlayID, pointerEvent);
}
}
function sendTouchStartEventToTouchTarget(hand, touchTarget) {
var pointerEvent = {
type: "Press",
id: hand + 1, // 0 is reserved for hardware mouse
pos2D: touchTarget.position2D,
pos3D: touchTarget.position,
normal: touchTarget.normal,
direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal),
button: "Primary",
isPrimaryHeld: true
};
if (touchTarget.entityID && touchTarget.entityID !== Uuid.NONE) {
Entities.sendMousePressOnEntity(touchTarget.entityID, pointerEvent);
Entities.sendClickDownOnEntity(touchTarget.entityID, pointerEvent);
} else if (touchTarget.overlayID && touchTarget.overlayID !== Uuid.NONE) {
Overlays.sendMousePressOnOverlay(touchTarget.overlayID, pointerEvent);
}
}
function sendTouchEndEventToTouchTarget(hand, touchTarget) {
var pointerEvent = {
type: "Release",
id: hand + 1, // 0 is reserved for hardware mouse
pos2D: touchTarget.position2D,
pos3D: touchTarget.position,
normal: touchTarget.normal,
direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal),
button: "Primary"
};
if (touchTarget.entityID && touchTarget.entityID !== Uuid.NONE) {
Entities.sendMouseReleaseOnEntity(touchTarget.entityID, pointerEvent);
Entities.sendClickReleaseOnEntity(touchTarget.entityID, pointerEvent);
Entities.sendHoverLeaveEntity(touchTarget.entityID, pointerEvent);
} else if (touchTarget.overlayID && touchTarget.overlayID !== Uuid.NONE) {
Overlays.sendMouseReleaseOnOverlay(touchTarget.overlayID, pointerEvent);
}
}
function sendTouchMoveEventToTouchTarget(hand, touchTarget) {
var pointerEvent = {
type: "Move",
id: hand + 1, // 0 is reserved for hardware mouse
pos2D: touchTarget.position2D,
pos3D: touchTarget.position,
normal: touchTarget.normal,
direction: Vec3.subtract(controllerDispatcher.ZERO_VEC, touchTarget.normal),
button: "Primary",
isPrimaryHeld: true
};
if (touchTarget.entityID && touchTarget.entityID !== Uuid.NONE) {
Entities.sendMouseMoveOnEntity(touchTarget.entityID, pointerEvent);
Entities.sendHoldingClickOnEntity(touchTarget.entityID, pointerEvent);
} else if (touchTarget.overlayID && touchTarget.overlayID !== Uuid.NONE) {
Overlays.sendMouseMoveOnOverlay(touchTarget.overlayID, pointerEvent);
}
}
function composeTouchTargetFromIntersection(intersection) {
var isEntity = (intersection.type === Picks.INTERSECTED_ENTITY);
var objectID = intersection.objectID;
var worldPos = intersection.intersection;
var props = null;
if (isEntity) {
props = Entities.getProperties(intersection.objectID);
}
var position2D =(isEntity ? controllerDispatcher.projectOntoEntityXYPlane(objectID, worldPos, props) :
controllerDispatcher.projectOntoOverlayXYPlane(objectID, worldPos));
return {
entityID: isEntity ? objectID : null,
overlayID: isEntity ? null : objectID,
distance: intersection.distance,
position: worldPos,
position2D: position2D,
normal: intersection.surfaceNormal
};
}
// will return undefined if overlayID does not exist.
function calculateTouchTargetFromOverlay(touchTip, overlayID) {
var overlayPosition = Entities.getEntityProperties(overlayID, ["position"]).position;
if (overlayPosition === undefined) {
return;
}
// project touchTip onto overlay plane.
var overlayRotation = Entities.getEntityProperties(overlayID, ["rotation"]).rotation;
if (overlayRotation === undefined) {
return;
}
var normal = Vec3.multiplyQbyV(overlayRotation, {x: 0, y: 0, z: 1});
var distance = Vec3.dot(Vec3.subtract(touchTip.position, overlayPosition), normal);
var position = Vec3.subtract(touchTip.position, Vec3.multiply(normal, distance));
// calclulate normalized position
var invRot = Quat.inverse(overlayRotation);
var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(position, overlayPosition));
// V8TODO: check if this is correct for entities
var dimensions = Entities.getEntityProperties(overlayID, ["dimensions"]).dimensions;
if (dimensions === undefined) {
return;
}
dimensions.z = 0.01; // we are projecting onto the XY plane of the overlay, so ignore the z dimension
var invDimensions = { x: 1 / dimensions.x, y: 1 / dimensions.y, z: 1 / dimensions.z };
var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), DEFAULT_REGISTRATION_POINT);
// 2D position on overlay plane in meters, relative to the bounding box upper-left hand corner.
var position2D = {
x: normalizedPosition.x * dimensions.x,
y: (1 - normalizedPosition.y) * dimensions.y // flip y-axis
};
return {
entityID: null,
overlayID: overlayID,
distance: distance,
position: position,
position2D: position2D,
normal: normal,
normalizedPosition: normalizedPosition,
dimensions: dimensions,
valid: true
};
}
// will return undefined if entity does not exist.
function calculateTouchTargetFromEntity(touchTip, props) {
if (props.rotation === undefined) {
// if rotation is missing from props object, then this entity has probably been deleted.
return;
}
// project touch tip onto entity plane.
var normal = Vec3.multiplyQbyV(props.rotation, {x: 0, y: 0, z: 1});
Vec3.multiplyQbyV(props.rotation, {x: 0, y: 1, z: 0});
var distance = Vec3.dot(Vec3.subtract(touchTip.position, props.position), normal);
var position = Vec3.subtract(touchTip.position, Vec3.multiply(normal, distance));
// generate normalized coordinates
var invRot = Quat.inverse(props.rotation);
var localPos = Vec3.multiplyQbyV(invRot, Vec3.subtract(position, props.position));
var invDimensions = { x: 1 / props.dimensions.x, y: 1 / props.dimensions.y, z: 1 / props.dimensions.z };
var normalizedPosition = Vec3.sum(Vec3.multiplyVbyV(localPos, invDimensions), props.registrationPoint);
// 2D position on entity plane in meters, relative to the bounding box upper-left hand corner.
var position2D = {
x: normalizedPosition.x * props.dimensions.x,
y: (1 - normalizedPosition.y) * props.dimensions.y // flip y-axis
};
return {
entityID: props.id,
entityProps: props,
overlayID: null,
distance: distance,
position: position,
position2D: position2D,
normal: normal,
normalizedPosition: normalizedPosition,
dimensions: props.dimensions,
valid: true
};
}
module.exports = {
calculateTouchTargetFromEntity: calculateTouchTargetFromEntity,
calculateTouchTargetFromOverlay: calculateTouchTargetFromOverlay,
touchTargetHasKeyboardFocus: touchTargetHasKeyboardFocus,
setKeyboardFocusOnTouchTarget: setKeyboardFocusOnTouchTarget,
sendHoverEnterEventToTouchTarget: sendHoverEnterEventToTouchTarget,
sendHoverOverEventToTouchTarget: sendHoverOverEventToTouchTarget,
sendTouchStartEventToTouchTarget: sendTouchStartEventToTouchTarget,
sendTouchEndEventToTouchTarget: sendTouchEndEventToTouchTarget,
sendTouchMoveEventToTouchTarget: sendTouchMoveEventToTouchTarget,
composeTouchTargetFromIntersection: composeTouchTargetFromIntersection
};