From 53b9f5e97b14f202a7ba6a69d3ab4bcb34929efd Mon Sep 17 00:00:00 2001 From: Brad Root Date: Sun, 30 Jan 2022 18:59:49 -0800 Subject: [PATCH 1/3] move public functions up in file --- Shared/Scene/Animations.swift | 96 ++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/Shared/Scene/Animations.swift b/Shared/Scene/Animations.swift index 446b5de..54534fc 100644 --- a/Shared/Scene/Animations.swift +++ b/Shared/Scene/Animations.swift @@ -60,6 +60,54 @@ class Animation { } + // Static methods for queuing animations + + static func spinBothHands(by degrees: CGFloat) -> Animation { + let animation = Animation(animation: .spinBothHands) + animation.degrees = degrees + return animation + } + + static func printString(string: String) -> Animation { + let animation = Animation(animation: .print) + animation.string = string + return animation + } + + static func currentTimePrint() -> Animation { + return Animation(animation: .currentTimePrint) + } + + static func currentTimeClock() -> Animation { + return Animation(animation: .currentTimeClock) + } + + static func wait(duration: TimeInterval) -> Animation { + let animation = Animation(animation: .wait) + animation.duration = duration + return animation + } + + static func positionBothHands(minuteDegrees: CGFloat, hourDegrees: CGFloat) -> Animation { + let animation = Animation(animation: .positionBothHands) + animation.minuteDegrees = minuteDegrees + animation.hourDegrees = hourDegrees + return animation + } + + static func spinBothHandsWithDelay(by degrees: CGFloat, delay: TimeInterval) -> Animation { + let animation = Animation(animation: .spinBothHandsWithDelay) + animation.degrees = degrees + animation.delay = delay + return animation + } + + static func display(pattern: [Int: [(CGFloat, CGFloat)]]) -> Animation { + let animation = Animation(animation: .displayPattern) + animation.pattern = pattern + return animation + } + // Animations private func wait(clocks: [ClockNode]) -> SKAction { @@ -273,53 +321,7 @@ class Animation { return distanceInDegrees.degreesToRadians() } - // Static methods for queuing animations - - static func spinBothHands(by degrees: CGFloat) -> Animation { - let animation = Animation(animation: .spinBothHands) - animation.degrees = degrees - return animation - } - - static func printString(string: String) -> Animation { - let animation = Animation(animation: .print) - animation.string = string - return animation - } - - static func currentTimePrint() -> Animation { - return Animation(animation: .currentTimePrint) - } - - static func currentTimeClock() -> Animation { - return Animation(animation: .currentTimeClock) - } - - static func wait(duration: TimeInterval) -> Animation { - let animation = Animation(animation: .wait) - animation.duration = duration - return animation - } - - static func positionBothHands(minuteDegrees: CGFloat, hourDegrees: CGFloat) -> Animation { - let animation = Animation(animation: .positionBothHands) - animation.minuteDegrees = minuteDegrees - animation.hourDegrees = hourDegrees - return animation - } - - static func spinBothHandsWithDelay(by degrees: CGFloat, delay: TimeInterval) -> Animation { - let animation = Animation(animation: .spinBothHandsWithDelay) - animation.degrees = degrees - animation.delay = delay - return animation - } - - static func display(pattern: [Int: [(CGFloat, CGFloat)]]) -> Animation { - let animation = Animation(animation: .displayPattern) - animation.pattern = pattern - return animation - } + // Pattern Generators static func randomizedPattern() -> [Int: [(CGFloat, CGFloat)]] { return [ From 37c81234ec470958517db2e1a2a735841d67f71e Mon Sep 17 00:00:00 2001 From: Brad Root Date: Sun, 30 Jan 2022 19:22:56 -0800 Subject: [PATCH 2/3] replace notificationcenter use with completion handlers --- Shared/Scene/Animations.swift | 74 +++++++++++++++--------------- Shared/Scene/ClockController.swift | 4 +- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/Shared/Scene/Animations.swift b/Shared/Scene/Animations.swift index 54534fc..aeeac7e 100644 --- a/Shared/Scene/Animations.swift +++ b/Shared/Scene/Animations.swift @@ -37,25 +37,25 @@ class Animation { animationType = animation } - public func actions(clocks: [ClockNode], clusters: [ClusterNode]) -> SKAction { + public func actions(clocks: [ClockNode], clusters: [ClusterNode], completionHandler: @escaping () -> Void) -> SKAction { switch animationType { case .spinBothHands: - return spinBothHands(clocks: clocks) + return spinBothHands(clocks: clocks, completionHandler: completionHandler) case .currentTimePrint: - return currentTimePrint(clusters: clusters) + return currentTimePrint(clusters: clusters, completionHandler: completionHandler) case .currentTimeClock: - return currentTimeClock(clocks: clocks) + return currentTimeClock(clocks: clocks, completionHandler: completionHandler) case .wait: - return wait(clocks: clocks) + return wait(clocks: clocks, completionHandler: completionHandler) case .positionBothHands: - return positionBothHands(clocks: clocks) + return positionBothHands(clocks: clocks, completionHandler: completionHandler) case .spinBothHandsWithDelay: - return spinBothHandsWithDelay(clusters: clusters) + return spinBothHandsWithDelay(clusters: clusters, completionHandler: completionHandler) case .displayPattern: - return displayPattern(clusters: clusters) + return displayPattern(clusters: clusters, completionHandler: completionHandler) case .print: - return print(clusters: clusters) + return print(clusters: clusters, completionHandler: completionHandler) } } @@ -110,31 +110,31 @@ class Animation { // Animations - private func wait(clocks: [ClockNode]) -> SKAction { + private func wait(clocks: [ClockNode], completionHandler: @escaping () -> Void) -> SKAction { Log.debug("Waiting for \(self.duration) seconds...") var actions: [SKAction] = [] clocks.forEach { clock in actions.append(SKAction.run { let action = SKAction.wait(forDuration: self.duration) clock.run(action) { - NotificationCenter.default.post(name: NSNotification.Name("AnimationComplete"), object: nil) - NotificationCenter.default.post(name: NSNotification.Name("AnimationComplete"), object: nil) + completionHandler() + completionHandler() } }) } return SKAction.group(actions) } - private func positionBothHands(clocks: [ClockNode]) -> SKAction { + private func positionBothHands(clocks: [ClockNode], completionHandler: @escaping () -> Void) -> SKAction { Log.debug("Positioning minute hands to \(self.minuteDegrees), hour hands to \(self.hourDegrees)...") var actions: [SKAction] = [] clocks.forEach { clock in - actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: self.minuteDegrees, hourDegrees: self.hourDegrees)) + actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: self.minuteDegrees, hourDegrees: self.hourDegrees, completionHandler: completionHandler)) } return SKAction.group(actions) } - private func print(clusters: [ClusterNode]) -> SKAction { + private func print(clusters: [ClusterNode], completionHandler: @escaping () -> Void) -> SKAction { var actions: [SKAction] = [] let array = string.map(String.init) @@ -143,7 +143,7 @@ class Animation { if let numberConfig = numberConfigs[Int(array[index])!] { for (index, item) in numberConfig.enumerated() { let clock = cluster.clocks[index] - actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: item.1, hourDegrees: item.0)) + actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: item.1, hourDegrees: item.0, completionHandler: completionHandler)) } } @@ -152,7 +152,7 @@ class Animation { return SKAction.group(actions) } - private func currentTimePrint(clusters: [ClusterNode]) -> SKAction { + private func currentTimePrint(clusters: [ClusterNode], completionHandler: @escaping () -> Void) -> SKAction { let date = Date() let dateFormatter = DateFormatter() dateFormatter.dateFormat = "hhmm" @@ -170,7 +170,7 @@ class Animation { if let numberConfig = numberConfigs[Int(array[index])!] { for (index, item) in numberConfig.enumerated() { let clock = cluster.clocks[index] - actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: item.1, hourDegrees: item.0)) + actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: item.1, hourDegrees: item.0, completionHandler: completionHandler)) } } @@ -181,7 +181,7 @@ class Animation { return SKAction.group(actions) } - private func currentTimeClock(clocks: [ClockNode]) -> SKAction { + private func currentTimeClock(clocks: [ClockNode], completionHandler: @escaping () -> Void) -> SKAction { Log.debug("Displaying current time as clocks...") let date = Date() let minute = Int(date.get(.minute))! @@ -193,21 +193,21 @@ class Animation { var actions: [SKAction] = [] clocks.forEach { clock in - actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: -CGFloat(((360/60)*minute)), hourDegrees: -CGFloat(((360/12)*hourFloat)))) + actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: -CGFloat(((360/60)*minute)), hourDegrees: -CGFloat(((360/12)*hourFloat)), completionHandler: completionHandler)) } return SKAction.group(actions) } - private func spinBothHands(clocks: [ClockNode]) -> SKAction { + private func spinBothHands(clocks: [ClockNode], completionHandler: @escaping () -> Void) -> SKAction { Log.debug("Spinning all hands \(self.degrees) degrees...") var actions: [SKAction] = [] clocks.forEach { clock in - actions.append(getActionGroupForSpin(clock: clock, degrees: self.degrees)) + actions.append(getActionGroupForSpin(clock: clock, degrees: self.degrees, completionHandler: completionHandler)) } return SKAction.group(actions) } - private func spinBothHandsWithDelay(clusters: [ClusterNode]) -> SKAction { + private func spinBothHandsWithDelay(clusters: [ClusterNode], completionHandler: @escaping () -> Void) -> SKAction { Log.debug("Spinning all hands \(self.degrees) degrees, with \(self.delay) seconds delay...") var actions: [SKAction] = [] var currentDelay: TimeInterval = 0 @@ -215,9 +215,9 @@ class Animation { clusters.forEach { cluster in var clockActions: [SKAction] = [] - clockActions.append(getActionGroupForSpin(clock: cluster.clocks[0], degrees: self.degrees)) - clockActions.append(getActionGroupForSpin(clock: cluster.clocks[2], degrees: self.degrees)) - clockActions.append(getActionGroupForSpin(clock: cluster.clocks[4], degrees: self.degrees)) + clockActions.append(getActionGroupForSpin(clock: cluster.clocks[0], degrees: self.degrees, completionHandler: completionHandler)) + clockActions.append(getActionGroupForSpin(clock: cluster.clocks[2], degrees: self.degrees, completionHandler: completionHandler)) + clockActions.append(getActionGroupForSpin(clock: cluster.clocks[4], degrees: self.degrees, completionHandler: completionHandler)) actions.append(SKAction.sequence([ SKAction.wait(forDuration: currentDelay), @@ -228,9 +228,9 @@ class Animation { clockActions.removeAll() - clockActions.append(getActionGroupForSpin(clock: cluster.clocks[1], degrees: self.degrees)) - clockActions.append(getActionGroupForSpin(clock: cluster.clocks[3], degrees: self.degrees)) - clockActions.append(getActionGroupForSpin(clock: cluster.clocks[5], degrees: self.degrees)) + clockActions.append(getActionGroupForSpin(clock: cluster.clocks[1], degrees: self.degrees, completionHandler: completionHandler)) + clockActions.append(getActionGroupForSpin(clock: cluster.clocks[3], degrees: self.degrees, completionHandler: completionHandler)) + clockActions.append(getActionGroupForSpin(clock: cluster.clocks[5], degrees: self.degrees, completionHandler: completionHandler)) actions.append(SKAction.sequence([ SKAction.wait(forDuration: currentDelay), @@ -242,7 +242,7 @@ class Animation { return SKAction.group(actions) } - private func displayPattern(clusters: [ClusterNode]) -> SKAction { + private func displayPattern(clusters: [ClusterNode], completionHandler: @escaping () -> Void) -> SKAction { Log.debug("Displaying pattern...") var actions: [SKAction] = [] @@ -251,7 +251,7 @@ class Animation { if let patternConfig = self.pattern[index] { for (index, item) in patternConfig.enumerated() { let clock = cluster.clocks[index] - actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: item.1, hourDegrees: item.0)) + actions.append(getActionGroupForPosition(clock: clock, minuteDegrees: item.1, hourDegrees: item.0, completionHandler: completionHandler)) } } @@ -262,14 +262,14 @@ class Animation { // Utils - private func getActionGroupForPosition(clock: ClockNode, minuteDegrees: CGFloat, hourDegrees: CGFloat) -> SKAction { + private func getActionGroupForPosition(clock: ClockNode, minuteDegrees: CGFloat, hourDegrees: CGFloat, completionHandler: @escaping () -> Void) -> SKAction { let radianDifference = getRadianDifference(startDegrees: clock.minuteHandNode.zRotation.radiansToDegrees(), endDegrees: -minuteDegrees) let duration = radianDifference / movementSpeed let minuteHandAction = SKAction.run { let action = SKAction.rotate(byAngle: -radianDifference, duration: duration) clock.minuteHandNode.run(action) { - NotificationCenter.default.post(name: NSNotification.Name("AnimationComplete"), object: nil) + completionHandler() } } @@ -279,27 +279,27 @@ class Animation { let hourHandAction = SKAction.run { let action = SKAction.rotate(byAngle: -radianDifferenceHour, duration: durationHour) clock.hourHandNode.run(action) { - NotificationCenter.default.post(name: NSNotification.Name("AnimationComplete"), object: nil) + completionHandler() } } return SKAction.group([minuteHandAction, hourHandAction]) } - private func getActionGroupForSpin(clock: ClockNode, degrees: CGFloat) -> SKAction { + private func getActionGroupForSpin(clock: ClockNode, degrees: CGFloat, completionHandler: @escaping () -> Void) -> SKAction { let radians = degrees.degreesToRadians() let minuteHandAction = SKAction.run { let action = SKAction.rotate(byAngle: -radians, duration: radians / self.movementSpeed) clock.minuteHandNode.run(action) { - NotificationCenter.default.post(name: NSNotification.Name("AnimationComplete"), object: nil) + completionHandler() } } let hourHandAction = SKAction.run { let action = SKAction.rotate(byAngle: -radians, duration: radians / self.movementSpeed) clock.hourHandNode.run(action) { - NotificationCenter.default.post(name: NSNotification.Name("AnimationComplete"), object: nil) + completionHandler() } } return SKAction.group([minuteHandAction, hourHandAction]) diff --git a/Shared/Scene/ClockController.swift b/Shared/Scene/ClockController.swift index f1a0a63..5f36f44 100644 --- a/Shared/Scene/ClockController.swift +++ b/Shared/Scene/ClockController.swift @@ -53,8 +53,6 @@ class ClockController { updateInterval = TimeInterval(1) - NotificationCenter.default.addObserver(self, selector: #selector(animationCompleted), name: NSNotification.Name("AnimationComplete"), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(setCurrentTime(_:)), name: NSNotification.Name("SetCurrentTime"), object: nil) } @@ -237,7 +235,7 @@ class ClockController { } private func run(_ animation: Animation) { - let actionGroup = animation.actions(clocks: clocks, clusters: clusters) + let actionGroup = animation.actions(clocks: clocks, clusters: clusters, completionHandler: animationCompleted) isAnimating = true timeSinceLastAnimation = 0 scene?.run(actionGroup) From 2a326600ecc0aa3bc51479e8bb45501557986fe2 Mon Sep 17 00:00:00 2001 From: Brad Root Date: Sun, 30 Jan 2022 19:30:38 -0800 Subject: [PATCH 3/3] replace set current time notification with a completion handler --- Shared/Scene/Animations.swift | 8 ++++---- Shared/Scene/ClockController.swift | 23 ++++++++++------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/Shared/Scene/Animations.swift b/Shared/Scene/Animations.swift index aeeac7e..b85f2f5 100644 --- a/Shared/Scene/Animations.swift +++ b/Shared/Scene/Animations.swift @@ -37,13 +37,13 @@ class Animation { animationType = animation } - public func actions(clocks: [ClockNode], clusters: [ClusterNode], completionHandler: @escaping () -> Void) -> SKAction { + public func actions(clocks: [ClockNode], clusters: [ClusterNode], completionHandler: @escaping () -> Void, timeSetCompletionHandler: @escaping (String) -> Void) -> SKAction { switch animationType { case .spinBothHands: return spinBothHands(clocks: clocks, completionHandler: completionHandler) case .currentTimePrint: - return currentTimePrint(clusters: clusters, completionHandler: completionHandler) + return currentTimePrint(clusters: clusters, completionHandler: completionHandler, timeSetCompletionHandler: timeSetCompletionHandler) case .currentTimeClock: return currentTimeClock(clocks: clocks, completionHandler: completionHandler) case .wait: @@ -152,7 +152,7 @@ class Animation { return SKAction.group(actions) } - private func currentTimePrint(clusters: [ClusterNode], completionHandler: @escaping () -> Void) -> SKAction { + private func currentTimePrint(clusters: [ClusterNode], completionHandler: @escaping () -> Void, timeSetCompletionHandler: @escaping (String) -> Void) -> SKAction { let date = Date() let dateFormatter = DateFormatter() dateFormatter.dateFormat = "hhmm" @@ -176,7 +176,7 @@ class Animation { } - NotificationCenter.default.post(name: NSNotification.Name("SetCurrentTime"), object: nil, userInfo: ["time": timeString]) + timeSetCompletionHandler(timeString) return SKAction.group(actions) } diff --git a/Shared/Scene/ClockController.swift b/Shared/Scene/ClockController.swift index 5f36f44..9796965 100644 --- a/Shared/Scene/ClockController.swift +++ b/Shared/Scene/ClockController.swift @@ -52,8 +52,6 @@ class ClockController { Log.useEmoji = true updateInterval = TimeInterval(1) - - NotificationCenter.default.addObserver(self, selector: #selector(setCurrentTime(_:)), name: NSNotification.Name("SetCurrentTime"), object: nil) } public func start() { @@ -69,15 +67,6 @@ class ClockController { // MARK: - Timer - @objc func setCurrentTime(_ notification: NSNotification) { - if let time = notification.userInfo?["time"] as? String { - if time != lastTimeDisplayed { - Log.debug("New displayed time: \(time)") - lastTimeDisplayed = time - } - } - } - @objc func updateTime() { let date = Date() let dateFormatter = DateFormatter() @@ -218,7 +207,7 @@ class ClockController { // MARK: - Animations - @objc func animationCompleted() { + private func animationCompleted() { timeSinceLastAnimation = 0 animationsCompleted += 1 if animationsCompleted == 48 { @@ -234,8 +223,16 @@ class ClockController { } } + + private func setCurrentTime(time: String) { + if time != lastTimeDisplayed { + Log.debug("New displayed time: \(time)") + lastTimeDisplayed = time + } + } + private func run(_ animation: Animation) { - let actionGroup = animation.actions(clocks: clocks, clusters: clusters, completionHandler: animationCompleted) + let actionGroup = animation.actions(clocks: clocks, clusters: clusters, completionHandler: animationCompleted, timeSetCompletionHandler: setCurrentTime) isAnimating = true timeSinceLastAnimation = 0 scene?.run(actionGroup)