- motion control demo1
- feat: movable on-screen functional buttons
This commit is contained in:
+75
-28
@@ -35,16 +35,14 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
*/
|
||||
@implementation StreamView {
|
||||
UIView* streamFrameTopLayerView;
|
||||
UIViewController* streamFrameVC;
|
||||
|
||||
TemporarySettings* settings;
|
||||
|
||||
OnScreenControls* onScreenControls;
|
||||
|
||||
|
||||
KeyboardInputField* keyInputField;
|
||||
BOOL isInputingText;
|
||||
NSMutableSet* keysDown;
|
||||
float streamAspectRatio;
|
||||
|
||||
|
||||
|
||||
// iOS 13.4 mouse support
|
||||
NSInteger lastMouseButtonMask;
|
||||
@@ -78,6 +76,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
UIKeyModifierFlags comboKeyModifierFlags;
|
||||
|
||||
WidgetSizeTransition _widgetSizeTransition;
|
||||
OSCProfilesManager* profilesManager;
|
||||
}
|
||||
|
||||
- (void) setupStreamView:(ControllerSupport*)controllerSupport
|
||||
@@ -156,7 +155,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
}
|
||||
|
||||
// we'll render on-screen controls on the toplayer too:
|
||||
onScreenControls = [[OnScreenControls alloc] initWithView:self->streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig]; // don't delete, this is mandatory
|
||||
_onScreenControls = [[OnScreenControls alloc] initWithView:self->streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig]; // don't delete, this is mandatory
|
||||
/*
|
||||
// here we pass the tap recognizer to the onscreencontrols obj
|
||||
if (settings.touchMode.intValue == RelativeTouch){
|
||||
@@ -167,7 +166,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
OnScreenControlsLevel level = (OnScreenControlsLevel)[settings.onscreenControls integerValue];
|
||||
if (settings.touchMode.intValue != RelativeTouch && settings.touchMode.intValue != NativeTouch ) {
|
||||
Log(LOG_I, @"On-screen controls disabled in non-relative touch mode");
|
||||
[onScreenControls setLevel:OnScreenControlsLevelOff];
|
||||
[_onScreenControls setLevel:OnScreenControlsLevelOff];
|
||||
|
||||
//pass touchesCaptureByOnScreenButtons Set to the native touchhandler, this NSSet is init witihin onscreencontrols class, don't do it again in native touch handler class
|
||||
[OnScreenControls.touchAddrsCapturedByOnScreenControls removeAllObjects]; // reset the attribute to nil
|
||||
@@ -182,11 +181,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
}
|
||||
//else if (level == OnScreenControlsLevelAuto) {
|
||||
else if (false) { // level auto cancelled in settings
|
||||
[controllerSupport initAutoOnScreenControlMode:onScreenControls];
|
||||
[controllerSupport initAutoOnScreenControlMode:_onScreenControls];
|
||||
}
|
||||
else {
|
||||
Log(LOG_I, @"Setting manual on-screen controls level: %d", (int)level);
|
||||
[onScreenControls setLevel:level];
|
||||
[_onScreenControls setLevel:level];
|
||||
}
|
||||
// It would be nice to just use GCMouse on iOS 14+ and the older API on iOS 13
|
||||
// but unfortunately that isn't possible today. GCMouse doesn't recognize many
|
||||
@@ -263,6 +262,17 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
NSLog(@"keyboard will show %f", CACurrentMediaTime());
|
||||
}
|
||||
|
||||
- (UIViewController *)parentViewController {
|
||||
UIResponder *responder = self;
|
||||
while (responder) {
|
||||
if ([responder isKindOfClass:[UIViewController class]]) {
|
||||
return (UIViewController *)responder;
|
||||
}
|
||||
responder = responder.nextResponder;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// this method also deals with recovering streamview when local keyboard is turned off
|
||||
- (void)keyboardWillHide{
|
||||
// NSLog(@"keyboard will hide markmark %f", CACurrentMediaTime());
|
||||
@@ -401,7 +411,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
|
||||
- (void) showOnScreenControls {
|
||||
#if !TARGET_OS_TV
|
||||
if(!_widgetToolOpened) [onScreenControls show];
|
||||
if(!_widgetToolOpened) [_onScreenControls show];
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -411,7 +421,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
|
||||
- (void) disableOnScreenControls {
|
||||
#if !TARGET_OS_TV
|
||||
[onScreenControls setLevel:OnScreenControlsLevelOff];
|
||||
[_onScreenControls setLevel:OnScreenControlsLevelOff];
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -438,7 +448,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
andConfig:(StreamConfiguration*)streamConfig {
|
||||
|
||||
// we'll render on-screen controllers on the toplayer too.
|
||||
onScreenControls = [[OnScreenControls alloc] initWithView:self->streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig];
|
||||
_onScreenControls = [[OnScreenControls alloc] initWithView:self->streamFrameTopLayerView controllerSup:controllerSupport streamConfig:streamConfig];
|
||||
/*
|
||||
// pass mouseRightClickTapRecognizer to onScreenControls obj here:
|
||||
if([self isOscEnabled]){
|
||||
@@ -446,7 +456,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
RelativeTouchHandler* relativeTouchHandler = (RelativeTouchHandler *)touchHandler;
|
||||
onScreenControls.mouseRightClickTapRecognizer = relativeTouchHandler.mouseRightClickTapRecognizer;
|
||||
} */
|
||||
if([self isOscEnabled]) [onScreenControls setLevel:(OnScreenControlsLevel)settings.onscreenControls.intValue];
|
||||
if([self isOscEnabled]) [_onScreenControls setLevel:(OnScreenControlsLevel)settings.onscreenControls.intValue];
|
||||
}
|
||||
|
||||
|
||||
@@ -477,6 +487,35 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
else return longSide;
|
||||
}
|
||||
|
||||
- (void)saveRelocatedWidgetViews{
|
||||
NSMutableDictionary* relocatedWidgetDict = [NSMutableDictionary dictionary];
|
||||
|
||||
for(UIView* subview in self->streamFrameTopLayerView.subviews){
|
||||
if([subview isKindOfClass:[OnScreenWidgetView class]]){
|
||||
OnScreenWidgetView* widget = (OnScreenWidgetView* )subview;
|
||||
if(widget.relocatedDuringStreaming) [relocatedWidgetDict setObject:widget forKey:widget.identifier];
|
||||
}
|
||||
}
|
||||
|
||||
if(relocatedWidgetDict.allKeys.count == 0) return;
|
||||
|
||||
profilesManager = [OSCProfilesManager sharedManager:self->streamFrameTopLayerView.bounds];
|
||||
OSCProfile *newProfile = [profilesManager getSelectedProfile];
|
||||
|
||||
for (NSInteger i = 0; i < newProfile.buttonStatesEncoded.count; i++) {
|
||||
NSData* buttonStateEncoded = newProfile.buttonStatesEncoded[i];
|
||||
OnScreenButtonState *newButtonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||
if([relocatedWidgetDict.allKeys containsObject:newButtonState.identifier]){
|
||||
OnScreenWidgetView* widget = [relocatedWidgetDict objectForKey:newButtonState.identifier];
|
||||
newButtonState.position = [profilesManager normalizeWidgetPosition:widget.center];
|
||||
NSData *newButtonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:newButtonState requiringSecureCoding:YES error:nil];
|
||||
newProfile.buttonStatesEncoded[i] = newButtonStateEncoded;
|
||||
}
|
||||
}
|
||||
|
||||
[profilesManager replaceSelectedProfileWith:newProfile];
|
||||
}
|
||||
|
||||
- (void) reloadOnScreenWidgetViews{
|
||||
|
||||
// NSLog(@"reload on screen keyboard buttons here");
|
||||
@@ -484,25 +523,33 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
// remove all keyboard widget views first
|
||||
[self clearOnScreenWidgets];
|
||||
|
||||
// get streamFrameVC
|
||||
if(!streamFrameVC) streamFrameVC = [self parentViewController];
|
||||
|
||||
// bool customOscEnabled = [self isOscEnabled] && settings.onscreenControls.intValue == OnScreenControlsLevelCustom;
|
||||
|
||||
if(![self isOnScreenWidgetEnabled]) return;
|
||||
|
||||
OnScreenWidgetView.buttonVisualFeedbackEnabled = settings.buttonVisualFeedback;
|
||||
|
||||
OSCProfilesManager* profilesManager = [OSCProfilesManager sharedManager: self.bounds];
|
||||
if(!profilesManager) profilesManager = [OSCProfilesManager sharedManager:self->streamFrameTopLayerView.bounds];
|
||||
OSCProfile *oscProfile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile
|
||||
|
||||
if(!OnScreenWidgetView.editMode){ // in edit mode, keyboard widget view will be updated within layoutool view controller.
|
||||
|
||||
for (NSData *buttonStateEncoded in oscProfile.buttonStates) {
|
||||
|
||||
for (NSData *buttonStateEncoded in oscProfile.buttonStatesEncoded) {
|
||||
OnScreenButtonState* buttonState = [profilesManager unarchiveButtonStateEncoded:buttonStateEncoded];
|
||||
if(buttonState.buttonType == CustomOnScreenWidget){
|
||||
if(buttonState.widgetType == CustomOnScreenWidget){
|
||||
OnScreenWidgetView* widgetView = [[OnScreenWidgetView alloc] initWithCmdString:buttonState.name buttonLabel:buttonState.alias shape:buttonState.widgetShape]; //reconstruct widgetView
|
||||
//--------------------------------------------------
|
||||
onScreenControls.delegate = widgetView; // connecting onScreenControls to OnScreenWidgetView, sending the active instance for touchPad stick control
|
||||
[onScreenControls sendInstance];
|
||||
_onScreenControls.instanceReceiverDelegate = widgetView; // connecting onScreenControls to OnScreenWidgetView, sending the active instance for touchPad stick control
|
||||
[_onScreenControls sendInstance];
|
||||
//--------------------------------------------------
|
||||
|
||||
widgetView.functionalButtonDelegate = (id<OnScreenFunctionalButtonDelegate>)streamFrameVC;
|
||||
widgetView.mixInputDelegate = (id<OnScreenWidgetStickMixedInputDelegate>) [MotionHandler sharedInstance];
|
||||
|
||||
widgetView.identifier = buttonState.identifier;
|
||||
widgetView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
|
||||
widgetView.widthFactor = buttonState.widthFactor;
|
||||
widgetView.heightFactor = buttonState.heightFactor;
|
||||
@@ -515,7 +562,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
widgetView.trackballDecelerationRate = buttonState.decelerationRate;
|
||||
widgetView.stickIndicatorOffset = buttonState.stickIndicatorOffset;
|
||||
widgetView.minStickOffset = buttonState.minStickOffset;
|
||||
widgetView.buttonTriggerMode = buttonState.buttonTriggerMode;
|
||||
widgetView.buttonMode = buttonState.buttonMode;
|
||||
// Add the widgetView to the view controller's view
|
||||
[self->streamFrameTopLayerView addSubview:widgetView]; // add keyboard button to the stream frame view. must add it to the target view before setting location.
|
||||
buttonState.position = [self denormalizeWidgetPosition:buttonState.position];
|
||||
@@ -533,11 +580,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
}
|
||||
|
||||
- (OnScreenControlsLevel) getCurrentOscState {
|
||||
if (onScreenControls == nil) {
|
||||
if (_onScreenControls == nil) {
|
||||
return OnScreenControlsLevelOff;
|
||||
}
|
||||
else {
|
||||
return [onScreenControls getLevel];
|
||||
return [_onScreenControls getLevel];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,10 +761,10 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
[self startInteractionTimer];
|
||||
|
||||
if(settings.touchMode.intValue == NativeTouch || settings.touchMode.intValue == RelativeTouch){
|
||||
[self->onScreenControls handleTouchDownEvent:touches];
|
||||
[self->_onScreenControls handleTouchDownEvent:touches];
|
||||
[self->touchHandler touchesBegan:touches withEvent:event];
|
||||
}
|
||||
else if(![onScreenControls handleTouchDownEvent:touches]) [touchHandler touchesBegan:touches withEvent:event];
|
||||
else if(![_onScreenControls handleTouchDownEvent:touches]) [touchHandler touchesBegan:touches withEvent:event];
|
||||
}
|
||||
|
||||
- (UIBarButtonItem *)createButtonWithImageNamed:(NSString *)imageName backgroundColor:(UIColor *)backgroundColor target:(id)target action:(SEL)action keyCode:(NSInteger)keyCode isToggleable:(BOOL)isToggleable {
|
||||
@@ -880,9 +927,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
|
||||
if(self->settings.touchMode.intValue == NativeTouch || self->settings.touchMode.intValue == RelativeTouch){
|
||||
[self->touchHandler touchesMoved:touches withEvent:event];
|
||||
[self->onScreenControls handleTouchMovedEvent:touches];
|
||||
[self->_onScreenControls handleTouchMovedEvent:touches];
|
||||
}
|
||||
else if(![self->onScreenControls handleTouchMovedEvent:touches]) [self->touchHandler touchesMoved:touches withEvent:event];
|
||||
else if(![self->_onScreenControls handleTouchMovedEvent:touches]) [self->touchHandler touchesMoved:touches withEvent:event];
|
||||
}
|
||||
|
||||
- (void) handleKeyCombos:(UIPress*) press{
|
||||
@@ -976,9 +1023,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
|
||||
if(settings.touchMode.intValue == NativeTouch || settings.touchMode.intValue == RelativeTouch){
|
||||
[self->touchHandler touchesEnded:touches withEvent:event]; // when touches ended, must call the native touchhandler before onScreenControls, since the NSSet of touches captured by on screen button shall be updated later
|
||||
[self->onScreenControls handleTouchUpEvent:touches];
|
||||
[self->_onScreenControls handleTouchUpEvent:touches];
|
||||
}
|
||||
else if(![onScreenControls handleTouchUpEvent:touches]) [touchHandler touchesEnded:touches withEvent:event];
|
||||
else if(![_onScreenControls handleTouchUpEvent:touches]) [touchHandler touchesEnded:touches withEvent:event];
|
||||
}
|
||||
|
||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
|
||||
Reference in New Issue
Block a user