From 43d933a1dc62805ae908bd054431544eafaa780c Mon Sep 17 00:00:00 2001 From: dscyrescotti Date: Fri, 24 May 2024 17:54:46 +0700 Subject: [PATCH] refactor: clean up --- Memola.xcodeproj/project.pbxproj | 26 +++++++++++++++---- Memola/Canvas/Contexts/GraphicContext.swift | 16 ++++++------ Memola/Canvas/Core/Canvas.swift | 4 +-- .../Stroke/{ => Core}/StrokeGenerator.swift | 6 ++--- .../SolidPointStrokeGenerator.swift | 14 +++++----- .../{Stroke.swift => Strokes/PenStroke.swift} | 26 +++++++------------ Memola/Canvas/History/HistoryEvent.swift | 2 +- .../Canvas/RenderPasses/CacheRenderPass.swift | 5 ++-- .../RenderPasses/EraserRenderPass.swift | 4 +-- .../RenderPasses/GraphicRenderPass.swift | 10 ++++--- .../RenderPasses/StrokeRenderPass.swift | 4 +-- Memola/Canvas/Tool/Pen/Core/Pen.swift | 4 +-- Memola/Canvas/Tool/Pen/Core/PenStyle.swift | 2 +- 13 files changed, 67 insertions(+), 56 deletions(-) rename Memola/Canvas/Geometries/Stroke/{ => Core}/StrokeGenerator.swift (56%) rename Memola/Canvas/Geometries/Stroke/{Stroke.swift => Strokes/PenStroke.swift} (92%) diff --git a/Memola.xcodeproj/project.pbxproj b/Memola.xcodeproj/project.pbxproj index 5a98a51..5420651 100644 --- a/Memola.xcodeproj/project.pbxproj +++ b/Memola.xcodeproj/project.pbxproj @@ -57,7 +57,7 @@ ECA738C92BE60EF700A4542E /* GraphicContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738C82BE60EF700A4542E /* GraphicContext.swift */; }; ECA738CB2BE60F1900A4542E /* ViewPortContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738CA2BE60F1900A4542E /* ViewPortContext.swift */; }; ECA738CD2BE60F2F00A4542E /* GridContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738CC2BE60F2F00A4542E /* GridContext.swift */; }; - ECA738D22BE60F7B00A4542E /* Stroke.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738D12BE60F7B00A4542E /* Stroke.swift */; }; + ECA738D22BE60F7B00A4542E /* PenStroke.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738D12BE60F7B00A4542E /* PenStroke.swift */; }; ECA738D42BE60F9100A4542E /* StrokeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738D32BE60F9100A4542E /* StrokeGenerator.swift */; }; ECA738D72BE60FC100A4542E /* SolidPointStrokeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738D62BE60FC100A4542E /* SolidPointStrokeGenerator.swift */; }; ECA738DA2BE60FF100A4542E /* CacheRenderPass.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECA738D92BE60FF100A4542E /* CacheRenderPass.swift */; }; @@ -139,7 +139,7 @@ ECA738C82BE60EF700A4542E /* GraphicContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphicContext.swift; sourceTree = ""; }; ECA738CA2BE60F1900A4542E /* ViewPortContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewPortContext.swift; sourceTree = ""; }; ECA738CC2BE60F2F00A4542E /* GridContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridContext.swift; sourceTree = ""; }; - ECA738D12BE60F7B00A4542E /* Stroke.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stroke.swift; sourceTree = ""; }; + ECA738D12BE60F7B00A4542E /* PenStroke.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenStroke.swift; sourceTree = ""; }; ECA738D32BE60F9100A4542E /* StrokeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StrokeGenerator.swift; sourceTree = ""; }; ECA738D62BE60FC100A4542E /* SolidPointStrokeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolidPointStrokeGenerator.swift; sourceTree = ""; }; ECA738D92BE60FF100A4542E /* CacheRenderPass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheRenderPass.swift; sourceTree = ""; }; @@ -539,10 +539,10 @@ ECA738CE2BE60F5000A4542E /* Stroke */ = { isa = PBXGroup; children = ( + ECE883B92C009DCA0045C53D /* Core */, + ECE883B82C009DC30045C53D /* Strokes */, EC5E838E2BFDB69000261D9C /* Algorithms */, ECA738D52BE60FA200A4542E /* Generators */, - ECA738D12BE60F7B00A4542E /* Stroke.swift */, - ECA738D32BE60F9100A4542E /* StrokeGenerator.swift */, ); path = Stroke; sourceTree = ""; @@ -618,6 +618,22 @@ path = Core; sourceTree = ""; }; + ECE883B82C009DC30045C53D /* Strokes */ = { + isa = PBXGroup; + children = ( + ECA738D12BE60F7B00A4542E /* PenStroke.swift */, + ); + path = Strokes; + sourceTree = ""; + }; + ECE883B92C009DCA0045C53D /* Core */ = { + isa = PBXGroup; + children = ( + ECA738D32BE60F9100A4542E /* StrokeGenerator.swift */, + ); + path = Core; + sourceTree = ""; + }; ECFA151E2BEF21BE00455818 /* Objects */ = { isa = PBXGroup; children = ( @@ -777,7 +793,7 @@ ECFA15282BEF225000455818 /* QuadObject.swift in Sources */, ECA738932BE6011100A4542E /* Stroke.metal in Sources */, ECA738B62BE60DCD00A4542E /* History.swift in Sources */, - ECA738D22BE60F7B00A4542E /* Stroke.swift in Sources */, + ECA738D22BE60F7B00A4542E /* PenStroke.swift in Sources */, ECA738F22BE6128F00A4542E /* Collection++.swift in Sources */, EC5050072BF65CED00B4D86E /* PenDropDelegate.swift in Sources */, ECA738A32BE6020A00A4542E /* CGFloat++.swift in Sources */, diff --git a/Memola/Canvas/Contexts/GraphicContext.swift b/Memola/Canvas/Contexts/GraphicContext.swift index 576d44c..b048432 100644 --- a/Memola/Canvas/Contexts/GraphicContext.swift +++ b/Memola/Canvas/Contexts/GraphicContext.swift @@ -11,11 +11,11 @@ import CoreData import Foundation final class GraphicContext: @unchecked Sendable { - var strokes: [Stroke] = [] + var strokes: [PenStroke] = [] var object: GraphicContextObject? - var currentStroke: Stroke? - var previousStroke: Stroke? + var currentStroke: PenStroke? + var previousStroke: PenStroke? var currentPoint: CGPoint? var renderType: RenderType = .finished var vertices: [ViewPortVertex] = [] @@ -64,9 +64,9 @@ extension GraphicContext { guard let object else { return } let queue = OperationQueue() queue.qualityOfService = .userInteractive - self.strokes = object.strokes.compactMap { stroke -> Stroke? in + self.strokes = object.strokes.compactMap { stroke -> PenStroke? in guard let stroke = stroke as? StrokeObject else { return nil } - let _stroke = Stroke(object: stroke) + let _stroke = PenStroke(object: stroke) if _stroke.isVisible(in: bounds) { let id = stroke.objectID queue.addOperation { @@ -91,7 +91,7 @@ extension GraphicContext { func loadQuads(_ bounds: CGRect) { for stroke in self.strokes { - guard stroke.isVisible(in: bounds), stroke.quads.isEmpty else { continue } + guard stroke.isVisible(in: bounds), stroke.isEmpty else { continue } stroke.loadQuads() } } @@ -114,8 +114,8 @@ extension GraphicContext: Drawable { } extension GraphicContext { - func beginStroke(at point: CGPoint, pen: Pen) -> Stroke { - let stroke = Stroke( + func beginStroke(at point: CGPoint, pen: Pen) -> PenStroke { + let stroke = PenStroke( bounds: [point.x - pen.thickness, point.y - pen.thickness, point.x + pen.thickness, point.y + pen.thickness], color: pen.rgba, style: pen.strokeStyle.rawValue, diff --git a/Memola/Canvas/Core/Canvas.swift b/Memola/Canvas/Core/Canvas.swift index b2787a0..b3a3a39 100644 --- a/Memola/Canvas/Core/Canvas.swift +++ b/Memola/Canvas/Core/Canvas.swift @@ -104,7 +104,7 @@ extension Canvas { // MARK: - Graphic Context extension Canvas { - func beginTouch(at point: CGPoint, pen: Pen) -> Stroke { + func beginTouch(at point: CGPoint, pen: Pen) -> PenStroke { graphicContext.beginStroke(at: point, pen: pen) } @@ -124,7 +124,7 @@ extension Canvas { graphicContext.renderType = renderType } - func getNewlyAddedStroke() -> Stroke? { + func getNewlyAddedStroke() -> PenStroke? { graphicContext.strokes.last } } diff --git a/Memola/Canvas/Geometries/Stroke/StrokeGenerator.swift b/Memola/Canvas/Geometries/Stroke/Core/StrokeGenerator.swift similarity index 56% rename from Memola/Canvas/Geometries/Stroke/StrokeGenerator.swift rename to Memola/Canvas/Geometries/Stroke/Core/StrokeGenerator.swift index 5c540f8..9486d84 100644 --- a/Memola/Canvas/Geometries/Stroke/StrokeGenerator.swift +++ b/Memola/Canvas/Geometries/Stroke/Core/StrokeGenerator.swift @@ -12,7 +12,7 @@ protocol StrokeGenerator { var configuration: Configuration { get set } - func begin(at point: CGPoint, on stroke: Stroke) - func append(to point: CGPoint, on stroke: Stroke) - func finish(at point: CGPoint, on stroke: Stroke) + func begin(at point: CGPoint, on stroke: PenStroke) + func append(to point: CGPoint, on stroke: PenStroke) + func finish(at point: CGPoint, on stroke: PenStroke) } diff --git a/Memola/Canvas/Geometries/Stroke/Generators/SolidPointStrokeGenerator.swift b/Memola/Canvas/Geometries/Stroke/Generators/SolidPointStrokeGenerator.swift index 0e31d2d..eb13484 100644 --- a/Memola/Canvas/Geometries/Stroke/Generators/SolidPointStrokeGenerator.swift +++ b/Memola/Canvas/Geometries/Stroke/Generators/SolidPointStrokeGenerator.swift @@ -10,13 +10,13 @@ import Foundation struct SolidPointStrokeGenerator: StrokeGenerator { var configuration: Configuration - func begin(at point: CGPoint, on stroke: Stroke) { + func begin(at point: CGPoint, on stroke: PenStroke) { let point = stroke.movingAverage.addPoint(point) stroke.keyPoints.append(point) addPoint(point, on: stroke) } - func append(to point: CGPoint, on stroke: Stroke) { + func append(to point: CGPoint, on stroke: PenStroke) { guard stroke.keyPoints.endIndex > 0 else { return } @@ -49,7 +49,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator { } } - func finish(at point: CGPoint, on stroke: Stroke) { + func finish(at point: CGPoint, on stroke: PenStroke) { switch stroke.keyPoints.endIndex { case 0...1: break @@ -58,7 +58,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator { } } - private func smoothOutPath(on stroke: Stroke) { + private func smoothOutPath(on stroke: PenStroke) { stroke.removeQuads(from: stroke.quadIndex + 1) adjustKeyPoint(on: stroke) switch stroke.keyPoints.endIndex { @@ -79,7 +79,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator { stroke.quadIndex = stroke.quads.endIndex - 1 } - private func adjustKeyPoint(on stroke: Stroke) { + private func adjustKeyPoint(on stroke: PenStroke) { let index = stroke.keyPoints.endIndex - 1 let prev = stroke.keyPoints[index - 1] let current = stroke.keyPoints[index] @@ -89,7 +89,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator { stroke.keyPoints[index] = point } - private func addPoint(_ point: CGPoint, on stroke: Stroke) { + private func addPoint(_ point: CGPoint, on stroke: PenStroke) { let rotation: CGFloat switch configuration.rotation { case .fixed: @@ -100,7 +100,7 @@ struct SolidPointStrokeGenerator: StrokeGenerator { stroke.addQuad(at: point, rotation: rotation, shape: .rounded) } - private func addCurve(from start: CGPoint, to end: CGPoint, by control: CGPoint, on stroke: Stroke) { + private func addCurve(from start: CGPoint, to end: CGPoint, by control: CGPoint, on stroke: PenStroke) { let distance = start.distance(to: end) let factor: CGFloat switch configuration.granularity { diff --git a/Memola/Canvas/Geometries/Stroke/Stroke.swift b/Memola/Canvas/Geometries/Stroke/Strokes/PenStroke.swift similarity index 92% rename from Memola/Canvas/Geometries/Stroke/Stroke.swift rename to Memola/Canvas/Geometries/Stroke/Strokes/PenStroke.swift index 8018da1..5d42e80 100644 --- a/Memola/Canvas/Geometries/Stroke/Stroke.swift +++ b/Memola/Canvas/Geometries/Stroke/Strokes/PenStroke.swift @@ -1,5 +1,5 @@ // -// Stroke.swift +// PenStroke.swift // Memola // // Created by Dscyre Scotti on 5/4/24. @@ -9,7 +9,7 @@ import MetalKit import CoreData import Foundation -final class Stroke: @unchecked Sendable { +final class PenStroke: @unchecked Sendable { var object: StrokeObject? var bounds: [CGFloat] var color: [CGFloat] @@ -17,6 +17,7 @@ final class Stroke: @unchecked Sendable { var createdAt: Date var thickness: CGFloat var quads: [Quad] + var penStyle: Style init(object: StrokeObject) { self.object = object @@ -26,6 +27,7 @@ final class Stroke: @unchecked Sendable { self.createdAt = object.createdAt self.thickness = object.thickness self.quads = [] + self.penStyle = Style(rawValue: style) ?? .marker } init( @@ -42,17 +44,12 @@ final class Stroke: @unchecked Sendable { self.createdAt = createdAt self.thickness = thickness self.quads = quads - } - - var angle: CGFloat = 0 - var penStyle: Style { - Style(rawValue: style) ?? .marker + self.penStyle = Style(rawValue: style) ?? .marker } var batchIndex: Int = 0 var quadIndex: Int = -1 var keyPoints: [CGPoint] = [] - var thicknessFactor: CGFloat = 0.7 let movingAverage = MovingAverage(windowSize: 3) @@ -60,12 +57,7 @@ final class Stroke: @unchecked Sendable { var indexBuffer: MTLBuffer? var vertexBuffer: MTLBuffer? - var isEmpty: Bool { - quads.isEmpty - } - var isEraserPenStyle: Bool { - penStyle == .eraser - } + var isEmpty: Bool { quads.isEmpty } var strokeBounds: CGRect { let x = bounds[0] let y = bounds[1] @@ -92,7 +84,7 @@ final class Stroke: @unchecked Sendable { } } -extension Stroke { +extension PenStroke { func loadQuads() { guard let object else { return } quads = object.quads.compactMap { quad in @@ -153,7 +145,7 @@ extension Stroke { } } -extension Stroke: Drawable { +extension PenStroke: Drawable { func prepare(device: MTLDevice) { if texture == nil { texture = penStyle.anyPenStyle.loadTexture(on: device) @@ -177,7 +169,7 @@ extension Stroke: Drawable { } } -extension Stroke { +extension PenStroke { enum Style: Int16 { case marker case eraser diff --git a/Memola/Canvas/History/HistoryEvent.swift b/Memola/Canvas/History/HistoryEvent.swift index 11ec7a3..1b2c7ce 100644 --- a/Memola/Canvas/History/HistoryEvent.swift +++ b/Memola/Canvas/History/HistoryEvent.swift @@ -8,5 +8,5 @@ import Foundation enum HistoryEvent { - case stroke(Stroke) + case stroke(PenStroke) } diff --git a/Memola/Canvas/RenderPasses/CacheRenderPass.swift b/Memola/Canvas/RenderPasses/CacheRenderPass.swift index ebc4210..d826897 100644 --- a/Memola/Canvas/RenderPasses/CacheRenderPass.swift +++ b/Memola/Canvas/RenderPasses/CacheRenderPass.swift @@ -46,11 +46,12 @@ class CacheRenderPass: RenderPass { let graphicContext = canvas.graphicContext if let stroke = graphicContext.currentStroke { - if stroke.isEraserPenStyle { + switch stroke.penStyle { + case .eraser: eraserRenderPass.stroke = stroke eraserRenderPass.descriptor = descriptor eraserRenderPass.draw(on: canvas, with: renderer) - } else { + case .marker: canvas.setGraphicRenderType(.inProgress) strokeRenderPass.stroke = stroke strokeRenderPass.graphicDescriptor = descriptor diff --git a/Memola/Canvas/RenderPasses/EraserRenderPass.swift b/Memola/Canvas/RenderPasses/EraserRenderPass.swift index 5290357..4854b2b 100644 --- a/Memola/Canvas/RenderPasses/EraserRenderPass.swift +++ b/Memola/Canvas/RenderPasses/EraserRenderPass.swift @@ -16,7 +16,7 @@ class EraserRenderPass: RenderPass { var eraserPipelineState: MTLRenderPipelineState? var quadPipelineState: MTLComputePipelineState? - var stroke: Stroke? + var stroke: PenStroke? weak var graphicTexture: MTLTexture? init(renderer: Renderer) { @@ -48,7 +48,7 @@ class EraserRenderPass: RenderPass { } private func generateVertexBuffer(on canvas: Canvas, with renderer: Renderer) { - guard let stroke, !stroke.quads.isEmpty, let quadPipelineState else { return } + guard let stroke, !stroke.isEmpty, let quadPipelineState else { return } guard let quadCommandBuffer = renderer.commandQueue.makeCommandBuffer() else { return } guard let computeEncoder = quadCommandBuffer.makeComputeCommandEncoder() else { return } diff --git a/Memola/Canvas/RenderPasses/GraphicRenderPass.swift b/Memola/Canvas/RenderPasses/GraphicRenderPass.swift index 0f8e4e5..a3c4783 100644 --- a/Memola/Canvas/RenderPasses/GraphicRenderPass.swift +++ b/Memola/Canvas/RenderPasses/GraphicRenderPass.swift @@ -52,11 +52,12 @@ class GraphicRenderPass: RenderPass { guard stroke.isVisible(in: canvas.bounds) else { continue } descriptor.colorAttachments[0].loadAction = clearsTexture ? .clear : .load clearsTexture = false - if stroke.isEraserPenStyle { + switch stroke.penStyle { + case .eraser: eraserRenderPass.stroke = stroke eraserRenderPass.descriptor = descriptor eraserRenderPass.draw(on: canvas, with: renderer) - } else { + case .marker: canvas.setGraphicRenderType(.finished) strokeRenderPass.stroke = stroke strokeRenderPass.graphicDescriptor = descriptor @@ -70,11 +71,12 @@ class GraphicRenderPass: RenderPass { if let stroke = graphicContext.previousStroke { descriptor.colorAttachments[0].loadAction = clearsTexture ? .clear : .load clearsTexture = false - if stroke.isEraserPenStyle { + switch stroke.penStyle { + case .eraser: eraserRenderPass.stroke = stroke eraserRenderPass.descriptor = descriptor eraserRenderPass.draw(on: canvas, with: renderer) - } else { + case .marker: canvas.setGraphicRenderType(.newlyFinished) strokeRenderPass.stroke = stroke strokeRenderPass.graphicDescriptor = descriptor diff --git a/Memola/Canvas/RenderPasses/StrokeRenderPass.swift b/Memola/Canvas/RenderPasses/StrokeRenderPass.swift index a9a4887..c9c6c84 100644 --- a/Memola/Canvas/RenderPasses/StrokeRenderPass.swift +++ b/Memola/Canvas/RenderPasses/StrokeRenderPass.swift @@ -18,7 +18,7 @@ class StrokeRenderPass: RenderPass { var quadPipelineState: MTLComputePipelineState? weak var graphicPipelineState: MTLRenderPipelineState? - var stroke: Stroke? + var stroke: PenStroke? var strokeTexture: MTLTexture? init(renderer: Renderer) { @@ -61,7 +61,7 @@ class StrokeRenderPass: RenderPass { } private func generateVertexBuffer(on canvas: Canvas, with renderer: Renderer) { - guard let stroke, !stroke.quads.isEmpty, let quadPipelineState else { return } + guard let stroke, !stroke.isEmpty, let quadPipelineState else { return } guard let quadCommandBuffer = renderer.commandQueue.makeCommandBuffer() else { return } guard let computeEncoder = quadCommandBuffer.makeComputeCommandEncoder() else { return } diff --git a/Memola/Canvas/Tool/Pen/Core/Pen.swift b/Memola/Canvas/Tool/Pen/Core/Pen.swift index 4b453cf..0238ece 100644 --- a/Memola/Canvas/Tool/Pen/Core/Pen.swift +++ b/Memola/Canvas/Tool/Pen/Core/Pen.swift @@ -43,14 +43,14 @@ class Pen: NSObject, ObservableObject, Identifiable { init(object: PenObject) { self.object = object self.id = object.objectID.uriRepresentation().absoluteString - self.style = (Stroke.Style(rawValue: object.style) ?? .marker).anyPenStyle + self.style = (PenStroke.Style(rawValue: object.style) ?? .marker).anyPenStyle self.rgba = object.color self.thickness = object.thickness self.isSelected = object.isSelected super.init() } - var strokeStyle: Stroke.Style { + var strokeStyle: PenStroke.Style { style.strokeStyle } } diff --git a/Memola/Canvas/Tool/Pen/Core/PenStyle.swift b/Memola/Canvas/Tool/Pen/Core/PenStyle.swift index 85b1a05..5072ccc 100644 --- a/Memola/Canvas/Tool/Pen/Core/PenStyle.swift +++ b/Memola/Canvas/Tool/Pen/Core/PenStyle.swift @@ -24,7 +24,7 @@ extension PenStyle { Textures.createPenTexture(with: textureName, on: device) } - var strokeStyle: Stroke.Style { + var strokeStyle: PenStroke.Style { switch self { case is MarkerPenStyle: return .marker