@@ -277,8 +277,9 @@ public readonly record struct ConnectionEvent(IInputDevice Device, long Timestam
277277public readonly record struct KeyChangedEvent (IKeyboard Keyboard , long Timestamp , Button <KeyName > Key , Button <KeyName > Previous , bool IsRepeat , KeyModifiers Modifiers );
278278public readonly record struct KeyCharEvent (IKeyboard Keyboard , long Timestamp , char ? Character );
279279public readonly record struct ButtonChangedEvent <T >(IButtonDevice <T > Device , long Timestamp , Button <T > Button , Button <T > Previous ) where T : struct , Enum ;
280- public readonly record struct PointChangedEvent (IPointer Pointer , long Timestamp , TargetPoint ? OldPoint , TargetPoint Point );
280+ public readonly record struct PointChangedEvent (IPointer Pointer , long Timestamp , TargetPoint ? OldPoint , TargetPoint ? NewPoint );
281281public readonly record struct PointerGripChangedEvent (IPointer Pointer , long Timestamp , float GripPressure , float Delta );
282+ public readonly record struct PointerTargetChangedEvent (IPointer Pointer , long Timestamp , IPointerTarget Target , bool IsAdded , Box3F <float > OldBounds , Box3F <float > NewBounds );
282283public readonly record struct MouseScrollEvent (IMouse Mouse , long Timestamp , TargetPoint Point , Vector2 WheelPosition , Vector2 Delta );
283284public readonly record struct PointerClickEvent (IPointer Pointer , long Timestamp , TargetPoint Point , MouseButton Button );
284285public readonly record struct JoystickHatMoveEvent (IJoystick Joystick , long Timestamp , Vector2 Value , Vector2 Delta );
@@ -372,23 +373,13 @@ A target is defined as follows:
372373public interface IPointerTarget
373374{
374375 /// <summary >
375- /// The minimum position of points on this target, where <see cref =" float.NegativeInfinity" /> represents the lack
376- /// of a lower bound on a particular axis and <c >0</c > represents an unused axis if <see cref =" MaxPosition" /> is
377- /// also <c >0</c > for that axis.
376+ /// The boundary in which positions of points on this target shall fall. For <see cref =" Box3F{T}.Min" />,
377+ /// <see cref =" float.NegativeInfinity" /> shall represent the lack of a lower bound on a particular axis. For
378+ /// For <see cref =" Box3F{T}.Max" />, <see cref =" float.PositiveInfinity" /> shall represent the lack of a lower bound
379+ /// on a particular axis. <c >0</c > represents an unused axis that axis is <c >0</c > on both
380+ /// <see cref =" Box3F{T}.Min" /> and <see cref =" Box3F{T}.Max" />.
378381 /// </summary >
379- Vector3 MinPosition { get ; }
380-
381- /// <summary >
382- /// The maximum position of points on this target, where <see cref =" float.PositiveInfinity" /> represents the lack
383- /// of an upper bound on a particular axis and <c >0</c > represents an unused axis if <see cref =" MinPosition" /> is
384- /// also <c >0</c > for that axis.
385- /// </summary >
386- Vector3 MaxPosition { get ; }
387-
388- /// <summary >
389- /// An optional name describing the target.
390- /// </summary >
391- string ? Name { get ; }
382+ Box3F <float > Bounds { get ; }
392383
393384 /// <summary >
394385 /// Gets the number of points with which the given pointer is pointing at this target.
@@ -415,6 +406,10 @@ public interface IPointerTarget
415406}
416407```
417408
409+ ** FUTURE IMPROVEMENT:** This interface could be expanded to provide rotation of the target itself as well, representing
410+ a full ` Transform ` structure for the space. At this time, this was not deemed necessary for inclusion, but should be a
411+ trivial extension to add in the future.
412+
418413** INFORMATIVE TEXT** : Furthermore, it is our eventual goal to be able to support considering VR hands as pointer devices
419414through raycasting. Such a future proposal will involve a way to create a child target within the bounds of this target
420415a ` IPointerTarget ` from that which represents the 3D world (i.e. the entire VR world is a target, and the point
@@ -445,31 +440,39 @@ public enum TargetPointFlags
445440/// <summary >
446441/// Represents a point on a target at which a pointer is pointing.
447442/// </summary >
443+ /// <param name =" Id" >
444+ /// An integral identifier for the point. This point must be the only point for the device currently pointing at a
445+ /// target with this identifier at any given time. If this point ceases to point at the target, then the identifier
446+ /// becomes free for another device point. This means that this identifier can just be an index, but may be globally
447+ /// unique depending on the backend's capabilities.
448+ /// </param >
448449/// <param name =" Flags" >Flags describing the state of the point.</param >
449450/// <param name =" Position" >The absolute position on the target at which the pointer is pointing.</param >
450451/// <param name =" NormalizedPosition" >
451452/// The normalized position on the target at which the pointer is pointing, if applicable. If this is not available
452453/// (e.g. due to the target being infinitely large a.k.a. "unbounded"), then this property shall have a value of
453454/// <c >default</c >.
454455/// </param >
455- /// <param name =" Orientation" >
456- /// The angle at which the pointer is pointing at the point on the target. An identity quaternion shall be interpreted
457- /// as the point directly perpendicular to and facing towards the target. This shall carry an identity quaternion if
458- /// there is no orientation available.
456+ /// <param name =" Pointer" >
457+ /// A ray representing the distance and angle at which the pointer is pointing at the point on the target. A ray with an
458+ /// orientation equivalent to an identity quaternion shall be interpreted as the point directly perpendicular to and
459+ /// facing towards the target, with this being the default value should this information be unavailable. If distance
460+ /// information is unavailable, this shall be equivalent to a <c >default</c > vector.
459461/// </param >
460- /// <param name =" Distance" >The distance of the pointer from the point the pointer is pointing at.</param >
461462/// <param name =" Pressure" >
462463/// The pressure applied to the point on the target by the pointer, between <c >0.0</c > representing the minimum amount
463464/// of pressure and <c >1.0</c > representing the maximum amount of pressure. This shall be <c >1.0</c > if such data is
464465/// unavailable but the point is otherwise valid.
465466/// </param >
467+ /// <param name =" Target" >The pointer being pointed at.</param >
466468public readonly record struct TargetPoint (
469+ int Id ,
467470 TargetPointFlags Flags ,
468471 Vector3 Position ,
469472 Vector3 NormalizedPosition ,
470- Quaternion Orientation ,
471- Vector3 Distance ,
472- float Pressure
473+ Ray3F < float > Pointer ,
474+ float Pressure ,
475+ IPointerTarget Target
473476) {
474477 public bool IsValid => (Flags & Flags .PointingAtTarget ) != Flags .NotPointingAtTarget ;
475478}
@@ -480,11 +483,9 @@ The `PointerState` shall be defined as follows:
480483public class PointerState
481484{
482485 public ButtonReadOnlyList <PointerButton > Buttons { get ; }
483- public InputReadOnlyList <PointerStatePoint > Points { get ; }
486+ public InputReadOnlyList <TargetPoint > Points { get ; }
484487 public float GripPressure { get ; }
485488}
486-
487- public readonly record struct PointerStatePoint (IPointerTarget Target , TargetPoint Point );
488489```
489490
490491` Points ` represents the ` TargetPoint ` s this pointer is pointing at on its "native targets" i.e. that which is enumerated
@@ -501,15 +502,43 @@ The handler for pointer inputs shall be defined as follows:
501502``` cs
502503public interface IPointerInputHandler : IButtonInputHandler <PointerButton >
503504{
505+ void HandleTargetChanged (PointerTargetChangedEvent @event );
504506 void HandlePointChanged (PointChangedEvent @event );
505507 void HandleGripChanged (PointerGripChangedEvent @event );
506508}
507509```
508510
511+ ` HandleTargetChanged ` must be called when properties on an ` IPointerTarget ` within ` IPointer.Targets ` changes, or when
512+ an ` IPointerTarget ` is added or removed to/from ` IPointer.Targets ` . ` IsAdded ` shall be ` true ` if it has been added,
513+ ` false ` if it has been removed.
514+
509515` HandlePointChanged ` must be called when a point within ` PointerState.Points ` changes.
510516
511517` HandleGripChanged ` must be called when ` PointerState.GripPressure ` changes.
512518
519+ These device interfaces and related APIs are designed to mirror physical hardware that the user uses to point at a
520+ target. However, there are many cases where applications would work better with an abstraction that creates "virtual
521+ pointers" for each point, rather that the points being spread across many logical devices. For this we propose the
522+ following addendum to the ` Pointers ` class:
523+
524+ ``` cs
525+ public partial class Pointers
526+ {
527+ public IReadOnlyList <ContextPoint > Points { get ; }
528+ }
529+
530+ public readonly record struct ContextPoint (IPointer Device , TargetPoint Point , ButtonReadOnlyList <PointerButton > Buttons , float GripPressure )
531+ {
532+ public int Id { get ; }
533+ }
534+ ```
535+
536+ ` Id ` shall be an identifier that mixes ` Point.Id ` and ` Device.Id ` in a way that ensures the identifier is unique across
537+ the whole context.
538+
539+ ** FUTURE IMPROVEMENT:** The ` Pointers ` class is also expected to be the site of gesture recognition when proposed in the
540+ future.
541+
513542` PointerButton ` shall be defined as follows:
514543``` cs
515544public enum PointerButton
0 commit comments