refactor: clean up

This commit is contained in:
dscyrescotti
2024-05-24 17:54:46 +07:00
parent f6055c0e70
commit 43d933a1dc
13 changed files with 67 additions and 56 deletions

View File

@@ -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 = "<group>"; };
ECA738CA2BE60F1900A4542E /* ViewPortContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewPortContext.swift; sourceTree = "<group>"; };
ECA738CC2BE60F2F00A4542E /* GridContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GridContext.swift; sourceTree = "<group>"; };
ECA738D12BE60F7B00A4542E /* Stroke.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stroke.swift; sourceTree = "<group>"; };
ECA738D12BE60F7B00A4542E /* PenStroke.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PenStroke.swift; sourceTree = "<group>"; };
ECA738D32BE60F9100A4542E /* StrokeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StrokeGenerator.swift; sourceTree = "<group>"; };
ECA738D62BE60FC100A4542E /* SolidPointStrokeGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolidPointStrokeGenerator.swift; sourceTree = "<group>"; };
ECA738D92BE60FF100A4542E /* CacheRenderPass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheRenderPass.swift; sourceTree = "<group>"; };
@@ -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 = "<group>";
@@ -618,6 +618,22 @@
path = Core;
sourceTree = "<group>";
};
ECE883B82C009DC30045C53D /* Strokes */ = {
isa = PBXGroup;
children = (
ECA738D12BE60F7B00A4542E /* PenStroke.swift */,
);
path = Strokes;
sourceTree = "<group>";
};
ECE883B92C009DCA0045C53D /* Core */ = {
isa = PBXGroup;
children = (
ECA738D32BE60F9100A4542E /* StrokeGenerator.swift */,
);
path = Core;
sourceTree = "<group>";
};
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 */,

View File

@@ -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,

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -8,5 +8,5 @@
import Foundation
enum HistoryEvent {
case stroke(Stroke)
case stroke(PenStroke)
}

View File

@@ -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

View File

@@ -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 }

View File

@@ -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

View File

@@ -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 }

View File

@@ -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
}
}

View File

@@ -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