diff --git a/Apps/PackageTest/0.63.1/package-lock.json b/Apps/PackageTest/0.63.1/package-lock.json index 9b916086a..cb7a8adc9 100644 --- a/Apps/PackageTest/0.63.1/package-lock.json +++ b/Apps/PackageTest/0.63.1/package-lock.json @@ -908,16 +908,16 @@ } }, "@babylonjs/core": { - "version": "5.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.0.0-alpha.6.tgz", - "integrity": "sha512-7Tg/MByT6nUHpV5TjVj1xHsmnbrk1hGMk/jKCui6bydR6YaGrkE0yoLAmJXX5ALGXhhKLIDj+qg3QHWVFsi1lA==", + "version": "5.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.0.0-alpha.9.tgz", + "integrity": "sha512-1xoYaq0CfJiKGLlsEAazK0oPR0DOzw1sl2JY3paeVi+Rh6muoHoKKgWAv+Pobq6rnQM1fQpj8uKbijtEeTLciw==", "requires": { "tslib": ">=1.10.0" } }, "@babylonjs/react-native": { "version": "file:../../../Package/Assembled/babylonjs-react-native-0.0.1.tgz", - "integrity": "sha512-eEjmBIRqheKSsMU58Ql0ZKack9FhA6Ac48yq2Y8MAQ5RlbWUzWWI2RRb6jjGkMr1huwdSRGWL2gsRMuEcghRww==", + "integrity": "sha512-jfKsyXhqdBg6UV3RhJRrbEmK3yyB4y/JZUidA97yLMEJYQsvuzZhGYEYanbvM/tflelxhxIR76XlMvUHmL2qug==", "requires": { "base-64": "^0.1.0", "semver": "^7.3.2" diff --git a/Apps/PackageTest/0.63.1/package.json b/Apps/PackageTest/0.63.1/package.json index 3f50f6c7e..8d8c0f032 100644 --- a/Apps/PackageTest/0.63.1/package.json +++ b/Apps/PackageTest/0.63.1/package.json @@ -10,7 +10,7 @@ "lint": "eslint . --ext .js,.jsx,.ts,.tsx" }, "dependencies": { - "@babylonjs/core": "^5.0.0-alpha.6", + "@babylonjs/core": "^5.0.0-alpha.9", "@babylonjs/react-native": "file:../../../Package/Assembled/babylonjs-react-native-0.0.1.tgz", "react": "16.13.1", "react-native": "0.63.1", diff --git a/Apps/PackageTest/0.64.0-rc.0/package-lock.json b/Apps/PackageTest/0.64.0-rc.0/package-lock.json index 2caadac60..fbc8cee86 100644 --- a/Apps/PackageTest/0.64.0-rc.0/package-lock.json +++ b/Apps/PackageTest/0.64.0-rc.0/package-lock.json @@ -912,18 +912,29 @@ } }, "@babylonjs/core": { - "version": "5.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.0.0-alpha.6.tgz", - "integrity": "sha512-7Tg/MByT6nUHpV5TjVj1xHsmnbrk1hGMk/jKCui6bydR6YaGrkE0yoLAmJXX5ALGXhhKLIDj+qg3QHWVFsi1lA==", + "version": "5.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.0.0-alpha.9.tgz", + "integrity": "sha512-1xoYaq0CfJiKGLlsEAazK0oPR0DOzw1sl2JY3paeVi+Rh6muoHoKKgWAv+Pobq6rnQM1fQpj8uKbijtEeTLciw==", "requires": { "tslib": ">=1.10.0" } }, "@babylonjs/react-native": { "version": "file:../../../Package/Assembled/babylonjs-react-native-0.0.1.tgz", - "integrity": "sha512-2iGNoOZz4gcuhPj8mdeOWV8DgXIC2W0Hn+m+APhmakC1FXic8i15dHobVLiY4jKR72uTqJ6oxz3da2B5KuTw2Q==", + "integrity": "sha512-jfKsyXhqdBg6UV3RhJRrbEmK3yyB4y/JZUidA97yLMEJYQsvuzZhGYEYanbvM/tflelxhxIR76XlMvUHmL2qug==", "requires": { - "base-64": "^0.1.0" + "base-64": "^0.1.0", + "semver": "^7.3.2" + }, + "dependencies": { + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "requires": { + "lru-cache": "^6.0.0" + } + } } }, "@bcoe/v8-coverage": { diff --git a/Apps/PackageTest/0.64.0-rc.0/package.json b/Apps/PackageTest/0.64.0-rc.0/package.json index a85cbf6aa..f052f3e13 100644 --- a/Apps/PackageTest/0.64.0-rc.0/package.json +++ b/Apps/PackageTest/0.64.0-rc.0/package.json @@ -12,7 +12,7 @@ "lint": "eslint . --ext .js,.jsx,.ts,.tsx" }, "dependencies": { - "@babylonjs/core": "^5.0.0-alpha.6", + "@babylonjs/core": "^5.0.0-alpha.9", "@babylonjs/react-native": "file:../../../Package/Assembled/babylonjs-react-native-0.0.1.tgz", "react": "^17.0.1", "react-native": "^0.64.0-rc.0", diff --git a/Apps/Playground/App.tsx b/Apps/Playground/App.tsx index 12ad93df5..e5b38959f 100644 --- a/Apps/Playground/App.tsx +++ b/Apps/Playground/App.tsx @@ -9,7 +9,7 @@ import React, { useState, FunctionComponent, useEffect, useCallback } from 'reac import { SafeAreaView, StatusBar, Button, View, Text, ViewProps, Image } from 'react-native'; import { EngineView, useEngine, EngineViewCallbacks } from '@babylonjs/react-native'; -import { Scene, Vector3, ArcRotateCamera, Camera, WebXRSessionManager, SceneLoader, TransformNode, DeviceSourceManager, DeviceType, DeviceSource, PointerInput, WebXRTrackingState } from '@babylonjs/core'; +import { Scene, Vector3, ArcRotateCamera, Camera, WebXRSessionManager, SceneLoader, TransformNode, DeviceSourceManager, DeviceType, DeviceSource, PointerInput, WebXRTrackingState, Nullable } from '@babylonjs/core'; import '@babylonjs/loaders'; import Slider from '@react-native-community/slider'; @@ -40,18 +40,28 @@ const EngineScreen: FunctionComponent = (props: ViewProps) => { setRootNode(rootNode); const deviceSourceManager = new DeviceSourceManager(engine); + const handlePointerInput = (inputIndex: PointerInput, previousState: Nullable, currentState: Nullable) => { + if (inputIndex === PointerInput.Horizontal && + currentState && previousState) { + rootNode.rotate(Vector3.Down(), (currentState - previousState) * 0.005); + }; + }; + deviceSourceManager.onDeviceConnectedObservable.add(device => { if (device.deviceType === DeviceType.Touch) { const touch: DeviceSource = deviceSourceManager.getDeviceSource(device.deviceType, device.deviceSlot)!; touch.onInputChangedObservable.add(touchEvent => { - if (touchEvent.inputIndex === PointerInput.Horizontal) { - if (touchEvent.currentState && touchEvent.previousState) { - rootNode.rotate(Vector3.Down(), (touchEvent.currentState - touchEvent.previousState) * 0.005); - } + handlePointerInput(touchEvent.inputIndex, touchEvent.previousState, touchEvent.currentState); + }); + } else if (device.deviceType === DeviceType.Mouse) { + const mouse: DeviceSource = deviceSourceManager.getDeviceSource(device.deviceType, device.deviceSlot)!; + mouse.onInputChangedObservable.add(mouseEvent => { + if (mouse.getInput(PointerInput.LeftClick)) { + handlePointerInput(mouseEvent.inputIndex, mouseEvent.previousState, mouseEvent.currentState); } - }) + }); } - }) + }); const transformContainer = new TransformNode("Transform Container", scene); transformContainer.parent = rootNode; diff --git a/Apps/Playground/package-lock.json b/Apps/Playground/package-lock.json index 64f86406d..61d594fdf 100644 --- a/Apps/Playground/package-lock.json +++ b/Apps/Playground/package-lock.json @@ -889,20 +889,20 @@ } }, "@babylonjs/core": { - "version": "5.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.0.0-alpha.6.tgz", - "integrity": "sha512-7Tg/MByT6nUHpV5TjVj1xHsmnbrk1hGMk/jKCui6bydR6YaGrkE0yoLAmJXX5ALGXhhKLIDj+qg3QHWVFsi1lA==", + "version": "5.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.0.0-alpha.9.tgz", + "integrity": "sha512-1xoYaq0CfJiKGLlsEAazK0oPR0DOzw1sl2JY3paeVi+Rh6muoHoKKgWAv+Pobq6rnQM1fQpj8uKbijtEeTLciw==", "requires": { "tslib": ">=1.10.0" } }, "@babylonjs/loaders": { - "version": "5.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-5.0.0-alpha.6.tgz", - "integrity": "sha512-mnUkcA2a4Mdo484q7ckw+QxPYM8mfMaZjfSyt4YjwUxXRdOvbQUPyk/ZojrQjXajEFdzpxhqEU5Iu5CZr01w1A==", + "version": "5.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-5.0.0-alpha.9.tgz", + "integrity": "sha512-HS7xCGQ07qtPvEMHOQV4sEFffpsUFTCF84YL4DQJFGsD3sdAsPFQeX9zwyd5pT+ABCPtj3Wh7dxwH09FQJLJqA==", "requires": { - "@babylonjs/core": "5.0.0-alpha.6", - "babylonjs-gltf2interface": "5.0.0-alpha.6", + "@babylonjs/core": "5.0.0-alpha.9", + "babylonjs-gltf2interface": "5.0.0-alpha.9", "tslib": ">=1.10.0" } }, @@ -4170,9 +4170,9 @@ } }, "babylonjs-gltf2interface": { - "version": "5.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-5.0.0-alpha.6.tgz", - "integrity": "sha512-rlsNUn+/anLusgeYwgiRmgo2KtTDA8HmaXTbaAesUHp4lSQfmCmWyl1SpTdGgBeBeG2ZVD9mOrSVamBc+L7YyA==" + "version": "5.0.0-alpha.9", + "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-5.0.0-alpha.9.tgz", + "integrity": "sha512-DtHrkuq/SAgB/xzaXo/pI63axfoSmuxPV1GJF/b7rqjCoxGGAe4ws50zbacviYIoerny6zBRu1krUiOtiCcsgw==" }, "balanced-match": { "version": "1.0.0", diff --git a/Apps/Playground/package.json b/Apps/Playground/package.json index 6ff827ce7..52d410c02 100644 --- a/Apps/Playground/package.json +++ b/Apps/Playground/package.json @@ -12,8 +12,8 @@ "lint": "eslint . --ext .js,.jsx,.ts,.tsx" }, "dependencies": { - "@babylonjs/core": "^5.0.0-alpha.6", - "@babylonjs/loaders": "^5.0.0-alpha.6", + "@babylonjs/core": "^5.0.0-alpha.9", + "@babylonjs/loaders": "^5.0.0-alpha.9", "@babylonjs/react-native": "file:../../Modules/@babylonjs/react-native", "@react-native-community/slider": "4.0.0-rc.2", "logkitty": "^0.7.1", diff --git a/Modules/@babylonjs/react-native/android/src/main/cpp/BabylonNativeInterop.cpp b/Modules/@babylonjs/react-native/android/src/main/cpp/BabylonNativeInterop.cpp index 182f6f004..f261f1307 100644 --- a/Modules/@babylonjs/react-native/android/src/main/cpp/BabylonNativeInterop.cpp +++ b/Modules/@babylonjs/react-native/android/src/main/cpp/BabylonNativeInterop.cpp @@ -77,12 +77,12 @@ extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInter Babylon::UpdateView(windowPtr, width, height); } -extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInterop_00024BabylonNative_setPointerButtonState(JNIEnv* env, jclass obj, jint pointerId, jint buttonId, jboolean isDown, jint x, jint y) +extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInterop_00024BabylonNative_setTouchButtonState(JNIEnv* env, jclass obj, jint pointerId, jboolean isDown, jint x, jint y) { - Babylon::SetPointerButtonState(static_cast(pointerId), static_cast(buttonId), isDown, static_cast(x), static_cast(y)); + Babylon::SetTouchButtonState(static_cast(pointerId), isDown, static_cast(x), static_cast(y)); } -extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInterop_00024BabylonNative_setPointerPosition(JNIEnv* env, jclass obj, jint pointerId, jint x, jint y) +extern "C" JNIEXPORT void JNICALL Java_com_babylonreactnative_BabylonNativeInterop_00024BabylonNative_setTouchPosition(JNIEnv* env, jclass obj, jint pointerId, jint x, jint y) { - Babylon::SetPointerPosition(static_cast(pointerId), static_cast(x), static_cast(y)); + Babylon::SetTouchPosition(static_cast(pointerId), static_cast(x), static_cast(y)); } diff --git a/Modules/@babylonjs/react-native/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java b/Modules/@babylonjs/react-native/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java index 319bc9fb1..f3139cb00 100644 --- a/Modules/@babylonjs/react-native/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java +++ b/Modules/@babylonjs/react-native/android/src/main/java/com/babylonreactnative/BabylonNativeInterop.java @@ -24,8 +24,8 @@ private static class BabylonNative { public static native void pause(); public static native void resume(); public static native void updateView(Surface surface); - public static native void setPointerButtonState(int pointerId, int buttonId, boolean isDown, int x, int y); - public static native void setPointerPosition(int pointerId, int x, int y); + public static native void setTouchButtonState(int pointerId, boolean isDown, int x, int y); + public static native void setTouchPosition(int pointerId, int x, int y); } private static LifecycleEventListener lifeCycleEventListener; @@ -98,13 +98,13 @@ public static void reportMotionEvent(MotionEvent motionEvent) { int pointerId = motionEvent.getPointerId(pointerIndex); int x = (int)motionEvent.getX(pointerIndex); int y = (int)motionEvent.getY(pointerIndex); - BabylonNative.setPointerButtonState(pointerId, 0, isPointerDown, x, y); + BabylonNative.setTouchButtonState(pointerId, isPointerDown, x, y); } else if (isPointerMove) { for (int pointerIndex = 0; pointerIndex < motionEvent.getPointerCount(); pointerIndex++) { int pointerId = motionEvent.getPointerId(pointerIndex); int x = (int)motionEvent.getX(pointerIndex); int y = (int)motionEvent.getY(pointerIndex); - BabylonNative.setPointerPosition(pointerId, x, y); + BabylonNative.setTouchPosition(pointerId, x, y); } } } diff --git a/Modules/@babylonjs/react-native/ios/BabylonNativeInterop.mm b/Modules/@babylonjs/react-native/ios/BabylonNativeInterop.mm index 9b0afe1c0..a34863c74 100644 --- a/Modules/@babylonjs/react-native/ios/BabylonNativeInterop.mm +++ b/Modules/@babylonjs/react-native/ios/BabylonNativeInterop.mm @@ -79,13 +79,13 @@ + (void)reportTouchEvent:(MTKView*)mtkView touches:(NSSet*)touches eve } else { [activeTouches replaceObjectAtIndex:pointerId withObject:touch]; } - Babylon::SetPointerButtonState(static_cast(pointerId), 0, true, x, y); + Babylon::SetTouchButtonState(static_cast(pointerId), true, x, y); break; } case UITouchPhaseMoved: { NSUInteger pointerId = [activeTouches indexOfObject:touch]; - Babylon::SetPointerPosition(static_cast(pointerId), x, y); + Babylon::SetTouchPosition(static_cast(pointerId), x, y); break; } @@ -93,7 +93,7 @@ + (void)reportTouchEvent:(MTKView*)mtkView touches:(NSSet*)touches eve case UITouchPhaseCancelled: { NSUInteger pointerId = [activeTouches indexOfObject:touch]; [activeTouches replaceObjectAtIndex:pointerId withObject:[NSNull null]]; - Babylon::SetPointerButtonState(static_cast(pointerId), 0, false, x, y); + Babylon::SetTouchButtonState(static_cast(pointerId), false, x, y); break; } diff --git a/Modules/@babylonjs/react-native/package.json b/Modules/@babylonjs/react-native/package.json index f27ff76aa..6258c549a 100644 --- a/Modules/@babylonjs/react-native/package.json +++ b/Modules/@babylonjs/react-native/package.json @@ -28,7 +28,7 @@ "semver": "^7.3.2" }, "peerDependencies": { - "@babylonjs/core": "^5.0.0-alpha.6", + "@babylonjs/core": "^5.0.0-alpha.9", "react": "^16.13.1", "react-native": "^0.63.1", "react-native-permissions": "^2.1.4", diff --git a/Modules/@babylonjs/react-native/shared/BabylonNative.cpp b/Modules/@babylonjs/react-native/shared/BabylonNative.cpp index ed46642b9..e28d89b22 100644 --- a/Modules/@babylonjs/react-native/shared/BabylonNative.cpp +++ b/Modules/@babylonjs/react-native/shared/BabylonNative.cpp @@ -12,13 +12,18 @@ namespace Babylon { + using namespace Babylon::Plugins; using namespace facebook; namespace { - Dispatcher g_inlineDispatcher{[](const std::function& func) { func(); }}; + Dispatcher g_inlineDispatcher{ [](const std::function& func) { func(); } }; } + const uint32_t LEFT_MOUSE_BUTTON_ID{ NativeInput::LEFT_MOUSE_BUTTON_ID }; + const uint32_t MIDDLE_MOUSE_BUTTON_ID{ NativeInput::MIDDLE_MOUSE_BUTTON_ID }; + const uint32_t RIGHT_MOUSE_BUTTON_ID{ NativeInput::RIGHT_MOUSE_BUTTON_ID }; + class ReactNativeModule : public jsi::HostObject { public: @@ -136,21 +141,38 @@ namespace Babylon }); } - void SetPointerButtonState(uint32_t pointerId, uint32_t buttonId, bool isDown, uint32_t x, uint32_t y) + void SetMouseButtonState(uint32_t buttonId, bool isDown, uint32_t x, uint32_t y) + { + if (isDown) + { + m_nativeInput->MouseDown(buttonId, x, y); + } + else + { + m_nativeInput->MouseUp(buttonId, x, y); + } + } + + void SetMousePosition(uint32_t x, uint32_t y) + { + m_nativeInput->MouseMove(x, y); + } + + void SetTouchButtonState(uint32_t pointerId, bool isDown, uint32_t x, uint32_t y) { if (isDown) { - m_nativeInput->PointerDown(pointerId, buttonId, x, y); + m_nativeInput->TouchDown(pointerId, x, y); } else { - m_nativeInput->PointerUp(pointerId, buttonId, x, y); + m_nativeInput->TouchUp(pointerId, x, y); } } - void SetPointerPosition(uint32_t pointerId, uint32_t x, uint32_t y) + void SetTouchPosition(uint32_t pointerId, uint32_t x, uint32_t y) { - m_nativeInput->PointerMove(pointerId, x, y); + m_nativeInput->TouchMove(pointerId, x, y); } jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& prop) override @@ -255,19 +277,35 @@ namespace Babylon } } - void SetPointerButtonState(uint32_t pointerId, uint32_t buttonId, bool isDown, uint32_t x, uint32_t y) + void SetMouseButtonState(uint32_t buttonId, bool isDown, uint32_t x, uint32_t y) + { + if (auto nativeModule{ g_nativeModule.lock() }) + { + nativeModule->SetMouseButtonState(buttonId, isDown, x, y); + } + } + + void SetMousePosition(uint32_t x, uint32_t y) + { + if (auto nativeModule{ g_nativeModule.lock() }) + { + nativeModule->SetMousePosition(x, y); + } + } + + void SetTouchButtonState(uint32_t pointerId, bool isDown, uint32_t x, uint32_t y) { if (auto nativeModule{ g_nativeModule.lock() }) { - nativeModule->SetPointerButtonState(pointerId, buttonId, isDown, x, y); + nativeModule->SetTouchButtonState(pointerId, isDown, x, y); } } - void SetPointerPosition(uint32_t pointerId, uint32_t x, uint32_t y) + void SetTouchPosition(uint32_t pointerId, uint32_t x, uint32_t y) { if (auto nativeModule{ g_nativeModule.lock() }) { - nativeModule->SetPointerPosition(pointerId, x, y); + nativeModule->SetTouchPosition(pointerId, x, y); } } } diff --git a/Modules/@babylonjs/react-native/shared/BabylonNative.h b/Modules/@babylonjs/react-native/shared/BabylonNative.h index 88d348c63..6a3679d2b 100644 --- a/Modules/@babylonjs/react-native/shared/BabylonNative.h +++ b/Modules/@babylonjs/react-native/shared/BabylonNative.h @@ -10,6 +10,12 @@ namespace Babylon void Deinitialize(); void UpdateView(void* windowPtr, size_t width, size_t height, void* windowTypePtr = nullptr); void RenderView(); - void SetPointerButtonState(uint32_t pointerId, uint32_t buttonId, bool isDown, uint32_t x, uint32_t y); - void SetPointerPosition(uint32_t pointerId, uint32_t x, uint32_t y); + void SetMouseButtonState(uint32_t buttonId, bool isDown, uint32_t x, uint32_t y); + void SetMousePosition(uint32_t x, uint32_t y); + void SetTouchButtonState(uint32_t pointerId, bool isDown, uint32_t x, uint32_t y); + void SetTouchPosition(uint32_t pointerId, uint32_t x, uint32_t y); + + extern const uint32_t LEFT_MOUSE_BUTTON_ID; + extern const uint32_t MIDDLE_MOUSE_BUTTON_ID; + extern const uint32_t RIGHT_MOUSE_BUTTON_ID; } diff --git a/Modules/@babylonjs/react-native/submodules/BabylonNative b/Modules/@babylonjs/react-native/submodules/BabylonNative index 4fb4abede..b4f81771a 160000 --- a/Modules/@babylonjs/react-native/submodules/BabylonNative +++ b/Modules/@babylonjs/react-native/submodules/BabylonNative @@ -1 +1 @@ -Subproject commit 4fb4abede658640965ff61c84cdbee098cdd0089 +Subproject commit b4f81771abb2722c3c18731a59b31c18298fcd40 diff --git a/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.cpp b/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.cpp index d499e416f..7fafc308b 100644 --- a/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.cpp +++ b/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.cpp @@ -2,6 +2,11 @@ #include "EngineView.h" #include "EngineView.g.cpp" +using namespace winrt::Windows::Devices::Input; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::System::Threading; +using namespace winrt::Windows::UI::Core; +using namespace winrt::Windows::UI::Input; using namespace winrt::Windows::UI::Xaml; using namespace winrt::Windows::UI::Xaml::Input; using namespace winrt::Windows::UI::Xaml::Media; @@ -9,10 +14,28 @@ using namespace winrt::Windows::UI::Xaml::Controls; namespace winrt::BabylonReactNative::implementation { EngineView::EngineView() { + _revokerData.SizeChangedRevoker = SizeChanged(winrt::auto_revoke, { this, &EngineView::OnSizeChanged }); - _revokerData.PointerPressedRevoker = PointerPressed(winrt::auto_revoke, { this, &EngineView::OnPointerPressed }); - _revokerData.PointerMovedRevoker = PointerMoved(winrt::auto_revoke, { this, &EngineView::OnPointerMoved }); - _revokerData.PointerReleasedRevoker = PointerReleased(winrt::auto_revoke, { this, &EngineView::OnPointerReleased }); + + WorkItemHandler workItemHandler([weakThis{ this->get_weak() }](IAsyncAction const& /* action */) + { + if (auto trueThis = weakThis.get()) + { + auto deviceTypes = static_cast( + static_cast(Windows::UI::Core::CoreInputDeviceTypes::Mouse) | + static_cast(Windows::UI::Core::CoreInputDeviceTypes::Touch) | + static_cast(Windows::UI::Core::CoreInputDeviceTypes::Pen)); + auto coreInput = trueThis->CreateCoreIndependentInputSource(deviceTypes); + + trueThis->_revokerData.PointerPressedRevoker = coreInput.PointerPressed(winrt::auto_revoke, { trueThis.get(), &EngineView::OnPointerPressed }); + trueThis->_revokerData.PointerMovedRevoker = coreInput.PointerMoved(winrt::auto_revoke, { trueThis.get(), &EngineView::OnPointerMoved }); + trueThis->_revokerData.PointerReleasedRevoker = coreInput.PointerReleased(winrt::auto_revoke, { trueThis.get(), &EngineView::OnPointerReleased }); + + coreInput.Dispatcher().ProcessEvents(Windows::UI::Core::CoreProcessEventsOption::ProcessUntilQuit); + } + }); + + _inputLoopWorker = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::TimeSliced); _revokerData.RenderingRevoker = CompositionTarget::Rendering(winrt::auto_revoke, [weakThis{ this->get_weak() }](auto const&, auto const&) { @@ -35,36 +58,98 @@ namespace winrt::BabylonReactNative::implementation { Babylon::UpdateView(windowPtr, _width, _height, windowTypePtr); } - void EngineView::OnPointerPressed(IInspectable const& /*sender*/, PointerRoutedEventArgs const& args) + void EngineView::OnPointerPressed(IInspectable const& /*sender*/, PointerEventArgs const& args) { - const auto pointerId = args.Pointer().PointerId(); - const auto buttonId = 0; // Update as needed - const auto point = args.GetCurrentPoint(*this); + const auto point = args.CurrentPoint(); + const auto properties = point.Properties(); + const auto deviceType = point.PointerDevice().PointerDeviceType(); const auto position = point.Position(); const uint32_t x = position.X < 0 ? 0 : static_cast(position.X); const uint32_t y = position.Y < 0 ? 0 : static_cast(position.Y); - Babylon::SetPointerButtonState(pointerId, buttonId, true, x, y); + + if (deviceType == PointerDeviceType::Mouse) + { + if (properties.IsLeftButtonPressed()) + { + _pressedMouseButtons.insert(Babylon::LEFT_MOUSE_BUTTON_ID); + Babylon::SetMouseButtonState(Babylon::LEFT_MOUSE_BUTTON_ID, true, x, y); + } + + if (properties.IsMiddleButtonPressed()) + { + _pressedMouseButtons.insert(Babylon::MIDDLE_MOUSE_BUTTON_ID); + Babylon::SetMouseButtonState(Babylon::MIDDLE_MOUSE_BUTTON_ID, true, x, y); + } + + if (properties.IsRightButtonPressed()) + { + _pressedMouseButtons.insert(Babylon::RIGHT_MOUSE_BUTTON_ID); + Babylon::SetMouseButtonState(Babylon::RIGHT_MOUSE_BUTTON_ID, true, x, y); + } + } + else + { + const auto pointerId = point.PointerId(); + Babylon::SetTouchButtonState(pointerId, true, x, y); + } } - void EngineView::OnPointerMoved(IInspectable const& /*sender*/, PointerRoutedEventArgs const& args) + void EngineView::OnPointerMoved(IInspectable const& /*sender*/, PointerEventArgs const& args) { - const auto pointerId = args.Pointer().PointerId(); - const auto point = args.GetCurrentPoint(*this); + const auto point = args.CurrentPoint(); + const auto deviceType = point.PointerDevice().PointerDeviceType(); const auto position = point.Position(); const uint32_t x = position.X < 0 ? 0 : static_cast(position.X); const uint32_t y = position.Y < 0 ? 0 : static_cast(position.Y); - Babylon::SetPointerPosition(pointerId, x, y); + + if (deviceType == PointerDeviceType::Mouse) + { + Babylon::SetMousePosition(x, y); + } + else + { + const auto pointerId = point.PointerId(); + Babylon::SetTouchPosition(pointerId, x, y); + } } - void EngineView::OnPointerReleased(IInspectable const& /*sender*/, PointerRoutedEventArgs const& args) + void EngineView::OnPointerReleased(IInspectable const& /*sender*/, PointerEventArgs const& args) { - const auto pointerId = args.Pointer().PointerId(); - const auto buttonId = 0; // Update as needed - const auto point = args.GetCurrentPoint(*this); + const auto point = args.CurrentPoint(); + const auto properties = point.Properties(); + const auto deviceType = point.PointerDevice().PointerDeviceType(); const auto position = point.Position(); const uint32_t x = position.X < 0 ? 0 : static_cast(position.X); const uint32_t y = position.Y < 0 ? 0 : static_cast(position.Y); - Babylon::SetPointerButtonState(pointerId, buttonId, false, x, y); + + if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Mouse) + { + if (!properties.IsLeftButtonPressed() && + _pressedMouseButtons.find(Babylon::LEFT_MOUSE_BUTTON_ID) != _pressedMouseButtons.end()) + { + _pressedMouseButtons.erase(Babylon::LEFT_MOUSE_BUTTON_ID); + Babylon::SetMouseButtonState(Babylon::LEFT_MOUSE_BUTTON_ID, false, x, y); + } + + if (!properties.IsMiddleButtonPressed() && + _pressedMouseButtons.find(Babylon::MIDDLE_MOUSE_BUTTON_ID) != _pressedMouseButtons.end()) + { + _pressedMouseButtons.erase(Babylon::MIDDLE_MOUSE_BUTTON_ID); + Babylon::SetMouseButtonState(Babylon::MIDDLE_MOUSE_BUTTON_ID, false, x, y); + } + + if (!properties.IsRightButtonPressed() && + _pressedMouseButtons.find(Babylon::RIGHT_MOUSE_BUTTON_ID) != _pressedMouseButtons.end()) + { + _pressedMouseButtons.erase(Babylon::RIGHT_MOUSE_BUTTON_ID); + Babylon::SetMouseButtonState(Babylon::RIGHT_MOUSE_BUTTON_ID, false, x, y); + } + } + else + { + const auto pointerId = point.PointerId(); + Babylon::SetTouchButtonState(pointerId, false, x, y); + } } void EngineView::OnRendering() diff --git a/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.h b/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.h index 6f4a2a8cb..062618b24 100644 --- a/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.h +++ b/Modules/@babylonjs/react-native/windows/BabylonReactNative/EngineView.h @@ -1,5 +1,6 @@ #pragma once #include "EngineView.g.h" +#include namespace winrt::BabylonReactNative::implementation { struct EngineView : EngineViewT @@ -9,20 +10,23 @@ namespace winrt::BabylonReactNative::implementation { private: void OnSizeChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::SizeChangedEventArgs const& args); - void OnPointerPressed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& args); - void OnPointerMoved(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& args); - void OnPointerReleased(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& args); + void OnPointerPressed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + void OnPointerMoved(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); + void OnPointerReleased(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Core::PointerEventArgs const& args); void OnRendering(); + uint32_t GetButtonId(winrt::Windows::Devices::Input::PointerDeviceType deviceType, winrt::Windows::UI::Input::PointerPointProperties properties); size_t _width{ 1 }; size_t _height{ 1 }; + winrt::Windows::Foundation::IAsyncAction _inputLoopWorker{}; + std::unordered_set _pressedMouseButtons{}; struct RevokerData { winrt::Windows::UI::Xaml::FrameworkElement::SizeChanged_revoker SizeChangedRevoker{}; - winrt::Windows::UI::Xaml::FrameworkElement::PointerPressed_revoker PointerPressedRevoker{}; - winrt::Windows::UI::Xaml::FrameworkElement::PointerMoved_revoker PointerMovedRevoker{}; - winrt::Windows::UI::Xaml::FrameworkElement::PointerReleased_revoker PointerReleasedRevoker{}; + winrt::Windows::UI::Core::CoreIndependentInputSource::PointerPressed_revoker PointerPressedRevoker{}; + winrt::Windows::UI::Core::CoreIndependentInputSource::PointerMoved_revoker PointerMovedRevoker{}; + winrt::Windows::UI::Core::CoreIndependentInputSource::PointerReleased_revoker PointerReleasedRevoker{}; winrt::Windows::UI::Xaml::Media::CompositionTarget::Rendering_revoker RenderingRevoker{}; }; RevokerData _revokerData{}; diff --git a/Modules/@babylonjs/react-native/windows/BabylonReactNative/pch.h b/Modules/@babylonjs/react-native/windows/BabylonReactNative/pch.h index 731f30feb..37999c7d0 100644 --- a/Modules/@babylonjs/react-native/windows/BabylonReactNative/pch.h +++ b/Modules/@babylonjs/react-native/windows/BabylonReactNative/pch.h @@ -3,9 +3,11 @@ #define NOMINMAX #include +#include #include #include #include +#include #include #include #include