pencil tip offset
This commit is contained in:
1 parent
e0aff4b532
commit
51c13faa0c
19 files changed
+590
-8
No files matched your search
@@ -32,6 +32,7 @@
|
|||||||
18A765BD2ECD51FB004784AA /* ControllerUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A765BC2ECD51FB004784AA /* ControllerUtil.swift */; };
|
18A765BD2ECD51FB004784AA /* ControllerUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18A765BC2ECD51FB004784AA /* ControllerUtil.swift */; };
|
||||||
18B317032EE67A3A009B62C2 /* InertialScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B317022EE67A39009B62C2 /* InertialScroller.swift */; };
|
18B317032EE67A3A009B62C2 /* InertialScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18B317022EE67A39009B62C2 /* InertialScroller.swift */; };
|
||||||
18D43D7F2F050240008C326F /* PressureCurve.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18D43D7E2F050240008C326F /* PressureCurve.swift */; };
|
18D43D7F2F050240008C326F /* PressureCurve.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18D43D7E2F050240008C326F /* PressureCurve.swift */; };
|
||||||
|
18D43D812F050240008C326F /* PencilTipOffsetCalibrationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18D43D802F050240008C326F /* PencilTipOffsetCalibrationViewController.swift */; };
|
||||||
18E4BCEA2E891895000A8657 /* MotionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18E4BCE92E891895000A8657 /* MotionHandler.swift */; };
|
18E4BCEA2E891895000A8657 /* MotionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18E4BCE92E891895000A8657 /* MotionHandler.swift */; };
|
||||||
18FCADAF2ECAC23200787A96 /* PencilHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FCADAE2ECAC23200787A96 /* PencilHandler.swift */; };
|
18FCADAF2ECAC23200787A96 /* PencilHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18FCADAE2ECAC23200787A96 /* PencilHandler.swift */; };
|
||||||
2A263D4A2FF3B3F800154DEA /* PublicExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A263D492FF3B3F800154DEA /* PublicExtensions.swift */; };
|
2A263D4A2FF3B3F800154DEA /* PublicExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A263D492FF3B3F800154DEA /* PublicExtensions.swift */; };
|
||||||
@@ -209,6 +210,7 @@
|
|||||||
18B317022EE67A39009B62C2 /* InertialScroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InertialScroller.swift; sourceTree = "<group>"; };
|
18B317022EE67A39009B62C2 /* InertialScroller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InertialScroller.swift; sourceTree = "<group>"; };
|
||||||
18BF141D2E0D7A00009DEE4F /* VoidLink v1.0.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "VoidLink v1.0.xcdatamodel"; sourceTree = "<group>"; };
|
18BF141D2E0D7A00009DEE4F /* VoidLink v1.0.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "VoidLink v1.0.xcdatamodel"; sourceTree = "<group>"; };
|
||||||
18D43D7E2F050240008C326F /* PressureCurve.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PressureCurve.swift; sourceTree = "<group>"; };
|
18D43D7E2F050240008C326F /* PressureCurve.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PressureCurve.swift; sourceTree = "<group>"; };
|
||||||
|
18D43D802F050240008C326F /* PencilTipOffsetCalibrationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PencilTipOffsetCalibrationViewController.swift; sourceTree = "<group>"; };
|
||||||
18E4BCE92E891895000A8657 /* MotionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionHandler.swift; sourceTree = "<group>"; };
|
18E4BCE92E891895000A8657 /* MotionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MotionHandler.swift; sourceTree = "<group>"; };
|
||||||
18FCADAE2ECAC23200787A96 /* PencilHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PencilHandler.swift; sourceTree = "<group>"; };
|
18FCADAE2ECAC23200787A96 /* PencilHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PencilHandler.swift; sourceTree = "<group>"; };
|
||||||
2A039E562F72892B00546768 /* VoidLinkPreview.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VoidLinkPreview.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
2A039E562F72892B00546768 /* VoidLinkPreview.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VoidLinkPreview.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -773,6 +775,7 @@
|
|||||||
988FCD3F293B091B003050E2 /* KeyboardInputField.h */,
|
988FCD3F293B091B003050E2 /* KeyboardInputField.h */,
|
||||||
988FCD40293B091B003050E2 /* KeyboardInputField.m */,
|
988FCD40293B091B003050E2 /* KeyboardInputField.m */,
|
||||||
18D43D7E2F050240008C326F /* PressureCurve.swift */,
|
18D43D7E2F050240008C326F /* PressureCurve.swift */,
|
||||||
|
18D43D802F050240008C326F /* PencilTipOffsetCalibrationViewController.swift */,
|
||||||
18FCADAE2ECAC23200787A96 /* PencilHandler.swift */,
|
18FCADAE2ECAC23200787A96 /* PencilHandler.swift */,
|
||||||
18416EA32EBB3DCE00AE0124 /* UITouchUtil.swift */,
|
18416EA32EBB3DCE00AE0124 /* UITouchUtil.swift */,
|
||||||
18B317022EE67A39009B62C2 /* InertialScroller.swift */,
|
18B317022EE67A39009B62C2 /* InertialScroller.swift */,
|
||||||
@@ -1202,6 +1205,7 @@
|
|||||||
187F4B282E04658A00EECC59 /* WidgetPanelStackView.m in Sources */,
|
187F4B282E04658A00EECC59 /* WidgetPanelStackView.m in Sources */,
|
||||||
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
|
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
|
||||||
18D43D7F2F050240008C326F /* PressureCurve.swift in Sources */,
|
18D43D7F2F050240008C326F /* PressureCurve.swift in Sources */,
|
||||||
|
18D43D812F050240008C326F /* PencilTipOffsetCalibrationViewController.swift in Sources */,
|
||||||
180E6E372E93BFDB0067C73A /* AlertControllerUtil.swift in Sources */,
|
180E6E372E93BFDB0067C73A /* AlertControllerUtil.swift in Sources */,
|
||||||
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */,
|
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */,
|
||||||
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
|
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
|
||||||
|
|||||||
@@ -1144,6 +1144,26 @@
|
|||||||
<constraint firstAttribute="width" constant="380" id="gdZ-zL-Wl7"/>
|
<constraint firstAttribute="width" constant="380" id="gdZ-zL-Wl7"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</stackView>
|
</stackView>
|
||||||
|
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="pTO-ff-set">
|
||||||
|
<rect key="frame" x="3145" y="191" width="293.5" height="31"/>
|
||||||
|
<subviews>
|
||||||
|
<label verifyAmbiguity="off" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Pencil Tip Offset" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.64999997615814209" adjustsLetterSpacingToFitWidth="YES" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pTO-ff-lbl" userLabel="uiLabel">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="143.5" height="31"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="pTO-ff-swi">
|
||||||
|
<rect key="frame" x="163.5" y="0.0" width="132" height="31"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="130" id="pTO-ff-wid"/>
|
||||||
|
</constraints>
|
||||||
|
</switch>
|
||||||
|
</subviews>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="31" id="pTO-ff-hgt"/>
|
||||||
|
</constraints>
|
||||||
|
</stackView>
|
||||||
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Bp6-7U-E9H">
|
<stackView verifyAmbiguity="off" opaque="NO" contentMode="scaleToFill" ambiguous="YES" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="Bp6-7U-E9H">
|
||||||
<rect key="frame" x="3145" y="230" width="266.5" height="31"/>
|
<rect key="frame" x="3145" y="230" width="266.5" height="31"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
@@ -2342,6 +2362,8 @@
|
|||||||
<outlet property="pencilTickIntervalStack" destination="O2s-9s-ABi" id="0kk-q4-ppy"/>
|
<outlet property="pencilTickIntervalStack" destination="O2s-9s-ABi" id="0kk-q4-ppy"/>
|
||||||
<outlet property="pencilTickSelector" destination="bVv-CW-kN8" id="Ymr-VI-Ilj"/>
|
<outlet property="pencilTickSelector" destination="bVv-CW-kN8" id="Ymr-VI-Ilj"/>
|
||||||
<outlet property="pencilTickStack" destination="zuF-a5-GOI" id="Nn7-GA-yQM"/>
|
<outlet property="pencilTickStack" destination="zuF-a5-GOI" id="Nn7-GA-yQM"/>
|
||||||
|
<outlet property="pencilTipOffsetStack" destination="pTO-ff-set" id="pTO-ff-oSt"/>
|
||||||
|
<outlet property="pencilTipOffsetSwitch" destination="pTO-ff-swi" id="pTO-ff-oSw"/>
|
||||||
<outlet property="performanceGraphStack" destination="H8p-G9-pnl" id="9RJ-uO-IpF"/>
|
<outlet property="performanceGraphStack" destination="H8p-G9-pnl" id="9RJ-uO-IpF"/>
|
||||||
<outlet property="pinchGestureStack" destination="uEq-Pc-Fum" id="68g-K6-P87"/>
|
<outlet property="pinchGestureStack" destination="uEq-Pc-Fum" id="68g-K6-P87"/>
|
||||||
<outlet property="pinchGestureSwitch" destination="TJy-Zp-DKM" id="Haj-ha-vNy"/>
|
<outlet property="pinchGestureSwitch" destination="TJy-Zp-DKM" id="Haj-ha-vNy"/>
|
||||||
|
|||||||
@@ -118,6 +118,8 @@
|
|||||||
// Pencil settings:
|
// Pencil settings:
|
||||||
@property (nonatomic, retain) NSNumber * pencilTickMode;
|
@property (nonatomic, retain) NSNumber * pencilTickMode;
|
||||||
@property (nonatomic, retain) NSNumber * pencilTickIntervalUs;
|
@property (nonatomic, retain) NSNumber * pencilTickIntervalUs;
|
||||||
|
@property (nonatomic, retain) NSNumber * pencilTipOffsetX;
|
||||||
|
@property (nonatomic, retain) NSNumber * pencilTipOffsetY;
|
||||||
|
|
||||||
|
|
||||||
- (id) initFromSettings:(Settings*)settings;
|
- (id) initFromSettings:(Settings*)settings;
|
||||||
|
|||||||
@@ -175,6 +175,8 @@
|
|||||||
// Pencil settings:
|
// Pencil settings:
|
||||||
self.pencilTickMode = settings.pencilTickMode;
|
self.pencilTickMode = settings.pencilTickMode;
|
||||||
self.pencilTickIntervalUs = settings.pencilTickIntervalUs;
|
self.pencilTickIntervalUs = settings.pencilTickIntervalUs;
|
||||||
|
self.pencilTipOffsetX = settings.pencilTipOffsetX;
|
||||||
|
self.pencilTipOffsetY = settings.pencilTipOffsetY;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -154,8 +154,8 @@ import UIKit
|
|||||||
@objc public static let stickWheels: [String] = ["LSWHEEL", "RSWHEEL"]
|
@objc public static let stickWheels: [String] = ["LSWHEEL", "RSWHEEL"]
|
||||||
@objc public static let velocityBasedTouchPads: [String] = ["LSVPAD", "RSVPAD", "MOUSEPAD", "TRACKBALL", "LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL"]
|
@objc public static let velocityBasedTouchPads: [String] = ["LSVPAD", "RSVPAD", "MOUSEPAD", "TRACKBALL", "LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL"]
|
||||||
@objc public static let inertialTouchPads: [String] = ["LSVPAD", "RSVPAD", "TRACKBALL", "LSPAD", "RSPAD"]
|
@objc public static let inertialTouchPads: [String] = ["LSVPAD", "RSVPAD", "TRACKBALL", "LSPAD", "RSPAD"]
|
||||||
@objc public static let verticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL", "DISCRETEWHEEL", "DSWHEEL"]
|
@objc public static let verticalTouchPads: [String] = ["LTPAD", "RTPAD", "DISCRETEWHEEL", "DSWHEEL"]
|
||||||
@objc public static let bidirectionalVerticalTouchPads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL", "DISCRETEWHEEL", "DSWHEEL"]
|
@objc public static let singleDimensionActiveTouchpads: [String] = ["LTPAD", "RTPAD", "MOUSEWHEEL", "WHEEL", "DISCRETEWHEEL", "DSWHEEL"]
|
||||||
@objc public static let functionalButtonCmds: [String] = [
|
@objc public static let functionalButtonCmds: [String] = [
|
||||||
"SETTINGS",
|
"SETTINGS",
|
||||||
"TOOLBOX",
|
"TOOLBOX",
|
||||||
|
|||||||
@@ -244,7 +244,8 @@ class OSCProfilesManager: NSObject {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
let fileData = try Data(contentsOf: URL(fileURLWithPath: filePath), options: .mappedIfSafe)
|
let fileData = try Data(contentsOf: URL(fileURLWithPath: filePath), options: .mappedIfSafe)
|
||||||
if let profilesEncoded = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSMutableData.self, NSMutableArray.self], from: fileData) as? NSMutableArray {
|
let profilePayloadData = try ProfileFileContainer.unpackedData(from: fileData)
|
||||||
|
if let profilesEncoded = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSMutableData.self, NSMutableArray.self], from: profilePayloadData) as? NSMutableArray {
|
||||||
importEncodedProfiles(profilesEncoded)
|
importEncodedProfiles(profilesEncoded)
|
||||||
if let selectedIndex = selectedIndex {
|
if let selectedIndex = selectedIndex {
|
||||||
setProfileToSelected(selectedIndex)
|
setProfileToSelected(selectedIndex)
|
||||||
|
|||||||
@@ -619,9 +619,11 @@ import ObjectiveC.runtime
|
|||||||
self.hasSensitivityY = CommandManager.touchPadCmds.contains(self.touchPadString) && !CommandManager.stickWheels.contains(self.touchPadString)
|
self.hasSensitivityY = CommandManager.touchPadCmds.contains(self.touchPadString) && !CommandManager.stickWheels.contains(self.touchPadString)
|
||||||
self.hasSlideThreshold = CommandManager.mousePads.contains(self.touchPadString)
|
self.hasSlideThreshold = CommandManager.mousePads.contains(self.touchPadString)
|
||||||
|
|
||||||
if CommandManager.bidirectionalVerticalTouchPads.contains(self.touchPadString){
|
if CommandManager.singleDimensionActiveTouchpads.contains(self.touchPadString){
|
||||||
self.sensitivityYMin = -4.0
|
self.sensitivityYMin = -4.0
|
||||||
self.sensitivityYMax = 4.0
|
self.sensitivityYMax = 4.0
|
||||||
|
self.sensitivityXMin = -4.0
|
||||||
|
self.sensitivityXMax = 4.0
|
||||||
}
|
}
|
||||||
|
|
||||||
if CommandManager.mousePads.contains(self.touchPadString){
|
if CommandManager.mousePads.contains(self.touchPadString){
|
||||||
@@ -2661,7 +2663,15 @@ import ObjectiveC.runtime
|
|||||||
self.updateTouchLocation(touch: touch)
|
self.updateTouchLocation(touch: touch)
|
||||||
case "MOUSEWHEEL","WHEEL":
|
case "MOUSEWHEEL","WHEEL":
|
||||||
self.weightedDeltaY = Int(self.deltaY*7.5*self.sensitivityFactorY)
|
self.weightedDeltaY = Int(self.deltaY*7.5*self.sensitivityFactorY)
|
||||||
if firstTouchMoved {LiSendHighResScrollEvent(Int16(self.weightedDeltaY))}
|
self.weightedDeltaX = Int(self.deltaX*7.5*self.sensitivityFactorX)
|
||||||
|
if firstTouchMoved {
|
||||||
|
if abs(weightedDeltaY)>abs(weightedDeltaX) {
|
||||||
|
LiSendHighResScrollEvent(Int16(self.weightedDeltaY))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LiSendHighResHScrollEvent(-Int16(self.weightedDeltaX))
|
||||||
|
}
|
||||||
|
}
|
||||||
self.updateTouchLocation(touch: touch)
|
self.updateTouchLocation(touch: touch)
|
||||||
case "DISCRETEWHEEL", "DSWHEEL":
|
case "DISCRETEWHEEL", "DSWHEEL":
|
||||||
let currentLocation = touch.location(in: self)
|
let currentLocation = touch.location(in: self)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import UIKit
|
|||||||
private var manualTick: Bool
|
private var manualTick: Bool
|
||||||
private var pencilTickEnabled: Bool
|
private var pencilTickEnabled: Bool
|
||||||
private var pressureCurveEnabled: Bool = false
|
private var pressureCurveEnabled: Bool = false
|
||||||
|
@objc private(set) var pencilTipOffset: CGPoint = .zero
|
||||||
private var manualHoverFlag: Bool = false
|
private var manualHoverFlag: Bool = false
|
||||||
@objc static var hoverSupported: Bool = false
|
@objc static var hoverSupported: Bool = false
|
||||||
// @objc static private(set) var autoHoverTermination: Bool = false
|
// @objc static private(set) var autoHoverTermination: Bool = false
|
||||||
@@ -66,6 +67,8 @@ 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
|
||||||
|
pencilTipOffset = CGPoint(x: CGFloat(settings.pencilTipOffsetX?.floatValue ?? 0),
|
||||||
|
y: CGFloat(settings.pencilTipOffsetY?.floatValue ?? 0))
|
||||||
// initialMoveEventIndexLimit = UIScreen.main.maximumFramesPerSecond > 60 ? 4 : 2
|
// initialMoveEventIndexLimit = UIScreen.main.maximumFramesPerSecond > 60 ? 4 : 2
|
||||||
initialMoveEventIndexLimit = 0
|
initialMoveEventIndexLimit = 0
|
||||||
super.init()
|
super.init()
|
||||||
@@ -110,6 +113,7 @@ import UIKit
|
|||||||
IAPManager.checkPurchaseInfo(.PencilProPack) { info in
|
IAPManager.checkPurchaseInfo(.PencilProPack) { info in
|
||||||
self.pressureCurveEnabled = self.pressureCurveEnabled && info.valid
|
self.pressureCurveEnabled = self.pressureCurveEnabled && info.valid
|
||||||
self.pencilTickEnabled = self.pencilTickEnabled && info.valid
|
self.pencilTickEnabled = self.pencilTickEnabled && info.valid
|
||||||
|
self.pencilTipOffset = info.valid ? self.pencilTipOffset : .zero
|
||||||
self.pencilProEnabled = info.valid
|
self.pencilProEnabled = info.valid
|
||||||
PencilHandler.pencilPausesNativeTouch = selectedProfile.pencilPausesNativeTouch && info.valid
|
PencilHandler.pencilPausesNativeTouch = selectedProfile.pencilPausesNativeTouch && info.valid
|
||||||
if info.valid {
|
if info.valid {
|
||||||
@@ -243,6 +247,7 @@ import UIKit
|
|||||||
|
|
||||||
for touch in touchBatch {
|
for touch in touchBatch {
|
||||||
let point = touch.preciseLocation(in: streamView)
|
let point = touch.preciseLocation(in: streamView)
|
||||||
|
.applying(CGAffineTransform(translationX: pencilTipOffset.x, y: pencilTipOffset.y))
|
||||||
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)
|
||||||
@@ -345,6 +350,10 @@ import UIKit
|
|||||||
@objc public func switchPencilHover(){
|
@objc public func switchPencilHover(){
|
||||||
manualHoverFlag = !manualHoverFlag
|
manualHoverFlag = !manualHoverFlag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc public func updatePencilTipOffset(x: CGFloat, y: CGFloat) {
|
||||||
|
pencilTipOffset = CGPoint(x: x, y: y)
|
||||||
|
}
|
||||||
|
|
||||||
@objc public func enablePencilHover(){
|
@objc public func enablePencilHover(){
|
||||||
manualHoverFlag = true
|
manualHoverFlag = true
|
||||||
|
|||||||
@@ -0,0 +1,361 @@
|
|||||||
|
//
|
||||||
|
// PencilTipOffsetCalibrationViewController.swift
|
||||||
|
// VoidLink
|
||||||
|
//
|
||||||
|
// Created by True砖家 on 2026/7/30.
|
||||||
|
// Copyright © 2026 True砖家 on Bilibili. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
private enum PencilTipOffsetCalibrationLayout {
|
||||||
|
static let containerWidth: CGFloat = 430
|
||||||
|
static let containerHeight: CGFloat = 430
|
||||||
|
static let navBarHeight: CGFloat = 50
|
||||||
|
static let canvasTop: CGFloat = 66
|
||||||
|
static let canvasWidth: CGFloat = 320
|
||||||
|
static let canvasHeight: CGFloat = 260
|
||||||
|
static let sliderTopSpacing: CGFloat = 18
|
||||||
|
static let horizontalInset: CGFloat = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class PencilTipOffsetCanvasView: UIView {
|
||||||
|
var offset: CGPoint = .zero {
|
||||||
|
didSet { setNeedsDisplay() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var rawTouchPoint: CGPoint? {
|
||||||
|
didSet { setNeedsDisplay() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
isMultipleTouchEnabled = false
|
||||||
|
backgroundColor = UIColor(white: 0.97, alpha: 1)
|
||||||
|
layer.borderColor = UIColor.black.withAlphaComponent(0.12).cgColor
|
||||||
|
layer.borderWidth = 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func draw(_ rect: CGRect) {
|
||||||
|
guard let context = UIGraphicsGetCurrentContext() else { return }
|
||||||
|
|
||||||
|
let center = CGPoint(x: bounds.midX, y: bounds.midY)
|
||||||
|
context.setLineWidth(1)
|
||||||
|
context.setStrokeColor(UIColor.black.withAlphaComponent(0.14).cgColor)
|
||||||
|
context.move(to: CGPoint(x: 0, y: center.y))
|
||||||
|
context.addLine(to: CGPoint(x: bounds.maxX, y: center.y))
|
||||||
|
context.move(to: CGPoint(x: center.x, y: 0))
|
||||||
|
context.addLine(to: CGPoint(x: center.x, y: bounds.maxY))
|
||||||
|
context.strokePath()
|
||||||
|
|
||||||
|
context.setStrokeColor(UIColor.systemBlue.withAlphaComponent(0.45).cgColor)
|
||||||
|
context.setLineWidth(2)
|
||||||
|
context.move(to: center)
|
||||||
|
context.addLine(to: CGPoint(x: center.x + offset.x, y: center.y + offset.y))
|
||||||
|
context.strokePath()
|
||||||
|
|
||||||
|
if let rawTouchPoint {
|
||||||
|
drawLandingPreview(in: context, rawPoint: rawTouchPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
context.setFillColor(UIColor.black.withAlphaComponent(0.22).cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(x: center.x - 5, y: center.y - 5, width: 10, height: 10))
|
||||||
|
|
||||||
|
let tipCenter = CGPoint(x: center.x + offset.x, y: center.y + offset.y)
|
||||||
|
context.setFillColor(UIColor.systemBlue.cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(x: tipCenter.x - 5, y: tipCenter.y - 5, width: 10, height: 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
private func drawLandingPreview(in context: CGContext, rawPoint: CGPoint) {
|
||||||
|
let correctedPoint = CGPoint(x: rawPoint.x + offset.x, y: rawPoint.y + offset.y)
|
||||||
|
|
||||||
|
context.setFillColor(UIColor.black.withAlphaComponent(0.28).cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(x: rawPoint.x - 5, y: rawPoint.y - 5, width: 10, height: 10))
|
||||||
|
|
||||||
|
context.setFillColor(UIColor.systemBlue.cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(x: correctedPoint.x - 5, y: correctedPoint.y - 5, width: 10, height: 10))
|
||||||
|
}
|
||||||
|
|
||||||
|
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
updateTouchPoint(from: touches)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
updateTouchPoint(from: touches)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
updateTouchPoint(from: touches)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
rawTouchPoint = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateTouchPoint(from touches: Set<UITouch>) {
|
||||||
|
guard let touch = touches.first(where: { $0.type == .pencil }) else { return }
|
||||||
|
rawTouchPoint = touch.preciseLocation(in: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc class PencilTipOffsetCalibrationViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||||
|
private let container = UIView()
|
||||||
|
private let canvasView = PencilTipOffsetCanvasView()
|
||||||
|
private let xSlider = UISlider()
|
||||||
|
private let ySlider = UISlider()
|
||||||
|
private let xLabel = UILabel()
|
||||||
|
private let yLabel = UILabel()
|
||||||
|
private var saveButton = UIBarButtonItem()
|
||||||
|
private var persistedOffset: CGPoint = .zero
|
||||||
|
private var currentOffset: CGPoint = .zero
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
view.isOpaque = false
|
||||||
|
view.backgroundColor = UIColor.clear
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
overrideUserInterfaceStyle = .light
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPersistedOffset()
|
||||||
|
setupContainer()
|
||||||
|
setupNavigationBar()
|
||||||
|
setupCanvas()
|
||||||
|
setupSliders()
|
||||||
|
applyOffset(currentOffset)
|
||||||
|
|
||||||
|
NotificationCenter.default.addObserver(
|
||||||
|
self,
|
||||||
|
selector: #selector(pencilProPurchaseAborted(_:)),
|
||||||
|
name: AddOnProduct.PencilProPack.purchaseAbortedNotification(),
|
||||||
|
object: nil
|
||||||
|
)
|
||||||
|
NotificationCenter.default.addObserver(
|
||||||
|
self,
|
||||||
|
selector: #selector(persistOffset),
|
||||||
|
name: AddOnProduct.PencilProPack.purchaseSucceededNotification(),
|
||||||
|
object: nil
|
||||||
|
)
|
||||||
|
|
||||||
|
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissSelf))
|
||||||
|
tap.delegate = self
|
||||||
|
view.addGestureRecognizer(tap)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillDisappear(_ animated: Bool) {
|
||||||
|
super.viewWillDisappear(animated)
|
||||||
|
NotificationCenter.default.removeObserver(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadPersistedOffset() {
|
||||||
|
let dataMan = DataManager()
|
||||||
|
let settings = dataMan.retrieveSettings()
|
||||||
|
persistedOffset = CGPoint(
|
||||||
|
x: CGFloat(settings?.pencilTipOffsetX?.floatValue ?? 0),
|
||||||
|
y: CGFloat(settings?.pencilTipOffsetY?.floatValue ?? 0)
|
||||||
|
)
|
||||||
|
currentOffset = persistedOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupContainer() {
|
||||||
|
container.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
container.backgroundColor = .white
|
||||||
|
container.layer.cornerRadius = 12
|
||||||
|
container.layer.masksToBounds = true
|
||||||
|
container.layer.borderWidth = 0.5
|
||||||
|
container.layer.borderColor = UIColor.black.withAlphaComponent(0.15).cgColor
|
||||||
|
view.addSubview(container)
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
container.centerXAnchor.constraint(equalTo: view.centerXAnchor),
|
||||||
|
container.centerYAnchor.constraint(equalTo: view.centerYAnchor),
|
||||||
|
container.widthAnchor.constraint(equalToConstant: PencilTipOffsetCalibrationLayout.containerWidth),
|
||||||
|
container.heightAnchor.constraint(equalToConstant: PencilTipOffsetCalibrationLayout.containerHeight)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupNavigationBar() {
|
||||||
|
let navBar = UINavigationBar()
|
||||||
|
navBar.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
container.addSubview(navBar)
|
||||||
|
|
||||||
|
if #available(iOS 13.0, *) {
|
||||||
|
let appearance = UINavigationBarAppearance()
|
||||||
|
appearance.shadowColor = nil
|
||||||
|
appearance.backgroundColor = .white
|
||||||
|
navBar.standardAppearance = appearance
|
||||||
|
navBar.scrollEdgeAppearance = appearance
|
||||||
|
} else {
|
||||||
|
navBar.setBackgroundImage(UIImage(), for: .default)
|
||||||
|
navBar.shadowImage = UIImage()
|
||||||
|
navBar.isTranslucent = true
|
||||||
|
navBar.backgroundColor = .clear
|
||||||
|
}
|
||||||
|
|
||||||
|
saveButton = UIBarButtonItem(title: LocalizationHelper.localizedString(forKey: "Save"), style: .plain, target: self, action: #selector(saveTapped))
|
||||||
|
let resetButton = UIBarButtonItem(title: LocalizationHelper.localizedString(forKey: "Reset"), style: .plain, target: self, action: #selector(resetTapped))
|
||||||
|
let navItem = UINavigationItem(title: LocalizationHelper.localizedString(forKey: "Pencil Tip Offset"))
|
||||||
|
navItem.leftBarButtonItems = [resetButton]
|
||||||
|
navItem.rightBarButtonItems = [saveButton]
|
||||||
|
|
||||||
|
if #available(iOS 26.0, *) {
|
||||||
|
resetButton.hidesSharedBackground = true
|
||||||
|
saveButton.hidesSharedBackground = true
|
||||||
|
resetButton.tintColor = .tintColor
|
||||||
|
saveButton.tintColor = .tintColor
|
||||||
|
}
|
||||||
|
|
||||||
|
navBar.items = [navItem]
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
navBar.topAnchor.constraint(equalTo: container.safeAreaLayoutGuide.topAnchor),
|
||||||
|
navBar.leadingAnchor.constraint(equalTo: container.leadingAnchor),
|
||||||
|
navBar.trailingAnchor.constraint(equalTo: container.trailingAnchor),
|
||||||
|
navBar.heightAnchor.constraint(equalToConstant: PencilTipOffsetCalibrationLayout.navBarHeight)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupCanvas() {
|
||||||
|
canvasView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
container.addSubview(canvasView)
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
canvasView.topAnchor.constraint(equalTo: container.topAnchor, constant: PencilTipOffsetCalibrationLayout.canvasTop),
|
||||||
|
canvasView.centerXAnchor.constraint(equalTo: container.centerXAnchor),
|
||||||
|
canvasView.widthAnchor.constraint(equalToConstant: PencilTipOffsetCalibrationLayout.canvasWidth),
|
||||||
|
canvasView.heightAnchor.constraint(equalToConstant: PencilTipOffsetCalibrationLayout.canvasHeight)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupSliders() {
|
||||||
|
let sliderStack = UIStackView()
|
||||||
|
sliderStack.axis = .vertical
|
||||||
|
sliderStack.spacing = 10
|
||||||
|
sliderStack.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
container.addSubview(sliderStack)
|
||||||
|
|
||||||
|
configureSlider(xSlider, action: #selector(sliderMoved(_:)))
|
||||||
|
configureSlider(ySlider, action: #selector(sliderMoved(_:)))
|
||||||
|
configureLabel(xLabel)
|
||||||
|
configureLabel(yLabel)
|
||||||
|
|
||||||
|
sliderStack.addArrangedSubview(makeSliderRow(label: xLabel, slider: xSlider))
|
||||||
|
sliderStack.addArrangedSubview(makeSliderRow(label: yLabel, slider: ySlider))
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
sliderStack.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: PencilTipOffsetCalibrationLayout.horizontalInset),
|
||||||
|
sliderStack.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -PencilTipOffsetCalibrationLayout.horizontalInset),
|
||||||
|
sliderStack.topAnchor.constraint(equalTo: canvasView.bottomAnchor, constant: PencilTipOffsetCalibrationLayout.sliderTopSpacing)
|
||||||
|
])
|
||||||
|
|
||||||
|
xSlider.value = Float(currentOffset.x)
|
||||||
|
ySlider.value = Float(currentOffset.y)
|
||||||
|
updateLabels()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func configureSlider(_ slider: UISlider, action: Selector) {
|
||||||
|
slider.minimumValue = -15
|
||||||
|
slider.maximumValue = 15
|
||||||
|
slider.addTarget(self, action: action, for: .valueChanged)
|
||||||
|
if PublicUtils.liquidGlassEnabled, #available(iOS 13.0, *) {
|
||||||
|
slider.maximumTrackTintColor = .tertiarySystemFill
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func configureLabel(_ label: UILabel) {
|
||||||
|
label.font = UIFont.systemFont(ofSize: 14)
|
||||||
|
label.textColor = .black
|
||||||
|
label.widthAnchor.constraint(equalToConstant: 110).isActive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private func makeSliderRow(label: UILabel, slider: UISlider) -> UIStackView {
|
||||||
|
let row = UIStackView(arrangedSubviews: [label, slider])
|
||||||
|
row.axis = .horizontal
|
||||||
|
row.alignment = .center
|
||||||
|
row.spacing = 12
|
||||||
|
return row
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func sliderMoved(_ sender: UISlider) {
|
||||||
|
currentOffset = CGPoint(x: CGFloat(xSlider.value), y: CGFloat(ySlider.value))
|
||||||
|
applyOffset(currentOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func applyOffset(_ offset: CGPoint) {
|
||||||
|
canvasView.offset = offset
|
||||||
|
updateLabels()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateLabels() {
|
||||||
|
xLabel.text = "\(LocalizationHelper.localizedString(forKey: "X Offset")): \(String(format: "%.1f", currentOffset.x))"
|
||||||
|
yLabel.text = "\(LocalizationHelper.localizedString(forKey: "Y Offset")): \(String(format: "%.1f", currentOffset.y))"
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func resetTapped() {
|
||||||
|
xSlider.value = 0
|
||||||
|
ySlider.value = 0
|
||||||
|
currentOffset = .zero
|
||||||
|
applyOffset(currentOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func persistOffset() {
|
||||||
|
let dataMan = DataManager()
|
||||||
|
guard let settings = dataMan.retrieveSettings() else { return }
|
||||||
|
settings.pencilTipOffsetX = NSNumber(value: Float(currentOffset.x))
|
||||||
|
settings.pencilTipOffsetY = NSNumber(value: Float(currentOffset.y))
|
||||||
|
dataMan.saveData()
|
||||||
|
persistedOffset = currentOffset
|
||||||
|
PencilHandler.shared?.updatePencilTipOffset(x: currentOffset.x, y: currentOffset.y)
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
AlertControllerUtil.autoCompletion = true
|
||||||
|
AlertControllerUtil.showAlert(
|
||||||
|
in: self,
|
||||||
|
title: "",
|
||||||
|
message: LocalizationHelper.localizedString(forKey: "Pencil tip offset saved"),
|
||||||
|
withCancel: false,
|
||||||
|
buttonTitle: "",
|
||||||
|
countdown: 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func saveTapped() {
|
||||||
|
saveButton.isEnabled = false
|
||||||
|
IAPManager.checkPurchaseInfo(.PencilProPack) { info in
|
||||||
|
self.saveButton.isEnabled = true
|
||||||
|
if info.valid {
|
||||||
|
self.persistOffset()
|
||||||
|
} else {
|
||||||
|
IAPManager.inAppPurchaseAction(viewController: self, product: .PencilProPack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func pencilProPurchaseAborted(_ notification: Notification) {
|
||||||
|
guard let interruption = notification.object as? PurchaseInterruption else { return }
|
||||||
|
if interruption == .lowOSVersion {
|
||||||
|
AlertControllerUtil.showAlert(
|
||||||
|
in: self,
|
||||||
|
title: "",
|
||||||
|
message: LocalizationHelper.localizedString(forKey:"PencilProPackLowOSVersionTip"),
|
||||||
|
withCancel: false,
|
||||||
|
buttonTitle: LocalizationHelper.localizedString(forKey: "OK"),
|
||||||
|
countdown: 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func dismissSelf() {
|
||||||
|
dismiss(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
||||||
|
return touch.view == view
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1000,6 +1000,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
|
|
||||||
CGPoint location = [self adjustCoordinatesForVideoArea:[gesture locationInView:self]];
|
CGPoint location = [self adjustCoordinatesForVideoArea:[gesture locationInView:self]];
|
||||||
|
PencilHandler* handler = PencilHandler.shared;
|
||||||
|
location = CGPointApplyAffineTransform(location, CGAffineTransformMakeTranslation(handler.pencilTipOffset.x, handler.pencilTipOffset.y));
|
||||||
|
|
||||||
CGSize videoSize = [self getVideoAreaSize];
|
CGSize videoSize = [self getVideoAreaSize];
|
||||||
|
|
||||||
float distance = 0.0f;
|
float distance = 0.0f;
|
||||||
|
|||||||
@@ -90,6 +90,8 @@
|
|||||||
<attribute name="passthroughGestures" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
<attribute name="passthroughGestures" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||||
<attribute name="pencilTickIntervalUs" optional="YES" attributeType="Float" defaultValueString="2000" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="pencilTickIntervalUs" optional="YES" attributeType="Float" defaultValueString="2000" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="pencilTickMode" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="pencilTickMode" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||||
|
<attribute name="pencilTipOffsetX" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||||
|
<attribute name="pencilTipOffsetY" optional="YES" attributeType="Float" defaultValueString="0" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="pinchSensitivity" optional="YES" attributeType="Float" defaultValueString="1" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="pinchSensitivity" optional="YES" attributeType="Float" defaultValueString="1" usesScalarValueType="NO" syncable="YES"/>
|
||||||
<attribute name="playAudioOnPC" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
<attribute name="playAudioOnPC" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||||
<attribute name="pointerVelocityModeDivider" optional="YES" attributeType="Float" defaultValueString="0.5" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="pointerVelocityModeDivider" optional="YES" attributeType="Float" defaultValueString="0.5" usesScalarValueType="NO" syncable="YES"/>
|
||||||
@@ -125,4 +127,4 @@
|
|||||||
<attribute name="useBuiltinMic" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
<attribute name="useBuiltinMic" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||||
<attribute name="width" attributeType="Integer 32" defaultValueString="1280" usesScalarValueType="NO" syncable="YES"/>
|
<attribute name="width" attributeType="Integer 32" defaultValueString="1280" usesScalarValueType="NO" syncable="YES"/>
|
||||||
</entity>
|
</entity>
|
||||||
</model>
|
</model>
|
||||||
@@ -13303,6 +13303,64 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Pencil Tip Offset" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Pencil Tip Offset"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔尖偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆尖偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆尖偏移"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Pencil tip offset saved" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Pencil tip offset saved"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔尖偏移已保存"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆尖偏移已儲存"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆尖偏移已儲存"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Pencil hover" : {
|
"Pencil hover" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -19111,6 +19169,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"X Offset" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "X Offset"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "X 偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "X 偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "X 偏移"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Yaw factor: %.2f" : {
|
"Yaw factor: %.2f" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -19134,6 +19221,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Y Offset" : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Y Offset"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Y 偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Y 偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "Y 偏移"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Yes" : {
|
"Yes" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+1
-1
@@ -138,7 +138,7 @@ private enum ProfilePayloadCompression: UInt8 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum ProfileFileContainer {
|
enum ProfileFileContainer {
|
||||||
private static let magic = Array("VLPR".utf8)
|
private static let magic = Array("VLPR".utf8)
|
||||||
private static let version: UInt8 = 1
|
private static let version: UInt8 = 1
|
||||||
private static let headerSize = 14
|
private static let headerSize = 14
|
||||||
|
|||||||
@@ -1890,6 +1890,8 @@ static NSMutableSet* hostList;
|
|||||||
// if([UIScreen mainScreen].maximumFramesPerSecond < 65) settings.touchMoveEventInterval = @(60);
|
// if([UIScreen mainScreen].maximumFramesPerSecond < 65) settings.touchMoveEventInterval = @(60);
|
||||||
settings.onscreenControls = @(OnScreenControlsLevelCustom);
|
settings.onscreenControls = @(OnScreenControlsLevelCustom);
|
||||||
settings.pencilTickIntervalUs = @(1750);
|
settings.pencilTickIntervalUs = @(1750);
|
||||||
|
settings.pencilTipOffsetX = @(0);
|
||||||
|
settings.pencilTipOffsetY = @(0);
|
||||||
settings.oscLayoutToolFingers = @(99);
|
settings.oscLayoutToolFingers = @(99);
|
||||||
settings.keyboardToggleFingers = @(99);
|
settings.keyboardToggleFingers = @(99);
|
||||||
|
|
||||||
|
|||||||
@@ -291,6 +291,9 @@
|
|||||||
@property (strong, nonatomic) IBOutlet UIStackView *pencilTickIntervalStack;
|
@property (strong, nonatomic) IBOutlet UIStackView *pencilTickIntervalStack;
|
||||||
@property (strong, nonatomic) IBOutlet UISlider *pencilTickIntervalSlider;
|
@property (strong, nonatomic) IBOutlet UISlider *pencilTickIntervalSlider;
|
||||||
|
|
||||||
|
@property (weak, nonatomic) IBOutlet UIStackView *pencilTipOffsetStack;
|
||||||
|
@property (weak, nonatomic) IBOutlet UISwitch *pencilTipOffsetSwitch;
|
||||||
|
|
||||||
@property (weak, nonatomic) IBOutlet UIStackView *doubleTapShortcutStack;
|
@property (weak, nonatomic) IBOutlet UIStackView *doubleTapShortcutStack;
|
||||||
@property (weak, nonatomic) IBOutlet UISwitch *doubleTapShortcutSwitch;
|
@property (weak, nonatomic) IBOutlet UISwitch *doubleTapShortcutSwitch;
|
||||||
|
|
||||||
|
|||||||
@@ -1074,6 +1074,8 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
self.pencilTickIntervalStack.hasDynamicLabel = YES;
|
self.pencilTickIntervalStack.hasDynamicLabel = YES;
|
||||||
[self addSetting:self.pencilTickIntervalStack ofId:@"pencilTickIntervalStack" to:pencilSection];
|
[self addSetting:self.pencilTickIntervalStack ofId:@"pencilTickIntervalStack" to:pencilSection];
|
||||||
|
|
||||||
|
[self addSetting:self.pencilTipOffsetStack ofId:@"pencilTipOffsetStack" to:pencilSection];
|
||||||
|
|
||||||
self.pressureCurveStack.isGameProfileSetting = YES;
|
self.pressureCurveStack.isGameProfileSetting = YES;
|
||||||
[self addSetting:self.pressureCurveStack ofId:@"pressureCurveStack" to:pencilSection];
|
[self addSetting:self.pressureCurveStack ofId:@"pressureCurveStack" to:pencilSection];
|
||||||
|
|
||||||
@@ -4069,6 +4071,7 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
[self.squeezeShortcutSwitch setOn:false];
|
[self.squeezeShortcutSwitch setOn:false];
|
||||||
[self.pencilPausesNativeTouchSwitch setOn:false];
|
[self.pencilPausesNativeTouchSwitch setOn:false];
|
||||||
[self.disablePencilSlideGestureSwitch setOn:false];
|
[self.disablePencilSlideGestureSwitch setOn:false];
|
||||||
|
[self.pencilTipOffsetSwitch setOn:false];
|
||||||
|
|
||||||
|
|
||||||
NSNumber *value = notification.userInfo[@"interruption"];
|
NSNumber *value = notification.userInfo[@"interruption"];
|
||||||
@@ -4109,6 +4112,15 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)pencilTipOffsetSwitchFlipped:(UISwitch* )sender{
|
||||||
|
if(sender.isOn && !settingsViewJustLoaded){
|
||||||
|
PencilTipOffsetCalibrationViewController* calibrationVC = [[PencilTipOffsetCalibrationViewController alloc] init];
|
||||||
|
calibrationVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
|
||||||
|
self.definesPresentationContext = true;
|
||||||
|
[self presentViewController:calibrationVC animated:YES completion:nil];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)doubleTapShortcutSwitchFlipped:(UISwitch* )sender{
|
- (void)doubleTapShortcutSwitchFlipped:(UISwitch* )sender{
|
||||||
if(sender.isOn && !settingsViewJustLoaded){
|
if(sender.isOn && !settingsViewJustLoaded){
|
||||||
[IAPManager checkPurchaseInfo:AddOnProductPencilProPack completion:^(PurchaseInfo* info) {
|
[IAPManager checkPurchaseInfo:AddOnProductPencilProPack completion:^(PurchaseInfo* info) {
|
||||||
@@ -4203,6 +4215,9 @@ BOOL isCustomResolution(int resolutionSelected) {
|
|||||||
[self.pencilTickIntervalSlider addTarget:self action:@selector(pencilTickIntervalSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
[self.pencilTickIntervalSlider addTarget:self action:@selector(pencilTickIntervalSliderMoved:) forControlEvents:UIControlEventValueChanged];
|
||||||
[self.pencilTickIntervalSlider sendActionsForControlEvents:UIControlEventValueChanged];
|
[self.pencilTickIntervalSlider sendActionsForControlEvents:UIControlEventValueChanged];
|
||||||
|
|
||||||
|
[self.pencilTipOffsetSwitch setOn:(fabs(tempSettings.pencilTipOffsetX.floatValue) > 0.01 || fabs(tempSettings.pencilTipOffsetY.floatValue) > 0.01)];
|
||||||
|
[self.pencilTipOffsetSwitch addTarget:self action:@selector(pencilTipOffsetSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||||
|
|
||||||
[self.pressureCurveSwitch addTarget:self action:@selector(pressureCurveSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
[self.pressureCurveSwitch addTarget:self action:@selector(pressureCurveSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||||
[self.doubleTapShortcutSwitch addTarget:self action:@selector(doubleTapShortcutSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
[self.doubleTapShortcutSwitch addTarget:self action:@selector(doubleTapShortcutSwitchFlipped:) forControlEvents:UIControlEventValueChanged];
|
||||||
|
|
||||||
|
|||||||
@@ -5564,6 +5564,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pTO-ff-lbl.text" : {
|
||||||
|
"comment" : "Class = \"UILabel\"; text = \"Pencil Tip Offset\"; ObjectID = \"pTO-ff-lbl\";",
|
||||||
|
"extractionState" : "extracted_with_value",
|
||||||
|
"localizations" : {
|
||||||
|
"en" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "new",
|
||||||
|
"value" : "Pencil Tip Offset"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔尖偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆尖偏移"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆尖偏移"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Pwa-YK-6Q2.text" : {
|
"Pwa-YK-6Q2.text" : {
|
||||||
"comment" : "Class = \"UILabel\"; text = \"Opacity\"; ObjectID = \"Pwa-YK-6Q2\";",
|
"comment" : "Class = \"UILabel\"; text = \"Opacity\"; ObjectID = \"Pwa-YK-6Q2\";",
|
||||||
"extractionState" : "extracted_with_value",
|
"extractionState" : "extracted_with_value",
|
||||||
@@ -7254,4 +7284,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"version" : "1.0"
|
"version" : "1.0"
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user