Skip to content

Commit d6a8094

Browse files
committed
Improve PointerEventComponent
- Add secondLastEvent - latestEventForCurrentFrame is no longer a computed property. CHECK: Should improve performance. - OCD indentation
1 parent caafe1a commit d6a8094

File tree

1 file changed

+70
-39
lines changed

1 file changed

+70
-39
lines changed

Sources/OctopusKit/Components/Input/Pointer/PointerEventComponent.swift

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -118,51 +118,78 @@ public final class PointerEventComponent: OctopusComponent, OctopusUpdatableComp
118118
@LogInputEventChanges(propertyName: "PointerEventComponent.pointerBegan")
119119
public var pointerBegan: PointerEvent? = nil { // Not private(set) so we can make update(deltaTime:) @inlinable
120120
didSet {
121-
if let pointerBegan = pointerBegan,
122-
(lastEvent == nil || lastEvent!.timestamp < pointerBegan.timestamp)
123-
{
124-
lastEvent = pointerBegan
121+
if let pointerBegan = pointerBegan {
122+
123+
if lastEvent == nil || lastEvent!.timestamp < pointerBegan.timestamp {
124+
lastEvent = pointerBegan
125+
}
126+
127+
if latestEventForCurrentFrame == nil || latestEventForCurrentFrame!.timestamp < pointerBegan.timestamp {
128+
latestEventForCurrentFrame = pointerBegan
129+
}
125130
}
126131
}
127132
}
128133

129134
@LogInputEventChanges(propertyName: "PointerEventComponent.pointerMoved")
130135
public var pointerMoved: PointerEvent? = nil { // Not private(set) so we can make update(deltaTime:) @inlinable
131-
didSet {
132-
if let pointerMoved = pointerMoved,
133-
(lastEvent == nil || lastEvent!.timestamp < pointerMoved.timestamp)
134-
{
135-
lastEvent = pointerMoved
136-
}
137-
}
138-
}
136+
didSet {
137+
if let pointerMoved = pointerMoved {
138+
139+
if lastEvent == nil || lastEvent!.timestamp < pointerMoved.timestamp {
140+
lastEvent = pointerMoved
141+
}
142+
143+
if latestEventForCurrentFrame == nil || latestEventForCurrentFrame!.timestamp < pointerMoved.timestamp {
144+
latestEventForCurrentFrame = pointerMoved
145+
}
146+
}
147+
}
148+
}
139149

140150
@LogInputEventChanges(propertyName: "PointerEventComponent.pointerEnded")
141151
public var pointerEnded: PointerEvent? = nil { // Not private(set) so we can make update(deltaTime:) @inlinable
142-
didSet {
143-
if let pointerEnded = pointerEnded,
144-
(lastEvent == nil || lastEvent!.timestamp < pointerEnded.timestamp)
145-
{
146-
lastEvent = pointerEnded
147-
}
148-
}
149-
}
152+
didSet {
153+
if let pointerEnded = pointerEnded {
154+
155+
if lastEvent == nil || lastEvent!.timestamp < pointerEnded.timestamp {
156+
lastEvent = pointerEnded
157+
}
158+
159+
if latestEventForCurrentFrame == nil || latestEventForCurrentFrame!.timestamp < pointerEnded.timestamp {
160+
latestEventForCurrentFrame = pointerEnded
161+
}
162+
163+
}
164+
}
165+
}
150166

151167
/// Returns the event which was received during this frame. To check the last event received in previous frames, use `lastEvent`
152-
@inlinable
153-
public var latestEventForCurrentFrame: PointerEvent? {
154-
[pointerBegan, pointerMoved, pointerEnded]
155-
.compactMap { $0 }
156-
.sorted { $0.timestamp > $1.timestamp }
157-
.first
158-
}
168+
// @inlinable
169+
public var latestEventForCurrentFrame: PointerEvent? = nil // Not private(set) so update(deltaTime:) can be @inlinable
170+
// {
171+
// [pointerBegan, pointerMoved, pointerEnded]
172+
// .compactMap { $0 }
173+
// .sorted { $0.timestamp > $1.timestamp }
174+
// .first
175+
// }
159176

160177
@available(*, unavailable, renamed: "latestEventForCurrentFrame")
161178
public var latestEvent: PointerEvent? = nil // TODO: Remove in 4.0.0 :)
162179

163-
/// Returns the last event received during this *or any previous* previous frames. To check the *latest* event received during the current frame, use `latestEvent`.
180+
/// Returns the last event received during this *or any previous* frames. To check the *latest* event received during the current frame, use `latestEventForCurrentFrame`.
164181
@LogInputEventChanges(propertyName: "PointerEventComponent.lastEvent")
165-
public private(set) var lastEvent: PointerEvent? = nil
182+
public private(set) var lastEvent: PointerEvent? = nil {
183+
didSet {
184+
if lastEvent != oldValue {
185+
secondLastEvent = oldValue
186+
}
187+
}
188+
}
189+
190+
/// Returns the second last event received in previous updates. Use this for comparing pointer movement and state between events.
191+
@LogInputEventChanges(propertyName: "PointerEventComponent.secondLastEvent")
192+
public private(set) var secondLastEvent: PointerEvent? = nil
166193

167194
// MARK: - Frame Cycle
168195

@@ -179,25 +206,29 @@ public final class PointerEventComponent: OctopusComponent, OctopusUpdatableComp
179206
return
180207
}
181208

182-
// #2: Mirror a `TouchEventComponent` on iOS or a `MouseEventComponent` on macOS.
209+
// #2: Clear latestEventForCurrentFrame until we have an event.
210+
211+
latestEventForCurrentFrame = nil
212+
213+
// #3: Mirror a `TouchEventComponent` on iOS or a `MouseEventComponent` on macOS.
183214

184215
#if canImport(AppKit)
185216

186217
if let mouseEventComponent = coComponent(MouseEventComponent.self) {
187218

188-
if let mouseDown = mouseEventComponent.mouseDown {
219+
if let mouseDown = mouseEventComponent.mouseDown {
189220
pointerBegan = PointerEvent(category: .began,
190221
event: mouseDown.event,
191222
node: mouseDown.node)
192223
}
193224

194-
if let mouseDragged = mouseEventComponent.mouseDragged {
225+
if let mouseDragged = mouseEventComponent.mouseDragged {
195226
pointerMoved = PointerEvent(category: .moved,
196227
event: mouseDragged.event,
197228
node: mouseDragged.node)
198229
}
199230

200-
if let mouseUp = mouseEventComponent.mouseUp {
231+
if let mouseUp = mouseEventComponent.mouseUp {
201232
pointerEnded = PointerEvent(category: .ended,
202233
event: mouseUp.event,
203234
node: mouseUp.node)
@@ -206,16 +237,16 @@ public final class PointerEventComponent: OctopusComponent, OctopusUpdatableComp
206237

207238
#elseif canImport(UIKit)
208239

209-
if let touchEventComponent = coComponent(TouchEventComponent.self) {
240+
if let touchEventComponent = coComponent(TouchEventComponent.self) {
210241

211-
if let touchesBegan = touchEventComponent.touchesBegan {
242+
if let touchesBegan = touchEventComponent.touchesBegan {
212243
pointerBegan = PointerEvent(category: .began,
213244
firstTouch: touchesBegan.touches.first,
214245
event: touchesBegan.event,
215246
node: touchesBegan.node)
216247
}
217248

218-
if let touchesMoved = touchEventComponent.touchesMoved {
249+
if let touchesMoved = touchEventComponent.touchesMoved {
219250
pointerMoved = PointerEvent(category: .moved,
220251
firstTouch: touchesMoved.touches.first,
221252
event: touchesMoved.event,
@@ -224,7 +255,7 @@ public final class PointerEventComponent: OctopusComponent, OctopusUpdatableComp
224255

225256
// ⚠️ TODO: CHECK: Safeguard against different touches being ended or cancelled, which may cause jumps in touch-dependent nodes when using multiple fingers.
226257

227-
if let touchesEnded = touchEventComponent.touchesEnded ?? touchEventComponent.touchesCancelled {
258+
if let touchesEnded = touchEventComponent.touchesEnded ?? touchEventComponent.touchesCancelled {
228259
pointerEnded = PointerEvent(category: .ended,
229260
firstTouch: touchesEnded.touches.first,
230261
event: touchesEnded.event,
@@ -234,15 +265,15 @@ public final class PointerEventComponent: OctopusComponent, OctopusUpdatableComp
234265

235266
#endif
236267

237-
// #3: Clear stale events whose flags have been set.
268+
// #4: Clear stale events whose flags have been set.
238269

239270
// ℹ️ We cannot use `if let` unwrapping as we need to modify the actual properties themselves, not their values.
240271

241272
if pointerBegan?.shouldClear ?? false { pointerBegan = nil }
242273
if pointerMoved?.shouldClear ?? false { pointerMoved = nil }
243274
if pointerEnded?.shouldClear ?? false { pointerEnded = nil }
244275

245-
// #4: Flag non-`nil` events to be cleared on the next frame, so that other components do not see any stale input data.
276+
// #5: Flag non-`nil` events to be cleared on the next frame, so that other components do not see any stale input data.
246277

247278
pointerBegan?.shouldClear = true
248279
pointerMoved?.shouldClear = true

0 commit comments

Comments
 (0)