- reduce pressure curve tool tips

- fixed crash in pressure curve tool drawing stage
- initial pencil move force tweak
- frame queue tweaks demo
This commit is contained in:
True Zhuanjia committed 2026-02-06 15:27:29 +08:00
1 parent fa32d157ca
commit fa164f0e02
20 files changed
+445 -107

No files matched your search

+7 -1
View File
@@ -21,6 +21,7 @@ import UIKit
@objc public static var actionCancelled:Bool = false @objc public static var actionCancelled:Bool = false
@objc public static var alertController:UIAlertController = UIAlertController() @objc public static var alertController:UIAlertController = UIAlertController()
@objc public static var cancelButtonString:String = "Cancel" @objc public static var cancelButtonString:String = "Cancel"
@objc public static var autoCompletion:Bool = false
@objc class func showAlert( @objc class func showAlert(
in viewController: UIViewController, in viewController: UIViewController,
@@ -51,7 +52,7 @@ import UIKit
confirmAction.isEnabled = false confirmAction.isEnabled = false
if withCancel {alertController.addAction(cancelAction)} if withCancel {alertController.addAction(cancelAction)}
if buttonTitle != "" {alertController.addAction(confirmAction)} if buttonTitle != "" && !autoCompletion {alertController.addAction(confirmAction)}
if(countdown == 0) { if(countdown == 0) {
confirmAction.setValue(buttonTitle, forKey: "title") confirmAction.setValue(buttonTitle, forKey: "title")
@@ -72,6 +73,11 @@ import UIKit
timer.cancel() timer.cancel()
confirmAction.isEnabled = true confirmAction.isEnabled = true
confirmAction.setValue(buttonTitle, forKey: "title") confirmAction.setValue(buttonTitle, forKey: "title")
if autoCompletion {
autoCompletion = false
alertController.dismiss(animated: false)
return
}
} else { } else {
confirmAction.setValue("\(remainingSeconds)", forKey: "title") confirmAction.setValue("\(remainingSeconds)", forKey: "title")
} }
+49 -5
View File
@@ -1782,7 +1782,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="v6i-HA-XRx"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="v6i-HA-XRx">
<rect key="frame" x="440" y="1405" width="380" height="56.5"/> <rect key="frame" x="440" y="1545" width="380" height="56.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Switch Gyro by Controller" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="26O-xW-5EH"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Switch Gyro by Controller" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="26O-xW-5EH">
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
@@ -1990,6 +1990,46 @@
<constraint firstAttribute="height" constant="31" id="pV0-m0-1pz"/> <constraint firstAttribute="height" constant="31" id="pV0-m0-1pz"/>
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="A31-WC-As7">
<rect key="frame" x="441" y="1363" width="280" height="31"/>
<subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable Timebase" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cpg-mq-kYj" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="130" height="31"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="StG-nI-WpK">
<rect key="frame" x="150" y="0.0" width="132" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="130" id="lFV-eP-bfD"/>
</constraints>
</switch>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="31" id="seO-0F-yIw"/>
</constraints>
</stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="e0Q-XV-ydj">
<rect key="frame" x="441" y="1402" width="260" height="31"/>
<subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Async Deueue" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="X0u-7f-F86" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="110" height="31"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="auR-cw-77D">
<rect key="frame" x="130" y="0.0" width="132" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="130" id="mZn-6A-4OO"/>
</constraints>
</switch>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="31" id="UK8-ck-1zc"/>
</constraints>
</stackView>
</subviews> </subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view> </view>
@@ -1997,6 +2037,8 @@
<connections> <connections>
<outlet property="appThemeSelector" destination="wi6-L4-KwS" id="mf9-YY-eyE"/> <outlet property="appThemeSelector" destination="wi6-L4-KwS" id="mf9-YY-eyE"/>
<outlet property="appThemeStack" destination="Wf6-BA-Mdv" id="hlq-bB-S8N"/> <outlet property="appThemeStack" destination="Wf6-BA-Mdv" id="hlq-bB-S8N"/>
<outlet property="asyncFrameDequeueStack" destination="e0Q-XV-ydj" id="7TK-zc-BqI"/>
<outlet property="asyncFrameDequeueSwitch" destination="auR-cw-77D" id="SYx-KY-cqs"/>
<outlet property="audioConfigSelector" destination="iZL-dA-jk9" id="Yja-os-o6g"/> <outlet property="audioConfigSelector" destination="iZL-dA-jk9" id="Yja-os-o6g"/>
<outlet property="audioConfigStack" destination="qnG-5F-2YY" id="kFX-VK-vuK"/> <outlet property="audioConfigStack" destination="qnG-5F-2YY" id="kFX-VK-vuK"/>
<outlet property="audioEngineSelector" destination="85A-d5-pLE" id="Ads-EZ-Bpm"/> <outlet property="audioEngineSelector" destination="85A-d5-pLE" id="Ads-EZ-Bpm"/>
@@ -2046,6 +2088,8 @@
<outlet property="frameQueueSizeLabel" destination="Ce3-FM-vIh" id="90D-Tq-OGd"/> <outlet property="frameQueueSizeLabel" destination="Ce3-FM-vIh" id="90D-Tq-OGd"/>
<outlet property="frameQueueSizeSlider" destination="oZa-8Y-icz" id="Jo1-Fx-UMw"/> <outlet property="frameQueueSizeSlider" destination="oZa-8Y-icz" id="Jo1-Fx-UMw"/>
<outlet property="frameQueueSizeStack" destination="MML-c1-D5j" id="82B-r7-Zbh"/> <outlet property="frameQueueSizeStack" destination="MML-c1-D5j" id="82B-r7-Zbh"/>
<outlet property="frameTimebaseStack" destination="A31-WC-As7" id="vcp-SE-PuI"/>
<outlet property="frameTimebaseSwitch" destination="StG-nI-WpK" id="yYY-DO-U1D"/>
<outlet property="framerateSelector" destination="8hF-kb-2uV" id="dfT-hb-csE"/> <outlet property="framerateSelector" destination="8hF-kb-2uV" id="dfT-hb-csE"/>
<outlet property="fullColorRangeStack" destination="iPd-Rg-St7" id="iPd-Out-Let"/> <outlet property="fullColorRangeStack" destination="iPd-Rg-St7" id="iPd-Out-Let"/>
<outlet property="fullColorRangeSwitch" destination="iPd-Wt-Ch9" id="iPd-Out-Swt"/> <outlet property="fullColorRangeSwitch" destination="iPd-Wt-Ch9" id="iPd-Out-Swt"/>
@@ -3106,7 +3150,7 @@
<image name="tray.full.fill" catalog="system" width="128" height="88"/> <image name="tray.full.fill" catalog="system" width="128" height="88"/>
<image name="video.and.waveform" catalog="system" width="128" height="94"/> <image name="video.and.waveform" catalog="system" width="128" height="94"/>
<systemColor name="linkColor"> <systemColor name="linkColor">
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>
<systemColor name="secondarySystemGroupedBackgroundColor"> <systemColor name="secondarySystemGroupedBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -3115,13 +3159,13 @@
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor> </systemColor>
<systemColor name="systemBrownColor"> <systemColor name="systemBrownColor">
<color red="0.67450980392156867" green="0.49803921568627452" blue="0.36862745098039218" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.63529411759999999" green="0.51764705879999995" blue="0.36862745099999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>
<systemColor name="systemGray3Color"> <systemColor name="systemGray3Color">
<color red="0.7803921568627451" green="0.7803921568627451" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.78039215689999997" green="0.78039215689999997" blue="0.80000000000000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>
<systemColor name="systemTealColor"> <systemColor name="systemTealColor">
<color red="0.0" green="0.76470588235294112" blue="0.81568627450980391" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.18823529410000001" green="0.69019607839999997" blue="0.78039215689999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>
</resources> </resources>
</document> </document>
+56 -12
View File
@@ -1931,7 +1931,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="IHx-FO-ctr" userLabel="frameQueueSize Stack"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="IHx-FO-ctr" userLabel="frameQueueSize Stack">
<rect key="frame" x="437" y="1973" width="380" height="89.5"/> <rect key="frame" x="456" y="2063" width="380" height="89.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Frames to Buffer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r8X-jt-JfH"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Frames to Buffer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="r8X-jt-JfH">
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
@@ -2020,7 +2020,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="U0H-kh-QLS" userLabel="framePacing Stack"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="U0H-kh-QLS" userLabel="framePacing Stack">
<rect key="frame" x="437" y="2081" width="380" height="56.5"/> <rect key="frame" x="456" y="2171" width="380" height="56.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Frame Pacing" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Cvx-kQ-L3H" userLabel="Frame Pacing Mode"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Frame Pacing" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Cvx-kQ-L3H" userLabel="Frame Pacing Mode">
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
@@ -2344,7 +2344,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="qaV-ZR-fo7"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="qaV-ZR-fo7">
<rect key="frame" x="437" y="2464" width="380" height="55.5"/> <rect key="frame" x="459" y="2763" width="380" height="55.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Slide Distance Threshold" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bsU-vw-dTl" userLabel="uiLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Slide Distance Threshold" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bsU-vw-dTl" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/>
@@ -2364,7 +2364,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="kiR-q0-FQX" userLabel="hapticEngineStack"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="kiR-q0-FQX" userLabel="hapticEngineStack">
<rect key="frame" x="437" y="2159" width="380" height="56.5"/> <rect key="frame" x="459" y="2458" width="380" height="56.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Haptic Engine" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ldr-kv-d7n" userLabel="hapticEngine"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Haptic Engine" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ldr-kv-d7n" userLabel="hapticEngine">
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
@@ -2390,7 +2390,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Wpg-TL-KJy" userLabel="appThemeStack"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Wpg-TL-KJy" userLabel="appThemeStack">
<rect key="frame" x="437" y="2241" width="380" height="56.5"/> <rect key="frame" x="459" y="2540" width="380" height="56.5"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Theme" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yF6-p8-b2s"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Theme" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yF6-p8-b2s">
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
@@ -2435,7 +2435,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="N0i-z6-WgC" userLabel="singleTapSensitivityStack"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="N0i-z6-WgC" userLabel="singleTapSensitivityStack">
<rect key="frame" x="437" y="2383" width="380" height="55.5"/> <rect key="frame" x="459" y="2682" width="380" height="55.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Tap Sensitivity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WzD-wo-Wum"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Single Tap Sensitivity" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WzD-wo-Wum">
<rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="20.5"/>
@@ -2599,7 +2599,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="cNd-hI-JAS" userLabel="touchModeStack2"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="cNd-hI-JAS" userLabel="touchModeStack2">
<rect key="frame" x="437" y="2604" width="380" height="31"/> <rect key="frame" x="459" y="2903" width="380" height="31"/>
<subviews> <subviews>
<segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="n8C-pt-nPE" userLabel="Touch Mode Selector"> <segmentedControl verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" apportionsSegmentWidthsByContent="YES" segmentControlStyle="plain" selectedSegmentIndex="1" translatesAutoresizingMaskIntoConstraints="NO" id="n8C-pt-nPE" userLabel="Touch Mode Selector">
<rect key="frame" x="0.0" y="0.0" width="380" height="32"/> <rect key="frame" x="0.0" y="0.0" width="380" height="32"/>
@@ -2682,7 +2682,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="xyO-r6-abA"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="xyO-r6-abA">
<rect key="frame" x="434" y="2708" width="300" height="31"/> <rect key="frame" x="456" y="3007" width="300" height="31"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Controller → Mouse" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="F0O-Ht-fW5" userLabel="uiLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Controller → Mouse" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="F0O-Ht-fW5" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="150" height="31"/> <rect key="frame" x="0.0" y="0.0" width="150" height="31"/>
@@ -2702,7 +2702,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="QuI-NM-qCU"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="QuI-NM-qCU">
<rect key="frame" x="437" y="2838" width="380" height="55.5"/> <rect key="frame" x="459" y="3137" width="380" height="55.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Curve Exponent" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AEN-EU-8LZ" userLabel="uiLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Curve Exponent" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AEN-EU-8LZ" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/>
@@ -2722,7 +2722,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="jxy-UY-jFk"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="jxy-UY-jFk">
<rect key="frame" x="437" y="2763" width="380" height="55.5"/> <rect key="frame" x="459" y="3062" width="380" height="55.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Pointer Velocity" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="H3s-ud-yqh" userLabel="uiLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Pointer Velocity" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="H3s-ud-yqh" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/>
@@ -2807,7 +2807,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Twt-JJ-ihg"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Twt-JJ-ihg">
<rect key="frame" x="437" y="2919" width="380" height="55.5"/> <rect key="frame" x="459" y="3218" width="380" height="55.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Left Stick Minimum Offset" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="whI-oR-V8o" userLabel="uiLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Left Stick Minimum Offset" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="whI-oR-V8o" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/>
@@ -2827,7 +2827,7 @@
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="aQs-Ww-sPZ"> <stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="aQs-Ww-sPZ">
<rect key="frame" x="437" y="2993" width="380" height="55.5"/> <rect key="frame" x="459" y="3292" width="380" height="55.5"/>
<subviews> <subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Right Stick Minimum Offset" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="q6s-4H-y9n" userLabel="uiLabel"> <label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Right Stick Minimum Offset" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="q6s-4H-y9n" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/> <rect key="frame" x="0.0" y="0.0" width="380" height="16.5"/>
@@ -2846,6 +2846,46 @@
<constraint firstAttribute="width" constant="380" id="tSR-LD-qKK"/> <constraint firstAttribute="width" constant="380" id="tSR-LD-qKK"/>
</constraints> </constraints>
</stackView> </stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="HCc-SK-NBk">
<rect key="frame" x="459" y="2252" width="280" height="31"/>
<subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable Timebase" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="P4N-i6-1zD" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="130" height="31"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bwf-wJ-EC2">
<rect key="frame" x="150" y="0.0" width="132" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="130" id="KUb-Mq-m9s"/>
</constraints>
</switch>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="31" id="qzI-PN-1ml"/>
</constraints>
</stackView>
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="dZ3-os-MKX">
<rect key="frame" x="459" y="2291" width="260" height="31"/>
<subviews>
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Async Deueue" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="e1n-pw-04X" userLabel="uiLabel">
<rect key="frame" x="0.0" y="0.0" width="110" height="31"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="19e-9S-OgQ">
<rect key="frame" x="130" y="0.0" width="132" height="31"/>
<constraints>
<constraint firstAttribute="width" constant="130" id="hFO-BO-ck5"/>
</constraints>
</switch>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="31" id="O8n-y9-TrQ"/>
</constraints>
</stackView>
</subviews> </subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view> </view>
@@ -2853,6 +2893,8 @@
<connections> <connections>
<outlet property="appThemeSelector" destination="pNz-vd-Sr9" id="nYB-7o-wkT"/> <outlet property="appThemeSelector" destination="pNz-vd-Sr9" id="nYB-7o-wkT"/>
<outlet property="appThemeStack" destination="Wpg-TL-KJy" id="Vhd-oB-Sy3"/> <outlet property="appThemeStack" destination="Wpg-TL-KJy" id="Vhd-oB-Sy3"/>
<outlet property="asyncFrameDequeueStack" destination="dZ3-os-MKX" id="jfS-Q7-GAV"/>
<outlet property="asyncFrameDequeueSwitch" destination="19e-9S-OgQ" id="lgy-q2-16O"/>
<outlet property="audioConfigSelector" destination="hfR-K8-Ti4" id="4La-bI-jLq"/> <outlet property="audioConfigSelector" destination="hfR-K8-Ti4" id="4La-bI-jLq"/>
<outlet property="audioConfigStack" destination="Rld-CY-qzs" id="dmf-m8-sor"/> <outlet property="audioConfigStack" destination="Rld-CY-qzs" id="dmf-m8-sor"/>
<outlet property="audioEngineSelector" destination="pVq-EW-Dta" id="fcu-q8-UNI"/> <outlet property="audioEngineSelector" destination="pVq-EW-Dta" id="fcu-q8-UNI"/>
@@ -2900,6 +2942,8 @@
<outlet property="frameQueueSizeLabel" destination="r8X-jt-JfH" id="Tr9-eb-bIx"/> <outlet property="frameQueueSizeLabel" destination="r8X-jt-JfH" id="Tr9-eb-bIx"/>
<outlet property="frameQueueSizeSlider" destination="thv-JE-onX" id="gKD-6c-5tw"/> <outlet property="frameQueueSizeSlider" destination="thv-JE-onX" id="gKD-6c-5tw"/>
<outlet property="frameQueueSizeStack" destination="IHx-FO-ctr" id="gob-Ea-Avh"/> <outlet property="frameQueueSizeStack" destination="IHx-FO-ctr" id="gob-Ea-Avh"/>
<outlet property="frameTimebaseStack" destination="HCc-SK-NBk" id="xts-bc-f0C"/>
<outlet property="frameTimebaseSwitch" destination="bwf-wJ-EC2" id="fwl-GA-bQ6"/>
<outlet property="framerateSelector" destination="dAN-Gy-Eg7" id="tMv-Va-PhO"/> <outlet property="framerateSelector" destination="dAN-Gy-Eg7" id="tMv-Va-PhO"/>
<outlet property="fullColorRangeStack" destination="fRg-Rn-St7" id="fRg-Out-Let"/> <outlet property="fullColorRangeStack" destination="fRg-Rn-St7" id="fRg-Out-Let"/>
<outlet property="fullColorRangeSwitch" destination="fRs-Wt-Ch9" id="fRs-Out-Let"/> <outlet property="fullColorRangeSwitch" destination="fRs-Wt-Ch9" id="fRs-Out-Let"/>
+2
View File
@@ -154,6 +154,8 @@ typedef NS_ENUM(NSInteger, PencilTickMode) {
controllerMousePointerVelocity:(CGFloat)controllerMousePointerVelocity controllerMousePointerVelocity:(CGFloat)controllerMousePointerVelocity
controllerMouseExpo:(CGFloat)controllerMouseExpo controllerMouseExpo:(CGFloat)controllerMouseExpo
controllerGyroSwitchMode:(NSInteger)controllerGyroSwitchMode controllerGyroSwitchMode:(NSInteger)controllerGyroSwitchMode
enableFrameTimebase:(BOOL)enableFrameTimebase
asyncFrameDequeue:(BOOL)asyncFrameDequeue
backgroundSessionTimer:(NSInteger)backgroundSessionTimer; backgroundSessionTimer:(NSInteger)backgroundSessionTimer;
- (NSArray*) getHosts; - (NSArray*) getHosts;
+4
View File
@@ -126,6 +126,8 @@
controllerMousePointerVelocity:(CGFloat)controllerMousePointerVelocity controllerMousePointerVelocity:(CGFloat)controllerMousePointerVelocity
controllerMouseExpo:(CGFloat)controllerMouseExpo controllerMouseExpo:(CGFloat)controllerMouseExpo
controllerGyroSwitchMode:(NSInteger)controllerGyroSwitchMode controllerGyroSwitchMode:(NSInteger)controllerGyroSwitchMode
enableFrameTimebase:(BOOL)enableFrameTimebase
asyncFrameDequeue:(BOOL)asyncFrameDequeue
backgroundSessionTimer:(NSInteger)backgroundSessionTimer{ backgroundSessionTimer:(NSInteger)backgroundSessionTimer{
__block Settings* settingsToSave = settings; __block Settings* settingsToSave = settings;
@@ -178,6 +180,8 @@
settingsToSave.backroundSessionTimer = [NSNumber numberWithInteger:backgroundSessionTimer]; settingsToSave.backroundSessionTimer = [NSNumber numberWithInteger:backgroundSessionTimer];
settingsToSave.frameQueueSize = [NSNumber numberWithInteger:frameQueueSize]; settingsToSave.frameQueueSize = [NSNumber numberWithInteger:frameQueueSize];
settingsToSave.enableFrameTimebase = enableFrameTimebase;
settingsToSave.asyncFrameDequeue = asyncFrameDequeue;
settingsToSave.enableGraphs = enableGraphs; settingsToSave.enableGraphs = enableGraphs;
settingsToSave.graphOpacity = [NSNumber numberWithInteger:graphOpacity]; settingsToSave.graphOpacity = [NSNumber numberWithInteger:graphOpacity];
settingsToSave.renderingBackend = [NSNumber numberWithInteger:renderingBackend]; settingsToSave.renderingBackend = [NSNumber numberWithInteger:renderingBackend];
+2
View File
@@ -74,6 +74,8 @@
@property (nonatomic) BOOL showKeyboardToolbar; @property (nonatomic) BOOL showKeyboardToolbar;
@property (nonatomic) BOOL unlockDisplayOrientation; @property (nonatomic) BOOL unlockDisplayOrientation;
@property (nonatomic) BOOL enableGraphs; @property (nonatomic) BOOL enableGraphs;
@property (nonatomic) BOOL enableFrameTimebase;
@property (nonatomic) BOOL asyncFrameDequeue;
@property (nonatomic, retain) NSNumber * frameQueueSize; @property (nonatomic, retain) NSNumber * frameQueueSize;
@property (nonatomic, retain) NSNumber * graphOpacity; @property (nonatomic, retain) NSNumber * graphOpacity;
@property (nonatomic, retain) NSNumber * renderingBackend; @property (nonatomic, retain) NSNumber * renderingBackend;
+2
View File
@@ -91,6 +91,8 @@
self.enablePIP = settings.enablePIP; self.enablePIP = settings.enablePIP;
self.fullColorRange = settings.fullColorRange; self.fullColorRange = settings.fullColorRange;
self.frameQueueSize = settings.frameQueueSize; self.frameQueueSize = settings.frameQueueSize;
self.enableFrameTimebase = settings.enableFrameTimebase;
self.asyncFrameDequeue = settings.asyncFrameDequeue;
self.playAudioOnPC = settings.playAudioOnPC; self.playAudioOnPC = settings.playAudioOnPC;
self.redirectMic = settings.redirectMic; self.redirectMic = settings.redirectMic;
self.useBuiltinMic = settings.useBuiltinMic; self.useBuiltinMic = settings.useBuiltinMic;
+14 -3
View File
@@ -24,6 +24,10 @@ import UIKit
private var manualHoverFlag: Bool = false private var manualHoverFlag: Bool = false
private var autoHoverFlag: Bool = false private var autoHoverFlag: Bool = false
private(set) var pencilProEnabled: Bool = false private(set) var pencilProEnabled: Bool = false
private var isFirstMove: Bool = false
private var moveEventIndex: Int64 = 0
private var initialMoveEventIndexLimit: Int64
private var touchBeganForce: Float = 0
@objc static private(set) var isDrawing: Bool = false @objc static private(set) var isDrawing: Bool = false
@objc static private(set) var pencilPausesNativeTouch: Bool = false @objc static private(set) var pencilPausesNativeTouch: Bool = false
@@ -38,6 +42,7 @@ import UIKit
tickInterval = TimeInterval(settings.pencilTickIntervalUs.floatValue/1000000) tickInterval = TimeInterval(settings.pencilTickIntervalUs.floatValue/1000000)
manualTick = settings.pencilTickMode.intValue == PencilTickMode.ManualTick.rawValue manualTick = settings.pencilTickMode.intValue == PencilTickMode.ManualTick.rawValue
pencilTickEnabled = settings.pencilTickMode.intValue != PencilTickMode.PencilTickDisabled.rawValue pencilTickEnabled = settings.pencilTickMode.intValue != PencilTickMode.PencilTickDisabled.rawValue
initialMoveEventIndexLimit = UIScreen.main.maximumFramesPerSecond > 60 ? 4 : 2
super.init() super.init()
setupPressureLUT() setupPressureLUT()
PencilHandler.shared = self PencilHandler.shared = self
@@ -83,6 +88,8 @@ import UIKit
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let event = event else { return } guard let event = event else { return }
PencilHandler.isDrawing = true PencilHandler.isDrawing = true
// isFirstMove = true
moveEventIndex = 0
for touch in touches { for touch in touches {
let coalesced = event.coalescedTouches(for: touch) ?? [] let coalesced = event.coalescedTouches(for: touch) ?? []
_ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch]) _ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch])
@@ -95,6 +102,7 @@ import UIKit
let coalesced = event.coalescedTouches(for: touch) ?? [] let coalesced = event.coalescedTouches(for: touch) ?? []
_ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch]) _ = self.sendStylusEvent(touchBatch: pencilTickEnabled ? coalesced : [touch])
} }
moveEventIndex += 1
} }
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
@@ -173,22 +181,24 @@ import UIKit
var dispatchMoment: DispatchTime = .now() var dispatchMoment: DispatchTime = .now()
for touch in touchBatch { for touch in touchBatch {
let point = touch.location(in: streamView) let point = touch.preciseLocation(in: streamView)
let azimuth = touch.azimuthAngle(in: streamView) let azimuth = touch.azimuthAngle(in: streamView)
let altitude = touch.altitudeAngle let altitude = touch.altitudeAngle
let location = self.adjustCoordinatesForVideoArea(point: point) let location = self.adjustCoordinatesForVideoArea(point: point)
let videoSize = self.getVideoAreaSize() let videoSize = self.getVideoAreaSize()
let normalizedLocation = CGPoint(x: location.x/videoSize.width, y: location.y/videoSize.height) let normalizedLocation = CGPoint(x: location.x/videoSize.width, y: location.y/videoSize.height)
let force = Float(touch.force/touch.maximumPossibleForce)/sin(Float(altitude)) let force = Float(touch.force/touch.maximumPossibleForce)/sin(Float(altitude))
let targetForce = pressureCurveEnabled ? self.pressureLUT.value(at: force) : force var targetForce = pressureCurveEnabled ? self.pressureLUT.value(at: force) : force
let eventType:UInt8 let eventType:UInt8
switch touch.phase { switch touch.phase {
case .began: case .began:
eventType = UInt8(LI_TOUCH_EVENT_DOWN) eventType = UInt8(LI_TOUCH_EVENT_DOWN)
touchBeganForce = targetForce
case .moved: case .moved:
eventType = UInt8(manualHoverFlag ? LI_TOUCH_EVENT_HOVER : LI_TOUCH_EVENT_MOVE) eventType = UInt8(manualHoverFlag ? LI_TOUCH_EVENT_HOVER : LI_TOUCH_EVENT_MOVE)
targetForce = moveEventIndex < initialMoveEventIndexLimit ? touchBeganForce : targetForce
case .ended: case .ended:
eventType = UInt8(LI_TOUCH_EVENT_UP) eventType = UInt8(LI_TOUCH_EVENT_UP)
case .cancelled: case .cancelled:
@@ -209,8 +219,9 @@ import UIKit
tickMoment += (manualTick ? tickInterval : touch.timestamp - previousTimeStamp) tickMoment += (manualTick ? tickInterval : touch.timestamp - previousTimeStamp)
} }
let sendableForce = targetForce
DispatchQueue.global().asyncAfter(deadline: dispatchMoment + tickMoment + delay) { DispatchQueue.global().asyncAfter(deadline: dispatchMoment + tickMoment + delay) {
LiSendPenEvent(eventType, UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), targetForce, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude))) LiSendPenEvent(eventType, UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), sendableForce, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude)))
if eventType == UInt8(LI_TOUCH_EVENT_UP) { if eventType == UInt8(LI_TOUCH_EVENT_UP) {
PencilHandler.isDrawing = false PencilHandler.isDrawing = false
} }
+52 -18
View File
@@ -412,12 +412,13 @@ final class PressureCurveView: UIView {
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if testStage == .drawingStage { if testStage == .drawingStage {
if pressures.isEmpty { return }
curve.polylinePoints = PressureCurve.generateLinearCurvePoints(from: pressures) curve.polylinePoints = PressureCurve.generateLinearCurvePoints(from: pressures)
testStage = .curveStage testStage = .curveStage
showGraph = true showGraph = true
let parentVC = parentViewController as! PressureCurveViewController let parentVC = parentViewController as! PressureCurveViewController
parentVC.setupNavigationBar() parentVC.setupNavigationBar()
parentVC.showCurveStageTips() // parentVC.showCurveStageTips()
} }
draggingIndex = nil draggingIndex = nil
} }
@@ -479,6 +480,18 @@ class PressureCurveViewController: UIViewController {
private var minPressure: CGFloat = 0 private var minPressure: CGFloat = 0
private var maxPressure: CGFloat = 1 private var maxPressure: CGFloat = 1
private var isFirstLaunch: Bool = {
let key = "hasLaunchedPressureCurveTool"
let defaults = UserDefaults.standard
var launchedBefore = defaults.bool(forKey: key)
if !launchedBefore {
defaults.set(true, forKey: key)
return true
}
return false
}()
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@@ -532,6 +545,7 @@ class PressureCurveViewController: UIViewController {
} }
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
/*
AlertControllerUtil.cancelButtonString = SwiftLocalizationHelper.localizedString(forKey: "No") AlertControllerUtil.cancelButtonString = SwiftLocalizationHelper.localizedString(forKey: "No")
AlertControllerUtil.showAlert( AlertControllerUtil.showAlert(
in: self, in: self,
@@ -553,14 +567,16 @@ class PressureCurveViewController: UIViewController {
self.pressureRangeTest() self.pressureRangeTest()
} }
} }
) ) */
if isFirstLaunch {
showCurveStageTips()
}
} }
override func viewWillDisappear(_ animated: Bool) { override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
} }
private func loadPersistedCurve() { private func loadPersistedCurve() {
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero) let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
let persistedCurvePoints = PressureCurve.importCurvePoints(oscProfileMan.getSelectedProfile().pressureCurvePoints) let persistedCurvePoints = PressureCurve.importCurvePoints(oscProfileMan.getSelectedProfile().pressureCurvePoints)
@@ -625,8 +641,8 @@ class PressureCurveViewController: UIViewController {
title: SwiftLocalizationHelper.localizedString(forKey: "Pen Pressure Curve"), title: SwiftLocalizationHelper.localizedString(forKey: "Pen Pressure Curve"),
message: SwiftLocalizationHelper.localizedString(forKey:"Adjust the pressure curve by adding or dragging the purple squares."), message: SwiftLocalizationHelper.localizedString(forKey:"Adjust the pressure curve by adding or dragging the purple squares."),
withCancel: false, withCancel: false,
buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "OK"), buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "This tip won't be shown again"),
countdown: 0 countdown: 6
) )
} }
@@ -648,11 +664,13 @@ class PressureCurveViewController: UIViewController {
AlertControllerUtil.showAlert( AlertControllerUtil.showAlert(
in: self, in: self,
title: SwiftLocalizationHelper.localizedString(forKey: "Pressure Range Test"), title: SwiftLocalizationHelper.localizedString(forKey: "Pressure Range Test"),
message: SwiftLocalizationHelper.localizedString(forKey:"Draw freely and vary pen pressure naturally."), message: SwiftLocalizationHelper.localizedString(forKey:"pressureRangeTestTip"),
withCancel: false, withCancel: true,
buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "OK"), buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "OK"),
countdown: 0, countdown: 0,
completion:{ completion:{
if AlertControllerUtil.actionCancelled { return }
self.resetTapped()
self.curveView.showGraph = false self.curveView.showGraph = false
self.curveView.testStage = .drawingStage self.curveView.testStage = .drawingStage
self.curveView.setNeedsDisplay() self.curveView.setNeedsDisplay()
@@ -667,16 +685,32 @@ class PressureCurveViewController: UIViewController {
oscProfileMan.replaceSelectedProfile(with: selectedProfile, overwriteDefault: true) oscProfileMan.replaceSelectedProfile(with: selectedProfile, overwriteDefault: true)
DispatchQueue.main.async { DispatchQueue.main.async {
AlertControllerUtil.showAlert( if self.isFirstLaunch {
in: self, AlertControllerUtil.showAlert(
title: SwiftLocalizationHelper.localizedString(forKey: "Pen Pressure Curve"), in: self,
message: SwiftLocalizationHelper.localizedString(forKey:"Pressure curve saved with current on-screen widget profile!"), title: SwiftLocalizationHelper.localizedString(forKey: "Pen Pressure Curve"),
withCancel: false, message: SwiftLocalizationHelper.localizedString(forKey:"firstPressureCurvePersistTip"),
buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "OK"), withCancel: false,
countdown: 0, buttonTitle: SwiftLocalizationHelper.localizedString(forKey: "This tip won't be shown again"),
completion: { countdown: 11,
PencilHandler.shared?.setupPressureLUT() completion: {
}) PencilHandler.shared?.setupPressureLUT()
})
self.isFirstLaunch = false
}
else{
AlertControllerUtil.autoCompletion = true
AlertControllerUtil.showAlert(
in: self,
title: SwiftLocalizationHelper.localizedString(forKey: ""),
message: SwiftLocalizationHelper.localizedString(forKey:"Pressure curve saved"),
withCancel: false,
buttonTitle: "",
countdown: 1,
completion: {
PencilHandler.shared?.setupPressureLUT()
})
}
} }
} }
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="24411" systemVersion="24G325" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier=""> <model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="24512" systemVersion="24G419" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<entity name="App" representedClassName="App" syncable="YES" codeGenerationType="class"> <entity name="App" representedClassName="App" syncable="YES" codeGenerationType="class">
<attribute name="hdrSupported" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/> <attribute name="hdrSupported" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="hidden" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/> <attribute name="hidden" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
@@ -23,6 +23,7 @@
</entity> </entity>
<entity name="Settings" representedClassName="Settings" syncable="YES" codeGenerationType="class"> <entity name="Settings" representedClassName="Settings" syncable="YES" codeGenerationType="class">
<attribute name="appTheme" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/> <attribute name="appTheme" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="asyncFrameDequeue" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="asyncNativeTouchPriority" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/> <attribute name="asyncNativeTouchPriority" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="audioConfig" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="NO" syncable="YES"/> <attribute name="audioConfig" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="NO" syncable="YES"/>
<attribute name="audioEngine" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/> <attribute name="audioEngine" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
@@ -42,6 +43,7 @@
<attribute name="duckOtherApps" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/> <attribute name="duckOtherApps" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="edgeSlidingSensitivity" optional="YES" attributeType="Float" defaultValueString="22" usesScalarValueType="NO" syncable="YES"/> <attribute name="edgeSlidingSensitivity" optional="YES" attributeType="Float" defaultValueString="22" usesScalarValueType="NO" syncable="YES"/>
<attribute name="emulatedControllerType" optional="YES" attributeType="Integer 16" defaultValueString="2" usesScalarValueType="NO" syncable="YES"/> <attribute name="emulatedControllerType" optional="YES" attributeType="Integer 16" defaultValueString="2" usesScalarValueType="NO" syncable="YES"/>
<attribute name="enableFrameTimebase" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="enableGraphs" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/> <attribute name="enableGraphs" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="enableHdr" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/> <attribute name="enableHdr" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
<attribute name="enablePinch" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/> <attribute name="enablePinch" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES" syncable="YES"/>
+85 -27
View File
@@ -2131,29 +2131,6 @@
} }
} }
}, },
"Draw freely and vary pen pressure naturally." : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "请随意绘制,笔压自然变化即可。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "請隨意繪製,筆壓自然變化即可。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "請隨意繪製,筆壓自然變化即可。"
}
}
}
},
"Drift Correction" : { "Drift Correction" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@@ -2863,6 +2840,35 @@
} }
} }
}, },
"firstPressureCurvePersistTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pressure curve saved with current on-screen widget profile. Check custom 'On Screen Widget' in 'Touch Control' section of the settings menu, or toolbox menu brought up by right screen edge slide gesture.\nWhen you switch widget profile, pressure curve will change too."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "笔压曲线已随屏显控件配置保存。见设置菜单‘触控分区’的’屏显控件’ 自定义选项, 或屏幕右边缘滑动手势调出的工具箱菜单。\n切换屏显控件配置时,笔压曲线也将随之变化。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "笔壓曲線已隨「螢幕小工具」配置儲存。請至設定選單「觸控分區」中的「螢幕小工具」自訂選項,或由螢幕右側邊緣滑動手勢呼叫的工具箱選單查看。\n切換「螢幕小工具」配置時,筆壓曲線也會隨之變化。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "笔壓曲線已隨「螢幕小工具」配置儲存。請至設定選單「觸控分區」中的「螢幕小工具」自訂選項,或由螢幕右側邊緣滑動手勢呼叫的工具箱選單查看。\n切換「螢幕小工具」配置時,筆壓曲線也會隨之變化。"
}
}
}
},
"framePacingStackTip" : { "framePacingStackTip" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@@ -5558,25 +5564,25 @@
} }
} }
}, },
"Pressure curve saved with current on-screen widget profile!" : { "Pressure curve saved" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
"zh-Hans" : { "zh-Hans" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "笔压曲线已随屏显控件配置保存!" "value" : "笔压曲线已保存"
} }
}, },
"zh-Hant" : { "zh-Hant" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "筆壓曲線已隨螢幕小工具設定儲存!" "value" : "筆壓曲線已儲存"
} }
}, },
"zh-HK" : { "zh-HK" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "筆壓曲線已隨螢幕小工具設定儲存!" "value" : "筆壓曲線已儲存"
} }
} }
} }
@@ -5627,6 +5633,35 @@
} }
} }
}, },
"pressureRangeTestTip" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "This will reset the pressure curve. To proceed with the test, tap 'OK' to draw freely and vary pen pressure naturally."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "此测试将重置笔压曲线。 \n若继续测试,请点’确认’,并随意绘制。笔压自然变化即可。\n"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "此測試將重置筆壓曲線。\n若繼續測試,請點選「確認」,並隨意繪製即可,讓筆壓自然變化。"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "此測試將重置筆壓曲線。\n若繼續測試,請點選「確認」,並隨意繪製即可,讓筆壓自然變化。"
}
}
}
},
"Profile %@ duplicated from current layout" : { "Profile %@ duplicated from current layout" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@@ -7269,6 +7304,29 @@
} }
} }
}, },
"This tip won't be shown again" : {
"extractionState" : "manual",
"localizations" : {
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "该提示将不再弹出"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "該提示將不再彈出"
}
},
"zh-HK" : {
"stringUnit" : {
"state" : "translated",
"value" : "該提示將不再彈出"
}
}
}
},
"Tips" : { "Tips" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
+1 -1
View File
@@ -129,7 +129,7 @@
return; return;
} }
CFTimeInterval timeout = (1.0f / _framerate) - _renderer.averageGPUTime; CFTimeInterval timeout = (1.0f / _framerate) - _renderer.averageGPUTime;
Frame *frame = [_frameQueue dequeueWithTimeout:timeout]; Frame *frame = [_frameQueue dequeueWithTimeoutSync:timeout];
if (!_renderer.isStopping) { if (!_renderer.isStopping) {
// Only render if not paused // Only render if not paused
+81 -37
View File
@@ -57,6 +57,8 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
RenderingBackend _renderingBackend; RenderingBackend _renderingBackend;
FramePacingMode _framePacingMode; FramePacingMode _framePacingMode;
bool _enableTimebase;
bool _asyncFrameDequeue;
} }
- (void)reinitializeDisplayLayer - (void)reinitializeDisplayLayer
@@ -132,12 +134,15 @@ extern int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size,
_parameterSetBuffers = [[NSMutableArray alloc] init]; _parameterSetBuffers = [[NSMutableArray alloc] init];
DataManager* dataMan = [[DataManager alloc] init]; DataManager* dataMan = [[DataManager alloc] init];
TemporarySettings* tempSettings = [dataMan getSettings];
_framePacingMode = [[dataMan getSettings].framePacingMode integerValue]; _framePacingMode = tempSettings.framePacingMode.integerValue;
_enableTimebase = tempSettings.enableFrameTimebase;
_asyncFrameDequeue = tempSettings.asyncFrameDequeue;
_frameQueue = [FrameQueue sharedInstance]; _frameQueue = [FrameQueue sharedInstance];
[_frameQueue start]; [_frameQueue start];
[_frameQueue setHighWaterMark:(int)[[dataMan getSettings].frameQueueSize integerValue]]; [_frameQueue setHighWaterMark:(int)[tempSettings.frameQueueSize integerValue]];
[self reinitializeDisplayLayer]; [self reinitializeDisplayLayer];
@@ -271,57 +276,96 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
CFTimeInterval deadline = link.targetTimestamp; CFTimeInterval deadline = link.targetTimestamp;
static CFTimeInterval lastTargetLocal = 0.0f; static CFTimeInterval lastTargetLocal = 0.0f;
CFTimeInterval dl0 = CACurrentMediaTime(); CFTimeInterval dl0 = CACurrentMediaTime();
static int lateCallbacks = 0; static int lateCallbacks = 0;
if (dl0 > deadline) { if (dl0 > deadline) {
// we already missed it, count how often this happens // we already missed it, count how often this happens
lateCallbacks++; lateCallbacks++;
return; return;
} }
[self checkDisplayLayer]; [self checkDisplayLayer];
static CFTimeInterval avgOverhead = 0.004f; // averaged each callback static CFTimeInterval avgOverhead = 0.004f; // averaged each callback
CFTimeInterval waitFor = deadline - dl0 - avgOverhead; CFTimeInterval waitFor = deadline - dl0 - avgOverhead;
if (waitFor < 0.001f) { if (waitFor < 0.001f) {
waitFor = 0.0f; waitFor = 0.0f;
} }
// Get the next frame or wait if necessary. If no frame arrives the previous one will be redisplayed automatically. if(_asyncFrameDequeue){
Frame *frame = [_frameQueue dequeueWithTimeout:waitFor]; [_frameQueue dequeueWithTimeout:waitFor completion:^(Frame *frame) {
if (frame) { if (frame) {
CFTimeInterval dl1 = CACurrentMediaTime(); CFTimeInterval dl1 = CACurrentMediaTime();
LogOnce(LOG_I, @"Frame pacing: using AVSampleBufferDisplayLayer target %f Hz with %d FPS stream", 1.0f / (deadline - start), self->_frameRate); // LogOnce(LOG_I, @"Frame pacing: using AVSampleBufferDisplayLayer target %f Hz with %d FPS stream", 1.0f / (deadline - start), self->_frameRate);
// The system works best with properly timed video frames, which we time to the end of the next vsync period, // The system works best with properly timed video frames, which we time to the end of the next vsync period,
// the earliest they can be displayed due to double-buffering. // the earliest they can be displayed due to double-buffering.
CFTimeInterval targetLocal = deadline + link.duration; CFTimeInterval targetLocal = deadline + link.duration;
[self renderFrame:frame atTime:CMTimeMakeWithSeconds(targetLocal, NSEC_PER_SEC)]; [self renderFrame:frame atTime:CMTimeMakeWithSeconds(targetLocal, NSEC_PER_SEC)];
#ifdef DISPLAYLINK_VERBOSE #ifdef DISPLAYLINK_VERBOSE
Log(LOG_I, @"[%.3f] rendering frame %d, waitFor %.3f ms, overhead %.3f ms, lateCallbacks %d, queue size %d", Log(LOG_I, @"[%.3f] rendering frame %d, waitFor %.3f ms, overhead %.3f ms, lateCallbacks %d, queue size %d",
deadline, frame.frameNumber, waitFor * 1000.0, avgOverhead * 1000.0, lateCallbacks, [_frameQueue count]); deadline, frame.frameNumber, waitFor * 1000.0, avgOverhead * 1000.0, lateCallbacks, [_frameQueue count]);
#endif #endif
// Update metrics // Update metrics
if (lastTargetLocal != 0) { if (lastTargetLocal != 0) {
CFTimeInterval frametime = targetLocal - lastTargetLocal; CFTimeInterval frametime = targetLocal - lastTargetLocal;
if (frametime > deadline - start + 0.0005f) { if (frametime > deadline - start + 0.0005f) {
// we missed a callback // we missed a callback
// Log(LOG_W, @"*** slow frametime %.3f ms", frametime * 1000.0); // Log(LOG_W, @"*** slow frametime %.3f ms", frametime * 1000.0);
}
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) {
[[ImGuiPlots sharedInstance] observeFloat:PLOT_FRAMETIME value:frametime * 1000.0];
}
}
lastTargetLocal = targetLocal;
// weighted moving average of how much time displayLink needs after dequeuing a frame.
// This is used to avoid overshooting a vsync by waiting too long.
const double alpha = 0.1f;
avgOverhead = ((CACurrentMediaTime() - dl1) * alpha) + (avgOverhead * (1.0 - alpha));
} }
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) { }];
[[ImGuiPlots sharedInstance] observeFloat:PLOT_FRAMETIME value:frametime * 1000.0]; }
else{
Frame *frame = [_frameQueue dequeueWithTimeoutSync:waitFor];
if (frame) {
CFTimeInterval dl1 = CACurrentMediaTime();
// LogOnce(LOG_I, @"Frame pacing: using AVSampleBufferDisplayLayer target %f Hz with %d FPS stream", 1.0f / (deadline - start), self->_frameRate);
// The system works best with properly timed video frames, which we time to the end of the next vsync period,
// the earliest they can be displayed due to double-buffering.
CFTimeInterval targetLocal = deadline + link.duration;
[self renderFrame:frame atTime:CMTimeMakeWithSeconds(targetLocal, NSEC_PER_SEC)];
#ifdef DISPLAYLINK_VERBOSE
Log(LOG_I, @"[%.3f] rendering frame %d, waitFor %.3f ms, overhead %.3f ms, lateCallbacks %d, queue size %d",
deadline, frame.frameNumber, waitFor * 1000.0, avgOverhead * 1000.0, lateCallbacks, [_frameQueue count]);
#endif
// Update metrics
if (lastTargetLocal != 0) {
CFTimeInterval frametime = targetLocal - lastTargetLocal;
if (frametime > deadline - start + 0.0005f) {
// we missed a callback
// Log(LOG_W, @"*** slow frametime %.3f ms", frametime * 1000.0);
}
if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateBackground) {
[[ImGuiPlots sharedInstance] observeFloat:PLOT_FRAMETIME value:frametime * 1000.0];
}
} }
lastTargetLocal = targetLocal;
// weighted moving average of how much time displayLink needs after dequeuing a frame.
// This is used to avoid overshooting a vsync by waiting too long.
const double alpha = 0.1f;
avgOverhead = ((CACurrentMediaTime() - dl1) * alpha) + (avgOverhead * (1.0 - alpha));
} }
lastTargetLocal = targetLocal;
// weighted moving average of how much time displayLink needs after dequeuing a frame.
// This is used to avoid overshooting a vsync by waiting too long.
const double alpha = 0.1f;
avgOverhead = ((CACurrentMediaTime() - dl1) * alpha) + (avgOverhead * (1.0 - alpha));
} }
} }
@@ -361,7 +405,7 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit);
- (void)renderFrame:(Frame *)frame atTime:(CMTime)targetTime { - (void)renderFrame:(Frame *)frame atTime:(CMTime)targetTime {
CMSampleBufferSetOutputPresentationTimeStamp(frame.sampleBuffer, targetTime); CMSampleBufferSetOutputPresentationTimeStamp(frame.sampleBuffer, targetTime);
if ([self->_displayLayer controlTimebase] == NULL) { if (_enableTimebase && [self->_displayLayer controlTimebase] == NULL) {
// On first frame, set timebase to the initial presentation time. // On first frame, set timebase to the initial presentation time.
// This will let us present frames using the local clock (vsync pacing) or // This will let us present frames using the local clock (vsync pacing) or
// the pts timestamps from the host. // the pts timestamps from the host.
+3 -1
View File
@@ -13,6 +13,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) int highWaterMark; @property (nonatomic) int highWaterMark;
@property (nonatomic, readonly) int maxCapacity; @property (nonatomic, readonly) int maxCapacity;
@property (atomic) BOOL paused; @property (atomic) BOOL paused;
- (void)dequeueWithTimeout:(CFTimeInterval)timeout
completion:(void (^)(Frame *frame))completion;
+ (instancetype)sharedInstance; + (instancetype)sharedInstance;
@@ -23,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
- (int)enqueue:(Frame *)frame; - (int)enqueue:(Frame *)frame;
- (int)enqueue:(Frame *)frame withSlackSize:(int)slack; - (int)enqueue:(Frame *)frame withSlackSize:(int)slack;
- (nullable Frame *)dequeue; - (nullable Frame *)dequeue;
- (nullable Frame *)dequeueWithTimeout:(CFTimeInterval)timeout; - (nullable Frame *)dequeueWithTimeoutSync:(CFTimeInterval)timeout;
- (CFTimeInterval)estimatedFramerate; - (CFTimeInterval)estimatedFramerate;
- (int)currentSoftCap; - (int)currentSoftCap;
- (void)waitForEnqueue; - (void)waitForEnqueue;
+13 -1
View File
@@ -251,7 +251,19 @@
return frame; return frame;
} }
- (Frame *)dequeueWithTimeout:(CFTimeInterval)timeout { - (void)dequeueWithTimeout:(CFTimeInterval)timeout
completion:(void (^)(Frame *frame))completion {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
Frame *frame = [self dequeueWithTimeoutSync:timeout];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(frame);
}
});
});
}
- (Frame *)dequeueWithTimeoutSync:(CFTimeInterval)timeout {
CFTimeInterval start = CACurrentMediaTime(); CFTimeInterval start = CACurrentMediaTime();
CFTimeInterval deadline = start + timeout; CFTimeInterval deadline = start + timeout;
int round = 0; int round = 0;
@@ -1222,6 +1222,9 @@ static NSMutableSet* hostList;
// Enable frame pacing mode selector only if not in stream view AND not in performance mode // Enable frame pacing mode selector only if not in stream view AND not in performance mode
BOOL shouldEnableFramePacing = !_settingsExpandedInStreamView && (settingsViewController.renderingBackendSelector.selectedSegmentIndex != RENDER_METAL); BOOL shouldEnableFramePacing = !_settingsExpandedInStreamView && (settingsViewController.renderingBackendSelector.selectedSegmentIndex != RENDER_METAL);
[settingsViewController.framePacingModeSelector setEnabled:shouldEnableFramePacing]; [settingsViewController.framePacingModeSelector setEnabled:shouldEnableFramePacing];
[settingsViewController.frameTimebaseSwitch setEnabled:shouldEnableFramePacing];
[settingsViewController.asyncFrameDequeueSwitch setEnabled:shouldEnableFramePacing];
// Disable mic switch if sunshine does not support mic redirection // Disable mic switch if sunshine does not support mic redirection
[settingsViewController.redirectMicSwitch setEnabled:!_settingsExpandedInStreamView||streamFrameViewController.micStreamInitialized]; [settingsViewController.redirectMicSwitch setEnabled:!_settingsExpandedInStreamView||streamFrameViewController.micStreamInitialized];
if(_settingsExpandedInStreamView && !streamFrameViewController.micStreamInitialized) [settingsViewController.redirectMicSwitch setOn:false]; if(_settingsExpandedInStreamView && !streamFrameViewController.micStreamInitialized) [settingsViewController.redirectMicSwitch setOn:false];
@@ -243,6 +243,13 @@
@property (strong, nonatomic) IBOutlet UIStackView *pressureCurveStack; @property (strong, nonatomic) IBOutlet UIStackView *pressureCurveStack;
@property (strong, nonatomic) IBOutlet UISwitch *pressureCurveSwitch; @property (strong, nonatomic) IBOutlet UISwitch *pressureCurveSwitch;
@property (weak, nonatomic) IBOutlet UIStackView *frameTimebaseStack;
@property (weak, nonatomic) IBOutlet UISwitch *frameTimebaseSwitch;
@property (weak, nonatomic) IBOutlet UIStackView *asyncFrameDequeueStack;
@property (weak, nonatomic) IBOutlet UISwitch *asyncFrameDequeueSwitch;
@property (strong, nonatomic) IBOutlet UIStackView *testStack; @property (strong, nonatomic) IBOutlet UIStackView *testStack;
@@ -262,6 +269,8 @@
@property (weak, nonatomic) IBOutlet UIStackView *pencilPausesNativeTouchStack; @property (weak, nonatomic) IBOutlet UIStackView *pencilPausesNativeTouchStack;
@property (weak, nonatomic) IBOutlet UISwitch *pencilPausesNativeTouchSwitch; @property (weak, nonatomic) IBOutlet UISwitch *pencilPausesNativeTouchSwitch;
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability" #pragma clang diagnostic ignored "-Wunguarded-availability"
@@ -794,6 +794,8 @@ BOOL isCustomResolution(int resolutionSelected) {
[self addSetting:self.pipStack ofId:@"pipStack" withInfoTag:YES withDynamicLabel:NO to:videoSection]; [self addSetting:self.pipStack ofId:@"pipStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
[self addSetting:self.framePacingStack ofId:@"framePacingStack" withInfoTag:YES withDynamicLabel:NO to:videoSection]; [self addSetting:self.framePacingStack ofId:@"framePacingStack" withInfoTag:YES withDynamicLabel:NO to:videoSection];
[self addSetting:self.frameQueueSizeStack ofId:@"frameQueueSizeStack" withInfoTag:NO withDynamicLabel:YES to:videoSection]; [self addSetting:self.frameQueueSizeStack ofId:@"frameQueueSizeStack" withInfoTag:NO withDynamicLabel:YES to:videoSection];
[self addSetting:self.frameTimebaseStack ofId:@"frameTimebaseStack" withInfoTag:NO withDynamicLabel:NO to:videoSection];
[self addSetting:self.asyncFrameDequeueStack ofId:@"asyncFrameDequeueStack" withInfoTag:NO withDynamicLabel:NO to:videoSection];
[videoSection addToParentStack:_parentStack]; [videoSection addToParentStack:_parentStack];
// [videoSection setExpanded:NO]; // [videoSection setExpanded:NO];
@@ -1885,6 +1887,9 @@ BOOL isCustomResolution(int resolutionSelected) {
[self.framePacingModeSelector setSelectedSegmentIndex:framePacingMode]; [self.framePacingModeSelector setSelectedSegmentIndex:framePacingMode];
[self.framePacingModeSelector addTarget:self action:@selector(framePacingModeChanged:) forControlEvents:UIControlEventValueChanged]; [self.framePacingModeSelector addTarget:self action:@selector(framePacingModeChanged:) forControlEvents:UIControlEventValueChanged];
[self framePacingModeChanged:self.framePacingModeSelector]; [self framePacingModeChanged:self.framePacingModeSelector];
[self.frameTimebaseSwitch setOn:self->tempSettings.enableFrameTimebase];
[self.asyncFrameDequeueSwitch setOn:self->tempSettings.asyncFrameDequeue];
[self renderingBackendChanged:self.renderingBackendSelector]; // Update PiP and frame pacing state based on current selection [self renderingBackendChanged:self.renderingBackendSelector]; // Update PiP and frame pacing state based on current selection
@@ -2303,6 +2308,8 @@ BOOL isCustomResolution(int resolutionSelected) {
- (void)framePacingModeChanged:(UISegmentedControl *)sender { - (void)framePacingModeChanged:(UISegmentedControl *)sender {
// Hide frame queue size for Off and Legacy modes // Hide frame queue size for Off and Legacy modes
[self setHidden:(sender.selectedSegmentIndex == FramePacingModeOff || sender.selectedSegmentIndex == FramePacingModeLegacy) forStack:self.frameQueueSizeStack]; [self setHidden:(sender.selectedSegmentIndex == FramePacingModeOff || sender.selectedSegmentIndex == FramePacingModeLegacy) forStack:self.frameQueueSizeStack];
[self setHidden:(sender.selectedSegmentIndex != FramePacingModeQueue) forStack:self.frameTimebaseStack];
[self setHidden:(sender.selectedSegmentIndex != FramePacingModeQueue) forStack:self.frameTimebaseStack];
if(sender.selectedSegmentIndex == FramePacingModeOff || sender.selectedSegmentIndex == FramePacingModeLegacy){ if(sender.selectedSegmentIndex == FramePacingModeOff || sender.selectedSegmentIndex == FramePacingModeLegacy){
[self.enableGraphsSwitch setOn:NO]; [self.enableGraphsSwitch setOn:NO];
@@ -3533,6 +3540,8 @@ BOOL isCustomResolution(int resolutionSelected) {
CGFloat controllerMousePointerVelocity = self.controllerMouseVelocitySlider.value; CGFloat controllerMousePointerVelocity = self.controllerMouseVelocitySlider.value;
CGFloat controllerMouseExpo = self.controllerMouseExpoSlider.value; CGFloat controllerMouseExpo = self.controllerMouseExpoSlider.value;
NSInteger controllerGyroSwitchMode = self.controllerGyroSwitchButtonSetter.selectedSegmentIndex; NSInteger controllerGyroSwitchMode = self.controllerGyroSwitchButtonSetter.selectedSegmentIndex;
BOOL enableFrameTimebase = self.frameTimebaseSwitch.isOn;
BOOL asyncFrameDequeue = self.asyncFrameDequeueSwitch.isOn;
NSInteger backgroundSessionTimer = self.backgroundSessionTimerSlider.value == self.backgroundSessionTimerSlider.maximumValue ? (uint32_t) INT16_MAX : (uint32_t)self.backgroundSessionTimerSlider.value; NSInteger backgroundSessionTimer = self.backgroundSessionTimerSlider.value == self.backgroundSessionTimerSlider.maximumValue ? (uint32_t) INT16_MAX : (uint32_t)self.backgroundSessionTimerSlider.value;
[dataMan saveSettings:currentSettings [dataMan saveSettings:currentSettings
@@ -3605,6 +3614,8 @@ BOOL isCustomResolution(int resolutionSelected) {
controllerMousePointerVelocity:controllerMousePointerVelocity controllerMousePointerVelocity:controllerMousePointerVelocity
controllerMouseExpo:controllerMouseExpo controllerMouseExpo:controllerMouseExpo
controllerGyroSwitchMode:controllerGyroSwitchMode controllerGyroSwitchMode:controllerGyroSwitchMode
enableFrameTimebase:enableFrameTimebase
asyncFrameDequeue:asyncFrameDequeue
backgroundSessionTimer:backgroundSessionTimer]; backgroundSessionTimer:backgroundSessionTimer];
} }
+24
View File
@@ -2065,6 +2065,18 @@
} }
} }
}, },
"cpg-mq-kYj.text" : {
"comment" : "Class = \"UILabel\"; text = \"Enable Timebase\"; ObjectID = \"cpg-mq-kYj\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Enable Timebase"
}
}
}
},
"CpY-Sb-BDc.title" : { "CpY-Sb-BDc.title" : {
"comment" : "Class = \"UIBarButtonItem\"; title = \"Import\"; ObjectID = \"CpY-Sb-BDc\";", "comment" : "Class = \"UIBarButtonItem\"; title = \"Import\"; ObjectID = \"CpY-Sb-BDc\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
@@ -5629,6 +5641,18 @@
} }
} }
}, },
"X0u-7f-F86.text" : {
"comment" : "Class = \"UILabel\"; text = \"Async Deueue\"; ObjectID = \"X0u-7f-F86\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Async Deueue"
}
}
}
},
"x9i-JN-FSn.text" : { "x9i-JN-FSn.text" : {
"comment" : "Class = \"UILabel\"; text = \"Roll factor\"; ObjectID = \"x9i-JN-FSn\";", "comment" : "Class = \"UILabel\"; text = \"Roll factor\"; ObjectID = \"x9i-JN-FSn\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
+24
View File
@@ -2023,6 +2023,18 @@
} }
} }
}, },
"e1n-pw-04X.text" : {
"comment" : "Class = \"UILabel\"; text = \"Async Deueue\"; ObjectID = \"e1n-pw-04X\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Async Deueue"
}
}
}
},
"E7F-vx-pnM.text" : { "E7F-vx-pnM.text" : {
"comment" : "Class = \"UILabel\"; text = \"Frame Rate\"; ObjectID = \"E7F-vx-pnM\";", "comment" : "Class = \"UILabel\"; text = \"Frame Rate\"; ObjectID = \"E7F-vx-pnM\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",
@@ -3955,6 +3967,18 @@
} }
} }
}, },
"P4N-i6-1zD.text" : {
"comment" : "Class = \"UILabel\"; text = \"Enable Timebase\"; ObjectID = \"P4N-i6-1zD\";",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "Enable Timebase"
}
}
}
},
"PaG-9w-YxB.text" : { "PaG-9w-YxB.text" : {
"comment" : "Class = \"UILabel\"; text = \"Mute in Background\"; ObjectID = \"PaG-9w-YxB\";", "comment" : "Class = \"UILabel\"; text = \"Mute in Background\"; ObjectID = \"PaG-9w-YxB\";",
"extractionState" : "extracted_with_value", "extractionState" : "extracted_with_value",