mirror of
https://github.com/dscyrescotti/Memola.git
synced 2026-03-17 23:13:56 +01:00
bug: fix stroke glitching
This commit is contained in:
@@ -13,6 +13,11 @@ struct MemolaApp: App {
|
||||
WindowGroup {
|
||||
MemosView()
|
||||
.persistence(\.viewContext)
|
||||
.onReceive(NotificationCenter.default.publisher(for: UIApplication.willTerminateNotification)) { _ in
|
||||
withPersistenceSync(\.backgroundContext) { context in
|
||||
try context.saveIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,8 +153,10 @@ extension GraphicContext {
|
||||
func endStroke(at point: CGPoint) {
|
||||
guard currentPoint != nil, let currentStroke else { return }
|
||||
currentStroke.finish(at: point)
|
||||
withPersistence(\.backgroundContext) { [currentStroke] context in
|
||||
currentStroke.object?.bounds = currentStroke.bounds
|
||||
let batchIndex = currentStroke.batchIndex
|
||||
let quads = Array(currentStroke.quads[batchIndex..<currentStroke.quads.count])
|
||||
currentStroke.saveQuads(for: quads)
|
||||
withPersistence(\.backgroundContext) { context in
|
||||
try context.saveIfNeeded()
|
||||
if let stroke = currentStroke.object {
|
||||
context.refresh(stroke, mergeChanges: false)
|
||||
|
||||
@@ -29,6 +29,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
|
||||
let control = CGPoint.middle(p1: start, p2: end)
|
||||
addCurve(from: start, to: end, by: control, on: stroke)
|
||||
case 3:
|
||||
stroke.removeQuads(from: stroke.quadIndex + 1)
|
||||
let index = stroke.keyPoints.endIndex - 1
|
||||
var start = stroke.keyPoints[index - 2]
|
||||
var end = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
||||
@@ -39,7 +40,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
|
||||
end = CGPoint.middle(p1: stroke.keyPoints[index - 1], p2: stroke.keyPoints[index])
|
||||
addCurve(from: start, to: end, by: control, on: stroke)
|
||||
default:
|
||||
adjustKeyPoint(on: stroke)
|
||||
smoothOutPath(on: stroke)
|
||||
let index = stroke.keyPoints.endIndex - 1
|
||||
let start = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
||||
let control = stroke.keyPoints[index - 1]
|
||||
@@ -57,6 +58,27 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private func smoothOutPath(on stroke: Stroke) {
|
||||
stroke.removeQuads(from: stroke.quadIndex + 1)
|
||||
adjustKeyPoint(on: stroke)
|
||||
switch stroke.keyPoints.endIndex {
|
||||
case 4:
|
||||
let index = stroke.keyPoints.endIndex - 2
|
||||
let start = stroke.keyPoints[index - 2]
|
||||
let end = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
||||
let control = CGPoint.middle(p1: start, p2: end)
|
||||
addCurve(from: start, to: end, by: control, on: stroke)
|
||||
fallthrough
|
||||
default:
|
||||
let index = stroke.keyPoints.endIndex - 2
|
||||
let start = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
||||
let control = stroke.keyPoints[index - 1]
|
||||
let end = CGPoint.middle(p1: stroke.keyPoints[index - 1], p2: stroke.keyPoints[index])
|
||||
addCurve(from: start, to: end, by: control, on: stroke)
|
||||
}
|
||||
stroke.quadIndex = stroke.quads.endIndex - 1
|
||||
}
|
||||
|
||||
private func adjustKeyPoint(on stroke: Stroke) {
|
||||
let index = stroke.keyPoints.endIndex - 1
|
||||
let prev = stroke.keyPoints[index - 1]
|
||||
|
||||
@@ -116,20 +116,38 @@ extension Stroke {
|
||||
color: color
|
||||
)
|
||||
quads.append(quad)
|
||||
withPersistence(\.backgroundContext) { [weak self, _quad = quad, object, bounds] context in
|
||||
let quad = QuadObject(\.backgroundContext)
|
||||
quad.originX = _quad.originX.cgFloat
|
||||
quad.originY = _quad.originY.cgFloat
|
||||
quad.size = _quad.size.cgFloat
|
||||
quad.rotation = _quad.rotation.cgFloat
|
||||
quad.shape = _quad.shape
|
||||
quad.color = _quad.getColor()
|
||||
quad.stroke = object
|
||||
object?.quads.add(quad)
|
||||
self?.bounds[0] = min(_quad.originX.cgFloat, bounds[0])
|
||||
self?.bounds[1] = min(_quad.originY.cgFloat, bounds[1])
|
||||
self?.bounds[2] = max(_quad.originX.cgFloat, bounds[2])
|
||||
self?.bounds[3] = max(_quad.originY.cgFloat, bounds[3])
|
||||
}
|
||||
|
||||
func removeQuads(from index: Int) {
|
||||
let dropCount = quads.endIndex - max(1, index)
|
||||
quads.removeLast(dropCount)
|
||||
let quads = Array(quads[batchIndex..<index])
|
||||
batchIndex = index
|
||||
saveQuads(for: quads)
|
||||
}
|
||||
|
||||
func saveQuads(for quads: [Quad]) {
|
||||
var topLeft: CGPoint = CGPoint(x: bounds[0], y: bounds[1])
|
||||
var bottomRight: CGPoint = CGPoint(x: bounds[2], y: bounds[3])
|
||||
withPersistence(\.backgroundContext) { [weak self, object] context in
|
||||
guard let self else { return }
|
||||
for _quad in quads {
|
||||
let quad = QuadObject(\.backgroundContext)
|
||||
quad.originX = _quad.originX.cgFloat
|
||||
quad.originY = _quad.originY.cgFloat
|
||||
quad.size = _quad.size.cgFloat
|
||||
quad.rotation = _quad.rotation.cgFloat
|
||||
quad.shape = _quad.shape
|
||||
quad.color = _quad.getColor()
|
||||
quad.stroke = object
|
||||
object?.quads.add(quad)
|
||||
topLeft.x = min(quad.originX, topLeft.x)
|
||||
topLeft.y = min(quad.originY, topLeft.y)
|
||||
bottomRight.x = max(quad.originX, bottomRight.x)
|
||||
bottomRight.y = max(quad.originY, bottomRight.y)
|
||||
}
|
||||
bounds = [topLeft.x, topLeft.y, bottomRight.x, bottomRight.y]
|
||||
object?.bounds = bounds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,9 +128,17 @@ struct Toolbar: View {
|
||||
}
|
||||
|
||||
func closeMemo() {
|
||||
withPersistenceSync(\.viewContext) { context in
|
||||
try context.saveIfNeeded()
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
DispatchQueue.main.async {
|
||||
canvas.state = .closing
|
||||
}
|
||||
withPersistenceSync(\.viewContext) { context in
|
||||
try context.saveIfNeeded()
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
canvas.state = .closed
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user