diff --git a/Shared/SampleCanvasBackdropLayer.swift b/Shared/SampleCanvasBackdropLayer.swift index a1471d4..0a307b2 100644 --- a/Shared/SampleCanvasBackdropLayer.swift +++ b/Shared/SampleCanvasBackdropLayer.swift @@ -10,16 +10,18 @@ import Foundation import MetalKit + class SampleCanvasBackdropLayer: CanvasLayer { lazy var imageRenderable: ImageRenderable? = { guard let device = self.device else { return nil } - guard let image = XImage(named: "Grid") else { fatalError("not found") } - return ImageRenderable(device: device, image: image, frame: Rect(0, 0, 2048, 1024))! + guard let image = XImage(named: .grid) else { fatalError("not found") } + return ImageRenderable(device: device, + image: image, frame: Rect(0, 0, 2048, 1024))! }() lazy var brushPatternTexture: MTLTexture! = { - return self.device?.texture(of: XImage(named: "test")!)! + return self.device?.texture(of: XImage(named: .test)!)! }() diff --git a/Shared/SampleCanvasScribbleLayer.swift b/Shared/SampleCanvasScribbleLayer.swift index ee012c7..31ad6d2 100644 --- a/Shared/SampleCanvasScribbleLayer.swift +++ b/Shared/SampleCanvasScribbleLayer.swift @@ -13,12 +13,12 @@ import MetalKit class SampleCanvasScribbleLayer: CanvasLayer { lazy var brushSapeTexture: MTLTexture? = { - return self.device?.texture(of: XImage(named: "Particle")!)! + return self.device?.texture(of: XImage(named: .particle)!)! }() lazy var brushPatternTexture: MTLTexture! = { - return self.device?.texture(of: XImage(named: "Pencil")!)! + return self.device?.texture(of: XImage(named: .pencil)!)! }() lazy var strokePaths: [CGPath] = { diff --git a/Shared/SampleScene.swift b/Shared/SampleScene.swift index c3c19ea..abca7cb 100644 --- a/Shared/SampleScene.swift +++ b/Shared/SampleScene.swift @@ -26,7 +26,7 @@ class SampleScene: Scene { }() lazy var image1Texture: MTLTexture = { - return self.device.texture(of: XImage(named: "BlueMarble")!)! + return self.device.texture(of: XImage(named: .blueMarble)!)! }() // MRAK: - @@ -93,13 +93,13 @@ class SampleScene: Scene { let bezierRenderer = device.renderer() as BezierRenderer bezierRenderer.render(context: context, cgPaths: [self.samplePath()]) - context.widthCGContext { (cgContext) in + context.withCGContext { (cgContext) in let paragraphStyle : NSMutableParagraphStyle = .makeParagraphStyle() paragraphStyle.alignment = .center let attributes = [ - NSFontAttributeName: XFont.boldSystemFont(ofSize: 32), - NSForegroundColorAttributeName: XColor.white, - NSParagraphStyleAttributeName: paragraphStyle + NSAttributedStringKey.font: XFont.boldSystemFont(ofSize: 32), + NSAttributedStringKey.foregroundColor: XColor.white, + NSAttributedStringKey.paragraphStyle: paragraphStyle ] let formatter = DateFormatter() formatter.dateFormat = "HH:mm:ss" diff --git a/Silvershadow.xcodeproj/project.pbxproj b/Silvershadow.xcodeproj/project.pbxproj index cc5d657..685644e 100644 --- a/Silvershadow.xcodeproj/project.pbxproj +++ b/Silvershadow.xcodeproj/project.pbxproj @@ -361,6 +361,7 @@ CCF3496D1E0F999400EF1312 = { CreatedOnToolsVersion = 8.2.1; DevelopmentTeam = 2P97EM4L4N; + LastSwiftMigration = 0910; ProvisioningStyle = Automatic; }; }; @@ -777,7 +778,8 @@ SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -826,7 +828,8 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/Silvershadow/BezierRenderer.swift b/Silvershadow/BezierRenderer.swift index 8a593b9..9c2ec70 100644 --- a/Silvershadow/BezierRenderer.swift +++ b/Silvershadow/BezierRenderer.swift @@ -112,7 +112,7 @@ class BezierRenderer: Renderer { } var library: MTLLibrary { - return self.device.newDefaultLibrary()! + return self.device.makeDefaultLibrary()! } lazy var computePipelineState: MTLComputePipelineState = { @@ -158,11 +158,11 @@ class BezierRenderer: Renderer { }() lazy var shapeSamplerState: MTLSamplerState = { - return self.device.makeSamplerState(descriptor: .`default`) + return self.device.makeDefaultSamplerState() }() lazy var patternSamplerState: MTLSamplerState = { - return self.device.makeSamplerState(descriptor: .`default`) + return self.device.makeDefaultSamplerState() }() private typealias LineSegment = (type: ElementType, length: CGFloat, p0: CGPoint, p1: CGPoint, p2: CGPoint, p3: CGPoint) @@ -212,10 +212,9 @@ class BezierRenderer: Renderer { lazy var heap: XHeap = { return self.device.makeHeap(size: 1024 * 1024 * 64) // ?? }() - #endif - #if os(macOS) - var heap: XHeap { return self.device } + #elseif os(macOS) + var heap: XHeap { return self.device } #endif @@ -299,13 +298,13 @@ class BezierRenderer: Renderer { // build contiguous vertexes using computing shader from PathElement do { - let encoder = commandBuffer.makeComputeCommandEncoder() + let encoder = commandBuffer.makeComputeCommandEncoder()! encoder.pushDebugGroup("bezier - kernel") encoder.setComputePipelineState(computePipelineState) elementBuffer.set(elements) - encoder.setBuffer(elementBuffer.buffer, offset: 0, at: 0) - encoder.setBuffer(vertexBuffer.buffer, offset: 0, at: 1) + encoder.setBuffer(elementBuffer.buffer, offset: 0, index: 0) + encoder.setBuffer(vertexBuffer.buffer, offset: 0, index: 1) let threadgroupsPerGrid = MTLSizeMake(elements.count, 1, 1) let threadsPerThreadgroup = MTLSizeMake(1, 1, 1) encoder.dispatchThreadgroups(threadgroupsPerGrid, threadsPerThreadgroup: threadsPerThreadgroup) @@ -317,20 +316,20 @@ class BezierRenderer: Renderer { // vertex buffer should be filled with vertexes then draw it do { - let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: shadingRenderPassDescriptor) + let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: shadingRenderPassDescriptor)! encoder.pushDebugGroup("bezier - brush shaping") encoder.setRenderPipelineState(renderPipelineState) encoder.setFrontFacing(.clockwise) - encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, at: 0) - encoder.setVertexBuffer(uniformsBuffer, offset: 0, at: 1) + encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, index: 0) + encoder.setVertexBuffer(uniformsBuffer, offset: 0, index: 1) - encoder.setFragmentTexture(context.brushShape, at: 0) - encoder.setFragmentSamplerState(shapeSamplerState, at: 0) + encoder.setFragmentTexture(context.brushShape, index: 0) + encoder.setFragmentSamplerState(shapeSamplerState, index: 0) - encoder.setFragmentTexture(context.brushPattern, at: 1) - encoder.setFragmentSamplerState(patternSamplerState, at: 1) + encoder.setFragmentTexture(context.brushPattern, index: 1) + encoder.setFragmentSamplerState(patternSamplerState, index: 1) encoder.drawPrimitives(type: .point, vertexStart: 0, vertexCount: Int(vertexCount)) encoder.popDebugGroup() diff --git a/Silvershadow/CGPath+Z.swift b/Silvershadow/CGPath+Z.swift index 608ba74..11a7790 100644 --- a/Silvershadow/CGPath+Z.swift +++ b/Silvershadow/CGPath+Z.swift @@ -98,8 +98,7 @@ public extension CGPath { } } - let pathelements = elements.pathElements - return pathelements + return elements.pathElements } } diff --git a/Silvershadow/Canvas.swift b/Silvershadow/Canvas.swift index 623d193..4005689 100644 --- a/Silvershadow/Canvas.swift +++ b/Silvershadow/Canvas.swift @@ -34,10 +34,10 @@ extension MTLTextureDescriptor { } extension MTLDevice { - final func makeTexture2D(size: CGSize, mipmapped: Bool, usage: MTLTextureUsage) -> MTLTexture { + func makeTexture2D(size: CGSize, mipmapped: Bool, usage: MTLTextureUsage) -> MTLTexture { return makeTexture(descriptor: .texture2DDescriptor(size: size, mipmapped: mipmapped, - usage: usage)) + usage: usage))! } } @@ -79,7 +79,7 @@ class Canvas: Scene { }() lazy var subcomandQueue: MTLCommandQueue = { - return self.device.makeCommandQueue() + return self.device.makeCommandQueue()! }() override func update() { @@ -97,8 +97,8 @@ class Canvas: Scene { // clear canvas texture renderPassDescriptor.colorAttachments[0].loadAction = .clear - let commandBuffer = commandQueue.makeCommandBuffer() - let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) + let commandBuffer = commandQueue.makeCommandBuffer()! + let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)! commandEncoder.endEncoding() commandBuffer.commit() renderPassDescriptor.colorAttachments[0].loadAction = .load @@ -119,8 +119,8 @@ class Canvas: Scene { // clear subtexture subrenderPassDescriptor.colorAttachments[0].loadAction = .clear - let commandBuffer = commandQueue.makeCommandBuffer() - let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: subrenderPassDescriptor) + let commandBuffer = commandQueue.makeCommandBuffer()! + let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: subrenderPassDescriptor)! commandEncoder.endEncoding() commandBuffer.commit() subrenderPassDescriptor.colorAttachments[0].loadAction = .load @@ -189,7 +189,7 @@ class Canvas: Scene { // clear subtexture let commandBuffer = context.makeCommandBuffer() - let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: subrenderPassDescriptor) + let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: subrenderPassDescriptor)! commandEncoder.endEncoding() commandBuffer.commit() diff --git a/Silvershadow/ColorRenderer.swift b/Silvershadow/ColorRenderer.swift index c1d9321..77654c2 100644 --- a/Silvershadow/ColorRenderer.swift +++ b/Silvershadow/ColorRenderer.swift @@ -53,7 +53,7 @@ class ColorRenderer: Renderer { } lazy var library: MTLLibrary = { - return self.device.newDefaultLibrary()! + return self.device.makeDefaultLibrary()! }() lazy var renderPipelineState: MTLRenderPipelineState = { @@ -77,7 +77,7 @@ class ColorRenderer: Renderer { }() lazy var colorSamplerState: MTLSamplerState = { - return self.device.makeSamplerState(descriptor: .`default`) + return self.device.makeDefaultSamplerState() }() func render(context: RenderContext, vertexBuffer: VertexBuffer) { @@ -86,10 +86,10 @@ class ColorRenderer: Renderer { let commandBuffer = context.makeCommandBuffer() - let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor) + let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor)! encoder.setRenderPipelineState(self.renderPipelineState) - encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, at: 0) - encoder.setVertexBuffer(uniformsBuffer, offset: 0, at: 1) + encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, index: 0) + encoder.setVertexBuffer(uniformsBuffer, offset: 0, index: 1) encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: vertexBuffer.count) @@ -126,7 +126,6 @@ class ColorRenderer: Renderer { extension RenderContext { - func render(triangles: [(ColorVertex, ColorVertex, ColorVertex)]) { let renderer: ColorRenderer = self.device.renderer() diff --git a/Silvershadow/CoreGraphics+Z.swift b/Silvershadow/CoreGraphics+Z.swift index fe20e88..cb5f52d 100644 --- a/Silvershadow/CoreGraphics+Z.swift +++ b/Silvershadow/CoreGraphics+Z.swift @@ -99,7 +99,7 @@ extension CGSize { func aspectFit(_ size: CGSize) -> CGSize { let widthRatio = self.width / size.width let heightRatio = self.height / size.height - let ratio = (widthRatio < heightRatio) ? widthRatio : heightRatio + let ratio = min(widthRatio, heightRatio) let width = size.width * ratio let height = size.height * ratio return CGSize(width: width, height: height) diff --git a/Silvershadow/CrossPlatform.swift b/Silvershadow/CrossPlatform.swift index e992e64..5dedfb6 100644 --- a/Silvershadow/CrossPlatform.swift +++ b/Silvershadow/CrossPlatform.swift @@ -66,7 +66,6 @@ import Foundation } extension NSView { - func setNeedsLayout() { layout() } @@ -77,24 +76,21 @@ import Foundation func sendSubview(toBack: NSView) { var subviews = self.subviews - guard let index = subviews.index(of: toBack) else { return } - subviews.remove(at: index) + guard let _ = subviews.remove(toBack) else { return } subviews.insert(toBack, at: 0) self.subviews = subviews } func bringSubview(toFront: NSView) { var subviews = self.subviews - guard let index = subviews.index(of: toFront) else { return } - subviews.remove(at: index) + guard let _ = subviews.remove(toFront) else { return } subviews.append(toFront) self.subviews = subviews } func replaceSubview(subview: NSView, with other: NSView) { var subviews = self.subviews - guard let index = subviews.index(of: subview) else { return } - subviews.remove(at: index) + guard let index = subviews.remove(subview) else { return } subviews.insert(other, at: index) self.subviews = subviews } @@ -110,13 +106,18 @@ import Foundation extension CGContext { static var current : CGContext? { - return NSGraphicsContext.current()?.cgContext + return NSGraphicsContext.current?.cgContext } } extension NSScrollView { var zoomScale : CGFloat { - return magnification + get { + return magnification + } + set { + magnification = newValue + } } } @@ -146,20 +147,22 @@ struct XRGBA { } extension XColor { - var rgba: XRGBA { return .init(color: self) } } -extension NSMutableParagraphStyle { +extension XImage.Name { + static let grid = XImage.Name(rawValue: "Grid") + static let test = XImage.Name(rawValue: "test") + static let pencil = XImage.Name(rawValue: "Pencil") + static let particle = XImage.Name(rawValue: "Particle") + static let blueMarble = XImage.Name(rawValue: "BlueMarble") +} +extension NSMutableParagraphStyle { static func makeParagraphStyle() -> NSMutableParagraphStyle { - #if os(iOS) - return NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle - #elseif os(macOS) - return NSParagraphStyle.default().mutableCopy() as! NSMutableParagraphStyle - #endif + return NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle } } diff --git a/Silvershadow/ImageRenderer.swift b/Silvershadow/ImageRenderer.swift index 23f1c41..37f17dc 100644 --- a/Silvershadow/ImageRenderer.swift +++ b/Silvershadow/ImageRenderer.swift @@ -105,7 +105,7 @@ class ImageRenderer: Renderer { }() lazy var colorSamplerState: MTLSamplerState = { - return self.device.makeSamplerState(descriptor: .`default`) + return self.device.makeDefaultSamplerState() }() func vertexBuffer(for vertices: [Vertex]) -> VertexBuffer? { @@ -118,11 +118,11 @@ class ImageRenderer: Renderer { func texture(of image: XImage) -> MTLTexture? { guard let cgImage: CGImage = image.cgImage else { return nil } - var options: [String : NSObject] = [MTKTextureLoaderOptionSRGB: false as NSNumber] + var options: [MTKTextureLoader.Option : Any] = [.SRGB: false as NSNumber] if #available(iOS 10.0, *) { - options[MTKTextureLoaderOptionOrigin] = true as NSNumber + options[.origin] = true as NSNumber } - return try? device.textureLoader.newTexture(with: cgImage, options: options) + return try? device.textureLoader.newTexture(cgImage: cgImage, options: options) } // MARK: - @@ -134,7 +134,7 @@ class ImageRenderer: Renderer { self.device.makeBuffer(length: MemoryLayout.size, options: [.storageModeShared]), self.device.makeBuffer(length: MemoryLayout.size, options: [.storageModeShared]) ] - }() + }() as! [MTLBuffer] let rectangularVertexCount = 6 @@ -161,17 +161,17 @@ class ImageRenderer: Renderer { vertexBuffer.set(vertices) let commandBuffer = context.makeCommandBuffer() - let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor) + let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor)! encoder.pushDebugGroup("image") encoder.setRenderPipelineState(self.renderPipelineState) encoder.setFrontFacing(.clockwise) // commandEncoder.setCullMode(.back) - encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, at: 0) - encoder.setVertexBuffer(uniformsBuffer, offset: 0, at: 1) + encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, index: 0) + encoder.setVertexBuffer(uniformsBuffer, offset: 0, index: 1) - encoder.setFragmentTexture(texture, at: 0) - encoder.setFragmentSamplerState(self.colorSamplerState, at: 0) + encoder.setFragmentTexture(texture, index: 0) + encoder.setFragmentSamplerState(self.colorSamplerState, index: 0) encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: vertexBuffer.count) encoder.popDebugGroup() diff --git a/Silvershadow/Kernel.swift b/Silvershadow/Kernel.swift index fcc7f70..1bd1e58 100644 --- a/Silvershadow/Kernel.swift +++ b/Silvershadow/Kernel.swift @@ -17,7 +17,7 @@ protocol Kernel: class { extension Kernel { var library: MTLLibrary { - return self.device.newDefaultLibrary()! + return self.device.makeDefaultLibrary()! } } diff --git a/Silvershadow/MTLDevice+Z.swift b/Silvershadow/MTLDevice+Z.swift index 3c2be86..bf1afae 100644 --- a/Silvershadow/MTLDevice+Z.swift +++ b/Silvershadow/MTLDevice+Z.swift @@ -15,21 +15,23 @@ extension MTLDevice { return MTKTextureLoader(device: self) } + func makeDefaultSamplerState() -> MTLSamplerState { + return makeSamplerState(descriptor: .`default`)! + } + func texture(of image: CGImage) -> MTLTexture? { let textureUsage : MTLTextureUsage = [.pixelFormatView, .shaderRead] - var options: [String : NSObject] = [ - MTKTextureLoaderOptionSRGB: false as NSNumber, - MTKTextureLoaderOptionTextureUsage: textureUsage.rawValue as NSNumber - ] + var options: [MTKTextureLoader.Option : Any] = [.SRGB: false as NSNumber, + .textureUsage: textureUsage.rawValue as NSNumber] if #available(iOS 10.0, *) { - options[MTKTextureLoaderOptionOrigin] = true as NSNumber + options[.origin] = true as NSNumber } - guard let texture = try? self.textureLoader.newTexture(with: image, options: options) else { return nil } + guard let texture = try? textureLoader.newTexture(cgImage: image, options: options) else { return nil } if texture.pixelFormat == .bgra8Unorm { return texture } - else { return texture.makeTextureView(pixelFormat: .bgra8Unorm) } + return texture.makeTextureView(pixelFormat: .bgra8Unorm) } func texture(of image: XImage) -> MTLTexture? { @@ -37,12 +39,15 @@ extension MTLDevice { } func texture(named name: String) -> MTLTexture? { - var options = [String: NSObject]() - options[MTKTextureLoaderOptionSRGB] = false as NSNumber + var options : [MTKTextureLoader.Option: Any] = [.SRGB : false as NSNumber] + if #available(iOS 10.0, *) { - options[MTKTextureLoaderOptionOrigin] = MTKTextureLoaderOriginTopLeft as NSObject + options[.origin] = MTKTextureLoader.Origin.topLeft as NSObject } - do { return try self.textureLoader.newTexture(withName: name, scaleFactor: 1.0, bundle: nil, options: options) } + + do { return try textureLoader.newTexture(name: name, scaleFactor: 1.0, + bundle: nil, + options: options) } catch { fatalError("\(error)") } } diff --git a/Silvershadow/MetalBuffer.swift b/Silvershadow/MetalBuffer.swift index 8654f9f..0267fbc 100644 --- a/Silvershadow/MetalBuffer.swift +++ b/Silvershadow/MetalBuffer.swift @@ -38,11 +38,11 @@ class MetalBuffer { self.capacity = capacity let buffer = self.heap.makeBuffer(length: length, options: [.storageModeShared]) if let vertices = vertices { - let destinationArrayPtr = UnsafeMutablePointer(OpaquePointer(buffer.contents())) + let destinationArrayPtr = UnsafeMutablePointer(OpaquePointer(buffer?.contents())) let destinationArray = UnsafeMutableBufferPointer(start: destinationArrayPtr, count: vertices.count) (0 ..< vertices.count).forEach { destinationArray[$0] = vertices[$0] } } - self.buffer = buffer + self.buffer = buffer! } deinit { @@ -64,7 +64,7 @@ class MetalBuffer { let buffer = self.heap.makeBuffer(length: length, options: [.storageModeShared]) let sourceArrayPtr = UnsafeMutablePointer(OpaquePointer(self.buffer.contents())) let sourceArray = UnsafeMutableBufferPointer(start: sourceArrayPtr, count: count) - let destinationArrayPtr = UnsafeMutablePointer(OpaquePointer(buffer.contents())) + let destinationArrayPtr = UnsafeMutablePointer(OpaquePointer(buffer?.contents())) let destinationArray = UnsafeMutableBufferPointer(start: destinationArrayPtr, count: count + items.count) (0 ..< count).forEach { destinationArray[$0] = sourceArray[$0] } @@ -73,7 +73,7 @@ class MetalBuffer { self.count = count + items.count self.capacity = self.count - self.buffer = buffer + self.buffer = buffer! } } @@ -90,7 +90,7 @@ class MetalBuffer { let buffer = self.heap.makeBuffer(bytes: items, length: bytes, options: [.storageModeShared]) self.count = items.count self.capacity = items.count - self.buffer = buffer + self.buffer = buffer! } } diff --git a/Silvershadow/PatternRenderer.swift b/Silvershadow/PatternRenderer.swift index ed5edaa..ff5dc6f 100644 --- a/Silvershadow/PatternRenderer.swift +++ b/Silvershadow/PatternRenderer.swift @@ -12,7 +12,6 @@ import MetalKit import GLKit import simd - // // ImageRenderer // @@ -38,14 +37,20 @@ class PatternRenderer: Renderer { } struct Uniforms { - var transform: GLKMatrix4 - var contentSize: float2 - var patternSize: float2 + let transform: GLKMatrix4 + let contentSize: float2 + let patternSize: float2 + + init(context: RenderContext) { + transform = context.transform + contentSize = float2(Float(context.deviceSize.width), Float(context.deviceSize.height)) + patternSize = float2(Float(context.brushPattern.width), Float(context.brushPattern.height)) + } + } let device: MTLDevice - required init(device: MTLDevice) { self.device = device } @@ -105,11 +110,11 @@ class PatternRenderer: Renderer { }() lazy var shadingSamplerState: MTLSamplerState = { - return self.device.makeSamplerState(descriptor: .`default`) + return self.device.makeDefaultSamplerState() }() lazy var patternSamplerState: MTLSamplerState = { - return self.device.makeSamplerState(descriptor: .`default`) + return self.device.makeDefaultSamplerState() }() func vertexBuffer(for vertices: [Vertex]) -> VertexBuffer? { @@ -122,11 +127,11 @@ class PatternRenderer: Renderer { func texture(of image: XImage) -> MTLTexture? { guard let cgImage: CGImage = image.cgImage else { return nil } - var options: [String : NSObject] = [MTKTextureLoaderOptionSRGB: false as NSNumber] + var options: [MTKTextureLoader.Option : Any] = [.SRGB: false as NSNumber] if #available(iOS 10.0, *) { - options[MTKTextureLoaderOptionOrigin] = true as NSNumber + options[.origin] = true as NSNumber } - return try? device.textureLoader.newTexture(with: cgImage, options: options) + return try? device.textureLoader.newTexture(cgImage: cgImage, options: options) } // MARK: - @@ -140,16 +145,16 @@ class PatternRenderer: Renderer { self.device.makeBuffer(length: MemoryLayout.size, options: [.storageModeShared]), self.device.makeBuffer(length: MemoryLayout.size, options: [.storageModeShared]) ] - }() + }() as! [MTLBuffer] let rectangularVertexCount = 6 lazy var rectVertexTripleBuffer: [MTLBuffer] = { let len = MemoryLayout.size * self.rectangularVertexCount return [ - self.device.makeBuffer(length: len, options: [.storageModeShared]), - self.device.makeBuffer(length: len, options: [.storageModeShared]), - self.device.makeBuffer(length: len, options: [.storageModeShared]) + self.device.makeBuffer(length: len, options: [.storageModeShared])!, + self.device.makeBuffer(length: len, options: [.storageModeShared])!, + self.device.makeBuffer(length: len, options: [.storageModeShared])! ] }() @@ -159,10 +164,9 @@ class PatternRenderer: Renderer { defer { tripleBufferIndex = (tripleBufferIndex + 1) % uniformTripleBuffer.count } let uniformsBuffer = uniformTripleBuffer[tripleBufferIndex] - let uniformsBufferPtr = UnsafeMutablePointer(OpaquePointer(uniformsBuffer.contents())) - uniformsBufferPtr.pointee.transform = context.transform - uniformsBufferPtr.pointee.contentSize = float2(Float(context.deviceSize.width), Float(context.deviceSize.height)) - uniformsBufferPtr.pointee.patternSize = float2(Float(context.brushPattern.width), Float(context.brushPattern.height)) + let uniformsBufferPtr = uniformsBuffer.contents().assumingMemoryBound(to: Uniforms.self) + let uniform = Uniforms(context: context) + uniformsBufferPtr.pointee = uniform let vertexes = self.vertices(for: rect) assert(vertexes.count == rectangularVertexCount) @@ -172,21 +176,21 @@ class PatternRenderer: Renderer { (0 ..< vertexes.count).forEach { vertexArray[$0] = vertexes[$0] } let commandBuffer = context.makeCommandBuffer() - let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor) + let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor)! encoder.pushDebugGroup("pattern filling") encoder.setRenderPipelineState(self.renderPipelineState) encoder.setFrontFacing(.clockwise) // commandEncoder.setCullMode(.back) - encoder.setVertexBuffer(vertexBuffer, offset: 0, at: 0) - encoder.setVertexBuffer(uniformsBuffer, offset: 0, at: 1) - - encoder.setFragmentTexture(context.shadingTexture, at: 0) - encoder.setFragmentTexture(context.brushPattern, at: 1) - encoder.setFragmentSamplerState(self.shadingSamplerState, at: 0) - encoder.setFragmentSamplerState(self.patternSamplerState, at: 1) - encoder.setFragmentBuffer(uniformsBuffer, offset: 0, at: 0) + encoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) + encoder.setVertexBuffer(uniformsBuffer, offset: 0, index: 1) + + encoder.setFragmentTexture(context.shadingTexture, index: 0) + encoder.setFragmentTexture(context.brushPattern, index: 1) + encoder.setFragmentSamplerState(self.shadingSamplerState, index: 0) + encoder.setFragmentSamplerState(self.patternSamplerState, index: 1) + encoder.setFragmentBuffer(uniformsBuffer, offset: 0, index: 0) encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: vertexes.count) diff --git a/Silvershadow/PointsRenderer.swift b/Silvershadow/PointsRenderer.swift index b93a7a3..8bee59c 100644 --- a/Silvershadow/PointsRenderer.swift +++ b/Silvershadow/PointsRenderer.swift @@ -86,7 +86,7 @@ class PointsRenderer: Renderer { } var library: MTLLibrary { - return self.device.newDefaultLibrary()! + return self.device.makeDefaultLibrary()! } var vertexDescriptor: MTLVertexDescriptor { @@ -126,7 +126,7 @@ class PointsRenderer: Renderer { }() lazy var colorSamplerState: MTLSamplerState = { - return self.device.makeSamplerState(descriptor: .`default`) + return self.device.makeDefaultSamplerState() }() func vertexBuffer(for vertices: [Vertex], capacity: Int? = nil) -> VertexBuffer { @@ -139,14 +139,14 @@ class PointsRenderer: Renderer { let uniformsBuffer = device.makeBuffer(bytes: &uniforms, length: MemoryLayout.size, options: []) let commandBuffer = context.makeCommandBuffer() - let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor) + let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: context.renderPassDescriptor)! encoder.setRenderPipelineState(self.renderPipelineState) - encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, at: 0) - encoder.setVertexBuffer(uniformsBuffer, offset: 0, at: 1) + encoder.setVertexBuffer(vertexBuffer.buffer, offset: 0, index: 0) + encoder.setVertexBuffer(uniformsBuffer, offset: 0, index: 1) - encoder.setFragmentTexture(texture, at: 0) - encoder.setFragmentSamplerState(self.colorSamplerState, at: 0) + encoder.setFragmentTexture(texture, index: 0) + encoder.setFragmentSamplerState(self.colorSamplerState, index: 0) encoder.drawPrimitives(type: .point, vertexStart: 0, vertexCount: vertexBuffer.count) encoder.endEncoding() diff --git a/Silvershadow/RenderContentView.swift b/Silvershadow/RenderContentView.swift index 21b17ca..0251d08 100644 --- a/Silvershadow/RenderContentView.swift +++ b/Silvershadow/RenderContentView.swift @@ -24,25 +24,13 @@ class RenderContentView: XView { super.draw(rect) } - #if os(iOS) - override func layoutSubviews() { - super.layoutSubviews() - } - - #elseif os(macOS) - override func layout() { - super.layout() - } - - override var isFlipped: Bool { - return true - } - #endif - - // MARK: - #if os(iOS) + override func layoutSubviews() { + super.layoutSubviews() + } + override func touchesBegan(_ touches: Set, with event: UIEvent?) { renderView?.scene?.touchesBegan(touches, with: event) } @@ -60,6 +48,14 @@ class RenderContentView: XView { } #elseif os(macOS) + override func layout() { + super.layout() + } + + override var isFlipped: Bool { + return true + } + override func mouseDown(with event: NSEvent) { renderView?.scene?.mouseDown(with: event) } diff --git a/Silvershadow/RenderContext.swift b/Silvershadow/RenderContext.swift index 1de2d2c..0c2d845 100644 --- a/Silvershadow/RenderContext.swift +++ b/Silvershadow/RenderContext.swift @@ -82,18 +82,20 @@ class RenderContext { // lazy var shadingTexture: MTLTexture = { - let descriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .`default`, - width: Int(self.deviceSize.width), height: Int(self.deviceSize.height), mipmapped: false) + let descriptor : MTLTextureDescriptor = .texture2DDescriptor(pixelFormat: .`default`, + width: Int(self.deviceSize.width), + height: Int(self.deviceSize.height), + mipmapped: false) descriptor.usage = [.shaderRead, .renderTarget] - return self.device.makeTexture(descriptor: descriptor) + return self.device.makeTexture(descriptor: descriptor)! }() lazy var brushShape: MTLTexture = { - return self.device.texture(of: XImage(named: "Particle")!)! + return self.device.texture(of: XImage(named: .particle)!)! }() lazy var brushPattern: MTLTexture = { - return self.device.texture(of: XImage(named: "Pencil")!)! + return self.device.texture(of: XImage(named: .pencil)!)! }() init( @@ -104,13 +106,16 @@ class RenderContext { transform: GLKMatrix4, zoomScale: CGFloat = 1 ) { - self.current = RenderContextState( - renderPassDescriptor: renderPassDescriptor, commandQueue: commandQueue, - contentSize: contentSize, deviceSize: deviceSize, transform: transform, zoomScale: zoomScale) + self.current = RenderContextState(renderPassDescriptor: renderPassDescriptor, + commandQueue: commandQueue, + contentSize: contentSize, + deviceSize: deviceSize, + transform: transform, + zoomScale: zoomScale) } func makeCommandBuffer() -> MTLCommandBuffer { - return commandQueue.makeCommandBuffer() + return commandQueue.makeCommandBuffer()! } // MARK: - @@ -130,7 +135,7 @@ class RenderContext { extension RenderContext { - func widthCGContext(_ closure: (CGContext) -> ()) { + func withCGContext(_ closure: (CGContext) -> ()) { let (width, height, bytesPerRow) = (Int(contentSize.width), Int(contentSize.height), Int(contentSize.width) * 4) let colorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue) @@ -147,9 +152,9 @@ extension RenderContext { #if os(iOS) UIGraphicsPushContext(context) #elseif os(macOS) - let savedContext = NSGraphicsContext.current() + let savedContext = NSGraphicsContext.current let graphicsContext = NSGraphicsContext(cgContext: context, flipped: false) - NSGraphicsContext.setCurrent(graphicsContext) + NSGraphicsContext.current = graphicsContext #endif closure(context) @@ -157,7 +162,7 @@ extension RenderContext { #if os(iOS) UIGraphicsPopContext() #elseif os(macOS) - NSGraphicsContext.setCurrent(savedContext) + NSGraphicsContext.current = savedContext #endif context.restoreGState() diff --git a/Silvershadow/RenderView.swift b/Silvershadow/RenderView.swift index f14b7b3..c8cc44d 100644 --- a/Silvershadow/RenderView.swift +++ b/Silvershadow/RenderView.swift @@ -19,62 +19,16 @@ class RenderView: XView, MTKViewDelegate { var scene: Scene? { didSet { - if scene !== oldValue { - if let scene = scene { - self.mtkView.device = scene.device - self.commandQueue = scene.device.makeCommandQueue() - scene.didMove(to: self) - } - self.setNeedsLayout() // implies adjusting document - } + guard scene !== oldValue else { return } + if let scene = scene { + self.mtkView.device = scene.device + self.commandQueue = scene.device.makeCommandQueue() + scene.didMove(to: self) + } + self.setNeedsLayout() // implies adjusting document } } - #if os(iOS) - override func layoutSubviews() { - super.layoutSubviews() - - self.sendSubview(toBack: self.mtkView) - self.bringSubview(toFront: self.drawView) - self.bringSubview(toFront: self.scrollView) - - if let scene = self.scene { - let contentSize = scene.contentSize - self.scrollView.contentSize = contentSize -// self.contentView.bounds = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height) - let bounds = CGRect(size: contentSize) - let frame = self.scrollView.convert(bounds, to: self.contentView) - self.contentView.frame = frame - } - else { - self.scrollView.contentSize = self.bounds.size - self.contentView.bounds = self.bounds - } - self.scrollView.autoresizesSubviews = false; - self.contentView.translatesAutoresizingMaskIntoConstraints = false - self.contentView.autoresizingMask = [] - self.contentView.autoresizingMask = [.flexibleRightMargin, .flexibleBottomMargin] - self.setNeedsDisplay() - } - - #elseif os(macOS) - override func layout() { - super.layout() - - self.sendSubview(toBack: self.mtkView) - self.bringSubview(toFront: self.drawView) - self.bringSubview(toFront: self.scrollView) - - let contentSize = scene?.contentSize ?? bounds.size - - self.scrollView.documentView?.frame = CGRect(size: contentSize) - - self.contentView.translatesAutoresizingMaskIntoConstraints = false - self.contentView.autoresizingMask = [.viewMaxXMargin, /*.viewMinYMargin,*/ .viewMaxYMargin] - self.setNeedsDisplay() - } - #endif - private (set) lazy var mtkView: MTKView = { let mtkView = MTKView(frame: self.bounds) mtkView.device = MTLCreateSystemDefaultDevice()! @@ -90,7 +44,7 @@ class RenderView: XView, MTKViewDelegate { private (set) lazy var scrollView: UIScrollView = { let scrollView = UIScrollView(frame: self.bounds) scrollView.delegate = self - scrollView.backgroundColor = UIColor.clear + scrollView.backgroundColor = .clear scrollView.maximumZoomScale = 4.0 scrollView.minimumZoomScale = 1.0 scrollView.autoresizesSubviews = false @@ -102,6 +56,53 @@ class RenderView: XView, MTKViewDelegate { return scrollView }() + override func setNeedsDisplay() { + super.setNeedsDisplay() + self.mtkView.setNeedsDisplay() + self.drawView.setNeedsDisplay() + } + + var minimumNumberOfTouchesToScroll: Int { + get { return self.scrollView.panGestureRecognizer.minimumNumberOfTouches } + set { self.scrollView.panGestureRecognizer.minimumNumberOfTouches = newValue } + } + + var scrollEnabled: Bool { + get { return self.scrollView.isScrollEnabled } + set { self.scrollView.isScrollEnabled = newValue } + } + + var delaysContentTouches: Bool { + get { return self.scrollView.delaysContentTouches } + set { self.scrollView.delaysContentTouches = newValue } + } + + override func layoutSubviews() { + super.layoutSubviews() + + self.sendSubview(toBack: self.mtkView) + self.bringSubview(toFront: self.drawView) + self.bringSubview(toFront: self.scrollView) + + if let scene = self.scene { + let contentSize = scene.contentSize + self.scrollView.contentSize = contentSize + // self.contentView.bounds = CGRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height) + let bounds = CGRect(size: contentSize) + let frame = self.scrollView.convert(bounds, to: self.contentView) + self.contentView.frame = frame + } + else { + self.scrollView.contentSize = self.bounds.size + self.contentView.bounds = self.bounds + } + self.scrollView.autoresizesSubviews = false; + self.contentView.translatesAutoresizingMaskIntoConstraints = false + self.contentView.autoresizingMask = [] + self.contentView.autoresizingMask = [.flexibleRightMargin, .flexibleBottomMargin] + self.setNeedsDisplay() + } + #elseif os(macOS) private (set) lazy var scrollView: NSScrollView = { let scrollView = NSScrollView(frame: self.bounds) @@ -123,8 +124,8 @@ class RenderView: XView, MTKViewDelegate { // posting notification when zoomed, scrolled or resized - NotificationCenter.default.addObserver(self, selector: #selector(RenderView.scrollContentDidChange), - name: .NSViewBoundsDidChange, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(scrollContentDidChange), + name: NSView.boundsDidChangeNotification, object: nil) scrollView.allowsMagnification = true scrollView.maxMagnification = 4 scrollView.minMagnification = 1 @@ -141,6 +142,31 @@ class RenderView: XView, MTKViewDelegate { // self.drawView.setNeedsDisplay() self.mtkView.setNeedsDisplay() } + + override func setNeedsDisplay() { + self.mtkView.setNeedsDisplay() + self.drawView.setNeedsDisplay() + } + + override var isFlipped: Bool { + return true + } + + override func layout() { + super.layout() + + self.sendSubview(toBack: self.mtkView) + self.bringSubview(toFront: self.drawView) + self.bringSubview(toFront: self.scrollView) + + let contentSize = scene?.contentSize ?? bounds.size + + self.scrollView.documentView?.frame = CGRect(size: contentSize) + + self.contentView.translatesAutoresizingMaskIntoConstraints = false + self.contentView.autoresizingMask = [.maxXMargin, /*.viewMinYMargin,*/ .maxYMargin] + self.setNeedsDisplay() + } #endif private (set) lazy var drawView: RenderDrawView = { @@ -170,26 +196,6 @@ class RenderView: XView, MTKViewDelegate { // MARK: - - #if os(iOS) - override func setNeedsDisplay() { - super.setNeedsDisplay() - self.mtkView.setNeedsDisplay() - self.drawView.setNeedsDisplay() - } - #elseif os(macOS) - override func setNeedsDisplay() { - self.mtkView.setNeedsDisplay() - self.drawView.setNeedsDisplay() - } - - override var isFlipped: Bool { - return true - } - - #endif - - // MARK: - - let semaphore = DispatchSemaphore(value: 1) func draw(in view: MTKView) { @@ -216,8 +222,8 @@ class RenderView: XView, MTKViewDelegate { // just for clearing screen do { - let commandBuffer = commandQueue.makeCommandBuffer() - let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) + let commandBuffer = commandQueue.makeCommandBuffer()! + let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)! commandEncoder.endEncoding() commandBuffer.commit() } @@ -225,16 +231,18 @@ class RenderView: XView, MTKViewDelegate { // setup render context let transform = GLKMatrix4(self.drawingTransform) renderPassDescriptor.colorAttachments[0].loadAction = .load - let renderContext = RenderContext( - renderPassDescriptor: renderPassDescriptor, commandQueue: commandQueue, - contentSize: scene.contentSize, deviceSize: self.mtkView.drawableSize, - transform: transform, zoomScale: self.zoomScale) + let renderContext = RenderContext(renderPassDescriptor: renderPassDescriptor, + commandQueue: commandQueue, + contentSize: scene.contentSize, + deviceSize: self.mtkView.drawableSize, + transform: transform, + zoomScale: self.zoomScale) // actual rendering scene.render(in: renderContext) do { - let commandBuffer = commandQueue.makeCommandBuffer() + let commandBuffer = commandQueue.makeCommandBuffer()! commandBuffer.present(drawable) commandBuffer.commit() } @@ -247,13 +255,15 @@ class RenderView: XView, MTKViewDelegate { var drawingTransform: CGAffineTransform { guard let scene = self.scene else { return .identity } let targetRect = contentView.convert(self.contentView.bounds, to: self.mtkView) - let transform0 = CGAffineTransform(translationX: 0, y: self.contentView.bounds.height).scaledBy(x: 1, y: -1) + let transform1 = scene.bounds.transform(to: targetRect) let transform2 = self.mtkView.bounds.transform(to: CGRect(x: -1.0, y: -1.0, width: 2.0, height: 2.0)) - let transform3 = CGAffineTransform.identity.translatedBy(x: 0, y: +1).scaledBy(x: 1, y: -1).translatedBy(x: 0, y: 1) + #if os(iOS) + let transform3 = CGAffineTransform.identity.translatedBy(x: 0, y: +1).scaledBy(x: 1, y: -1).translatedBy(x: 0, y: 1) let transform = transform1 * transform2 * transform3 #elseif os(macOS) + let transform0 = CGAffineTransform(translationX: 0, y: self.contentView.bounds.height).scaledBy(x: 1, y: -1) let transform = transform0 * transform1 * transform2 #endif return transform @@ -261,25 +271,6 @@ class RenderView: XView, MTKViewDelegate { func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) { } - - // MARK: - - - #if os(iOS) - var minimumNumberOfTouchesToScroll: Int { - get { return self.scrollView.panGestureRecognizer.minimumNumberOfTouches } - set { self.scrollView.panGestureRecognizer.minimumNumberOfTouches = newValue } - } - - var scrollEnabled: Bool { - get { return self.scrollView.isScrollEnabled } - set { self.scrollView.isScrollEnabled = newValue } - } - - var delaysContentTouches: Bool { - get { return self.scrollView.delaysContentTouches } - set { self.scrollView.delaysContentTouches = newValue } - } - #endif } #if os(iOS) diff --git a/Silvershadow/Renderable.swift b/Silvershadow/Renderable.swift index 699d550..e47bfee 100644 --- a/Silvershadow/Renderable.swift +++ b/Silvershadow/Renderable.swift @@ -20,8 +20,7 @@ protocol Renderable: class { extension Renderable { var renderer: RendererType { - let renderer = self.device.renderer() as RendererType - return renderer + return self.device.renderer() as RendererType } } diff --git a/Silvershadow/Renderer.swift b/Silvershadow/Renderer.swift index 006bdff..1e9e709 100644 --- a/Silvershadow/Renderer.swift +++ b/Silvershadow/Renderer.swift @@ -21,7 +21,7 @@ protocol Renderer: class { extension Renderer { var library: MTLLibrary { - return self.device.newDefaultLibrary()! + return self.device.makeDefaultLibrary()! } } diff --git a/Silvershadow/VertexBuffer.swift b/Silvershadow/VertexBuffer.swift index f98f462..e1cdc96 100644 --- a/Silvershadow/VertexBuffer.swift +++ b/Silvershadow/VertexBuffer.swift @@ -27,7 +27,7 @@ class VertexBuffer { let capacity = capacity ?? vertices.count let length = MemoryLayout.stride * capacity self.capacity = capacity - self.buffer = device.makeBuffer(bytes: vertices, length: length, options: [.storageModeShared]) // !?! + self.buffer = device.makeBuffer(bytes: vertices, length: length, options: [.storageModeShared])! // !?! } deinit { @@ -45,7 +45,7 @@ class VertexBuffer { else { let count = self.count let length = MemoryLayout.stride * (count + vertices.count) - let buffer = self.device.makeBuffer(length: length, options: [.storageModeShared]) + let buffer = self.device.makeBuffer(length: length, options: [.storageModeShared])! let sourceArrayPtr = UnsafeMutablePointer(OpaquePointer(self.buffer.contents())) let sourceArray = UnsafeMutableBufferPointer(start: sourceArrayPtr, count: count) let destinationArrayPtr = UnsafeMutablePointer(OpaquePointer(buffer.contents())) @@ -70,7 +70,7 @@ class VertexBuffer { } else { let bytes = MemoryLayout.size * vertices.count - let buffer = device.makeBuffer(bytes: vertices, length: bytes, options: [.storageModeShared]) + let buffer = device.makeBuffer(bytes: vertices, length: bytes, options: [.storageModeShared])! self.count = vertices.count self.capacity = vertices.count self.buffer = buffer diff --git a/SilvershadowApp_mac/AppDelegate.swift b/SilvershadowApp_mac/AppDelegate.swift index 415bcf8..fc90184 100644 --- a/SilvershadowApp_mac/AppDelegate.swift +++ b/SilvershadowApp_mac/AppDelegate.swift @@ -17,7 +17,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { - let app = NSApplication.shared() + let app = NSApplication.shared if let sampleSceneAction = sampleCanvasMenuItem.action { app.sendAction(sampleSceneAction, to: app, from: sampleCanvasMenuItem) }