mirror of
https://github.com/dscyrescotti/Memola.git
synced 2026-07-04 12:01:54 +02:00
refactor: save quads right after they are added
This commit is contained in:
@@ -154,11 +154,12 @@ extension GraphicContext {
|
|||||||
func endStroke(at point: CGPoint) {
|
func endStroke(at point: CGPoint) {
|
||||||
guard currentPoint != nil, let currentStroke else { return }
|
guard currentPoint != nil, let currentStroke else { return }
|
||||||
currentStroke.finish(at: point)
|
currentStroke.finish(at: point)
|
||||||
currentStroke.saveQuads(to: currentStroke.quads.endIndex)
|
withPersistence(\.backgroundContext) { [currentStroke] context in
|
||||||
withPersistence(\.backgroundContext) { context in
|
guard let stroke = currentStroke.stroke(as: PenStroke.self) else { return }
|
||||||
|
stroke.object?.bounds = stroke.bounds
|
||||||
try context.saveIfNeeded()
|
try context.saveIfNeeded()
|
||||||
if let stroke = currentStroke.stroke(as: PenStroke.self)?.object {
|
if let object = stroke.object {
|
||||||
context.refresh(stroke, mergeChanges: false)
|
context.refresh(object, mergeChanges: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previousStroke = currentStroke
|
previousStroke = currentStroke
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ protocol Stroke: AnyObject, Drawable, Hashable, Equatable {
|
|||||||
var quads: [Quad] { get set }
|
var quads: [Quad] { get set }
|
||||||
var penStyle: any PenStyle { get set }
|
var penStyle: any PenStyle { get set }
|
||||||
|
|
||||||
var batchIndex: Int { get set }
|
|
||||||
var quadIndex: Int { get set }
|
|
||||||
var keyPoints: [CGPoint] { get set }
|
var keyPoints: [CGPoint] { get set }
|
||||||
var movingAverage: MovingAverage { get set }
|
var movingAverage: MovingAverage { get set }
|
||||||
|
|
||||||
@@ -32,8 +30,6 @@ protocol Stroke: AnyObject, Drawable, Hashable, Equatable {
|
|||||||
func finish(at point: CGPoint)
|
func finish(at point: CGPoint)
|
||||||
|
|
||||||
func addQuad(at point: CGPoint, rotation: CGFloat, shape: QuadShape)
|
func addQuad(at point: CGPoint, rotation: CGFloat, shape: QuadShape)
|
||||||
func removeQuads(from index: Int)
|
|
||||||
func saveQuads(to index: Int)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Stroke {
|
extension Stroke {
|
||||||
@@ -78,11 +74,6 @@ extension Stroke {
|
|||||||
)
|
)
|
||||||
quads.append(quad)
|
quads.append(quad)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeQuads(from index: Int) {
|
|
||||||
let dropCount = quads.endIndex - max(1, index)
|
|
||||||
quads.removeLast(dropCount)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Stroke {
|
extension Stroke {
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
|
|||||||
let control = CGPoint.middle(p1: start, p2: end)
|
let control = CGPoint.middle(p1: start, p2: end)
|
||||||
addCurve(from: start, to: end, by: control, on: stroke)
|
addCurve(from: start, to: end, by: control, on: stroke)
|
||||||
case 3:
|
case 3:
|
||||||
let quadIndex = stroke.quadIndex + 1
|
|
||||||
stroke.removeQuads(from: quadIndex)
|
|
||||||
stroke.saveQuads(to: quadIndex)
|
|
||||||
let index = stroke.keyPoints.endIndex - 1
|
let index = stroke.keyPoints.endIndex - 1
|
||||||
var start = stroke.keyPoints[index - 2]
|
var start = stroke.keyPoints[index - 2]
|
||||||
var end = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
var end = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
||||||
@@ -42,7 +39,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
|
|||||||
end = CGPoint.middle(p1: stroke.keyPoints[index - 1], p2: stroke.keyPoints[index])
|
end = CGPoint.middle(p1: stroke.keyPoints[index - 1], p2: stroke.keyPoints[index])
|
||||||
addCurve(from: start, to: end, by: control, on: stroke)
|
addCurve(from: start, to: end, by: control, on: stroke)
|
||||||
default:
|
default:
|
||||||
smoothOutPath(on: stroke)
|
adjustKeyPoint(on: stroke)
|
||||||
let index = stroke.keyPoints.endIndex - 1
|
let index = stroke.keyPoints.endIndex - 1
|
||||||
let start = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
let start = CGPoint.middle(p1: stroke.keyPoints[index - 2], p2: stroke.keyPoints[index - 1])
|
||||||
let control = stroke.keyPoints[index - 1]
|
let control = stroke.keyPoints[index - 1]
|
||||||
@@ -60,29 +57,6 @@ struct SolidPointStrokeGenerator: StrokeGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func smoothOutPath(on stroke: any Stroke) {
|
|
||||||
let quadIndex = stroke.quadIndex + 1
|
|
||||||
stroke.removeQuads(from: quadIndex)
|
|
||||||
stroke.saveQuads(to: quadIndex)
|
|
||||||
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: any Stroke) {
|
private func adjustKeyPoint(on stroke: any Stroke) {
|
||||||
let index = stroke.keyPoints.endIndex - 1
|
let index = stroke.keyPoints.endIndex - 1
|
||||||
let prev = stroke.keyPoints[index - 1]
|
let prev = stroke.keyPoints[index - 1]
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ final class EraserStroke: Stroke, @unchecked Sendable {
|
|||||||
var quads: [Quad]
|
var quads: [Quad]
|
||||||
var penStyle: any PenStyle
|
var penStyle: any PenStyle
|
||||||
|
|
||||||
var batchIndex: Int = 0
|
|
||||||
var quadIndex: Int = -1
|
|
||||||
var keyPoints: [CGPoint] = []
|
var keyPoints: [CGPoint] = []
|
||||||
var movingAverage: MovingAverage = MovingAverage(windowSize: 3)
|
var movingAverage: MovingAverage = MovingAverage(windowSize: 3)
|
||||||
|
|
||||||
@@ -43,8 +41,4 @@ final class EraserStroke: Stroke, @unchecked Sendable {
|
|||||||
self.quads = quads
|
self.quads = quads
|
||||||
self.penStyle = style.penStyle
|
self.penStyle = style.penStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveQuads(to index: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ final class PenStroke: Stroke, @unchecked Sendable {
|
|||||||
var quads: [Quad]
|
var quads: [Quad]
|
||||||
var penStyle: any PenStyle
|
var penStyle: any PenStyle
|
||||||
|
|
||||||
var batchIndex: Int = 0
|
|
||||||
var quadIndex: Int = -1
|
|
||||||
var keyPoints: [CGPoint] = []
|
var keyPoints: [CGPoint] = []
|
||||||
var movingAverage: MovingAverage = MovingAverage(windowSize: 3)
|
var movingAverage: MovingAverage = MovingAverage(windowSize: 3)
|
||||||
|
|
||||||
@@ -71,30 +69,31 @@ final class PenStroke: Stroke, @unchecked Sendable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveQuads(to index: Int) {
|
func addQuad(at point: CGPoint, rotation: CGFloat, shape: QuadShape) {
|
||||||
let quads = Array(quads[batchIndex..<index])
|
let quad = Quad(
|
||||||
batchIndex = index
|
origin: point,
|
||||||
withPersistence(\.backgroundContext) { [weak self, object] context in
|
size: thickness,
|
||||||
guard let self else { return }
|
rotation: rotation,
|
||||||
var topLeft: CGPoint = CGPoint(x: bounds[0], y: bounds[1])
|
shape: shape.rawValue,
|
||||||
var bottomRight: CGPoint = CGPoint(x: bounds[2], y: bounds[3])
|
color: color
|
||||||
for _quad in quads {
|
)
|
||||||
let quad = QuadObject(\.backgroundContext)
|
quads.append(quad)
|
||||||
quad.originX = _quad.originX.cgFloat
|
bounds = [
|
||||||
quad.originY = _quad.originY.cgFloat
|
min(quad.originX.cgFloat, bounds[0]),
|
||||||
quad.size = _quad.size.cgFloat
|
min(quad.originY.cgFloat, bounds[1]),
|
||||||
quad.rotation = _quad.rotation.cgFloat
|
max(quad.originX.cgFloat, bounds[2]),
|
||||||
quad.shape = _quad.shape
|
max(quad.originY.cgFloat, bounds[3])
|
||||||
quad.color = _quad.getColor()
|
]
|
||||||
quad.stroke = object
|
withPersistence(\.backgroundContext) { [object, _quad = quad] context in
|
||||||
object?.quads.add(quad)
|
let quad = QuadObject(\.backgroundContext)
|
||||||
topLeft.x = min(quad.originX, topLeft.x)
|
quad.originX = _quad.originX.cgFloat
|
||||||
topLeft.y = min(quad.originY, topLeft.y)
|
quad.originY = _quad.originY.cgFloat
|
||||||
bottomRight.x = max(quad.originX, bottomRight.x)
|
quad.size = _quad.size.cgFloat
|
||||||
bottomRight.y = max(quad.originY, bottomRight.y)
|
quad.rotation = _quad.rotation.cgFloat
|
||||||
}
|
quad.shape = _quad.shape
|
||||||
bounds = [topLeft.x, topLeft.y, bottomRight.x, bottomRight.y]
|
quad.color = _quad.getColor()
|
||||||
object?.bounds = bounds
|
quad.stroke = object
|
||||||
|
object?.quads.add(quad)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user