Как включить мультитач в ARViewIOS

Программируем под IOS
Ответить
Anonymous
 Как включить мультитач в ARView

Сообщение Anonymous »

Как включить мультитач в ARView?
Сенсорные функции (touchesBegan, touchesMoved, ...), кажется, обрабатывают только одно касание за раз, несмотря на настройку isMultipleTouchEnabled = true. Чтобы обрабатывать несколько касаний одновременно с помощью ARView, мне нужно либо:
  • Разместить UIView поверх ARView, чтобы фиксировать касания и выполнять тестирование нажатия, передав ссылку на ARView
  • Использовать SwiftUI .simultainGesture поверх представляемого ARView
Ожидаемое поведение:
  • ARView должен фиксировать все касания через touchesBegan/Moved/Ended/Cancelled.
Вот что я пробовал на iOS 26.1 и macOS 26.1:
Настройка ARView
Приведенная ниже настройка представляет собой минимальный ARView, представленный SwiftUI, с событиями касания, обрабатываемыми внутри ARView. Мультитач с этой настройкой не работает. Обратите внимание, что мультитач также не будет работать, если ARView представлен UIViewController вместо SwiftUI.

Код: Выделить всё

import RealityKit
import SwiftUI

struct ARViewMultiTouchView: View {
var body: some View {
ZStack {
ARViewMultiTouchRepresentable()
.ignoresSafeArea()
}
}
}

#Preview {
ARViewMultiTouchView()
}

// MARK: Representable ARView

struct ARViewMultiTouchRepresentable: UIViewRepresentable {

func makeUIView(context: Context) -> ARView {
let arView = ARViewMultiTouch(frame: .zero)

let anchor = AnchorEntity()
arView.scene.addAnchor(anchor)

let boxWidth: Float = 0.4
let boxMaterial = SimpleMaterial(color: .red, isMetallic: false)
let box = ModelEntity(mesh: .generateBox(size: boxWidth), materials: [boxMaterial])
box.name = "Box"
box.components.set(CollisionComponent(shapes: [.generateBox(width: boxWidth, height: boxWidth, depth: boxWidth)]))
anchor.addChild(box)

return arView
}

func updateUIView(_ uiView: ARView, context: Context) { }
}

// MARK: ARView

class ARViewMultiTouch: ARView {

required init(frame: CGRect) {
super.init(frame: frame)

/// Enable multi-touch
isMultipleTouchEnabled = true

cameraMode = .nonAR
automaticallyConfigureSession = false
environment.background = .color(.gray)

/// Disable gesture recognizers to not conflict with touch events
/// But it doesn't fix the issue
gestureRecognizers?.forEach { $0.isEnabled = false }
}

required dynamic init?(coder decoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
for touch in touches {
/// # Problem
/// This should print for every new touch, up to 5 simultaneously on an iPhone (multi-touch)
/// But it only fires for one touch at a time (single-touch)
print("Touch began at: \(touch.location(in: self))")
}
}

}
Мультитач с наложением
Эта настройка работает, но для этого требуется наложить UIView поверх ARView и оттуда обрабатывать мультитач.

Код: Выделить всё

import SwiftUI
import RealityKit

struct MultiTouchOverlayView: View {
var body: some View {
ZStack {
MultiTouchOverlayRepresentable()
.ignoresSafeArea()
Text("Multi touch with overlay view")
.font(.system(size: 24, weight: .medium))
.foregroundStyle(.white)
.offset(CGSize(width: 0, height: -150))
}
}
}

#Preview {
MultiTouchOverlayView()
}

// MARK: Representable Container

struct MultiTouchOverlayRepresentable: UIViewRepresentable {

func makeUIView(context: Context) ->  UIView {
/// The view that SwiftUI will present
let container = UIView()

/// ARView
let arView = ARView(frame: container.bounds)
arView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
arView.cameraMode = .nonAR
arView.automaticallyConfigureSession = false
arView.environment.background = .color(.gray)

let anchor = AnchorEntity()
arView.scene.addAnchor(anchor)

let boxWidth: Float = 0.4
let boxMaterial = SimpleMaterial(color: .red, isMetallic: false)
let box = ModelEntity(mesh: .generateBox(size: boxWidth), materials: [boxMaterial])
box.name = "Box"
box.components.set(CollisionComponent(shapes: [.generateBox(width: boxWidth, height: boxWidth, depth: boxWidth)]))
anchor.addChild(box)

/// The view that will capture touches
let touchOverlay = TouchOverlayView(frame: container.bounds)
touchOverlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]
touchOverlay.backgroundColor = .clear

/// Pass an arView reference to the overlay for hit testing
touchOverlay.arView = arView

/// Add views to the container.
/// ARView goes in first, at the bottom.
container.addSubview(arView)
/// TouchOverlay goes in last, on top.
container.addSubview(touchOverlay)

return container
}

func updateUIView(_ uiView: UIView, context: Context) {

}
}

// MARK: Touch Overlay View

/// A UIView to handle multi-touch on top of ARView
class TouchOverlayView: UIView {

weak var arView: ARView?

override init(frame: CGRect) {
super.init(frame: frame)
isMultipleTouchEnabled = true
isUserInteractionEnabled = true
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func touchesBegan(_ touches: Set, with event: UIEvent?) {
let totalTouches = event?.allTouches?.count ?? touches.count
print("--- Touches Began --- (New: \(touches.count), Total: \(totalTouches))")

for touch in touches {
let location = touch.location(in: self)

/// Hit testing.
/// ARView and Touch View must be of the same size
if let arView = arView {
let entity = arView.entity(at: location)
if let entity = entity {
print("Touched entity: \(entity.name)")
} else {
print("Touched: none")
}
}
}
}

override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
let totalTouches = event?.allTouches?.count ?? touches.count
print("--- Touches Cancelled --- (Cancelled: \(touches.count), Total: \(totalTouches))")
}
}
Как обрабатывать мультитач прямо в ARView?


Подробнее здесь: https://stackoverflow.com/questions/798 ... -on-arview
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»