PointerVelocity tweak core implementation
This commit is contained in:
1 parent
9b270b2e90
commit
6c5cd094c3
3 files changed
+101
-35
No files matched your search
@@ -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
|
||||||
|
|
||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user