diff --git a/Limelight/Base.lproj/iPad.storyboard b/Limelight/Base.lproj/iPad.storyboard
index 1316a9c3..3a0c1f79 100644
--- a/Limelight/Base.lproj/iPad.storyboard
+++ b/Limelight/Base.lproj/iPad.storyboard
@@ -669,7 +669,7 @@ ICAgICAgICAgICAgICA
-
+
-
@@ -797,6 +813,8 @@ ICAgICAgICAgICAgICA
+
+
diff --git a/Limelight/Input/CustomOSC/LayoutOnScreenControls.m b/Limelight/Input/CustomOSC/LayoutOnScreenControls.m
index 4e2605d6..8557c797 100644
--- a/Limelight/Input/CustomOSC/LayoutOnScreenControls.m
+++ b/Limelight/Input/CustomOSC/LayoutOnScreenControls.m
@@ -162,7 +162,10 @@
}
/* save the name, position, and visibility of button being touched in array in case user wants to undo the change later */
- OnScreenButtonState *onScreenButtonState = [[OnScreenButtonState alloc] initWithButtonName:layerBeingDragged.name isKeyboardButton:NO isHidden:layerBeingDragged.isHidden andPosition:layerBeingDragged.position];
+ OnScreenButtonState *onScreenButtonState = [[OnScreenButtonState alloc] initWithButtonName:layerBeingDragged.name buttonType:GameControllerButton andPosition:layerBeingDragged.position];
+ // add hidden attr here
+ onScreenButtonState.isHidden = layerBeingDragged.isHidden;
+
[layoutChanges addObject:onScreenButtonState];
[[NSNotificationCenter defaultCenter] postNotificationName:@"OSCLayoutChanged" object:self]; // lets the view controller know whether to fade the undo button in or out depending on whether there are any further OSC layout changes the user is allowed to undo
diff --git a/Limelight/Input/CustomOSC/OSCProfilesManager.h b/Limelight/Input/CustomOSC/OSCProfilesManager.h
index 0892c866..82d76992 100644
--- a/Limelight/Input/CustomOSC/OSCProfilesManager.h
+++ b/Limelight/Input/CustomOSC/OSCProfilesManager.h
@@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (OSCProfilesManager *) sharedManager;
++ (void) setOnScreenKeyViewsDict:(NSMutableDictionary* )dict;
#pragma mark - Getters
/**
@@ -50,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void) saveProfileWithName:(NSString*)name andButtonLayers:(NSMutableArray *)buttonLayers;
-- (bool) updateSelectedProfileSucceedWithButtonLayers:(NSMutableArray *)buttonLayers;
+- (bool) updateSelectedProfile:(NSMutableArray *) oscButtonLayers;
/**
* Delete current selected profile.
*/
diff --git a/Limelight/Input/CustomOSC/OSCProfilesManager.m b/Limelight/Input/CustomOSC/OSCProfilesManager.m
index 985fddb6..3015f14e 100644
--- a/Limelight/Input/CustomOSC/OSCProfilesManager.m
+++ b/Limelight/Input/CustomOSC/OSCProfilesManager.m
@@ -7,10 +7,13 @@
//
#import "OSCProfilesManager.h"
+#import "OnScreenButtonState.h"
+#import "Moonlight-Swift.h"
+#import "LayoutOnScreenControlsViewController.h"
@implementation OSCProfilesManager
-
+static NSMutableDictionary *onScreenKeyViewsDict;
#pragma mark - Initializer
@@ -27,6 +30,11 @@
#pragma mark - Class Helper Methods
+
++ (void) setOnScreenKeyViewsDict:(NSMutableDictionary* )dict{
+ onScreenKeyViewsDict = dict;
+}
+
/**
* Returns the profile whose 'name' property has a value that is equal to the 'name' passed into the method
*/
@@ -94,7 +102,6 @@
NSMutableArray *profiles = [self getAllProfiles];
for (OSCProfile *profile in profiles) { // set all profiles' 'isSelected' property to NO since the new profile we're saving over the old profile with will be the 'selected' profile
-
profile.isSelected = NO;
}
@@ -192,7 +199,7 @@
}
-- (bool) updateSelectedProfileSucceedWithButtonLayers:(NSMutableArray *)buttonLayers {
+- (bool) updateSelectedProfile:(NSMutableArray *) oscButtonLayers {
/* iterate through each OSC button the user sees on screen, create an 'OnScreenButtonState' object from each button, encode each object, and then add each object to an array */
/*
NSSet *validPositionButtonNames = [NSSet setWithObjects:
@@ -211,9 +218,12 @@
@"startButton",
nil]; */
NSMutableArray *buttonStatesEncoded = [[NSMutableArray alloc] init];
- for (CALayer *buttonLayer in buttonLayers) {
+ for (CALayer *oscButtonLayer in oscButtonLayers) {
+
+ OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:oscButtonLayer.name buttonType:GameControllerButton andPosition:oscButtonLayer.position];
+ // add hidden attr here
+ buttonState.isHidden = oscButtonLayer.isHidden;
- OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:buttonLayer.name isKeyboardButton:NO isHidden:buttonLayer.isHidden andPosition:buttonLayer.position];
/* //-------------------------------------
NSLog(@"buttonName to be saved: %@", buttonState.name);
if([validPositionButtonNames containsObject:buttonState.name]) buttonState.hasValidPosition = true; // this is for setting up DZ for custom OSC buttons.
@@ -222,6 +232,19 @@
NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
[buttonStatesEncoded addObject: buttonStateEncoded];
}
+
+ // save keyboard button as buttonstate
+ [onScreenKeyViewsDict enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { // this dict is passed from the layout tool VC, as a static obj in this class.
+ OnScreenKeyView *keyView = value;
+ OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:keyView.keyString buttonType:KeyboardButton andPosition:keyView.frame.origin];
+ buttonState.alias = keyView.keyLabel;
+ buttonState.timestamp = keyView.timestamp;
+ NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
+ [buttonStatesEncoded addObject: buttonStateEncoded];
+ }];
+
+
+
if([self getIndexOfSelectedProfile]==0) return false;
OSCProfile *newProfile = [[OSCProfile alloc] initWithName:[self getSelectedProfile].name
buttonStates:buttonStatesEncoded isSelected:YES]; // create a new 'OSCProfile'. Set the array of encoded button states created above to the 'buttonStates' property of the new profile, along with a 'name'. Set 'isSelected' argument to YES which will set this saved profile as the one that will show up in the game stream view
@@ -258,7 +281,9 @@
nil]; */
NSMutableArray *buttonStatesEncoded = [[NSMutableArray alloc] init];
for (CALayer *buttonLayer in buttonLayers) {
- OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:buttonLayer.name isKeyboardButton:NO isHidden:buttonLayer.isHidden andPosition:buttonLayer.position];
+ OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:buttonLayer.name buttonType:GameControllerButton andPosition:buttonLayer.position];
+ // add hidden attr here
+ buttonState.isHidden = buttonLayer.isHidden;
/* //-------------------------------------
NSLog(@"buttonName to be saved: %@", buttonState.name);
if([validPositionButtonNames containsObject:buttonState.name]) buttonState.hasValidPosition = true; // this is for setting up DZ for custom OSC buttons.
diff --git a/Limelight/Input/CustomOSC/OnScreenButtonState.h b/Limelight/Input/CustomOSC/OnScreenButtonState.h
index 30884210..e675429e 100644
--- a/Limelight/Input/CustomOSC/OnScreenButtonState.h
+++ b/Limelight/Input/CustomOSC/OnScreenButtonState.h
@@ -20,12 +20,19 @@ NS_ASSUME_NONNULL_BEGIN
@interface OnScreenButtonState : NSObject
@property NSString *name;
+@property NSString *alias;
@property CGPoint position;
@property (nonatomic, assign) BOOL isHidden;
-@property (nonatomic, assign) BOOL isKeyboardButton;
+@property (nonatomic, assign) uint8_t buttonType;
+@property (nonatomic, assign) NSTimeInterval timestamp;
// @property (nonatomic, assign) BOOL hasValidPosition;
-- (id) initWithButtonName:(NSString*)name isKeyboardButton:(BOOL)isKeyboardButton isHidden:(BOOL)isHidden andPosition:(CGPoint)position;
+typedef NS_ENUM(NSInteger, OnScreenButtonType) {
+ GameControllerButton,
+ KeyboardButton
+};
+
+- (id) initWithButtonName:(NSString*)name buttonType:(uint8_t)buttonType andPosition:(CGPoint)position;
+ (BOOL) supportsSecureCoding;
- (void) encodeWithCoder:(NSCoder*)encoder;
diff --git a/Limelight/Input/CustomOSC/OnScreenButtonState.m b/Limelight/Input/CustomOSC/OnScreenButtonState.m
index 4e1feed7..b125b56b 100644
--- a/Limelight/Input/CustomOSC/OnScreenButtonState.m
+++ b/Limelight/Input/CustomOSC/OnScreenButtonState.m
@@ -10,12 +10,13 @@
@implementation OnScreenButtonState
-- (id) initWithButtonName:(NSString*)name isKeyboardButton:(BOOL)isKeyboardButton isHidden:(BOOL)isHidden andPosition:(CGPoint)position {
+
+- (id) initWithButtonName:(NSString*)name buttonType:(uint8_t)buttonType andPosition:(CGPoint)position {
if ((self = [self init])) {
self.name = name;
- self.isHidden = isHidden;
+ //self.isHidden = isHidden;
self.position = position;
- self.isKeyboardButton = isKeyboardButton;
+ self.buttonType = buttonType;
}
return self;
@@ -27,19 +28,21 @@
- (void) encodeWithCoder:(NSCoder*)encoder {
[encoder encodeObject:self.name forKey:@"name"];
- [encoder encodeBool:self.isKeyboardButton forKey:@"isKeyboardButton"];
- [encoder encodeBool:self.isHidden forKey:@"isHidden"];
- // [encoder encodeBool:self.hasValidPosition forKey:@"hasValidPosition"];
+ [encoder encodeObject:self.alias forKey:@"alias"];
+ [encoder encodeDouble:self.timestamp forKey:@"timestamp"];
+ [encoder encodeInt:self.buttonType forKey:@"buttonType"];
[encoder encodeCGPoint:self.position forKey:@"position"];
+ [encoder encodeBool:self.isHidden forKey:@"isHidden"];
}
- (id) initWithCoder:(NSCoder*)decoder {
if (self = [super init]) {
self.name = [decoder decodeObjectForKey:@"name"];
- self.isKeyboardButton = [decoder decodeBoolForKey:@"isKeyboardButton"];
- self.isHidden = [decoder decodeBoolForKey:@"isHidden"];
- // self.hasValidPosition = [decoder decodeBoolForKey:@"hasValidPosition"];
+ self.alias = [decoder decodeObjectForKey:@"alias"];
+ self.timestamp = [decoder decodeDoubleForKey:@"timestamp"];
+ self.buttonType = [decoder decodeIntForKey:@"buttonType"];
self.position = [decoder decodeCGPointForKey:@"position"];
+ self.isHidden = [decoder decodeBoolForKey:@"isHidden"];
}
return self;
diff --git a/Limelight/Input/OnScreenControls.m b/Limelight/Input/OnScreenControls.m
index 74beeaeb..5305da39 100644
--- a/Limelight/Input/OnScreenControls.m
+++ b/Limelight/Input/OnScreenControls.m
@@ -272,7 +272,8 @@ static float L3_Y;
NSLog(@"_activeCustomOscButtonPositionDict update: STARTOVER");
for (NSData *buttonStateEncoded in oscProfile.buttonStates) {
OnScreenButtonState *buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil];
- if(!buttonState.isHidden && [validPositionButtonNames containsObject:buttonState.name] ){
+
+ if(!buttonState.isHidden && [validPositionButtonNames containsObject:buttonState.name] && (buttonState.buttonType == GameControllerButton || [profilesManager getIndexOfSelectedProfile] == 0 ) ){
[_activeCustomOscButtonPositionDict setObject:[NSValue valueWithCGPoint:buttonState.position] forKey:buttonState.name]; // we got a buttonname -> position dict here
NSLog(@"_activeCustomOscButtonPositionDict update, button name:%@, position: %f, %f", buttonState.name, buttonState.position.x, buttonState.position.y);
}
diff --git a/Limelight/Input/OnScreenKeyView.swift b/Limelight/Input/OnScreenKeyView.swift
index 3a4a9fdb..29bb7b6c 100644
--- a/Limelight/Input/OnScreenKeyView.swift
+++ b/Limelight/Input/OnScreenKeyView.swift
@@ -8,10 +8,13 @@
import UIKit
+
@objc class OnScreenKeyView: UIView {
- @objc static var relocationMode: Bool = false
- @objc var keyLabel: String
- @objc var keyString: String
+ @objc static public var editMode: Bool = false
+ @objc static public var timestampOfButtonBeingDragged: TimeInterval = 0
+ @objc public var keyLabel: String
+ @objc public var keyString: String
+ @objc public var timestamp: TimeInterval
private let label: UILabel
private let originalBackgroundColor: UIColor
private var storedLocation: CGPoint = .zero
@@ -22,7 +25,7 @@ import UIKit
self.keyLabel = keyLabel
self.label = UILabel()
self.originalBackgroundColor = UIColor(white: 0.2, alpha: 0.7)
-
+ self.timestamp = 0;
super.init(frame: .zero)
setupView()
}
@@ -39,16 +42,17 @@ import UIKit
}
@objc public func enableRelocationMode(enabled: Bool){
- OnScreenKeyView.relocationMode = enabled
+ OnScreenKeyView.editMode = enabled
}
private func setupView() {
label.text = self.keyLabel
- label.font = UIFont.systemFont(ofSize: 30)
+ label.font = UIFont.systemFont(ofSize: 22)
label.textColor = UIColor(white: 1.0, alpha: 0.8)
label.shadowColor = .black
label.translatesAutoresizingMaskIntoConstraints = false
+ self.translatesAutoresizingMaskIntoConstraints = true // this is mandatory to prevent unexpected key view location change
self.layer.borderColor = UIColor.black.cgColor
self.layer.borderWidth = 2
self.layer.cornerRadius = 8
@@ -64,21 +68,24 @@ import UIKit
])
NSLayoutConstraint.activate([
- self.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.088),
- self.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height * 0.1),
- ])
+ //self.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width * 0.088),
+ //self.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height * 0.1),
+ self.widthAnchor.constraint(equalToConstant: 85),
+ self.heightAnchor.constraint(equalToConstant: 65),
+ ])
}
// Touch event handling
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
//self.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 0.7)
- self.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.7)
- if !OnScreenKeyView.relocationMode { LiSendKeyboardEvent(CommandManager.keyMappings[self.keyString]!,Int8(KEY_ACTION_DOWN), 0) }
+ if !OnScreenKeyView.editMode {
+ self.backgroundColor = UIColor.systemBlue.withAlphaComponent(0.7)
+ LiSendKeyboardEvent(CommandManager.keyMappings[self.keyString]!,Int8(KEY_ACTION_DOWN), 0)
+ }
else {
- // Store the initial center point of the key
if let touch = touches.first {
let touchLocation = touch.location(in: superview)
storedLocation = touchLocation
@@ -89,15 +96,17 @@ import UIKit
override func touchesMoved(_ touches: Set, with event: UIEvent?) {
super.touchesMoved(touches, with: event)
+ OnScreenKeyView.timestampOfButtonBeingDragged = self.timestamp
// Move the KeyView based on touch movement in relocation mode
- if OnScreenKeyView.relocationMode {
+ if OnScreenKeyView.editMode {
if let touch = touches.first {
let currentLocation = touch.location(in: superview)
let offsetX = currentLocation.x - storedLocation.x
let offsetY = currentLocation.y - storedLocation.y
center = CGPoint(x: center.x + offsetX, y: center.y + offsetY)
+ //NSLog("x coord: %f, y coord: %f", self.frame.origin.x, self.frame.origin.y)
storedLocation = currentLocation // Update initial center for next movement
}
}
@@ -106,7 +115,30 @@ import UIKit
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
+ if !OnScreenKeyView.editMode {
+ LiSendKeyboardEvent(CommandManager.keyMappings[self.keyString]!,Int8(KEY_ACTION_UP), 0)
+ return
+ }
self.backgroundColor = self.originalBackgroundColor
- if !OnScreenKeyView.relocationMode { LiSendKeyboardEvent(CommandManager.keyMappings[self.keyString]!,Int8(KEY_ACTION_UP), 0) }
+
+ guard let superview = superview else { return }
+
+ // Deactivate existing constraints if necessary
+ NSLayoutConstraint.deactivate(self.constraints)
+
+ // Add new constraints based on the current center position
+ translatesAutoresizingMaskIntoConstraints = true
+
+ // Create new constraints
+ let newLeadingConstraint = self.leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: self.frame.origin.x)
+ let newTopConstraint = self.topAnchor.constraint(equalTo: superview.topAnchor, constant: self.frame.origin.y)
+
+ // Activate the new location constraints
+ NSLayoutConstraint.activate([newLeadingConstraint, newTopConstraint])
+
+ // Trigger layout update
+ superview.layoutIfNeeded()
+
+ setupView(); //re-setup keyview style
}
}
diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h
index bc7c451d..7afec09b 100644
--- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h
+++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.h
@@ -11,6 +11,7 @@
#import "ToolBarContainerView.h"
#import "OSCProfilesManager.h"
#import "OSCProfilesTableViewController.h"
+#import "Moonlight-Swift.h"
NS_ASSUME_NONNULL_BEGIN
@@ -19,8 +20,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface LayoutOnScreenControlsViewController : UIViewController
- (void)profileRefresh;
+- (void)reloadOnScreenKeyboardButtons;
@property LayoutOnScreenControls *layoutOSC; // object that contains a view which contains the on screen controller buttons that allows the user to drag and positions each button on the screen using touch
+@property (nonatomic) NSMutableDictionary* onScreenKeyViewsDict;
+
@property int OSCSegmentSelected;
@property (weak, nonatomic) IBOutlet UIButton *trashCanButton;
diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
index 14a552dd..f39a8890 100644
--- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
+++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
@@ -12,6 +12,7 @@
#import "OnScreenControls.h"
#import "OSCProfilesManager.h"
#import "LocalizationHelper.h"
+#import "Moonlight-Swift.h"
@interface LayoutOnScreenControlsViewController ()
@@ -34,14 +35,59 @@
- (void) viewWillDisappear:(BOOL)animated{
+ OnScreenKeyView.editMode = false;
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] postNotificationName:@"OscLayoutCloseNotification" object:self];
}
+- (void) reloadOnScreenKeyboardButtons {
+ /*
+ [self.onScreenKeyViewsDict enumerateKeysAndObjectsUsingBlock:^(id timeIntervalKey, id keyView, BOOL *stop) {
+ [keyView removeFromSuperview];
+ }];*/
+
+ for (UIView *subview in self.view.subviews) {
+ // 检查子视图是否是特定类型的实例
+ if ([subview isKindOfClass:[OnScreenKeyView class]]) {
+ // 如果是,就添加到将要被移除的数组中
+ [subview removeFromSuperview];
+ }
+ }
+
+ [self.onScreenKeyViewsDict removeAllObjects];
+
+ NSLog(@"reload os Key here");
+
+ // _activeCustomOscButtonPositionDict will be updated every time when the osc profile is reloaded
+ OSCProfile *oscProfile = [profilesManager getSelectedProfile]; //returns the currently selected OSCProfile
+ for (NSData *buttonStateEncoded in oscProfile.buttonStates) {
+ OnScreenButtonState* buttonState = [NSKeyedUnarchiver unarchivedObjectOfClass:[OnScreenButtonState class] fromData:buttonStateEncoded error:nil];
+ if(buttonState.buttonType == KeyboardButton){
+ OnScreenKeyView* keyView = [[OnScreenKeyView alloc] initWithKeyString:buttonState.name keyLabel:buttonState.alias]; //reconstruct keyView
+ keyView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
+ keyView.timestamp = buttonState.timestamp; // will be set as key in in the dict.
+ // Add the KeyView to the view controller's view
+ [self.view addSubview:keyView];
+ [keyView setKeyLocationWithXOffset:buttonState.position.x yOffset:buttonState.position.y];
+
+ [self.onScreenKeyViewsDict setObject:keyView forKey:@(keyView.timestamp)];
+ }
+ }
+
+ //////////////////
+ /*
+ [self.onScreenKeyViewsDict enumerateKeysAndObjectsUsingBlock:^(id timeIntervalKey, id keyView, BOOL *stop) {
+ [self.view addSubview:keyView];
+ }];*/
+
+}
+
+
- (void) viewDidLoad {
[super viewDidLoad];
-
profilesManager = [OSCProfilesManager sharedManager];
+ self.onScreenKeyViewsDict = [[NSMutableDictionary alloc] init]; // will be revised to read persisted data , somewhere else
+ [OSCProfilesManager setOnScreenKeyViewsDict:self.onScreenKeyViewsDict]; // pass the keyboard button dict to profiles manager
isToolbarHidden = NO; // keeps track if the toolbar is hidden up above the screen so that we know whether to hide or show it when the user taps the toolbar's hide/show button
@@ -80,6 +126,14 @@
name:@"OscLayoutTableViewCloseNotification"
object:nil];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(reloadOnScreenKeyboardButtons)
+ name:@"OscLayoutProfileSelctedInTableView" // This is a special notification for reloading the on screen keyboard buttons. which can't be executed by _oscProfilesTableViewController.needToUpdateOscLayoutTVC code block, and has to be triggered by a notification
+ object:nil];
+
+
+
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(OSCLayoutChanged) name:@"OSCLayoutChanged" object:nil]; // used to notifiy this view controller that the user made a change to the OSC layout so that the VC can either fade in or out its 'Undo button' which will signify to the user whether there are any OSC layout changes to undo
/* This will animate the toolbar with a subtle up and down motion intended to telegraph to the user that they can hide the toolbar if they wish*/
@@ -108,7 +162,10 @@
[self profileRefresh];
}
+
+
- (void) viewDidAppear:(BOOL)animated {
+ OnScreenKeyView.editMode = true;
[super viewWillAppear:animated];
[self profileRefresh];
}
@@ -224,10 +281,23 @@
}
}
+- (IBAction) addTapped:(id)sender{
+ OnScreenKeyView* keyView = [[OnScreenKeyView alloc] initWithKeyString:@"ALT" keyLabel:@"test"];
+ keyView.translatesAutoresizingMaskIntoConstraints = NO; // weird but this is mandatory, or you will find no key views added to the right place
+
+ keyView.timestamp = CACurrentMediaTime(); // will be set as key in in the dict.
+ [self.onScreenKeyViewsDict setObject:keyView forKey:@(keyView.timestamp)];
+ // Add the KeyView to the view controller's view
+ [self.view addSubview:keyView];
+ [keyView setKeyLocationWithXOffset:50 yOffset:50];
+}
+
+
+
/* show pop up notification that lets users choose to save the current OSC layout configuration as a profile they can load when they want. User can also choose to cancel out of this pop up */
- (IBAction) saveTapped:(id)sender {
- if([self->profilesManager updateSelectedProfileSucceedWithButtonLayers:self.layoutOSC.OSCButtonLayers]){
+ if([self->profilesManager updateSelectedProfile:self.layoutOSC.OSCButtonLayers]){
UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Current profile updated successfully"] preferredStyle:UIAlertControllerStyleAlert];
[savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
}]];
@@ -298,17 +368,17 @@
self->_oscProfilesTableViewController = [storyboard instantiateViewControllerWithIdentifier:@"OSCProfilesTableViewController"];
//this part is just for registration, will not be immediately executed.
- self->_oscProfilesTableViewController.didDismissOSCProfilesTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC profile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the profile and then hide/show and move each OSC button to their appropriate position
+ self->_oscProfilesTableViewController.needToUpdateOscLayoutTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC profile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the profile and then hide/show and move each OSC button to their appropriate position
[self.layoutOSC updateControls]; // creates and saves a 'Default' OSC profile or loads the one the user selected on the previous screen
[self addInnerAnalogSticksToOuterAnalogLayers];
[self.layoutOSC.layoutChanges removeAllObjects]; // since a new OSC profile is being loaded, this will remove all previous layout changes made from the array
[self OSCLayoutChanged]; // fades the 'Undo Button' out
self->_oscProfilesTableViewController.currentOSCButtonLayers = self.layoutOSC.OSCButtonLayers; //pass updated OSCLayout to OSCProfileTableView again
+ //[self reloadOnScreenKeyboardButtons];
};
[self.oscProfilesTableViewController profileViewRefresh]; // execute this will make sure OSCLayout is updated from persisted profile, not any cache.
-
-
+ [self reloadOnScreenKeyboardButtons];
// [self presentViewController:vc animated:YES completion:nil];
}
@@ -327,7 +397,7 @@
_oscProfilesTableViewController = [storyboard instantiateViewControllerWithIdentifier:@"OSCProfilesTableViewController"] ;
- _oscProfilesTableViewController.didDismissOSCProfilesTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC ofile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the profile and then hide/show and move each OSC button to their appropriate position
+ _oscProfilesTableViewController.needToUpdateOscLayoutTVC = ^() { // a block that will be called when the modally presented 'OSCProfilesTableViewController' VC is dismissed. By the time the 'OSCProfilesTableViewController' VC is dismissed the user would have potentially selected a different OSC ofile with a different layout and they want to see this layout on this 'LayoutOnScreenControlsViewController.' This block of code will load the profile and then hide/show and move each OSC button to their appropriate position
[self.layoutOSC updateControls]; // creates and saves a 'Default' OSC profile or loads the one the user selected on the previous screen
[self addInnerAnalogSticksToOuterAnalogLayers];
@@ -363,8 +433,9 @@
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+
+ // -------- for OSC buttons
[self.layoutOSC touchesMoved:touches withEvent:event];
-
if ([self.layoutOSC isLayer:self.layoutOSC.layerBeingDragged
hoveringOverButton:trashCanButton]) { // check if user is dragging around a button and hovering it over the trash can button
trashCanButton.tintColor = [UIColor redColor];
@@ -372,11 +443,44 @@
else {
trashCanButton.tintColor = [UIColor colorWithRed:171.0/255.0 green:157.0/255.0 blue:255.0/255.0 alpha:1];
}
+
+ // -------- for keyboard Buttons
+ UITouch *touch = [touches anyObject]; // Get the first touch in the set
+ if([self touchWithinTashcanButton:touch]){
+ trashCanButton.tintColor = [UIColor redColor];
+ }
+ else trashCanButton.tintColor = [UIColor colorWithRed:171.0/255.0 green:157.0/255.0 blue:255.0/255.0 alpha:1];
+
+
}
+- (bool)touchWithinTashcanButton:(UITouch* )touch {
+ CGPoint locationInView = [touch locationInView:self.view];
+
+ // Convert the location to the button's coordinate system
+ CGPoint locationInButton = [self.view convertPoint:locationInView toView:trashCanButton];
+ bool ret = CGRectContainsPoint(trashCanButton.bounds, locationInButton);
+ NSLog(@"within button: %d", ret);
+ // Check if the location is within the button's bounds
+ return ret;
+}
+
+
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+
+ // removing keyboard buttons objs
+ UITouch *touch = [touches anyObject]; // Get the first touch in the set
+ if([self touchWithinTashcanButton:touch]){
+ [self.onScreenKeyViewsDict[@(OnScreenKeyView.timestampOfButtonBeingDragged)] removeFromSuperview];
+ [self.onScreenKeyViewsDict removeObjectForKey:@(OnScreenKeyView.timestampOfButtonBeingDragged)];
+ OnScreenKeyView.timestampOfButtonBeingDragged = 0; //reset thie timestamp
+ }
+
+
+ //removing OSC buttons
if (self.layoutOSC.layerBeingDragged != nil &&
[self.layoutOSC isLayer:self.layoutOSC.layerBeingDragged hoveringOverButton:trashCanButton]) { // check if user wants to throw OSC button into the trash can
+ // here we're going to delete something
self.layoutOSC.layerBeingDragged.hidden = YES;
@@ -394,8 +498,6 @@
if ([self.layoutOSC.layerBeingDragged.name isEqualToString:@"rightStickBackground"]) {
self.layoutOSC._rightStick.hidden = YES;
}
-
- trashCanButton.tintColor = [UIColor colorWithRed:171.0/255.0 green:157.0/255.0 blue:255.0/255.0 alpha:1];
}
[self.layoutOSC touchesEnded:touches withEvent:event];
@@ -407,6 +509,9 @@
}]];
[self presentViewController:movedAlertController animated:YES completion:nil];
}
+
+
+ trashCanButton.tintColor = [UIColor colorWithRed:171.0/255.0 green:157.0/255.0 blue:255.0/255.0 alpha:1];
}
@end
diff --git a/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.h b/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.h
index 26dbe440..eb2df598 100644
--- a/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.h
+++ b/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.h
@@ -19,7 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (weak, nonatomic) IBOutlet UITableView *tableView;
-@property (nonatomic, copy) void (^didDismissOSCProfilesTVC)(void);
+@property (nonatomic, copy) void (^needToUpdateOscLayoutTVC)(void);
@property (nonatomic, assign) NSMutableArray *currentOSCButtonLayers;
@end
diff --git a/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m
index 779c4345..ec1ac7da 100644
--- a/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m
+++ b/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m
@@ -22,7 +22,6 @@ const double NAV_BAR_HEIGHT = 50;
@implementation OSCProfilesTableViewController {
OSCProfilesManager *profilesManager;
- LayoutOnScreenControlsViewController *parentLayoutOSCViewController;
}
@synthesize tableView;
@@ -139,9 +138,11 @@ const double NAV_BAR_HEIGHT = 50;
//[self dismissViewControllerAnimated:YES completion:nil];
//[selfparentLayoutOSCViewController]
[self.tableView reloadData]; // table view will be refreshed by calling reloadData
- if (self.didDismissOSCProfilesTVC) { // tells the presenting view controller to lay out the on screen buttons according to the selected profile's instructions
- self.didDismissOSCProfilesTVC();
+
+ if (self.needToUpdateOscLayoutTVC) { // tells the presenting view controller to lay out the on screen buttons according to the selected profile's instructions
+ self.needToUpdateOscLayoutTVC();
}
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"OscLayoutProfileSelctedInTableView" object:self]; // notify other view that oscLayoutManager is closing
}
- (IBAction) deleteTapped:(id)sender{// delete can be executed simply by calling this 2 methods.
diff --git a/Limelight/ViewControllers/StreamFrameViewController.m b/Limelight/ViewControllers/StreamFrameViewController.m
index 61a49300..aa1ecd03 100644
--- a/Limelight/ViewControllers/StreamFrameViewController.m
+++ b/Limelight/ViewControllers/StreamFrameViewController.m
@@ -179,8 +179,8 @@
CGFloat spacing = 10.0;
[keyView setKeyLocationWithXOffset:500 yOffset:(CGFloat)550];
- */
-
+
+ */
diff --git a/Limelight/mul.lproj/iPad.xcstrings b/Limelight/mul.lproj/iPad.xcstrings
index 5a352e01..dc736f8b 100644
--- a/Limelight/mul.lproj/iPad.xcstrings
+++ b/Limelight/mul.lproj/iPad.xcstrings
@@ -385,6 +385,18 @@
}
}
},
+ "bMH-Yb-sb6.normalTitle" : {
+ "comment" : "Class = \"UIButton\"; normalTitle = \"+\"; ObjectID = \"bMH-Yb-sb6\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "+"
+ }
+ }
+ }
+ },
"byH-Qz-Nbw.segmentTitles[0]" : {
"comment" : "Class = \"UISegmentedControl\"; byH-Qz-Nbw.segmentTitles[0] = \"No\"; ObjectID = \"byH-Qz-Nbw\";",
"extractionState" : "extracted_with_value",