- valid & invalid button mode tips

- widget panel tips
This commit is contained in:
True Zhuanjia committed 2026-05-13 15:45:25 +08:00
1 parent 57a8c22a3f
commit f72e0f6292
9 files changed
+683 -250

No files matched your search

+1
View File
@@ -60,6 +60,7 @@ static NSString* DB_NAME = @"Limelight_iOS.sqlite";
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for command tool customization after application launch (works only when user default is nil) // Override point for command tool customization after application launch (works only when user default is nil)
[CommandManager presetDefaultCommands]; [CommandManager presetDefaultCommands];
[GenericUtils installSegmentedControlPreviousSelectionTracking];
// For iOS 12 and below, we need to manually create the window // For iOS 12 and below, we need to manually create the window
if (@available(iOS 13.0, *)) { if (@available(iOS 13.0, *)) {
+15 -15
View File
@@ -2815,17 +2815,17 @@
<stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="9ZS-28-txW" userLabel="borderWidthAlphaStack"> <stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="9ZS-28-txW" userLabel="borderWidthAlphaStack">
<rect key="frame" x="0.0" y="358" width="650" height="34"/> <rect key="frame" x="0.0" y="358" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.59999999999999998" translatesAutoresizingMaskIntoConstraints="NO" id="Pwa-YK-6Q2" userLabel="widgetAlphaLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.29999999999999999" translatesAutoresizingMaskIntoConstraints="NO" id="Pwa-YK-6Q2" userLabel="widgetAlphaLabel">
<rect key="frame" x="0.0" y="0.0" width="101" height="34"/> <rect key="frame" x="0.0" y="0.0" width="110" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="101" id="1ru-Nd-cf4"/> <constraint firstAttribute="width" constant="110" id="1ru-Nd-cf4"/>
</constraints> </constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<slider verifyAmbiguity="off" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" contentHorizontalAlignment="leading" contentVerticalAlignment="center" value="0.83300000429153442" minValue="0.0010000000474974513" maxValue="0.99900001287460327" translatesAutoresizingMaskIntoConstraints="NO" id="ii1-Iq-jI4" userLabel="Alpha Slider"> <slider verifyAmbiguity="off" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" contentHorizontalAlignment="leading" contentVerticalAlignment="center" value="0.83300000429153442" minValue="0.0010000000474974513" maxValue="0.99900001287460327" translatesAutoresizingMaskIntoConstraints="NO" id="ii1-Iq-jI4" userLabel="Alpha Slider">
<rect key="frame" x="106" y="0.0" width="165" height="34"/> <rect key="frame" x="115" y="0.0" width="165" height="34"/>
<color key="tintColor" red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/> <color key="tintColor" red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="165" id="tRM-SO-nlr"/> <constraint firstAttribute="width" constant="165" id="tRM-SO-nlr"/>
@@ -2833,7 +2833,7 @@
<color key="maximumTrackTintColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="maximumTrackTintColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</slider> </slider>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="BorderWidth" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r8L-dl-yLZ" userLabel="widgetBorderLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="BorderWidth" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r8L-dl-yLZ" userLabel="widgetBorderLabel">
<rect key="frame" x="276" y="0.0" width="150" height="34"/> <rect key="frame" x="285" y="0.0" width="150" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="150" id="ZWS-S0-FRB"/> <constraint firstAttribute="width" constant="150" id="ZWS-S0-FRB"/>
</constraints> </constraints>
@@ -2842,7 +2842,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<slider verifyAmbiguity="off" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="8" translatesAutoresizingMaskIntoConstraints="NO" id="aOV-38-CQt" userLabel="Widget Border Width Slider"> <slider verifyAmbiguity="off" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="8" translatesAutoresizingMaskIntoConstraints="NO" id="aOV-38-CQt" userLabel="Widget Border Width Slider">
<rect key="frame" x="431" y="0.0" width="219" height="34"/> <rect key="frame" x="440" y="0.0" width="210" height="34"/>
<color key="tintColor" red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/> <color key="tintColor" red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<color key="maximumTrackTintColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="maximumTrackTintColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</slider> </slider>
@@ -3254,7 +3254,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="faR-Se-Fc5"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="faR-Se-Fc5">
<rect key="frame" x="0.0" y="1003" width="650" height="34"/> <rect key="frame" x="0.0" y="1003" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Width" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="D7h-Kq-SRP"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Width" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D7h-Kq-SRP">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="VeB-6b-wgo"/> <constraint firstAttribute="width" constant="160" id="VeB-6b-wgo"/>
@@ -3276,7 +3276,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ugt-Uc-gHA"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ugt-Uc-gHA">
<rect key="frame" x="0.0" y="1042" width="650" height="34"/> <rect key="frame" x="0.0" y="1042" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Height" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="V1y-Wk-uHM"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Height" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="V1y-Wk-uHM">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="VN7-XV-yPb"/> <constraint firstAttribute="width" constant="160" id="VN7-XV-yPb"/>
@@ -3298,7 +3298,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KSh-xS-xfD"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="KSh-xS-xfD">
<rect key="frame" x="0.0" y="1081" width="650" height="34"/> <rect key="frame" x="0.0" y="1081" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yF0-Tu-L8X"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="yF0-Tu-L8X">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="ofw-9E-Plc"/> <constraint firstAttribute="width" constant="160" id="ofw-9E-Plc"/>
@@ -3320,7 +3320,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Wxc-0O-tca"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Wxc-0O-tca">
<rect key="frame" x="0.0" y="1120" width="650" height="34"/> <rect key="frame" x="0.0" y="1120" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Border width" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wTH-1Z-Fgh"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Border width" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wTH-1Z-Fgh">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="OyF-eF-9ag"/> <constraint firstAttribute="width" constant="160" id="OyF-eF-9ag"/>
@@ -3342,7 +3342,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="O0O-pZ-URe" userLabel="Bulk Label Alpha Stack"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="O0O-pZ-URe" userLabel="Bulk Label Alpha Stack">
<rect key="frame" x="0.0" y="1159" width="650" height="34"/> <rect key="frame" x="0.0" y="1159" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kSX-ci-kx5"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="kSX-ci-kx5">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="L3D-Ej-6ZS"/> <constraint firstAttribute="width" constant="160" id="L3D-Ej-6ZS"/>
@@ -3364,7 +3364,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rfr-nL-OCc"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rfr-nL-OCc">
<rect key="frame" x="0.0" y="1198" width="650" height="34"/> <rect key="frame" x="0.0" y="1198" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Border alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sAF-Vy-ZzK"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Border opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sAF-Vy-ZzK">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="cWO-t5-t5M"/> <constraint firstAttribute="width" constant="160" id="cWO-t5-t5M"/>
@@ -3386,7 +3386,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="X7d-dV-lHa"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="X7d-dV-lHa">
<rect key="frame" x="0.0" y="1237" width="650" height="34"/> <rect key="frame" x="0.0" y="1237" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Highlight alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1sF-08-aCr"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Highlight opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1sF-08-aCr">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="ZUf-9R-Smf"/> <constraint firstAttribute="width" constant="160" id="ZUf-9R-Smf"/>
@@ -3408,7 +3408,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nBA-Ii-jNy"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nBA-Ii-jNy">
<rect key="frame" x="0.0" y="1276" width="650" height="34"/> <rect key="frame" x="0.0" y="1276" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Highlight size" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hKK-ro-C5E"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Highlight size" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hKK-ro-C5E">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="C4Q-cb-ZXx"/> <constraint firstAttribute="width" constant="160" id="C4Q-cb-ZXx"/>
@@ -3452,7 +3452,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3dC-9Z-wKV"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3dC-9Z-wKV">
<rect key="frame" x="0.0" y="1354" width="650" height="34"/> <rect key="frame" x="0.0" y="1354" width="650" height="34"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Docked alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qFn-D7-7aD"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Docked opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qFn-D7-7aD">
<rect key="frame" x="0.0" y="0.0" width="160" height="34"/> <rect key="frame" x="0.0" y="0.0" width="160" height="34"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="B6V-Z1-ZAh"/> <constraint firstAttribute="width" constant="160" id="B6V-Z1-ZAh"/>
+5 -5
View File
@@ -430,7 +430,7 @@
<stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="50p-sC-ObU" userLabel="borderWidthAlphaStack"> <stackView opaque="NO" contentMode="scaleToFill" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="50p-sC-ObU" userLabel="borderWidthAlphaStack">
<rect key="frame" x="0.0" y="415" width="550" height="20"/> <rect key="frame" x="0.0" y="415" width="550" height="20"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.29999999999999999" translatesAutoresizingMaskIntoConstraints="NO" id="qPQ-U2-aSg" userLabel="widgetAlphaLabel"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.29999999999999999" translatesAutoresizingMaskIntoConstraints="NO" id="qPQ-U2-aSg" userLabel="widgetAlphaLabel">
<rect key="frame" x="0.0" y="0.0" width="101" height="20"/> <rect key="frame" x="0.0" y="0.0" width="101" height="20"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="101" id="F3F-cO-OPA"/> <constraint firstAttribute="width" constant="101" id="F3F-cO-OPA"/>
@@ -1039,7 +1039,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YB4-fc-lM6"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YB4-fc-lM6">
<rect key="frame" x="0.0" y="1009" width="550" height="20"/> <rect key="frame" x="0.0" y="1009" width="550" height="20"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9Dr-3c-z61"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="9Dr-3c-z61">
<rect key="frame" x="0.0" y="0.0" width="160" height="20"/> <rect key="frame" x="0.0" y="0.0" width="160" height="20"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="sSo-xR-0nl"/> <constraint firstAttribute="width" constant="160" id="sSo-xR-0nl"/>
@@ -1061,7 +1061,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8tb-mS-WEu"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8tb-mS-WEu">
<rect key="frame" x="0.0" y="1036" width="550" height="20"/> <rect key="frame" x="0.0" y="1036" width="550" height="20"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Border alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eRy-My-vvU"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Border opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="eRy-My-vvU">
<rect key="frame" x="0.0" y="0.0" width="160" height="20"/> <rect key="frame" x="0.0" y="0.0" width="160" height="20"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="ZBl-sM-khB"/> <constraint firstAttribute="width" constant="160" id="ZBl-sM-khB"/>
@@ -1083,7 +1083,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cJk-PA-Lp0"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cJk-PA-Lp0">
<rect key="frame" x="0.0" y="1063" width="550" height="20"/> <rect key="frame" x="0.0" y="1063" width="550" height="20"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Highlight alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Kd-Cc-aYN"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Highlight opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="4Kd-Cc-aYN">
<rect key="frame" x="0.0" y="0.0" width="160" height="20"/> <rect key="frame" x="0.0" y="0.0" width="160" height="20"/>
<constraints> <constraints>
<constraint firstAttribute="width" constant="160" id="kDG-5Z-TXN"/> <constraint firstAttribute="width" constant="160" id="kDG-5Z-TXN"/>
@@ -1149,7 +1149,7 @@
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="n71-jv-Ziw"> <stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="n71-jv-Ziw">
<rect key="frame" x="0.0" y="1144" width="550" height="20"/> <rect key="frame" x="0.0" y="1144" width="550" height="20"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Docked alpha" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kxI-bn-pRU"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Docked opacity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.20000000000000001" translatesAutoresizingMaskIntoConstraints="NO" id="kxI-bn-pRU">
<rect key="frame" x="0.0" y="0.0" width="160" height="20"/> <rect key="frame" x="0.0" y="0.0" width="160" height="20"/>
<constraints> <constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="160" id="JhH-nj-7cT"/> <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="160" id="JhH-nj-7cT"/>
+2 -2
View File
@@ -919,7 +919,7 @@ static float L3_Y;
[buttonLayer.name isEqualToString:@"rightButton"] || [buttonLayer.name isEqualToString:@"rightButton"] ||
[buttonLayer.name isEqualToString:@"downButton"] || [buttonLayer.name isEqualToString:@"downButton"] ||
[buttonLayer.name isEqualToString:@"leftButton"]){ [buttonLayer.name isEqualToString:@"leftButton"]){
// NSLog(@"layerName: %@, alpha: %f", buttonLayer.name, buttonStateDecoded.backgroundAlpha); // NSLog(@"layerName: %@, opacity: %f", buttonLayer.name, buttonStateDecoded.backgroundAlpha);
[self adjustControllerLayerOpacityWith:buttonLayer and:buttonStateDecoded.backgroundAlpha]; [self adjustControllerLayerOpacityWith:buttonLayer and:buttonStateDecoded.backgroundAlpha];
} }
if([buttonLayer.name isEqualToString:@"leftStickBackground"]){ if([buttonLayer.name isEqualToString:@"leftStickBackground"]){
@@ -2056,7 +2056,7 @@ static float L3_Y;
if (layer == self._rightStickBackground) { if (layer == self._rightStickBackground) {
self._rightStick.opacity = targetAlpha; self._rightStick.opacity = targetAlpha;
self._rightStickBackground.opacity = targetAlpha + 1.0f/6.0f; self._rightStickBackground.opacity = targetAlpha + 1.0f/6.0f;
NSLog(@"right stick init alpha: %f", targetAlpha); NSLog(@"right stick init opacity: %f", targetAlpha);
} }
if (layer == self._leftStickBackground){ if (layer == self._leftStickBackground){
+240 -42
View File
@@ -2243,29 +2243,6 @@
} }
} }
}, },
"Alpha: %.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"
}
}
}
},
"Applications" : { "Applications" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@@ -2750,12 +2727,18 @@
} }
} }
}, },
"Border alpha: %.2f" : { "Border opacity: %.2f" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
"zh-Hans" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Border opacity: %.2f "
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "边界透明度: %.2f" "value" : "边界透明度: %.2f"
} }
}, },
@@ -2934,6 +2917,64 @@
} }
} }
}, },
"buttonModeLink" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/tvlizqfgoidrn20o"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/mbyiwshw8bxhktlh"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/mbyiwshw8bxhktlh"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/mbyiwshw8bxhktlh"
}
}
}
},
"buttonModeTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tap “Tutorial” to learn about button modes."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "点击 “看教程” 了解按键模式。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "點擊「看教學」了解按鍵模式。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "點擊「看教學」了解按鍵模式。"
}
}
}
},
"Calibrating..." : { "Calibrating..." : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@@ -4241,18 +4282,18 @@
} }
} }
}, },
"Docked alpha: %d%%" : { "Docked opacity: %d%%" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Docked alpha: %d%" "value" : "Docked opacity: %d%% "
} }
}, },
"zh-Hans" : { "zh-Hans" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "needs_review",
"value" : "吸附后透明度: %d%%" "value" : "吸附后透明度: %d%%"
} }
}, },
@@ -5434,25 +5475,25 @@
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "\n1. By default, The widget menu button will be automatically docked to bottom edge, then become almost transparent after staying idle for 10 seconds. \nThis timeout can be changed by entering “Edit” in the widget menu.\n\n2. From %@ edge, slide %d%% screen width to open settings menu\n\n3. From %@ edge, slide %d%% screen width to open toolbox menu\n\n4. Slide from top 40%% of screen edge to avoid sending touch events to PC side" "value" : "\n1. By default, The widget menu button will be automatically docked to bottom edge, then become almost transparent after staying idle for 10 seconds. \nThis timeout can be changed by entering “Edit” in the widget menu.\n\n2. From %@ edge, slide %d%% screen width to open settings menu\n\n3. From %@ edge, slide %d%% screen width to open toolbox menu\n\n4. Slide from top 40%% of screen edge to avoid sending touch events to PC side\n\nIf the screen shows large green or purple color artifacts, disable variable display refresh rate on the PC and set the display refresh rate to match the streaming frame rate."
} }
}, },
"zh-Hans" : { "zh-Hans" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "\n1. 默认状态下,控件菜单按键在闲置10秒后将自动吸附屏幕底部边缘,并进入高透明状态。\n可展开控件菜单,进入“修改布局”修改该延迟。\n\n2. 展开设置菜单: 从%@边缘滑动%d%%屏幕宽度\n\n3. 展开工具箱菜单: 从%@边缘滑动%d%%屏幕宽度\n\n4. 从40%%上半边缘滑动避免触控事件影响PC端\n" "value" : "\n1. 默认状态下,控件菜单按键在闲置10秒后将自动吸附屏幕底部边缘,并进入高透明状态。\n可展开控件菜单,进入“修改布局”修改该延迟。\n\n2. 展开设置菜单: 从%@边缘滑动%d%%屏幕宽度\n\n3. 展开工具箱菜单: 从%@边缘滑动%d%%屏幕宽度\n\n4. 从40%%上半边缘滑动避免触控事件影响PC端\n\n若画面出现大片发绿、发紫的颜色异常,请在主机端关闭可变显示刷新率,并将显示刷新率设定为与串流帧率一致。"
} }
}, },
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "needs_review",
"value" : "\n1. 預設狀態下,控件選單按鍵在閒置10秒後將自動吸附至螢幕底部邊緣,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端" "value" : "\n1. 預設狀態下,控件選單按鍵在閒置10秒後將自動吸附至螢幕底部邊緣,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端\n\n若畫面出現大片發綠、發紫等色彩異常,請在主機端關閉可變顯示更新率,並將顯示更新率設定為與串流幀率一致。"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "needs_review",
"value" : "\n1. 預設狀態下,控件選單按鍵在閒置10秒後將自動吸附至螢幕底部邊緣,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端" "value" : "\n1. 預設狀態下,控件選單按鍵在閒置10秒後將自動吸附至螢幕底部邊緣,並進入高透明狀態。\n可展開控件選單,進入「修改佈局」修改該延遲。\n\n2. 展開設定選單: 從%@邊緣滑動%d%%螢幕寬度\n\n3. 展開工具箱選單: 從%@邊緣滑動%d%%螢幕寬度\n\n4. 從40%%上半邊緣滑動避免觸控事件影響PC端\n\n若畫面出現大片發綠、發紫等色彩異常,請在主機端關閉可變顯示更新率,並將顯示更新率設定為與串流幀率一致。"
} }
} }
} }
@@ -5555,30 +5596,59 @@
} }
} }
}, },
"folderButtonModeTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Folder button supports the following modes:\n\n- Slide and hold: Expands while pressed and collapses when released. Double-tap and hold to drag during streaming.\n\n- Movable: Tap to toggle expand/collapse. Long press to enter draggable mode.\n\n- Normal: Tap to toggle expand/collapse state. Cannot be dragged and moved during streaming."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "Folder 控件夹按键支持以下模式:\n\n- 滑动时按下: 按压时展开,松开折叠。双击并长按可在串流过程中拖动。\n\n- 可移动:点按切换展开 / 折叠。长按进入可拖动状态。\n\n- 常规:点按切换展开 / 折叠状态。无法在串流中被拖动。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "Folder 控件夾按鍵支援以下模式:\n\n- 滑動時按下:按壓時展開,鬆開折疊。雙擊並長按可在串流過程中拖動。\n\n- 可移動:點按切換展開/折疊狀態。長按進入可拖動狀態。\n\n- 常規:點按切換展開/折疊狀態。無法在串流中被拖動。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "Folder 控件夾按鍵支援以下模式:\n\n- 滑動時按下:按壓時展開,鬆開折疊。雙擊並長按可在串流過程中拖動。\n\n- 可移動:點按切換展開/折疊狀態。長按進入可拖動狀態。\n\n- 常規:點按切換展開/折疊狀態。無法在串流中被拖動。"
}
}
}
},
"folderTutorialTip" : { "folderTutorialTip" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "\nDrag other widgets (buttons or touchpads). Release when the touch point enters the folder’s bounding frame to complete collecting.\n\n- When the folder is unfolded, the collected widget will snap back to its original position.\n\n- When the folder is folded, the grouped widget will be hidden.\n\n- Drag a sub-widget or a folder over the trash icon (do not release) to detach it from the collection." "value" : "\nDrag other widgets (buttons or touchpads). Release when the touch point enters the folder’s bounding frame to complete collecting.\n\n- When the folder is unfolded, the collected widget will snap back to its original position.\n\n- When the folder is folded, the collected widget will be hidden.\n\n- Drag a sub-widget or a folder over the trash icon (do not release) to detach it from the collection."
} }
}, },
"zh-Hans" : { "zh-Hans" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "needs_review",
"value" : "\n拖动其他控件(按键或触控板),当手指触点进入控件夹边框时松开,即可完成收纳。\n\n- 当控件夹处于展开状态时, 被收纳控件将弹回原先的位置。\n\n- 当控件夹处于折叠状态时,被收纳控件将隐藏。\n\n- 拖动子控件或控件夹划过垃圾桶图标(不要松开),即可解除收纳关系。" "value" : "\n拖动其他控件(按键或触控板),当手指触点进入控件夹边框时松开,即可完成收纳。\n\n- 当控件夹处于展开状态时, 被收纳控件将弹回原先的位置。\n\n- 当控件夹处于折叠状态时,被收纳控件将隐藏。\n\n- 拖动子控件或控件夹划过垃圾桶图标(不要松开),即可解除收纳关系。"
} }
}, },
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "needs_review",
"value" : "\n拖動其他螢幕控制項(按鍵或觸控板),當手指觸點進入資料夾邊框時放開,即可完成收納。\n\n- 當控制項夾處於展開狀態時,被收納的控制項會彈回原本的位置。\n\n- 當控制項夾處於折疊狀態時,被收納的控制項會隱藏。\n\n- 拖動子控制項或控制項夾按键,劃過垃圾桶圖示(不要放開),即可解除收納關係。\n" "value" : "\n拖動其他螢幕控制項(按鍵或觸控板),當手指觸點進入資料夾邊框時放開,即可完成收納。\n\n- 當控制項夾處於展開狀態時,被收納的控制項會彈回原本的位置。\n\n- 當控制項夾處於折疊狀態時,被收納的控制項會隱藏。\n\n- 拖動子控制項或控制項夾按键,劃過垃圾桶圖示(不要放開),即可解除收納關係。\n"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "needs_review",
"value" : "\n拖動其他螢幕控制項(按鍵或觸控板),當手指觸點進入資料夾邊框時放開,即可完成收納。\n\n- 當控制項夾處於展開狀態時,被收納的控制項會彈回原本的位置。\n\n- 當控制項夾處於折疊狀態時,被收納的控制項會隱藏。\n\n- 拖動子控制項或控制項夾按键,劃過垃圾桶圖示(不要放開),即可解除收納關係。\n" "value" : "\n拖動其他螢幕控制項(按鍵或觸控板),當手指觸點進入資料夾邊框時放開,即可完成收納。\n\n- 當控制項夾處於展開狀態時,被收納的控制項會彈回原本的位置。\n\n- 當控制項夾處於折疊狀態時,被收納的控制項會隱藏。\n\n- 拖動子控制項或控制項夾按键,劃過垃圾桶圖示(不要放開),即可解除收納關係。\n"
} }
} }
@@ -6581,12 +6651,18 @@
} }
} }
}, },
"Highlight alpha: %.2f" : { "Highlight opacity: %.2f" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
"zh-Hans" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Highlight opacity: %.2f "
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "高亮透明度: %.2f" "value" : "高亮透明度: %.2f"
} }
}, },
@@ -6898,6 +6974,35 @@
} }
} }
}, },
"invalidButtonModeTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "This button is not applicable in this mode."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "此模式不适用该按键。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "此模式不適用該按鍵。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "此模式不適用該按鍵。"
}
}
}
},
"Keyboard / Mouse" : { "Keyboard / Mouse" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@@ -6996,12 +7101,18 @@
} }
} }
}, },
"Label alpha: %.2f" : { "Label opacity: %.2f" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
"zh-Hans" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Label opacity: %.2f "
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "标签透明度: %.2f" "value" : "标签透明度: %.2f"
} }
}, },
@@ -8886,6 +8997,35 @@
} }
} }
}, },
"Opacity: %.2f" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Opacity: %.2f "
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "透明度: %.2f"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "透明度: %.2f"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "透明度: %.2f"
}
}
}
},
"Open on-screen widget layout tool" : { "Open on-screen widget layout tool" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@@ -13943,6 +14083,64 @@
} }
} }
}, },
"widgetPanelLink" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/dcke52amz8ay3g37"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/zrg0ga93avz4s747"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/zrg0ga93avz4s747"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "https://voidlink.yuque.com/org-wiki-voidlink-znirha/fa3tgr/zrg0ga93avz4s747"
}
}
}
},
"widgetPanelTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "- Tap the “Opacity” or “Border Width” label to reveal hidden features.\n\n- If batch edit is unavailable, tap & unfold the parent folder button"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "- 点击“透明度” 、“边界宽度” 标签,可切换出隐藏功能。\n\n- 若无批量编辑功能,请点击上一级 Folder 控件夹按键,并将其展开。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "- 點擊「透明度」 「邊界寬度」標籤,可切換出隱藏功能。\n\n- 若無批次編輯功能,請點擊上一級 Folder 控制項夾按鍵,並將其展開。\n"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "- 點擊「透明度」 「邊界寬度」標籤,可切換出隱藏功能。\n\n- 若無批次編輯功能,請點擊上一級 Folder 控制項夾按鍵,並將其展開。\n"
}
}
}
},
"Width" : { "Width" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
+212 -1
View File
@@ -9,9 +9,13 @@
import Foundation import Foundation
import GameController import GameController
import ObjectiveC
import UIKit import UIKit
@objc public class GenericUtils: NSObject { @objc public class GenericUtils: NSObject {
@objc static func installSegmentedControlPreviousSelectionTracking() {
UISegmentedControl.installPreviousSelectionTracking()
}
@objc static var hardwareKeyboardAlreadyDetected: Bool = false @objc static var hardwareKeyboardAlreadyDetected: Bool = false
@@ -115,7 +119,7 @@ import UIKit
} }
@objc static func isFirstTappingFolderInLayoutTool() -> Bool { @objc static func isFirstTappingFolderInLayoutTool() -> Bool {
let key = "hasTappedFolderInLayoutTool" let key = "hasTappedFolderInLayoutTool2"
let defaults = UserDefaults.standard let defaults = UserDefaults.standard
let launchedBefore = defaults.bool(forKey: key) let launchedBefore = defaults.bool(forKey: key)
if !launchedBefore { if !launchedBefore {
@@ -241,6 +245,36 @@ import UIKit
} }
} }
@objc static var hasTappedButtonModeSelector = false
@objc static func isFirstTappingButtonModeSelector() -> Bool {
guard !hasTappedButtonModeSelector else { return false }
hasTappedButtonModeSelector = true
let key = "hasTappedButtonModeSelector3"
let defaults = UserDefaults.standard
let launchedBefore = defaults.bool(forKey: key)
if !launchedBefore {
defaults.set(true, forKey: key)
return true
}
return false
}
@objc static func handleButtonModeTip(in vc: UIViewController?) {
if isFirstTappingButtonModeSelector() {
AlertControllerUtil.showAlert(
in: vc,
title: LocalizationHelper.localizedString(forKey: "Tips"),
message: "\n\(LocalizationHelper.localizedString(forKey: "buttonModeTip"))",
withCancel: false,
buttonTitle: LocalizationHelper.localizedString(forKey: "Tutorial"),
countdown: 3,
completion: {
GenericUtils.openUrl(LocalizationHelper.localizedString(forKey: "buttonModeLink"))
}
)
}
}
@objc static var hasTappedStickWheel = false @objc static var hasTappedStickWheel = false
@objc static func isFirstTappingStickWheel() -> Bool { @objc static func isFirstTappingStickWheel() -> Bool {
guard !hasTappedStickWheel else { return false } guard !hasTappedStickWheel else { return false }
@@ -273,6 +307,38 @@ import UIKit
} }
} }
@objc static var hasTappedWidgetPanel = false
@objc static func isFirstTappingWidgetPanel() -> Bool {
guard !hasTappedWidgetPanel else { return false }
hasTappedWidgetPanel = true
let key = "hasTappedWidgetPanel7"
let defaults = UserDefaults.standard
let launchedBefore = defaults.bool(forKey: key)
if !launchedBefore {
defaults.set(true, forKey: key)
return true
}
return false
}
@objc static func handleWidgetPanelTip(in vc: UIViewController?) {
if isFirstTappingWidgetPanel() {
// AlertControllerUtil.cancelButtonString = LocalizationHelper.localizedString(forKey: "Detailed Tutorial")
AlertControllerUtil.showAlert(
in: vc,
title: LocalizationHelper.localizedString(forKey: "Tips"),
message: "\n\(LocalizationHelper.localizedString(forKey: "widgetPanelTip"))",
withCancel: false,
buttonTitle: LocalizationHelper.localizedString(forKey: "Got it!"),
countdown: 6,
completion: {
if AlertControllerUtil.actionCancelled {
GenericUtils.openUrl(LocalizationHelper.localizedString(forKey: "widgetPanelLink"))
}
}
)
}
}
@objc static func isFirstTappingInputAccessoryBar() -> Bool { @objc static func isFirstTappingInputAccessoryBar() -> Bool {
let key = "isFirstTappingInputAccessoryBar" let key = "isFirstTappingInputAccessoryBar"
let defaults = UserDefaults.standard let defaults = UserDefaults.standard
@@ -539,3 +605,148 @@ extension CGPoint {
x.isFinite && y.isFinite x.isFinite && y.isFinite
} }
} }
private var previousSelectedSegmentIndexKey: UInt8 = 0
private var lastKnownSelectedSegmentIndexKey: UInt8 = 0
extension UISegmentedControl {
@objc static func installPreviousSelectionTracking() {
_ = enablePreviousSelectionTracking
}
private static let enablePreviousSelectionTracking: Void = {
guard
let originalSetter = class_getInstanceMethod(
UISegmentedControl.self,
#selector(setter: UISegmentedControl.selectedSegmentIndex)
),
let swizzledSetter = class_getInstanceMethod(
UISegmentedControl.self,
#selector(UISegmentedControl.vl_setSelectedSegmentIndex(_:))
),
let originalSendAction = class_getInstanceMethod(
UISegmentedControl.self,
#selector(UISegmentedControl.sendAction(_:to:for:))
),
let swizzledSendAction = class_getInstanceMethod(
UISegmentedControl.self,
#selector(UISegmentedControl.vl_sendAction(_:to:for:))
)
else {
return
}
swizzleMethod(
on: UISegmentedControl.self,
originalMethod: originalSetter,
originalSelector: #selector(setter: UISegmentedControl.selectedSegmentIndex),
swizzledMethod: swizzledSetter,
swizzledSelector: #selector(UISegmentedControl.vl_setSelectedSegmentIndex(_:))
)
swizzleMethod(
on: UISegmentedControl.self,
originalMethod: originalSendAction,
originalSelector: #selector(UISegmentedControl.sendAction(_:to:for:)),
swizzledMethod: swizzledSendAction,
swizzledSelector: #selector(UISegmentedControl.vl_sendAction(_:to:for:))
)
}()
@objc var previousSelectedSegmentIndex: Int {
Self.installPreviousSelectionTracking()
initializeLastKnownIndexIfNeeded()
return (objc_getAssociatedObject(self, &previousSelectedSegmentIndexKey) as? NSNumber)?.intValue
?? selectedSegmentIndex
}
@objc func resetPreviousSelectedSegmentIndex() {
Self.installPreviousSelectionTracking()
storePreviousSelectedSegmentIndex(selectedSegmentIndex)
storeLastKnownSelectedSegmentIndex(selectedSegmentIndex)
}
@objc private func vl_setSelectedSegmentIndex(_ newValue: Int) {
Self.installPreviousSelectionTracking()
initializeLastKnownIndexIfNeeded()
let currentValue = selectedSegmentIndex
if currentValue != newValue {
storePreviousSelectedSegmentIndex(newValue)
storeLastKnownSelectedSegmentIndex(newValue)
}
vl_setSelectedSegmentIndex(newValue)
}
@objc private func vl_sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
Self.installPreviousSelectionTracking()
updatePreviousSelectedSegmentIndexIfNeeded()
vl_sendAction(action, to: target, for: event)
}
private func initializeLastKnownIndexIfNeeded() {
guard objc_getAssociatedObject(self, &lastKnownSelectedSegmentIndexKey) == nil else {
return
}
storeLastKnownSelectedSegmentIndex(selectedSegmentIndex)
}
private func updatePreviousSelectedSegmentIndexIfNeeded() {
initializeLastKnownIndexIfNeeded()
let currentValue = selectedSegmentIndex
let lastKnownValue = (objc_getAssociatedObject(self, &lastKnownSelectedSegmentIndexKey) as? NSNumber)?.intValue
?? UISegmentedControl.noSegment
guard currentValue != lastKnownValue else {
return
}
storePreviousSelectedSegmentIndex(lastKnownValue)
storeLastKnownSelectedSegmentIndex(currentValue)
}
private func storePreviousSelectedSegmentIndex(_ value: Int) {
objc_setAssociatedObject(
self,
&previousSelectedSegmentIndexKey,
NSNumber(value: value),
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
private func storeLastKnownSelectedSegmentIndex(_ value: Int) {
objc_setAssociatedObject(
self,
&lastKnownSelectedSegmentIndexKey,
NSNumber(value: value),
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
)
}
private static func swizzleMethod(
on cls: AnyClass,
originalMethod: Method,
originalSelector: Selector,
swizzledMethod: Method,
swizzledSelector: Selector
) {
let didAddMethod = class_addMethod(
cls,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod)
)
if didAddMethod {
class_replaceMethod(
cls,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod)
)
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
@@ -188,7 +188,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
private var oscProfilesTableViewController: OSCProfilesTableViewController? private var oscProfilesTableViewController: OSCProfilesTableViewController?
private var profilesManager: OSCProfilesManager! private var profilesManager: OSCProfilesManager!
private var bulkEditEnabled: Bool = false private var bulkEditEnabled: Bool = false
private var selectedWidgetView: OnScreenWidgetView? private var selectedWidget: OnScreenWidgetView?
private var alphaSliderMode: AlphaSliderMode = .widgetAlpha private var alphaSliderMode: AlphaSliderMode = .widgetAlpha
private var borderWidthSliderMode: BorderWidthSliderMode = .widgetBorderWidth private var borderWidthSliderMode: BorderWidthSliderMode = .widgetBorderWidth
private var decelerationRateSliderMode: DecelerationRateSliderMode = .decelerationRateX private var decelerationRateSliderMode: DecelerationRateSliderMode = .decelerationRateX
@@ -300,7 +300,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
bulkEditStacks = [bulkWidthStack, bulkHeightStack, bulkAlphaStack, bulkBorderAlphaStack, bulkLabelAlphaStack, bulkBorderWidthStack, bulkHighlightAlphaStack, bulkHighlightSizeStack] bulkEditStacks = [bulkWidthStack, bulkHeightStack, bulkAlphaStack, bulkBorderAlphaStack, bulkLabelAlphaStack, bulkBorderWidthStack, bulkHighlightAlphaStack, bulkHighlightSizeStack]
bulkEditEnabled = false bulkEditEnabled = false
OnScreenWidgetView.editMode = true OnScreenWidgetView.editMode = true
selectedWidgetView = nil selectedWidget = nil
widgetPanelStoredCenter = widgetPanelStack.center widgetPanelStoredCenter = widgetPanelStack.center
profileRefresh() profileRefresh()
setupWidgetPanel() setupWidgetPanel()
@@ -519,7 +519,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
pickedProfileDataHandler: ((OSCProfile) -> Void)? = nil pickedProfileDataHandler: ((OSCProfile) -> Void)? = nil
) { ) {
hideStickIndicators() hideStickIndicators()
if loadingMode != .pickProfileData {selectedWidgetView = nil} if loadingMode != .pickProfileData {selectedWidget = nil}
let storyboardName = UIDevice.current.userInterfaceIdiom == .phone ? "iPhone" : "iPad" let storyboardName = UIDevice.current.userInterfaceIdiom == .phone ? "iPhone" : "iPad"
let storyboard = UIStoryboard(name: storyboardName, bundle: nil) let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "OSCProfilesTableViewController") as? OSCProfilesTableViewController let controller = storyboard.instantiateViewController(withIdentifier: "OSCProfilesTableViewController") as? OSCProfilesTableViewController
@@ -552,19 +552,19 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
// importFromOtherButton.setTitle(LocalizationHelper.localizedString(forKey: "Import"), for: .normal) // importFromOtherButton.setTitle(LocalizationHelper.localizedString(forKey: "Import"), for: .normal)
presentProfilesTableView(with: .pickProfileData) { [weak self] profile in presentProfilesTableView(with: .pickProfileData) { [weak self] profile in
if profile.name == self?.profilesManager.getSelectedProfile().name {return} if profile.name == self?.profilesManager.getSelectedProfile().name {return}
self?.loadWidgets(from: profile, to: self?.selectedWidgetView) self?.loadWidgets(from: profile, to: self?.selectedWidget)
} }
} }
@IBAction func clearFolderButtonTapped(_ sender: Any?) { @IBAction func clearFolderButtonTapped(_ sender: Any?) {
for widget in OnScreenWidgetView.mapping.values { for widget in OnScreenWidgetView.mapping.values {
if widget.parentSequence == selectedWidgetView?.sequence, widget.sequenceSet.isEmpty { if widget.parentSequence == selectedWidget?.sequence, widget.sequenceSet.isEmpty {
OnScreenWidgetView.mapping.removeValue(forKey: widget.sequence) OnScreenWidgetView.mapping.removeValue(forKey: widget.sequence)
widget.removeFromSuperview() widget.removeFromSuperview()
} }
} }
selectedWidgetView?.sequenceSet = Set() selectedWidget?.sequenceSet = Set()
} }
private func setBulkEditStackHidden(_ hidden:Bool) { private func setBulkEditStackHidden(_ hidden:Bool) {
@@ -591,8 +591,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
stack.isHidden = hidden stack.isHidden = hidden
} }
buttonModeStack.isHidden = !hidden || (selectedWidgetView?.widgetType != .button) buttonModeStack.isHidden = !hidden || (selectedWidget?.widgetType != .button)
collectedWidgetsStack.isHidden = selectedWidgetView?.isFolder != true collectedWidgetsStack.isHidden = selectedWidget?.isFolder != true
if GenericUtils.isIPhone() { if GenericUtils.isIPhone() {
vibrationStyleStack.isHidden = false vibrationStyleStack.isHidden = false
@@ -602,7 +602,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@IBAction func bulkEditButtonTapped(_ sender: Any?) { @IBAction func bulkEditButtonTapped(_ sender: Any?) {
guard let selectedWidgetView = selectedWidgetView else {return} guard let selectedWidgetView = selectedWidget else {return}
if !bulkEditEnabled {applyTitle("Batch updated", for: sender as! UIButton)} if !bulkEditEnabled {applyTitle("Batch updated", for: sender as! UIButton)}
else {applyTitle("Batch edit", for: sender as! UIButton)} else {applyTitle("Batch edit", for: sender as! UIButton)}
bulkEditEnabled = !bulkEditEnabled bulkEditEnabled = !bulkEditEnabled
@@ -679,7 +679,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
private func updateViewBounds() { private func updateViewBounds() {
viewWillBeResized = false viewWillBeResized = false
selectedWidgetView = nil selectedWidget = nil
selectedControllerLayer = nil selectedControllerLayer = nil
oscProfilesTableViewController?.layoutViewBounds = view.bounds oscProfilesTableViewController?.layoutViewBounds = view.bounds
OSCProfilesManager.setLayoutViewBounds(view.bounds) OSCProfilesManager.setLayoutViewBounds(view.bounds)
@@ -757,52 +757,52 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
private func loadWidgetAlphas() { private func loadWidgetAlphas() {
guard let selectedWidgetView, widgetViewSelected else { return } guard let selectedWidget, widgetViewSelected else { return }
setHiddenForWidgetHighlights(selectedWidgetView) setHiddenForWidgetHighlights(selectedWidget)
switch alphaSliderMode { switch alphaSliderMode {
case .widgetAlpha: case .widgetAlpha:
widgetAlphaSlider.maximumValue = 1 widgetAlphaSlider.maximumValue = 1
widgetAlphaSlider.minimumValue = -1 widgetAlphaSlider.minimumValue = -1
widgetAlphaSlider.value = Float(selectedWidgetView.backgroundAlpha) widgetAlphaSlider.value = Float(selectedWidget.backgroundAlpha)
widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Alpha: %.2f", widgetAlphaSlider.value) widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Opacity: %.2f", widgetAlphaSlider.value)
case .labelAlpha: case .labelAlpha:
widgetAlphaSlider.maximumValue = 1 widgetAlphaSlider.maximumValue = 1
widgetAlphaSlider.minimumValue = -1 widgetAlphaSlider.minimumValue = -1
widgetAlphaSlider.value = Float(selectedWidgetView.labelAlpha) widgetAlphaSlider.value = Float(selectedWidget.labelAlpha)
widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Label alpha: %.2f", widgetAlphaSlider.value) widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Label opacity: %.2f", widgetAlphaSlider.value)
case .borderAlpha: case .borderAlpha:
widgetAlphaSlider.maximumValue = 1 widgetAlphaSlider.maximumValue = 1
widgetAlphaSlider.minimumValue = -1 widgetAlphaSlider.minimumValue = -1
widgetAlphaSlider.value = Float(selectedWidgetView.borderAlpha) widgetAlphaSlider.value = Float(selectedWidget.borderAlpha)
widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Border alpha: %.2f", widgetAlphaSlider.value) widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Border opacity: %.2f", widgetAlphaSlider.value)
case .highlightAlpha: case .highlightAlpha:
widgetAlphaSlider.maximumValue = 1 widgetAlphaSlider.maximumValue = 1
widgetAlphaSlider.minimumValue = 0 widgetAlphaSlider.minimumValue = 0
widgetAlphaSlider.value = Float(selectedWidgetView.highlightAlpha) widgetAlphaSlider.value = Float(selectedWidget.highlightAlpha)
widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Highlight alpha: %.2f", widgetAlphaSlider.value) widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Highlight opacity: %.2f", widgetAlphaSlider.value)
} }
} }
private func loadWidgetWidths() { private func loadWidgetWidths() {
guard let selectedWidgetView, widgetViewSelected else { return } guard let selectedWidget, widgetViewSelected else { return }
setHiddenForWidgetHighlights(selectedWidgetView) setHiddenForWidgetHighlights(selectedWidget)
switch borderWidthSliderMode { switch borderWidthSliderMode {
case .widgetBorderWidth: case .widgetBorderWidth:
widgetBorderWidthSlider.minimumValue = 0 widgetBorderWidthSlider.minimumValue = 0
widgetBorderWidthSlider.maximumValue = 8 widgetBorderWidthSlider.maximumValue = 8
widgetBorderWidthSlider.setValue(Float(selectedWidgetView.borderWidth), animated: false) widgetBorderWidthSlider.setValue(Float(selectedWidget.borderWidth), animated: false)
widgetBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Border width: %.2f", widgetBorderWidthSlider.value) widgetBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Border width: %.2f", widgetBorderWidthSlider.value)
case .highlightSize: case .highlightSize:
widgetBorderWidthSlider.minimumValue = 0.01 widgetBorderWidthSlider.minimumValue = 0.01
widgetBorderWidthSlider.maximumValue = 2 widgetBorderWidthSlider.maximumValue = 2
widgetBorderWidthSlider.setValue(Float(selectedWidgetView.highlightSizeFactor), animated: false) widgetBorderWidthSlider.setValue(Float(selectedWidget.highlightSizeFactor), animated: false)
widgetBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Highlight size: %.2f", widgetBorderWidthSlider.value) widgetBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Highlight size: %.2f", widgetBorderWidthSlider.value)
} }
} }
private func loadDecelerationRates() { private func loadDecelerationRates() {
guard let selectedWidgetView else { return } guard let selectedWidget else { return }
let value = decelerationRateSliderMode == .decelerationRateX ? selectedWidgetView.decelerationRateX : selectedWidgetView.decelerationRateY let value = decelerationRateSliderMode == .decelerationRateX ? selectedWidget.decelerationRateX : selectedWidget.decelerationRateY
decelerationRateSlider.value = Float(value) decelerationRateSlider.value = Float(value)
let key = decelerationRateSliderMode == .decelerationRateX ? "DecelerationRateX: %.3f " : "DecelerationRateY: %.3f " let key = decelerationRateSliderMode == .decelerationRateX ? "DecelerationRateX: %.3f " : "DecelerationRateY: %.3f "
decelerationRateLabel.text = LocalizationHelper.localizedString(forKey: key, decelerationRateSlider.value) decelerationRateLabel.text = LocalizationHelper.localizedString(forKey: key, decelerationRateSlider.value)
@@ -815,8 +815,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
widgetViewSelected = true widgetViewSelected = true
controllerLayerSelected = false controllerLayerSelected = false
if widgetView !== selectedWidgetView { if widgetView !== selectedWidget {
selectedWidgetView?.setAutoTapIntervalByText(str: autoTapField.text ?? "") selectedWidget?.setAutoTapIntervalByText(str: autoTapField.text ?? "")
} }
widgetView.hideAllHighlightLayersOfAllWidgets(selfIncluded: true) widgetView.hideAllHighlightLayersOfAllWidgets(selfIncluded: true)
@@ -824,7 +824,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
autoFitLabel(currentProfileLabel) autoFitLabel(currentProfileLabel)
currentProfileLabel.textAlignment = .left currentProfileLabel.textAlignment = .left
currentProfileLabel.text = LocalizationHelper.localizedString(forKey: " Profile: %@ Alias: %@ Cmd: %@ Parent: %@", profilesManager.getSelectedProfile().name, widgetView.widgetLabel, widgetView.cmdString, LocalizationHelper.localizedString(forKey:OnScreenWidgetView.mapping[widgetView.parentSequence]?.widgetLabel ?? "null")) currentProfileLabel.text = LocalizationHelper.localizedString(forKey: " Profile: %@ Alias: %@ Cmd: %@ Parent: %@", profilesManager.getSelectedProfile().name, widgetView.widgetLabel, widgetView.cmdString, LocalizationHelper.localizedString(forKey:OnScreenWidgetView.mapping[widgetView.parentSequence]?.widgetLabel ?? "null"))
if selectedWidgetView?.hasWalkSprintKeys == true { if selectedWidget?.hasWalkSprintKeys == true {
let cmdCounts = widgetView.comboButtonStrings.count let cmdCounts = widgetView.comboButtonStrings.count
currentProfileLabel.text = LocalizationHelper.localizedString(forKey: " Cmd: %@ Sprint: %@ Walk: %@ Parent: %@", currentProfileLabel.text = LocalizationHelper.localizedString(forKey: " Cmd: %@ Sprint: %@ Walk: %@ Parent: %@",
widgetView.cmdString, cmdCounts>0 ? widgetView.comboButtonStrings[0] : LocalizationHelper.localizedString(forKey: "null"), widgetView.cmdString, cmdCounts>0 ? widgetView.comboButtonStrings[0] : LocalizationHelper.localizedString(forKey: "null"),
@@ -990,12 +990,6 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
dockedAlphaSliderMoved(dockedAlphaSlider) dockedAlphaSliderMoved(dockedAlphaSlider)
buttonModeStack.isHidden = widgetView.widgetType != .button buttonModeStack.isHidden = widgetView.widgetType != .button
buttonModeSelector.setEnabled(!widgetView.isFunctionalButton, forSegmentAt: Int(ButtonMode.slideToToggle.rawValue))
buttonModeSelector.setEnabled((!widgetView.isFunctionalButton || widgetView.isFolder)
&& !widgetView.containsShortcutAction
, forSegmentAt: Int(ButtonMode.slideAndHold.rawValue))
// buttonModeSelector.setEnabled(!widgetView.isFolder, forSegmentAt: Int(ButtonMode.regular.rawValue))
buttonModeSelector.setEnabled(!widgetView.isFunctionalButton || widgetView.isTapToToggleException, forSegmentAt: Int(ButtonMode.tapToToggle.rawValue))
buttonModeSelector.selectedSegmentIndex = Int(widgetView.buttonMode.rawValue) buttonModeSelector.selectedSegmentIndex = Int(widgetView.buttonMode.rawValue)
collectedWidgetsStack.isHidden = !widgetView.isFolder collectedWidgetsStack.isHidden = !widgetView.isFolder
@@ -1047,7 +1041,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@objc private func widgetViewTapped(_ notification: Notification) { @objc private func widgetViewTapped(_ notification: Notification) {
guard let widgetView = notification.object as? OnScreenWidgetView else { return } guard let widgetView = notification.object as? OnScreenWidgetView else { return }
selectedWidgetView = widgetView selectedWidget = widgetView
layoutOSC.updateGuidelinesFor(onScreenWidget: widgetView) layoutOSC.updateGuidelinesFor(onScreenWidget: widgetView)
if bulkEditEnabled { if bulkEditEnabled {
bulkEditButtonTapped(bulkEditButton) // this will call refreshPanelForSelectedWidget too bulkEditButtonTapped(bulkEditButton) // this will call refreshPanelForSelectedWidget too
@@ -1065,7 +1059,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
enableCommonWidgetTools() enableCommonWidgetTools()
hideStickIndicators() hideStickIndicators()
widgetViewSelected = false widgetViewSelected = false
selectedWidgetView = nil selectedWidget = nil
autoTapStack.isHidden = true autoTapStack.isHidden = true
stickIndicatorOffsetStack.isHidden = true stickIndicatorOffsetStack.isHidden = true
sensitivityXStack.isHidden = true sensitivityXStack.isHidden = true
@@ -1090,7 +1084,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
widgetAlphaSlider.value = Float(alpha) widgetAlphaSlider.value = Float(alpha)
widgetSizeLabel.text = LocalizationHelper.localizedString(forKey: "Size: %.2f", sizeFactor) widgetSizeLabel.text = LocalizationHelper.localizedString(forKey: "Size: %.2f", sizeFactor)
widgetHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", sizeFactor) widgetHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", sizeFactor)
widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Alpha: %.2f", alpha) widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Opacity: %.2f", alpha)
if isIPhone() { if isIPhone() {
vibrationStyleStack.isHidden = false vibrationStyleStack.isHidden = false
if let style = OnScreenControls.layerVibrationStyleDic()?.object(forKey: controllerLayer.name ?? "") as? NSNumber { if let style = OnScreenControls.layerVibrationStyleDic()?.object(forKey: controllerLayer.name ?? "") as? NSNumber {
@@ -1148,13 +1142,13 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} else { } else {
present(alert, animated: true) present(alert, animated: true)
} }
} else if let selectedWidgetView { } else if let selectedWidget {
if selectedWidgetView.layoutChanges.count > 1 { if selectedWidget.layoutChanges.count > 1 {
selectedWidgetView.undoRelocation() selectedWidget.undoRelocation()
} else { } else {
present(alert, animated: true) present(alert, animated: true)
} }
undoButton.alpha = selectedWidgetView.layoutChanges.count > 1 ? 1.0 : 0.3 undoButton.alpha = selectedWidget.layoutChanges.count > 1 ? 1.0 : 0.3
} }
} }
@@ -1269,7 +1263,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
newWidget.tweakHighlightAlpha(alpha: widget.highlightAlpha) newWidget.tweakHighlightAlpha(alpha: widget.highlightAlpha)
newWidget.adjustBorder(width: widget.borderWidth) newWidget.adjustBorder(width: widget.borderWidth)
onScreenWidgetViews.add(newWidget) onScreenWidgetViews.add(newWidget)
selectedWidgetView = newWidget selectedWidget = newWidget
if !createNew { if !createNew {
onScreenWidgetViews.remove(widget) onScreenWidgetViews.remove(widget)
widget.removeFromSuperview() widget.removeFromSuperview()
@@ -1465,12 +1459,12 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
let params = payload.mutableCopy() as? NSMutableDictionary ?? NSMutableDictionary() let params = payload.mutableCopy() as? NSMutableDictionary ?? NSMutableDictionary()
let pickerAction = ((params["pickerAction"] as? String) ?? "").lowercased() let pickerAction = ((params["pickerAction"] as? String) ?? "").lowercased()
params.removeObject(forKey: "pickerAction") params.removeObject(forKey: "pickerAction")
if pickerAction == "modify", let selectedWidgetView { if pickerAction == "modify", let selectedWidget {
updateWidget(selectedWidgetView, params: params, createNew: false) updateWidget(selectedWidget, params: params, createNew: false)
return return
} }
if pickerAction == "create", controller.isEditMode, let selectedWidgetView { if pickerAction == "create", controller.isEditMode, let selectedWidget {
updateWidget(selectedWidgetView, params: params, createNew: true) updateWidget(selectedWidget, params: params, createNew: true)
return return
} }
createWidgetFromParams(params) createWidgetFromParams(params)
@@ -1478,7 +1472,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@IBAction func editTapped(_ sender: Any?) { @IBAction func editTapped(_ sender: Any?) {
GenericUtils.autoPopSoftKeyboard = false GenericUtils.autoPopSoftKeyboard = false
guard let selectedWidgetView else { guard let selectedWidget else {
AlertControllerUtil.autoCompletion = true AlertControllerUtil.autoCompletion = true
AlertControllerUtil.showAlert(in: self, title: "", message: LocalizationHelper.localizedString(forKey: "No widget selected"), withCancel: false, buttonTitle: "", countdown: 1, action: {}, completion: {}) AlertControllerUtil.showAlert(in: self, title: "", message: LocalizationHelper.localizedString(forKey: "No widget selected"), withCancel: false, buttonTitle: "", countdown: 1, action: {}, completion: {})
return return
@@ -1489,16 +1483,16 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
pickerViewController.tabIdentifiers = ["gamepad", "keyboard", "functional"] pickerViewController.tabIdentifiers = ["gamepad", "keyboard", "functional"]
pickerViewController.initialTabIdentifier = "gamepad" pickerViewController.initialTabIdentifier = "gamepad"
pickerViewController.isEditMode = true pickerViewController.isEditMode = true
pickerViewController.initialCmdString = selectedWidgetView.cmdString pickerViewController.initialCmdString = selectedWidget.cmdString
pickerViewController.initialButtonLabel = selectedWidgetView.widgetLabel pickerViewController.initialButtonLabel = selectedWidget.widgetLabel
pickerViewController.initialShape = selectedWidgetView.shape pickerViewController.initialShape = selectedWidget.shape
let nav = UINavigationController(rootViewController: pickerViewController) let nav = UINavigationController(rootViewController: pickerViewController)
nav.modalPresentationStyle = .overFullScreen nav.modalPresentationStyle = .overFullScreen
present(nav, animated: true) present(nav, animated: true)
return return
} }
presentLegacyEditWidgetAlert(for: selectedWidgetView) presentLegacyEditWidgetAlert(for: selectedWidget)
} }
@IBAction func saveTapped(_ sender: Any?) { @IBAction func saveTapped(_ sender: Any?) {
@@ -1536,8 +1530,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
let color = overlapping ? UIColor.red : trashCanStoryBoardColor ?? UIColor.systemTeal let color = overlapping ? UIColor.red : trashCanStoryBoardColor ?? UIColor.systemTeal
trashCanButton.tintColor = color trashCanButton.tintColor = color
trashCanButton.titleLabel?.textColor = color trashCanButton.titleLabel?.textColor = color
if overlapping, let selectedWidgetView { if overlapping, let selectedWidget {
OnScreenWidgetView.setFree(widget: selectedWidgetView) OnScreenWidgetView.setFree(widget: selectedWidget)
} }
undoButton.alpha = 1.0 undoButton.alpha = 1.0
} }
@@ -1547,7 +1541,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
private func clearSickInput() { private func clearSickInput() {
if selectedWidgetView != nil && widgetViewSelected { if selectedWidget != nil && widgetViewSelected {
OnScreenControls.shared()?.clearLeftStickTouchPadFlag() OnScreenControls.shared()?.clearLeftStickTouchPadFlag()
OnScreenControls.shared()?.clearRightStickTouchPadFlag() OnScreenControls.shared()?.clearRightStickTouchPadFlag()
} }
@@ -1743,7 +1737,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
componentSizeStack.isHidden = true componentSizeStack.isHidden = true
alphaSliderMode = .widgetAlpha alphaSliderMode = .widgetAlpha
widgetAlphaSlider.addTarget(self, action: #selector(widgetAlphaSliderMoved(_:)), for: .valueChanged) widgetAlphaSlider.addTarget(self, action: #selector(widgetAlphaSliderMoved(_:)), for: .valueChanged)
widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Alpha") widgetAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Opacity")
widgetAlphaLabel.isUserInteractionEnabled = true widgetAlphaLabel.isUserInteractionEnabled = true
widgetAlphaLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(switchAlphaSlider(_:)))) widgetAlphaLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(switchAlphaSlider(_:))))
borderWidthSliderMode = .widgetBorderWidth borderWidthSliderMode = .widgetBorderWidth
@@ -1809,7 +1803,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
autoDockTimerStack.isHidden = true; autoDockTimerStack.isHidden = true;
dockedAlphaSlider.addTarget(self, action: #selector(dockedAlphaSliderMoved(_:)), for: .valueChanged) dockedAlphaSlider.addTarget(self, action: #selector(dockedAlphaSliderMoved(_:)), for: .valueChanged)
dockedAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Docked alpha") dockedAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Docked opacity")
dockedAlphaStack.isHidden = true; dockedAlphaStack.isHidden = true;
let whiteAttrs: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.white] let whiteAttrs: [NSAttributedString.Key: Any] = [.foregroundColor: UIColor.white]
@@ -1844,20 +1838,20 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
bulkHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height") bulkHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height")
bulkAlphaSlider.addTarget(self, action: #selector(bulkAlphaSliderMoved(_:)), for: .valueChanged) bulkAlphaSlider.addTarget(self, action: #selector(bulkAlphaSliderMoved(_:)), for: .valueChanged)
bulkAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Alpha") bulkAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Opacity")
bulkBorderWidthSlider.addTarget(self, action: #selector(bulkBorderWidthSliderMoved(_:)), for: .valueChanged) bulkBorderWidthSlider.addTarget(self, action: #selector(bulkBorderWidthSliderMoved(_:)), for: .valueChanged)
bulkBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Border width") bulkBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Border width")
bulkLabelAlphaSlider.addTarget(self, action: #selector(bulkLabelAlphaSliderMoved(_:)), for: .valueChanged) bulkLabelAlphaSlider.addTarget(self, action: #selector(bulkLabelAlphaSliderMoved(_:)), for: .valueChanged)
bulkLabelAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Label alpha") bulkLabelAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Label opacity")
bulkBorderAlphaSlider.addTarget(self, action: #selector(bulkBorderAlphaSliderMoved(_:)), for: .valueChanged) bulkBorderAlphaSlider.addTarget(self, action: #selector(bulkBorderAlphaSliderMoved(_:)), for: .valueChanged)
bulkBorderAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Border alpha") bulkBorderAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Border opacity")
bulkHighlightAlphaSlider.addTarget(self, action: #selector(bulkHighlightAlphaSliderMoved(_:)), for: .valueChanged) bulkHighlightAlphaSlider.addTarget(self, action: #selector(bulkHighlightAlphaSliderMoved(_:)), for: .valueChanged)
bulkHighlightAlphaSlider.addTarget(self, action: #selector(bulkHighlightAlphaSliderMoveStopped(_:)), for: [.touchUpInside, .touchUpOutside]) bulkHighlightAlphaSlider.addTarget(self, action: #selector(bulkHighlightAlphaSliderMoveStopped(_:)), for: [.touchUpInside, .touchUpOutside])
bulkHighlightAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Highlight alpha") bulkHighlightAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Highlight opacity")
bulkHighlightSizeSlider.minimumValue = 0.01 bulkHighlightSizeSlider.minimumValue = 0.01
bulkHighlightSizeSlider.maximumValue = 2 bulkHighlightSizeSlider.maximumValue = 2
@@ -1916,7 +1910,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
func textFieldShouldReturn(_ textField: UITextField) -> Bool { func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == autoTapField { if textField == autoTapField {
textField.resignFirstResponder() textField.resignFirstResponder()
selectedWidgetView?.setAutoTapIntervalByText(str: textField.text ?? "") selectedWidget?.setAutoTapIntervalByText(str: textField.text ?? "")
} }
return true return true
} }
@@ -1930,14 +1924,14 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func widgetSizeSliderMoved(_ sender: UISlider) { @objc private func widgetSizeSliderMoved(_ sender: UISlider) {
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
selectedWidgetView.translatesAutoresizingMaskIntoConstraints = true selectedWidget.translatesAutoresizingMaskIntoConstraints = true
let aspectRatio = selectedWidgetView.heightFactor / selectedWidgetView.widthFactor let aspectRatio = selectedWidget.heightFactor / selectedWidget.widthFactor
selectedWidgetView.widthFactor = CGFloat(sender.value) selectedWidget.widthFactor = CGFloat(sender.value)
selectedWidgetView.heightFactor = min(max(CGFloat(sender.minimumValue), selectedWidgetView.widthFactor * aspectRatio), CGFloat(sender.maximumValue)) selectedWidget.heightFactor = min(max(CGFloat(sender.minimumValue), selectedWidget.widthFactor * aspectRatio), CGFloat(sender.maximumValue))
widgetSizeLabel.text = LocalizationHelper.localizedString(forKey: "Size: %.2f", sender.value) widgetSizeLabel.text = LocalizationHelper.localizedString(forKey: "Size: %.2f", sender.value)
widgetHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", selectedWidgetView.heightFactor) widgetHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", selectedWidget.heightFactor)
widgetHeightSlider.value = Float(selectedWidgetView.heightFactor) widgetHeightSlider.value = Float(selectedWidget.heightFactor)
} }
if let selectedControllerLayer, controllerLayerSelected { if let selectedControllerLayer, controllerLayerSelected {
layoutOSC.resizeControllerLayer(with: selectedControllerLayer, and: CGFloat(sender.value)) layoutOSC.resizeControllerLayer(with: selectedControllerLayer, and: CGFloat(sender.value))
@@ -1945,39 +1939,39 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func widgetSizeSliderTouchUp(_ sender: UISlider) { @objc private func widgetSizeSliderTouchUp(_ sender: UISlider) {
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
selectedWidgetView.isBeingResized = false selectedWidget.isBeingResized = false
} }
} }
} }
@objc private func widgetHeightSliderMoved(_ sender: UISlider) { @objc private func widgetHeightSliderMoved(_ sender: UISlider) {
widgetHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", sender.value) widgetHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", sender.value)
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
selectedWidgetView.translatesAutoresizingMaskIntoConstraints = true selectedWidget.translatesAutoresizingMaskIntoConstraints = true
if selectedWidgetView.shape == "round" { return } if selectedWidget.shape == "round" { return }
selectedWidgetView.heightFactor = CGFloat(sender.value) selectedWidget.heightFactor = CGFloat(sender.value)
} }
} }
@objc private func componentSizeSliderMoved(_ sender: UISlider) { @objc private func componentSizeSliderMoved(_ sender: UISlider) {
componentSizeLabel.text = LocalizationHelper.localizedString(forKey: "Component size: %.2f ", sender.value) componentSizeLabel.text = LocalizationHelper.localizedString(forKey: "Component size: %.2f ", sender.value)
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
selectedWidgetView.translatesAutoresizingMaskIntoConstraints = true selectedWidget.translatesAutoresizingMaskIntoConstraints = true
selectedWidgetView.componentSizeFactor = CGFloat(sender.value) selectedWidget.componentSizeFactor = CGFloat(sender.value)
} }
} }
@objc private func widgetAlphaSliderMoved(_ sender: UISlider) { @objc private func widgetAlphaSliderMoved(_ sender: UISlider) {
CATransaction.begin() CATransaction.begin()
CATransaction.setDisableActions(true) CATransaction.setDisableActions(true)
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
switch alphaSliderMode { switch alphaSliderMode {
case .widgetAlpha: selectedWidgetView.adjustTransparency(alpha: CGFloat(sender.value), tweakBorderAlpha: true) case .widgetAlpha: selectedWidget.adjustTransparency(alpha: CGFloat(sender.value), tweakBorderAlpha: true)
case .labelAlpha: selectedWidgetView.tweakLabelAlpha(alpha: CGFloat(sender.value)) case .labelAlpha: selectedWidget.tweakLabelAlpha(alpha: CGFloat(sender.value))
case .borderAlpha: selectedWidgetView.tweakBorderAlpha(alpha: CGFloat(sender.value)) case .borderAlpha: selectedWidget.tweakBorderAlpha(alpha: CGFloat(sender.value))
case .highlightAlpha: selectedWidgetView.tweakHighlightAlpha(alpha: CGFloat(sender.value)) case .highlightAlpha: selectedWidget.tweakHighlightAlpha(alpha: CGFloat(sender.value))
} }
loadWidgetAlphas() loadWidgetAlphas()
} }
@@ -1988,15 +1982,15 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func widgetBorderWidthSliderMoved(_ sender: UISlider) { @objc private func widgetBorderWidthSliderMoved(_ sender: UISlider) {
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
switch borderWidthSliderMode { switch borderWidthSliderMode {
case .widgetBorderWidth: case .widgetBorderWidth:
selectedWidgetView.adjustBorder(width: CGFloat(sender.value)) selectedWidget.adjustBorder(width: CGFloat(sender.value))
case .highlightSize: case .highlightSize:
selectedWidgetView.highlightSizeFactor = CGFloat(sender.value) selectedWidget.highlightSizeFactor = CGFloat(sender.value)
if selectedWidgetView.widgetType == .button { selectedWidgetView.setupButtonDownVisualEffectLayer() } if selectedWidget.widgetType == .button { selectedWidget.setupButtonDownVisualEffectLayer() }
if selectedWidgetView.hasL3R3Indicator { selectedWidgetView.setupL3R3Indicator() } if selectedWidget.hasL3R3Indicator { selectedWidget.setupL3R3Indicator() }
if selectedWidgetView.isDirectionPad { selectedWidgetView.setupLrudDirectionIndicatorlayers() } if selectedWidget.isDirectionPad { selectedWidget.setupLrudDirectionIndicatorlayers() }
} }
} }
loadWidgetWidths() loadWidgetWidths()
@@ -2004,7 +1998,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@objc private func bulkBorderWidthSliderMoved(_ sender: UISlider) { @objc private func bulkBorderWidthSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Border width: %.2f", sender.value) bulkBorderWidthLabel.text = LocalizationHelper.localizedString(forKey: "Border width: %.2f", sender.value)
if selectedWidget.isFolder { if selectedWidget.isFolder {
for sequence in selectedWidget.sequenceSet { for sequence in selectedWidget.sequenceSet {
@@ -2019,7 +2013,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkWidthSliderMoved(_ sender: UISlider) { @objc private func bulkWidthSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkWidthLabel.text = LocalizationHelper.localizedString(forKey: "Width: %.2f", sender.value) bulkWidthLabel.text = LocalizationHelper.localizedString(forKey: "Width: %.2f", sender.value)
if selectedWidget.isFolder { if selectedWidget.isFolder {
for sequence in selectedWidget.sequenceSet { for sequence in selectedWidget.sequenceSet {
@@ -2037,7 +2031,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkHeightSliderMoved(_ sender: UISlider) { @objc private func bulkHeightSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", sender.value) bulkHeightLabel.text = LocalizationHelper.localizedString(forKey: "Height: %.2f", sender.value)
if selectedWidget.isFolder { if selectedWidget.isFolder {
for sequence in selectedWidget.sequenceSet { for sequence in selectedWidget.sequenceSet {
@@ -2055,8 +2049,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkAlphaSliderMoved(_ sender: UISlider) { @objc private func bulkAlphaSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Alpha: %.2f", sender.value) bulkAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Opacity: %.2f", sender.value)
if selectedWidget.isFolder { if selectedWidget.isFolder {
for sequence in selectedWidget.sequenceSet { for sequence in selectedWidget.sequenceSet {
let widget = OnScreenWidgetView.mapping[sequence]; let widget = OnScreenWidgetView.mapping[sequence];
@@ -2073,8 +2067,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkLabelAlphaSliderMoved(_ sender: UISlider) { @objc private func bulkLabelAlphaSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkLabelAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Label alpha: %.2f", sender.value) bulkLabelAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Label opacity: %.2f", sender.value)
if selectedWidget.isFolder { if selectedWidget.isFolder {
for sequence in selectedWidget.sequenceSet { for sequence in selectedWidget.sequenceSet {
OnScreenWidgetView.mapping[sequence]?.tweakLabelAlpha(alpha: CGFloat(sender.value)) OnScreenWidgetView.mapping[sequence]?.tweakLabelAlpha(alpha: CGFloat(sender.value))
@@ -2088,8 +2082,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkBorderAlphaSliderMoved(_ sender: UISlider) { @objc private func bulkBorderAlphaSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkBorderAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Border alpha: %.2f", sender.value) bulkBorderAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Border opacity: %.2f", sender.value)
if selectedWidget.isFolder { if selectedWidget.isFolder {
for sequence in selectedWidget.sequenceSet { for sequence in selectedWidget.sequenceSet {
OnScreenWidgetView.mapping[sequence]?.tweakBorderAlpha(alpha: CGFloat(sender.value)) OnScreenWidgetView.mapping[sequence]?.tweakBorderAlpha(alpha: CGFloat(sender.value))
@@ -2103,8 +2097,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkHighlightAlphaSliderMoved(_ sender: UISlider) { @objc private func bulkHighlightAlphaSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkHighlightAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Highlight alpha: %.2f", sender.value) bulkHighlightAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Highlight opacity: %.2f", sender.value)
OnScreenWidgetView.isTweakingHighlight = true OnScreenWidgetView.isTweakingHighlight = true
if selectedWidget.isFolder { if selectedWidget.isFolder {
for sequence in selectedWidget.sequenceSet { for sequence in selectedWidget.sequenceSet {
@@ -2123,7 +2117,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkHighlightAlphaSliderMoveStopped(_ sender: UISlider) { @objc private func bulkHighlightAlphaSliderMoveStopped(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
OnScreenWidgetView.isTweakingHighlight = false OnScreenWidgetView.isTweakingHighlight = false
if selectedWidget.isFolder { if selectedWidget.isFolder {
@@ -2142,7 +2136,7 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkHighlightSizeSliderMoved(_ sender: UISlider) { @objc private func bulkHighlightSizeSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
bulkHighlightSizeLabel.text = LocalizationHelper.localizedString(forKey: "Highlight size: %.2f", sender.value) bulkHighlightSizeLabel.text = LocalizationHelper.localizedString(forKey: "Highlight size: %.2f", sender.value)
OnScreenWidgetView.isTweakingHighlight = true OnScreenWidgetView.isTweakingHighlight = true
CATransaction.begin() CATransaction.begin()
@@ -2177,34 +2171,60 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func autoDockTimerSliderMoved(_ sender: UISlider) { @objc private func autoDockTimerSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
selectedWidget.autoDockIdleDuration = TimeInterval(Int(sender.value)) selectedWidget.autoDockIdleDuration = TimeInterval(Int(sender.value))
autoDockTimerLabel.text = Int(sender.value) == 0 ? LocalizationHelper.localizedString(forKey: "Auto dock disabled", Int(sender.value)) : LocalizationHelper.localizedString(forKey: "Auto dock: %d s", Int(sender.value)) autoDockTimerLabel.text = Int(sender.value) == 0 ? LocalizationHelper.localizedString(forKey: "Auto dock disabled", Int(sender.value)) : LocalizationHelper.localizedString(forKey: "Auto dock: %d s", Int(sender.value))
return return
} }
@objc private func dockedAlphaSliderMoved(_ sender: UISlider) { @objc private func dockedAlphaSliderMoved(_ sender: UISlider) {
guard let selectedWidget = selectedWidgetView else {return} guard let selectedWidget = selectedWidget else {return}
selectedWidget.autoDockSettledAlpha = CGFloat(sender.value) selectedWidget.autoDockSettledAlpha = CGFloat(sender.value)
dockedAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Docked alpha: %d%%", Int(sender.value*100)) dockedAlphaLabel.text = LocalizationHelper.localizedString(forKey: "Docked opacity: %d%%", Int(sender.value*100))
return return
} }
@objc private func animationChanged(_ sender: UISegmentedControl) { @objc private func animationChanged(_ sender: UISegmentedControl) {
selectedWidgetView?.animatesTransition = sender.selectedSegmentIndex == 1 selectedWidget?.animatesTransition = sender.selectedSegmentIndex == 1
} }
@objc private func mouseDownButtonChanged(_ sender: UISegmentedControl) { @objc private func mouseDownButtonChanged(_ sender: UISegmentedControl) {
selectedWidgetView?.mouseButtonAction = MouseButtonAction(rawValue: sender.selectedSegmentIndex) ?? .hovering selectedWidget?.mouseButtonAction = MouseButtonAction(rawValue: sender.selectedSegmentIndex) ?? .hovering
} }
@objc private func buttonModeChanged(_ sender: UISegmentedControl) { @objc private func buttonModeChanged(_ sender: UISegmentedControl) {
selectedWidgetView?.buttonMode = ButtonMode(rawValue: sender.selectedSegmentIndex) ?? .slideToToggle if let selectedWidget {
switch sender.selectedSegmentIndex {
case ButtonMode.slideToToggle.rawValue where selectedWidget.isFunctionalButton:
self.handleInvalidButtonModeTipsFor(widget: selectedWidget, sender: sender)
case ButtonMode.slideAndHold.rawValue where (selectedWidget.isFunctionalButton && !selectedWidget.isFolder) || selectedWidget.containsShortcutAction:
self.handleInvalidButtonModeTipsFor(widget: selectedWidget, sender: sender)
case ButtonMode.tapToToggle.rawValue where selectedWidget.isFunctionalButton && !selectedWidget.isTapToToggleException:
self.handleInvalidButtonModeTipsFor(widget: selectedWidget, sender: sender)
default:
GenericUtils.handleButtonModeTip(in: self)
selectedWidget.buttonMode = ButtonMode(rawValue: sender.selectedSegmentIndex) ?? .slideToToggle
}
}
}
private func handleInvalidButtonModeTipsFor(widget: OnScreenWidgetView, sender: UISegmentedControl) {
AlertControllerUtil.showAlert(
in: self,
title: LocalizationHelper.localizedString(forKey: "Tips"),
message: "\n\(LocalizationHelper.localizedString(forKey: "invalidButtonModeTip"))\n\n\(LocalizationHelper.localizedString(forKey:widget.isFolder ? "folderButtonModeTip" : ""))",
withCancel: false,
buttonTitle: LocalizationHelper.localizedString(forKey: "Got it!"),
countdown: 0,
completion: {
sender.selectedSegmentIndex = sender.previousSelectedSegmentIndex
}
)
} }
@objc private func collectionHiddenChanged(_ sender: UISegmentedControl) { @objc private func collectionHiddenChanged(_ sender: UISegmentedControl) {
if let selectedWidgetView { if let selectedWidget {
OnScreenWidgetView.set(folded: sender.selectedSegmentIndex == 1, for: selectedWidgetView) OnScreenWidgetView.set(folded: sender.selectedSegmentIndex == 1, for: selectedWidget)
} }
self.bulkEditButton.isEnabled = sender.selectedSegmentIndex == 0 self.bulkEditButton.isEnabled = sender.selectedSegmentIndex == 0
self.importFromOtherButton.isEnabled = sender.selectedSegmentIndex == 0 self.importFromOtherButton.isEnabled = sender.selectedSegmentIndex == 0
@@ -2213,18 +2233,18 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func bulkMoveChanged(_ sender: UISegmentedControl) { @objc private func bulkMoveChanged(_ sender: UISegmentedControl) {
selectedWidgetView?.bulkMoveEnabled = sender.selectedSegmentIndex == 1 selectedWidget?.bulkMoveEnabled = sender.selectedSegmentIndex == 1
} }
@objc private func revealModeChanged(_ sender: UISegmentedControl) { @objc private func revealModeChanged(_ sender: UISegmentedControl) {
if let selectedWidgetView { if let selectedWidget {
selectedWidgetView.revealMode = RevealMode(rawValue: sender.selectedSegmentIndex) ?? .coexist selectedWidget.revealMode = RevealMode(rawValue: sender.selectedSegmentIndex) ?? .coexist
OnScreenWidgetView.set(folded: selectedWidgetView.folded, for: selectedWidgetView) OnScreenWidgetView.set(folded: selectedWidget.folded, for: selectedWidget)
} }
} }
@objc private func vibrationStyleChanged(_ sender: UISegmentedControl) { @objc private func vibrationStyleChanged(_ sender: UISegmentedControl) {
guard let selectedWidgetView = selectedWidgetView else {return} guard let selectedWidgetView = selectedWidget else {return}
if #available(iOS 13.0, *) { if #available(iOS 13.0, *) {
if sender.selectedSegmentIndex <= UIImpactFeedbackGenerator.FeedbackStyle.rigid.rawValue { if sender.selectedSegmentIndex <= UIImpactFeedbackGenerator.FeedbackStyle.rigid.rawValue {
@@ -2248,28 +2268,28 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
} }
@objc private func sensitivityXSliderMoved(_ sender: UISlider) { @objc private func sensitivityXSliderMoved(_ sender: UISlider) {
let key = selectedWidgetView?.hasSensitivityY == true ? "SensitivityX: %.2f" : "Sensitivity: %.2f" let key = selectedWidget?.hasSensitivityY == true ? "SensitivityX: %.2f" : "Sensitivity: %.2f"
sensitivityXLabel.text = LocalizationHelper.localizedString(forKey: key, sender.value) sensitivityXLabel.text = LocalizationHelper.localizedString(forKey: key, sender.value)
sensitivityYLabel.text = LocalizationHelper.localizedString(forKey: "SensitivityY: %.2f", sender.value) sensitivityYLabel.text = LocalizationHelper.localizedString(forKey: "SensitivityY: %.2f", sender.value)
sensitivityYSlider.value = sender.value sensitivityYSlider.value = sender.value
selectedWidgetView?.sensitivityFactorX = CGFloat(sender.value) selectedWidget?.sensitivityFactorX = CGFloat(sender.value)
selectedWidgetView?.sensitivityFactorY = CGFloat(sender.value) selectedWidget?.sensitivityFactorY = CGFloat(sender.value)
} }
@objc private func sensitivityYSliderMoved(_ sender: UISlider) { @objc private func sensitivityYSliderMoved(_ sender: UISlider) {
sensitivityYLabel.text = LocalizationHelper.localizedString(forKey: "SensitivityY: %.2f", sender.value) sensitivityYLabel.text = LocalizationHelper.localizedString(forKey: "SensitivityY: %.2f", sender.value)
selectedWidgetView?.sensitivityFactorY = CGFloat(sender.value) selectedWidget?.sensitivityFactorY = CGFloat(sender.value)
} }
@objc private func walkModeThresholdSliderMoved(_ sender: UISlider) { @objc private func walkModeThresholdSliderMoved(_ sender: UISlider) {
walkModeThresholdLabel.text = LocalizationHelper.localizedString(forKey: "Walkmode threshold: %.0f ", sender.value) walkModeThresholdLabel.text = LocalizationHelper.localizedString(forKey: "Walkmode threshold: %.0f ", sender.value)
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
selectedWidgetView.dWheelWalkModeThreshold = CGFloat(sender.value) selectedWidget.dWheelWalkModeThreshold = CGFloat(sender.value)
guard let onScreenControls = OnScreenControls.shared() else { return } guard let onScreenControls = OnScreenControls.shared() else { return }
if selectedWidgetView.touchPadString == "LSWHEEL" { if selectedWidget.touchPadString == "LSWHEEL" {
onScreenControls.sendLeftStickTouchPadEvent(0, CGFloat(sender.value)) onScreenControls.sendLeftStickTouchPadEvent(0, CGFloat(sender.value))
} }
if selectedWidgetView.touchPadString == "RSWHEEL" { if selectedWidget.touchPadString == "RSWHEEL" {
onScreenControls.sendRightStickTouchPadEvent(0, CGFloat(sender.value)) onScreenControls.sendRightStickTouchPadEvent(0, CGFloat(sender.value))
} }
} }
@@ -2277,17 +2297,17 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@objc private func minStickOffsetSliderMoved(_ sender: UISlider) { @objc private func minStickOffsetSliderMoved(_ sender: UISlider) {
minStickOffsetLabel.text = LocalizationHelper.localizedString(forKey: "Minimum offset: %.0f", sender.value) minStickOffsetLabel.text = LocalizationHelper.localizedString(forKey: "Minimum offset: %.0f", sender.value)
if let selectedWidgetView, widgetViewSelected { if let selectedWidget, widgetViewSelected {
selectedWidgetView.minStickOffset = CGFloat(sender.value) selectedWidget.minStickOffset = CGFloat(sender.value)
guard let onScreenControls = OnScreenControls.shared() else { return } guard let onScreenControls = OnScreenControls.shared() else { return }
if selectedWidgetView.touchPadString == "LSPAD" if selectedWidget.touchPadString == "LSPAD"
|| selectedWidgetView.touchPadString == "LSVPAD" || selectedWidget.touchPadString == "LSVPAD"
|| selectedWidgetView.touchPadString == "LSWHEEL" { || selectedWidget.touchPadString == "LSWHEEL" {
onScreenControls.sendLeftStickTouchPadEvent(CGFloat(sender.value), 0) onScreenControls.sendLeftStickTouchPadEvent(CGFloat(sender.value), 0)
} }
if selectedWidgetView.touchPadString == "RSPAD" if selectedWidget.touchPadString == "RSPAD"
|| selectedWidgetView.touchPadString == "RSVPAD" || selectedWidget.touchPadString == "RSVPAD"
|| selectedWidgetView.touchPadString == "RSWHEEL" { || selectedWidget.touchPadString == "RSWHEEL" {
onScreenControls.sendRightStickTouchPadEvent(CGFloat(sender.value), 0) onScreenControls.sendRightStickTouchPadEvent(CGFloat(sender.value), 0)
} }
} }
@@ -2295,18 +2315,18 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@objc private func slideThresholdSliderMoved(_ sender: UISlider) { @objc private func slideThresholdSliderMoved(_ sender: UISlider) {
slideThresholdLabel.text = LocalizationHelper.localizedString(forKey: "Slide threshold: %.1f ", sender.value) slideThresholdLabel.text = LocalizationHelper.localizedString(forKey: "Slide threshold: %.1f ", sender.value)
selectedWidgetView?.slideThreshold = CGFloat(sender.value) selectedWidget?.slideThreshold = CGFloat(sender.value)
} }
@objc private func sprintKeyActionChanged(_ sender: UISegmentedControl) { @objc private func sprintKeyActionChanged(_ sender: UISegmentedControl) {
selectedWidgetView?.sprintKeyActionType = OnScreenWidgetView.WalkSprintKeyActionType(rawValue: UInt8(sender.selectedSegmentIndex)) ?? .hold selectedWidget?.sprintKeyActionType = OnScreenWidgetView.WalkSprintKeyActionType(rawValue: UInt8(sender.selectedSegmentIndex)) ?? .hold
} }
@objc private func sprintKeyThresholdSliderMoved(_ sender: UISlider) { @objc private func sprintKeyThresholdSliderMoved(_ sender: UISlider) {
sprintKeyThresholdLabel.text = LocalizationHelper.localizedString(forKey: " Slide threshold: %0.2f ", sender.value) sprintKeyThresholdLabel.text = LocalizationHelper.localizedString(forKey: " Slide threshold: %0.2f ", sender.value)
autoFitLabel(sprintKeyThresholdLabel) autoFitLabel(sprintKeyThresholdLabel)
guard OnScreenWidgetView.editMode, let selectedWidgetView, widgetViewSelected else { return } guard OnScreenWidgetView.editMode, let selectedWidget, widgetViewSelected else { return }
if sender.value < walkKeyThresholdSlider.value { if sender.value < walkKeyThresholdSlider.value {
walkKeyThresholdSlider.value = sender.value walkKeyThresholdSlider.value = sender.value
@@ -2314,13 +2334,13 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
autoFitLabel(walkKeyThresholdLabel) autoFitLabel(walkKeyThresholdLabel)
} }
selectedWidgetView.sprintKeyThreshold = CGFloat(sender.value) selectedWidget.sprintKeyThreshold = CGFloat(sender.value)
selectedWidgetView.walkKeyThreshold = CGFloat(walkKeyThresholdSlider.value) selectedWidget.walkKeyThreshold = CGFloat(walkKeyThresholdSlider.value)
selectedWidgetView.updateMovementThresholdPreview() selectedWidget.updateMovementThresholdPreview()
} }
@objc private func walkKeyActionChanged(_ sender: UISegmentedControl) { @objc private func walkKeyActionChanged(_ sender: UISegmentedControl) {
selectedWidgetView?.walkKeyActionType = OnScreenWidgetView.WalkSprintKeyActionType(rawValue: UInt8(sender.selectedSegmentIndex)) ?? .hold selectedWidget?.walkKeyActionType = OnScreenWidgetView.WalkSprintKeyActionType(rawValue: UInt8(sender.selectedSegmentIndex)) ?? .hold
} }
@objc private func walkKeyThresholdSliderMoved(_ sender: UISlider) { @objc private func walkKeyThresholdSliderMoved(_ sender: UISlider) {
@@ -2331,50 +2351,50 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
walkKeyThresholdLabel.text = LocalizationHelper.localizedString(forKey: " Slide threshold: %0.2f ", sender.value) walkKeyThresholdLabel.text = LocalizationHelper.localizedString(forKey: " Slide threshold: %0.2f ", sender.value)
autoFitLabel(walkKeyThresholdLabel) autoFitLabel(walkKeyThresholdLabel)
guard OnScreenWidgetView.editMode, let selectedWidgetView, widgetViewSelected else { return } guard OnScreenWidgetView.editMode, let selectedWidget, widgetViewSelected else { return }
selectedWidgetView.walkKeyThreshold = CGFloat(sender.value) selectedWidget.walkKeyThreshold = CGFloat(sender.value)
selectedWidgetView.updateMovementThresholdPreview() selectedWidget.updateMovementThresholdPreview()
} }
@objc private func yawFactorSliderMoved(_ sender: UISlider) { @objc private func yawFactorSliderMoved(_ sender: UISlider) {
yawFactorLabel.text = LocalizationHelper.localizedString(forKey: "Yaw factor: %.2f", sender.value) yawFactorLabel.text = LocalizationHelper.localizedString(forKey: "Yaw factor: %.2f", sender.value)
pitchFactorLabel.text = LocalizationHelper.localizedString(forKey: "Pitch factor: %.2f", sender.value) pitchFactorLabel.text = LocalizationHelper.localizedString(forKey: "Pitch factor: %.2f", sender.value)
pitchFactorSlider.value = sender.value pitchFactorSlider.value = sender.value
selectedWidgetView?.yawFactor = CGFloat(sender.value) selectedWidget?.yawFactor = CGFloat(sender.value)
selectedWidgetView?.pitchFactor = CGFloat(sender.value) selectedWidget?.pitchFactor = CGFloat(sender.value)
} }
@objc private func pitchFactorSliderMoved(_ sender: UISlider) { @objc private func pitchFactorSliderMoved(_ sender: UISlider) {
pitchFactorLabel.text = LocalizationHelper.localizedString(forKey: "Pitch factor: %.2f", sender.value) pitchFactorLabel.text = LocalizationHelper.localizedString(forKey: "Pitch factor: %.2f", sender.value)
selectedWidgetView?.pitchFactor = CGFloat(sender.value) selectedWidget?.pitchFactor = CGFloat(sender.value)
} }
@objc private func rollFactorSliderMoved(_ sender: UISlider) { @objc private func rollFactorSliderMoved(_ sender: UISlider) {
rollFactorLabel.text = LocalizationHelper.localizedString(forKey: "Roll factor: %.2f", sender.value) rollFactorLabel.text = LocalizationHelper.localizedString(forKey: "Roll factor: %.2f", sender.value)
selectedWidgetView?.rollFactor = CGFloat(sender.value) selectedWidget?.rollFactor = CGFloat(sender.value)
} }
@objc private func decelerationRateSliderMoved(_ sender: UISlider) { @objc private func decelerationRateSliderMoved(_ sender: UISlider) {
if let selectedWidgetView { if let selectedWidget {
switch decelerationRateSliderMode { switch decelerationRateSliderMode {
case .decelerationRateX: selectedWidgetView.decelerationRateX = CGFloat(sender.value) case .decelerationRateX: selectedWidget.decelerationRateX = CGFloat(sender.value)
case .decelerationRateY: selectedWidgetView.decelerationRateY = CGFloat(sender.value) case .decelerationRateY: selectedWidget.decelerationRateY = CGFloat(sender.value)
} }
} }
loadDecelerationRates() loadDecelerationRates()
} }
@objc private func anchorModeChanged(_ sender: UISegmentedControl) { @objc private func anchorModeChanged(_ sender: UISegmentedControl) {
if let selectedWidgetView { if let selectedWidget {
selectedWidgetView.touchPointAnchored = sender.selectedSegmentIndex == 1 selectedWidget.touchPointAnchored = sender.selectedSegmentIndex == 1
componentSizeStack.isHidden = sender.selectedSegmentIndex != 0 componentSizeStack.isHidden = sender.selectedSegmentIndex != 0
stickIndicatorOffsetStack.isHidden = sender.selectedSegmentIndex != 1 stickIndicatorOffsetStack.isHidden = sender.selectedSegmentIndex != 1
stickIndicatorOffsetSlider.value = Float(selectedWidgetView.stickIndicatorOffset) stickIndicatorOffsetSlider.value = Float(selectedWidget.stickIndicatorOffset)
self.stickIndicatorOffsetSliderMoved(stickIndicatorOffsetSlider) self.stickIndicatorOffsetSliderMoved(stickIndicatorOffsetSlider)
autoFitStack(self.widgetPanelStack) autoFitStack(self.widgetPanelStack)
if selectedWidgetView.isDirectionPad { if selectedWidget.isDirectionPad {
sensitivityXSlider.value = sender.selectedSegmentIndex == 0 ? 0.0 : 6.5 sensitivityXSlider.value = sender.selectedSegmentIndex == 0 ? 0.0 : 6.5
sensitivityXSliderMoved(sensitivityXSlider) sensitivityXSliderMoved(sensitivityXSlider)
} }
@@ -2383,8 +2403,8 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
@objc private func stickIndicatorOffsetSliderMoved(_ sender: UISlider) { @objc private func stickIndicatorOffsetSliderMoved(_ sender: UISlider) {
stickIndicatorOffsetLabel.text = LocalizationHelper.localizedString(forKey: "Indicator offset: %.0f", sender.value) stickIndicatorOffsetLabel.text = LocalizationHelper.localizedString(forKey: "Indicator offset: %.0f", sender.value)
if let selectedWidgetView { if let selectedWidget {
selectedWidgetView.stickIndicatorOffset = CGFloat(sender.value) selectedWidget.stickIndicatorOffset = CGFloat(sender.value)
} }
} }
@@ -2416,6 +2436,9 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
if widgetPanelMovedByTouch { if widgetPanelMovedByTouch {
latestTouchLocation = touch.location(in: view) latestTouchLocation = touch.location(in: view)
} }
if widgetPanelTouched(touch), selectedWidget != nil {
GenericUtils.handleWidgetPanelTip(in: self)
}
} }
for touch in touches { for touch in touches {
var touchLocation = touch.location(in: view) var touchLocation = touch.location(in: view)
@@ -2446,17 +2469,17 @@ final class LayoutOnScreenControlsViewController: UIViewController, OnScreenWidg
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
widgetPanelStack.isUserInteractionEnabled = true widgetPanelStack.isUserInteractionEnabled = true
if let selectedWidgetView { if let selectedWidget {
view.insertSubview(selectedWidgetView, belowSubview: widgetPanelStack) view.insertSubview(selectedWidget, belowSubview: widgetPanelStack)
if selectedWidgetView.widgetType == .touchPad { if selectedWidget.widgetType == .touchPad {
view.sendSubviewToBack(selectedWidgetView) view.sendSubviewToBack(selectedWidget)
} }
} }
if !isToolbarHidden, let selectedWidgetView, layerIsOverlappingWithTrashcanButton(selectedWidgetView.layer), selectedWidgetView.firstTouchMoved { if !isToolbarHidden, let selectedWidget, layerIsOverlappingWithTrashcanButton(selectedWidget.layer), selectedWidget.firstTouchMoved {
OnScreenWidgetView.setFree(widget: selectedWidgetView) OnScreenWidgetView.setFree(widget: selectedWidget)
OnScreenWidgetView.removeWidgetFromMappings(key: selectedWidgetView.sequence) OnScreenWidgetView.removeWidgetFromMappings(key: selectedWidget.sequence)
selectedWidgetView.removeFromSuperview() selectedWidget.removeFromSuperview()
onScreenWidgetViews.remove(selectedWidgetView) onScreenWidgetViews.remove(selectedWidget)
} }
if !isToolbarHidden, let draggedLayer = layoutOSC.layerBeingDragged, layerIsOverlappingWithTrashcanButton(draggedLayer) { if !isToolbarHidden, let draggedLayer = layoutOSC.layerBeingDragged, layerIsOverlappingWithTrashcanButton(draggedLayer) {
draggedLayer.isHidden = true draggedLayer.isHidden = true
+12 -12
View File
@@ -2,13 +2,13 @@
"sourceLanguage" : "en", "sourceLanguage" : "en",
"strings" : { "strings" : {
"1sF-08-aCr.text" : { "1sF-08-aCr.text" : {
"comment" : "Class = \"UILabel\"; text = \"Highlight alpha\"; ObjectID = \"1sF-08-aCr\";", "comment" : "Class = \"UILabel\"; text = \"Highlight opacity\"; ObjectID = \"1sF-08-aCr\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Highlight alpha" "value" : "Highlight opacity"
} }
} }
} }
@@ -4383,13 +4383,13 @@
} }
}, },
"kSX-ci-kx5.text" : { "kSX-ci-kx5.text" : {
"comment" : "Class = \"UILabel\"; text = \"Label alpha\"; ObjectID = \"kSX-ci-kx5\";", "comment" : "Class = \"UILabel\"; text = \"Label opacity\"; ObjectID = \"kSX-ci-kx5\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Label alpha" "value" : "Label opacity"
} }
} }
} }
@@ -5505,13 +5505,13 @@
} }
}, },
"Pwa-YK-6Q2.text" : { "Pwa-YK-6Q2.text" : {
"comment" : "Class = \"UILabel\"; text = \"Alpha\"; ObjectID = \"Pwa-YK-6Q2\";", "comment" : "Class = \"UILabel\"; text = \"Opacity\"; ObjectID = \"Pwa-YK-6Q2\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Alpha" "value" : "Opacity"
} }
} }
} }
@@ -5669,13 +5669,13 @@
} }
}, },
"qFn-D7-7aD.text" : { "qFn-D7-7aD.text" : {
"comment" : "Class = \"UILabel\"; text = \"Docked alpha\"; ObjectID = \"qFn-D7-7aD\";", "comment" : "Class = \"UILabel\"; text = \"Docked opacity\"; ObjectID = \"qFn-D7-7aD\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Docked alpha" "value" : "Docked opacity"
} }
} }
} }
@@ -5975,13 +5975,13 @@
} }
}, },
"sAF-Vy-ZzK.text" : { "sAF-Vy-ZzK.text" : {
"comment" : "Class = \"UILabel\"; text = \"Border alpha\"; ObjectID = \"sAF-Vy-ZzK\";", "comment" : "Class = \"UILabel\"; text = \"Border opacity\"; ObjectID = \"sAF-Vy-ZzK\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Border alpha" "value" : "Border opacity"
} }
} }
} }
@@ -6989,13 +6989,13 @@
} }
}, },
"yF0-Tu-L8X.text" : { "yF0-Tu-L8X.text" : {
"comment" : "Class = \"UILabel\"; text = \"Alpha\"; ObjectID = \"yF0-Tu-L8X\";", "comment" : "Class = \"UILabel\"; text = \"Opacity\"; ObjectID = \"yF0-Tu-L8X\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Alpha" "value" : "Opacity"
} }
} }
} }
+10 -10
View File
@@ -284,13 +284,13 @@
} }
}, },
"4Kd-Cc-aYN.text" : { "4Kd-Cc-aYN.text" : {
"comment" : "Class = \"UILabel\"; text = \"Highlight alpha\"; ObjectID = \"4Kd-Cc-aYN\";", "comment" : "Class = \"UILabel\"; text = \"Highlight opacity\"; ObjectID = \"4Kd-Cc-aYN\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Highlight alpha" "value" : "Highlight opacity"
} }
} }
} }
@@ -914,13 +914,13 @@
} }
}, },
"9Dr-3c-z61.text" : { "9Dr-3c-z61.text" : {
"comment" : "Class = \"UILabel\"; text = \"Label alpha\"; ObjectID = \"9Dr-3c-z61\";", "comment" : "Class = \"UILabel\"; text = \"Label opacity\"; ObjectID = \"9Dr-3c-z61\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Label alpha" "value" : "Label opacity"
} }
} }
} }
@@ -2390,13 +2390,13 @@
} }
}, },
"eRy-My-vvU.text" : { "eRy-My-vvU.text" : {
"comment" : "Class = \"UILabel\"; text = \"Border alpha\"; ObjectID = \"eRy-My-vvU\";", "comment" : "Class = \"UILabel\"; text = \"Border opacity\"; ObjectID = \"eRy-My-vvU\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Border alpha" "value" : "Border opacity"
} }
} }
} }
@@ -3332,13 +3332,13 @@
} }
}, },
"kxI-bn-pRU.text" : { "kxI-bn-pRU.text" : {
"comment" : "Class = \"UILabel\"; text = \"Docked alpha\"; ObjectID = \"kxI-bn-pRU\";", "comment" : "Class = \"UILabel\"; text = \"Docked opacity\"; ObjectID = \"kxI-bn-pRU\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Docked alpha" "value" : "Docked opacity"
} }
} }
} }
@@ -5204,13 +5204,13 @@
} }
}, },
"qPQ-U2-aSg.text" : { "qPQ-U2-aSg.text" : {
"comment" : "Class = \"UILabel\"; text = \"Alpha\"; ObjectID = \"qPQ-U2-aSg\";", "comment" : "Class = \"UILabel\"; text = \"Opacity\"; ObjectID = \"qPQ-U2-aSg\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "new", "state" : "new",
"value" : "Alpha" "value" : "Opacity"
} }
} }
} }