Skip to content

Commit 951d641

Browse files
authored
Merge pull request #11 from maxxfrazer/touch-updates
Release 1.3.0 - Update RUIStepper and RUISwitch to have better touch controls. - Added hasCollided to arTouchEnded method call. - Added tests for the above. - Modified the default opacity background of RUIStepper - Update indentation - Add DocC Articles for setup + started RUIControls. All updated methods have deprecated tags with auto-update options on the old ones. Fixes: - Fix padding value on RUIButton - Fix collision shape for RUISwitch
2 parents 82584a4 + f91e6f4 commit 951d641

24 files changed

+2266
-1957
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.2
1+
// swift-tools-version:5.6
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription

README.md

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@ The classes included in RealityUI aim to offer familiar User Interface guideline
66
The User Interface controls in this repository so far are made to be familiar to what people are used to with 2D interfaces, however the plan is to expand the tools on offer to new and unique controls, which are more appropriate for an Augmented Reality and Virtual Reality context.
77

88
<p align="center">
9-
<img src="https://img.shields.io/github/v/release/maxxfrazer/RealityUI?color=orange&label=SwiftPM&logo=swift"/>
10-
<img src="https://img.shields.io/badge/platform-iOS%20%7C%20macOS-lightgrey"/>
11-
<img src="https://img.shields.io/badge/Swift-5.2-orange?logo=swift"/>
12-
<!-- <a href="https://codecov.io/gh/maxxfrazer/RealityUI" >
13-
<img src="https://codecov.io/gh/maxxfrazer/RealityUI/branch/main/graph/badge.svg?token=3PCDBMSCLL"/>
14-
</a> -->
9+
<a href="https://swiftpackageindex.com/maxxfrazer/RealityUI">
10+
<img src="https://img.shields.io/github/v/release/maxxfrazer/RealityUI?color=F05138&label=Package%20Version&logo=Swift"/>
11+
</a>
12+
<a href="https://swiftpackageindex.com/maxxfrazer/RealityUI">
13+
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmaxxfrazer%2FRealityUI%2Fbadge%3Ftype%3Dplatforms"/>
14+
</a>
15+
<a href="https://swiftpackageindex.com/maxxfrazer/RealityUI">
16+
<img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fmaxxfrazer%2FRealityUI%2Fbadge%3Ftype%3Dswift-versions"/>
17+
</a>
18+
<br/>
1519
<img src="https://img.shields.io/github/license/maxxfrazer/RealityUI"/>
1620
<img src="https://github.com/maxxfrazer/RealityUI/workflows/build/badge.svg?branch=main"/>
1721
<img src="https://github.com/maxxfrazer/RealityUI/workflows/Deploy%20DocC/badge.svg?branch=main"/>
@@ -22,8 +26,8 @@ The User Interface controls in this repository so far are made to be familiar to
2226
## Requirements
2327

2428
- iOS 13 or macOS 10.15
25-
- Swift 5.2
26-
- Xcode 11
29+
- Swift 5.4
30+
- Xcode 12
2731

2832
## Content
2933

@@ -56,8 +60,10 @@ All components used in RealityUI must be registered before they are used, simply
5660

5761
#### Activating Gestures
5862

59-
If you plan on using RUISwitch or RUIStepper, then you should at least enable `.tap`
60-
RUISlider uses `.pan`, but I would just recommend using `.all` to avoid issues, as these will inevitably move around ad RealityUI develops, and will not interfere with the rest of your RealityKit scene.
63+
Enabling RealityUI gestures can be doen by calling `RealityUI.enableGestures(.all, on: ARView)`, with `ARView` being your instance of an [ARView](https://developer.apple.com/documentation/realitykit/arview) object.
64+
65+
RUISlider, RUISwitch, RUIStepper and RUIButton all use `.longTouch`, and if you are adding elements that use the protocol `HasClick` you can use the gesture `.tap`.
66+
I would just recommend using `.all` when enabling gestures, as these will inevitably move around as RealityUI develops.
6167

6268
`RealityUI.enableGestures(.all, on: arView)`
6369

RealityUI+Examples/RealityUI+Examples/ViewController.swift

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,42 @@ import RealityUI
1515
class ViewController: UIViewController {
1616

1717
var arView = ARView(frame: .zero, cameraMode: .ar, automaticallyConfigureSession: false)
18-
18+
var arMode = true
1919
func addARView() {
20+
2021
arView.frame = self.view.bounds
2122
self.arView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
2223
self.view.addSubview(arView)
24+
RealityUI.enableGestures(.all, on: self.arView)
2325
self.arView.renderOptions.insert(.disableGroundingShadows)
2426

25-
let config = ARWorldTrackingConfiguration()
26-
config.planeDetection = [.horizontal]
27-
arView.session.run(config, options: [])
27+
if self.arMode {
28+
let config = ARWorldTrackingConfiguration()
29+
config.planeDetection = [.horizontal]
30+
arView.session.run(config, options: [])
31+
self.addObjectToPlane()
32+
} else {
33+
arView.cameraMode = .nonAR
34+
arView.environment.background = .color(.orange)
35+
self.addNonARParts()
36+
}
2837
// Replaces camera feed, if 6dof VR look is wanted
2938
// arView.environment.background = .color(.systemGray)
3039

3140
// Register all the components used in RealityUI
3241
RealityUI.registerComponents()
3342
}
3443

44+
func addNonARParts() {
45+
let stepper = RUIStepper()
46+
let anchor = AnchorEntity(world: .zero)
47+
self.arView.scene.addAnchor(anchor)
48+
anchor.addChild(stepper)
49+
}
50+
3551
override func viewDidLoad() {
3652
super.viewDidLoad()
37-
38-
self.addARView()
39-
4053
// Add all RealityUI gestures to the current ARView
41-
RealityUI.enableGestures(.all, on: self.arView)
42-
self.addObjectToPlane()
54+
self.addARView()
4355
}
4456
}

Sources/RealityUI/HasClick.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ import RealityKit
1010

1111
/// An interface used for entities which have actions upon being clicked
1212
public protocol HasClick: HasRUI, HasCollision {
13-
/// Action to be applied on successfully tapping an Entity.
14-
var tapAction: ((HasClick, SIMD3<Float>?) -> Void)? {get set}
13+
/// Action to be applied on successfully tapping an Entity.
14+
var tapAction: ((HasClick, SIMD3<Float>?) -> Void)? {get set}
1515
}
1616
internal extension HasClick {
17-
func onTap(worldCollision: SIMD3<Float>? = nil) {
18-
self.tapAction?(self, worldCollision)
19-
}
17+
func onTap(worldCollision: SIMD3<Float>? = nil) {
18+
self.tapAction?(self, worldCollision)
19+
}
2020
}

Sources/RealityUI/HasRUI.swift

Lines changed: 88 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -11,112 +11,117 @@ import CoreGraphics
1111

1212
/// A collection of properties for all RealityUI Entities.
1313
public struct RUIComponent: Component {
14-
/// A Boolean value indicating whether the RealityUI Entity is enabled.
15-
public internal(set) var ruiEnabled: Bool
16-
/// A Boolean value indicating whether the RealityUI Entity materials respond to light.
17-
internal var respondsToLighting: Bool
14+
/// A Boolean value indicating whether the RealityUI Entity is enabled.
15+
public internal(set) var ruiEnabled: Bool
16+
/// A Boolean value indicating whether the RealityUI Entity materials respond to light.
17+
internal var respondsToLighting: Bool
1818

19-
/// Create a new `RUIComponent` for a RealityUI Entity
20-
/// - Parameters:
21-
/// - isEnabled: A Boolean value indicating whether the RealityUI Entity is enabled.
22-
/// - respondsToLighting: A Boolean value indicating whether the RealityUI Entity materials respond to light.
23-
public init(isEnabled: Bool = true, respondsToLighting: Bool = false) {
24-
self.ruiEnabled = isEnabled
25-
self.respondsToLighting = respondsToLighting
26-
}
19+
/// Create a new ``RUIComponent`` for a RealityUI Entity
20+
/// - Parameters:
21+
/// - isEnabled: A Boolean value indicating whether the RealityUI Entity is enabled.
22+
/// - respondsToLighting: A Boolean value indicating whether the RealityUI Entity materials respond to light.
23+
public init(isEnabled: Bool = true, respondsToLighting: Bool = false) {
24+
self.ruiEnabled = isEnabled
25+
self.respondsToLighting = respondsToLighting
26+
}
2727
}
2828

2929
/// An interface used for all entities in the RealityUI package
30-
public protocol HasRUI: Entity {
31-
}
30+
public protocol HasRUI: Entity {}
31+
3232
public extension HasRUI {
33-
/// A Boolean value that determines whether touch events are ignored on this RealityUI Entity
34-
var ruiEnabled: Bool {
35-
get { self.RUI.ruiEnabled }
36-
set {
37-
if self.RUI.ruiEnabled == newValue { return }
38-
self.RUI.ruiEnabled = newValue
39-
(self as? HasRUIMaterials)?.materialsShouldChange()
33+
/// A Boolean value that determines whether touch events are ignored on this RealityUI Entity
34+
var ruiEnabled: Bool {
35+
get { self.rui.ruiEnabled }
36+
set {
37+
if self.rui.ruiEnabled == newValue { return }
38+
self.rui.ruiEnabled = newValue
39+
(self as? HasRUIMaterials)?.materialsShouldChange()
40+
}
4041
}
41-
}
4242

43-
/// A Boolean value that determines whether this Entity's materials respond to lighting
44-
var respondsToLighting: Bool {
45-
get { self.RUI.respondsToLighting }
46-
set {
47-
if self.RUI.respondsToLighting == newValue { return }
48-
self.RUI.respondsToLighting = newValue
49-
(self as? HasRUIMaterials)?.materialsShouldChange()
43+
/// A Boolean value that determines whether this Entity's materials respond to lighting
44+
var respondsToLighting: Bool {
45+
get { self.rui.respondsToLighting }
46+
set {
47+
if self.rui.respondsToLighting == newValue { return }
48+
self.rui.respondsToLighting = newValue
49+
(self as? HasRUIMaterials)?.materialsShouldChange()
50+
}
5051
}
51-
}
5252

53-
/// Replace the current RUIComponent
54-
/// - Parameter RUI: new RUIComponent
55-
func replaceRUI(with RUI: RUIComponent) {
56-
self.RUI = RUI
57-
(self as? HasRUIMaterials)?.materialsShouldChange()
58-
}
53+
/// Replace the current RUIComponent
54+
/// - Parameter rui: new RUIComponent
55+
func replaceRUI(with rui: RUIComponent) {
56+
self.rui = rui
57+
(self as? HasRUIMaterials)?.materialsShouldChange()
58+
}
5959

60-
/// RealityUI Component for the entity.
61-
internal(set) var RUI: RUIComponent {
62-
get {
63-
if let ruiComp = self.components[RUIComponent.self] as? RUIComponent {
64-
return ruiComp
65-
} else {
66-
self.components[RUIComponent.self] = RUIComponent()
67-
return self.components[RUIComponent.self]!
68-
}
60+
@available(*, deprecated, renamed: "rui")
61+
internal(set) var RUI: RUIComponent {
62+
get { self.rui }
63+
set { self.rui = newValue }
6964
}
70-
set {
71-
self.components[RUIComponent.self] = newValue
65+
/// RealityUI Component for the entity.
66+
internal(set) var rui: RUIComponent {
67+
get {
68+
if let ruiComp = self.components[RUIComponent.self] as? RUIComponent {
69+
return ruiComp
70+
} else {
71+
self.components[RUIComponent.self] = RUIComponent()
72+
return self.components[RUIComponent.self]!
73+
}
74+
}
75+
set {
76+
self.components[RUIComponent.self] = newValue
77+
}
7278
}
73-
}
7479

7580
}
7681

7782
internal extension HasRUI {
78-
func getModel(part: String) -> ModelEntity? {
79-
self.findEntity(named: part) as? ModelEntity
80-
}
81-
func ruiOrientation() {
82-
if let startOrient = RealityUI.startingOrientation {
83-
self.orientation = startOrient
83+
func getModel(part: String) -> ModelEntity? {
84+
self.findEntity(named: part) as? ModelEntity
85+
}
86+
func ruiOrientation() {
87+
if let startOrient = RealityUI.startingOrientation {
88+
self.orientation = startOrient
89+
}
8490
}
85-
}
86-
func addModel(part: String) -> ModelEntity {
87-
if let modelPart = self.getModel(part: part) {
88-
return modelPart
91+
func addModel(part: String) -> ModelEntity {
92+
if let modelPart = self.getModel(part: part) {
93+
return modelPart
94+
}
95+
let newModelPart = ModelEntity()
96+
newModelPart.name = part
97+
self.addChild(newModelPart)
98+
return newModelPart
8999
}
90-
let newModelPart = ModelEntity()
91-
newModelPart.name = part
92-
self.addChild(newModelPart)
93-
return newModelPart
94-
}
95100
}
96101

97102
/// An interface used for RealityUI entities that have materials generated from colours
98-
/// These materials change with ruiEnabled and `self.RUI.respondsToLighting`.
103+
/// These materials change with ``HasRUI/ruiEnabled`` and ``HasRUI/respondsToLighting``.
99104
public protocol HasRUIMaterials: HasRUI {
100-
/// All RealityUI Entities should have a method for updating all the materials
101-
/// This is in case of disabling entities or changing their responsiveness to light.
102-
/// This method does not need to be called by outside of a RealityUI class.
103-
func updateMaterials()
105+
/// All RealityUI Entities should have a method for updating all the materials
106+
/// This is in case of disabling entities or changing their responsiveness to light.
107+
/// This method does not need to be called by outside of a RealityUI class.
108+
func updateMaterials()
104109
}
105110
extension HasRUIMaterials {
106-
fileprivate func materialsShouldChange() {
107-
self.updateMaterials()
108-
}
109-
func getMaterial(with color: Material.Color) -> Material {
110-
var alpha: CGFloat = 0
111-
#if os(macOS)
112-
alpha = color.alphaComponent
113-
#else
114-
color.getWhite(nil, alpha: &alpha)
115-
#endif
116-
let adjustedColor = color.withAlphaComponent(alpha * (self.ruiEnabled ? 1 : 0.5))
117-
if self.RUI.respondsToLighting {
118-
return SimpleMaterial(color: adjustedColor, isMetallic: false)
111+
fileprivate func materialsShouldChange() {
112+
self.updateMaterials()
113+
}
114+
func getMaterial(with color: Material.Color) -> Material {
115+
var alpha: CGFloat = 0
116+
#if os(macOS)
117+
alpha = color.alphaComponent
118+
#else
119+
color.getWhite(nil, alpha: &alpha)
120+
#endif
121+
let adjustedColor = color.withAlphaComponent(alpha * (self.ruiEnabled ? 1 : 0.5))
122+
if self.rui.respondsToLighting {
123+
return SimpleMaterial(color: adjustedColor, isMetallic: false)
124+
}
125+
return UnlitMaterial(color: adjustedColor)
119126
}
120-
return UnlitMaterial(color: adjustedColor)
121-
}
122127
}

0 commit comments

Comments
 (0)