diff --git a/Metaballs.xcodeproj/project.pbxproj b/Metaballs.xcodeproj/project.pbxproj index dee73da..1eb5e84 100644 --- a/Metaballs.xcodeproj/project.pbxproj +++ b/Metaballs.xcodeproj/project.pbxproj @@ -13,6 +13,9 @@ C0B906E01F455AD000B5F89B /* MetaballsSaverView.m in Sources */ = {isa = PBXBuildFile; fileRef = C0B906DF1F455AD000B5F89B /* MetaballsSaverView.m */; }; C0B906E51F455B7C00B5F89B /* Renderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0BBE3AB1F2E941200E68524 /* Renderer.swift */; }; C0B906E61F455B7E00B5F89B /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = C0BBE3A91F2E91D900E68524 /* Shaders.metal */; }; + C0B906E71F455C2F00B5F89B /* MetaballsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0BBE38C1F2E81B600E68524 /* MetaballsKit.framework */; }; + C0B906E91F455D1A00B5F89B /* MetaballsSaverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0B906E81F455D1A00B5F89B /* MetaballsSaverView.swift */; }; + C0B906EA1F455EB300B5F89B /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0BBE3A71F2E893A00E68524 /* MetalKit.framework */; }; C0BBE36B1F2E816500E68524 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0BBE36A1F2E816500E68524 /* AppDelegate.swift */; }; C0BBE36D1F2E816500E68524 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0BBE36C1F2E816500E68524 /* ViewController.swift */; }; C0BBE36F1F2E816500E68524 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C0BBE36E1F2E816500E68524 /* Assets.xcassets */; }; @@ -53,6 +56,7 @@ C0B906DD1F455AD000B5F89B /* MetaballsSaverView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MetaballsSaverView.h; sourceTree = ""; }; C0B906DF1F455AD000B5F89B /* MetaballsSaverView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MetaballsSaverView.m; sourceTree = ""; }; C0B906E11F455AD000B5F89B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + C0B906E81F455D1A00B5F89B /* MetaballsSaverView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MetaballsSaverView.swift; sourceTree = ""; }; C0BBE3671F2E816500E68524 /* Metaballs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metaballs.app; sourceTree = BUILT_PRODUCTS_DIR; }; C0BBE36A1F2E816500E68524 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C0BBE36C1F2E816500E68524 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -81,6 +85,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + C0B906EA1F455EB300B5F89B /* MetalKit.framework in Frameworks */, + C0B906E71F455C2F00B5F89B /* MetaballsKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -124,6 +130,7 @@ children = ( C0B906DD1F455AD000B5F89B /* MetaballsSaverView.h */, C0B906DF1F455AD000B5F89B /* MetaballsSaverView.m */, + C0B906E81F455D1A00B5F89B /* MetaballsSaverView.swift */, C0B906E11F455AD000B5F89B /* Info.plist */, ); path = MetaballsSaver; @@ -332,6 +339,7 @@ C0B906DA1F455AD000B5F89B = { CreatedOnToolsVersion = 8.3.3; DevelopmentTeam = 78372RE6B4; + LastSwiftMigration = 0830; ProvisioningStyle = Automatic; }; C0BBE3661F2E816500E68524 = { @@ -425,6 +433,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C0B906E91F455D1A00B5F89B /* MetaballsSaverView.swift in Sources */, C0B906E01F455AD000B5F89B /* MetaballsSaverView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -498,12 +507,16 @@ C0B906E31F455AD000B5F89B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 78372RE6B4; INFOPLIST_FILE = MetaballsSaver/Info.plist; INSTALL_PATH = "$(HOME)/Library/Screen Savers"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.erynwells.MetaballsSaver; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; WRAPPER_EXTENSION = saver; }; name = Debug; @@ -511,12 +524,15 @@ C0B906E41F455AD000B5F89B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = 78372RE6B4; INFOPLIST_FILE = MetaballsSaver/Info.plist; INSTALL_PATH = "$(HOME)/Library/Screen Savers"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.erynwells.MetaballsSaver; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; WRAPPER_EXTENSION = saver; }; name = Release; diff --git a/MetaballsSaver/MetaballsSaverView.h b/MetaballsSaver/MetaballsSaverView.h index 3b185be..ccc1a6b 100644 --- a/MetaballsSaver/MetaballsSaverView.h +++ b/MetaballsSaver/MetaballsSaverView.h @@ -8,6 +8,6 @@ #import -@interface MetaballsSaverView : ScreenSaverView +@interface MetaballsSaverViewX : ScreenSaverView @end diff --git a/MetaballsSaver/MetaballsSaverView.m b/MetaballsSaver/MetaballsSaverView.m index 0fd2a7c..ee718ca 100644 --- a/MetaballsSaver/MetaballsSaverView.m +++ b/MetaballsSaver/MetaballsSaverView.m @@ -6,9 +6,11 @@ // Copyright © 2017 Eryn Wells. All rights reserved. // +@import MetaballsKit; + #import "MetaballsSaverView.h" -@implementation MetaballsSaverView +@implementation MetaballsSaverViewX - (instancetype)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview { diff --git a/MetaballsSaver/MetaballsSaverView.swift b/MetaballsSaver/MetaballsSaverView.swift new file mode 100644 index 0000000..2ba7537 --- /dev/null +++ b/MetaballsSaver/MetaballsSaverView.swift @@ -0,0 +1,97 @@ +// +// MetaballsSaverView.swift +// Metaballs +// +// Created by Eryn Wells on 8/16/17. +// Copyright © 2017 Eryn Wells. All rights reserved. +// + +import Foundation +import MetaballsKit +import MetalKit +import ScreenSaver + +class MetaballsSaverView: ScreenSaverView, RendererDelegate { + private static func defaultParameters() -> Parameters { + var p = Parameters() + let defaults = UserDefaults.standard + let style = defaults.colorStyle ?? .gradient2Horizontal + p.colorStyle = style + let color0 = defaults.color0 ?? Float4(0.50, 0.79, 1, 1) + p.color0 = color0 + let color1 = defaults.color1 ?? Float4(0.88, 0.50, 1, 1) + p.color1 = color1 + return p + } + + public var metalView: MTKView + + public var field: Field { + didSet { + field.size = Size(size: metalView.drawableSize) + } + } + + internal var renderer: RendererDelegate + + override init?(frame: NSRect, isPreview: Bool) { + let params = MetaballsSaverView.defaultParameters() + field = Field(parameters: params) + + metalView = MTKView() + metalView.translatesAutoresizingMaskIntoConstraints = false + addSubview(metalView) + NSLayoutConstraint.activate([ + metalView.topAnchor.constraint(equalTo: topAnchor), + metalView.leftAnchor.constraint(equalTo: leftAnchor), + metalView.bottomAnchor.constraint(equalTo: bottomAnchor), + metalView.rightAnchor.constraint(equalTo: rightAnchor), + ]) + + do { + renderer = try Renderer(delegate: self) + } catch let e { + fatalError("\(e)") + } + + super.init(frame: frame, isPreview: isPreview) + } + + required init?(coder: NSCoder) { + let params = MetaballsSaverView.defaultParameters() + field = Field(parameters: params) + + metalView = MTKView() + metalView.translatesAutoresizingMaskIntoConstraints = false + addSubview(metalView) + NSLayoutConstraint.activate([ + metalView.topAnchor.constraint(equalTo: topAnchor), + metalView.leftAnchor.constraint(equalTo: leftAnchor), + metalView.bottomAnchor.constraint(equalTo: bottomAnchor), + metalView.rightAnchor.constraint(equalTo: rightAnchor), + ]) + + do { + renderer = try Renderer(delegate: self) + } catch let e { + fatalError("\(e)") + } + + super.init(coder: coder) + } + + override func animateOneFrame() { + + } + + // MARK: - RendererDelegate + + public var renderSize: Size { + get { + return field.size + } + set { + field.size = newValue + } + } +}