PointerVelocity tweak core implementation
This commit is contained in:
@@ -10,18 +10,24 @@
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NativeTouchHandler : UIResponder
|
||||
@interface TouchPointer : NSObject
|
||||
|
||||
+ (NSMutableDictionary* )initializePointerIdDict;
|
||||
+ (NSMutableSet* )initializePointerIdSet;
|
||||
+ (void)populatePointerId:(UITouch*)event;
|
||||
+ (void)removePointerId:(UITouch*)event;
|
||||
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)event;
|
||||
+ (void)initContextWith:(StreamView *)view;
|
||||
+ (void)populatePointerId:(UITouch*)touch;
|
||||
+ (void)removePointerId:(UITouch*)touch;
|
||||
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)touch;
|
||||
|
||||
+ (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
|
||||
|
||||
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "NativeTouchHandler.h"
|
||||
|
||||
#include <Limelight.h>
|
||||
|
||||
|
||||
@@ -18,31 +16,86 @@
|
||||
// Use a NSSet store pointerId, for quick repeition inquiry, NSSet存放活跃的pointerId合集,用于快速查找,以防重复.
|
||||
static NSMutableDictionary *pointerIdDict; //pointerId Dict for native touch.
|
||||
static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
|
||||
static NSMutableDictionary *pointerDict;
|
||||
|
||||
@implementation NativeTouchHandler {
|
||||
StreamView* view;
|
||||
static CGFloat pointerVelocityFactor = 0.7;
|
||||
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 {
|
||||
self = [self init];
|
||||
self->view = view;
|
||||
return self;
|
||||
- (instancetype)initWith:(UITouch *)touch{
|
||||
self = [self init];
|
||||
self->initialPoint = [touch locationInView:streamView];
|
||||
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 {
|
||||
return pointerIdDict = [NSMutableDictionary dictionary];
|
||||
+ (CGPoint)selectCoordsFor:(UITouch *)touch{
|
||||
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
|
||||
// generate & populate pointerId into NSDict & NSSet, called in UITouchPhaseBegan
|
||||
+ (void)populatePointerId:(UITouch*)event{
|
||||
uint64_t eventAddrValue = (uint64_t)event;
|
||||
+ (void)populatePointerId:(UITouch*)touch{
|
||||
uint64_t eventAddrValue = (uint64_t)touch;
|
||||
uint32_t randomPointerId = arc4random_uniform(UINT32_MAX); // generate pointerId from eletronic noise.
|
||||
while(true){
|
||||
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
|
||||
+ (void)removePointerId:(UITouch*)event{
|
||||
uint64_t eventAddrValue = (uint64_t)event;
|
||||
+ (void)removePointerId:(UITouch*)touch{
|
||||
uint64_t eventAddrValue = (uint64_t)touch;
|
||||
NSNumber* pointerIdObj = [pointerIdDict objectForKey:@(eventAddrValue)];
|
||||
if(pointerIdObj != nil){
|
||||
[pointerIdSet removeObject:pointerIdObj];
|
||||
@@ -66,8 +121,8 @@ static NSMutableSet<NSNumber *> *pointerIdSet; //pointerIdSet for native touch.
|
||||
|
||||
// 从字典中获取UITouch事件对应的pointerId
|
||||
// call this only when NSDcit & NSSet is up-to-date.
|
||||
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)event{
|
||||
return [[pointerIdDict objectForKey:@((uint64_t)event)] unsignedIntValue];
|
||||
+ (uint32_t) retrievePointerIdFromDict:(UITouch*)touch{
|
||||
return [[pointerIdDict objectForKey:@((uint64_t)touch)] unsignedIntValue];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -57,8 +57,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
- (void) setupStreamView:(ControllerSupport*)controllerSupport
|
||||
interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate
|
||||
config:(StreamConfiguration*)streamConfig {
|
||||
[NativeTouchHandler initializePointerIdDict];
|
||||
[NativeTouchHandler initializePointerIdSet];
|
||||
[TouchPointer initContextWith:self];
|
||||
|
||||
self->interactionDelegate = interactionDelegate;
|
||||
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{
|
||||
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];
|
||||
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) {
|
||||
case UITouchPhaseBegan://开始触摸
|
||||
type = LI_TOUCH_EVENT_DOWN;
|
||||
[NativeTouchHandler populatePointerId:event]; //获取并记录pointerId
|
||||
[TouchPointer populatePointerId:event]; //获取并记录pointerId
|
||||
if(true) [TouchPointer populatePointerObjIntoDict:event];
|
||||
break;
|
||||
case UITouchPhaseMoved://移动
|
||||
case UITouchPhaseStationary:
|
||||
type = LI_TOUCH_EVENT_MOVE;
|
||||
if(true) [TouchPointer updatePointerObjInDict:event];
|
||||
break;
|
||||
case UITouchPhaseRegionEntered://停留
|
||||
case UITouchPhaseRegionMoved://停留
|
||||
@@ -378,17 +382,18 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
case UITouchPhaseCancelled://触摸取消
|
||||
type = LI_TOUCH_EVENT_CANCEL;
|
||||
[self sendTouchEvent:event touchType:type]; //先发送,再删除
|
||||
[NativeTouchHandler removePointerId:event]; //删除pointerId
|
||||
[TouchPointer removePointerId:event]; //删除pointerId
|
||||
if(true) [TouchPointer removePointerObjFromDict:event];
|
||||
return;
|
||||
case UITouchPhaseEnded://触摸结束
|
||||
type = LI_TOUCH_EVENT_UP;
|
||||
[self sendTouchEvent:event touchType:type]; //先发送,再删除
|
||||
[NativeTouchHandler removePointerId:event]; //删除pointerId
|
||||
[TouchPointer removePointerId:event]; //删除pointerId
|
||||
if(true) [TouchPointer removePointerObjFromDict:event];
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
[self sendTouchEvent:event touchType:type];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user