Skip to content

Commit

Permalink
Add Random Color Preset Option (#12)
Browse files Browse the repository at this point in the history
* run swiftformat

* add swiftlint to macOS build

* update pods

* refactor presets and add support for random color preset

* when "extra death" occurs, fade color back to bg color

* fix bug with extra death animations

* setup random color preset option

* implement random color preset in screensaver

* add missing license excerpts

* run swiftformat again

* add tooltip for random preset checkbox and adjust spacing

* add version number to settings screen
  • Loading branch information
amiantos authored Jun 22, 2019
1 parent 1c3b1da commit 6cbf3c0
Show file tree
Hide file tree
Showing 50 changed files with 1,762 additions and 184 deletions.
5 changes: 4 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ excluded: # paths to ignore during linting. Takes precedence over `included`.

line_length:
- 150 # warning
- 200 # error
- 200 # error

cyclomatic_complexity:
ignores_case_statements: true
67 changes: 50 additions & 17 deletions Life Saver Screensaver/Configuration/ConfigureSheet.xib

Large diffs are not rendered by default.

119 changes: 58 additions & 61 deletions Life Saver Screensaver/Configuration/ConfigureSheetController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Created by Brad Root on 5/21/19.
// Copyright © 2019 Brad Root. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import Cocoa
import SpriteKit
Expand All @@ -14,7 +17,7 @@ final class ConfigureSheetController: NSObject {

// MARK: - Presets

fileprivate let presets: [LifeSettings] = lifePresets
fileprivate let presets: [LifePreset] = lifePresets

// MARK: - Config Actions and Outlets

Expand All @@ -24,14 +27,38 @@ final class ConfigureSheetController: NSObject {
@IBAction func stylePresetsAction(_ sender: NSSegmentedControl) {
switch sender.selectedSegment {
case 0:
let simulationSettings = LifeSettings(title: "Simulation", appearanceMode: nil, squareSize: .small, animationSpeed: .fast, color1: nil, color2: nil, color3: nil)
setupFields(with: simulationSettings)
let simulationSettings = LifePreset(
title: "Simulation",
appearanceMode: nil,
squareSize: .small,
animationSpeed: .fast,
color1: nil,
color2: nil,
color3: nil
)
loadPreset(simulationSettings)
case 2:
let abstractSettings = LifeSettings(title: "Abstract", appearanceMode: nil, squareSize: .large, animationSpeed: .slow, color1: nil, color2: nil, color3: nil)
setupFields(with: abstractSettings)
let abstractSettings = LifePreset(
title: "Abstract",
appearanceMode: nil,
squareSize: .large,
animationSpeed: .slow,
color1: nil,
color2: nil,
color3: nil
)
loadPreset(abstractSettings)
default:
let defaultSettings = LifeSettings(title: "Defaults", appearanceMode: nil, squareSize: .medium, animationSpeed: .normal, color1: nil, color2: nil, color3: nil)
setupFields(with: defaultSettings)
let defaultSettings = LifePreset(
title: "Defaults",
appearanceMode: nil,
squareSize: .medium,
animationSpeed: .normal,
color1: nil,
color2: nil,
color3: nil
)
loadPreset(defaultSettings)
}
}

Expand All @@ -40,7 +67,7 @@ final class ConfigureSheetController: NSObject {
guard let title = sender.titleOfSelectedItem else { return }
let soughtPreset = presets.filter { $0.title == title }.first
if let preset = soughtPreset {
setupFields(with: preset)
loadPreset(preset)
}
}

Expand Down Expand Up @@ -98,6 +125,12 @@ final class ConfigureSheetController: NSObject {
updateColorPresetsControl()
}

@IBOutlet var randomColorPresetCheck: NSButton!
@IBAction func randomColorPresetAction(_ sender: NSButtonCell) {
manager.setRandomColorPreset(sender.state == .on ? true : false)
updateColorPresetsControl()
}

@IBAction func twitterAction(_: NSButton) {
URLType.twitter.open()
}
Expand Down Expand Up @@ -126,10 +159,13 @@ final class ConfigureSheetController: NSObject {
let myBundle = Bundle(for: ConfigureSheetController.self)
myBundle.loadNibNamed("ConfigureSheet", owner: self, topLevelObjects: nil)

setupFields()
randomColorPresetCheck.toolTip = "Enable this to have a random color preset selected each time the screensaver loads."

loadPresets()
loadSettings()
}

fileprivate func setupFields() {
fileprivate func loadSettings() {
switch manager.appearanceMode {
case .dark:
appearanceControl.selectedSegment = 0
Expand Down Expand Up @@ -163,12 +199,13 @@ final class ConfigureSheetController: NSObject {
color2Well.color = manager.color2
color3Well.color = manager.color3

setupPresets()
randomColorPresetCheck.state = manager.randomColorPreset ? .on : .off

updateStylePresetsControl()
updateColorPresetsControl()
}

fileprivate func setupPresets() {
fileprivate func loadPresets() {
presetsButton.removeAllItems()
var presetTitles: [String] = []
for preset in presets {
Expand All @@ -192,56 +229,16 @@ final class ConfigureSheetController: NSObject {
fileprivate func updateColorPresetsControl() {
let filteredPresets = presets.filter { $0.color1 == manager.color1 && $0.color2 == manager.color2 && $0.color3 == manager.color3 }
presetsButton.selectItem(withTitle: filteredPresets.first?.title ?? "Custom")
}

fileprivate func setupFields(with preset: LifeSettings) {
if let appearanceMode = preset.appearanceMode {
switch appearanceMode {
case .dark:
appearanceControl.selectedSegment = 0
case .light:
appearanceControl.selectedSegment = 1
}
manager.setAppearanceMode(appearanceMode)
}
if let squareSize = preset.squareSize {
switch squareSize {
case .small:
squareSizeControl.selectedSegment = 0
case .medium:
squareSizeControl.selectedSegment = 1
case .large:
squareSizeControl.selectedSegment = 2
case .superSmall:
squareSizeControl.selectedSegment = 0
case .verySmall:
squareSizeControl.selectedSegment = 0
}
manager.setSquareSize(squareSize)
}
presetsButton.isEnabled = !manager.randomColorPreset
color1Well.isEnabled = !manager.randomColorPreset
color2Well.isEnabled = !manager.randomColorPreset
color3Well.isEnabled = !manager.randomColorPreset
appearanceControl.isEnabled = !manager.randomColorPreset
}

if let animationSpeed = preset.animationSpeed {
switch animationSpeed {
case .normal:
animationSpeedControl.selectedSegment = 1
case .fast:
animationSpeedControl.selectedSegment = 0
case .slow:
animationSpeedControl.selectedSegment = 2
}
manager.setAnimationSpeed(animationSpeed)
}
if let color1 = preset.color1 {
color1Well.color = color1
manager.setColor(color1, for: .color1)
}
if let color2 = preset.color2 {
color2Well.color = color2
manager.setColor(color2, for: .color2)
}
if let color3 = preset.color3 {
color3Well.color = color3
manager.setColor(color3, for: .color3)
}
fileprivate func loadPreset(_ preset: LifePreset) {
manager.configure(with: preset)
loadSettings()
}
}
15 changes: 14 additions & 1 deletion Life Saver Screensaver/LifeDatabase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Created by Brad Root on 5/21/19.
// Copyright © 2019 Brad Root. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import ScreenSaver
import SpriteKit
Expand All @@ -18,6 +21,7 @@ struct LifeDatabase {
static let color1 = "color1"
static let color2 = "color2"
static let color3 = "color3"
static let randomColorPreset = "randomColorPreset"
}

static var standard: ScreenSaverDefaults {
Expand All @@ -31,7 +35,8 @@ struct LifeDatabase {
Key.squareSize: SquareSize.medium.rawValue,
Key.color1: archiveData(SKColor.defaultColor1),
Key.color2: archiveData(SKColor.defaultColor2),
Key.color3: archiveData(SKColor.defaultColor3)])
Key.color3: archiveData(SKColor.defaultColor3),
Key.randomColorPreset: false])

return database
}
Expand Down Expand Up @@ -62,6 +67,14 @@ extension ScreenSaverDefaults {
set(animationSpeed.rawValue, for: LifeDatabase.Key.animationSpeed)
}

var randomColorPreset: Bool {
return bool(forKey: LifeDatabase.Key.randomColorPreset)
}

func set(randomColorPreset: Bool) {
set(randomColorPreset, for: LifeDatabase.Key.randomColorPreset)
}

func getColor(_ color: Colors) -> SKColor {
switch color {
case .color1:
Expand Down
8 changes: 8 additions & 0 deletions Life Saver Screensaver/LifeScreenSaverView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Created by Bradley Root on 5/18/19.
// Copyright © 2019 Brad Root. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import Foundation
import ScreenSaver
Expand Down Expand Up @@ -50,10 +53,15 @@ final class LifeScreenSaverView: ScreenSaverView {
self.spriteView = spriteView
addSubview(spriteView)

if manager.randomColorPreset, let preset = lifePresets.randomElement() {
manager.configure(with: preset)
}

scene.appearanceMode = manager.appearanceMode
scene.squareSize = manager.squareSize
scene.animationSpeed = manager.animationSpeed
scene.aliveColors = [manager.color1, manager.color2, manager.color3]

scene.isUserInteractionEnabled = false

spriteView.presentScene(scene)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Created by Brad Root on 5/21/19.
// Copyright © 2019 Brad Root. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import Foundation
import ScreenSaver
Expand All @@ -17,6 +20,7 @@ final class LifeManager {
private(set) var color1: SKColor
private(set) var color2: SKColor
private(set) var color3: SKColor
private(set) var randomColorPreset: Bool

init() {
appearanceMode = LifeDatabase.standard.appearanceMode
Expand All @@ -25,6 +29,38 @@ final class LifeManager {
color1 = LifeDatabase.standard.getColor(.color1)
color2 = LifeDatabase.standard.getColor(.color2)
color3 = LifeDatabase.standard.getColor(.color3)
randomColorPreset = LifeDatabase.standard.randomColorPreset
}

func configure(with preset: LifePreset) {
if let appearanceMode = preset.appearanceMode {
setAppearanceMode(appearanceMode)
}

if let squareSize = preset.squareSize {
setSquareSize(squareSize)
}

if let animationSpeed = preset.animationSpeed {
setAnimationSpeed(animationSpeed)
}

if let color1 = preset.color1 {
setColor(color1, for: .color1)
}

if let color2 = preset.color2 {
setColor(color2, for: .color2)
}

if let color3 = preset.color3 {
setColor(color3, for: .color3)
}
}

func setRandomColorPreset(_ randomColorPreset: Bool) {
self.randomColorPreset = randomColorPreset
LifeDatabase.standard.set(randomColorPreset: randomColorPreset)
}

func setAppearanceMode(_ appearanceMode: Appearance) {
Expand Down
14 changes: 11 additions & 3 deletions Life Saver Shared/LifeNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
// Created by Brad Root on 5/23/19.
// Copyright © 2019 Brad Root. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import SpriteKit

Expand All @@ -15,12 +18,14 @@ class LifeNode: SKSpriteNode {
var alive: Bool
var timeInState: Int = 0
var aliveColor: SKColor
var deadColor: SKColor
var neighbors: [LifeNode] = []

init(relativePosition: CGPoint, alive: Bool, color: SKColor, size: CGSize) {
self.relativePosition = relativePosition
self.alive = alive
aliveColor = color
deadColor = color
super.init(texture: squareTexture, color: aliveColor, size: size)
anchorPoint = CGPoint(x: 0, y: 0)
colorBlendFactor = 1
Expand Down Expand Up @@ -54,10 +59,13 @@ class LifeNode: SKSpriteNode {
if !alive {
timeInState += 1

if timeInState >= 50 {
if timeInState == 30 {
removeAllActions()
let fadeAction = SKAction.fadeAlpha(to: 0, duration: duration)
fadeAction.timingMode = .easeIn
run(fadeAction)
let colorAction = SKAction.colorize(with: deadColor, colorBlendFactor: 1, duration: duration)
let actionGroup = SKAction.group([fadeAction, colorAction])
actionGroup.timingMode = .easeIn
run(actionGroup)
}

return
Expand Down
Loading

0 comments on commit 6cbf3c0

Please sign in to comment.