@@ -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