Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[iOS] Stylus support #3113

Merged
merged 43 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
ada4fbf
Add initial implementation to Pan
m-bert Sep 15, 2024
9138c70
Mergele main
m-bert Sep 16, 2024
d7c6b76
Merge branch 'main' into @mbert/stylus-support-web
m-bert Sep 17, 2024
3f5a48c
Add another conversion algorithm
m-bert Sep 17, 2024
5992af5
Add stylus support to hover
m-bert Sep 17, 2024
dc601b7
Change comparison operators
m-bert Sep 17, 2024
8c8f104
Add check for undefined azimuth
m-bert Sep 17, 2024
8012cda
Add missing tsdocs
m-bert Sep 17, 2024
02f1a3b
Add example
m-bert Sep 17, 2024
95599e0
Send pressure on pointerMove
m-bert Sep 17, 2024
ebc5321
Add docs
m-bert Sep 17, 2024
e562197
Merge branch 'main' into @mbert/stylus-support-web
m-bert Sep 17, 2024
b3edab6
Update example
m-bert Sep 18, 2024
878a43d
Remove docs
m-bert Sep 18, 2024
93ab09f
Works... but not really
m-bert Sep 18, 2024
ab2edb3
Works
m-bert Sep 18, 2024
08b9f5b
Set reference at init
m-bert Sep 18, 2024
ad5e32b
Add if
m-bert Sep 18, 2024
f3b97e1
Merge branch 'main' into @mbert/stylus-support-web
m-bert Sep 18, 2024
d60656f
Merge branch 'main' into @mbert/stylus-support-ios
m-bert Sep 18, 2024
91cbc3d
Remove hover from example
m-bert Sep 18, 2024
d8ef835
Merge branch '@mbert/stylus-support-web' into @mbert/stylus-support-ios
m-bert Sep 18, 2024
5f0aca9
Change assign to strong
m-bert Sep 18, 2024
099d03e
Fix macos build
m-bert Sep 19, 2024
e3440b8
Avoid sending empty stylus data
m-bert Sep 19, 2024
64c6fa9
Simplify code and fix macos build
m-bert Sep 19, 2024
a424031
Mergele main
m-bert Sep 19, 2024
b8f2afb
Change signature
m-bert Sep 19, 2024
e120bac
Do not use the same reference
m-bert Sep 19, 2024
252a7de
Move pressure change to reset
m-bert Sep 19, 2024
b359bc4
Add prefix
m-bert Sep 19, 2024
3b1ac10
More prefixes
m-bert Sep 19, 2024
f482862
Return object without assignment
m-bert Sep 19, 2024
b25ff50
Merge branch 'main' into @mbert/stylus-support-ios
m-bert Sep 20, 2024
708baef
Fix build macos
m-bert Sep 20, 2024
832df10
Merge branch 'main' into @mbert/stylus-support-ios
m-bert Sep 20, 2024
b2a7437
Review suggestions
m-bert Sep 20, 2024
716f1f9
Merge branch 'main' into @mbert/stylus-support-ios
m-bert Sep 23, 2024
16afa6e
Remove #ifs
m-bert Sep 23, 2024
e27b3a3
Merge branch 'main' into @mbert/stylus-support-ios
m-bert Sep 23, 2024
848f69e
Fix macos build
m-bert Sep 24, 2024
9044aeb
Merge branch 'main' into @mbert/stylus-support-ios
m-bert Sep 24, 2024
35ce0de
Add commentary
m-bert Sep 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 57 additions & 7 deletions apple/Handlers/RNPanHandler.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import "RNPanHandler.h"
#import "RNGHStylusData.h"

#if TARGET_OS_OSX

Expand All @@ -31,6 +32,10 @@ @interface RNBetterPanGestureRecognizer : UIPanGestureRecognizer
@property (nonatomic) CGFloat failOffsetYEnd;
@property (nonatomic) CGFloat activateAfterLongPress;

#if !TARGET_OS_OSX && !TARGET_OS_TV
@property (atomic, readonly, strong) RNGHStylusData *stylusData;
#endif

- (id)initWithGestureHandler:(RNGestureHandler *)gestureHandler;

@end
Expand Down Expand Up @@ -80,6 +85,28 @@ - (void)setMinimumNumberOfTouches:(NSUInteger)minimumNumberOfTouches
}
#endif

#if !TARGET_OS_OSX && !TARGET_OS_TV
- (void)tryUpdateStylusData:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];

if (touch.type != UITouchTypePencil) {
return;
} else if (_stylusData == nil) {
_stylusData = [[RNGHStylusData alloc] init];
}

_stylusData.altitudeAngle = touch.altitudeAngle;
_stylusData.azimuthAngle = [touch azimuthAngleInView:nil];
_stylusData.pressure = touch.force / touch.maximumPossibleForce;

CGPoint tilts = ghSpherical2tilt(_stylusData.altitudeAngle, _stylusData.azimuthAngle);

_stylusData.tiltX = tilts.x;
_stylusData.tiltY = tilts.y;
}
#endif

- (void)activateAfterLongPress
{
self.state = UIGestureRecognizerStateBegan;
Expand All @@ -102,6 +129,8 @@ - (void)interactionsBegan:(NSSet *)touches withEvent:(UIEvent *)event
} else {
super.minimumNumberOfTouches = _realMinimumNumberOfTouches;
}

[self tryUpdateStylusData:event];
#endif

#if TARGET_OS_OSX
Expand Down Expand Up @@ -150,17 +179,28 @@ - (void)interactionsMoved:(NSSet *)touches withEvent:(UIEvent *)event
[self setTranslation:CGPointMake(0, 0) inView:self.view];
}
}

[self tryUpdateStylusData:event];
#endif
}

- (void)interactionsEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[_gestureHandler.pointerTracker touchesEnded:touches withEvent:event];

#if !TARGET_OS_TV && !TARGET_OS_OSX
[self tryUpdateStylusData:event];
#endif
}

- (void)interactionsCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[_gestureHandler.pointerTracker touchesCancelled:touches withEvent:event];

#if !TARGET_OS_TV && !TARGET_OS_OSX
[self tryUpdateStylusData:event];
#endif

[self reset];
}

Expand Down Expand Up @@ -224,6 +264,10 @@ - (void)reset
self.enabled = YES;
[super reset];
[_gestureHandler reset];

#if !TARGET_OS_TV && !TARGET_OS_OSX
_stylusData = nil;
#endif
}

- (void)updateHasCustomActivationCriteria
Expand Down Expand Up @@ -405,17 +449,23 @@ - (RNGestureHandlerEventExtraData *)eventExtraData:(NSPanGestureRecognizer *)rec
withTranslation:[recognizer translationInView:recognizer.view.window.contentView]
withVelocity:[recognizer velocityInView:recognizer.view.window.contentView]
withNumberOfTouches:1
withPointerType:RNGestureHandlerMouse];
withPointerType:RNGestureHandlerMouse
j-piasecki marked this conversation as resolved.
Show resolved Hide resolved
withStylusData:nil];
}
#else
- (RNGestureHandlerEventExtraData *)eventExtraData:(UIPanGestureRecognizer *)recognizer
{
return [RNGestureHandlerEventExtraData forPan:[recognizer locationInView:recognizer.view]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
withTranslation:[recognizer translationInView:recognizer.view.window]
withVelocity:[recognizer velocityInView:recognizer.view.window]
withNumberOfTouches:recognizer.numberOfTouches
withPointerType:_pointerType];
RNBetterPanGestureRecognizer *panRecognizer = (RNBetterPanGestureRecognizer *)recognizer;

return [RNGestureHandlerEventExtraData
forPan:[recognizer locationInView:recognizer.view]
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
withTranslation:[recognizer translationInView:recognizer.view.window]
withVelocity:[recognizer velocityInView:recognizer.view.window]
withNumberOfTouches:recognizer.numberOfTouches
withPointerType:_pointerType
withStylusData:[panRecognizer.stylusData toDictionary]]; // In Objective-C calling method on nil returns
// nil, therefore this line does not crash.
}
#endif

Expand Down
77 changes: 77 additions & 0 deletions apple/RNGHStylusData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// RNGHStylusData.h
// Pods
//
// Created by Michał Bert on 18/09/2024.
//

#ifndef RNGHStylusData_h
#define RNGHStylusData_h

@interface RNGHStylusData : NSObject

@property (atomic, assign) double tiltX;
@property (atomic, assign) double tiltY;
@property (atomic, assign) double altitudeAngle;
@property (atomic, assign) double azimuthAngle;
@property (atomic, assign) double pressure;

- (NSDictionary *)toDictionary;

@end

static CGPoint ghSpherical2tilt(double altitudeAngle, double azimuthAngle)
{
CGPoint tilts = {.x = 0.0, .y = 0.0};

const double radToDeg = 180 / M_PI;
const double eps = 0.000000001;

if (altitudeAngle < eps) {
// the pen is in the X-Y plane
if (azimuthAngle < eps || fabs(azimuthAngle - 2 * M_PI) < eps) {
// pen is on positive X axis
tilts.x = M_PI_2;
}
if (fabs(azimuthAngle - M_PI_2) < eps) {
// pen is on positive Y axis
tilts.y = M_PI_2;
}
if (fabs(azimuthAngle - M_PI) < eps) {
// pen is on negative X axis
tilts.x = -M_PI_2;
}
if (fabs(azimuthAngle - 3 * M_PI_2) < eps) {
// pen is on negative Y axis
tilts.y = -M_PI_2;
}
if (azimuthAngle > eps && fabs(azimuthAngle - M_PI_2) < eps) {
tilts.x = M_PI_2;
tilts.y = M_PI_2;
}
if (fabs(azimuthAngle - M_PI_2) > eps && fabs(azimuthAngle - M_PI) < eps) {
tilts.x = -M_PI_2;
tilts.y = M_PI_2;
}
if (azimuthAngle - M_PI > eps && fabs(azimuthAngle - 3 * M_PI_2) < eps) {
tilts.x = -M_PI_2;
tilts.y = -M_PI_2;
}
if (fabs(azimuthAngle - 3 * M_PI_2) > eps && fabs(azimuthAngle - 2 * M_PI) < eps) {
tilts.x = M_PI_2;
tilts.y = -M_PI_2;
}
} else {
const double tanAlt = tan(altitudeAngle);

tilts.x = atan(cos(azimuthAngle) / tanAlt);
tilts.y = atan(sin(azimuthAngle) / tanAlt);
}

tilts.x = round(tilts.x * radToDeg);
tilts.y = round(tilts.y * radToDeg);

return tilts;
}

#endif /* RNGHStylusData_h */
37 changes: 37 additions & 0 deletions apple/RNGHStylusData.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// RNGHStylusData.m
// DoubleConversion
//
// Created by Michał Bert on 18/09/2024.
//

#import "RNGHStylusData.h"
#import <Foundation/Foundation.h>

@implementation RNGHStylusData

- (instancetype)init
{
if (self = [super init]) {
self.tiltX = 0;
self.tiltY = 0;
self.altitudeAngle = M_PI_2;
self.azimuthAngle = 0;
self.pressure = 0;
}

return self;
}

- (NSDictionary *)toDictionary
{
return @{
@"tiltX" : @(_tiltX),
@"tiltY" : @(_tiltY),
@"altitudeAngle" : @(_altitudeAngle),
@"azimuthAngle" : @(_azimuthAngle),
@"pressure" : @(_pressure),
};
}

@end
4 changes: 3 additions & 1 deletion apple/RNGestureHandlerEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#import <Foundation/Foundation.h>

#import "RNGHStylusData.h"
#import "RNGHTouchEventType.h"
#import "RNGHUIKit.h"
#import "RNGestureHandlerState.h"
Expand Down Expand Up @@ -29,7 +30,8 @@
withTranslation:(CGPoint)translation
withVelocity:(CGPoint)velocity
withNumberOfTouches:(NSUInteger)numberOfTouches
withPointerType:(NSInteger)pointerType;
withPointerType:(NSInteger)pointerType
withStylusData:(NSDictionary *)stylusData;
+ (RNGestureHandlerEventExtraData *)forForce:(CGFloat)force
forPosition:(CGPoint)position
withAbsolutePosition:(CGPoint)absolutePosition
Expand Down
14 changes: 11 additions & 3 deletions apple/RNGestureHandlerEvents.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ + (RNGestureHandlerEventExtraData *)forPan:(CGPoint)position
withVelocity:(CGPoint)velocity
withNumberOfTouches:(NSUInteger)numberOfTouches
withPointerType:(NSInteger)pointerType
withStylusData:(NSDictionary *)stylusData
{
return [[RNGestureHandlerEventExtraData alloc] initWithData:@{
NSMutableDictionary *data = [@{
@"x" : @(position.x),
@"y" : @(position.y),
@"absoluteX" : @(absolutePosition.x),
Expand All @@ -74,8 +75,15 @@ + (RNGestureHandlerEventExtraData *)forPan:(CGPoint)position
@"velocityX" : SAFE_VELOCITY(velocity.x),
@"velocityY" : SAFE_VELOCITY(velocity.y),
@"numberOfPointers" : @(numberOfTouches),
@"pointerType" : @(pointerType)
}];
@"pointerType" : @(pointerType),
} mutableCopy];

// Add the stylusData to the dictionary only if necessary
if (stylusData != nil) {
data[@"stylusData"] = stylusData;
}

return [[RNGestureHandlerEventExtraData alloc] initWithData:data];
}

+ (RNGestureHandlerEventExtraData *)forForce:(CGFloat)force
Expand Down
Loading