From 460e103f738b229705615a6220511f2e4ed6a50d Mon Sep 17 00:00:00 2001 From: workinghard Date: Sat, 11 Apr 2015 21:18:15 -0700 Subject: [PATCH] a --- Cube4Fun/Animations.swift | 230 ++++++++++++++++++ Cube4Fun/AnimationsController.swift | 99 ++++---- Cube4Fun/AppDelegate.swift | 4 + Cube4Fun/Base.lproj/MainMenu.xib | 12 +- Cube4Fun/GameView.swift | 120 +++++---- Cube4Fun/GameViewController.swift | 26 +- .../AppIcon.appiconset/Contents.json | 14 +- .../AppIcon.appiconset/Cube6-128j.png | Bin 0 -> 25579 bytes .../AppIcon.appiconset/Cube6-16j.png | Bin 0 -> 23590 bytes .../AppIcon.appiconset/Cube6-256j-1.png | Bin 0 -> 27633 bytes .../AppIcon.appiconset/Cube6-256j.png | Bin 0 -> 27633 bytes .../AppIcon.appiconset/Cube6-32j-1.png | Bin 0 -> 24046 bytes .../AppIcon.appiconset/Cube6-32j.png | Bin 0 -> 24046 bytes .../AppIcon.appiconset/Cube6-64j.png | Bin 0 -> 24729 bytes Cube4Fun/PrimitivesScene.swift | 16 +- 15 files changed, 392 insertions(+), 129 deletions(-) create mode 100644 Cube4Fun/Animations.swift create mode 100644 Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-128j.png create mode 100644 Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-16j.png create mode 100644 Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-256j-1.png create mode 100644 Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-256j.png create mode 100644 Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-32j-1.png create mode 100644 Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-32j.png create mode 100644 Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-64j.png diff --git a/Cube4Fun/Animations.swift b/Cube4Fun/Animations.swift new file mode 100644 index 0000000..28bcbef --- /dev/null +++ b/Cube4Fun/Animations.swift @@ -0,0 +1,230 @@ +// +// Animations.swift +// Cube4Fun +// +// Created by Nik on 07.04.15. +// Copyright (c) 2015 DerNik. All rights reserved. +// + +// Constants +let AnimName = "AnimName" +let AnimKey = "AnimKey" +let AnimDuration = "AnimDur" +let AnimSpeed = "AnimSpeed" +let AnimFrames = "AnimData" + +class Animations: NSObject { + + let _emptyFrame: [UInt8] = [ + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255, + 255,255,255,255] + + var _displayedFrame: Int = 1; +// var _frameCount: UInt32 = 1; +// var _oneFrame: NSMutableData = NSMutableData() // == byte[] array +// var _emptyAnimation: NSMutableDictionary = NSMutableDictionary() + var _animationArray: [NSMutableDictionary] = [NSMutableDictionary]() + var _animationSelected: Int = 0 + let _minSendDelay: NSTimeInterval = 0.200 // fastes speed 200 milliseconds + let maxFrameSpeed = 3000 // the lowest possible speed allowed + let minFrameSpeed = 200 // the fastest possible speed allowed + let frameSpeedStep = 100 // how fast increase or decrease speed +// var _playSendDelay: NSTimeInterval = 0.5 // 500 milliseconds as default + + override init() { + super.init() + // Show the first frame + _displayedFrame = 1 + // Append empty animation + self.addAnimation() + // Set visible animation + _animationSelected = 0 + } + + // How much animations do we have + func count() -> (Int) { + return _animationArray.count + } + + func getAnimation(id: Int) -> (NSDictionary) { + let myAnimation = _animationArray[id] as NSDictionary + return myAnimation + } + + func getAnimationName(id: Int) -> (String) { + let value = (self.getAnimation(id)).objectForKey(AnimName) as! String + return value + } + func setAnimationName(id: Int, value: String) { + (self.getAnimation(id)).setValue(value, forKey: AnimName) + } + + func getAnimationKey(id: Int) -> (String) { + let value = (self.getAnimation(id)).objectForKey(AnimKey) as! String + return value + } + func setAnimationKey(id: Int, value: String) { + (self.getAnimation(id)).setValue(value, forKey: AnimKey) + } + + func getAnimationDuration(id: Int) -> (Int) { + let value = (self.getAnimation(id)).objectForKey(AnimDuration) as! Int + return value + } + func setAnimationDuration(id: Int, value: Int) { + (self.getAnimation(id)).setValue(value, forKey: AnimDuration) + } + + func getAnimationSpeed(id: Int) -> (Int) { + let value = (self.getAnimation(id)).objectForKey(AnimSpeed) as! Int + return value + } + func setAnimationSpeed(id: Int, value: Int) { + (self.getAnimation(id)).setValue(value, forKey: AnimSpeed) + } + + func getAnimationFrameCount() -> (Int) { + return self.getAnimationFrameCount(_animationSelected) + } + func getAnimationFrameCount(id: Int) -> (Int) { + let myFrames: NSMutableData = (self.getAnimation(id)).objectForKey(AnimFrames) as! NSMutableData + return myFrames.length / 64 + //let value = (self.getAnimation(id)).objectForKey("AnimFrames") as Int + //return value + } + func getAnimationFrameID() -> Int { + return _displayedFrame + } + func setAnimationFrameID(id: Int) { + _displayedFrame = id + } + + func setSelectedAnimationID(id: Int) { + if id >= 0 { + _animationSelected = id + _displayedFrame = 1 + } + } + func getSelectedAnimationID() -> (Int) { + return _animationSelected + } + func deleteSelected() { + _animationArray.removeAtIndex(_animationSelected) + if ( _animationSelected == 0 && _animationArray.count == 0 ) { // last Frame + self.addAnimation() + } + } + func moveUpSelected() { + if ( _animationSelected > 0 ) { + _animationArray.insert(_animationArray[_animationSelected], atIndex: _animationSelected-1) + _animationArray.removeAtIndex(_animationSelected+1) + } + } + func moveDownSelected() { + if (_animationSelected < _animationArray.count - 1) { + _animationArray.insert(_animationArray[_animationSelected+1], atIndex: _animationSelected) + _animationArray.removeAtIndex(_animationSelected+2) + } + } + + func addAnimation() { + _animationArray.append(self.newAnimation()) + println("append Animation count: \(_animationArray.count)") + } + func newAnimation() -> (NSMutableDictionary) { + println("create new animation") + return [AnimName: "Animation1", AnimKey: "1=anim1", AnimDuration: 1, AnimSpeed: 500, AnimFrames: self.newFrame()] + } + func newFrame() -> (NSMutableData) { + println("create new frame") + return NSMutableData(bytes: _emptyFrame, length: 64) + } + func addFrame() { + let myData: NSMutableData = (self.getAnimation(_animationSelected)).objectForKey(AnimFrames) as! NSMutableData + myData.appendBytes(_emptyFrame, length: 64) + } + func removeFrame() { + if self.getAnimationFrameCount() > 1 { + let myData: NSMutableData = (self.getAnimation(_animationSelected)).objectForKey(AnimFrames) as! NSMutableData + let myLength = myData.length + myData.length = myLength - 64 // remove one frame + } + } + + func animationSpeedInt() -> Int { + let frameSpeed: Int = (self.getAnimation(_animationSelected)).objectForKey(AnimSpeed) as! Int + return frameSpeed + } + func animationSpeedFloat() -> NSTimeInterval { + let frameSpeed: Int = (self.getAnimation(_animationSelected)).objectForKey(AnimSpeed) as! Int + let mySpeed: NSTimeInterval = NSTimeInterval(Float(frameSpeed)/1000) + return mySpeed + } + func increaseSpeed() { + let frameSpeed: Int = (self.getAnimation(_animationSelected)).objectForKey(AnimSpeed) as! Int + if frameSpeed < maxFrameSpeed { + (self.getAnimation(_animationSelected)).setValue(frameSpeed+frameSpeedStep, forKey: AnimSpeed) + } + } + func decreaseSpeed() { + let frameSpeed: Int = (self.getAnimation(_animationSelected)).objectForKey(AnimSpeed) as! Int + if frameSpeed > minFrameSpeed { + (self.getAnimation(_animationSelected)).setValue(frameSpeed-frameSpeedStep, forKey: AnimSpeed) + } + } + + func gotoLastFrame() { + self.setAnimationFrameID(self.getAnimationFrameCount()) + } + func gotoFirstFrame() { + self.setAnimationFrameID(1) + } + func gotoNextFrame() { + if self.getAnimationFrameID() < self.getAnimationFrameCount() { + self.setAnimationFrameID(self.getAnimationFrameID()+1) + } + } + func gotoPrevFrame() { + if self.getAnimationFrameID() > 1 { + self.setAnimationFrameID(self.getAnimationFrameID()-1) + } + } + + + func getMinSendDelay() -> (NSTimeInterval) { + return _minSendDelay + } + + func getAnimData() -> (UnsafePointer) { + let myData: NSMutableData = (self.getAnimation(_animationSelected)).objectForKey(AnimFrames) as! NSMutableData + let byteArray = UnsafePointer(myData.bytes) + return byteArray + } + + func setLEDColor(color: UInt8, led: Int) { + var myByte: [UInt8] = [color] + let myData: NSMutableData = (self.getAnimation(_animationSelected)).objectForKey(AnimFrames) as! NSMutableData + myData.replaceBytesInRange(NSMakeRange(((self.getAnimationFrameID()-1)*64)+led, 1), withBytes: myByte) + } + + func clearLEDColor() { + var myByte: [UInt8] = [255] + let myData: NSMutableData = (self.getAnimation(_animationSelected)).objectForKey(AnimFrames) as! NSMutableData + myData.replaceBytesInRange(NSMakeRange((self.getAnimationFrameID()-1)*64, 64), withBytes: _emptyFrame) + } + +} diff --git a/Cube4Fun/AnimationsController.swift b/Cube4Fun/AnimationsController.swift index d2b67ac..5797b32 100644 --- a/Cube4Fun/AnimationsController.swift +++ b/Cube4Fun/AnimationsController.swift @@ -9,7 +9,6 @@ import Cocoa import Foundation - //let _emptyAnimation: NSMutableDictionary = ["AnimName": "Animation1", "AnimKey": "1=anim1", "AnimDur": 1, "AnimSpeed": 500, "AnimFrames": 1] /* @@ -21,48 +20,47 @@ var dataArray: [NSMutableDictionary] = [["AnimName": "Animation1", "AnimKey": "1 ["AnimName": "Animation6", "AnimKey": "1=anim6", "AnimDur": 2, "AnimSpeed": 1000, "AnimFrames": 52]]; */ -var _animationArray: [NSMutableDictionary] = [NSMutableDictionary](); +//var _animationArray: [NSMutableDictionary] = [NSMutableDictionary](); +//var _selectedAnimation: Int = 0; class AnimationsController: NSObject, NSTableViewDataSource, NSTableViewDelegate { @IBOutlet weak var myTableView: NSTableView! - var _selectedRow: Int = -1 - - override func awakeFromNib() { - _animationArray.append(_emptyAnimation) - } - func numberOfRowsInTableView(tableView: NSTableView) -> Int { - let numberOfRows:Int = _animationArray.count + let numberOfRows:Int = __animations.count() // _animationArray.count return numberOfRows } func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? { - //println("Display: \(row)") - let object: NSDictionary = _animationArray[row] as NSDictionary + //let object: NSDictionary = __animations.getAnimation(row) //_animationArray[row] as NSDictionary //println(object) let column: String = tableColumn?.identifier as String! if column == "AnimName" { - let value = object.objectForKey(column) as String - return value + return __animations.getAnimationName(row) + //let value = object.objectForKey(column) as String + //return value } if column == "AnimKey" { - let value = object.objectForKey(column) as String - return value + return __animations.getAnimationKey(row) + //let value = object.objectForKey(column) as String + //return value } if column == "AnimDur" { - let value = object.objectForKey(column) as Int - return value + return __animations.getAnimationDuration(row) + //let value = object.objectForKey(column) as Int + //return value } if column == "AnimSpeed" { - let value = object.objectForKey(column) as Int - return value + return __animations.getAnimationSpeed(row) + //let value = object.objectForKey(column) as Int + //return value } if column == "AnimFrames" { - let value = object.objectForKey(column) as Int - return value + return __animations.getAnimationFrameCount(row) + //let value = object.objectForKey(column) as Int + //return value } return column @@ -70,8 +68,15 @@ class AnimationsController: NSObject, NSTableViewDataSource, NSTableViewDelegate func tableViewSelectionDidChange(notification: NSNotification) { - let view: NSTableView = notification.object as NSTableView - _selectedRow = view.selectedRow + let view: NSTableView = notification.object as! NSTableView + __animations.setSelectedAnimationID(view.selectedRow) + + _gameView.resetView() + //let myCubeController: GameViewController = _animationsWindow.contentViewController as! GameViewController + //let myCubeView: GameView = myCubeController.view as! GameView + //myCubeView.resetView() + + //_selectedAnimation = view.selectedRow //println("klicked \(view.selectedRow)") } @@ -80,54 +85,54 @@ class AnimationsController: NSObject, NSTableViewDataSource, NSTableViewDelegate let column: String = tableColumn?.identifier as String! //println("Object: \(object) Key: \((tableColumn?.identifier)!)" ) - let value = object! as NSString + let value = object! as! NSString if column == "AnimName" { - _animationArray[row].setObject(value, forKey: (tableColumn?.identifier)!) + __animations.setAnimationName(row, value: value as String) + //_animationArray[row].setObject(value, forKey: (tableColumn?.identifier)!) } if column == "AnimKey" { - _animationArray[row].setObject(value, forKey: (tableColumn?.identifier)!) + __animations.setAnimationKey(row, value: value as String) + //_animationArray[row].setObject(value, forKey: (tableColumn?.identifier)!) } if column == "AnimDur" { - _animationArray[row].setObject(value.integerValue, forKey: (tableColumn?.identifier)!) + __animations.setAnimationDuration(row, value: value.integerValue) + //_animationArray[row].setObject(value.integerValue, forKey: (tableColumn?.identifier)!) } if column == "AnimSpeed" { - _animationArray[row].setObject(value.integerValue, forKey: (tableColumn?.identifier)!) - } - if column == "AnimFrames" { - _animationArray[row].setObject(value.integerValue, forKey: (tableColumn?.identifier)!) + __animations.setAnimationSpeed(row, value: value.integerValue) + //_animationArray[row].setObject(value.integerValue, forKey: (tableColumn?.identifier)!) } + + _gameView.resetView() + + //if column == "AnimFrames" { + // _animationArray[row].setObject(value.integerValue, forKey: (tableColumn?.identifier)!) + //} } @IBAction func addNewAnimation(sender: AnyObject) { - _animationArray.append(_emptyAnimation) + __animations.addAnimation() myTableView.reloadData() - // println("Adding new Item") } @IBAction func delNewAnimation(sender: AnyObject) { - if ( _selectedRow >= 0 ) { - _animationArray.removeAtIndex(_selectedRow) - myTableView.reloadData() - } -// println("Deleting selected Item") + __animations.deleteSelected() + myTableView.reloadData() } @IBAction func moveUpItem(send: AnyObject) { - if ( _selectedRow > 0 ) { - _animationArray.insert(_animationArray[_selectedRow], atIndex: _selectedRow-1) - _animationArray.removeAtIndex(_selectedRow+1) + if ( __animations.getSelectedAnimationID() > 0 ) { + __animations.moveUpSelected() myTableView.reloadData() - myTableView.selectRowIndexes(NSIndexSet(index: _selectedRow-1), byExtendingSelection: false) -// let save: NSMutableDictionary = dataArray. + myTableView.selectRowIndexes(NSIndexSet(index: __animations.getSelectedAnimationID()-1), byExtendingSelection: false) } } @IBAction func moveDownItem(send: AnyObject) { - if (_selectedRow < _animationArray.count - 1) { - _animationArray.insert(_animationArray[_selectedRow+1], atIndex: _selectedRow) - _animationArray.removeAtIndex(_selectedRow+2) + if (__animations.getSelectedAnimationID() < __animations.count() - 1) { + __animations.moveDownSelected() myTableView.reloadData() - myTableView.selectRowIndexes(NSIndexSet(index: _selectedRow+1), byExtendingSelection: false) + myTableView.selectRowIndexes(NSIndexSet(index: __animations.getSelectedAnimationID()+1), byExtendingSelection: false) } } diff --git a/Cube4Fun/AppDelegate.swift b/Cube4Fun/AppDelegate.swift index b231416..c9064e9 100644 --- a/Cube4Fun/AppDelegate.swift +++ b/Cube4Fun/AppDelegate.swift @@ -9,6 +9,8 @@ import Cocoa var _animationsWindow: NSWindow = NSWindow() +var _cubeWindow: NSWindow = NSWindow() +var __animations: Animations = Animations() @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { @@ -19,6 +21,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(aNotification: NSNotification) { // Insert code here to initialize your application _animationsWindow = animationsWindow + _cubeWindow = window + //__animations.initialize() } func applicationShouldTerminate(sender: NSApplication) -> NSApplicationTerminateReply { diff --git a/Cube4Fun/Base.lproj/MainMenu.xib b/Cube4Fun/Base.lproj/MainMenu.xib index 79083ef..847f09a 100644 --- a/Cube4Fun/Base.lproj/MainMenu.xib +++ b/Cube4Fun/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - - + + @@ -684,10 +684,10 @@ - + - + @@ -842,7 +842,7 @@ - + diff --git a/Cube4Fun/GameView.swift b/Cube4Fun/GameView.swift index 656f1bb..2bba0b3 100644 --- a/Cube4Fun/GameView.swift +++ b/Cube4Fun/GameView.swift @@ -10,12 +10,20 @@ import SceneKit var lastMousePos: NSPoint = NSPoint() var startAngle: CGFloat = CGFloat() -var klickedColor: Byte = Byte(1) +var klickedColor: UInt8 = UInt8(1) let relativeBarPosition: CGFloat = 500.0 class GameView: SCNView { + func resetView() { + // goto first frame + self.firstButtonPressed() + + // Update speed + self.updateSpeedText() + } + func updateButtonVisibility() { // init var nextFrame = false; @@ -26,7 +34,7 @@ class GameView: SCNView { // first Frame, only one Frame // -> no button visible - if myFrameCount == 1 && myMaxFrameCount == 1 { + if __animations.getAnimationFrameID() == 1 && __animations.getAnimationFrameCount() == 1 { nextFrame = false; lastFrame = false; prevFrame = false; @@ -35,7 +43,7 @@ class GameView: SCNView { } // first Frame, second exists. - if myFrameCount == 1 && myMaxFrameCount > 1 { + if __animations.getAnimationFrameID() == 1 && __animations.getAnimationFrameCount() > 1 { // Visible: nextFrame = true; lastFrame = true; @@ -46,7 +54,7 @@ class GameView: SCNView { } // previous Frame exists, no more Frames - if myFrameCount > 1 && myFrameCount == myMaxFrameCount { + if __animations.getAnimationFrameID() > 1 && __animations.getAnimationFrameID() == __animations.getAnimationFrameCount() { // Visible: prevFrame = true; firstFrame = true; @@ -57,7 +65,7 @@ class GameView: SCNView { } // previous Frame exists and next Frame exists { - if myFrameCount > 1 && myFrameCount < myMaxFrameCount { + if __animations.getAnimationFrameID() > 1 && __animations.getAnimationFrameID() < __animations.getAnimationFrameCount() { // Visible: prevFrame = true; firstFrame = true; @@ -68,7 +76,7 @@ class GameView: SCNView { if let rootNode = self.scene?.rootNode { for childNode in rootNode.childNodes { - let buttonNode: SCNNode = childNode as SCNNode + let buttonNode: SCNNode = childNode as! SCNNode if buttonNode.name == "myNextFrameButton" { buttonNode.hidden = !nextFrame; } @@ -85,8 +93,8 @@ class GameView: SCNView { buttonNode.hidden = !delFrame } if buttonNode.name == "myFrameText" { - let geometry:SCNText = buttonNode.geometry as SCNText - geometry.string = "Frame: \(myFrameCount)/\(myMaxFrameCount)" + let geometry:SCNText = buttonNode.geometry as! SCNText + geometry.string = "Frame: \(__animations.getAnimationFrameID())/\(__animations.getAnimationFrameCount())" } } @@ -97,7 +105,8 @@ class GameView: SCNView { func updateLEDFrame() { // get actuall frame data - let data : UnsafePointer = UnsafePointer(myFrames.mutableBytes) +// let data : UnsafePointer = UnsafePointer(myFrames.mutableBytes) + let data = __animations.getAnimData() //NSMutableData if let rootNode = self.scene?.rootNode { if let cubeNode = rootNode.childNodeWithName("cubeNode", recursively: true) { @@ -108,8 +117,8 @@ class GameView: SCNView { let ledID: Int = Int(name.integerValue) if let material: SCNMaterial = geometry.firstMaterial { var color: NSColor = NSColor() - let colorPosition: Int = ((myFrameCount-1)*64) + ledID - let savedColor: Byte = data[colorPosition] + let colorPosition: Int = ((__animations.getAnimationFrameID()-1)*64) + ledID + let savedColor: UInt8 = data[colorPosition] if data[colorPosition] == 255 { color = NSColor.grayColor() }else{ @@ -130,13 +139,15 @@ class GameView: SCNView { func plusButtonPressed() { // Extend the data array with one frame - myFrames.appendBytes(emptyFrame, length: 64) + //myFrames.appendBytes(emptyFrame, length: 64) + __animations.addFrame() // Add frame - myMaxFrameCount++; + //myMaxFrameCount++; // Goto new frame - myFrameCount = myMaxFrameCount; + //myFrameCount = __animations.getAnimationFrameCount(); + __animations.gotoLastFrame() // Update LEDs updateLEDFrame() @@ -150,21 +161,24 @@ class GameView: SCNView { // TODO! // Remove frame - if myMaxFrameCount > 1 { - myMaxFrameCount--; - } - if myFrameCount > 1 { - myFrameCount--; - } + __animations.removeFrame() +// if __animations.getAnimationFrameCount() > 1 { +// myMaxFrameCount--; +// } +// if myFrameCount > 1 { +// myFrameCount--; +// } // Update control button visibility updateButtonVisibility() } func prevButtonPressed() { - if myFrameCount > 1 { - myFrameCount-- - } +// if myFrameCount > 1 { +// myFrameCount-- +// } + __animations.gotoPrevFrame() + // Update LEDs updateLEDFrame() @@ -173,9 +187,10 @@ class GameView: SCNView { } func nextButtonPressed() { - if myFrameCount < myMaxFrameCount { - myFrameCount++ - } +// if myFrameCount < myMaxFrameCount { +// myFrameCount++ +// } + __animations.gotoNextFrame() // Update LEDs updateLEDFrame() @@ -185,7 +200,8 @@ class GameView: SCNView { } func firstButtonPressed() { - myFrameCount = 1; + //myFrameCount = 1; + __animations.gotoFirstFrame() // Update LEDs updateLEDFrame() @@ -195,7 +211,7 @@ class GameView: SCNView { } func lastButtonPressed() { - myFrameCount = myMaxFrameCount + __animations.gotoLastFrame() // Update LEDs updateLEDFrame() @@ -205,27 +221,29 @@ class GameView: SCNView { } func plusSpeedButtonPressed() { - if ( _playSendDelay <= 3 ) { // 3 seconds slowest fps - _playSendDelay = _playSendDelay + 0.1 + __animations.increaseSpeed() +// if ( _playSendDelay <= 3 ) { // 3 seconds slowest fps +// _playSendDelay = _playSendDelay + 0.1 updateSpeedText() - } +// } } func minusSpeedButtonPressed() { - println(_playSendDelay) - if ( _playSendDelay > 0.2 ) { // 100ms fastest fps - _playSendDelay = _playSendDelay - 0.1 + //println(_playSendDelay) + __animations.decreaseSpeed() +// if ( _playSendDelay > 0.2 ) { // 100ms fastest fps +// _playSendDelay = _playSendDelay - 0.1 updateSpeedText() - } +// } } func updateSpeedText() { if let rootNode = self.scene?.rootNode { for childNode in rootNode.childNodes { - let buttonNode: SCNNode = childNode as SCNNode + let buttonNode: SCNNode = childNode as! SCNNode if buttonNode.name == "mySpeedText" { - let geometry:SCNText = buttonNode.geometry as SCNText - geometry.string = "Speed: \(Int(_playSendDelay*1000)) ms" + let geometry:SCNText = buttonNode.geometry as! SCNText + geometry.string = "Speed: \(__animations.animationSpeedInt()) ms" } } @@ -272,14 +290,14 @@ class GameView: SCNView { if let geom = node.geometry { if let name:NSString = geom.name { if name.integerValue >= 0 && name.integerValue < 64 { // LED lamps - let color: NSColor = geom.firstMaterial?.diffuse.contents as NSColor + let color: NSColor = geom.firstMaterial?.diffuse.contents as! NSColor if color != NSColor.grayColor() { // Make sure we are in range of 0...255 let ledColor = (color.hueComponent * 255) % 255 if ( ledColor >= 0 && ledColor < 255 ) { - klickedColor = Byte(ledColor) + klickedColor = UInt8(ledColor) } - klickedColor = Byte (color.hueComponent * 255) + klickedColor = UInt8 (color.hueComponent * 255) moveArrows(Int(klickedColor)) //println(klickedColor) } @@ -314,7 +332,7 @@ class GameView: SCNView { if clickedNode.name == "myBox" { anim = false } - if clickedNode.name == "myPlayButton" && myMaxFrameCount > 1 { + if clickedNode.name == "myPlayButton" && __animations.getAnimationFrameCount() > 1 { playButtonPressed() anim = false } @@ -357,7 +375,7 @@ class GameView: SCNView { if colorInt > 253 { klickedColor = 253 // Maximum value }else{ - klickedColor = Byte(colorInt) + klickedColor = UInt8(colorInt) println(klickedColor) } } @@ -376,11 +394,11 @@ class GameView: SCNView { if let node = result.node { if let geom = node.geometry { if let name:NSString = geom.name { - let myGeometry:SCNText = self.scene!.rootNode.childNodeWithName("myDescr", recursively: true)?.geometry as SCNText + let myGeometry:SCNText = self.scene!.rootNode.childNodeWithName("myDescr", recursively: true)?.geometry as! SCNText // Show touched led myGeometry.string = name // Check for previously color - let prevColor = geom.firstMaterial?.diffuse.contents as NSColor + let prevColor = geom.firstMaterial?.diffuse.contents as! NSColor if prevColor != NSColor.grayColor() { geom.firstMaterial?.diffuse.contents = NSColor.grayColor() ledColorOn = false @@ -443,13 +461,14 @@ class GameView: SCNView { SCNTransaction.commit() // Update the LED frame - var myByte: [Byte] + var myByte: UInt8 if ledColorOn { - myByte = [klickedColor] + myByte = klickedColor }else{ - myByte = [255] // Off + myByte = 255 // Off } - myFrames.replaceBytesInRange(NSMakeRange(((myFrameCount-1)*64)+ledPressed, 1), withBytes: myByte) + __animations.setLEDColor(myByte, led: ledPressed) + //myFrames.replaceBytesInRange(NSMakeRange(((myFrameCount-1)*64)+ledPressed, 1), withBytes: myByte) } @@ -518,7 +537,8 @@ class GameView: SCNView { break; case 17: // t - Key // Reset the frame color on the Cube - myFrames.replaceBytesInRange(NSMakeRange(myFrameCount-1, 64), withBytes: emptyFrame) + //myFrames.replaceBytesInRange(NSMakeRange(myFrameCount-1, 64), withBytes: emptyFrame) + __animations.clearLEDColor() // Reset the frame color in 3D if let rootNode = self.scene?.rootNode { diff --git a/Cube4Fun/GameViewController.swift b/Cube4Fun/GameViewController.swift index d13a7bb..40b3441 100644 --- a/Cube4Fun/GameViewController.swift +++ b/Cube4Fun/GameViewController.swift @@ -9,7 +9,7 @@ import SceneKit import QuartzCore - +/* var myFrameCount: UInt32 = 1; var myMaxFrameCount: UInt32 = 1; var myFrames: NSMutableData = NSMutableData() // == byte[] array @@ -33,12 +33,15 @@ let emptyFrame: [Byte] = [ 255,255,255,255, 255,255,255,255] -var _previousUpdateTime: NSTimeInterval = NSTimeInterval() -var _deltaTime: NSTimeInterval = NSTimeInterval() let _minSendDelay: NSTimeInterval = 0.200 // 200 milliseconds let _frameSendDelay: NSTimeInterval = 0.2 // one second var _playSendDelay: NSTimeInterval = 0.5 // 500 milliseconds as default +*/ + +var _previousUpdateTime: NSTimeInterval = NSTimeInterval() +var _deltaTime: NSTimeInterval = NSTimeInterval() var _playAllFrames = false +var _gameView: GameView = GameView(); class GameViewController: NSViewController { // SCNSceneRendererDelegate @@ -73,18 +76,18 @@ class GameViewController: NSViewController { // SCNSceneRendererDelegate //var ms = Int((time % 1) * 1000) if ( _playAllFrames ) { - if ( _deltaTime >= _playSendDelay ){ - if myFrameCount >= myMaxFrameCount { + if ( _deltaTime >= __animations.animationSpeedFloat() ){ + if (__animations.getAnimationFrameID() >= __animations.getAnimationFrameCount()) { self.gameView!.firstButtonPressed() }else{ self.gameView!.nextButtonPressed() } - CubeNetworkObj.updateFrame(UnsafePointer(myFrames.bytes), count: myFrameCount) + CubeNetworkObj.updateFrame(__animations.getAnimData(), count: UInt32(__animations.getAnimationFrameID())) _previousUpdateTime = time; } }else{ - if ( _deltaTime >= _minSendDelay ) { - CubeNetworkObj.updateFrame(UnsafePointer(myFrames.bytes), count: myFrameCount) + if ( _deltaTime >= __animations.getMinSendDelay() ) { + CubeNetworkObj.updateFrame(__animations.getAnimData(), count: UInt32(__animations.getAnimationFrameID())) //println("SendFrame: \(_deltaTime)") _previousUpdateTime = time; } @@ -94,18 +97,19 @@ class GameViewController: NSViewController { // SCNSceneRendererDelegate override func awakeFromNib(){ + _gameView = gameView; //NSTimer.scheduledTimerWithTimeInterval(_frameSendDelay, invocation: CubeNetworkObj.initObjects(), repeats: true) // CubeNetworkObj.initObjects(); // Init first frame - myFrames = NSMutableData(bytes: emptyFrame, length: 64) - myFrameCount = 1 +// myFrames = NSMutableData(bytes: emptyFrame, length: 64) +// myFrameCount = 1 // Open connection to the LED cube CubeNetworkObj.openConnection() // Fallback timer if nothing render at the moment - NSTimer.scheduledTimerWithTimeInterval(_frameSendDelay, target: self, selector: Selector("sendFrame"), userInfo: nil, repeats: true) + NSTimer.scheduledTimerWithTimeInterval(__animations.getMinSendDelay(), target: self, selector: Selector("sendFrame"), userInfo: nil, repeats: true) diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Contents.json b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Contents.json index 66257b0..4ae3a01 100644 --- a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Contents.json @@ -3,43 +3,43 @@ { "size" : "16x16", "idiom" : "mac", - "filename" : "Cube4Fun-Icon-16.png", + "filename" : "Cube6-16j.png", "scale" : "1x" }, { "size" : "16x16", "idiom" : "mac", - "filename" : "Cube4Fun-Icon-32.png", + "filename" : "Cube6-32j-1.png", "scale" : "2x" }, { "size" : "32x32", "idiom" : "mac", - "filename" : "Cube4Fun-Icon-32-1.png", + "filename" : "Cube6-32j.png", "scale" : "1x" }, { "size" : "32x32", "idiom" : "mac", - "filename" : "Cube4Fun-Icon-64.png", + "filename" : "Cube6-64j.png", "scale" : "2x" }, { "size" : "128x128", "idiom" : "mac", - "filename" : "Cube4Fun-Icon-128.png", + "filename" : "Cube6-128j.png", "scale" : "1x" }, { "size" : "128x128", "idiom" : "mac", - "filename" : "Cube4Fun-Icon-256.png", + "filename" : "Cube6-256j-1.png", "scale" : "2x" }, { "size" : "256x256", "idiom" : "mac", - "filename" : "Cube4Fun-Icon-256-1.png", + "filename" : "Cube6-256j.png", "scale" : "1x" }, { diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-128j.png b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-128j.png new file mode 100644 index 0000000000000000000000000000000000000000..01c096e867ac8e7845182b5d13b40fd8373f7aee GIT binary patch literal 25579 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 literal 0 HcmV?d00001 diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-16j.png b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-16j.png new file mode 100644 index 0000000000000000000000000000000000000000..0cefcf4017d74b8906e5dec559511d79c551c8ce GIT binary patch literal 23590 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 literal 0 HcmV?d00001 diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-256j-1.png b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-256j-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f2242de42270be5857efa081d49b12cc5f5b7d3d GIT binary patch literal 27633 zcmeHw2{_c-8~=A24Pj7`Ej5-(GG@j;_I)W!SwbqtEKHWMj4XvgqUAW= z0Nl_(#|!`<;1B|^tN=e6xzsV>$0~ON8!rH0TTA}~0TPn<0D#q$tgXFsrxS%r@p7WL zBMh~*5$>K864`|a0KPAh%^fYw``4+CzZ})t5kWh%gJQh^>!WT}3UW_fiQ_Eb)!X9HFvrCS~o}sm2^{deG(z4fYq%?wA#oPfdmOBJtuW3;T@Fh@1Wt&JL z^CJM_+sMWO6dETMqSuGdat>(4?}gBgKnkg+6?d@ExB(6SQ(Bh+4Lt}gIc~E#kjezu zSK=MIft^UeeoN5XMu3+5CH@cuustKp14%s%Al4EibO0x1;9BkOA`GeCAC4k#*lX#w>)kIEL&) zQzL&Wo5Kz{Pym}1ad7CK>8Z_h*8qUm)WG@~Nz@$ynlg;$I&)#uFq6}Mwp8!&6QtXm z8ux(I{ufpw?sRN)&qw7vf8O)vP3!hjEn8fLRltm6v0b6nw9D5(m8tQuSC6{Hf~EHb z>oa|MRa`Y{l(xS1_fLqG4>!evb@>>3AvPq~z$CUF)h%_;PCt zacQvZz6ci?Fs(TuhIksmy-Q@rX*mOo*>MYmrGd~VRnHaJ@V$Bu zPb)tGq(i2T=ILY31mE7J+QfcOJ11R1;E3J@wmJe8lMuNsHL=d~u7K)E`SZPXnNFN9 zBGt6Z(S?0{%rd1eXsNOity_wctD^Chw?wY7XO;#d)b4*)$OHR}Z!&{du8rC%EHMp6H_Dg0Y${GlWMn8Q)aK6oqJtK+O_9X00 z@|%)3GH(Rm2!FC=O?J@mxb(%mOWdsDz;^x~t{&MQ7%@&-)AC}1Sx5SLi`8SXF84hSXK( zG{N(^Iz9z%SBB$K9_^>47*Vdg^vmy^SRa6zwwQLExH6{CZVkJ`E(U93ui;a9EayQ{ z5ki%>ecYwJuS7#T4R;n7`})Y~oO+du&3eD-ah@cX?d=xpb}e%)ySN#)S$Ojf;{oI0 z1T*8D%Udri8z~!=S65YEsD2hNm#B(qk?u|GO>9Z*yl=n9caLOtdiDdN;q5njF53)e z=edRL!P=x*TkhF+NAG&_^-a%mujgJ_eI>^v+9WgOnPW-T$Ly!s8Ta|KdRk#^H?m!` z18|NGypH!D-zXW5&W{dw81UP)DleboKokcr$UJEqUHVt;X*DH#` zqfT30Z^^o!=5uu%_nuenvzq6*ZnbU|g_qJVZS1NP3hzI;UujxGNwEv-)D9AzCCvKI z)&o~)n;?$RW5JriwksyT_#YN7IHj)CM*MvH`H<$x)ErG7&B&1JAw5Ocg`J+fi@Gj6 z-WykQx`xaVwllErSsgR(E$&1~Ap4fE@Gz^R>ZjZztOe>Zv2s53?b=?QIuklEIxiC) zF{ap?$nA0xYFDKWsJu{kDEm;oOp0Vv)oh(?ZRoONJyuHMhP<20qt2jSSC%fC+EnPjHo;#xKT%zyhVcfwjP|&lltR+`bF)Khir2jUJv;5_4lAUP_1pYw2e7wQJp9^NyLnb_ zJGvWoP36JyYzfz9)65~O*c*ZQoBfTQgZCFzgcRL_I1jQ}vi5`p47Rrn?K8DT*>v8+ zO&m=YRO2~z{04U$Z!Awxt9ZL_k6<{Zq9DHg%-xL4(i}o9se#o0_9ZgKmLukB?Aurl zH~8}xcj2A8?+%T9)@?(@R*SdghGuK$Tr5y|kVm}ow5D2F-QtqPsKtbZ{BT3ZJzUEd zxB6khLwTQN-!-?{=8aFQJ$=+>39&S8CN&c$4JYr6tKT?wwf{@Zr0c%xCaxYs<hfA?Y5q^ zRu8NaZYtTi4p0YFW}+KS%X5=*6K>?}b

~&%bwwG~O?mqEOQ@n(y~<-R!gG6s&4T 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 literal 0 HcmV?d00001 diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-256j.png b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-256j.png new file mode 100644 index 0000000000000000000000000000000000000000..f2242de42270be5857efa081d49b12cc5f5b7d3d GIT binary patch literal 27633 zcmeHw2{_c-8~=A24Pj7`Ej5-(GG@j;_I)W!SwbqtEKHWMj4XvgqUAW= z0Nl_(#|!`<;1B|^tN=e6xzsV>$0~ON8!rH0TTA}~0TPn<0D#q$tgXFsrxS%r@p7WL zBMh~*5$>K864`|a0KPAh%^fYw``4+CzZ})t5kWh%gJQh^>!WT}3UW_fiQ_Eb)!X9HFvrCS~o}sm2^{deG(z4fYq%?wA#oPfdmOBJtuW3;T@Fh@1Wt&JL z^CJM_+sMWO6dETMqSuGdat>(4?}gBgKnkg+6?d@ExB(6SQ(Bh+4Lt}gIc~E#kjezu zSK=MIft^UeeoN5XMu3+5CH@cuustKp14%s%Al4EibO0x1;9BkOA`GeCAC4k#*lX#w>)kIEL&) zQzL&Wo5Kz{Pym}1ad7CK>8Z_h*8qUm)WG@~Nz@$ynlg;$I&)#uFq6}Mwp8!&6QtXm z8ux(I{ufpw?sRN)&qw7vf8O)vP3!hjEn8fLRltm6v0b6nw9D5(m8tQuSC6{Hf~EHb z>oa|MRa`Y{l(xS1_fLqG4>!evb@>>3AvPq~z$CUF)h%_;PCt zacQvZz6ci?Fs(TuhIksmy-Q@rX*mOo*>MYmrGd~VRnHaJ@V$Bu zPb)tGq(i2T=ILY31mE7J+QfcOJ11R1;E3J@wmJe8lMuNsHL=d~u7K)E`SZPXnNFN9 zBGt6Z(S?0{%rd1eXsNOity_wctD^Chw?wY7XO;#d)b4*)$OHR}Z!&{du8rC%EHMp6H_Dg0Y${GlWMn8Q)aK6oqJtK+O_9X00 z@|%)3GH(Rm2!FC=O?J@mxb(%mOWdsDz;^x~t{&MQ7%@&-)AC}1Sx5SLi`8SXF84hSXK( zG{N(^Iz9z%SBB$K9_^>47*Vdg^vmy^SRa6zwwQLExH6{CZVkJ`E(U93ui;a9EayQ{ z5ki%>ecYwJuS7#T4R;n7`})Y~oO+du&3eD-ah@cX?d=xpb}e%)ySN#)S$Ojf;{oI0 z1T*8D%Udri8z~!=S65YEsD2hNm#B(qk?u|GO>9Z*yl=n9caLOtdiDdN;q5njF53)e z=edRL!P=x*TkhF+NAG&_^-a%mujgJ_eI>^v+9WgOnPW-T$Ly!s8Ta|KdRk#^H?m!` z18|NGypH!D-zXW5&W{dw81UP)DleboKokcr$UJEqUHVt;X*DH#` zqfT30Z^^o!=5uu%_nuenvzq6*ZnbU|g_qJVZS1NP3hzI;UujxGNwEv-)D9AzCCvKI z)&o~)n;?$RW5JriwksyT_#YN7IHj)CM*MvH`H<$x)ErG7&B&1JAw5Ocg`J+fi@Gj6 z-WykQx`xaVwllErSsgR(E$&1~Ap4fE@Gz^R>ZjZztOe>Zv2s53?b=?QIuklEIxiC) zF{ap?$nA0xYFDKWsJu{kDEm;oOp0Vv)oh(?ZRoONJyuHMhP<20qt2jSSC%fC+EnPjHo;#xKT%zyhVcfwjP|&lltR+`bF)Khir2jUJv;5_4lAUP_1pYw2e7wQJp9^NyLnb_ zJGvWoP36JyYzfz9)65~O*c*ZQoBfTQgZCFzgcRL_I1jQ}vi5`p47Rrn?K8DT*>v8+ zO&m=YRO2~z{04U$Z!Awxt9ZL_k6<{Zq9DHg%-xL4(i}o9se#o0_9ZgKmLukB?Aurl zH~8}xcj2A8?+%T9)@?(@R*SdghGuK$Tr5y|kVm}ow5D2F-QtqPsKtbZ{BT3ZJzUEd zxB6khLwTQN-!-?{=8aFQJ$=+>39&S8CN&c$4JYr6tKT?wwf{@Zr0c%xCaxYs<hfA?Y5q^ zRu8NaZYtTi4p0YFW}+KS%X5=*6K>?}b

~&%bwwG~O?mqEOQ@n(y~<-R!gG6s&4T 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 literal 0 HcmV?d00001 diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-32j-1.png b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-32j-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d688034064ee0b96ca3c7a7dacd80ad9b41fbd29 GIT binary patch literal 24046 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 I$YuNg03b#%PXGV_ literal 0 HcmV?d00001 diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-32j.png b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-32j.png new file mode 100644 index 0000000000000000000000000000000000000000..d688034064ee0b96ca3c7a7dacd80ad9b41fbd29 GIT binary patch literal 24046 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 I$YuNg03b#%PXGV_ literal 0 HcmV?d00001 diff --git a/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-64j.png b/Cube4Fun/Images.xcassets/AppIcon.appiconset/Cube6-64j.png new file mode 100644 index 0000000000000000000000000000000000000000..3b3e0a30e6eaf24e08bf6983fb97f64abf6e72f3 GIT binary patch literal 24729 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 bq63V&u1Y$jY@!6d!T>WPOT%n^*PZ_Z)Z25G literal 0 HcmV?d00001 diff --git a/Cube4Fun/PrimitivesScene.swift b/Cube4Fun/PrimitivesScene.swift index a1b3ffb..228ae63 100644 --- a/Cube4Fun/PrimitivesScene.swift +++ b/Cube4Fun/PrimitivesScene.swift @@ -31,7 +31,7 @@ class PrimitivesScene: SCNScene { pauseImageNode.name = "myPauseButton" pauseImageNode.position = SCNVector3(x:0, y:14, z:0) pauseImageNode.hidden = true - if myFrameCount == 1 && myMaxFrameCount == 1 { + if __animations.getAnimationFrameID() == 1 && __animations.getAnimationFrameCount() == 1 { pauseImageNode.hidden = true } self.rootNode.addChildNode(pauseImageNode) @@ -42,7 +42,7 @@ class PrimitivesScene: SCNScene { let nextFrameImageNode = SCNNode(geometry: nextFrameImage) nextFrameImageNode.name = "myNextFrameButton" nextFrameImageNode.position = SCNVector3(x:2, y:14, z:0) - if myFrameCount == 1 && myMaxFrameCount == 1 { + if __animations.getAnimationFrameID() == 1 && __animations.getAnimationFrameCount() == 1 { nextFrameImageNode.hidden = true } self.rootNode.addChildNode(nextFrameImageNode) @@ -53,7 +53,7 @@ class PrimitivesScene: SCNScene { let prevFrameImageNode = SCNNode(geometry: prevFrameImage) prevFrameImageNode.name = "myPrevFrameButton" prevFrameImageNode.position = SCNVector3(x:-2, y:14, z:0) - if myFrameCount == 1 { + if __animations.getAnimationFrameID() == 1 { prevFrameImageNode.hidden = true } self.rootNode.addChildNode(prevFrameImageNode) @@ -64,7 +64,7 @@ class PrimitivesScene: SCNScene { let startFrameImageNode = SCNNode(geometry: startFrameImage) startFrameImageNode.name = "myStartFrameButton" startFrameImageNode.position = SCNVector3(x:-5, y:14, z:0) - if myFrameCount == 1 { + if __animations.getAnimationFrameID() == 1 { startFrameImageNode.hidden = true } self.rootNode.addChildNode(startFrameImageNode) @@ -75,7 +75,7 @@ class PrimitivesScene: SCNScene { let lastFrameImageNode = SCNNode(geometry: lastFrameImage) lastFrameImageNode.name = "myLastFrameButton" lastFrameImageNode.position = SCNVector3(x:5, y:14, z:0) - if myFrameCount == myMaxFrameCount { + if __animations.getAnimationFrameID() == __animations.getAnimationFrameCount() { lastFrameImageNode.hidden = true } self.rootNode.addChildNode(lastFrameImageNode) @@ -84,7 +84,7 @@ class PrimitivesScene: SCNScene { func createSpeedButtons() { // Frame - let textSpeed = SCNText(string: "Speed: \(Int(_playSendDelay*1000)) ms", extrusionDepth: 0) + let textSpeed = SCNText(string: "Speed: \(__animations.animationSpeedInt()) ms", extrusionDepth: 0) textSpeed.font = NSFont(name: "Arial", size: 1.2) let textSpeedNode = SCNNode(geometry: textSpeed) textSpeedNode.name = "mySpeedText" @@ -109,7 +109,7 @@ class PrimitivesScene: SCNScene { } func createFrameButtons() { - let textFrame = SCNText(string: "Frame: \(myFrameCount)/\(myMaxFrameCount)", extrusionDepth: 0) + let textFrame = SCNText(string: "Frame: \(__animations.getAnimationFrameID())/\(__animations.getAnimationFrameCount())", extrusionDepth: 0) textFrame.font = NSFont(name: "Arial", size: 1.2) let textFrameNode = SCNNode(geometry: textFrame) textFrameNode.name = "myFrameText" @@ -131,7 +131,7 @@ class PrimitivesScene: SCNScene { delFrameImageNode.name = "myDelFrameButton" delFrameImageNode.position = SCNVector3(x:-18.7, y:12, z:0) // for first frame, there is nothing to delete - if ( myFrameCount == 1 ) { + if ( __animations.getAnimationFrameID() == 1 ) { delFrameImageNode.hidden = true } self.rootNode.addChildNode(delFrameImageNode)