123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476 |
- import { WebXRAbstractMotionController } from "./webXRAbstractMotionController.js";
- import { WebXRMotionControllerManager } from "./webXRMotionControllerManager.js";
- import { Mesh } from "../../Meshes/mesh.js";
- import { Quaternion } from "../../Maths/math.vector.js";
- import { SceneLoader } from "../../Loading/sceneLoader.js";
- import { Logger } from "../../Misc/logger.js";
- /**
- * The motion controller class for all microsoft mixed reality controllers
- */
- export class WebXRMicrosoftMixedRealityController extends WebXRAbstractMotionController {
- constructor(scene, gamepadObject, handedness) {
- super(scene, MixedRealityProfile["left-right"], gamepadObject, handedness);
- // use this in the future - https://github.com/immersive-web/webxr-input-profiles/tree/master/packages/assets/profiles/microsoft
- this._mapping = {
- defaultButton: {
- valueNodeName: "VALUE",
- unpressedNodeName: "UNPRESSED",
- pressedNodeName: "PRESSED",
- },
- defaultAxis: {
- valueNodeName: "VALUE",
- minNodeName: "MIN",
- maxNodeName: "MAX",
- },
- buttons: {
- "xr-standard-trigger": {
- rootNodeName: "SELECT",
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- },
- "xr-standard-squeeze": {
- rootNodeName: "GRASP",
- componentProperty: "state",
- states: ["pressed"],
- },
- "xr-standard-touchpad": {
- rootNodeName: "TOUCHPAD_PRESS",
- labelAnchorNodeName: "squeeze-label",
- touchPointNodeName: "TOUCH", // TODO - use this for visual feedback
- },
- "xr-standard-thumbstick": {
- rootNodeName: "THUMBSTICK_PRESS",
- componentProperty: "state",
- states: ["pressed"],
- },
- },
- axes: {
- "xr-standard-touchpad": {
- "x-axis": {
- rootNodeName: "TOUCHPAD_TOUCH_X",
- },
- "y-axis": {
- rootNodeName: "TOUCHPAD_TOUCH_Y",
- },
- },
- "xr-standard-thumbstick": {
- "x-axis": {
- rootNodeName: "THUMBSTICK_X",
- },
- "y-axis": {
- rootNodeName: "THUMBSTICK_Y",
- },
- },
- },
- };
- this.profileId = "microsoft-mixed-reality";
- }
- _getFilenameAndPath() {
- let filename = "";
- if (this.handedness === "left") {
- filename = WebXRMicrosoftMixedRealityController.MODEL_LEFT_FILENAME;
- }
- else {
- // Right is the default if no hand is specified
- filename = WebXRMicrosoftMixedRealityController.MODEL_RIGHT_FILENAME;
- }
- const device = "default";
- const path = WebXRMicrosoftMixedRealityController.MODEL_BASE_URL + device + "/";
- return {
- filename,
- path,
- };
- }
- _getModelLoadingConstraints() {
- const glbLoaded = SceneLoader.IsPluginForExtensionAvailable(".glb");
- if (!glbLoaded) {
- Logger.Warn("glTF / glb loaded was not registered, using generic controller instead");
- }
- return glbLoaded;
- }
- _processLoadedModel(_meshes) {
- if (!this.rootMesh) {
- return;
- }
- // Button Meshes
- this.getComponentIds().forEach((id, i) => {
- if (this.disableAnimation) {
- return;
- }
- if (id && this.rootMesh) {
- const buttonMap = this._mapping.buttons[id];
- const buttonMeshName = buttonMap.rootNodeName;
- if (!buttonMeshName) {
- Logger.Log("Skipping unknown button at index: " + i + " with mapped name: " + id);
- return;
- }
- const buttonMesh = this._getChildByName(this.rootMesh, buttonMeshName);
- if (!buttonMesh) {
- Logger.Warn("Missing button mesh with name: " + buttonMeshName);
- return;
- }
- buttonMap.valueMesh = this._getImmediateChildByName(buttonMesh, this._mapping.defaultButton.valueNodeName);
- buttonMap.pressedMesh = this._getImmediateChildByName(buttonMesh, this._mapping.defaultButton.pressedNodeName);
- buttonMap.unpressedMesh = this._getImmediateChildByName(buttonMesh, this._mapping.defaultButton.unpressedNodeName);
- if (buttonMap.valueMesh && buttonMap.pressedMesh && buttonMap.unpressedMesh) {
- const comp = this.getComponent(id);
- if (comp) {
- comp.onButtonStateChangedObservable.add((component) => {
- this._lerpTransform(buttonMap, component.value);
- }, undefined, true);
- }
- }
- else {
- // If we didn't find the mesh, it simply means this button won't have transforms applied as mapped button value changes.
- Logger.Warn("Missing button submesh under mesh with name: " + buttonMeshName);
- }
- }
- });
- // Axis Meshes
- this.getComponentIds().forEach((id) => {
- const comp = this.getComponent(id);
- if (!comp.isAxes()) {
- return;
- }
- ["x-axis", "y-axis"].forEach((axis) => {
- if (!this.rootMesh) {
- return;
- }
- const axisMap = this._mapping.axes[id][axis];
- const axisMesh = this._getChildByName(this.rootMesh, axisMap.rootNodeName);
- if (!axisMesh) {
- Logger.Warn("Missing axis mesh with name: " + axisMap.rootNodeName);
- return;
- }
- axisMap.valueMesh = this._getImmediateChildByName(axisMesh, this._mapping.defaultAxis.valueNodeName);
- axisMap.minMesh = this._getImmediateChildByName(axisMesh, this._mapping.defaultAxis.minNodeName);
- axisMap.maxMesh = this._getImmediateChildByName(axisMesh, this._mapping.defaultAxis.maxNodeName);
- if (axisMap.valueMesh && axisMap.minMesh && axisMap.maxMesh) {
- if (comp) {
- comp.onAxisValueChangedObservable.add((axisValues) => {
- const value = axis === "x-axis" ? axisValues.x : axisValues.y;
- this._lerpTransform(axisMap, value, true);
- }, undefined, true);
- }
- }
- else {
- // If we didn't find the mesh, it simply means this button won't have transforms applied as mapped button value changes.
- Logger.Warn("Missing axis submesh under mesh with name: " + axisMap.rootNodeName);
- }
- });
- });
- }
- _setRootMesh(meshes) {
- this.rootMesh = new Mesh(this.profileId + " " + this.handedness, this.scene);
- this.rootMesh.isPickable = false;
- let rootMesh;
- // Find the root node in the loaded glTF scene, and attach it as a child of 'parentMesh'
- for (let i = 0; i < meshes.length; i++) {
- const mesh = meshes[i];
- mesh.isPickable = false;
- if (!mesh.parent) {
- // Handle root node, attach to the new parentMesh
- rootMesh = mesh;
- }
- }
- if (rootMesh) {
- rootMesh.setParent(this.rootMesh);
- }
- if (!this.scene.useRightHandedSystem) {
- this.rootMesh.rotationQuaternion = Quaternion.FromEulerAngles(0, Math.PI, 0);
- }
- }
- _updateModel() {
- // no-op. model is updated using observables.
- }
- }
- /**
- * The base url used to load the left and right controller models
- */
- WebXRMicrosoftMixedRealityController.MODEL_BASE_URL = "https://controllers.babylonjs.com/microsoft/";
- /**
- * The name of the left controller model file
- */
- WebXRMicrosoftMixedRealityController.MODEL_LEFT_FILENAME = "left.glb";
- /**
- * The name of the right controller model file
- */
- WebXRMicrosoftMixedRealityController.MODEL_RIGHT_FILENAME = "right.glb";
- // register the profile
- WebXRMotionControllerManager.RegisterController("windows-mixed-reality", (xrInput, scene) => {
- return new WebXRMicrosoftMixedRealityController(scene, xrInput.gamepad, xrInput.handedness);
- });
- // https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/microsoft/microsoft-mixed-reality.json
- const MixedRealityProfile = {
- left: {
- selectComponentId: "xr-standard-trigger",
- components: {
- "xr-standard-trigger": {
- type: "trigger",
- gamepadIndices: {
- button: 0,
- },
- rootNodeName: "xr_standard_trigger",
- visualResponses: {
- xr_standard_trigger_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_trigger_pressed_value",
- minNodeName: "xr_standard_trigger_pressed_min",
- maxNodeName: "xr_standard_trigger_pressed_max",
- },
- },
- },
- "xr-standard-squeeze": {
- type: "squeeze",
- gamepadIndices: {
- button: 1,
- },
- rootNodeName: "xr_standard_squeeze",
- visualResponses: {
- xr_standard_squeeze_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_squeeze_pressed_value",
- minNodeName: "xr_standard_squeeze_pressed_min",
- maxNodeName: "xr_standard_squeeze_pressed_max",
- },
- },
- },
- "xr-standard-touchpad": {
- type: "touchpad",
- gamepadIndices: {
- button: 2,
- xAxis: 0,
- yAxis: 1,
- },
- rootNodeName: "xr_standard_touchpad",
- visualResponses: {
- xr_standard_touchpad_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_pressed_value",
- minNodeName: "xr_standard_touchpad_pressed_min",
- maxNodeName: "xr_standard_touchpad_pressed_max",
- },
- xr_standard_touchpad_xaxis_pressed: {
- componentProperty: "xAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_xaxis_pressed_value",
- minNodeName: "xr_standard_touchpad_xaxis_pressed_min",
- maxNodeName: "xr_standard_touchpad_xaxis_pressed_max",
- },
- xr_standard_touchpad_yaxis_pressed: {
- componentProperty: "yAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_yaxis_pressed_value",
- minNodeName: "xr_standard_touchpad_yaxis_pressed_min",
- maxNodeName: "xr_standard_touchpad_yaxis_pressed_max",
- },
- xr_standard_touchpad_xaxis_touched: {
- componentProperty: "xAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_xaxis_touched_value",
- minNodeName: "xr_standard_touchpad_xaxis_touched_min",
- maxNodeName: "xr_standard_touchpad_xaxis_touched_max",
- },
- xr_standard_touchpad_yaxis_touched: {
- componentProperty: "yAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_yaxis_touched_value",
- minNodeName: "xr_standard_touchpad_yaxis_touched_min",
- maxNodeName: "xr_standard_touchpad_yaxis_touched_max",
- },
- xr_standard_touchpad_axes_touched: {
- componentProperty: "state",
- states: ["touched", "pressed"],
- valueNodeProperty: "visibility",
- valueNodeName: "xr_standard_touchpad_axes_touched_value",
- },
- },
- touchPointNodeName: "xr_standard_touchpad_axes_touched_value",
- },
- "xr-standard-thumbstick": {
- type: "thumbstick",
- gamepadIndices: {
- button: 3,
- xAxis: 2,
- yAxis: 3,
- },
- rootNodeName: "xr_standard_thumbstick",
- visualResponses: {
- xr_standard_thumbstick_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_thumbstick_pressed_value",
- minNodeName: "xr_standard_thumbstick_pressed_min",
- maxNodeName: "xr_standard_thumbstick_pressed_max",
- },
- xr_standard_thumbstick_xaxis_pressed: {
- componentProperty: "xAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_thumbstick_xaxis_pressed_value",
- minNodeName: "xr_standard_thumbstick_xaxis_pressed_min",
- maxNodeName: "xr_standard_thumbstick_xaxis_pressed_max",
- },
- xr_standard_thumbstick_yaxis_pressed: {
- componentProperty: "yAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_thumbstick_yaxis_pressed_value",
- minNodeName: "xr_standard_thumbstick_yaxis_pressed_min",
- maxNodeName: "xr_standard_thumbstick_yaxis_pressed_max",
- },
- },
- },
- },
- gamepadMapping: "xr-standard",
- rootNodeName: "microsoft-mixed-reality-left",
- assetPath: "left.glb",
- },
- right: {
- selectComponentId: "xr-standard-trigger",
- components: {
- "xr-standard-trigger": {
- type: "trigger",
- gamepadIndices: {
- button: 0,
- },
- rootNodeName: "xr_standard_trigger",
- visualResponses: {
- xr_standard_trigger_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_trigger_pressed_value",
- minNodeName: "xr_standard_trigger_pressed_min",
- maxNodeName: "xr_standard_trigger_pressed_max",
- },
- },
- },
- "xr-standard-squeeze": {
- type: "squeeze",
- gamepadIndices: {
- button: 1,
- },
- rootNodeName: "xr_standard_squeeze",
- visualResponses: {
- xr_standard_squeeze_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_squeeze_pressed_value",
- minNodeName: "xr_standard_squeeze_pressed_min",
- maxNodeName: "xr_standard_squeeze_pressed_max",
- },
- },
- },
- "xr-standard-touchpad": {
- type: "touchpad",
- gamepadIndices: {
- button: 2,
- xAxis: 0,
- yAxis: 1,
- },
- rootNodeName: "xr_standard_touchpad",
- visualResponses: {
- xr_standard_touchpad_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_pressed_value",
- minNodeName: "xr_standard_touchpad_pressed_min",
- maxNodeName: "xr_standard_touchpad_pressed_max",
- },
- xr_standard_touchpad_xaxis_pressed: {
- componentProperty: "xAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_xaxis_pressed_value",
- minNodeName: "xr_standard_touchpad_xaxis_pressed_min",
- maxNodeName: "xr_standard_touchpad_xaxis_pressed_max",
- },
- xr_standard_touchpad_yaxis_pressed: {
- componentProperty: "yAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_yaxis_pressed_value",
- minNodeName: "xr_standard_touchpad_yaxis_pressed_min",
- maxNodeName: "xr_standard_touchpad_yaxis_pressed_max",
- },
- xr_standard_touchpad_xaxis_touched: {
- componentProperty: "xAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_xaxis_touched_value",
- minNodeName: "xr_standard_touchpad_xaxis_touched_min",
- maxNodeName: "xr_standard_touchpad_xaxis_touched_max",
- },
- xr_standard_touchpad_yaxis_touched: {
- componentProperty: "yAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_touchpad_yaxis_touched_value",
- minNodeName: "xr_standard_touchpad_yaxis_touched_min",
- maxNodeName: "xr_standard_touchpad_yaxis_touched_max",
- },
- xr_standard_touchpad_axes_touched: {
- componentProperty: "state",
- states: ["touched", "pressed"],
- valueNodeProperty: "visibility",
- valueNodeName: "xr_standard_touchpad_axes_touched_value",
- },
- },
- touchPointNodeName: "xr_standard_touchpad_axes_touched_value",
- },
- "xr-standard-thumbstick": {
- type: "thumbstick",
- gamepadIndices: {
- button: 3,
- xAxis: 2,
- yAxis: 3,
- },
- rootNodeName: "xr_standard_thumbstick",
- visualResponses: {
- xr_standard_thumbstick_pressed: {
- componentProperty: "button",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_thumbstick_pressed_value",
- minNodeName: "xr_standard_thumbstick_pressed_min",
- maxNodeName: "xr_standard_thumbstick_pressed_max",
- },
- xr_standard_thumbstick_xaxis_pressed: {
- componentProperty: "xAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_thumbstick_xaxis_pressed_value",
- minNodeName: "xr_standard_thumbstick_xaxis_pressed_min",
- maxNodeName: "xr_standard_thumbstick_xaxis_pressed_max",
- },
- xr_standard_thumbstick_yaxis_pressed: {
- componentProperty: "yAxis",
- states: ["default", "touched", "pressed"],
- valueNodeProperty: "transform",
- valueNodeName: "xr_standard_thumbstick_yaxis_pressed_value",
- minNodeName: "xr_standard_thumbstick_yaxis_pressed_min",
- maxNodeName: "xr_standard_thumbstick_yaxis_pressed_max",
- },
- },
- },
- },
- gamepadMapping: "xr-standard",
- rootNodeName: "microsoft-mixed-reality-right",
- assetPath: "right.glb",
- },
- };
- //# sourceMappingURL=webXRMicrosoftMixedRealityController.js.map
|