prototype one was feature complete for our base platform to experiment with… except that it slowed to a crawl in it’s first real-world session. prototype two has the engineering work to maintain a snappy drawing experience and UI. this hasn’t made the drawing itself performant, rather it has made the engine responsive regardless of the drawing performance. it keeps the act of drawing syncronous along with the rest of UI, while pushing the updating of the whole canvas in the background.
prototype one looked something like this, the standard fill-in-the-placeholder function to draw into the view –
override func draw(_ rect: CGRect)
the prototype two equivalent looks like this. it’s… a lot more complicated.
// Drawing canvas for the live stroke, which changes during stroking given prediction etc.
private var activeStrokeLayer: CALayer!
private var drawingLayerDelegate: DrawingLayerDelegate!
// Drawing canvas for the completed strokes; async, accumulating, and other sophistry
private var completedStrokesLayer: CALayer!
private var layerDelegate: LayerDelegate!
private var completedStrokesQueue: DispatchQueue!
private var completedStrokesBlocks: [DispatchWorkItem]!
private var completedStrokesContext: CGContext!
// Draw methods to abstract what’s going on behind the scenes
func drawCompletedStrokes(onlyAdd: [Stroke]? = nil)
func drawActiveStroke()
// When receiving a new set of strokes, if any stroke from the old set is missing from the new, we need to completely redraw. Conversely, new strokes can be drawn on top of the existing canvas.
func diff(_ oldElements: [Stroke], _ newElements: [Stroke]) -> diffResult
oh, and the timestamps on the audio timeline are nicely formatted now.