136 lines · 4.0 KB · JavaScript
RawDownload
"use strict";////  androidControls.js////  Created by keeshii on September 26th, 2023.//  Copyright 2022-2023 Overte e.V.////  This script read touch screen events and triggers mouse events.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//  SPDX-License-Identifier: Apache-2.0// (function () {   Script.include("/~/system/libraries/controllerDispatcherUtils.js");  var DISPATCHER_TOUCH_PROPERTIES = ["id", "position", "rotation", "dimensions", "registrationPoint"];   var TAP_DELAY = 300;   function AndroidControls() {    this.onTouchStartFn = null;    this.onTouchEndFn = null;    this.touchStartTime = 0;  }   AndroidControls.prototype.intersectsEntity = function (intersection) {    if (intersection && intersection.intersects && intersection.entityID) {      return true;    }    return false;  };   AndroidControls.prototype.findRayIntersection = function (pickRay) {    // Check all entities. Argument is an object with origin and direction.    var entityRayIntersection = Entities.findRayIntersection(pickRay, Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_AVATAR_ENTITIES | Picks.PICK_LOCAL_ENTITIES);    var isEntityInters = this.intersectsEntity(entityRayIntersection);     if (isEntityInters) {      return {type: 'entity', obj: entityRayIntersection};    }    return false;  };   AndroidControls.prototype.createEventProperties = function (entityId, info, eventType) {    var pointerEvent = {      type: eventType,      id: 1,      pos2D: {x: 0, y: 0},      pos3D: info.obj.intersection,      normal: info.obj.surfaceNormal,      direction: info.obj.direction,      button: "Primary",      isPrimaryButton: true,      isLeftButton: true,      isPrimaryHeld: eventType === 'Press',      isSecondaryHeld: false,      isTertiaryHeld: false,      keyboardModifiers: 0    };     var properties = Entities.getEntityProperties(entityId, DISPATCHER_TOUCH_PROPERTIES);    if (properties.id === entityId) {      pointerEvent.pos2D = projectOntoEntityXYPlane(entityId, info.obj.intersection, properties);    }     return pointerEvent;  };   AndroidControls.prototype.triggerClick = function (event) {    var info = this.findRayIntersection(Camera.computePickRay(event.x, event.y));     if (!info) {      return;    }     var entityId = info.obj.entityID;    var pressEvent = this.createEventProperties(entityId, info, 'Press');    var releaseEvent = this.createEventProperties(entityId, info, 'Release');     Entities.sendMousePressOnEntity(entityId, pressEvent);    Entities.sendClickDownOnEntity(entityId, pressEvent);     Script.setTimeout(function () {      Entities.sendMouseReleaseOnEntity(entityId, releaseEvent);      Entities.sendClickReleaseOnEntity(entityId, releaseEvent);    }, 75);  };   AndroidControls.prototype.onTouchStart = function (_event) {    this.touchStartTime = Date.now();  };   AndroidControls.prototype.onTouchEnd = function (event) {    var now = Date.now();    if (now - this.touchStartTime < TAP_DELAY) {      this.triggerClick(event);    }    this.touchStartTime = 0;  };   AndroidControls.prototype.init = function () {    var self = this;    this.onTouchStartFn = function (ev) {      self.onTouchStart(ev);    };    this.onTouchEndFn = function (ev) {      self.onTouchEnd(ev);    };     Controller.touchBeginEvent.connect(this.onTouchStartFn);    Controller.touchEndEvent.connect(this.onTouchEndFn);  };   AndroidControls.prototype.ending = function () {    if (this.onTouchStartFn) {      Controller.touchBeginEvent.disconnect(this.onTouchStartFn);    }    if (this.onTouchEndFn) {      Controller.touchEndEvent.disconnect(this.onTouchEndFn);    }    this.touchStartTime = 0;    this.onTouchStartFn = null;    this.onTouchEndFn = null;  };   var androidControls = new AndroidControls();   Script.scriptEnding.connect(function () {    androidControls.ending();  });  androidControls.init();   module.exports = androidControls;}());