stroke start equalization and filtering
This commit is contained in:
1 parent
42f29074fa
commit
e59f3ba1ab
5 files changed
+410
-36
No files matched your search
@@ -59,6 +59,10 @@ typedef NS_ENUM(NSInteger, PencilHoverMode) {
|
|||||||
@property (nonatomic, assign) int controllerGyroSwitchHold;
|
@property (nonatomic, assign) int controllerGyroSwitchHold;
|
||||||
@property (nonatomic, assign) int controllerGyroSwitchToggle;
|
@property (nonatomic, assign) int controllerGyroSwitchToggle;
|
||||||
@property NSArray<NSNumber *> *pressureCurvePoints;
|
@property NSArray<NSNumber *> *pressureCurvePoints;
|
||||||
|
// @property NSArray<NSNumber *> *initialTouchPressureCurvePoints;
|
||||||
|
@property (nonatomic, assign) int phase1StrokeSampleIndexEnd;
|
||||||
|
@property (nonatomic, assign) int phase2StrokeSampleIndexEnd;
|
||||||
|
@property (nonatomic, assign) CGFloat strokeEqualizationStrength;
|
||||||
@property (nonatomic, assign) bool pressureCurveEnabled;
|
@property (nonatomic, assign) bool pressureCurveEnabled;
|
||||||
@property (nonatomic, assign) bool doubleTapShorcutEnabled;
|
@property (nonatomic, assign) bool doubleTapShorcutEnabled;
|
||||||
@property NSString *brushShortcut;
|
@property NSString *brushShortcut;
|
||||||
|
|||||||
@@ -52,6 +52,10 @@
|
|||||||
[encoder encodeInt:self.controllerGyroSwitchHold forKey:@"controllerGyroSwitchHold"];
|
[encoder encodeInt:self.controllerGyroSwitchHold forKey:@"controllerGyroSwitchHold"];
|
||||||
[encoder encodeInt:self.controllerGyroSwitchToggle forKey:@"controllerGyroSwitchToggle"];
|
[encoder encodeInt:self.controllerGyroSwitchToggle forKey:@"controllerGyroSwitchToggle"];
|
||||||
[encoder encodeObject:self.pressureCurvePoints forKey:@"pressureCurvePoints"];
|
[encoder encodeObject:self.pressureCurvePoints forKey:@"pressureCurvePoints"];
|
||||||
|
// [encoder encodeObject:self.initialTouchPressureCurvePoints forKey:@"initialTouchPressureCurvePoints"];
|
||||||
|
[encoder encodeInt:self.phase1StrokeSampleIndexEnd forKey:@"phase1StrokeSampleIndexEnd"];
|
||||||
|
[encoder encodeInt:self.phase2StrokeSampleIndexEnd forKey:@"phase2StrokeSampleIndexEnd"];
|
||||||
|
[encoder encodeDouble:self.strokeEqualizationStrength forKey:@"strokeEqualizationStrength"];
|
||||||
[encoder encodeBool:self.pressureCurveEnabled forKey:@"pressureCurveEnabled"];
|
[encoder encodeBool:self.pressureCurveEnabled forKey:@"pressureCurveEnabled"];
|
||||||
[encoder encodeBool:self.doubleTapShorcutEnabled forKey:@"doubleTapShorcutEnabled"];
|
[encoder encodeBool:self.doubleTapShorcutEnabled forKey:@"doubleTapShorcutEnabled"];
|
||||||
[encoder encodeObject:self.brushShortcut forKey:@"brushShortcut"];
|
[encoder encodeObject:self.brushShortcut forKey:@"brushShortcut"];
|
||||||
@@ -108,6 +112,7 @@
|
|||||||
self.reverseGyroHoldButton = [decoder containsValueForKey:@"reverseGyroHoldButton"] ? [decoder decodeBoolForKey:@"reverseGyroHoldButton"] : false;
|
self.reverseGyroHoldButton = [decoder containsValueForKey:@"reverseGyroHoldButton"] ? [decoder decodeBoolForKey:@"reverseGyroHoldButton"] : false;
|
||||||
self.controllerGyroSwitchHold = [decoder containsValueForKey:@"controllerGyroSwitchHold"] ? [decoder decodeIntForKey:@"controllerGyroSwitchHold"] : ControllerButtonNull;
|
self.controllerGyroSwitchHold = [decoder containsValueForKey:@"controllerGyroSwitchHold"] ? [decoder decodeIntForKey:@"controllerGyroSwitchHold"] : ControllerButtonNull;
|
||||||
self.controllerGyroSwitchToggle = [decoder containsValueForKey:@"controllerGyroSwitchToggle"] ? [decoder decodeIntForKey:@"controllerGyroSwitchToggle"] : ControllerButtonNull;
|
self.controllerGyroSwitchToggle = [decoder containsValueForKey:@"controllerGyroSwitchToggle"] ? [decoder decodeIntForKey:@"controllerGyroSwitchToggle"] : ControllerButtonNull;
|
||||||
|
|
||||||
self.pressureCurvePoints =
|
self.pressureCurvePoints =
|
||||||
[decoder containsValueForKey:@"pressureCurvePoints"]
|
[decoder containsValueForKey:@"pressureCurvePoints"]
|
||||||
? [decoder decodeObjectOfClasses:
|
? [decoder decodeObjectOfClasses:
|
||||||
@@ -117,6 +122,21 @@
|
|||||||
nil]
|
nil]
|
||||||
forKey:@"pressureCurvePoints"]
|
forKey:@"pressureCurvePoints"]
|
||||||
: @[@0.0, @0.0, @1.0, @1.0];
|
: @[@0.0, @0.0, @1.0, @1.0];
|
||||||
|
|
||||||
|
/* self.initialTouchPressureCurvePoints =
|
||||||
|
[decoder containsValueForKey:@"initialTouchPressureCurvePoints"]
|
||||||
|
? [decoder decodeObjectOfClasses:
|
||||||
|
[NSSet setWithObjects:
|
||||||
|
[NSArray class],
|
||||||
|
[NSNumber class],
|
||||||
|
nil]
|
||||||
|
forKey:@"initialTouchPressureCurvePoints"]
|
||||||
|
: @[@0.0, @0.0, @1.0, @1.0]; */
|
||||||
|
|
||||||
|
self.phase1StrokeSampleIndexEnd = [decoder containsValueForKey:@"phase1StrokeSampleIndexEnd"] ? [decoder decodeIntForKey:@"phase1StrokeSampleIndexEnd"] : 10;
|
||||||
|
self.phase2StrokeSampleIndexEnd = [decoder containsValueForKey:@"phase2StrokeSampleIndexEnd"] ? [decoder decodeIntForKey:@"phase2StrokeSampleIndexEnd"] : 24;
|
||||||
|
self.strokeEqualizationStrength = [decoder containsValueForKey:@"strokeEqualizationStrength"] ? [decoder decodeFloatForKey:@"strokeEqualizationStrength"] : 1.0;
|
||||||
|
|
||||||
self.pressureCurveEnabled = [decoder containsValueForKey:@"pressureCurveEnabled"] ? [decoder decodeBoolForKey:@"pressureCurveEnabled"] : false;
|
self.pressureCurveEnabled = [decoder containsValueForKey:@"pressureCurveEnabled"] ? [decoder decodeBoolForKey:@"pressureCurveEnabled"] : false;
|
||||||
|
|
||||||
self.doubleTapShorcutEnabled = [decoder containsValueForKey:@"doubleTapShorcutEnabled"] ? [decoder decodeBoolForKey:@"doubleTapShorcutEnabled"] : false;
|
self.doubleTapShorcutEnabled = [decoder containsValueForKey:@"doubleTapShorcutEnabled"] ? [decoder decodeBoolForKey:@"doubleTapShorcutEnabled"] : false;
|
||||||
@@ -190,6 +210,10 @@
|
|||||||
copy.controllerGyroSwitchHold = self.controllerGyroSwitchHold;
|
copy.controllerGyroSwitchHold = self.controllerGyroSwitchHold;
|
||||||
copy.controllerGyroSwitchToggle = self.controllerGyroSwitchToggle;
|
copy.controllerGyroSwitchToggle = self.controllerGyroSwitchToggle;
|
||||||
copy.pressureCurvePoints = [[NSMutableArray alloc] initWithArray:self.pressureCurvePoints copyItems:YES];
|
copy.pressureCurvePoints = [[NSMutableArray alloc] initWithArray:self.pressureCurvePoints copyItems:YES];
|
||||||
|
// copy.initialTouchPressureCurvePoints = [[NSMutableArray alloc] initWithArray:self.initialTouchPressureCurvePoints copyItems:YES];
|
||||||
|
copy.phase1StrokeSampleIndexEnd = self.phase1StrokeSampleIndexEnd;
|
||||||
|
copy.phase2StrokeSampleIndexEnd = self.phase2StrokeSampleIndexEnd;
|
||||||
|
copy.strokeEqualizationStrength = self.strokeEqualizationStrength;
|
||||||
copy.pressureCurveEnabled = self.pressureCurveEnabled;
|
copy.pressureCurveEnabled = self.pressureCurveEnabled;
|
||||||
copy.doubleTapShorcutEnabled = self.doubleTapShorcutEnabled;
|
copy.doubleTapShorcutEnabled = self.doubleTapShorcutEnabled;
|
||||||
copy.brushShortcut = [self.brushShortcut mutableCopy]; // NSString → NSMutableString
|
copy.brushShortcut = [self.brushShortcut mutableCopy]; // NSString → NSMutableString
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import UIKit
|
|||||||
@objc static private(set) var hoverMode: PencilHoverMode = .HoverPencil
|
@objc static private(set) var hoverMode: PencilHoverMode = .HoverPencil
|
||||||
private(set) var pencilProEnabled: Bool = false
|
private(set) var pencilProEnabled: Bool = false
|
||||||
private var isFirstMove: Bool = false
|
private var isFirstMove: Bool = false
|
||||||
private var moveEventIndex: Int64 = 0
|
private var strokeSampleIndex: Int32 = 0
|
||||||
private var initialMoveEventIndexLimit: Int64
|
private var initialMoveEventIndexLimit: Int64
|
||||||
private var touchBeganForce: Float = 0
|
private var touchBeganForce: Float = 0
|
||||||
@objc static private(set) var isDrawing: Bool = false
|
@objc static private(set) var isDrawing: Bool = false
|
||||||
@@ -36,7 +36,27 @@ import UIKit
|
|||||||
// static private let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
// static private let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
static private var selectedProfile:OSCProfile?
|
static private var selectedProfile:OSCProfile?
|
||||||
|
|
||||||
private var pressureLUT = PressureCurveLUT(curve: PressureCurve())
|
private var strokeLUT = PressureCurveLUT(curve: PressureCurve())
|
||||||
|
// private var initialTouchLUT = PressureCurveLUT(curve: PressureCurve())
|
||||||
|
private var phase1StrokeSampleIndexEnd:Int32 = 0
|
||||||
|
private var phase2StrokeSampleIndexEnd:Int32 = 0
|
||||||
|
private var phase2EqualizationStrength:Float = 0
|
||||||
|
|
||||||
|
enum StrokePhase: UInt8, CaseIterable {
|
||||||
|
case phase1
|
||||||
|
case phase2
|
||||||
|
case phase3
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getStrokePhase(sampleIndex:Int32) -> StrokePhase {
|
||||||
|
if sampleIndex > phase2StrokeSampleIndexEnd {
|
||||||
|
return .phase3
|
||||||
|
}
|
||||||
|
if sampleIndex > phase1StrokeSampleIndexEnd {
|
||||||
|
return .phase2
|
||||||
|
}
|
||||||
|
return .phase1
|
||||||
|
}
|
||||||
|
|
||||||
@objc init(streamView: UIView, settings: TemporarySettings) {
|
@objc init(streamView: UIView, settings: TemporarySettings) {
|
||||||
self.streamView = streamView
|
self.streamView = streamView
|
||||||
@@ -96,12 +116,23 @@ import UIKit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let persistedCurvePoints = PressureCurve.importCurvePoints(selectedProfile.pressureCurvePoints)
|
let strokePressureCurvePoints = PressureCurve.importCurvePoints(selectedProfile.pressureCurvePoints)
|
||||||
let curve = PressureCurve()
|
let strokePressureCurve = PressureCurve()
|
||||||
curve.polylinePoints = persistedCurvePoints
|
strokePressureCurve.polylinePoints = strokePressureCurvePoints
|
||||||
curve.buildCurveSegments()
|
strokePressureCurve.buildCurveSegments()
|
||||||
|
|
||||||
|
// let initialTouchPressureCurvePoints = PressureCurve.importCurvePoints(selectedProfile.initialTouchPressureCurvePoints)
|
||||||
|
// let initialTouchPressureCurve = PressureCurve()
|
||||||
|
// initialTouchPressureCurve.polylinePoints = initialTouchPressureCurvePoints
|
||||||
|
// initialTouchPressureCurve.buildCurveSegments()
|
||||||
|
|
||||||
|
phase1StrokeSampleIndexEnd = selectedProfile.phase1StrokeSampleIndexEnd
|
||||||
|
phase2StrokeSampleIndexEnd = selectedProfile.phase2StrokeSampleIndexEnd
|
||||||
|
phase2EqualizationStrength = Float(selectedProfile.strokeEqualizationStrength)
|
||||||
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()) {
|
DispatchQueue.main.asyncAfter(deadline: .now()) {
|
||||||
self.pressureLUT = PressureCurveLUT(curve: curve)
|
self.strokeLUT = PressureCurveLUT(curve: strokePressureCurve)
|
||||||
|
// self.initialTouchLUT = PressureCurveLUT(curve: initialTouchPressureCurve)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,9 +140,11 @@ 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 }
|
||||||
|
previousForce = 0
|
||||||
|
previousTargetForce = 0
|
||||||
PencilHandler.isDrawing = true
|
PencilHandler.isDrawing = true
|
||||||
// isFirstMove = true
|
// isFirstMove = true
|
||||||
moveEventIndex = 0
|
strokeSampleIndex = 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])
|
||||||
@@ -124,7 +157,6 @@ 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?) {
|
||||||
@@ -194,6 +226,9 @@ import UIKit
|
|||||||
return UInt8(90 - min(90, Int(altitudeDegs)))
|
return UInt8(90 - min(90, Int(altitudeDegs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var previousForce: Float = 0
|
||||||
|
var previousTargetForce: Float = 0
|
||||||
|
var phase2IndexCount: Int32 = 0
|
||||||
private func sendStylusEvent(touchBatch: [UITouch], with event: UIEvent? = nil) -> DispatchTime {
|
private func sendStylusEvent(touchBatch: [UITouch], with event: UIEvent? = nil) -> DispatchTime {
|
||||||
guard let streamView = streamView, touchBatch.count>0 else { return .now() }
|
guard let streamView = streamView, touchBatch.count>0 else { return .now() }
|
||||||
|
|
||||||
@@ -201,6 +236,8 @@ import UIKit
|
|||||||
var previousTimeStamp: TimeInterval = 0
|
var previousTimeStamp: TimeInterval = 0
|
||||||
var delay:TimeInterval = 0
|
var delay:TimeInterval = 0
|
||||||
var dispatchMoment: DispatchTime = .now()
|
var dispatchMoment: DispatchTime = .now()
|
||||||
|
|
||||||
|
phase2IndexCount = phase2StrokeSampleIndexEnd - phase1StrokeSampleIndexEnd
|
||||||
|
|
||||||
for touch in touchBatch {
|
for touch in touchBatch {
|
||||||
let point = touch.preciseLocation(in: streamView)
|
let point = touch.preciseLocation(in: streamView)
|
||||||
@@ -209,22 +246,50 @@ import UIKit
|
|||||||
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))
|
var force = Float(touch.force/touch.maximumPossibleForce)/sin(Float(altitude))
|
||||||
var targetForce = pressureCurveEnabled ? self.pressureLUT.value(at: force) : force
|
force = (self.pencilTickEnabled && force == 0) ? previousForce : force
|
||||||
|
|
||||||
|
self.strokeSampleIndex += 1
|
||||||
|
|
||||||
|
var targetForce:Float
|
||||||
|
var equalizationStep:Float = 0
|
||||||
|
var equalizedForce:Float = 0
|
||||||
|
if(phase2IndexCount>0){
|
||||||
|
equalizationStep = (phase2EqualizationStrength-1)/Float(phase2IndexCount-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let strokePhase = getStrokePhase(sampleIndex: self.strokeSampleIndex)
|
||||||
|
switch strokePhase {
|
||||||
|
case .phase1:
|
||||||
|
targetForce = pencilTickEnabled ? 0 : self.strokeLUT.value(at: force)
|
||||||
|
case .phase2:
|
||||||
|
targetForce = self.strokeLUT.value(at: force)
|
||||||
|
targetForce = max(targetForce,previousTargetForce)
|
||||||
|
equalizedForce = targetForce*(phase2EqualizationStrength - equalizationStep*Float(strokeSampleIndex-phase1StrokeSampleIndexEnd-1))
|
||||||
|
case .phase3:
|
||||||
|
targetForce = self.strokeLUT.value(at: force)
|
||||||
|
}
|
||||||
|
targetForce = self.pressureCurveEnabled ? targetForce : force
|
||||||
|
|
||||||
|
previousForce = force
|
||||||
|
previousTargetForce = targetForce
|
||||||
|
|
||||||
let eventType:UInt8
|
let eventType:UInt8
|
||||||
|
|
||||||
switch touch.phase {
|
switch touch.phase {
|
||||||
case .began:
|
case .began:
|
||||||
eventType = UInt8(manualHoverFlag ? LI_TOUCH_EVENT_HOVER : LI_TOUCH_EVENT_DOWN)
|
eventType = UInt8(manualHoverFlag ? LI_TOUCH_EVENT_HOVER : 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(manualHoverFlag ? LI_TOUCH_EVENT_HOVER_LEAVE : LI_TOUCH_EVENT_UP)
|
eventType = UInt8(manualHoverFlag ? LI_TOUCH_EVENT_HOVER_LEAVE : LI_TOUCH_EVENT_UP)
|
||||||
|
previousForce = 0
|
||||||
|
previousTargetForce = 0
|
||||||
case .cancelled:
|
case .cancelled:
|
||||||
eventType = UInt8(manualHoverFlag ? LI_TOUCH_EVENT_HOVER_LEAVE : LI_TOUCH_EVENT_UP)
|
eventType = UInt8(manualHoverFlag ? LI_TOUCH_EVENT_HOVER_LEAVE : LI_TOUCH_EVENT_UP)
|
||||||
|
previousForce = 0
|
||||||
|
previousTargetForce = 0
|
||||||
default:
|
default:
|
||||||
eventType = UInt8(LI_TOUCH_EVENT_HOVER)
|
eventType = UInt8(LI_TOUCH_EVENT_HOVER)
|
||||||
}
|
}
|
||||||
@@ -241,16 +306,19 @@ import UIKit
|
|||||||
tickMoment += (manualTick ? tickInterval : touch.timestamp - previousTimeStamp)
|
tickMoment += (manualTick ? tickInterval : touch.timestamp - previousTimeStamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
let sendableForce = targetForce
|
let sendableForce = strokePhase == .phase2 ? equalizedForce : targetForce
|
||||||
|
|
||||||
DispatchQueue.global().asyncAfter(deadline: dispatchMoment + tickMoment + delay) {
|
DispatchQueue.global().asyncAfter(deadline: dispatchMoment + tickMoment + delay) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if PencilHandler.autoHoverEnabled, eventType == UInt8(LI_TOUCH_EVENT_DOWN) {
|
if PencilHandler.autoHoverEnabled, eventType == UInt8(LI_TOUCH_EVENT_DOWN) {
|
||||||
LiSendPenEvent(UInt8(LI_TOUCH_EVENT_HOVER_LEAVE), UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), 0, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude)))
|
LiSendPenEvent(UInt8(LI_TOUCH_EVENT_HOVER_LEAVE), UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), 0, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude)))
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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 strokePhase != .phase1 || !self.pencilTickEnabled {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)))}
|
||||||
|
else {
|
||||||
|
LiSendPenEvent(UInt8(LI_TOUCH_EVENT_HOVER), UInt8(LI_TOOL_TYPE_PEN), 0, Float(normalizedLocation.x), Float(normalizedLocation.y), 0, 0, 0, self.getRotation(fromAzimuthAngle: Float(azimuth)), self.getTilt(fromAltitudeAngle: Float(altitude)))
|
||||||
|
}
|
||||||
|
|
||||||
if eventType == UInt8(LI_TOUCH_EVENT_UP) {
|
if eventType == UInt8(LI_TOUCH_EVENT_UP) {
|
||||||
PencilHandler.isDrawing = false
|
PencilHandler.isDrawing = false
|
||||||
|
|||||||
@@ -476,16 +476,43 @@ extension UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - ViewController
|
// MARK: - ViewController
|
||||||
class PressureCurveViewController: UIViewController {
|
class PressureCurveViewController: UIViewController, UIGestureRecognizerDelegate {
|
||||||
|
|
||||||
private var navBar = UINavigationBar()
|
private var navBar = UINavigationBar()
|
||||||
|
private var saveButton: UIBarButtonItem = UIBarButtonItem()
|
||||||
|
|
||||||
private var container = UIView()
|
private var container = UIView()
|
||||||
private var curveView = PressureCurveView()
|
private var curveView = PressureCurveView()
|
||||||
|
// private var initialTouchCurvePoints: [CGPoint] = []
|
||||||
|
private var strokePressureCurvePoints: [CGPoint] = []
|
||||||
|
|
||||||
|
private var phase1StrokeSampleIndexEnd: Int32 = 0
|
||||||
|
private var phase2StrokeSampleIndexEnd: Int32 = 0
|
||||||
|
|
||||||
private var minPressure: CGFloat = 0
|
private var minPressure: CGFloat = 0
|
||||||
private var maxPressure: CGFloat = 1
|
private var maxPressure: CGFloat = 1
|
||||||
private var isFirstLaunch: Bool = GenericUtils.isFirstLaunchPressureCurveTool()
|
private var isFirstLaunch: Bool = GenericUtils.isFirstLaunchPressureCurveTool()
|
||||||
|
|
||||||
|
// private var curvePhaseButton: UIBarButtonItem = UIBarButtonItem()
|
||||||
|
private let hookFilterLabel = UILabel()
|
||||||
|
private let hookFilterSlider = UISlider()
|
||||||
|
private let strokeEqualizationDepthLabel = UILabel()
|
||||||
|
private let strokeEqualizationDepthSlider = UISlider()
|
||||||
|
private let strokeEqualizationStrengthLabel = UILabel()
|
||||||
|
private let strokeEqualizationStrengthSlider = UISlider()
|
||||||
|
|
||||||
|
enum PressureCurvePhase: UInt8, CaseIterable {
|
||||||
|
case initialTouch
|
||||||
|
case stroke
|
||||||
|
func next() -> PressureCurvePhase {
|
||||||
|
let all = Self.allCases
|
||||||
|
let index = all.firstIndex(of: self)!
|
||||||
|
let nextIndex = (index + 1) % all.count
|
||||||
|
return all[nextIndex]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private(set) var curvePhase: PressureCurvePhase = .initialTouch
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
@@ -496,34 +523,39 @@ class PressureCurveViewController: UIViewController {
|
|||||||
let curveWidth: CGFloat = 530
|
let curveWidth: CGFloat = 530
|
||||||
let curveHeight: CGFloat = 530
|
let curveHeight: CGFloat = 530
|
||||||
curveView = PressureCurveView(frame: CGRect(x: 0, y: 0, width: curveWidth, height: curveHeight))
|
curveView = PressureCurveView(frame: CGRect(x: 0, y: 0, width: curveWidth, height: curveHeight))
|
||||||
curveView.center = self.view.center
|
curveView.center = CGPoint(x: self.view.center.x, y: self.view.center.y)
|
||||||
curveView.backgroundColor = .white
|
curveView.backgroundColor = .white
|
||||||
curveView.layer.cornerRadius = 0
|
curveView.layer.cornerRadius = 0
|
||||||
curveView.layer.masksToBounds = true
|
curveView.layer.masksToBounds = true
|
||||||
|
|
||||||
container = UIView(frame: CGRect(x: 0, y: 0, width: curveWidth+10, height: curveHeight+50))
|
container = UIView(frame: CGRect(x: 0, y: 0, width: curveWidth+10, height: curveHeight+148))
|
||||||
container.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY-20)
|
container.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.midY+3)
|
||||||
container.backgroundColor = .white
|
container.backgroundColor = .white
|
||||||
container.layer.cornerRadius = 12
|
container.layer.cornerRadius = 12
|
||||||
container.layer.masksToBounds = true
|
container.layer.masksToBounds = true
|
||||||
container.layer.borderWidth = 2
|
container.layer.borderWidth = 0.5
|
||||||
container.layer.borderColor = ThemeManager.separatorColor.cgColor
|
container.layer.borderColor = UIColor.black.withAlphaComponent(0.15).cgColor
|
||||||
container.addSubview(curveView)
|
container.addSubview(curveView)
|
||||||
|
|
||||||
|
self.setupNavigationBar()
|
||||||
|
self.setupBottomSliders()
|
||||||
self.loadPersistedCurve()
|
self.loadPersistedCurve()
|
||||||
self.curveView.showGraph = true
|
self.curveView.showGraph = true
|
||||||
|
|
||||||
self.setupNavigationBar()
|
|
||||||
|
|
||||||
self.view.addSubview(container)
|
self.view.addSubview(container)
|
||||||
|
|
||||||
curveView.translatesAutoresizingMaskIntoConstraints = false
|
curveView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
curveView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
|
curveView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
|
||||||
curveView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
|
curveView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor,constant: -25),
|
||||||
curveView.widthAnchor.constraint(equalToConstant: curveWidth),
|
curveView.widthAnchor.constraint(equalToConstant: curveWidth),
|
||||||
curveView.heightAnchor.constraint(equalToConstant: curveHeight)
|
curveView.heightAnchor.constraint(equalToConstant: curveHeight)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
self.displayCurve()
|
||||||
|
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(
|
NotificationCenter.default.addObserver(
|
||||||
self,
|
self,
|
||||||
selector: #selector(pencilProPurchaseAborted(_:)),
|
selector: #selector(pencilProPurchaseAborted(_:)),
|
||||||
@@ -536,6 +568,10 @@ class PressureCurveViewController: UIViewController {
|
|||||||
name: AddOnProduct.PencilProPack.purchaseSucceededNotification(),
|
name: AddOnProduct.PencilProPack.purchaseSucceededNotification(),
|
||||||
object: nil
|
object: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissSelf))
|
||||||
|
tap.delegate = self
|
||||||
|
view.addGestureRecognizer(tap)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
@@ -573,11 +609,123 @@ class PressureCurveViewController: UIViewController {
|
|||||||
|
|
||||||
private func loadPersistedCurve() {
|
private func loadPersistedCurve() {
|
||||||
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
let persistedCurvePoints = PressureCurve.importCurvePoints(oscProfileMan.getSelectedProfile().pressureCurvePoints)
|
let oscProfile = oscProfileMan.getSelectedProfile()
|
||||||
curveView.curve.polylinePoints = persistedCurvePoints
|
// initialTouchCurvePoints = PressureCurve.importCurvePoints(oscProfile.initialTouchPressureCurvePoints)
|
||||||
|
strokePressureCurvePoints = PressureCurve.importCurvePoints(oscProfile.pressureCurvePoints)
|
||||||
|
displayCurve()
|
||||||
|
|
||||||
|
hookFilterSlider.value = Float(oscProfile.phase1StrokeSampleIndexEnd)
|
||||||
|
strokeEqualizationDepthSlider.value = Float(oscProfile.phase2StrokeSampleIndexEnd)
|
||||||
|
strokeEqualizationStrengthSlider.value = Float(oscProfile.strokeEqualizationStrength)
|
||||||
|
|
||||||
|
strokeEqualizationDepthSliderMoved(strokeEqualizationDepthSlider)
|
||||||
|
hookFilterDepthSliderMoved(hookFilterSlider)
|
||||||
|
strokeEqualizationStrengthSliderMoved(strokeEqualizationStrengthSlider)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func displayCurve() {
|
||||||
|
switch curvePhase {
|
||||||
|
case .initialTouch:
|
||||||
|
break
|
||||||
|
// curveView.curve.polylinePoints = initialTouchCurvePoints
|
||||||
|
case .stroke:
|
||||||
|
curveView.curve.polylinePoints = strokePressureCurvePoints
|
||||||
|
}
|
||||||
curveView.setNeedsDisplay()
|
curveView.setNeedsDisplay()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func setupBottomSliders() {
|
||||||
|
|
||||||
|
hookFilterLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
hookFilterSlider.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
strokeEqualizationDepthLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
strokeEqualizationDepthSlider.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
strokeEqualizationStrengthLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
strokeEqualizationStrengthSlider.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
|
||||||
|
let traits = UITraitCollection(userInterfaceStyle: .light)
|
||||||
|
|
||||||
|
hookFilterLabel.font = UIFont.systemFont(ofSize: 14)
|
||||||
|
hookFilterLabel.textColor = .black
|
||||||
|
if GenericUtils.liquidGlassEnabled {
|
||||||
|
if #available(iOS 13.0, *) {hookFilterSlider.maximumTrackTintColor = .tertiarySystemFill.resolvedColor(with: traits)}
|
||||||
|
}
|
||||||
|
hookFilterSlider.minimumValue = 1
|
||||||
|
hookFilterSlider.maximumValue = 20
|
||||||
|
hookFilterSlider.addTarget(self, action: #selector(hookFilterDepthSliderMoved(_:)), for: .valueChanged)
|
||||||
|
|
||||||
|
strokeEqualizationDepthLabel.font = UIFont.systemFont(ofSize: 14)
|
||||||
|
strokeEqualizationDepthLabel.textColor = .black
|
||||||
|
if GenericUtils.liquidGlassEnabled {
|
||||||
|
if #available(iOS 13.0, *) {strokeEqualizationDepthSlider.maximumTrackTintColor = .tertiarySystemFill.resolvedColor(with: traits)}
|
||||||
|
}
|
||||||
|
strokeEqualizationDepthSlider.minimumValue = 1
|
||||||
|
strokeEqualizationDepthSlider.maximumValue = 80
|
||||||
|
strokeEqualizationDepthSlider.addTarget(self, action: #selector(strokeEqualizationDepthSliderMoved(_:)), for: .valueChanged)
|
||||||
|
|
||||||
|
strokeEqualizationStrengthLabel.font = UIFont.systemFont(ofSize: 14)
|
||||||
|
strokeEqualizationStrengthLabel.textColor = .black
|
||||||
|
if GenericUtils.liquidGlassEnabled {
|
||||||
|
if #available(iOS 13.0, *) {strokeEqualizationStrengthSlider.maximumTrackTintColor = .tertiarySystemFill.resolvedColor(with: traits)}
|
||||||
|
}
|
||||||
|
strokeEqualizationStrengthSlider.minimumValue = 0.1
|
||||||
|
strokeEqualizationStrengthSlider.maximumValue = 3.5
|
||||||
|
strokeEqualizationStrengthSlider.addTarget(self, action: #selector(strokeEqualizationStrengthSliderMoved(_:)), for: .valueChanged)
|
||||||
|
|
||||||
|
container.addSubview(hookFilterLabel)
|
||||||
|
container.addSubview(hookFilterSlider)
|
||||||
|
container.addSubview(strokeEqualizationDepthLabel)
|
||||||
|
container.addSubview(strokeEqualizationDepthSlider)
|
||||||
|
container.addSubview(strokeEqualizationStrengthLabel)
|
||||||
|
container.addSubview(strokeEqualizationStrengthSlider)
|
||||||
|
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
|
||||||
|
// Slider
|
||||||
|
hookFilterLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
|
||||||
|
hookFilterLabel.widthAnchor.constraint(equalToConstant: 260),
|
||||||
|
hookFilterSlider.leadingAnchor.constraint(equalTo: hookFilterLabel.trailingAnchor, constant: 12),
|
||||||
|
hookFilterSlider.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -16),
|
||||||
|
hookFilterSlider.topAnchor.constraint(equalTo: curveView.bottomAnchor, constant: 0),
|
||||||
|
hookFilterLabel.centerYAnchor.constraint(equalTo: hookFilterSlider.centerYAnchor, constant:0),
|
||||||
|
|
||||||
|
strokeEqualizationDepthLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
|
||||||
|
strokeEqualizationDepthLabel.widthAnchor.constraint(equalToConstant: 260),
|
||||||
|
strokeEqualizationDepthSlider.leadingAnchor.constraint(equalTo: strokeEqualizationDepthLabel.trailingAnchor, constant: 12),
|
||||||
|
strokeEqualizationDepthSlider.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -16),
|
||||||
|
strokeEqualizationDepthSlider.topAnchor.constraint(equalTo: hookFilterSlider.bottomAnchor, constant: 0),
|
||||||
|
strokeEqualizationDepthLabel.centerYAnchor.constraint(equalTo: strokeEqualizationDepthSlider.centerYAnchor, constant:0),
|
||||||
|
|
||||||
|
strokeEqualizationStrengthLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
|
||||||
|
strokeEqualizationStrengthLabel.widthAnchor.constraint(equalToConstant: 260),
|
||||||
|
strokeEqualizationStrengthSlider.leadingAnchor.constraint(equalTo: strokeEqualizationStrengthLabel.trailingAnchor, constant: 12),
|
||||||
|
strokeEqualizationStrengthSlider.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -16),
|
||||||
|
strokeEqualizationStrengthSlider.topAnchor.constraint(equalTo: strokeEqualizationDepthSlider.bottomAnchor, constant: 0),
|
||||||
|
strokeEqualizationStrengthLabel.centerYAnchor.constraint(equalTo: strokeEqualizationStrengthSlider.centerYAnchor, constant:0),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func hookFilterDepthSliderMoved(_ sender: UISlider) {
|
||||||
|
phase1StrokeSampleIndexEnd = Int32(sender.value.rounded())
|
||||||
|
hookFilterLabel.text = "\(SwiftLocalizationHelper.localizedString(forKey: "Stroke start hook filtering depth: "))\(String(format: "%d", Int32(sender.value)))";
|
||||||
|
if sender.value > strokeEqualizationDepthSlider.value {
|
||||||
|
strokeEqualizationDepthSlider.value = sender.value
|
||||||
|
strokeEqualizationDepthSliderMoved(strokeEqualizationDepthSlider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func strokeEqualizationDepthSliderMoved(_ sender: UISlider) {
|
||||||
|
sender.value = max(sender.value, hookFilterSlider.value)
|
||||||
|
phase2StrokeSampleIndexEnd = Int32(sender.value.rounded())
|
||||||
|
strokeEqualizationDepthLabel.text = "\(SwiftLocalizationHelper.localizedString(forKey: "Stroke start equalization depth: "))\(String(format: "%d", Int32(sender.value)))";
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func strokeEqualizationStrengthSliderMoved(_ sender: UISlider) {
|
||||||
|
// sender.value = sender.value
|
||||||
|
strokeEqualizationStrengthLabel.text = "\(SwiftLocalizationHelper.localizedString(forKey: "Stroke start force scaling: "))\(String(format: "%.2f", sender.value))";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public func setupNavigationBar() {
|
public func setupNavigationBar() {
|
||||||
// 1. 创建 UINavigationBar
|
// 1. 创建 UINavigationBar
|
||||||
navBar.removeFromSuperview()
|
navBar.removeFromSuperview()
|
||||||
@@ -589,9 +737,9 @@ class PressureCurveViewController: UIViewController {
|
|||||||
|
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
let appearance = UINavigationBarAppearance()
|
let appearance = UINavigationBarAppearance()
|
||||||
appearance.configureWithTransparentBackground() // 透明背景
|
// appearance.configureWithTransparentBackground() // 透明背景
|
||||||
appearance.shadowColor = nil // 去掉底部细线
|
appearance.shadowColor = nil // 去掉底部细线
|
||||||
appearance.backgroundColor = .clear // 可以额外设置完全透明
|
appearance.backgroundColor = .white // 可以额外设置完全透明
|
||||||
|
|
||||||
navBar.standardAppearance = appearance
|
navBar.standardAppearance = appearance
|
||||||
navBar.scrollEdgeAppearance = appearance
|
navBar.scrollEdgeAppearance = appearance
|
||||||
@@ -602,30 +750,45 @@ class PressureCurveViewController: UIViewController {
|
|||||||
navBar.backgroundColor = .clear
|
navBar.backgroundColor = .clear
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 2. 添加约束 (顶部,左右)
|
// 2. 添加约束 (顶部,左右)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
navBar.topAnchor.constraint(equalTo: container.safeAreaLayoutGuide.topAnchor),
|
navBar.topAnchor.constraint(equalTo: container.safeAreaLayoutGuide.topAnchor),
|
||||||
navBar.leadingAnchor.constraint(equalTo: container.leadingAnchor),
|
navBar.leadingAnchor.constraint(equalTo: container.leadingAnchor),
|
||||||
navBar.trailingAnchor.constraint(equalTo: container.trailingAnchor),
|
navBar.trailingAnchor.constraint(equalTo: container.trailingAnchor),
|
||||||
navBar.heightAnchor.constraint(equalToConstant: 42) // 导航栏标准高度
|
navBar.heightAnchor.constraint(equalToConstant: 50) // 导航栏标准高度
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
if curveView.testStage == .curveStage {
|
if curveView.testStage == .curveStage {
|
||||||
let resetButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Reset"), style: .plain, target: self, action: #selector(resetTapped))
|
let resetButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Reset"), style: .plain, target: self, action: #selector(resetTapped))
|
||||||
let rangeTestButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Pressure-range-test"), style: .plain, target: self, action: #selector(pressureRangeTest))
|
let rangeTestButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Pressure-range-test"), style: .plain, target: self, action: #selector(pressureRangeTest))
|
||||||
let saveButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Save"), style: .plain, target: self, action: #selector(saveTapped))
|
// curvePhaseButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Initial-touch-curve"), style: .plain, target: self, action: #selector(curvePhaseButtonTapped))
|
||||||
let quitButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Exit"), style: .plain, target: self, action: #selector(exitTapped))
|
curvePhase = .stroke
|
||||||
|
saveButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Save"), style: .plain, target: self, action: #selector(saveTapped))
|
||||||
|
// let quitButton = UIBarButtonItem(title: SwiftLocalizationHelper.localizedString(forKey: "Exit"), style: .plain, target: self, action: #selector(exitTapped))
|
||||||
navItem.leftBarButtonItems = [resetButton, rangeTestButton]
|
navItem.leftBarButtonItems = [resetButton, rangeTestButton]
|
||||||
navItem.rightBarButtonItems = [quitButton, saveButton]
|
navItem.rightBarButtonItems = [saveButton]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if curveView.testStage == .drawingStage {
|
if curveView.testStage == .drawingStage {
|
||||||
navItem = UINavigationItem(title: SwiftLocalizationHelper.localizedString(forKey: "Pressure Range Test"))
|
navItem = UINavigationItem(title: SwiftLocalizationHelper.localizedString(forKey: "Pressure Range Test"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if #available(iOS 26.0, *) {
|
||||||
|
if let buttons = navItem.leftBarButtonItems {
|
||||||
|
for button in buttons {
|
||||||
|
button.hidesSharedBackground = true
|
||||||
|
button.tintColor = .tintColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let buttons = navItem.rightBarButtonItems {
|
||||||
|
for button in buttons {
|
||||||
|
button.hidesSharedBackground = true
|
||||||
|
button.tintColor = .tintColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. 将 UINavigationItem 添加到导航栏
|
|
||||||
navBar.items = [navItem]
|
navBar.items = [navItem]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,10 +844,43 @@ class PressureCurveViewController: UIViewController {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@objc private func curvePhaseButtonTapped() {
|
||||||
|
switch curvePhase {
|
||||||
|
case .initialTouch:
|
||||||
|
// initialTouchCurvePoints = curveView.curve.polylinePoints
|
||||||
|
curvePhaseButton.title = SwiftLocalizationHelper.localizedString(forKey:"Initial-touch-curve")
|
||||||
|
case .stroke:
|
||||||
|
strokeCurvePoints = curveView.curve.polylinePoints
|
||||||
|
curvePhaseButton.title = SwiftLocalizationHelper.localizedString(forKey:"Stroke-curve")
|
||||||
|
}
|
||||||
|
curvePhase = curvePhase.next()
|
||||||
|
displayCurve()
|
||||||
|
} */
|
||||||
|
|
||||||
@objc private func persistCurve() {
|
@objc private func persistCurve() {
|
||||||
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
let oscProfileMan = OSCProfilesManager.sharedManager(CGRectZero)
|
||||||
let selectedProfile = oscProfileMan.getSelectedProfile()
|
let selectedProfile = oscProfileMan.getSelectedProfile()
|
||||||
|
|
||||||
|
switch curvePhase {
|
||||||
|
case .initialTouch:
|
||||||
|
break
|
||||||
|
// initialTouchCurvePoints = curveView.curve.polylinePoints
|
||||||
|
case .stroke:
|
||||||
|
strokePressureCurvePoints = curveView.curve.polylinePoints
|
||||||
|
}
|
||||||
|
|
||||||
|
curveView.curve.polylinePoints = strokePressureCurvePoints
|
||||||
selectedProfile.pressureCurvePoints = PressureCurve.exportCurvePoints(curveView.curve)
|
selectedProfile.pressureCurvePoints = PressureCurve.exportCurvePoints(curveView.curve)
|
||||||
|
// curveView.curve.polylinePoints = initialTouchCurvePoints
|
||||||
|
// selectedProfile.initialTouchPressureCurvePoints = PressureCurve.exportCurvePoints(curveView.curve)
|
||||||
|
|
||||||
|
displayCurve()
|
||||||
|
|
||||||
|
selectedProfile.phase1StrokeSampleIndexEnd = Int32(hookFilterSlider.value)
|
||||||
|
selectedProfile.phase2StrokeSampleIndexEnd = Int32(strokeEqualizationDepthSlider.value)
|
||||||
|
selectedProfile.strokeEqualizationStrength = CGFloat(strokeEqualizationStrengthSlider.value)
|
||||||
|
|
||||||
oscProfileMan.replaceSelectedProfile(with: selectedProfile, overwriteDefault: true)
|
oscProfileMan.replaceSelectedProfile(with: selectedProfile, overwriteDefault: true)
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
@@ -718,7 +914,9 @@ class PressureCurveViewController: UIViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc private func saveTapped() {
|
@objc private func saveTapped() {
|
||||||
|
saveButton.isEnabled = false
|
||||||
IAPManager.checkPurchaseInfo(.PencilProPack) { info in
|
IAPManager.checkPurchaseInfo(.PencilProPack) { info in
|
||||||
|
self.saveButton.isEnabled = true
|
||||||
if info.valid {
|
if info.valid {
|
||||||
self.persistCurve()
|
self.persistCurve()
|
||||||
}
|
}
|
||||||
@@ -731,4 +929,15 @@ class PressureCurveViewController: UIViewController {
|
|||||||
@objc private func exitTapped() {
|
@objc private func exitTapped() {
|
||||||
self.dismiss(animated: true)
|
self.dismiss(animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func gestureRecognizer(
|
||||||
|
_ gestureRecognizer: UIGestureRecognizer,
|
||||||
|
shouldReceive touch: UITouch
|
||||||
|
) -> Bool {
|
||||||
|
return touch.view == view
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func dismissSelf(){
|
||||||
|
dismiss(animated: true, completion: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8088,6 +8088,75 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Stroke start equalization depth: " : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔迹起始端均衡深度: "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆跡起始端均衡深度: "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆跡起始端均衡深度: "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Stroke start force scaling: " : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔迹起始端力度系数: "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆跡起始端力度係數: "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆跡起始端力度係數: "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Stroke start hook filtering depth: " : {
|
||||||
|
"extractionState" : "manual",
|
||||||
|
"localizations" : {
|
||||||
|
"zh-Hans" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "笔迹起始端勾子过滤深度: "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-Hant" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆跡起始端勾子過濾深度: "
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"zh-HK" : {
|
||||||
|
"stringUnit" : {
|
||||||
|
"state" : "translated",
|
||||||
|
"value" : "筆跡起始端勾子過濾深度: "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Successfully sent wake-up request. It may take a few moments for the PC to wake. If it never wakes up, ensure it's properly configured for Wake-on-LAN." : {
|
"Successfully sent wake-up request. It may take a few moments for the PC to wake. If it never wakes up, ensure it's properly configured for Wake-on-LAN." : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
|
|||||||
Reference in new issue
Block a user