generic improvements & fixes

This commit is contained in:
True Zhuanjia
2026-07-31 22:13:13 +08:00
parent 3d82009d4a
commit 5bd9c6bd98
21 changed files with 487 additions and 1005 deletions
+11 -13
View File
@@ -2,6 +2,7 @@
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24506" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="EVd-wq-ego">
<device id="ipad11_0rounded" orientation="portrait" layout="fullscreen" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24504"/>
<capability name="Image references" minToolsVersion="12.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -12,7 +13,7 @@
<objects>
<viewController id="wb7-af-jn8" customClass="MainFrameViewController" sceneMemberID="viewController">
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" indicatorStyle="black" dataMode="prototypes" id="TZj-Lc-M9d" customClass="AppCollectionView">
<rect key="frame" x="0.0" y="0.0" width="834" height="1210"/>
<rect key="frame" x="0.0" y="0.0" width="834" height="1124"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="f7l-kG-hJc">
@@ -1145,16 +1146,16 @@
</constraints>
</stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="pTO-ff-set">
<rect key="frame" x="3145" y="191" width="293.5" height="31"/>
<rect key="frame" x="3145" y="191" width="275.5" height="31"/>
<subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pencil Tip Offset" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pTO-ff-lbl" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="143.5" height="31"/>
<rect key="frame" x="0.0" y="0.0" width="125.5" height="31"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pTO-ff-swi">
<rect key="frame" x="163.5" y="0.0" width="132" height="31"/>
<rect key="frame" x="145.5" y="0.0" width="132" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="130" id="pTO-ff-wid"/>
</constraints>
@@ -2079,19 +2080,19 @@
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="WtH-Ii-ZUv">
<rect key="frame" x="3145" y="426" width="380" height="56.5"/>
<subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hover Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DhB-EF-mDt">
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pencil Mode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DhB-EF-mDt">
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.93902439019999995" green="0.9625305918" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="t12-bo-icS">
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="t12-bo-icS">
<rect key="frame" x="0.0" y="25.5" width="380" height="32"/>
<segments>
<segment title="Disabled"/>
<segment title="Hovering Disabled"/>
<segment title="Stylus"/>
<segment title="Mouse"/>
<segment title="Both"/>
<segment title="Touch"/>
</segments>
<color key="tintColor" red="0.6716768742" green="0.61711704730000005" blue="0.99902987480000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="selectedSegmentTintColor" systemColor="linkColor"/>
@@ -2325,8 +2326,6 @@
<outlet property="hapticEngineStack" destination="MUp-Hc-VgH" id="XuW-ww-cmv"/>
<outlet property="hdrStack" destination="dH7-Sy-EdJ" id="cJm-bj-Aqo"/>
<outlet property="hdrSwitch" destination="wIq-fF-X8l" id="Ozz-h0-nJL"/>
<outlet property="hoverModeSelector" destination="t12-bo-icS" id="0d6-QD-Mtg"/>
<outlet property="hoverModeStack" destination="WtH-Ii-ZUv" id="BvA-MP-rmE"/>
<outlet property="leftClickDelaySlider" destination="Mh4-1P-bSv" id="Tbj-Y0-t1x"/>
<outlet property="leftClickDelayStack" destination="q0S-CP-V6v" id="0lz-MN-OEb"/>
<outlet property="leftStickMinOffsetSlider" destination="KtJ-qH-KJX" id="vIV-4l-gbA"/>
@@ -2356,6 +2355,8 @@
<outlet property="optimizeGamesSwitch" destination="Sui-Ig-YxN" id="Lxu-si-ugy"/>
<outlet property="passthroughGesturesStack" destination="wUP-2q-5vh" id="a4w-16-lLs"/>
<outlet property="passthroughGesturesSwitch" destination="eO1-kV-e9j" id="5r8-o4-t9J"/>
<outlet property="pencilModeSelector" destination="t12-bo-icS" id="0d6-QD-Mtg"/>
<outlet property="pencilModeStack" destination="WtH-Ii-ZUv" id="BvA-MP-rmE"/>
<outlet property="pencilPausesNativeTouchStack" destination="jLJ-Eo-Zi6" id="a4V-Lp-xDG"/>
<outlet property="pencilPausesNativeTouchSwitch" destination="Pjf-Vi-3wE" id="L84-RY-6iV"/>
<outlet property="pencilTickIntervalSlider" destination="IOG-l4-gtQ" id="3Kb-uT-ILa"/>
@@ -3947,9 +3948,6 @@
<systemColor name="systemGray3Color">
<color red="0.78039215689999997" green="0.78039215689999997" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemGray5Color">
<color red="0.8980392157" green="0.8980392157" blue="0.91764705879999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemTealColor">
<color red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
+2
View File
@@ -389,6 +389,8 @@ import Foundation
@objc static var swapABXY:Bool = false
@objc static var gamepadArrivalReported: Bool = false
@objc static func string(for element: ControllerElement) -> String {
return element.displayName
}
@@ -88,9 +88,8 @@
[self._dPadBackground addSublayer:self._leftButton];
}
NSLog(@"layer name ttttttttttt============================");
for(CALayer* buttonLayer in self.OSCButtonLayerPool){
NSLog(@"layer name %@", buttonLayer.name);
// NSLog(@"layer name %@", buttonLayer.name);
}
[self resizeControllerLayerWith:self._dPadBackground and:_dPadSizeFactor];
+6 -6
View File
@@ -22,11 +22,11 @@ typedef NS_ENUM(NSInteger, MapGyroTo) {
driftCorrection
};
typedef NS_ENUM(NSInteger, PencilHoverMode) {
HoverDisabled,
HoverPencil,
HoverMouse,
HoverBoth
typedef NS_ENUM(NSInteger, PencilAndHoverMode) {
hoverDisabled,
pencilOnly,
pencilToMouse,
pencilToTouch
};
@@ -82,7 +82,7 @@ typedef NS_ENUM(NSInteger, PencilHoverMode) {
@property NSString *squeezeEndShortcut;
@property (nonatomic, assign) bool pencilPausesNativeTouch;
@property (nonatomic, assign) bool disablePencilSlideGestures;
@property (nonatomic, assign) PencilHoverMode pencilHoverMode;
@property (nonatomic, assign) PencilAndHoverMode pencilAndHoverMode;
+3 -3
View File
@@ -74,7 +74,7 @@
[encoder encodeObject:self.squeezeEndShortcut forKey:@"squeezeEndShortcut"];
[encoder encodeBool:self.pencilPausesNativeTouch forKey:@"pencilPausesNativeTouch"];
[encoder encodeBool:self.disablePencilSlideGestures forKey:@"disablePencilSlideGestures"];
[encoder encodeInt64:self.pencilHoverMode forKey:@"pencilHoverMode"];
[encoder encodeInt64:self.pencilAndHoverMode forKey:@"pencilHoverMode"];
}
- (id) initWithCoder:(NSCoder*)decoder {
@@ -201,7 +201,7 @@
self.pencilPausesNativeTouch = [decoder containsValueForKey:@"pencilPausesNativeTouch"] ? [decoder decodeBoolForKey:@"pencilPausesNativeTouch"] : false;
self.disablePencilSlideGestures = [decoder containsValueForKey:@"disablePencilSlideGestures"] ? [decoder decodeBoolForKey:@"disablePencilSlideGestures"] : false;
self.pencilHoverMode = [decoder containsValueForKey:@"pencilHoverMode"] ? [decoder decodeInt64ForKey:@"pencilHoverMode"] : HoverPencil;
self.pencilAndHoverMode = [decoder containsValueForKey:@"pencilHoverMode"] ? [decoder decodeInt64ForKey:@"pencilHoverMode"] : pencilOnly;
}
return self;
@@ -253,7 +253,7 @@
copy.squeezeEndShortcut = [self.squeezeEndShortcut mutableCopy]; // NSString → NSMutableString
copy.pencilPausesNativeTouch = self.pencilPausesNativeTouch;
copy.disablePencilSlideGestures = self.disablePencilSlideGestures;
copy.pencilHoverMode = self.pencilHoverMode;
copy.pencilAndHoverMode = self.pencilAndHoverMode;
return copy;
}
@@ -1,85 +0,0 @@
//
// OSCProfilesManager.h
// Moonlight
//
// Created by Long Le on 1/1/23.
// Copyright © 2022 Moonlight Game Streaming Project. All rights reserved.
//
// Modified by True砖家 since 2024.6.24
// Copyright © 2024 True砖家 @ Bilibili. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "OSCProfile.h"
#import "DataManager.h"
NS_ASSUME_NONNULL_BEGIN
/**
This singleton object can be accessed from any class and provides methods to get and set on screen controller profile related data.
Note that the implementation file contains a number of 'Helper' methods. These helper methods are only used in this class's implementation file and help to reduce re-writing large blocks of code that are called multiple times throughout the file
*/
@interface OSCProfilesManager : NSObject
@property NSMutableArray <OSCProfile *> *currentProfiles;
@property (atomic, assign) WidgetSizeTransition widgetSizeTransition;
+ (OSCProfilesManager *)sharedManager:(CGRect)viewBounds;
+ (void)setOnScreenWidgetViewsSet:(NSMutableSet* )set;
+ (void)setLayoutViewBounds:(CGRect)bounds;
#pragma mark - Getters
/**
* Returns an array of decoded profile objects
*/
- (NSMutableArray *) getAllProfiles;
/**
* Returns the OSC Profile that is currently selected to be displayed on screen during game streaming
*/
- (OSCProfile *) getSelectedProfile;
- (uint32_t) getIndexOfLastProfile;
/**
* Returns the index of the 'selected' profile within the array it's in
*/
- (NSInteger) getIndexOfSelectedProfile;
- (NSMutableArray *) getEncodedProfiles;
// - (NSData* )getSelectedEncodedProfile;
- (void) importEncodedProfiles:(NSMutableArray* )profilesEncoded;
- (OnScreenButtonState *)unarchiveButtonStateEncoded:(NSData *)data;
- (void) updateDefaultTemplates;
- (void) importDefaultTemplates;
#pragma mark - Setters
/**
* Sets the profile object with the particular index as the selected profile to be displayed on screen during game streaming
*/
- (void) setProfileToSelected:(uint32_t)index;
- (void) replaceSelectedProfileWith:(OSCProfile*)newProfile overwriteDefault:(bool)overwriteDefault;
- (void) replaceProfile:(OSCProfile*)oldProfile withProfile:(OSCProfile*)newProfile;
/**
* Saves a profile object with a particular 'name' and an array of button layers (the CALayer button layers are the objects currently visible on screen) to persistent storage
*/
- (void) duplicateSelectedProfileWithName:(NSString*)name;
- (bool) updateSelectedProfile:(NSMutableSet *) oscButtonLayers;
/**
* Delete current selected profile.
*/
- (void) deleteCurrentSelectedProfile;
#pragma mark - Queries
/**
* Lets the caller of this method know whether a profile with a given name already exists in persistent storage
*/
- (BOOL) profileNameAlreadyExist:(NSString*)name;
- (OSCProfile *) findProfileByName:(NSString*) name inProfileArray:(NSMutableArray*)profiles;
- (CGPoint)normalizeWidgetPosition:(CGPoint)position;
@end
NS_ASSUME_NONNULL_END
@@ -1,579 +0,0 @@
//
// OSCProfilesManager.m
// Moonlight
//
// Created by Long Le on 1/1/23.
// Copyright © 2023 Moonlight Game Streaming Project. All rights reserved.
//
// Modified by True砖家 since 2024.6.24
// Copyright © 2024 True砖家 @ Bilibili. All rights reserved.
//
#import "OSCProfilesManager.h"
#import "OnScreenButtonState.h"
#import "VoidLink-Swift.h"
#import "OnScreenControls.h"
@implementation OSCProfilesManager
static NSMutableSet *OnScreenWidgetViews;
static CGRect layoutViewBounds;
#pragma mark - Initializer
+ (OSCProfilesManager *) sharedManager:(CGRect)viewBounds {
static OSCProfilesManager *_sharedManager = nil;
static dispatch_once_t onceToken;
if(!CGRectEqualToRect(viewBounds, CGRectZero)) layoutViewBounds = viewBounds;
// NSLog(@"bounds width: %f, height: %f", layoutViewBounds.size.width, layoutViewBounds.size.height);
dispatch_once(&onceToken, ^{
_sharedManager = [[self alloc] init];
});
// _sharedManager.currentProfiles = [_sharedManager getAllProfiles];
return _sharedManager;
}
#pragma mark - Class Helper Methods
+ (void)setOnScreenWidgetViewsSet:(NSMutableSet* )set{
OnScreenWidgetViews = set;
}
+ (void)setLayoutViewBounds:(CGRect)bounds{
layoutViewBounds = bounds;
}
/**
* Returns the profile whose 'name' property has a value that is equal to the 'name' passed into the method
*/
- (OSCProfile *) OSCProfileWithName:(NSString*)name {
NSMutableArray *profiles = [self getAllProfiles];
for (OSCProfile *profile in profiles) {
if ([profile.name isEqualToString:name]) {
return profile;
}
}
return nil;
}
/**
* Returns an array of encoded 'OSCProfile' objects from the array of decoded 'OSCProfile' objects passed into this method
*/
- (NSMutableArray *) encodedProfilesFromArray:(NSMutableArray *)profiles {
NSMutableArray *profilesEncoded = [[NSMutableArray alloc] init];
/* encode each profile and add them back into an array */
for (OSCProfile *profile in profiles) { //
NSData *profileEncoded = [NSKeyedArchiver archivedDataWithRootObject:profile requiringSecureCoding:YES error:nil];
[profilesEncoded addObject:profileEncoded];
}
return profilesEncoded;
}
/**
* Delete an 'OSCProfile' object of specific index for another in the 'OSCProfile' objects array stored in persistent storage
*/
-(void)deleteCurrentSelectedProfile{
NSMutableArray *profiles = [self getAllProfiles];
NSInteger selectedIndex = [self getIndexOfSelectedProfile];
/* Remove the selected profile */
if(selectedIndex != 0) [profiles removeObjectAtIndex:selectedIndex]; //deleting default profile (index 0) is not allowed
else {
NSLog(@"Default profile!"); // to be updated here.
}
selectedIndex--;
if(selectedIndex < 0) selectedIndex = 0;
OSCProfile *newSelectedProfile = [profiles objectAtIndex:selectedIndex];
newSelectedProfile.isSelected = YES;
NSMutableArray *profilesEncoded = [self encodedProfilesFromArray:profiles]; // encode each 'profile' object in the array and add them to a new array
/* Encode the array itself, NOT the objects in the array, which are already encoded. Save array to persistent storage */
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:profilesEncoded requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"OSCProfiles"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)replaceSelectedProfileWith:(OSCProfile*)newProfile overwriteDefault:(bool)overwriteDefault{
NSInteger index = 0;
NSMutableArray *profiles = [self getAllProfiles];
for (OSCProfile *profile in profiles) {
if (profile.isSelected == YES) {
index = [profiles indexOfObject:profile];
}
}
if(index>0) profiles[index] = newProfile;
else if(overwriteDefault) profiles[index] = newProfile;
NSMutableArray *profilesEncoded = [self encodedProfilesFromArray:profiles];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:profilesEncoded requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"OSCProfiles"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
/**
* Replaces one 'OSCProfile' object for another in the 'OSCProfile' objects array stored in persistent storage
*/
- (void) replaceProfile:(OSCProfile*)oldProfile withProfile:(OSCProfile*)newProfile {
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;
}
/* Set the new profile as the selected one. The reasoning behind this is that this method is currently being used when the user saves over an existing profile with another profile that has the same name. The expected behavior is that the newly saved profile becomes the selected profile which will show on screen when they launch the game stream view */
newProfile.isSelected = YES;
/* Remove the old profile from the array and insert the new profile into its place */
int index = 0;
for (int i = 0; i < profiles.count; i++) {
if ([[profiles[i] name] isEqualToString: oldProfile.name]) {
index = i;
}
}
[profiles removeObjectAtIndex:index];
[profiles insertObject:newProfile atIndex:index];
NSMutableArray *profilesEncoded = [self encodedProfilesFromArray:profiles]; // encode each 'profile' object in the array and add them to a new array
/* Encode the array itself, NOT the objects in the array, which are already encoded. Save array to persistent storage */
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:profilesEncoded requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"OSCProfiles"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (NSMutableArray *) getEncodedProfiles {
NSData *profilesArrayEncoded = [[NSUserDefaults standardUserDefaults] objectForKey: @"OSCProfiles"]; // Get the encoded array of encoded OSC profiles from persistent storage
NSSet *classes = [NSSet setWithObjects:[NSString class], [NSMutableData class], [NSMutableArray class], [OSCProfile class], [OnScreenButtonState class], nil];
NSMutableArray *profilesEncoded = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:profilesArrayEncoded error:nil]; // Decode the encoded array itself, NOT the objects contained in the array
return profilesEncoded;
}
- (void) importEncodedProfiles:(NSMutableArray* )profilesEncoded {
NSMutableArray* targetProfiles = [_currentProfiles mutableCopy]; //_currentProfiles is availabled as long as getAllProfiles was called before calling this method (_currentProfiles avoids frequent accessing persisted data)
/*
profile = [self findProfileByName:DEFAULT_TEMPLATE_NAME1 inProfileArray:targetProfiles];
if(profile && targetProfiles.count > 1) [targetProfiles removeObject:profile];
profile = [self findProfileByName:DEFAULT_TEMPLATE_NAME2 inProfileArray:targetProfiles];
if(profile && targetProfiles.count > 1) [targetProfiles removeObject:profile];
*/
/*
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
bool importPencilProProfile = ([bundleId isEqualToString:@"com.voidlink.iOS"]
|| [bundleId isEqualToString:@"com.voidlinkextreme.iOS"]
|| [bundleId isEqualToString:@"com.voidlink.tf.debug10.iOS"]);
if(!importPencilProProfile && [GenericUtils isIPad]){
[profilesEncoded removeObjectAtIndex:1];
}
*/
if(targetProfiles.count > 0) [targetProfiles removeObjectAtIndex:0];
NSMutableArray* localEncodedPofiles = [self encodedProfilesFromArray:targetProfiles];
[profilesEncoded addObjectsFromArray:localEncodedPofiles];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:profilesEncoded requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"OSCProfiles"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (BOOL)isIPhone{
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone);
}
- (void) importDefaultTemplates{
NSString *filePath = [[NSBundle mainBundle] pathForResource: [self isIPhone] ? @"widgetTemplatesIPhone": @"widgetTemplates" ofType:@"bin"];
if (filePath) {
// 2. 读取二进制数据
NSError *error;
NSData *fileData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];
NSMutableArray *profilesEncoded;
if (fileData && !error) {
// 3. 成功读取
NSSet *classes = [NSSet setWithObjects: [NSMutableData class], [NSMutableArray class], nil];
profilesEncoded = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:fileData error:&error];
[self importEncodedProfiles:profilesEncoded];
NSString *bundleId = [[NSBundle mainBundle] bundleIdentifier];
/*
bool isRegularTF = !([bundleId isEqualToString:@"com.voidlink.iOS"]
|| [bundleId isEqualToString:@"com.voidlinkextreme.iOS"]
|| [bundleId isEqualToString:@"com.voidlink.tf.debug10.iOS"]);
[self setProfileToSelected: GenericUtils.isIPhone ? 1 : (isRegularTF ? 1: 2)]; */
[self setProfileToSelected: 0];
}
}
}
- (void) updateDefaultTemplates{
NSString *filePath = [[NSBundle mainBundle] pathForResource: [self isIPhone] ? @"widgetTemplatesIPhone": @"widgetTemplates" ofType:@"bin"];
if (filePath) {
// 2. 读取二进制数据
NSError *error;
NSData *fileData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];
if (fileData && !error) {
NSSet *classes = [NSSet setWithObjects:[NSString class], [NSMutableData class], [NSMutableArray class], [OSCProfile class], [OnScreenButtonState class], nil];
NSMutableArray *defaultProfilesEncoded = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:fileData error:nil]; // Decode the encoded array itself, NOT the objects contained in the array
OSCProfile *defaultProfileDecoded;
NSMutableArray *targetProfilesDecoded = [self getAllProfiles];
OSCProfile *newPencilProProfile;
bool pencilProProfileExisted = false;
for (NSData *profileEncoded in defaultProfilesEncoded) {
defaultProfileDecoded = [NSKeyedUnarchiver unarchivedObjectOfClasses: classes fromData:profileEncoded error: nil];
OSCProfile *targetProfile = [self findProfileByName:defaultProfileDecoded.name inProfileArray:targetProfilesDecoded];
if([defaultProfileDecoded.name isEqualToString:@"Pencil Pro"]){
newPencilProProfile = [defaultProfileDecoded mutableCopy];
}
if(targetProfile){
if([targetProfile.name isEqualToString:@"Pencil Pro"]){
pencilProProfileExisted = true;
}
uint64_t targetIndex = [targetProfilesDecoded indexOfObject:targetProfile];
targetProfilesDecoded[targetIndex] = defaultProfileDecoded;
}
}
if(newPencilProProfile && !pencilProProfileExisted){
if(newPencilProProfile) [targetProfilesDecoded insertObject:newPencilProProfile atIndex:1];
}
NSMutableArray* targetPofilesEncoded = [self encodedProfilesFromArray:targetProfilesDecoded];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:targetPofilesEncoded requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"OSCProfiles"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self setProfileToSelected:0];
}
}
}
#pragma mark - Globally Accessible Methods
#pragma mark - Getters
- (NSMutableArray *) getAllProfiles {
NSData *profilesArrayEncoded = [[NSUserDefaults standardUserDefaults] objectForKey: @"OSCProfiles"]; // Get the encoded array of encoded OSC profiles from persistent storage
NSSet *classes = [NSSet setWithObjects:[NSString class], [NSMutableData class], [NSMutableArray class], [OSCProfile class], [OnScreenButtonState class], nil];
NSMutableArray *profilesEncoded = [NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:profilesArrayEncoded error:nil]; // Decode the encoded array itself, NOT the objects contained in the array
/* Decode each of the encoded profiles, place them into an array, then return the array */
NSMutableArray *profilesDecoded = [[NSMutableArray alloc] init];
OSCProfile *profileDecoded;
for (NSData *profileEncoded in profilesEncoded) {
profileDecoded = [NSKeyedUnarchiver unarchivedObjectOfClasses: classes fromData:profileEncoded error: nil];
[profilesDecoded addObject: profileDecoded];
}
_currentProfiles = profilesDecoded;
return profilesDecoded;
}
- (NSMutableArray *) decodeProfilesFrom:(NSMutableArray* )profilesEncoded {
NSSet *classes = [NSSet setWithObjects:[NSString class], [NSMutableData class], [NSMutableArray class], [OSCProfile class], [OnScreenButtonState class], nil];
NSMutableArray *profilesDecoded = [[NSMutableArray alloc] init];
OSCProfile *profileDecoded;
for (NSData *profileEncoded in profilesEncoded) {
profileDecoded = [NSKeyedUnarchiver unarchivedObjectOfClasses: classes fromData:profileEncoded error: nil];
[profilesDecoded addObject: profileDecoded];
}
return profilesDecoded;
}
- (OSCProfile *) getSelectedProfile {
// NSLog(@"getAllProfiles test %f", CACurrentMediaTime());
NSMutableArray *profiles = [self getAllProfiles];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// NSString* persistedKey = @"widgetProfileUpdated-20251015";
// NSString* persistedKey = @"widgetProfileUpdated-20260322";
// NSString* persistedKey = @"widgetProfileUpdated-20260413-2";
// NSString* persistedKey = @"widgetProfileUpdated-20260430-1";
// NSString* persistedKey = @"widgetProfileUpdated-20260513-1";
NSString* persistedKey = @"widgetProfileUpdated-20260530";
BOOL needImportDefaultTemplates = [defaults objectForKey:persistedKey] == nil;
if(profiles.count == 0 || needImportDefaultTemplates){
if(profiles.count == 0) [self importDefaultTemplates];
else [self updateDefaultTemplates];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:persistedKey];
[[NSUserDefaults standardUserDefaults] synchronize];
profiles = [self getAllProfiles];
}
for (OSCProfile *profile in profiles) {
if (profile.isSelected) {
return profile;
}
}
return profiles[0];
}
- (NSInteger) getIndexOfSelectedProfile {
NSMutableArray *profiles = [self getAllProfiles];
for (OSCProfile *profile in profiles) {
if (profile.isSelected == YES) {
return [profiles indexOfObject:profile];
}
}
return 0; // if none of the profiles in the array have their 'isSelected' property set to YES (which should not be possible) return the 'Default' profile as the 'selected' profile
}
- (uint32_t) getIndexOfLastProfile {
NSMutableArray *profiles = [self getAllProfiles];
return (uint32_t)profiles.count-1; // if none of the profiles in the array have their 'isSelected' property set to YES (which should not be possible) return the 'Default' profile as the 'selected' profile
}
#pragma mark - Setters
- (void) setProfileToSelected:(uint32_t)tableIndex {
NSMutableArray *profiles = [self getAllProfiles];
[profiles enumerateObjectsUsingBlock:^(OSCProfile* profile, NSUInteger idx, BOOL *stop) {
profile.isSelected = idx == tableIndex;
}];
NSMutableArray *profilesEncoded = [self encodedProfilesFromArray:profiles]; // encode each 'profile' object in the array and add them to a new array
/* Encode the array itself, NOT the objects inside the array, which have already been encoded by this point */
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:profilesEncoded requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"OSCProfiles"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (bool) updateSelectedProfile:(NSMutableSet *) oscButtonLayers {
NSMutableArray* buttonStatesEncoded = [self convertOnScreenControllerAndWidgetsToButtonStates:oscButtonLayers];
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
*/
OSCProfile *selectedProfile = [self getSelectedProfile];
selectedProfile.buttonStatesEncoded = buttonStatesEncoded;
selectedProfile.unfoldedExclusiveFolderSequence = OnScreenWidgetView.unfoldedExclusiveFolderSequence;
selectedProfile.postExclusiveUnfoldedSequences = OnScreenWidgetView.postExclusiveUnfoldedSequences;
[self replaceSelectedProfileWith:selectedProfile overwriteDefault:NO];
return true;
}
- (void) duplicateSelectedProfileWithName:(NSString*)name {
if ([self profileNameAlreadyExist:name]) return;
else { // otherwise encode then add the new profile to the end of the OSCProfiles array
NSMutableArray *profiles = [self getAllProfiles];
OSCProfile* newProfile = nil;
for(OSCProfile* profile in profiles){
if(profile.isSelected){
profile.isSelected = false;
newProfile = [profile mutableCopy];
newProfile.isSelected = true;
newProfile.name = name;
}
}
if(newProfile){
NSData *newProfileEncoded = [NSKeyedArchiver archivedDataWithRootObject:newProfile requiringSecureCoding:YES error:nil];
NSMutableArray *profilesEncoded = [self encodedProfilesFromArray:profiles];
[profilesEncoded addObject:newProfileEncoded];
/* Encode the 'profilesEncoded' array itself, NOT the objects in the 'profilesEncoded' array, all of which are already encoded by this point */
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:profilesEncoded requiringSecureCoding:YES error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"OSCProfiles"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
}
- (CGPoint)normalizeWidgetPosition:(CGPoint)position {
CGPoint newPosition = position;
if(position.x > 1.0 && position.y >1.0){
position.x = position.x / layoutViewBounds.size.width;
position.y = position.y / layoutViewBounds.size.height;
}
NSLog(@"layoutToolView bounds: %f, %f", layoutViewBounds.size.width, layoutViewBounds.size.height);
NSLog(@"position: %f, %f, denormalized position: %f, %f", position.x, position.y, newPosition.x, newPosition.y);
return position;
}
- (CGPoint)denormalizeWidgetPosition:(CGPoint)position {
if(position.x < 1.0 && position.y < 1.0){
position.x = position.x * layoutViewBounds.size.width;
position.y = position.y * layoutViewBounds.size.height;
}
return position;
}
- (NSMutableArray* ) convertOnScreenControllerAndWidgetsToButtonStates:(NSMutableSet *) 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:
@"l2Button",
@"l1Button",
@"dPad",
@"selectButton",
@"leftStickBackground",
@"rightStickBackground",
@"r2Button",
@"r1Button",
@"aButton",
@"bButton",
@"xButton",
@"yButton",
@"startButton",
nil]; */
NSMutableArray *buttonStatesEncoded = [[NSMutableArray alloc] init];
// save on-screen game controller buttons & sticks as buttonstate:
for (CALayer *oscButtonLayer in oscButtonLayers) {
if(oscButtonLayer.isHidden) continue;
CGPoint normalizedPosition = [self normalizeWidgetPosition:oscButtonLayer.position];
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:oscButtonLayer.name buttonType:LegacyOnScreenControls andPosition:normalizedPosition];
// add hidden attr here
buttonState.isHidden = oscButtonLayer.isHidden;
buttonState.oscLayerSizeFactor = [OnScreenControls getControllerLayerSizeFactor:oscButtonLayer];
buttonState.backgroundAlpha = oscButtonLayer.opacity;
NSNumber *style = [OnScreenControls.layerVibrationStyleDic objectForKey:oscButtonLayer.name];
if ([style isKindOfClass:[NSNumber class]]) {
buttonState.vibrationStyle = [style unsignedCharValue];
// 使用 val
}
else buttonState.vibrationStyle = UIImpactFeedbackStyleLight;
// NSLog(@"oscLayerName: %@, opacity: %f, ", oscButtonLayer.name, buttonState.backgroundAlpha);
// buttonState.oscLayerSizeFactor = oscButtonLayer.bounds;
NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
[buttonStatesEncoded addObject: buttonStateEncoded];
}
// save on-screen widget views (keyboard & mouse command) as buttonstate:
_widgetSizeTransition = keepWidgetSize;
for(OnScreenWidgetView* widgetView in OnScreenWidgetView.mapping.allValues){
CGPoint normalizedPosition = [self normalizeWidgetPosition:widgetView.storedCenter];
OnScreenButtonState *buttonState = [[OnScreenButtonState alloc] initWithButtonName:widgetView.cmdString buttonType:CustomOnScreenWidget andPosition:normalizedPosition];
buttonState.alias = widgetView.widgetLabel;
buttonState.sequence = widgetView.sequence;
buttonState.sequenceSet = widgetView.sequenceSet;
buttonState.parentSequence = widgetView.parentSequence;
buttonState.autoDockTimer = widgetView.autoDockIdleDuration;
buttonState.dockedAlpha = widgetView.autoDockSettledAlpha;
buttonState.folded = widgetView.folded;
buttonState.revealMode = widgetView.revealMode;
buttonState.bulkMoveEnabled = widgetView.bulkMoveEnabled;
buttonState.widthFactor = [self normalizeSizeWidthFactorWith:widgetView];
buttonState.heightFactor = [self normalizeSizeHeightFactorWith:widgetView];
buttonState.backgroundAlpha = widgetView.originalBackgroundAlpha;
buttonState.labelAlpha = widgetView.originalLabelAlpha;
buttonState.borderAlpha = widgetView.borderAlpha;
buttonState.highlightAlpha = widgetView.highlightAlpha;
buttonState.borderWidth = widgetView.borderWidth;
buttonState.highlightSizeFactor = widgetView.highlightSizeFactor;
buttonState.autoTapInterval = widgetView.autoTapInterval;
buttonState.autoTapRepeats = widgetView.autoTapRepeats;
buttonState.vibrationStyle = widgetView.vibrationStyle;
buttonState.mouseButtonAction = widgetView.mouseButtonAction;
buttonState.animatesTransition = widgetView.animatesTransition;
buttonState.sensitivityFactorY = widgetView.sensitivityFactorY;
buttonState.slideThreshold = widgetView.slideThreshold;
buttonState.yawFactor = widgetView.yawFactor;
buttonState.pitchFactor = widgetView.pitchFactor;
buttonState.rollFactor = widgetView.rollFactor;
buttonState.decelerationRateX = widgetView.decelerationRateX;
buttonState.decelerationRateY = widgetView.decelerationRateY;
buttonState.widgetShape = widgetView.shape;
buttonState.walkModeThreshold = widgetView.dWheelWalkModeThreshold;
buttonState.minStickOffset = widgetView.minStickOffset;
buttonState.buttonMode = widgetView.buttonMode;
buttonState.sprintKeyActionType = widgetView.sprintKeyActionType;
buttonState.sprintKeyThreshold = widgetView.sprintKeyThreshold;
buttonState.walkKeyActionType = widgetView.walkKeyActionType;
buttonState.walkKeyThreshold = widgetView.walkKeyThreshold;
///
buttonState.sensitivityFactorX = widgetView.sensitivityFactorX;
buttonState.componentSizeFactor = [self normalizeComponentSizeFactorWith:widgetView];
buttonState.touchPointAnchored = widgetView.touchPointAnchored;
buttonState.stickIndicatorOffset = widgetView.stickIndicatorOffset;
NSData *buttonStateEncoded = [NSKeyedArchiver archivedDataWithRootObject:buttonState requiringSecureCoding:YES error:nil];
[buttonStatesEncoded addObject: buttonStateEncoded];
}
return buttonStatesEncoded;
}
- (CGFloat)getReferenceLen{
CGFloat screenWidthInPoints = CGRectGetWidth([[UIScreen mainScreen] bounds]);
CGFloat screenHeightInPoints = CGRectGetHeight([[UIScreen mainScreen] bounds]);
CGFloat longSideLen = fmax(screenWidthInPoints,screenHeightInPoints);
CGFloat referenceLen = longSideLen;
if(_widgetSizeTransition == keepWidgetSize) referenceLen = longSideLen;
if(_widgetSizeTransition == transitionWithOrientation) referenceLen = screenWidthInPoints;
return referenceLen;
}
- (CGFloat)normalizeSizeWidthFactorWith:(OnScreenWidgetView* )widget{
return widget.bounds.size.width/[self getReferenceLen] * 10000;
}
- (CGFloat)normalizeSizeHeightFactorWith:(OnScreenWidgetView* )widget{
return widget.bounds.size.height/[self getReferenceLen] * 10000;
}
- (CGFloat)normalizeComponentSizeFactorWith:(OnScreenWidgetView* )widget{
if(widget.isStickWheel
|| widget.isDisplacementBasedStickPad) {
return widget.denormalizedComponentSizeFactor*widget.baselineDiameter/[self getReferenceLen] * 10000;
}
return 1;
}
#pragma mark - Queries
- (BOOL) profileNameAlreadyExist:(NSString*)name {
NSMutableArray *profiles = [self getAllProfiles];
/* Iterate through the decoded profiles and return 'YES' if one of the profiles' 'name' properties equals the 'name' passed into this method */
for (OSCProfile *profile in profiles) {
if ([profile.name isEqualToString:name]) {
return YES;
}
}
return NO;
}
- (OSCProfile *) findProfileByName:(NSString*) name inProfileArray:(NSMutableArray*)profiles {
/* Iterate through the decoded profiles and return 'YES' if one of the profiles' 'name' properties equals the 'name' passed into this method */
for (OSCProfile *profile in profiles) {
if ([profile.name isEqualToString:name]) {
return profile;
}
}
return nil;
}
- (OnScreenButtonState *)unarchiveButtonStateEncoded:(NSData *)data {
OnScreenButtonState* buttonState;
buttonState = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[NSString class], [OnScreenButtonState class], [NSSet class], [NSNumber class], nil]
fromData:data
error:nil];
return buttonState;
}
@end
@@ -418,8 +418,8 @@ class OSCProfilesManager: NSObject {
func normalizeWidgetPosition(_ position: CGPoint) -> CGPoint {
var normalizedPosition = position
let originalPosition = position
if position.x > 1.0, position.y > 1.0 {
// let originalPosition = position
if abs(position.x) > 1.0, abs(position.y) > 1.0 {
normalizedPosition.x = position.x / Self.layoutViewBounds.size.width
normalizedPosition.y = position.y / Self.layoutViewBounds.size.height
}
@@ -430,7 +430,7 @@ class OSCProfilesManager: NSObject {
private func denormalizeWidgetPosition(_ position: CGPoint) -> CGPoint {
var denormalizedPosition = position
if position.x < 1.0, position.y < 1.0 {
if abs(position.x) < 2.01, abs(position.y) < 2.01 {
denormalizedPosition.x = position.x * Self.layoutViewBounds.size.width
denormalizedPosition.y = position.y * Self.layoutViewBounds.size.height
}
+2 -2
View File
@@ -404,8 +404,8 @@ import CoreMotion
}
private func clearGyroInput(interruptNonGyroInput:Bool){
// guard let onScreenControls = onScreenControls else { return }
guard ControllerUtil.gamepadArrivalReported else { return }
if yawPitchToRightStick{
onScreenControls?.sendRightStickTouchPadEvent(rightStickPhysicalInputX+rightStickTouchInputX-yawBias, rightStickPhysicalInputY+rightStickTouchInputY-pitchBias)
}
+1 -1
View File
@@ -360,7 +360,7 @@ static float L3_Y;
}
- (CGPoint) denormalizeWidgetPosition:(CGPoint)position {
if(position.x < 1.0 && position.y < 1.0) {
if(position.x < 1.01 && position.y < 1.01) {
position.x = position.x * _view.bounds.size.width;
position.y = position.y * _view.bounds.size.height;
// NSLog(@"denormalizing position: %f, %f", position.x, position.y);
+81 -53
View File
@@ -61,11 +61,11 @@ import ObjectiveC.runtime
func alterAbsTouchDragWith(mouseButton:Int32)
func enablePencilHover()
func disablePencilHover()
func setAllowSingleTouchEnabled(_ enabled:Bool)
func handleDisableSingleTouchButtonUp()
func replaceBrush(shortcut:String)
func replaceEraser(shortcut:String)
func presentPressureCurveVC()
func toggleTouch(disabled:Bool)
func handleTouchDisableButtonUp()
func toggleGamepadOverlay(overlayEnabled:Bool)
@objc(magnifierMoveStreamViewWithTranslation:)
func magnifierMoveStreamView(translation: CGVector)
@@ -672,14 +672,15 @@ import ObjectiveC.runtime
self.hasTrackPoint = true
self.hasNonEditableLabel = (self.cmdString == "DISABLETOUCH"
|| self.cmdString == "GAMEPADOVERLAY"
|| self.cmdString == "DISABLETILT")
|| self.cmdString == "DISABLETILT"
|| self.cmdString == "NOSINGLETOUCH")
self.hasTemporaryLabel = CommandManager.velocityBasedTouchPads.contains(self.touchPadString) && (self.isMotionControlButton || self.buttonString == "NULL")
|| self.cmdString == "RSVPAD"
|| self.cmdString == "LSVPAD"
self.mouseButtonActionDelay = self.cmdString.contains("ABSMOUSEPAD") ? 0.005 : 0
self.standardFoldingInterval = widgetType == .touchPad ? 0.05 : 0.15;
self.standardFoldingInterval = widgetType == .touchPad ? 0.05 : 0.085;
self.isMagnifier = self.cmdString.contains("MAGNIFIER")
@@ -1053,13 +1054,21 @@ import ObjectiveC.runtime
if self.hasNonEditableLabel {
switch cmdString {
case "DISABLETOUCH":
self.nonEditableWidgetLabel = LocalizationHelper.localizedString(forKey: touchDisabledFLag ? "=EnableTouch" : "=DisableTouch" )
case "GAMEPADOVERLAY":
self.nonEditableWidgetLabel = LocalizationHelper.localizedString(forKey: OnScreenWidgetView.gamepadOverlayFLag ? "=GamepadOverlayOn" : "=GamepadOverlayOff" )
self.nonEditableWidgetLabel = OnScreenWidgetView.gamepadOverlayFLag ? "=GamepadOverlayOn".localized : "=GamepadOverlayOff".localized
case "DISABLETOUCH":
if let vc = StreamFrameViewController.sharedInstance() {
self.nonEditableWidgetLabel = vc.touchDisabled ? "=EnableTouch".localized : "=DisableTouch".localized
}
else {self.nonEditableWidgetLabel = "=DisableTouch".localized}
case "NOSINGLETOUCH":
if let vc = StreamFrameViewController.sharedInstance() {
self.nonEditableWidgetLabel = vc.singleTouchDisabled ? "=EnableSingleTouch".localized : "=DisableSingleTouch".localized
}
else {self.nonEditableWidgetLabel = "=DisableSingleTouch".localized}
case "DISABLETILT":
if let pencilHandler = PencilHandler.shared {
self.nonEditableWidgetLabel = LocalizationHelper.localizedString(forKey: pencilHandler.disableTilt ? "=enableTilt" : "=disableTilt" )
self.nonEditableWidgetLabel = pencilHandler.disableTilt ? "=enableTilt".localized : "=disableTilt".localized
}
else {self.nonEditableWidgetLabel = "=disableTilt".localized}
default:
@@ -1690,7 +1699,7 @@ import ObjectiveC.runtime
// legacy keyboard button combo connected by "+"
if !OnScreenWidgetView.editMode && self.cmdString.contains("+") && !self.cmdString.contains("-"){
if buttonMode == .movable, moveableButtonLongPressed() {return}
if buttonMode == .movable, firstTouchMoved {return}
if leaveNonSkillButtonAlone {return}
self.buttonDownVisualEffect()
if var autoReleaseComboButtons = CommandManager.shared.extractAutoReleaseButtonStrings(from: self.cmdString) {
@@ -1874,7 +1883,7 @@ import ObjectiveC.runtime
self.onScreenControls?.sendRightStickTouchPadEvent(stickOffsetVector.dx, stickOffsetVector.dy)
}
self.motionHandler?.mixOnScreenRightStickAndGyroInput(x: targetX, y: targetY)
if !OnScreenWidgetView.gamepadArrivalReported {OnScreenWidgetView.gamepadArrivalReported = true}
if !ControllerUtil.gamepadArrivalReported {ControllerUtil.gamepadArrivalReported = true}
}
private func sendLeftStickTouchPadEvent(weightedTouchX:CGFloat, weightedTouchY:CGFloat, circulate:Bool=false){
@@ -1889,7 +1898,7 @@ import ObjectiveC.runtime
self.onScreenControls?.sendLeftStickTouchPadEvent(stickOffsetVector.dx, stickOffsetVector.dy)
}
self.motionHandler?.mixOnScreenLeftStickAndGyroInput(x: targetX, y: targetY)
if !OnScreenWidgetView.gamepadArrivalReported {OnScreenWidgetView.gamepadArrivalReported = true}
if !ControllerUtil.gamepadArrivalReported {ControllerUtil.gamepadArrivalReported = true}
}
private func sendLeftTriggerTouchPadEvent(inputY: CGFloat){
@@ -1963,7 +1972,7 @@ import ObjectiveC.runtime
DispatchQueue.global(qos: .userInteractive).async {
if CommandManager.oscButtonMappings.keys.contains(realButtonString) {
self.sendOscButtonDownEvent(oscString: realButtonString)
if !OnScreenWidgetView.gamepadArrivalReported {OnScreenWidgetView.gamepadArrivalReported = true}
if !ControllerUtil.gamepadArrivalReported {ControllerUtil.gamepadArrivalReported = true}
}
if CommandManager.keyboardButtonMappings.keys.contains(realButtonString) {
LiSendKeyboardEvent(CommandManager.keyboardButtonMappings[realButtonString]!,Int8(KEY_ACTION_DOWN), 0)
@@ -2249,8 +2258,10 @@ import ObjectiveC.runtime
if self.widgetType == WidgetTypeEnum.button && (self.buttonMode == .movable || self.temporarilyMovable) {
movableButtonReleased = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
OnScreenWidgetView.updateStreamViewGuidelines(for: self)
if false {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
OnScreenWidgetView.updateStreamViewGuidelines(for: self)
}
}
}
}
@@ -2341,8 +2352,10 @@ import ObjectiveC.runtime
layoutUpdateDelegate?.updateGuidelinesForOnScreenWidget(self)
}
else {
if self.widgetType == .button {superview?.bringSubviewToFront(self)}
OnScreenWidgetView.updateStreamViewGuidelines(for: self)
// if self.widgetType == .button {superview?.bringSubviewToFront(self)}
if false {
OnScreenWidgetView.updateStreamViewGuidelines(for: self)
}
}
}
@@ -2486,7 +2499,10 @@ import ObjectiveC.runtime
if (self.buttonMode == .movable || self.temporarilyMovable) && self.moveableButtonLongPressed() {
if let touch = touches.first {
CATransaction.begin()
CATransaction.setDisableActions(true)
self.moveByTouch(touch: touch)
CATransaction.commit()
}
}
}
@@ -2825,10 +2841,10 @@ import ObjectiveC.runtime
switch self.motionControlButtonString {
case "GYRO":
self.motionHandler?.startMotionControlByOnScreenButton(self, yawFactor: yawFactor, pitchFactor: pitchFactor, rollFactor: rollFactor)
if !OnScreenWidgetView.gamepadArrivalReported {OnScreenWidgetView.gamepadArrivalReported = oscProfile.mapGyroTo == .mapGyroToControllerStick}
if !ControllerUtil.gamepadArrivalReported {ControllerUtil.gamepadArrivalReported = oscProfile.mapGyroTo == .mapGyroToControllerStick}
case "GYROPAUSE":
self.motionHandler?.stopMotionUpdate(interruptNoneGyroInput:false)
if !OnScreenWidgetView.gamepadArrivalReported {OnScreenWidgetView.gamepadArrivalReported = oscProfile.mapGyroTo == .mapGyroToControllerStick}
if !ControllerUtil.gamepadArrivalReported {ControllerUtil.gamepadArrivalReported = oscProfile.mapGyroTo == .mapGyroToControllerStick}
break
case "ACCEL":
break
@@ -2888,9 +2904,6 @@ import ObjectiveC.runtime
case "PENCILHOVER":
if !self.isPencilProEnabled() {break}
self.functionalWidgetDelegate?.enablePencilHover()
case "NOSINGLETOUCH":
if !self.isPencilProEnabled() {break}
self.functionalWidgetDelegate?.setAllowSingleTouchEnabled(false)
default:
break
}
@@ -2898,29 +2911,24 @@ import ObjectiveC.runtime
private var movableButtonReleased:Bool = true
private func moveableButtonLongPressed() -> Bool{
return !movableButtonReleased && CACurrentMediaTime() - self.touchTapTimeStamp > 0.3
return !movableButtonReleased && CACurrentMediaTime() - self.touchTapTimeStamp > 0.05
}
private var singleTouchEnabled:Bool = true
private func handleFunctionalButtonUp(event: UIEvent? = nil){
// print("handleFunctionalButtonUp \(self.widgetLabel), event Empty: \(String(describing: event)), \(CACurrentMediaTime())")
if autoDockIsDocked {return}
if firstTouchMoved {return}
/*
if buttonMode == .movable {
if moveableButtonLongPressed() && !UITouchUtil.touches(in: self, from: event).isEmpty {return}
switch self.functionalButtonString {
// case "FOLDER":
// self.folded = !self.folded
// OnScreenWidgetView.set(folded: self.folded, for: self)
case "NOSINGLETOUCH":
if !self.isPencilProEnabled() {break}
singleTouchEnabled = !singleTouchEnabled
self.functionalWidgetDelegate?.setAllowSingleTouchEnabled(singleTouchEnabled)
return
default:
break
}
}
} */
switch self.functionalButtonString {
case "FOLDER":
@@ -2962,16 +2970,28 @@ import ObjectiveC.runtime
self.functionalWidgetDelegate?.bringUpSoftKeyboard()
case "ABSTCHDRAG":
self.functionalWidgetDelegate?.alterAbsTouchDragWith(mouseButton:BUTTON_LEFT)
case "DISABLETOUCH":
self.handleTouchDisableButtonUp()
case "GAMEPADOVERLAY":
self.gamepadOverlayButtonUp()
case "PENCILHOVER":
if !self.isPencilProEnabled() {break}
self.functionalWidgetDelegate?.disablePencilHover()
case "DISABLETOUCH":
if let streamFrameVC = StreamFrameViewController.sharedInstance() {
streamFrameVC.touchDisabled = !streamFrameVC.touchDisabled
self.functionalWidgetDelegate?.handleTouchDisableButtonUp()
}
case "NOSINGLETOUCH":
if !self.isPencilProEnabled() {break}
self.functionalWidgetDelegate?.setAllowSingleTouchEnabled(true)
if let streamFrameVC = StreamFrameViewController.sharedInstance() {
streamFrameVC.singleTouchDisabled = !streamFrameVC.singleTouchDisabled
self.functionalWidgetDelegate?.handleDisableSingleTouchButtonUp()
}
case "DISABLETILT":
if !self.isPencilProEnabled() {break}
if let pencilHandler = PencilHandler.shared {
pencilHandler.disableTilt = !pencilHandler.disableTilt
}
case "BRUSH":
if !self.isPencilProEnabled() {break}
var brushShortcut = self.cmdString.replacingOccurrences(of: "BRUSH+", with: "")
@@ -2982,12 +3002,6 @@ import ObjectiveC.runtime
var eraserShortcut = self.cmdString.replacingOccurrences(of: "ERASER+", with: "")
eraserShortcut = eraserShortcut.replacingOccurrences(of: "ERASER", with: "")
self.functionalWidgetDelegate?.replaceEraser(shortcut: eraserShortcut)
case "DISABLETILT":
if !self.isPencilProEnabled() {break}
if let pencilHandler = PencilHandler.shared {
pencilHandler.disableTilt = !pencilHandler.disableTilt
self.setupAtrributedText()
}
case "PRESSURECURVE":
if ["com.voidlink.iOS"
, "com.voidlinkextreme.iOS"
@@ -2998,15 +3012,12 @@ import ObjectiveC.runtime
default:
break
}
if self.hasNonEditableLabel {
self.setupAtrributedText()
}
}
private var touchDisabledFLag:Bool = false
private func handleTouchDisableButtonUp(){
touchDisabledFLag = !touchDisabledFLag
self.setupAtrributedText()
self.functionalWidgetDelegate?.toggleTouch(disabled: touchDisabledFLag)
}
@objc static var gamepadOverlayFLag:Bool = false
private func gamepadOverlayButtonUp(){
self.relocatedDuringStreaming = true
@@ -3806,10 +3817,20 @@ import ObjectiveC.runtime
@objc static var enableFolderAnimation:Bool = true
private static func setCollection(folded:Bool, for folder:OnScreenWidgetView, exception:OnScreenWidgetView? = nil, recursive:Bool = false, isExclusiveFolderAction:Bool = false) {
guard folder.isFolder else {return}
if !OnScreenWidgetView.enableFolderAnimation, folder.parentSequence == -1 {
folder.buttonDownVisualEffect()
folder.buttonDownVisualEffectLayer.isHidden = false
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
folder.buttonDownVisualEffectLayer.isHidden = true
}
}
// guard folder.folded != hidden else { return }
folder.folded = folded
folder.setupAtrributedText()
folder.reverseColorPhase(reversed: !folder.folded)
if folded {
for sequence in folder.sequenceSet {
guard let widget = OnScreenWidgetView.mapping[sequence], widget != exception else {continue}
@@ -3897,8 +3918,16 @@ import ObjectiveC.runtime
}
}
@objc static func disableFolderAnimation(for duration: TimeInterval){
enableFolderAnimation = false
DispatchQueue.global().asyncAfter(deadline: .now() + duration) {
enableFolderAnimation = true
}
}
@objc static func set(folded:Bool, for folder:OnScreenWidgetView) { // folder综合逻辑
guard folder.isFolder else {return}
if !folded {
OnScreenWidgetView.deepestButton = OnScreenWidgetView.getDeepestButton()
}
@@ -4129,7 +4158,6 @@ import ObjectiveC.runtime
return OnScreenWidgetView.mapping.keys.max() ?? -1
}
@objc static var gamepadArrivalReported: Bool = false
override func didMoveToSuperview() {
super.didMoveToSuperview()
OnScreenWidgetView.installAutoDockIfNeeded()
@@ -4141,14 +4169,14 @@ import ObjectiveC.runtime
label.alpha = 1
autoDockRestoreOriginalAlpha()
if self.motionControlButtonString == "GYRO" {
if OnScreenWidgetView.gamepadArrivalReported {self.motionHandler?.stopMotionUpdate(interruptNoneGyroInput: true)}
if ControllerUtil.gamepadArrivalReported {self.motionHandler?.stopMotionUpdate(interruptNoneGyroInput: true)}
self.motionHandler?.motionStarter = nil
}
if self.motionControlButtonString == "ACCEL" {}
if self.motionControlButtonString == "MOTION" {}
if self.widgetType == WidgetTypeEnum.button && !OnScreenWidgetView.editMode {
if OnScreenWidgetView.gamepadArrivalReported {self.sendComboButtonsUpEvent(comboStrings: self.comboButtonStrings)}
if ControllerUtil.gamepadArrivalReported {self.sendComboButtonsUpEvent(comboStrings: self.comboButtonStrings)}
self.functionalWidgetDelegate?.alterAbsTouchDragWith(mouseButton:BUTTON_LEFT)
}
buttonDownVisualEffectLayer.removeFromSuperlayer()
@@ -4167,7 +4195,7 @@ import ObjectiveC.runtime
stickWheelLayer.removeFromSuperlayer()
stickWheelLayerSmall.removeFromSuperlayer()
self.inertialScroller.timer?.clean()
if OnScreenWidgetView.gamepadArrivalReported {
if ControllerUtil.gamepadArrivalReported {
self.clearLeftStickTouchPadFlag()
self.clearRightStickTouchPadFlag()
}
@@ -4255,7 +4283,7 @@ import ObjectiveC.runtime
}
deinit {
print("onScreenWidgetView deinit \(self.widgetLabel))")
// print("onScreenWidgetView deinit \(self.widgetLabel))")
}
}
+59 -7
View File
@@ -25,7 +25,7 @@ import UIKit
private var manualHoverFlag: Bool = false
@objc static var hoverSupported: Bool = false
// @objc static private(set) var autoHoverTermination: Bool = false
@objc static private(set) var hoverMode: PencilHoverMode = .HoverPencil
@objc static private(set) var pencilAndHoverMode: PencilAndHoverMode = .pencilOnly
private(set) var pencilProEnabled: Bool = false
private var isFirstMove: Bool = false
private var strokeSampleIndex: Int32 = 0
@@ -105,7 +105,7 @@ import UIKit
}
// PencilHandler.autoHoverTermination = selectedProfile.autoPencilHoverTermination
PencilHandler.hoverMode = selectedProfile.pencilHoverMode
PencilHandler.pencilAndHoverMode = selectedProfile.pencilAndHoverMode
pressureCurveEnabled = selectedProfile.pressureCurveEnabled
@@ -151,6 +151,12 @@ import UIKit
PencilHandler.isDrawing = true
// isFirstMove = true
strokeSampleIndex = 0
guard PencilHandler.pencilAndHoverMode == .pencilOnly || PencilHandler.pencilAndHoverMode == .hoverDisabled else {
handleNonPencilModes(touches)
return
}
for touch in touches {
let coalesced = event.coalescedTouches(for: touch) ?? []
_ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch])
@@ -159,6 +165,12 @@ import UIKit
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let event = event else { return }
guard PencilHandler.pencilAndHoverMode == .pencilOnly || PencilHandler.pencilAndHoverMode == .hoverDisabled else {
handleNonPencilModes(touches)
return
}
for touch in touches {
let coalesced = event.coalescedTouches(for: touch) ?? []
_ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch])
@@ -167,6 +179,12 @@ import UIKit
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let event = event else { return }
guard PencilHandler.pencilAndHoverMode == .pencilOnly || PencilHandler.pencilAndHoverMode == .hoverDisabled else {
handleNonPencilModes(touches)
return
}
for touch in touches {
let coalesced = event.coalescedTouches(for: touch) ?? []
_ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch])
@@ -176,6 +194,34 @@ import UIKit
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
self.touchesEnded(touches, with: event)
}
private func handleNonPencilModes(_ touches: Set<UITouch>) {
guard let touch = touches.first else { return }
let location = touch.location(in: streamView)
let normalizedLocation = self.getNormalizedLocation(point: location)
if let streamView = streamView as? StreamView {
switch touch.phase {
case .began where PencilHandler.pencilAndHoverMode == .pencilToMouse:
streamView.updateCursorLocation(location, isMouse: false)
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_PRESS), BUTTON_LEFT)
case .began where PencilHandler.pencilAndHoverMode == .pencilToTouch:
LiSendTouchEvent(UInt8(LI_TOUCH_EVENT_DOWN), 666666, Float(normalizedLocation.x), Float(normalizedLocation.y), Float((touch.force/touch.maximumPossibleForce)/sin(touch.altitudeAngle)), 0, 0, getRotation(fromAzimuthAngle: Float(touch.azimuthAngle(in: streamView))))
case .moved where PencilHandler.pencilAndHoverMode == .pencilToMouse:
streamView.updateCursorLocation(location, isMouse: false)
case .moved where PencilHandler.pencilAndHoverMode == .pencilToTouch:
LiSendTouchEvent(UInt8(LI_TOUCH_EVENT_MOVE), 666666, Float(normalizedLocation.x), Float(normalizedLocation.y), Float((touch.force/touch.maximumPossibleForce)/sin(touch.altitudeAngle)), 0, 0, getRotation(fromAzimuthAngle: Float(touch.azimuthAngle(in: streamView))))
case .ended where PencilHandler.pencilAndHoverMode == .pencilToMouse,
.cancelled where PencilHandler.pencilAndHoverMode == .pencilToMouse:
streamView.updateCursorLocation(location, isMouse: false)
LiSendMouseButtonEvent(CChar(BUTTON_ACTION_RELEASE), BUTTON_LEFT)
case .ended where PencilHandler.pencilAndHoverMode == .pencilToTouch,
.cancelled where PencilHandler.pencilAndHoverMode == .pencilToTouch:
LiSendTouchEvent(UInt8(LI_TOUCH_EVENT_UP), 666666, Float(normalizedLocation.x), Float(normalizedLocation.y), 0, 0, 0, 0)
default:
break
}
}
}
// MARK: - Core Logic
@@ -229,7 +275,15 @@ import UIKit
func getTilt(fromAltitudeAngle altitudeAngle: Float) -> UInt8 {
let altitudeDegs = abs(Int16(altitudeAngle * (180.0 / .pi)))
return disableTilt ? 0 : UInt8(90 - min(90, Int(altitudeDegs)))
let tilt = disableTilt ? 0 : UInt8(90 - min(90, Int(altitudeDegs)))
return tilt
}
private func getNormalizedLocation(point: CGPoint) -> CGPoint {
let location = self.adjustCoordinatesForVideoArea(point: point)
let videoSize = self.getVideoAreaSize()
let normalizedLocation = CGPoint(x: location.x/videoSize.width, y: location.y/videoSize.height)
return normalizedLocation
}
var previousForce: Float = 0
@@ -250,9 +304,7 @@ import UIKit
.applying(CGAffineTransform(translationX: pencilTipOffset.x, y: pencilTipOffset.y))
let azimuth = touch.azimuthAngle(in: streamView)
let altitude = touch.altitudeAngle
let location = self.adjustCoordinatesForVideoArea(point: point)
let videoSize = self.getVideoAreaSize()
let normalizedLocation = CGPoint(x: location.x/videoSize.width, y: location.y/videoSize.height)
let normalizedLocation = self.getNormalizedLocation(point: point)
var force = Float(touch.force/touch.maximumPossibleForce)/sin(Float(altitude))
force = (self.pencilTickEnabled && force == 0) ? previousForce : force
@@ -332,7 +384,7 @@ import UIKit
if eventType == UInt8(LI_TOUCH_EVENT_UP) {
PencilHandler.isDrawing = false
if PencilHandler.hoverMode == .HoverDisabled || !PencilHandler.hoverSupported {
if PencilHandler.pencilAndHoverMode == .hoverDisabled || !PencilHandler.hoverSupported {
LiSendPenEvent(UInt8(LI_TOUCH_EVENT_HOVER), UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), 0, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude)))
DispatchQueue.global().asyncAfter(deadline: .now() + 0.0086){
if !PencilHandler.isDrawing {
+24 -13
View File
@@ -73,7 +73,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
NSTimer* interactionTimer;
BOOL hasUserInteracted;
NSDictionary<NSString *, NSNumber *> *dictCodes;
CustomTapGestureRecognizer *keyboardToggleRecognizer;
UIPanGestureRecognizer *discreteMouseWheelRecognizer;
@@ -236,6 +236,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
case NativeTouch:
keyboardToggleRecognizer.immediateTriggering = false;
self->touchHandler = [[NativeTouchHandler alloc] initWithView:self settings:settings profile:profile];
[(NativeTouchHandler* )touchHandler setAllowSingleTouchEnabled:!_streamFrameVC.singleTouchDisabled];
break;
case NativeTouchOnly:
keyboardToggleRecognizer.immediateTriggering = false;
@@ -254,11 +255,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
self->touchHandler = nil;
keyboardToggleRecognizer.immediateTriggering = false;
break;
default:
break;
}
sessionTouchHandler = touchHandler;
if(_streamFrameVC.touchDisabled) touchHandler = nil;
}
- (void)refreshKeyboardToggleRecognizer:(uint8_t)numberOfTouches{
@@ -619,7 +620,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
}
- (CGPoint)denormalizeWidgetPosition:(CGPoint)position {
if(position.x < 1.0 && position.y < 1.0){
if(position.x < 2.01 && position.y < 2.01){
position.x = position.x * _streamFrameTopLayerView.bounds.size.width;
position.y = position.y * _streamFrameTopLayerView.bounds.size.height;
}
@@ -691,10 +692,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
self->oscProfileMan = [OSCProfilesManager sharedManager:self->_streamFrameTopLayerView.bounds];
if(!profile){
NSLog(@"reloadOnScreenWidgets in streamview %d", reloadWidgets);
profile = [self->oscProfileMan getSelectedProfile]; //returns the currently selected OSCProfile
}
NSLog(@"reloadOnScreenWidgets in streamview %d", reloadWidgets);
dispatch_async(dispatch_get_main_queue(), ^{
MotionHandler* motionHandler = [MotionHandler sharedWithProfile:profile];
@@ -718,6 +720,11 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
// remove all keyboard widget views first
[self clearOnScreenWidgets];
self->_streamFrameVC.touchDisabled = false;
self->_streamFrameVC.singleTouchDisabled = false;
PencilHandler* pencilHandler = [PencilHandler shared];
if(pencilHandler) pencilHandler.disableTilt = false;
bool sequenceGenerated = false;
bool hasMovableWidget = false;
@@ -767,6 +774,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
widgetView.minStickOffset = buttonState.minStickOffset;
widgetView.dWheelWalkModeThreshold = buttonState.walkModeThreshold;
widgetView.buttonMode = buttonState.buttonMode;
if([widgetView.cmdString isEqualToString:@"NOSINGLETOUCH"]) widgetView.buttonMode = movable;
widgetView.sprintKeyActionType = buttonState.sprintKeyActionType;
widgetView.sprintKeyThreshold = buttonState.sprintKeyThreshold;
widgetView.walkKeyActionType = buttonState.walkKeyActionType;
@@ -999,7 +1007,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
});
}
CGPoint location = [self adjustCoordinatesForVideoArea:[gesture locationInView:self]];
CGPoint originalLocation = [gesture locationInView:self];
CGPoint location = [self adjustCoordinatesForVideoArea:originalLocation];
NSLog(@" location %f, %f", location.x, location.y);
PencilHandler* handler = PencilHandler.shared;
location = CGPointApplyAffineTransform(location, CGAffineTransformMakeTranslation(handler.pencilTipOffset.x, handler.pencilTipOffset.y));
@@ -1023,19 +1033,20 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
dispatch_after(0, dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE,0), ^{// Code to execute after the delay
if(PencilHandler.isDrawing) return;
switch (PencilHandler.hoverMode) {
case HoverPencil:
if(PencilHandler.isDrawing && PencilHandler.pencilAndHoverMode == pencilOnly && PencilHandler.pencilAndHoverMode == hoverDisabled) return;
switch (PencilHandler.pencilAndHoverMode) {
case pencilOnly:
LiSendPenEvent(type, LI_TOOL_TYPE_PEN, 0, location.x / videoSize.width, location.y / videoSize.height, distance, 0.0f, 0.0f, rotationAngle, tiltAngle);
break;
case HoverMouse:
[self updateCursorLocation:location isMouse:YES];
case pencilToMouse:
if(gesture.state != UIGestureRecognizerStateEnded) [self updateCursorLocation:originalLocation isMouse:NO];
break;
case HoverDisabled:
case hoverDisabled:
break;
case HoverBoth:
case pencilToTouch:
/*
LiSendPenEvent(type, LI_TOOL_TYPE_PEN, 0, location.x / videoSize.width, location.y / videoSize.height, distance, 0.0f, 0.0f, rotationAngle, tiltAngle);
[self updateCursorLocation:location isMouse:YES];
[self updateCursorLocation:location isMouse:YES]; */
break;
default:
break;
+186 -157
View File
@@ -1121,6 +1121,35 @@
}
}
},
"=DisableSingleTouch" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "🚫 SingleTouch"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "🚫 单指触摸"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "🚫 單指觸摸"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "🚫 單指觸摸"
}
}
}
},
"=disableTilt" : {
"extractionState" : "manual",
"localizations" : {
@@ -1295,6 +1324,35 @@
}
}
},
"=EnableSingleTouch" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "🟢 SingleTouch"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "🟢 单指触摸"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "🟢 單指觸摸"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "🟢 單指觸摸"
}
}
}
},
"=enableTilt" : {
"extractionState" : "manual",
"localizations" : {
@@ -2455,35 +2513,6 @@
}
}
},
"=noSingleTouch" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "🚫SingleTouch"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "🚫单指触摸"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "🚫單指觸摸"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "🚫單指觸摸"
}
}
}
},
"=null" : {
"extractionState" : "manual",
"localizations" : {
@@ -10149,35 +10178,6 @@
}
}
},
"hoverModeStackTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "When “both” is selected, you’ll get flickering cursor on host.\nThis function is available without purchasing [Drawing Toolkit]."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "当选择“同时悬停”时,PC端的光标将会闪烁。\n此功能是Pencil基础功能的一部分,不属于Drawing Toolkit。 "
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "當選擇「同時懸停」時,PC 端的游標將會閃爍。\n此功能為 Pencil 基礎功能的一部分,不屬於 Drawing Toolkit。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "當選擇「同時懸停」時,PC 端的游標將會閃爍。\n此功能為 Pencil 基礎功能的一部分,不屬於 Drawing Toolkit。"
}
}
}
},
"I'm an artist" : {
"extractionState" : "manual",
"localizations" : {
@@ -13303,6 +13303,52 @@
}
}
},
"Pencil hover" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 悬停"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 懸浮"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 懸浮"
}
}
}
},
"Pencil Pro Pack" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 专业套装"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 專業套裝"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 專業套裝"
}
}
}
},
"Pencil Tip Offset" : {
"extractionState" : "manual",
"localizations" : {
@@ -13361,52 +13407,6 @@
}
}
},
"Pencil hover" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 悬停"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 懸浮"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 懸浮"
}
}
}
},
"Pencil Pro Pack" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 专业套装"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 專業套裝"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pencil 專業套裝"
}
}
}
},
"pencilKeyboardCmdURL" : {
"extractionState" : "manual",
"localizations" : {
@@ -13436,6 +13436,35 @@
}
}
},
"pencilModeStackTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "This function is available without purchasing [Drawing Toolkit]."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "此功能是Pencil基础功能的一部分,不属于Drawing Toolkit。 "
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "此功能為 Pencil 基礎功能的一部分,不屬於 Drawing Toolkit。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "此功能為 Pencil 基礎功能的一部分,不屬於 Drawing Toolkit。"
}
}
}
},
"PencilProPackDescription" : {
"extractionState" : "manual"
},
@@ -19123,6 +19152,35 @@
}
}
},
"X Offset" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "X Offset"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "X 偏移"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "X 偏移"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "X 偏移"
}
}
}
},
"X1" : {
"extractionState" : "manual",
"localizations" : {
@@ -19169,58 +19227,6 @@
}
}
},
"X Offset" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "X Offset"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "X 偏移"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "X 偏移"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "X 偏移"
}
}
}
},
"Yaw factor: %.2f" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "偏航系数: %.2f"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "偏航係數: %.2f"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "偏航係數: %.2f"
}
}
}
},
"Y Offset" : {
"extractionState" : "manual",
"localizations" : {
@@ -19250,6 +19256,29 @@
}
}
},
"Yaw factor: %.2f" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "偏航系数: %.2f"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "偏航係數: %.2f"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "偏航係數: %.2f"
}
}
}
},
"Yes" : {
"extractionState" : "manual",
"localizations" : {
@@ -19359,4 +19388,4 @@
}
},
"version" : "1.1"
}
}
@@ -306,6 +306,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
selectedWidget = nil
widgetPanelStoredCenter = widgetPanelStack.center
setupWidgetPanel()
// print("loadingMode \(profileSelectorLoadingMode)")
profileRefresh()
if !toolbarStackView.isHidden {
GenericUtils.handleLayoutToolTip(in: self)
@@ -330,7 +331,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@objc func dummytest() {}
private func denormalizeWidgetPosition(_ position: CGPoint) -> CGPoint {
guard position.x < 1.0, position.y < 1.0 else { return position }
guard abs(position.x) < 2.01, abs(position.y) < 2.01 else { return position }
return CGPoint(x: position.x * view.bounds.width, y: position.y * view.bounds.height)
}
@@ -358,8 +359,10 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
}
@objc func reloadOnScreenWidgetViews() {
if self.profileSelectorLoadingMode == .selectProfileFromMainFrame { return }
// if self.profileSelectorLoadingMode == .selectProfileFromMainFrame { return }
guard self.profileSelectorLoadingMode == .selectProfileFromLayoutTool || self.profileSelectorLoadingMode == .selectProfileFromStreamView else { return }
OnScreenWidgetView.isTweakingHighlight = false
OnScreenWidgetView.editMode = true
@@ -367,7 +370,20 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
self.hideStickIndicators()
self.clearOnScreenWidgets()
guard let oscProfile = self.profilesManager?.getSelectedProfile() else { return }
var oscProfile: OSCProfile?
if let profileSelector = self.profileSelectorViewController, profileSelector.profiles.count > 0 {
oscProfile = profileSelector.profiles[profileSelector.selectedProfileIndex] as? OSCProfile
}
else {
oscProfile = self.profilesManager?.getSelectedProfile()
}
guard let oscProfile = oscProfile else { return }
if self.profileSelectorLoadingMode == .selectProfileFromStreamView, oscProfile.name == "Default" {
OnScreenWidgetView.disableFolderAnimation(for: 1)
}
if self.profileSelectorLoadingMode == .selectProfileFromStreamView || self.profileSelectorLoadingMode == .pickProfile {
NotificationCenter.default.post(name: Notification.Name("GameProfileSelectedNotification"), object: oscProfile)
@@ -529,16 +545,18 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
profileSelectorViewController?.layoutViewBounds = view.bounds
profileSelectorViewController?.needToUpdateOscLayoutTVC = { [weak self] in
guard let self else { return }
if !loadJustTapped {
// if !loadJustTapped {
self.reloadOnScreenWidgetViews()
}
// }
loadJustTapped = false
self.profileSelectorViewController?.currentOSCButtonLayers = self.layoutOSC.oscButtonLayerPool
}
reloadOnScreenWidgetViews()
if profileSelectorLoadingMode == .selectProfileFromLayoutTool {
reloadOnScreenWidgetViews()
}
}
@objc var profileSelectorLoadingMode: ProfileSelectorLoadingMode = .selectProfile
@objc var profileSelectorLoadingMode: ProfileSelectorLoadingMode = .selectProfileFromLayoutTool
@objc(presentProfileSelectorWithLoadingMode:)
func presentProfileSelector(with loadingModeRawValue: Int) {
@@ -562,18 +580,18 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
if loadingMode != .pickProfileData {selectedWidget = nil}
let controller = ProfileSelectorViewController()
controller.layoutViewBounds = view.bounds
controller.needToUpdateOscLayoutTVC = { [weak self] in
guard let self else { return }
if loadingMode == .selectProfile || loadingMode == .selectProfileFromStreamView || loadingMode == .pickProfile {
self.reloadOnScreenWidgetViews()
}
}
controller.currentOSCButtonLayers = layoutOSC.oscButtonLayerPool
controller.modalPresentationStyle = .overCurrentContext
controller.loadingMode = loadingMode
controller.pickedProfileDataHandler = pickedProfileDataHandler
widgetPanelStack.isHidden = true
profileSelectorViewController = controller
controller.needToUpdateOscLayoutTVC = { [weak self] in
guard let self else { return }
if loadingMode == .selectProfileFromLayoutTool || loadingMode == .selectProfileFromStreamView {
self.reloadOnScreenWidgetViews()
}
}
present(controller, animated: animated)
}
@@ -581,7 +599,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@IBAction func loadTapped(_ sender: Any?) {
// saveTapped(nil)
loadJustTapped = true
presentProfileSelector(with: .selectProfile)
presentProfileSelector(with: .selectProfileFromLayoutTool)
}
@IBAction func importFromOtherButtonTapped(_ sender: Any?) {
@@ -659,7 +677,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
super.viewWillTransition(to: size, with: coordinator)
viewWillBeResized = true
hideStickIndicators()
if self.profileSelectorLoadingMode == .selectProfile {
if self.profileSelectorLoadingMode == .selectProfileFromLayoutTool {
let oldSize = view.bounds.size
let scaleX = size.width / oldSize.width
@@ -842,7 +860,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
private func refreshPanelForSelectedWidget(_ widgetView: OnScreenWidgetView) {
// hideStickIndicators()
if OnScreenWidgetView.gamepadArrivalReported {clearSickInput()}
if ControllerUtil.gamepadArrivalReported {clearSickInput()}
enableCommonWidgetTools()
widgetViewSelected = true
controllerLayerSelected = false
@@ -1587,7 +1605,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
}
private func clearSickInput() {
if selectedWidget != nil && widgetViewSelected && OnScreenWidgetView.gamepadArrivalReported {
if selectedWidget != nil && widgetViewSelected && ControllerUtil.gamepadArrivalReported {
OnScreenControls.shared()?.clearLeftStickTouchPadFlag()
OnScreenControls.shared()?.clearRightStickTouchPadFlag()
}
@@ -1632,7 +1650,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@objc private func handleProfileSelectorDismiss() {
switch profileSelectorLoadingMode {
case .selectProfile:
case .selectProfileFromLayoutTool:
if profileSelectorViewController?.loadingMode != .pickProfileData {
setupWidgetPanel()
}
@@ -1721,7 +1739,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
}
private func setupWidgetPanel() {
widgetPanelStack.isHidden = profileSelectorLoadingMode != .selectProfile
widgetPanelStack.isHidden = profileSelectorLoadingMode != .selectProfileFromLayoutTool
tipTitleLabel.textAlignment = .left
tipTitleLabel.contentMode = .top
tipTitleLabel.lineBreakMode = .byWordWrapping
@@ -274,7 +274,7 @@ private extension UInt64 {
}
@objc enum ProfileSelectorLoadingMode: Int {
case selectProfile
case selectProfileFromLayoutTool
case selectProfileFromStreamView
case selectProfileFromMainFrame
case pickProfile
@@ -287,15 +287,15 @@ final class ProfileSelectorViewController: UIViewController, UICollectionViewDat
var currentFileOperation: FileOperation = .importOperation
private var currentExportScope: ProfileExportScope = .allProfiles
var needToUpdateOscLayoutTVC: (() -> Void)?
var loadingMode: ProfileSelectorLoadingMode = .selectProfile
var loadingMode: ProfileSelectorLoadingMode = .selectProfileFromLayoutTool
@nonobjc var pickedProfileDataHandler: ((OSCProfile) -> Void)?
weak var currentOSCButtonLayers: NSMutableSet?
var layoutViewBounds: CGRect = .zero
private var profilesManager: OSCProfilesManager!
private var horizontalConstraintsConfigured = false
private var profiles: NSMutableArray = []
private var selectedProfileIndex = 0
private(set) var profiles: NSMutableArray = []
private(set) var selectedProfileIndex = 0
private var profilesLoadGeneration = 0
private var profileCollectionView: UICollectionView!
private let contentView = UIView()
@@ -448,8 +448,9 @@ final class ProfileSelectorViewController: UIViewController, UICollectionViewDat
}
if profiles.count > 0 {
scrollToSelectedProfile(animated: true)
notifyProfileViewDidRefresh()
} else {
reloadProfilesAsync(scrollToSelected: true)
reloadProfilesAsync(scrollToSelected: true, notify: true)
}
if (loadingMode == .selectProfileFromMainFrame || loadingMode == .selectProfileFromStreamView)
@@ -748,7 +749,7 @@ final class ProfileSelectorViewController: UIViewController, UICollectionViewDat
if loadingMode != .selectProfileFromStreamView
&& loadingMode != .pickProfile
&& loadingMode != .pickProfileData
&& loadingMode != .selectProfile
&& loadingMode != .selectProfileFromLayoutTool
{
guard let selectedProfileIndex = validProfileIndex(selectedProfileIndex) else { return }
NotificationCenter.default.post(name: Notification.Name("GameProfileSelectedNotification"), object: self.profiles[selectedProfileIndex])
@@ -1189,7 +1190,7 @@ final class ProfileSelectorViewController: UIViewController, UICollectionViewDat
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if (loadingMode != .selectProfile
if (loadingMode != .selectProfileFromLayoutTool
&& loadingMode != .selectProfileFromMainFrame
&& loadingMode != .selectProfileFromStreamView
),
@@ -306,8 +306,8 @@
@property (weak, nonatomic) IBOutlet UIStackView *disablePencilSlideGestureStack;
@property (weak, nonatomic) IBOutlet UISwitch *disablePencilSlideGestureSwitch;
@property (weak, nonatomic) IBOutlet UIStackView *hoverModeStack;
@property (weak, nonatomic) IBOutlet UISegmentedControl *hoverModeSelector;
@property (weak, nonatomic) IBOutlet UIStackView *pencilModeStack;
@property (weak, nonatomic) IBOutlet UISegmentedControl *pencilModeSelector;
@@ -434,7 +434,7 @@ BOOL isCustomResolution(int resolutionSelected) {
[self.squeezeShortcutSwitch setOn:oscProfile.squeezeShorcutEnabled];
[self.pencilPausesNativeTouchSwitch setOn:oscProfile.pencilPausesNativeTouch];
[self.disablePencilSlideGestureSwitch setOn:oscProfile.disablePencilSlideGestures];
self.hoverModeSelector.selectedSegmentIndex = oscProfile.pencilHoverMode;
self.pencilModeSelector.selectedSegmentIndex = oscProfile.pencilAndHoverMode;
}
- (void)saveGameProfileConfigs{
@@ -472,7 +472,7 @@ BOOL isCustomResolution(int resolutionSelected) {
&& oscProfile.squeezeShorcutEnabled == self.squeezeShortcutSwitch.isOn
&& oscProfile.pencilPausesNativeTouch == self.pencilPausesNativeTouchSwitch.isOn
&& oscProfile.disablePencilSlideGestures == self.disablePencilSlideGestureSwitch.isOn
&& oscProfile.pencilHoverMode == self.hoverModeSelector.selectedSegmentIndex
&& oscProfile.pencilAndHoverMode == self.pencilModeSelector.selectedSegmentIndex
);
if(!configNotChanged){
@@ -499,12 +499,12 @@ BOOL isCustomResolution(int resolutionSelected) {
oscProfile.squeezeShorcutEnabled = self.squeezeShortcutSwitch.isOn;
oscProfile.pencilPausesNativeTouch = self.pencilPausesNativeTouchSwitch.isOn;
oscProfile.disablePencilSlideGestures = self.disablePencilSlideGestureSwitch.isOn;
oscProfile.pencilHoverMode = self.hoverModeSelector.selectedSegmentIndex;
oscProfile.pencilAndHoverMode = self.pencilModeSelector.selectedSegmentIndex;
[oscProfileMan replaceSelectedProfileWith:oscProfile overwriteDefault:YES];
if(PencilHandler.shared) [PencilHandler.shared setupPressureLUTWithProfile:oscProfile];
}
if(!leftStickMinOffsetSliderNotMoved || !rightStickMinOffsetSliderNotMoved || OnScreenWidgetView.gamepadArrivalReported){
if(!leftStickMinOffsetSliderNotMoved || !rightStickMinOffsetSliderNotMoved || ControllerUtil.gamepadArrivalReported){
if(OnScreenControls.shared){
[OnScreenControls.shared clearLeftStickTouchPadFlag];
[OnScreenControls.shared clearRightStickTouchPadFlag];
@@ -1087,9 +1087,9 @@ BOOL isCustomResolution(int resolutionSelected) {
self.squeezeShortcutStack.hasInfoTag = YES;
[self addSetting:self.squeezeShortcutStack ofId:@"squeezeShortcutStack" to:pencilSection];
self.hoverModeStack.isGameProfileSetting = YES;
self.hoverModeStack.hasInfoTag = YES;
[self addSetting:self.hoverModeStack ofId:@"hoverModeStack" to:pencilSection];
self.pencilModeStack.isGameProfileSetting = YES;
self.pencilModeStack.hasInfoTag = YES;
[self addSetting:self.pencilModeStack ofId:@"pencilModeStack" to:pencilSection];
self.pencilPausesNativeTouchStack.isGameProfileSetting = YES;
[self addSetting:self.pencilPausesNativeTouchStack ofId:@"pencilPausesNativeTouchStack" to:pencilSection];
@@ -1799,8 +1799,8 @@ BOOL isCustomResolution(int resolutionSelected) {
tipText = [LocalizationHelper localizedStringForKey:@"asyncFrameDequeueStackTip"];
showOnlineDocAction = false;
}
if([sender.superview.accessibilityIdentifier isEqualToString: @"hoverModeStack"]){
tipText = [LocalizationHelper localizedStringForKey:@"hoverModeStackTip"];
if([sender.superview.accessibilityIdentifier isEqualToString: @"pencilModeStack"]){
tipText = [LocalizationHelper localizedStringForKey:@"pencilModeStackTip"];
showOnlineDocAction = false;
}
if([sender.superview.accessibilityIdentifier isEqualToString: @"pencilTickStack"]){
@@ -3107,7 +3107,7 @@ BOOL isCustomResolution(int resolutionSelected) {
rightButtonCaptured = true;
if (@available(iOS 13.0, *)) {
NSLog(@"custom posistion local %d , stream: %d", currentSettings.customLocalRadialMenuButtonPosition.intValue, currentSettings.customStreamingRadialMenuButtonPosition.intValue);
// NSLog(@"custom posistion local %d , stream: %d", currentSettings.customLocalRadialMenuButtonPosition.intValue, currentSettings.customStreamingRadialMenuButtonPosition.intValue);
ControllerNavigator.localRadialMenuButton = (ControllerElement)currentSettings.localRadialMenuButton.intValue;
ControllerNavigator.customPositionForLocalRadialMenuButton = (ControllerElementPosition)currentSettings.customLocalRadialMenuButtonPosition.intValue;
@@ -3196,21 +3196,21 @@ BOOL isCustomResolution(int resolutionSelected) {
[self findDynamicLabelFromStack:(UIStackView*)sender.superview].text = [NSString stringWithFormat:@" %d ", (int16_t)sender.value];
if(settingsViewJustExpanded) return;
LiSendControllerEvent(0, 0, 0, _rollToLeftStickSwitch.isOn?sender.value:0, 0, _yawPitchToRightStickSwitch.isOn?sender.value:0, 0);
OnScreenWidgetView.gamepadArrivalReported = true;
ControllerUtil.gamepadArrivalReported = true;
}
- (void)leftStickMinOffsetSliderMoved:(UISlider* )sender{
[self findDynamicLabelFromStack:(UIStackView*)sender.superview].text = [NSString stringWithFormat:@" %d ", (int16_t)sender.value];
if(settingsViewJustExpanded) return;
LiSendControllerEvent(0, 0, 0, sender.value, 0, 0, 0);
OnScreenWidgetView.gamepadArrivalReported = true;
ControllerUtil.gamepadArrivalReported = true;
}
- (void)rightStickMinOffsetSliderMoved:(UISlider* )sender{
[self findDynamicLabelFromStack:(UIStackView*)sender.superview].text = [NSString stringWithFormat:@" %d ", (int16_t)sender.value];
if(settingsViewJustExpanded) return;
LiSendControllerEvent(0, 0, 0, 0, 0, sender.value, 0);
OnScreenWidgetView.gamepadArrivalReported = true;
ControllerUtil.gamepadArrivalReported = true;
}
- (void)invokeOscLayout{
@@ -4247,8 +4247,10 @@ BOOL isCustomResolution(int resolutionSelected) {
CGFloat settingsMenuOffset = _rememberFoldStateSwitch.isOn ? _scrollView.contentOffset.y : 0;
NSInteger height = self.mainFrameViewController.settingsExpandedInStreamView ? currentSettings.height.intValue : [self getChosenStreamHeight];
NSInteger width = self.mainFrameViewController.settingsExpandedInStreamView ? currentSettings.width.intValue : [self getChosenStreamWidth];
NSInteger height = self.mainFrameViewController.isStreaming ? currentSettings.height.intValue : [self getChosenStreamHeight];
NSInteger width = self.mainFrameViewController.isStreaming ? currentSettings.width.intValue : [self getChosenStreamWidth];
// NSLog(@"saveSettings aspectRatio %d, %ld, %ld",self.mainFrameViewController.isStreaming, width, height);
NSInteger framerate = [self getChosenFrameRate];
@@ -47,6 +47,9 @@
@property (nonatomic, assign) CGPoint streamViewMagnifierContentOffset;
@property (nonatomic, assign) CGFloat streamViewMagnifierZoomScale;
@property(nonatomic, assign) bool touchDisabled;
@property(nonatomic, assign) bool singleTouchDisabled;
+ (StreamFrameViewController *)sharedInstance;
@@ -41,6 +41,7 @@
@interface AVDisplayCriteria()
@property(readonly) int videoDynamicRange;
@property(readonly, nonatomic) float refreshRate;
- (id)initWithRefreshRate:(float)arg1 videoDynamicRange:(int)arg2;
@end
@@ -127,6 +128,7 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
MicHandler* micHandler;
MotionHandler *_motionHandler;
#else
UITapGestureRecognizer *_menuTapGestureRecognizer;
UITapGestureRecognizer *_menuDoubleTapGestureRecognizer;
@@ -857,12 +859,15 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
viewIsBeingResized = false;
_magnifierViewportInteractionActive = false;
_touchDisabled = false;
_singleTouchDisabled = false;
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES animated:YES];
[UIApplication sharedApplication].idleTimerDisabled = YES;
_settings = [[[DataManager alloc] init] getSettings]; //StreamFrameViewController retrieve the settings here.
_stageLabel = [[UILabel alloc] init];
@@ -898,9 +903,9 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
toolBoxViewController = [[ToolboxViewController alloc] init];
toolBoxViewController.specialEntryDelegate = self;
_isRestoringFromPiP = NO;
/*
_settings.externalDisplayMode.intValue:
0 - stage manager
@@ -915,12 +920,12 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
[self reConfigStreamViewRealtime]; // call this method again to make sure all gestures are configured & added to the superview(self.view), including the gestures added from inside the streamview.
if([self isFirstStreaming] || GenericUtils.isFirstStreamingOnMac) [self popFirstStreamingTip];
#if TARGET_OS_TV
if (!_menuTapGestureRecognizer || !_menuDoubleTapGestureRecognizer || !_playPauseTapGestureRecognizer) {
_menuTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(controllerPauseButtonPressed:)];
_menuTapGestureRecognizer.allowedPressTypes = @[@(UIPressTypeMenu)];
_playPauseTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(controllerPlayPauseButtonPressed:)];
_playPauseTapGestureRecognizer.allowedPressTypes = @[@(UIPressTypePlayPause)];
@@ -933,7 +938,7 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
[self.view addGestureRecognizer:_menuTapGestureRecognizer];
[self.view addGestureRecognizer:_menuDoubleTapGestureRecognizer];
[self.view addGestureRecognizer:_playPauseTapGestureRecognizer];
#else
//[self configSwipeGestures]; // swipe & exit gesture configured here
//[self configOscLayoutTool]; //_oscLayoutTapRecoginizer will be added or removed to the view here
@@ -978,7 +983,7 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
selector:@selector(gameProfileSelectorClosed)
name:@"GameProfileSelectorCloseNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleStreamAspectRatioChanged:)
name:@"StreamAspectRatioChanged"
@@ -1008,13 +1013,13 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
[self.view addSubview:_stageLabel];
[self.view addSubview:_spinner];
[self.view addSubview:_tipLabel];
if ([_settings.renderingBackend intValue] == RENDER_METAL) {
// Metal view for video
Log(LOG_I, @"StreamFrameViewController creating MetalViewController");
self.metalViewController = [[MetalViewController alloc] initWithFrame:self.view.bounds
framerate:[self->_settings.framerate floatValue]
settings:self->_settings
settings:self->_settings
metricsHandler:self.imguiView.metricsHandler];
self.metalViewController.view.userInteractionEnabled = NO;
[self addChildViewController:self.metalViewController];
@@ -1022,14 +1027,10 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
[self.view insertSubview:self.metalViewController.view atIndex:0];
[self.metalViewController didMoveToParentViewController:self];
}
OnScreenWidgetView.gamepadArrivalReported = false;
OnScreenWidgetView.enableFolderAnimation = false;
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC));
dispatch_after(delay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OnScreenWidgetView.enableFolderAnimation = true;
});
ControllerUtil.gamepadArrivalReported = false;
[OnScreenWidgetView disableFolderAnimationFor:2];
}
- (void)keyboardWillShow:(NSNotification *)notification{
@@ -1074,6 +1075,7 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
_layoutOnScreenControlsVC.toolbarStackView.hidden = true;
_layoutOnScreenControlsVC.toolbarRootView.hidden = true;
ProfileSelectorLoadingMode loadingMode = pickProfile ? ProfileSelectorLoadingModePickProfile : ProfileSelectorLoadingModeSelectProfileFromStreamView;
_layoutOnScreenControlsVC.profileSelectorLoadingMode = loadingMode;
[self presentViewController:_layoutOnScreenControlsVC animated:NO completion:^{
[self->_layoutOnScreenControlsVC presentProfileSelectorWith:loadingMode animated:false];
}];
@@ -1198,6 +1200,7 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
// [self->_streamView reloadLegacyWidgets];
[self reConfigStreamViewRealtimeAndReloadSettings:NO reloadOnscreenWidgets:_settings.onscreenControls.intValue == OnScreenControlsLevelCustom];
// [self->_streamView reloadGameProfile:nil reloadWidgets:true]; //update keyboard buttons here
[OnScreenWidgetView disableFolderAnimationFor:2];
}
- (void)handleStreamAspectRatioChanged:(NSNotification *)notification {
@@ -2111,8 +2114,8 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
[_streamView disablePencilHover];
}
- (void)setAllowSingleTouchEnabled:(BOOL)enabled{
[_streamView setAllowSingleTouchEnabled:enabled];
- (void)handleDisableSingleTouchButtonUp {
[_streamView setAllowSingleTouchEnabled:!_singleTouchDisabled];
}
- (void)replaceBrushWithShortcut:(NSString *)shortcut{
@@ -2127,8 +2130,8 @@ static __weak StreamFrameViewController *VLSharedStreamFrameViewController = nil
}
}
- (void)toggleTouchWithDisabled:(BOOL)disabled{
[_streamView toggleTouchDisabled:disabled];
- (void)handleTouchDisableButtonUp {
[_streamView toggleTouchDisabled:self.touchDisabled];
}
- (void)presentPressureCurveVC{
+16 -16
View File
@@ -2648,30 +2648,30 @@
}
},
"DhB-EF-mDt.text" : {
"comment" : "Class = \"UILabel\"; text = \"Hover Mode\"; ObjectID = \"DhB-EF-mDt\";",
"comment" : "Class = \"UILabel\"; text = \"Pencil Mode\"; ObjectID = \"DhB-EF-mDt\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Hover Mode"
"value" : "Pencil Mode"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "悬停模式"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "懸停模式"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"state" : "needs_review",
"value" : "懸停模式"
}
}
@@ -6311,31 +6311,31 @@
}
},
"t12-bo-icS.segmentTitles[0]" : {
"comment" : "Class = \"UISegmentedControl\"; t12-bo-icS.segmentTitles[0] = \"Disabled\"; ObjectID = \"t12-bo-icS\";",
"comment" : "Class = \"UISegmentedControl\"; t12-bo-icS.segmentTitles[0] = \"Hovering Disabled\"; ObjectID = \"t12-bo-icS\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Disabled"
"value" : "Hovering Disabled"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "关闭"
"value" : "关闭悬停"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "關閉"
"value" : "關閉懸停"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "關閉"
"value" : "關閉懸停"
}
}
}
@@ -6401,31 +6401,31 @@
}
},
"t12-bo-icS.segmentTitles[3]" : {
"comment" : "Class = \"UISegmentedControl\"; t12-bo-icS.segmentTitles[3] = \"Both\"; ObjectID = \"t12-bo-icS\";",
"comment" : "Class = \"UISegmentedControl\"; t12-bo-icS.segmentTitles[3] = \"Touch\"; ObjectID = \"t12-bo-icS\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Both"
"value" : "Touch"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "同时悬停"
"value" : "触控"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "同時懸停"
"value" : "觸控"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "同時懸停"
"value" : "觸控"
}
}
}
@@ -7284,4 +7284,4 @@
}
},
"version" : "1.0"
}
}