PointerVelocity tweak core implementation

This commit is contained in:
True Zhuanjia committed 2024-05-29 00:54:42 +08:00
1 parent 9b270b2e90
commit 6c5cd094c3
3 files changed
+101 -35

No files matched your search

+14 -8
View File
@@ -10,18 +10,24 @@
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
@interface NativeTouchHandler : UIResponder @interface TouchPointer : NSObject
+ (NSMutableDictionary* )initializePointerIdDict; + (void)initContextWith:(StreamView *)view;
+ (NSMutableSet* )initializePointerIdSet; + (void)populatePointerId:(UITouch*)touch;
+ (void)populatePointerId:(UITouch*)event; + (void)removePointerId:(UITouch*)touch;
+ (void)removePointerId:(UITouch*)event; + (uint32_t) retrievePointerIdFromDict:(UITouch*)touch;
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)event;
+ (void)populatePointerObjIntoDict:(UITouch*)touch;
+ (void)removePointerObjFromDict:(UITouch*)touch;
+ (void)updatePointerObjInDict:(UITouch *)touch;
+ (CGPoint)selectCoordsFor:(UITouch *)touch;
-(id)initWithView:(StreamView*)view; - (instancetype)initWith:(UITouch *)touch;
@end @end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END
+74 -19
View File
@@ -7,9 +7,7 @@
// //
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "NativeTouchHandler.h" #import "NativeTouchHandler.h"
#include <Limelight.h> #include <Limelight.h>
@@ -18,31 +16,86 @@
// Use a NSSet store pointerId, for quick repeition inquiry, NSSet存放活跃的pointerId合集,用于快速查找,以防重复. // Use a NSSet store pointerId, for quick repeition inquiry, NSSet存放活跃的pointerId合集,用于快速查找,以防重复.
static NSMutableDictionary *pointerIdDict; //pointerId Dict for native touch. static NSMutableDictionary *pointerIdDict; //pointerId Dict for native touch.
static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch. static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
static NSMutableDictionary *pointerDict;
@implementation NativeTouchHandler { static CGFloat pointerVelocityFactor = 0.7;
StreamView* view; static CGFloat pointerVelocityDivider = 0.5;
static CGFloat pointerVelocityDividerLocation;
StreamView *streamView;
@implementation TouchPointer{
CGPoint initialPoint;
CGPoint latestPoint;
CGPoint previousPoint;
CGPoint latestRelativePoint;
CGPoint previousRelativePoint;
CGFloat velocityX;
CGFloat velocityY;
} }
- (id)initWithView:(StreamView*)view { - (instancetype)initWith:(UITouch *)touch{
self = [self init]; self = [self init];
self->view = view; self->initialPoint = [touch locationInView:streamView];
return self; self->latestPoint = self->initialPoint;
self->latestRelativePoint = self->initialPoint;
return self;
}
- (void)updatePointerCoords:(UITouch *)touch{
previousPoint = latestPoint;
latestPoint = [touch locationInView:streamView];
if (pointerVelocityFactor != 1.0f){
velocityX = latestPoint.x - previousPoint.x;
velocityY = latestPoint.y - previousPoint.y;
previousRelativePoint = latestRelativePoint;
latestRelativePoint.x = previousRelativePoint.x + pointerVelocityFactor * velocityX;
latestRelativePoint.y = previousRelativePoint.y + pointerVelocityFactor * velocityY;
}
}
+ (void)initContextWith:(StreamView *)view{
streamView = view;
pointerIdDict = [NSMutableDictionary dictionary];
pointerIdSet = [NSMutableSet set];
pointerDict = [NSMutableDictionary dictionary];
pointerVelocityDividerLocation = CGRectGetHeight([[UIScreen mainScreen] bounds]) *pointerVelocityDivider;
}
+ (void)populatePointerObjIntoDict:(UITouch*)touch{
[pointerDict setObject:[[TouchPointer alloc] initWith:touch] forKey:@((uint64_t)touch)];
}
+ (void)removePointerObjFromDict:(UITouch*)touch{
uint64_t eventAddrValue = (uint64_t)touch;
TouchPointer* pointer = [pointerDict objectForKey:@(eventAddrValue)];
if(pointer != nil){
[pointerDict removeObjectForKey:@(eventAddrValue)];
}
}
+ (void)updatePointerObjInDict:(UITouch *)touch{
[[pointerDict objectForKey:@((uint64_t)touch)] updatePointerCoords:touch];
} }
+ (NSMutableDictionary* )initializePointerIdDict { + (CGPoint)selectCoordsFor:(UITouch *)touch{
return pointerIdDict = [NSMutableDictionary dictionary]; if (pointerVelocityFactor != 1.0f){
TouchPointer *pointer = [pointerDict objectForKey:@((uint64_t)touch)];
if((pointer -> initialPoint).x > pointerVelocityDividerLocation){
return pointer->latestRelativePoint;
}
}
return [touch locationInView:streamView];
} }
+ (NSMutableSet* )initializePointerIdSet {
return pointerIdSet = [NSMutableSet set];
}
// 随机生成pointerId并填入NSDict和NSSet // 随机生成pointerId并填入NSDict和NSSet
// generate & populate pointerId into NSDict & NSSet, called in UITouchPhaseBegan // generate & populate pointerId into NSDict & NSSet, called in UITouchPhaseBegan
+ (void)populatePointerId:(UITouch*)event{ + (void)populatePointerId:(UITouch*)touch{
uint64_t eventAddrValue = (uint64_t)event; uint64_t eventAddrValue = (uint64_t)touch;
uint32_t randomPointerId = arc4random_uniform(UINT32_MAX); // generate pointerId from eletronic noise. uint32_t randomPointerId = arc4random_uniform(UINT32_MAX); // generate pointerId from eletronic noise.
while(true){ while(true){
if([pointerIdSet containsObject:@(randomPointerId)]) randomPointerId = arc4random_uniform(UINT32_MAX); // in case of new pointerId collides with existing ones, generate again. if([pointerIdSet containsObject:@(randomPointerId)]) randomPointerId = arc4random_uniform(UINT32_MAX); // in case of new pointerId collides with existing ones, generate again.
@@ -54,9 +107,11 @@ static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
} }
} }
// remove pointerId in UITouchPhaseEnded condition // remove pointerId in UITouchPhaseEnded condition
+ (void)removePointerId:(UITouch*)event{ + (void)removePointerId:(UITouch*)touch{
uint64_t eventAddrValue = (uint64_t)event; uint64_t eventAddrValue = (uint64_t)touch;
NSNumber* pointerIdObj = [pointerIdDict objectForKey:@(eventAddrValue)]; NSNumber* pointerIdObj = [pointerIdDict objectForKey:@(eventAddrValue)];
if(pointerIdObj != nil){ if(pointerIdObj != nil){
[pointerIdSet removeObject:pointerIdObj]; [pointerIdSet removeObject:pointerIdObj];
@@ -66,8 +121,8 @@ static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
// 从字典中获取UITouch事件对应的pointerId // 从字典中获取UITouch事件对应的pointerId
// call this only when NSDcit & NSSet is up-to-date. // call this only when NSDcit & NSSet is up-to-date.
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)event{ + (uint32_t) retrievePointerIdFromDict:(UITouch*)touch{
return [[pointerIdDict objectForKey:@((uint64_t)event)] unsignedIntValue]; return [[pointerIdDict objectForKey:@((uint64_t)touch)] unsignedIntValue];
} }
+13 -8
View File
@@ -57,8 +57,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
- (void) setupStreamView:(ControllerSupport*)controllerSupport - (void) setupStreamView:(ControllerSupport*)controllerSupport
interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate
config:(StreamConfiguration*)streamConfig { config:(StreamConfiguration*)streamConfig {
[NativeTouchHandler initializePointerIdDict]; [TouchPointer initContextWith:self];
[NativeTouchHandler initializePointerIdSet];
self->interactionDelegate = interactionDelegate; self->interactionDelegate = interactionDelegate;
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height; self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
@@ -333,9 +332,12 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
- (void)sendTouchEvent:(UITouch*)event touchType:(uint8_t)touchType{ - (void)sendTouchEvent:(UITouch*)event touchType:(uint8_t)touchType{
CGPoint location = [self adjustCoordinatesForVideoArea:[event locationInView:self]]; CGPoint targetCoords;
if(true) targetCoords = [TouchPointer selectCoordsFor:event];
else targetCoords = [event locationInView:self];
CGPoint location = [self adjustCoordinatesForVideoArea:targetCoords];
CGSize videoSize = [self getVideoAreaSize]; CGSize videoSize = [self getVideoAreaSize];
LiSendTouchEvent(touchType,[NativeTouchHandler retrievePointerIdFromDict:event],location.x / videoSize.width, location.y / videoSize.height,(event.force / event.maximumPossibleForce) / sin(event.altitudeAngle),0.0f, 0.0f,[self getRotationFromAzimuthAngle:[event azimuthAngleInView:self]]); LiSendTouchEvent(touchType,[TouchPointer retrievePointerIdFromDict:event],location.x / videoSize.width, location.y / videoSize.height,(event.force / event.maximumPossibleForce) / sin(event.altitudeAngle),0.0f, 0.0f,[self getRotationFromAzimuthAngle:[event azimuthAngleInView:self]]);
} }
@@ -365,11 +367,13 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
switch (event.phase) { switch (event.phase) {
case UITouchPhaseBegan://开始触摸 case UITouchPhaseBegan://开始触摸
type = LI_TOUCH_EVENT_DOWN; type = LI_TOUCH_EVENT_DOWN;
[NativeTouchHandler populatePointerId:event]; //获取并记录pointerId [TouchPointer populatePointerId:event]; //获取并记录pointerId
if(true) [TouchPointer populatePointerObjIntoDict:event];
break; break;
case UITouchPhaseMoved://移动 case UITouchPhaseMoved://移动
case UITouchPhaseStationary: case UITouchPhaseStationary:
type = LI_TOUCH_EVENT_MOVE; type = LI_TOUCH_EVENT_MOVE;
if(true) [TouchPointer updatePointerObjInDict:event];
break; break;
case UITouchPhaseRegionEntered://停留 case UITouchPhaseRegionEntered://停留
case UITouchPhaseRegionMoved://停留 case UITouchPhaseRegionMoved://停留
@@ -378,17 +382,18 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
case UITouchPhaseCancelled://触摸取消 case UITouchPhaseCancelled://触摸取消
type = LI_TOUCH_EVENT_CANCEL; type = LI_TOUCH_EVENT_CANCEL;
[self sendTouchEvent:event touchType:type]; //先发送,再删除 [self sendTouchEvent:event touchType:type]; //先发送,再删除
[NativeTouchHandler removePointerId:event]; //删除pointerId [TouchPointer removePointerId:event]; //删除pointerId
if(true) [TouchPointer removePointerObjFromDict:event];
return; return;
case UITouchPhaseEnded://触摸结束 case UITouchPhaseEnded://触摸结束
type = LI_TOUCH_EVENT_UP; type = LI_TOUCH_EVENT_UP;
[self sendTouchEvent:event touchType:type]; //先发送,再删除 [self sendTouchEvent:event touchType:type]; //先发送,再删除
[NativeTouchHandler removePointerId:event]; //删除pointerId [TouchPointer removePointerId:event]; //删除pointerId
if(true) [TouchPointer removePointerObjFromDict:event];
return; return;
default: default:
return; return;
} }
[self sendTouchEvent:event touchType:type]; [self sendTouchEvent:event touchType:type];
} }