├── .gitignore ├── .gitmodules ├── Fiber2D ├── Action.swift ├── ActionConcurrent.swift ├── ActionContinous+Default.swift ├── ActionContinous.swift ├── ActionEase.swift ├── ActionInstant+Node.swift ├── ActionInstant.swift ├── ActionRepeat.swift ├── ActionRewind.swift ├── ActionSequence.swift ├── ActionSpeed.swift ├── ActionTransform.swift ├── Behaviour.swift ├── BlendMode.swift ├── Camera.swift ├── Color.swift ├── ColorNode.swift ├── Component.swift ├── Director+Internal.swift ├── Director+RunLoop.swift ├── Director+SDL.swift ├── Director+Scene.swift ├── Director+UIKit.swift ├── Director+macOS.swift ├── Director.swift ├── Extensions-Temp.swift ├── File.swift ├── FileLocator.swift ├── Image+PNG.swift ├── Image.swift ├── Layout.swift ├── LayoutBox.swift ├── Node+Actions.swift ├── Node+Component.swift ├── Node+Convertation.swift ├── Node+Hierarchy.swift ├── Node+Projection.swift ├── Node+Scene.swift ├── Node+Transform.swift ├── Node.swift ├── PhysicsBody+Internal.swift ├── PhysicsBody+Joints.swift ├── PhysicsBody+Shapes.swift ├── PhysicsBody+Simulation.swift ├── PhysicsBody.swift ├── PhysicsContact.swift ├── PhysicsJoint.swift ├── PhysicsShape+Internal.swift ├── PhysicsShape.swift ├── PhysicsShapeBox.swift ├── PhysicsShapeCircle.swift ├── PhysicsShapePolygon.swift ├── PhysicsSystem.swift ├── PhysicsTypes.swift ├── PhysicsWorld+Bodies.swift ├── PhysicsWorld+Internal.swift ├── PhysicsWorld+Joints.swift ├── PhysicsWorld+Shapes.swift ├── PhysicsWorld.swift ├── RenderTexture.swift ├── Renderer │ ├── Geometry.swift │ ├── Material.swift │ ├── Pass.swift │ ├── RenderComponent.swift │ ├── Renderer.swift │ ├── Shader.swift │ ├── Technique.swift │ ├── Texture+UV.swift │ ├── Texture.swift │ ├── TextureCache.swift │ └── bgfx │ │ ├── BGFXRenderer+RenderTexture.swift │ │ └── BGFXRenderer.swift ├── Responder.swift ├── ResponderManager+Mouse.swift ├── ResponderManager+SDL.swift ├── ResponderManager+UIKit.swift ├── ResponderManager+macOS.swift ├── ResponderManager.swift ├── Scene+Systems.swift ├── Scene.swift ├── Scheduler.swift ├── Scheduling.swift ├── Setup.swift ├── Sprite.swift ├── Sprite9Slice.swift ├── Sprite9SliceNode.swift ├── SpriteFrame.swift ├── SpriteFrameCache.swift ├── SpriteNode.swift ├── System.swift ├── Texture+Image.swift ├── Timer.swift ├── Transition.swift ├── ViewportNode.swift ├── events │ └── Event.swift ├── protocols │ ├── BehaviourProtocol.swift │ ├── Cloneable.swift │ ├── DirectorView.swift │ ├── Prioritized.swift │ └── Tagged.swift ├── typedefs │ ├── enums │ │ ├── CullMode.swift │ │ └── UnitTypes.swift │ └── structs │ │ ├── Input.swift │ │ ├── Tree.swift │ │ └── WeakBox.swift └── utils │ └── ArrayExtensions.swift ├── Makefile ├── Package.swift ├── README.md ├── demo ├── InputScene.swift ├── MainScene.swift ├── PhysicsScene.swift ├── UserComponents.swift ├── ViewportScene.swift ├── images │ ├── circle.png │ └── ninepatch_bubble.png └── platform │ ├── android │ ├── build.sh │ └── f2dc │ │ ├── .gitignore │ │ ├── Package.swift │ │ └── Sources │ │ ├── EventType.swift │ │ ├── InputScene.swift │ │ ├── PhysicsScene.swift │ │ ├── Surface.swift │ │ ├── Window+Fiber2D.swift │ │ ├── Window.swift │ │ ├── WindowMock.swift │ │ └── gameMain.swift │ ├── apple │ ├── .swift-version │ ├── Fiber2D-demo-iOS │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift │ ├── Fiber2D-demo.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ └── Fiber2D-demo │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ └── MainMenu.xib │ │ ├── Info.plist │ │ ├── MetalView.swift │ │ └── main.swift │ └── sdl │ ├── Makefile │ ├── Package.swift │ └── Sources │ ├── EventType.swift │ ├── MainScene.swift │ ├── Surface.swift │ ├── UserComponents.swift │ ├── Window+Fiber2D.swift │ ├── Window.swift │ └── main.swift ├── shaders ├── .gitignore ├── compile_shaders.sh ├── f2d_builtin_poscolor.sc ├── f2d_builtin_postexture.sc ├── f2d_builtin_vertex.sc ├── shaderc └── varying.def.sc └── xcode ├── ios-overrides.xcconfig └── macos-overrides.xcconfig /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | DerivedData 5 | xcuserdata 6 | !default.mode1v3 7 | !default.mode2v3 8 | !default.pbxuser 9 | !default.perspectivev3 10 | *.hmap 11 | *.ipa 12 | *.mode1v3 13 | *.mode2v3 14 | *.moved-aside 15 | *.pbxuser 16 | *.perspective 17 | *.perspectivev3 18 | *.swp 19 | *.xccheckout 20 | *.xcuserstate 21 | *~.nib 22 | .DS_Store 23 | 24 | # CocoaPods 25 | # 26 | # We recommend against adding the Pods directory to your .gitignore. However 27 | # you should judge for yourself, the pros and cons are mentioned at: 28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 29 | # 30 | # Pods/ 31 | 32 | 33 | # Misc 34 | *.sconsign.dblite 35 | *.pyc 36 | *.orig 37 | *.ninja_log 38 | 39 | Packages/ 40 | .build/ 41 | *.xcodeproj 42 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/SwiftBGFX"] 2 | path = external/SwiftBGFX 3 | url = https://github.com/SwiftGFX/SwiftBGFX.git 4 | [submodule "demo/platform/android/android-project"] 5 | path = demo/platform/android/android-project 6 | url = https://github.com/s1ddok/Fiber2D-Android-Project.git 7 | -------------------------------------------------------------------------------- /Fiber2D/ActionContinous+Default.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionContinous+Default.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 05.01.17. 6 | // 7 | // 8 | 9 | /** 10 | * Internal action model that does nothing 11 | */ 12 | internal struct ActionEmpty: ActionModel {} 13 | 14 | /** 15 | This action waits for the time specified. Used in sequences to delay (pause) the sequence for a given time. 16 | 17 | Example, wait for 2 seconds: 18 | 19 | let delay = ActionWait(for: 2.0) 20 | */ 21 | public func ActionWait(for time: Time) -> ActionContinousContainer { 22 | return ActionEmpty().continously(duration: time) 23 | } 24 | -------------------------------------------------------------------------------- /Fiber2D/ActionContinous.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionContinous.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 03.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public struct ActionContinousContainer: ActionContainer, Continous { 10 | 11 | mutating public func update(with target: Node, state: Float) { 12 | action.update(with: target, state: state) 13 | } 14 | 15 | public mutating func start(with target: Node) { 16 | elapsed = 0 17 | action.start(with: target) 18 | } 19 | 20 | public mutating func stop(with target: Node) { 21 | action.stop(with: target) 22 | } 23 | 24 | public mutating func step(with target: Node, dt: Time) { 25 | elapsed += dt 26 | 27 | self.update(with: target, state: max(0, // needed for rewind. elapsed could be negative 28 | min(1, elapsed / max(duration, Float.ulpOfOne)) // division by 0 29 | ) 30 | ) 31 | } 32 | 33 | public var tag: Int = 0 34 | private(set) public var duration: Time = 0.0 35 | private(set) public var elapsed: Time = 0.0 36 | 37 | public var isDone: Bool { 38 | return elapsed > duration 39 | } 40 | 41 | private(set) public var action: ActionModel 42 | public init(action: ActionModel, duration: Time) { 43 | self.action = action 44 | self.duration = duration 45 | } 46 | 47 | } 48 | 49 | public extension ActionModel { 50 | public func continously(duration: Time) -> ActionContinousContainer { 51 | return ActionContinousContainer(action: self, duration: duration) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Fiber2D/ActionEase.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionEase.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 04.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | public typealias EaseBlock = (Float) -> Float 12 | 13 | public protocol EaseType { 14 | var calculationBlock: EaseBlock { get } 15 | } 16 | 17 | public enum EaseSine: EaseType { 18 | public var calculationBlock: EaseBlock { 19 | switch self { 20 | case .`in`: return sineEaseIn 21 | case .out: return sineEaseOut 22 | case .inOut: return sineEaseInOut 23 | } 24 | } 25 | 26 | case `in`, out, inOut 27 | } 28 | 29 | public struct ActionEaseContainer: ActionContainer, Continous { 30 | 31 | mutating public func update(with target: Node, state: Float) { 32 | var actionStep = action 33 | actionStep.update(with: target, state: easeBlock(state)) 34 | self.action = actionStep 35 | } 36 | 37 | public mutating func start(with target: Node) { 38 | elapsed = 0 39 | action.start(with: target) 40 | } 41 | 42 | public mutating func stop(with target: Node) { 43 | action.stop(with: target) 44 | } 45 | 46 | public mutating func step(with target: Node, dt: Time) { 47 | // same as continous 48 | elapsed += dt 49 | 50 | self.update(with: target, state: max(0, // needed for rewind. elapsed could be negative 51 | min(1, elapsed / max(duration, Float.ulpOfOne)) // division by 0 52 | ) 53 | ) 54 | } 55 | 56 | public var tag: Int = 0 57 | public let duration: Time 58 | private(set) public var elapsed: Time = 0.0 59 | 60 | public var isDone: Bool { 61 | return elapsed > duration 62 | } 63 | 64 | private(set) var action: ActionContainer 65 | public let easeType: EaseType 66 | private let easeBlock: EaseBlock 67 | public init(action: ActionContainer, easeType: EaseType) { 68 | self.action = action 69 | self.easeType = easeType 70 | self.easeBlock = easeType.calculationBlock 71 | 72 | guard let action = action as? FiniteTime else { 73 | assertionFailure("ERROR: You can't ease an endless action.") 74 | // just to silence compiler error 75 | self.duration = 0.0 76 | return 77 | } 78 | self.duration = action.duration 79 | } 80 | } 81 | 82 | public extension ActionContainer { 83 | public func ease(_ type: EaseType) -> ActionEaseContainer { 84 | return ActionEaseContainer(action: self, easeType: type) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Fiber2D/ActionInstant+Node.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionInstant+Node.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 05.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | /** 10 | This action executes a code block. The block takes no parameters and returns nothing. 11 | 12 | @note This is meant to be instant action. If you will create this a continous one, the block will be called every frame. 13 | 14 | ### Passing Parameters 15 | 16 | Blocks can access all variables in scope, both variables local to the method as well as instance variables. 17 | 18 | Running a block is often preferable then using Target-Action pattern. 19 | 20 | ### Memory Management 21 | 22 | To avoid potential memory management issues it is recommended to use a weak self reference inside 23 | the block. If you are knowledgeable about [memory management with ARC and blocks](http://stackoverflow.com/questions/20030873/always-pass-weak-reference-of-self-into-block-in-arc) 24 | you can omit the weakSelf reference at your discretion. Otherwise use [unowned self] attribute in block 25 | 26 | ### Code Example 27 | 28 | Example block that reads and modifies a variable in scope and rotates a node to illustrate the code syntax: 29 | 30 | let callBlock = ActionCallBlock { [unowned self] () -> () in 31 | self.someMethod() 32 | }.instantly 33 | 34 | self.run(action:callBlock) 35 | 36 | @see [Blocks Programming Guide](https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/Blocks/Articles/00_Introduction.html) 37 | */ 38 | public struct ActionCallBlock: ActionModel { 39 | public let block: () -> () 40 | 41 | /** 42 | * Creates the action with the specified block, to be used as a callback. 43 | * 44 | * @param block Block to run. Block takes no parameters, returns nothing. 45 | * 46 | * @return The call block action. 47 | */ 48 | public init(block: @escaping () -> ()) { 49 | self.block = block 50 | } 51 | 52 | public func update(state: Float) { 53 | block() 54 | } 55 | } 56 | 57 | /** 58 | This action will hide the target by setting its `visible` property to NO. 59 | 60 | The action is created using the default Action initializer, don't use target one. 61 | */ 62 | public struct ActionHide: ActionModel { 63 | public var target: Node! 64 | 65 | public init() { } 66 | public mutating func start(with target: Node) { 67 | self.target = target 68 | } 69 | public mutating func update(state: Float) { 70 | target.visible = false 71 | } 72 | } 73 | 74 | /** 75 | This action will make the target visible by setting its `visible` property to YES. 76 | 77 | The action is created using the default Action initializer, don't use target one. 78 | */ 79 | public struct ActionShow: ActionModel { 80 | public var target: Node! 81 | 82 | public init() { } 83 | public mutating func start(with target: Node) { 84 | self.target = target 85 | } 86 | public mutating func update(state: Float) { 87 | target.visible = true 88 | } 89 | } 90 | 91 | /** 92 | This action toggles the target's visibility by altering the `visible` property. 93 | 94 | The action is created using the default Action initializer, don't use target one. 95 | */ 96 | public struct ActionToggleVisibility: ActionModel { 97 | public var target: Node! 98 | 99 | public init() { } 100 | public mutating func start(with target: Node) { 101 | self.target = target 102 | } 103 | public mutating func update(state: Float) { 104 | target.visible = !target.visible 105 | } 106 | } 107 | 108 | /** This action will remove the node running this action from its parent. 109 | 110 | The action is created using the default Action initializer, don't use target one. 111 | */ 112 | public struct ActionRemove: ActionModel { 113 | public var target: Node! 114 | 115 | public init() { } 116 | public mutating func start(with target: Node) { 117 | self.target = target 118 | } 119 | public mutating func update(state: Float) { 120 | target.removeFromParent() 121 | } 122 | } 123 | 124 | -------------------------------------------------------------------------------- /Fiber2D/ActionInstant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionInstant.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 03.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public struct ActionInstantContainer: ActionContainer { 10 | 11 | mutating public func update(with target: Node, state: Float) { 12 | action.update(with: target, state: 1.0) 13 | } 14 | 15 | mutating public func start(with target: Node) { 16 | action.start(with: target) 17 | } 18 | 19 | mutating public func stop(with target: Node) { 20 | action.stop(with: target) 21 | } 22 | 23 | mutating public func step(with target: Node, dt: Time) { 24 | self.update(with: target, state: 1.0) 25 | } 26 | 27 | public var tag: Int = 0 28 | public var isDone: Bool { 29 | return true 30 | } 31 | 32 | private(set) var action: ActionModel 33 | init(action: ActionModel) { 34 | self.action = action 35 | } 36 | } 37 | 38 | public extension ActionModel { 39 | public var instantly: ActionInstantContainer { 40 | return ActionInstantContainer(action: self) 41 | } 42 | } 43 | 44 | extension ActionInstantContainer: FiniteTime { 45 | public var duration: Time { 46 | return 0.0 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /Fiber2D/ActionRewind.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionRewind.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 06.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | // This will not be actually very usable 10 | // Since we can't basically rewind action like MoveTo, 11 | // since we don't the start point 12 | // Maybe we should consider introducing "Rewindable" protocol, 13 | // but as of Action are chosed to be value types, that will be a bit hacky 14 | // You can't make a lot of use from it, but maybe there are some special cases 15 | public struct ActionRewindContainer: ActionContainer, Continous { 16 | 17 | mutating public func update(with target: Node, state: Float) { 18 | action.update(with: target, state: 1.0 - state) 19 | } 20 | 21 | public mutating func start(with target: Node) { 22 | elapsed = 0 23 | action.start(with: target) 24 | } 25 | 26 | public mutating func stop(with target: Node) { 27 | action.stop(with: target) 28 | } 29 | 30 | public mutating func step(with target: Node, dt: Time) { 31 | elapsed += dt 32 | 33 | self.update(with: target, state: max(0, // needed for rewind. elapsed could be negative 34 | min(1, elapsed / max(duration, Float.ulpOfOne)) // division by 0 35 | ) 36 | ) 37 | } 38 | 39 | public var tag: Int = 0 40 | public let duration: Time 41 | private(set) public var elapsed: Time = 0.0 42 | 43 | public var isDone: Bool { 44 | return elapsed > duration 45 | } 46 | 47 | private(set) public var action: ActionContainerFiniteTime 48 | public init(action: ActionContainerFiniteTime) { 49 | self.action = action 50 | self.duration = action.duration 51 | } 52 | } 53 | 54 | public extension ActionContainer where Self: FiniteTime { 55 | /** 56 | * This will return ActionRewindContainer for a given ActionContainer 57 | * Passed value must conform to FiniteTime protocol 58 | * 59 | * @see FiniteTime 60 | */ 61 | public var rewinded: ActionRewindContainer { 62 | return ActionRewindContainer(action: self) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Fiber2D/ActionSequence.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionSequenceContainer.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 04.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public struct ActionSequenceContainer: ActionContainer, Continous { 10 | 11 | mutating public func update(with target: Node, state: Float) { 12 | let t = state 13 | var found = 0 14 | var new_t: Float = 0.0 15 | if t < split { 16 | // action[0] 17 | found = 0 18 | if split != 0 { 19 | new_t = t / split 20 | } 21 | else { 22 | new_t = 1 23 | } 24 | } else { 25 | // action[1] 26 | found = 1 27 | if split == 1 { 28 | new_t = 1 29 | } 30 | else { 31 | new_t = (t - split) / (1 - split) 32 | } 33 | } 34 | if found == 1 { 35 | if last == -1 { 36 | // action[0] was skipped, execute it. 37 | actions[0].start(with: target) 38 | actions[0].update(with: target, state: 1.0) 39 | actions[0].stop(with: target) 40 | } 41 | else if last == 0 { 42 | // switching to action 1. stop action 0. 43 | actions[0].update(with: target, state: 1.0) 44 | actions[0].stop(with: target) 45 | } 46 | } else if found == 0 && last == 1 { 47 | // Reverse mode ? 48 | // XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode" 49 | // since it will require a hack to know if an action is on reverse mode or not. 50 | // "step" should be overriden, and the "reverseMode" value propagated to inner Sequences. 51 | actions[1].update(with: target, state: 0) 52 | actions[1].stop(with: target) 53 | } 54 | 55 | // Last action found and it is done. 56 | if found == last && actions[found].isDone { 57 | return 58 | } 59 | // New action. Start it. 60 | if found != last { 61 | actions[found].start(with: target) 62 | } 63 | actions[found].update(with: target, state: new_t) 64 | self.last = found 65 | } 66 | 67 | public mutating func start(with target: Node) { 68 | elapsed = 0 69 | self.split = actions[0].duration / max(duration, Float.ulpOfOne) 70 | self.last = -1 71 | } 72 | 73 | public mutating func stop(with target: Node) { 74 | // Issue #1305 75 | if last != -1 { 76 | actions[last].stop(with: target) 77 | } 78 | } 79 | 80 | public mutating func step(with target: Node, dt: Time) { 81 | elapsed += dt 82 | 83 | self.update(with: target, state: max(0, // needed for rewind. elapsed could be negative 84 | min(1, elapsed / max(duration, Float.ulpOfOne)) // division by 0 85 | ) 86 | ) 87 | } 88 | 89 | public var tag: Int = 0 90 | private(set) public var duration: Time = 0.0 91 | private(set) public var elapsed: Time = 0.0 92 | 93 | public var isDone: Bool { 94 | return elapsed > duration 95 | } 96 | 97 | private(set) var actions: [ActionContainerFiniteTime] = [] 98 | 99 | private var split: Float = 0.0 100 | private var last = -1 101 | 102 | init(first: ActionContainerFiniteTime, second: ActionContainerFiniteTime) { 103 | actions = [first, second] 104 | // Force unwrap because it won't work otherwise anyways 105 | duration = first.duration + second.duration 106 | } 107 | } 108 | 109 | /*extension ActionSequenceContainer { 110 | init(actions: ActionContainer...) { 111 | guard actions.count > 2 else { 112 | assertionFailure("ERROR: Sequence must contain at least 2 actions") 113 | return 114 | } 115 | 116 | let first = actions.first! 117 | var second: ActionContainer = actions[1] 118 | 119 | for i in 2.. ActionSequenceContainer { 129 | return ActionSequenceContainer(first: self, second: next) 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Fiber2D/ActionSpeed.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionSpeed.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 04.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public struct ActionSpeedContainer: ActionContainer, Continous { 10 | 11 | mutating public func update(with target: Node, state: Float) { 12 | action.update(with: target, state: state) 13 | } 14 | 15 | public mutating func start(with target: Node) { 16 | elapsed = 0 17 | action.start(with: target) 18 | } 19 | 20 | public mutating func stop(with target: Node) { 21 | action.stop(with: target) 22 | } 23 | 24 | public mutating func step(with target: Node, dt: Time) { 25 | elapsed += dt * speed 26 | 27 | self.update(with: target, state: max(0, // needed for rewind. elapsed could be negative 28 | min(1, elapsed / max(actionDuration, Float.ulpOfOne)) // division by 0 29 | ) 30 | ) 31 | } 32 | 33 | weak var target: Node? 34 | public var tag: Int = 0 35 | public let speed: Float 36 | public let duration: Time 37 | private let actionDuration: Time 38 | private(set) public var elapsed: Time = 0.0 39 | 40 | public var isDone: Bool { 41 | return elapsed > duration 42 | } 43 | 44 | private(set) var action: ActionContainerFiniteTime 45 | public init(action: ActionContainerFiniteTime, speed: Float) { 46 | self.action = action 47 | self.actionDuration = action.duration 48 | self.duration = actionDuration / speed 49 | self.speed = speed 50 | } 51 | } 52 | 53 | public extension ActionContainer where Self: FiniteTime { 54 | public func speed(_ s: Float) -> ActionSpeedContainer { 55 | return ActionSpeedContainer(action: self, speed: s) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Fiber2D/Behaviour.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Behaviour.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 09.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | /** 10 | * Behaviours are Components that can be enabled or disabled. 11 | */ 12 | public protocol Behaviour: Component { 13 | 14 | // Enabled Behaviours are Updated, disabled Behaviours are not 15 | var enabled: Bool { get set } 16 | } 17 | -------------------------------------------------------------------------------- /Fiber2D/BlendMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BlendMode.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 29.10.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftBGFX 10 | 11 | /// Blending modes used with certain node's `blendMode` property. BlendMode treats blend modes by descriptive name rather 12 | /// than a nondescriptive combination of blend mode identifiers. 13 | public struct BlendMode { 14 | internal var state: RenderStateOptions 15 | internal var equation: RenderStateOptions 16 | 17 | /// @name Getting a Built-In Blend Mode 18 | 19 | /// Disabled blending mode. Use this with fully opaque surfaces for extra performance. 20 | public static let disabledMode = BlendMode(state: .blend(source: .blendOne, 21 | destination: .blendZero), 22 | equation: .blendEquationAdd) 23 | /// Pre-multiplied alpha blending. (This is usually the default) 24 | public static let premultipliedAlphaMode = BlendMode(state: .blend(source: .blendSourceAlpha, 25 | destination: .blendInverseSourceAlpha), 26 | equation: .blendEquationAdd) 27 | 28 | /// Additive blending. (Similar to PhotoShop's linear dodge mode) 29 | public static let addMode = BlendMode(state: .blend(source: .blendOne, 30 | destination: .blendOne), 31 | equation: .blendEquationAdd) 32 | /// Regular alpha blending. 33 | public static let alphaMode = BlendMode(state: .blend(source: .blendOne, 34 | destination: .blendInverseSourceAlpha), 35 | equation: .blendEquationAdd) 36 | 37 | /// Multiply blending mode. (Similar to PhotoShop's burn mode) 38 | public static let multiplyMode = BlendMode(state: .blend(source: .blendDestinationColor, 39 | destination: .blendZero), 40 | equation: .blendEquationAdd) 41 | } 42 | 43 | extension BlendMode: Equatable { 44 | public static func ==(lhs: BlendMode, rhs: BlendMode) -> Bool { 45 | return lhs.state == rhs.state && lhs.equation == rhs.equation 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Fiber2D/Camera.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Camera.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 09.10.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | /** 12 | * The type of camera. 13 | */ 14 | public enum CameraType { 15 | case orthographic 16 | } 17 | 18 | /** 19 | * Defines a camera. 20 | */ 21 | public class Camera: Node { 22 | /** 23 | * The type of camera. 24 | * 25 | * @return The camera type. 26 | */ 27 | public let type: CameraType = .orthographic 28 | 29 | public unowned let viewport: ViewportNode 30 | 31 | init(viewport: ViewportNode) { 32 | self.viewport = viewport 33 | } 34 | 35 | override public var contentSize: Size { 36 | get { return parent!.contentSize } 37 | set {} 38 | } 39 | 40 | override public var contentSizeType: SizeType { 41 | get { return parent!.contentSizeType } 42 | set {} 43 | } 44 | 45 | override public var contentSizeInPoints: Size { 46 | get { return parent!.contentSizeInPoints } 47 | set {} 48 | } 49 | 50 | // Override nodeToParentMatrix so input (like touches) in the viewport can be transformed into the node space of the content of the viewport. 51 | public override var nodeToParentMatrix: Matrix4x4f { 52 | let cs = viewport.contentSizeInPoints * 0.5 53 | let hw = cs.width 54 | let hh = cs.height 55 | 56 | // Scale and translate matrix to convert from clip coordiates to viewport internal coordinates 57 | let toProj = Matrix4x4f(vec4(hw, 0.0, 0.0, 0.0), 58 | vec4(0.0, hh, 0.0, 0.0), 59 | vec4(0.0, 0.0, 1.0, 0.0), 60 | vec4(hw, hh, 0.0, 1.0)) 61 | return toProj * cameraMatrix 62 | } 63 | 64 | // Camera matrix is used for drawing the contents of the viewport, relative to the camera. 65 | public var cameraMatrix: Matrix4x4f { 66 | let cameraTransform = super.nodeToParentMatrix.inversed 67 | return viewport.projection * cameraTransform 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /Fiber2D/Color.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Color.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 04.08.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | public typealias Color = Vector4f 12 | 13 | public extension Color { 14 | public init(white: Float, alpha: Float) { 15 | self.init(white, white, white, alpha) 16 | } 17 | 18 | /** Hue in degrees 19 | HSV-RGB Conversion adapted from code by Mr. Evil, beyondunreal wiki 20 | */ 21 | public init(hue: Float, saturation: Float, brightness: Float, alpha: Float) { 22 | let chroma: Float = saturation * brightness 23 | let hueSection: Float = hue / 60.0 24 | let X: Float = chroma * (1.0 - abs(hueSection.truncatingRemainder(dividingBy: 2.0) - 1.0)) 25 | var r:Float = 0.0, g:Float = 0.0, b:Float = 0.0, a: Float = 0.0 26 | if hueSection < 1.0 { 27 | r = chroma 28 | g = X 29 | } else if hueSection < 2.0 { 30 | r = X 31 | g = chroma 32 | } else if hueSection < 3.0 { 33 | g = chroma 34 | b = X 35 | } else if hueSection < 4.0 { 36 | g = X 37 | b = chroma 38 | } else if hueSection < 5.0 { 39 | r = X 40 | b = chroma 41 | } else if hueSection <= 6.0 { 42 | r = chroma 43 | b = X 44 | } 45 | 46 | let Min: Float = brightness - chroma 47 | r += Min 48 | g += Min 49 | b += Min 50 | a = alpha 51 | 52 | self.init(r, g, b, a) 53 | } 54 | 55 | public mutating func premultiplyAlpha() { 56 | r *= a 57 | g *= a 58 | b *= a 59 | } 60 | 61 | public var premultiplyingAlpha: Color { 62 | var retVal = self 63 | retVal.premultiplyAlpha() 64 | return retVal 65 | } 66 | 67 | public var white: Float { 68 | return (r + g + b) / 3.0 69 | } 70 | } 71 | 72 | // MARK: Constants 73 | public extension Color { 74 | public static let clear = Color(0.0) 75 | public static let darkGray = Color(white: 1.0/3.0, alpha: 1) 76 | public static let lightGray = Color(white: 2.0/3.0, alpha:1) 77 | public static let white = Color(white: 1, alpha: 1) 78 | public static let gray = Color(white: 0.5, alpha: 1) 79 | 80 | public static let blue = Color(0.0, 0.0, 1.0, 1.0) 81 | public static let red = Color(1.0, 0.0, 0.0, 1.0) 82 | public static let green = Color(0.0, 1.0, 0.0, 1.0) 83 | 84 | public static let black = Color(0, 0, 0, 1) 85 | public static let cyan = Color(0, 1, 1 , 1) 86 | public static let yellow = Color(1, 1, 0 , 1) 87 | public static let magenta = Color(1, 0, 1 , 1) 88 | public static let orange = Color(1, 0.5, 0 , 1) 89 | public static let purple = Color(0.5, 0, 0.5 , 1) 90 | public static let brown = Color(0.6, 0.4, 0.2 , 1) 91 | } 92 | 93 | public extension Color { 94 | public var uint32Representation: UInt32 { 95 | let r = UInt32(self.r * 255) << 24 96 | let g = UInt32(self.g * 255) << 16 97 | let b = UInt32(self.b * 255) << 8 98 | let a = UInt32(self.a * 255) 99 | 100 | return r | g | b | a 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Fiber2D/ColorNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorNode.swift 3 | // 4 | // Created by Andrey Volodin on 06.07.16. 5 | // Copyright © 2016. All rights reserved. 6 | // 7 | 8 | import SwiftMath 9 | import SwiftBGFX 10 | 11 | /** 12 | Draws a rectangle filled with a solid color. 13 | */ 14 | open class ColorNode: Node { 15 | /** 16 | * Creates a node with color, width and height in Points. 17 | * 18 | * @param color Color of the node. 19 | * @param size Width and Height of the node. 20 | * 21 | * @return An initialized ColorNode Object. 22 | * @see Color 23 | */ 24 | public init(color: Color = .clear, size: Size = .zero) { 25 | super.init() 26 | self.color = color 27 | self.contentSizeInPoints = size 28 | self.add(component: BackgroundColorRenderComponent()) 29 | } 30 | } 31 | 32 | public class BackgroundColorRenderComponent: QuadRenderer { 33 | 34 | public init() { 35 | super.init(material: Material(technique: .positionColor)) 36 | } 37 | 38 | public override func onAdd(to owner: Node) { 39 | super.onAdd(to: owner) 40 | 41 | self.update(for: owner.contentSizeInPoints) 42 | owner.onContentSizeInPointsChanged.subscribe(on: self) { 43 | self.update(for: $0) 44 | } 45 | 46 | self.geometry.color = owner.displayedColor.premultiplyingAlpha 47 | owner.onDisplayedColorChanged.subscribe(on: self) { 48 | self.geometry.color = $0.premultiplyingAlpha 49 | } 50 | } 51 | 52 | public override func onRemove() { 53 | // Do it before super, as it assigns owner to nil 54 | owner?.onContentSizeInPointsChanged.cancelSubscription(for: self) 55 | owner?.onDisplayedColorChanged.cancelSubscription(for: self) 56 | super.onRemove() 57 | } 58 | 59 | public func update(for size: Size) { 60 | geometry.positions = [vec4(0, 0, 0, 1), 61 | vec4(size.width, 0, 0, 1), 62 | vec4(size.width, size.height, 0, 1), 63 | vec4(0, size.height, 0, 1)] 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Fiber2D/Component.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Component.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 09.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | /** 10 | * Protocol for all components. Implemented as protocol to allow structs for components as well. 11 | * 12 | * @note You have to remember owner in onAdd implementation, it is not set anywhere internally 13 | */ 14 | public protocol Component: Tagged { 15 | weak var owner: Node? { get /*set*/} 16 | 17 | func onAdd(to owner: Node) 18 | func onRemove() 19 | } 20 | 21 | /** 22 | * Components are meant to be unique by tag withing one Node 23 | */ 24 | /*extension Component: Equatable { 25 | public static func ==(lhs: Component, rhs: Component) -> Bool { 26 | return lhs.tag == rhs.tag 27 | } 28 | }*/ 29 | 30 | /** 31 | * Base class for everything attached to Nodes. 32 | */ 33 | open class ComponentBase: Component { 34 | public weak var owner: Node? 35 | 36 | open var tag: Int = 0 37 | 38 | public init() {} 39 | 40 | open func onAdd(to owner: Node) { 41 | self.owner = owner 42 | } 43 | 44 | open func onRemove() { 45 | self.owner = nil 46 | } 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /Fiber2D/Director+Internal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Director+Internal.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 29.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | #if os(iOS) || os(tvOS) 11 | import QuartzCore 12 | #endif 13 | #if os(macOS) 14 | import Quartz 15 | #endif 16 | #if os(Android) || os(Linux) 17 | import Glibc 18 | #endif 19 | 20 | /** 21 | Get the current time in seconds. 22 | */ 23 | internal extension Time { 24 | internal static var absoluteTime: Time { 25 | #if os(iOS) || os(tvOS) || os(OSX) || os(watchOS) 26 | return Time(CACurrentMediaTime()) 27 | #else 28 | var t = timespec() 29 | clock_gettime(CLOCK_MONOTONIC, &t) 30 | 31 | return Time(t.tv_sec) + Time(t.tv_nsec) / Time(1.0e-9) 32 | #endif 33 | } 34 | } 35 | 36 | internal extension Director { 37 | /// Add a block to be called when the GPU finishes rendering a frame. 38 | /// This is used to pool rendering resources (renderers, buffers, textures, etc) without stalling the GPU pipeline. 39 | internal func add(frameCompletionHandler: @escaping ()->()) { 40 | self.view!.add(frameCompletionHandler: frameCompletionHandler) 41 | } 42 | 43 | internal func antiFlickrDrawCall() { 44 | // Questionable "anti-flickr", extra draw call: 45 | // overridden for android. 46 | self.mainLoopBody() 47 | } 48 | 49 | internal func calculateDeltaTime() { 50 | let now = Time.absoluteTime 51 | // new delta time 52 | if nextDeltaTimeZero { 53 | self.dt = 0 54 | self.nextDeltaTimeZero = false 55 | } else { 56 | self.dt = now - lastUpdate 57 | self.dt = max(0, dt) 58 | } 59 | // If we are debugging our code, prevent big delta time 60 | if dt > 0.2 { 61 | self.dt = 1 / 60.0 62 | } 63 | self.lastUpdate = now 64 | } 65 | 66 | internal var flipY: Float { 67 | #if os(iOS) || os(tvOS) 68 | return -1.0 69 | #endif 70 | #if os(OSX) || os(Linux) || os(Android) 71 | return 1.0 72 | #endif 73 | } 74 | 75 | /// Rect of the visible screen area in GL coordinates. 76 | internal var viewportRect: Rect { 77 | var projection = runningScene!.projection 78 | // TODO It's _possible_ that a user will use a non-axis aligned projection. Weird, but possible. 79 | let projectionInv = projection.inversed 80 | // Calculate z=0 using -> transform*[0, 0, 0, 1]/w 81 | let zClip = projection[3, 2] / projection[3, 3] 82 | // Bottom left and top right coords of viewport in clip coords. 83 | let clipBL = Vector3f(-1.0, -1.0, zClip) 84 | let clipTR = Vector3f(1.0, 1.0, zClip) 85 | // Bottom left and top right coords in GL coords. 86 | let glBL = projectionInv.multiplyAndProject(v: clipBL).xy 87 | let glTR = projectionInv.multiplyAndProject(v: clipTR).xy 88 | return Rect(bottomLeft: glBL, topRight: glTR) 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Fiber2D/Director+RunLoop.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Director+RunLoop.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 15.12.16. 6 | // 7 | // 8 | 9 | public extension Director { 10 | 11 | /** 12 | Start the main run loop of the game, drawing and updating. 13 | Generally, as a user, you will start the main loop by running a scene, using `presentScene` 14 | @see stopRunLoop 15 | */ 16 | public func startRunLoop() { 17 | nextDeltaTimeZero = true 18 | isAnimating = true 19 | } 20 | 21 | /** 22 | Stops the run loop. Nothing will be drawn or simulated. The main loop won't be triggered anymore. 23 | If you want to pause your game call [pause] instead. 24 | */ 25 | public func stopRunLoop() { 26 | isAnimating = false 27 | } 28 | 29 | /** Run the main loop once, handle updates and draw scene 30 | This method is called every frame. Don't call it manually. 31 | */ 32 | public func mainLoopBody() { 33 | guard isAnimating else { 34 | return 35 | } 36 | Director.pushCurrentDirector(self) 37 | /* calculate "global" dt */ 38 | calculateDeltaTime() 39 | /* tick before glClear: issue #533 */ 40 | guard let runningScene = runningScene else { 41 | return 42 | } 43 | 44 | if !isPaused { 45 | runningScene.scheduler.update(dt) 46 | } 47 | /* to avoid flickr, nextScene MUST be here: after tick and before draw. */ 48 | if nextScene != nil { 49 | self.setNextScene() 50 | } 51 | view!.beginFrame() 52 | let projection = runningScene.projection 53 | renderer.prepare(withProjection: projection) 54 | 55 | //CCRenderer.bindRenderer(renderer) 56 | currentRenderer = renderer 57 | renderer.enqueueClear(color: runningScene.colorRGBA) 58 | // Render 59 | runningScene.visit(renderer, parentTransform: projection) 60 | notificationNode?.visit(renderer, parentTransform: projection) 61 | 62 | //CCRenderer.bindRenderer(nil) 63 | currentRenderer = nil 64 | view!.add { 65 | // TODO: Completion handlers here 66 | } 67 | renderer.flush() 68 | totalFrames += 1 69 | Director.popCurrentDirector() 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /Fiber2D/Director+SDL.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Director+SDL.swift 3 | // Fiber2D-iOS 4 | // 5 | // Created by Andrey Volodin on 08.01.17. 6 | // 7 | // 8 | 9 | #if os(Android) 10 | import CSDL2 11 | import SwiftMath 12 | 13 | internal extension Director { 14 | func convertSDLTouchEventToInput(_ event: SDL_TouchFingerEvent) -> Input { 15 | let normalizedPosition = p2d(event.x, event.y) 16 | let positionInPoints = normalizedPosition * viewSize 17 | 18 | return Input(screenPosition: convertToGL(positionInPoints), force: event.pressure) 19 | } 20 | } 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /Fiber2D/Director+UIKit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Director+UIKit.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 03.01.17. 6 | // 7 | // 8 | 9 | #if os(iOS) || os(tvOS) 10 | import UIKit 11 | import SwiftMath 12 | 13 | internal extension Director { 14 | internal func convertUITouchToInput(_ touch: UITouch) -> Input { 15 | let viewLocation = touch.location(in: view as? UIView) 16 | 17 | return Input(screenPosition: convertToGL(Point(viewLocation)), force: Float(touch.force)) 18 | } 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /Fiber2D/Director+macOS.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Director+macOS.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 09.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | #if os(OSX) 10 | import SwiftMath 11 | import AppKit 12 | 13 | internal extension Director { 14 | internal func convertEventToGL(_ event: NSEvent) -> Point { 15 | if #available(OSX 10.11, *) { 16 | let point: NSPoint = (self.view as! NSView).convert(event.locationInWindow, from: nil) 17 | return self.convertToGL(Point(NSPointToCGPoint(point))) 18 | } 19 | return .zero 20 | } 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /Fiber2D/Extensions-Temp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Extensions-Temp.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 04.08.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | #if os(iOS) || os(tvOS) || os(OSX) 10 | 11 | import SwiftMath 12 | import CoreGraphics 13 | import Darwin 14 | 15 | extension Vector2f { 16 | var cgPoint: CGPoint { 17 | return CGPoint(x: Double(x), y: Double(y)) 18 | } 19 | 20 | init(_ cgPoint: CGPoint) { 21 | self.init(Float(cgPoint.x), Float(cgPoint.y)) 22 | } 23 | } 24 | 25 | public extension Size { 26 | public init(CGSize: CGSize) { 27 | self.init(Float(CGSize.width), Float(CGSize.height)) 28 | } 29 | 30 | var cgSize: CGSize { 31 | return CGSize(width: CGFloat(width), height: CGFloat(height)) 32 | } 33 | } 34 | 35 | extension Rect { 36 | init(CGRect: CGRect) { 37 | self.init(origin: p2d(CGRect.origin), size: Size(CGSize: CGRect.size)) 38 | } 39 | } 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /Fiber2D/Image.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Image.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 24.10.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftMath 11 | 12 | public struct ImageOptions { 13 | /** 14 | How much to rescale the image while loading it. 15 | 16 | The default value is 1.0. 17 | 18 | @warning Some image loaders may only support inverse powers of two (1/2, 1/4, etc) 19 | */ 20 | public var rescaleFactor: Float = 1.0 21 | 22 | /** 23 | Should the image dimensions be expanded to a power of two while loading? 24 | 25 | The default value is `false`. 26 | */ 27 | public var shouldExpandToPOT: Bool = false 28 | 29 | /** 30 | Should the image alpha be premultiplied while loading? 31 | 32 | The default value is `true`. 33 | 34 | @warning Some image loaders only support pre-multiplied alpha. 35 | */ 36 | public var shouldPremultiply: Bool = true 37 | 38 | public var shouldFlipX = false 39 | public var shouldFlipY = false 40 | 41 | public static let `default` = ImageOptions() 42 | } 43 | 44 | 45 | public final class Image { 46 | /** 47 | Initialize a new image with raw pixel data. All default options are applied to the image. 48 | 49 | @param pixelSize Size of the image in pixels. 50 | @param contentScale Content scale of the image. 51 | @param pixelData A pointer to raw, tightly packed, RGBA8 pixel data. 52 | @param options Optional parameter of type ImageOptions. 53 | 54 | @return An image object that wraps the given pixel data. 55 | */ 56 | public init(pixelSize: Size, contentScale: Float, pixelData: Data?, options: ImageOptions = .default) { 57 | 58 | self.contentScale = contentScale 59 | self.contentSize = pixelSize * (1.0 / contentScale) 60 | 61 | self.options = options 62 | self.pixelData = pixelData 63 | 64 | self.sizeInPixels.width = floor(pixelSize.width) 65 | self.sizeInPixels.height = floor(pixelSize.height) 66 | 67 | } 68 | 69 | /** 70 | @param file The File to load the image data from. 71 | @param options Optional parameter of type ImageOptions. 72 | 73 | @return An image loaded from the file. 74 | */ 75 | public convenience init(file: File, options: ImageOptions = .default) { 76 | //if file.name.hasSuffix(".png") { 77 | // use libpng 78 | //} else { 79 | // use other loader (i.e. CoreGraphics) 80 | //} 81 | 82 | // FIXME: Only works for .png for now 83 | self.init(pngFile: file, options: options) 84 | } 85 | 86 | /** 87 | Size of the image's bitmap in pixels. 88 | */ 89 | internal(set) public var sizeInPixels = Size.zero 90 | 91 | /** 92 | Bitmap data pointer. The format will always be RGBA8. 93 | */ 94 | internal(set) public var pixelData: Data? 95 | 96 | /** 97 | Content scale of the bitmap 98 | */ 99 | internal(set) public var contentScale: Float 100 | 101 | /** 102 | User assignable content size of the image in points. 103 | 104 | This value may not equal pixelSize/contentScale if the image is padded. 105 | It defaults to the original size of the image in points. 106 | */ 107 | public var contentSize: Size 108 | 109 | internal var options: ImageOptions 110 | } 111 | -------------------------------------------------------------------------------- /Fiber2D/Layout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Layout.swift 3 | // 4 | // Created by Andrey Volodin on 26.07.16. 5 | // Copyright © 2016. All rights reserved. 6 | // 7 | 8 | import SwiftMath 9 | 10 | /** 11 | The layout node is an abstract class. It will take control of its childrens' positions. 12 | 13 | Do not create instances of Layout, instead use one of its subclasses: 14 | 15 | - LayoutBox 16 | 17 | **Note:** If you are using a layout node you should not set the positions of the layout node's children manually or via move actions. 18 | 19 | ### Subclassing Note 20 | 21 | Layout is an abstract class for nodes that provide layouts. You should subclass Layout to create your own layout node. 22 | Implement the layout method to create your own layout. 23 | */ 24 | public class Layout: Node { 25 | private var _needsLayout = false 26 | 27 | override init() { 28 | super.init() 29 | self.needsLayout() 30 | onChildWasAdded.subscribe(on: self) { _ in 31 | self.sortAllChildren() 32 | self.layout() 33 | } 34 | 35 | onChildWasRemoved.subscribe(on: self) { 36 | _ in self.needsLayout() 37 | } 38 | } 39 | 40 | /** @name Methods Implemented by Subclasses */ 41 | 42 | /** 43 | * Called whenever the node needs to layout its children again. Normally, there is no need to call this method directly. 44 | */ 45 | public func needsLayout() { 46 | self._needsLayout = true 47 | } 48 | 49 | /** 50 | The layout method layouts the children according to the rules implemented in a CCLayout subclass. 51 | @note Your subclass must call `super.layout()` to reset the _needsLayout flag. Not calling super could cause the layout 52 | to unnecessarily run the layout method every frame. 53 | */ 54 | public func layout() { 55 | self._needsLayout = false 56 | } 57 | 58 | override public var contentSize: Size { 59 | get { 60 | if _needsLayout { 61 | self.layout() 62 | } 63 | return super.contentSize 64 | } 65 | set { 66 | super.contentSize = newValue 67 | } 68 | } 69 | 70 | override func visit(_ renderer: Renderer, parentTransform: Matrix4x4f) { 71 | if _needsLayout { 72 | self.layout() 73 | } 74 | super.visit(renderer, parentTransform: parentTransform) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Fiber2D/LayoutBox.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LayoutBox.swift 3 | // 4 | // Created by Andrey Volodin on 26.07.16. 5 | // Copyright © 2016. All rights reserved. 6 | // 7 | 8 | import SwiftMath 9 | #if os(macOS) || os(iOS) || os(tvOS) 10 | import Darwin 11 | #else 12 | import Glibc 13 | #endif 14 | 15 | /** 16 | Declares the possible directions for laying out nodes in a LayoutBox. 17 | */ 18 | public enum LayoutBoxDirection { 19 | /// The children will be horizontally aligned. 20 | case horizontal 21 | /// The children will be vertically aligned. 22 | case vertical 23 | } 24 | 25 | func roundUpToEven(_ f: Float) -> Float { 26 | return ceilf(f / 2.0) * 2.0 27 | } 28 | 29 | /** 30 | The box layout lays out its child nodes in a horizontal row or a vertical column. Optionally you can set a spacing between the child nodes. 31 | 32 | @note In order to layout nodes in a grid, you can add one or more LayoutBox as child node with the opposite layout direction, ie the parent 33 | box layout node uses vertical and the child box layout nodes use horizontal LayoutBoxDirection to create a grid of nodes. 34 | */ 35 | public class LayoutBox: Layout { 36 | /** @name Layout Options */ 37 | /** 38 | The direction is either horizontal or vertical. 39 | @see LayoutBoxDirection 40 | */ 41 | public var direction: LayoutBoxDirection = .horizontal { 42 | didSet { 43 | needsLayout() 44 | } 45 | } 46 | 47 | /** 48 | The spacing in points between the child nodes. 49 | */ 50 | public var spacing: Float = 0.0 { 51 | didSet { 52 | needsLayout() 53 | } 54 | } 55 | 56 | override public func layout() { 57 | super.layout() 58 | 59 | guard children.count > 0 else { 60 | return 61 | } 62 | 63 | if direction == .horizontal { 64 | // Get the maximum height 65 | var maxHeight: Float = 0 66 | for child in self.children { 67 | let height = Float(child.contentSizeInPoints.height) 68 | if height > maxHeight { 69 | maxHeight = height 70 | } 71 | } 72 | // Position the nodes 73 | var width: Float = 0 74 | for child in self.children { 75 | let childSize: Size = child.contentSizeInPoints 76 | let offset: Point = child.anchorPointInPoints 77 | let localPos: Point = p2d(roundf(width), roundf(maxHeight - childSize.height / 2.0)) 78 | let position: Point = localPos + offset 79 | child.position = position 80 | child.positionType = PositionType.points 81 | width += Float(childSize.width) 82 | width += spacing 83 | } 84 | // Account for last added increment 85 | width -= spacing 86 | if width < 0 { 87 | width = 0 88 | } 89 | self.contentSizeType = SizeType.points 90 | self.contentSize = Size(width: Float(roundUpToEven(width)), height: Float(roundUpToEven(maxHeight))) 91 | } else { 92 | // Get the maximum width 93 | var maxWidth: Float = 0 94 | for child in self.children { 95 | let width = Float(child.contentSizeInPoints.width) 96 | if width > maxWidth { 97 | maxWidth = width 98 | } 99 | } 100 | // Position the nodes 101 | var height: Float = 0 102 | for child in self.children { 103 | let childSize: Size = child.contentSizeInPoints 104 | let offset: Point = child.anchorPointInPoints 105 | let localPos: Point = p2d(Float(roundf((maxWidth - Float(childSize.width)) / 2.0)), Float(roundf(height))) 106 | let position: Point = localPos + offset 107 | child.position = position 108 | child.positionType = PositionType.points 109 | height += Float(childSize.height) 110 | height += spacing 111 | } 112 | // Account for last added increment 113 | height -= spacing 114 | if height < 0 { 115 | height = 0 116 | } 117 | self.contentSizeType = SizeType.points 118 | self.contentSize = Size(width: Float(roundUpToEven(maxWidth)), height: Float(roundUpToEven(height))) 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Fiber2D/Node+Projection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Node+Projection.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 02.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | extension Matrix4x4f { 12 | static func orthoProjection(for target: Node) -> Matrix4x4f { 13 | let size = target.contentSizeInPoints 14 | let w = Float(size.width) 15 | let h = Float(size.height) 16 | 17 | return Matrix4x4f.ortho(left: 0, right: w, bottom: 0, top: h, near: -1024, far: 1024) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Fiber2D/Node+Scene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Node+Scene.swift 3 | // 4 | // Created by Andrey Volodin on 23.07.16. 5 | // Copyright © 2016. All rights reserved. 6 | // 7 | 8 | internal extension Node { 9 | internal func _onEnter() { 10 | assert(self.scene != nil, "Missing scene on node. Was it not added to the hierarchy?") 11 | children.forEach { $0._onEnter() } 12 | let wasRunning: Bool = self.active 13 | // Add queued actions or scheduled code, if needed: 14 | for a in queuedActions { 15 | run(action: a) 16 | } 17 | self.queuedActions.removeAll() 18 | 19 | for c in queuedComponents { 20 | add(component: c) 21 | } 22 | self.queuedComponents.removeAll() 23 | 24 | scheduler!.schedule(target: self) 25 | 26 | self.isInActiveScene = true 27 | self.wasRunning(wasRunning) 28 | 29 | components.forEach { 30 | scene!.system(for: $0)?.add(component: $0) 31 | } 32 | onEnter.fire(()) 33 | } 34 | 35 | internal func _onEnterTransitionDidFinish() { 36 | children.forEach { $0._onEnterTransitionDidFinish() } 37 | onEnterTransitionDidFinish.fire(()) 38 | } 39 | 40 | internal func _onExitTransitionDidStart() { 41 | children.forEach { $0._onExitTransitionDidStart() } 42 | onExitTransitionDidStart.fire(()) 43 | } 44 | 45 | internal func _onExit() { 46 | let wasRunning: Bool = self.active 47 | self.isInActiveScene = false 48 | self.wasRunning(wasRunning) 49 | 50 | components.forEach { 51 | self.scene!.system(for: $0)?.remove(component: $0) 52 | } 53 | if updatableComponents.count > 0 || fixedUpdatableComponents.count > 0 { 54 | scheduler!.unscheduleUpdates(from: self) 55 | } 56 | onExit.fire(()) 57 | children.forEach { $0._onExit() } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Fiber2D/Node+Transform.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Node+Transform.swift 3 | // 4 | // Created by Andrey Volodin on 23.07.16. 5 | // Copyright © 2016. All rights reserved. 6 | // 7 | 8 | import Foundation 9 | import SwiftMath 10 | 11 | public extension Node { 12 | 13 | @inline(__always) 14 | internal func calculateTransformIfNeeded() { 15 | guard isTransformDirty else { 16 | return 17 | } 18 | 19 | // Get content size 20 | // Convert position to points 21 | var positionInPoints: p2d 22 | if positionType.isBasicPoints { 23 | // Optimization for basic points (most common case) 24 | positionInPoints = position 25 | } else { 26 | positionInPoints = self.positionInPoints 27 | } 28 | 29 | // Get x and y 30 | var x = positionInPoints.x 31 | var y = positionInPoints.y 32 | // Rotation values 33 | // Change rotation code to handle X and Y 34 | // If we skew with the exact same value for both x and y then we're simply just rotating 35 | var cx: Float = 1 36 | var sx: Float = 0 37 | var cy: Float = 1 38 | var sy: Float = 0 39 | if rotationalSkewX != .zero || rotationalSkewY != .zero { 40 | sincos(-rotationalSkewX, &sx, &cx) 41 | sincos(-rotationalSkewY, &sy, &cy) 42 | } 43 | 44 | let needsSkewMatrix = skewX != .zero || skewY != .zero 45 | var scaleFactor: Float = 1 46 | if scaleType == .scaled { 47 | scaleFactor = Setup.shared.UIScale 48 | } 49 | // optimization: 50 | // inline anchor point calculation if skew is not needed 51 | // Adjusted transform calculation for rotational skew 52 | if !needsSkewMatrix && !anchorPointInPoints.isZero { 53 | x += cy * -anchorPointInPoints.x * scaleX * scaleFactor + -sx * -anchorPointInPoints.y * scaleY 54 | y += sy * -anchorPointInPoints.x * scaleX * scaleFactor + cx * -anchorPointInPoints.y * scaleY 55 | } 56 | // Build Transform Matrix 57 | // Adjusted transfor m calculation for rotational skew 58 | self.transform = Matrix4x4f(vec4(cy * scaleX * scaleFactor, sy * scaleX * scaleFactor, 0.0, 0.0), 59 | vec4(-sx * scaleY * scaleFactor, cx * scaleY * scaleFactor, 0.0, 0.0), 60 | vec4(0, 0, 1, 0), 61 | vec4(x, y, vertexZ, 1)) 62 | // XXX: Try to inline skew 63 | // If skew is needed, apply skew and then anchor point 64 | if needsSkewMatrix { 65 | let skewMatrix = Matrix4x4f(vec4(1.0, tan(skewY), 0.0, 0.0), 66 | vec4(tan(skewX), 1.0, 0.0, 0.0), 67 | vec4(0.0, 0.0, 1.0, 0.0), 68 | vec4(0.0, 0.0, 0.0, 1.0)) 69 | self.transform = transform * skewMatrix 70 | // adjust anchor point 71 | if !anchorPointInPoints.isZero { 72 | self.transform = transform.translated(by: vec3(-anchorPointInPoints)) 73 | } 74 | } 75 | 76 | isTransformDirty = false 77 | } 78 | 79 | /** Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates. The matrix is in points. 80 | @see nodeToParentMatrix 81 | */ 82 | public var parentToNodeMatrix: Matrix4x4f { 83 | if isInverseTransformDirty { 84 | inverseTransform = nodeToParentMatrix.inversed 85 | isInverseTransformDirty = false 86 | } 87 | 88 | return inverseTransform 89 | } 90 | 91 | /** Returns the world transform matrix. The matrix is in points. 92 | @see nodeToParentMatrix 93 | @see worldToNodeMatrix 94 | */ 95 | public var nodeToWorldMatrix: Matrix4x4f { 96 | var t = self.nodeToParentMatrix 97 | var p = parent 98 | while p != nil { 99 | t = p!.nodeToParentMatrix * t 100 | p = p!.parent 101 | } 102 | return t 103 | } 104 | 105 | /** Returns the inverse world transform matrix. The matrix is in points. 106 | @see nodeToWorldTransform 107 | */ 108 | public var worldToNodeMatrix: Matrix4x4f { 109 | return nodeToWorldMatrix.inversed 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsBody+Internal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsBody+Internal.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 20.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import CChipmunk2D 10 | 11 | internal func internalBodySetMass(_ body: UnsafeMutablePointer, _ mass: cpFloat) 12 | { 13 | cpBodyActivate(body); 14 | body.pointee.m = mass; 15 | body.pointee.m_inv = 1.0 / mass 16 | //cpAssertSaneBody(body); 17 | } 18 | 19 | internal func internalBodyUpdateVelocity(_ body: UnsafeMutablePointer?, _ gravity: cpVect, _ damping: cpFloat, _ dt: cpFloat) { 20 | cpBodyUpdateVelocity(body, cpvzero, damping, dt) 21 | // Skip kinematic bodies. 22 | guard cpBodyGetType(body) != CP_BODY_TYPE_KINEMATIC else { 23 | return 24 | } 25 | 26 | let physicsBody = Unmanaged.fromOpaque(cpBodyGetUserData(body)).takeUnretainedValue() 27 | 28 | if physicsBody.isGravityEnabled { 29 | body!.pointee.v = cpvclamp(cpvadd(cpvmult(body!.pointee.v, damping), cpvmult(cpvadd(gravity, cpvmult(body!.pointee.f, body!.pointee.m_inv)), dt)), cpFloat(physicsBody.velocityLimit)) 30 | } else { 31 | body!.pointee.v = cpvclamp(cpvadd(cpvmult(body!.pointee.v, damping), cpvmult(cpvmult(body!.pointee.f, body!.pointee.m_inv), dt)), cpFloat(physicsBody.velocityLimit)) 32 | } 33 | let w_limit = cpFloat(physicsBody.angularVelocityLimit) 34 | body!.pointee.w = cpfclamp(body!.pointee.w * damping + body!.pointee.t * body!.pointee.i_inv * dt, -w_limit, w_limit) 35 | 36 | // Reset forces. 37 | body!.pointee.f = cpvzero 38 | //to check body sanity 39 | cpBodySetTorque(body, 0.0) 40 | } 41 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsBody+Joints.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsBody+Joints.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 20.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public extension PhysicsBody { 10 | 11 | internal func remove(joint: PhysicsJoint) { 12 | joints.removeObject(joint) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsContact.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsContact.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 22.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import CChipmunk2D 11 | 12 | public enum EventCode { 13 | case none, begin, presolve, postsolve, separate 14 | } 15 | 16 | /** 17 | * An object that implements the PhysicsContactDelegate protocol can respond 18 | * when two physics bodies are in contact with each other in a physics world. 19 | * To receive contact messages, you set the contactDelegate property of a PhysicsWorld object. 20 | * The delegate is called when a contact starts or ends. 21 | */ 22 | public protocol PhysicsContactDelegate: class { 23 | /** Called when two bodies first contact each other. */ 24 | func didBegin(contact: PhysicsContact) 25 | 26 | /** Called when the contact ends between two physics bodies. */ 27 | func didEnd(contact: PhysicsContact) 28 | } 29 | 30 | public struct PhysicsContactData { 31 | let points: [Point] 32 | let normal: Vector2f 33 | } 34 | 35 | /** 36 | * @brief Contact information. 37 | 38 | * It will be created automatically when two shape contact with each other. 39 | * And it will be destroyed automatically when two shape separated. 40 | */ 41 | public struct PhysicsContact { 42 | /** Get contact shape A. */ 43 | public unowned var shapeA: PhysicsShape 44 | 45 | /** Get contact shape B. */ 46 | public unowned var shapeB: PhysicsShape 47 | 48 | /** Get contact data */ 49 | public var contactData: PhysicsContactData 50 | 51 | /** Get previous contact data */ 52 | //public let previousContactData: PhysicsContactData 53 | 54 | internal let arbiter: UnsafeMutablePointer! 55 | 56 | internal init(shapeA: PhysicsShape, shapeB: PhysicsShape, arb: UnsafeMutablePointer!) { 57 | self.shapeA = shapeA 58 | self.shapeB = shapeB 59 | self.arbiter = arb 60 | let count = cpArbiterGetCount(arb) 61 | var points = [Point](repeating: Point.zero, count: Int(count)) 62 | for i in 0..]() 71 | internal func createConstraints() {} 72 | internal func chipmunkInitJoint() -> Bool { 73 | guard !chipmunkInitialized else { 74 | return chipmunkInitialized 75 | } 76 | createConstraints() 77 | 78 | for subjoint in chipmunkConstraints { 79 | cpConstraintSetMaxForce(subjoint, cpFloat(maxForce)) 80 | cpConstraintSetErrorBias(subjoint, cpFloat(pow(1.0 - 0.15, 60.0))) 81 | cpSpaceAddConstraint(world!.chipmunkSpace, subjoint) 82 | } 83 | 84 | chipmunkInitialized = true 85 | 86 | return chipmunkInitialized 87 | } 88 | 89 | deinit { 90 | collisionEnabled = false 91 | 92 | for cpc in chipmunkConstraints { 93 | cpConstraintFree(cpc) 94 | } 95 | } 96 | } 97 | 98 | public extension PhysicsJoint { 99 | /** Remove the joint from the world. */ 100 | public func removeFormWorld() { world?.remove(joint: self) } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsShape+Internal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsShape+Internal.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 20.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import CChipmunk2D 10 | 11 | internal extension PhysicsShape { 12 | func add(shape: UnsafeMutablePointer) { 13 | cpShapeSetUserData(shape, Unmanaged.passRetained(self).toOpaque()) 14 | cpShapeSetFilter(shape, cpShapeFilterNew(cpGroup(group), CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)) 15 | chipmunkShapes.append(shape) 16 | } 17 | 18 | } 19 | 20 | internal let SHARED_BODY = cpBodyNewStatic() 21 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsShapeBox.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsShapeBox.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 22.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import CChipmunk2D 11 | 12 | public class PhysicsShapeBox: PhysicsShapePolygon { 13 | /** 14 | * Get this box's width and height. 15 | * 16 | * @return An Size object. 17 | */ 18 | public var size: Size { 19 | let shape = chipmunkShapes.first! 20 | return Size(cpv(cpvdist(cpPolyShapeGetVert(shape, 1), cpPolyShapeGetVert(shape, 2)), 21 | cpvdist(cpPolyShapeGetVert(shape, 0), cpPolyShapeGetVert(shape, 1)))) 22 | } 23 | 24 | /** 25 | * Creates a PhysicsShapeBox with specified value. 26 | * 27 | * @param size Size contains this box's width and height. 28 | * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. 29 | * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. 30 | * @return An autoreleased PhysicsShapeBox object pointer. 31 | */ 32 | init(size: Size, material: PhysicsMaterial = PhysicsMaterial.default, offset: Vector2f = Vector2f.zero, radius: Float = 0.0) { 33 | let wh = size 34 | let verts = [p2d(x: -wh.x/2.0, y: -wh.y/2.0), 35 | p2d(x: -wh.x/2.0, y: wh.y/2.0), 36 | p2d(x: wh.x/2.0, y: wh.y/2.0), 37 | p2d(x: wh.x/2.0, y: -wh.y/2.0)] 38 | 39 | super.init(points: verts, material: material, offset: offset, radius: radius) 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsShapeCircle.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsShapeCircle.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 21.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import CChipmunk2D 11 | 12 | /** A circle shape. */ 13 | public class PhysicsShapeCircle: PhysicsShape { 14 | /** 15 | * Get the circle's radius. 16 | * 17 | * @return A float number. 18 | */ 19 | public var radius: Float { 20 | return Float(cpCircleShapeGetRadius(chipmunkShapes.first!)) 21 | } 22 | 23 | public override var offset: Vector2f { 24 | return vec2(cpCircleShapeGetOffset(chipmunkShapes.first!)) 25 | } 26 | 27 | public override func calculateArea() -> Float { 28 | return Float(cpAreaForCircle(0, cpCircleShapeGetRadius(chipmunkShapes.first!))) 29 | } 30 | 31 | override public func calculateDefaultMoment() -> Float { 32 | let shape = chipmunkShapes.first! 33 | return mass == PHYSICS_INFINITY ? PHYSICS_INFINITY 34 | : Float(cpMomentForCircle(cpFloat(mass), 35 | 0, 36 | cpCircleShapeGetRadius(shape), 37 | cpCircleShapeGetOffset(shape))) 38 | } 39 | 40 | /** 41 | * Creates a PhysicsShapeCircle with specified value. 42 | * 43 | * @param radius A float number, it is the circle's radius. 44 | * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. 45 | * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. 46 | * @return An autoreleased PhysicsShapeCircle object pointer. 47 | */ 48 | init(radius: Float = 1.0, material: PhysicsMaterial = PhysicsMaterial.default, offset: Vector2f = Vector2f.zero) { 49 | super.init() 50 | type = .circle 51 | let shape = cpCircleShapeNew(SHARED_BODY, cpFloat(radius), cpVect(offset))! 52 | cpShapeSetUserData(shape, Unmanaged.passUnretained(self).toOpaque()) 53 | add(shape: shape) 54 | 55 | area = calculateArea() 56 | mass = _material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : material.density * area 57 | moment = calculateDefaultMoment() 58 | 59 | self.material = material 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsShapePolygon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsShapePolygon.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 22.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import CChipmunk2D 11 | 12 | public class PhysicsShapePolygon: PhysicsShape { 13 | /** 14 | * Creates a PhysicsShapePolygon with specified value. 15 | * 16 | * @param points A [Point] object, it is an array of Point. 17 | * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. 18 | * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. 19 | * @return An PhysicsShapePolygon object pointer. 20 | */ 21 | init(points: [Point], material: PhysicsMaterial = PhysicsMaterial.default, offset: Vector2f = Vector2f.zero, radius: Float = 0.0) { 22 | super.init() 23 | let transform = cpTransformTranslate(cpVect(offset)) 24 | let verts = points.map { (vec: Vector2f) -> cpVect in 25 | return cpVect(vec) 26 | } 27 | let shape = cpPolyShapeNew(SHARED_BODY, Int32(points.count), verts, transform, cpFloat(radius))! 28 | 29 | cpShapeSetUserData(shape, Unmanaged.passUnretained(self).toOpaque()) 30 | 31 | add(shape: shape) 32 | 33 | area = calculateArea() 34 | mass = material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : material.density * area 35 | moment = calculateDefaultMoment() 36 | 37 | self.material = material 38 | } 39 | 40 | internal var verts: [cpVect] { 41 | let shape = chipmunkShapes.first! 42 | let count = cpPolyShapeGetCount(shape) 43 | var verts = [cpVect](repeating: cpVect(), count: Int(count)) 44 | for i in 0.. Float { 51 | let verts = self.verts 52 | let shape = chipmunkShapes.first! 53 | return Float(cpAreaForPoly(Int32(verts.count), verts, cpPolyShapeGetRadius(shape))) 54 | } 55 | 56 | public override func calculateDefaultMoment() -> Float { 57 | if mass == PHYSICS_INFINITY { 58 | return PHYSICS_INFINITY 59 | } else { 60 | let shape = chipmunkShapes.first! 61 | let verts = self.verts 62 | return Float(cpMomentForPoly(cpFloat(mass), Int32(verts.count), verts, cpvzero, cpPolyShapeGetRadius(shape))) 63 | } 64 | } 65 | 66 | public override var center: Vector2f { 67 | let verts = self.verts 68 | return Vector2f(cpCentroidForPoly(Int32(verts.count), verts)) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsSystem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsSystem.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 28.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | public class PhysicsSystem: System { 12 | public var paused: Bool = false 13 | public var dirty: Bool = true 14 | public let world: PhysicsWorld 15 | internal var rootNode: ComponentNode! 16 | 17 | public init(world: PhysicsWorld) { 18 | self.world = world 19 | } 20 | 21 | /** 22 | * Component related methods 23 | */ 24 | public func add(component: Component) { 25 | world.add(body: component as! PhysicsBody) 26 | dirty = true 27 | } 28 | 29 | public func remove(component: Component) { 30 | world.remove(body: component as! PhysicsBody) 31 | dirty = true 32 | } 33 | 34 | public func wants(component: Component) -> Bool { 35 | return component is PhysicsBody 36 | } 37 | 38 | public func updatePhysics(delta: Time) { 39 | if dirty { 40 | updatePhysicsBodyTree() 41 | dirty = false 42 | } 43 | 44 | if world.autoStep { 45 | world.updateDelaysIfNeeded() 46 | 47 | let sceneToWorldTransform = rootNode.node.nodeToParentMatrix 48 | rootNode.beforeSimulation(parentToWorldTransform: sceneToWorldTransform, 49 | nodeParentScaleX: 1, nodeParentScaleY: 1, 50 | parentRotation: Angle.zero) 51 | 52 | world.update(dt: delta) 53 | 54 | // Update physics position, should loop as the same sequence as node tree. 55 | rootNode.afterSimulation(parentToWorldTransform: sceneToWorldTransform, parentRotation: Angle.zero) 56 | } 57 | } 58 | 59 | public func updatePhysicsBodyTree() { 60 | rootNode = world.rootNode.subtree(of: PhysicsBody.self) 61 | } 62 | } 63 | 64 | extension PhysicsSystem: FixedUpdatable { 65 | public var priority: Int { 66 | return Int.max 67 | } 68 | 69 | public func fixedUpdate(delta: Time) { 70 | updatePhysics(delta: delta) 71 | } 72 | } 73 | 74 | internal extension ComponentNode where T: PhysicsBody { 75 | internal func beforeSimulation(parentToWorldTransform: Matrix4x4f, nodeParentScaleX: Float, nodeParentScaleY: Float, parentRotation: Angle) { 76 | let scaleX = nodeParentScaleX * node.scaleX 77 | let scaleY = nodeParentScaleY * node.scaleY 78 | let rotation = parentRotation + node.rotation 79 | 80 | let nodeToWorldTransform = parentToWorldTransform * node.nodeToParentMatrix 81 | 82 | component?.beforeSimulation(parentToWorldTransform: parentToWorldTransform, nodeToWorldTransform: nodeToWorldTransform, scaleX: scaleX, scaleY: scaleY, rotation: rotation) 83 | 84 | for c in children { 85 | c.beforeSimulation(parentToWorldTransform: nodeToWorldTransform, 86 | nodeParentScaleX: scaleX, nodeParentScaleY: scaleY, 87 | parentRotation: rotation) 88 | } 89 | } 90 | 91 | internal func afterSimulation(parentToWorldTransform: Matrix4x4f, parentRotation: Angle) { 92 | let nodeToWorldTransform = parentToWorldTransform * node.nodeToParentMatrix 93 | let nodeRotation = parentRotation + node.rotation 94 | 95 | component?.afterSimulation(parentToWorldTransform: parentToWorldTransform, parentRotation: parentRotation) 96 | 97 | for c in children { 98 | c.afterSimulation(parentToWorldTransform: nodeToWorldTransform, parentRotation: nodeRotation) 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsTypes.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 18.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import CChipmunk2D 11 | 12 | let CP_ALL_CATEGORIES: UInt32 = UInt32.max 13 | 14 | let PHYSICS_INFINITY = Float.infinity 15 | let MASS_DEFAULT: Float = 1 16 | let MOMENT_DEFAULT: Float = 200 17 | 18 | public enum DebugDrawOption { 19 | case shape, joint, contact 20 | } 21 | 22 | internal extension Vector2f { 23 | 24 | init(_ cpv: cpVect) { 25 | self.init(x: Float(cpv.x), y: Float(cpv.y)) 26 | } 27 | 28 | var cpVect: cpVect { return cpv(cpFloat(x), cpFloat(y)) } 29 | } 30 | 31 | internal extension cpVect { 32 | init(_ vec2: Vector2f) { 33 | self.init(x: cpFloat(vec2.x), y: cpFloat(vec2.y)) 34 | } 35 | } 36 | 37 | internal extension Angle { 38 | init(_ cpf: cpFloat) { 39 | self.init(degrees: Float(cpf)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Fiber2D/PhysicsWorld+Internal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsWorld+Internal.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 18.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import CChipmunk2D 10 | 11 | internal func collisionBeginCallbackFunc(_ arb: UnsafeMutablePointer?, _ space: UnsafeMutablePointer?, _ world: cpDataPointer?) -> cpBool { 12 | 13 | var a: UnsafeMutablePointer? = nil 14 | var b: UnsafeMutablePointer? = nil 15 | cpArbiterGetShapes(arb, &a, &b) 16 | 17 | let shapeA = Unmanaged.fromOpaque(cpShapeGetUserData(a)).takeUnretainedValue() 18 | let shapeB = Unmanaged.fromOpaque(cpShapeGetUserData(b)).takeUnretainedValue() 19 | 20 | let contactPointer = UnsafeMutablePointer.allocate(capacity: 1) 21 | let contact = PhysicsContact(shapeA: shapeA, shapeB: shapeB, arb: arb) 22 | contactPointer.initialize(to: contact) 23 | cpArbiterSetUserData(arb, contactPointer) 24 | 25 | let world = Unmanaged.fromOpaque(world!).takeUnretainedValue() 26 | world.contactDelegate?.didBegin(contact: contact) 27 | 28 | return 1 29 | } 30 | 31 | internal func collisionPreSolveCallbackFunc(_ arb: UnsafeMutablePointer?, _ space: UnsafeMutablePointer?, _ world: cpDataPointer?) -> cpBool { 32 | return 1 33 | } 34 | 35 | internal func collisionPostSolveCallbackFunc(_ arb: UnsafeMutablePointer?, _ space: UnsafeMutablePointer?, _ world: cpDataPointer?) -> Void { 36 | } 37 | 38 | internal func collisionSeparateCallbackFunc(_ arb: UnsafeMutablePointer?, _ space: UnsafeMutablePointer?, _ world: cpDataPointer?) -> Void { 39 | let contactPointer = cpArbiterGetUserData(arb).assumingMemoryBound(to: PhysicsContact.self) 40 | let contact = contactPointer.pointee 41 | let world = Unmanaged.fromOpaque(world!).takeUnretainedValue() 42 | world.contactDelegate?.didEnd(contact: contact) 43 | free(contactPointer) 44 | } 45 | 46 | internal extension PhysicsWorld { 47 | 48 | internal func updateDelaysIfNeeded() { 49 | if !delayAddBodies.isEmpty || !delayRemoveBodies.isEmpty { 50 | updateBodies() 51 | } 52 | 53 | if !delayAddJoints.isEmpty || !delayRemoveJoints.isEmpty { 54 | updateJoints() 55 | } 56 | } 57 | 58 | internal func update(dt: Time, userCall: Bool = false) { 59 | guard dt > Float.ulpOfOne else { 60 | return 61 | } 62 | 63 | if userCall { 64 | cpHastySpaceStep(chipmunkSpace, cpFloat(dt)) 65 | } else { 66 | updateTime += dt 67 | 68 | if fixedUpdateRate > 0 { 69 | let step = 1.0 / Time(fixedUpdateRate) 70 | let dt = step * speed 71 | while updateTime > step { 72 | updateTime -= step 73 | 74 | cpHastySpaceStep(chipmunkSpace, cpFloat(dt)) 75 | } 76 | } else { 77 | updateRateCount += 1 78 | if Float(updateRateCount) > updateRate { 79 | let dt = updateTime * speed / Time(substeps) 80 | for _ in 0.. 0 { 64 | return vertexBuffer.first!.color 65 | } 66 | 67 | return .zero 68 | } 69 | set { 70 | for i in 0.. Uniform { 60 | guard num > 0 else { 61 | fatalError("Uniform handle must be at least 1 element long") 62 | } 63 | 64 | let key = name + "_" + String(type.rawValue) + "_" + String(num) 65 | if let handle = Material.handles[key] { 66 | return handle 67 | } 68 | 69 | let newHandle = Uniform(name: name, type: type, num: UInt16(num)) 70 | Material.handles[key] = newHandle 71 | return newHandle 72 | } 73 | } 74 | 75 | internal extension Material { 76 | internal func apply() { 77 | if vec4Uniforms.count > 0 { 78 | for (key, value) in vec4Uniforms { 79 | bgfx.setUniform(key, value: value) 80 | } 81 | } 82 | 83 | if mat4Uniforms.count > 0 { 84 | for (key, value) in mat4Uniforms { 85 | bgfx.setUniform(key, value: value) 86 | } 87 | } 88 | 89 | // vec4/mat4 arrays and mat3 supports have to be done in SwiftBGFX 90 | 91 | if textureUniforms.count > 0 { 92 | for (key, value) in textureUniforms { 93 | bgfx.setTexture(value.unit, sampler: key, texture: value.texture.texture) 94 | } 95 | } 96 | } 97 | } 98 | 99 | extension Material: Cloneable { 100 | public var clone: Material { 101 | return Material(technique: technique) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/Pass.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Pass.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 24.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftBGFX 10 | 11 | // Considerations: 12 | // 1. Maybe implement this as a struct? 13 | // 2. Should we allows modification of the properies? 14 | // 3. Should this be cached? 15 | 16 | // TODO: 17 | // 1. Data-driven load from XML/JSON/YAML 18 | 19 | /// Material rendering pass, which defines shaders and render state. 20 | public final class Pass { 21 | internal(set) public var fragmentShader: Shader 22 | internal(set) public var vertexShader: Shader 23 | internal var program: Program 24 | 25 | internal(set) public var blendMode: BlendMode { 26 | didSet { 27 | if blendMode != oldValue { 28 | renderStateDirty = true 29 | } 30 | } 31 | } 32 | 33 | public var cullMode: CullMode = .none 34 | 35 | /// Control multisampling 36 | internal(set) public var multisampling: Bool 37 | 38 | /// Control depth writing 39 | internal(set) public var depthWrite: Bool 40 | 41 | /// Cache and return the current render state. 42 | internal(set) public var renderState: RenderStateOptions { 43 | get { 44 | if renderStateDirty { 45 | _renderState = Pass.defaultRenderState | blendMode.state | blendMode.equation | cullMode.renderState 46 | 47 | if depthWrite { 48 | _renderState = _renderState.union(.depthWrite) 49 | } 50 | 51 | if multisampling { 52 | _renderState = _renderState.union(.multisampling) 53 | } 54 | renderStateDirty = false 55 | } 56 | return _renderState 57 | } 58 | set { _renderState = newValue } 59 | } 60 | 61 | internal var renderStateDirty = true 62 | private var _renderState: RenderStateOptions = .default 63 | internal static let defaultRenderState: RenderStateOptions = [.colorWrite, .alphaWrite] 64 | 65 | public init(vertexShader: Shader, 66 | fragmentShader: Shader, 67 | blendMode: BlendMode = .premultipliedAlphaMode, 68 | depthWrite: Bool = false, 69 | multisampling: Bool = true) { 70 | self.vertexShader = vertexShader 71 | self.fragmentShader = fragmentShader 72 | self.program = Program(vertex: vertexShader, fragment: fragmentShader) 73 | self.blendMode = blendMode 74 | self.depthWrite = depthWrite 75 | self.multisampling = multisampling 76 | } 77 | } 78 | 79 | extension Pass: Hashable { 80 | public var hashValue: Int { 81 | return Int(renderState.rawValue) + fragmentShader.hashValue + vertexShader.hashValue 82 | } 83 | 84 | public static func ==(lhs: Pass, rhs: Pass) -> Bool { 85 | return lhs.renderState == rhs.renderState && 86 | lhs.fragmentShader == rhs.fragmentShader && 87 | lhs.vertexShader == rhs.vertexShader 88 | } 89 | } 90 | 91 | public extension Pass { 92 | public static let positionColor: Pass = { 93 | return Pass(vertexShader: .builtInVertexShader, fragmentShader: .builtInPosColorShader) 94 | }() 95 | 96 | public static let positionTexture: Pass = { 97 | return Pass(vertexShader: .builtInVertexShader, fragmentShader: .builtInPosTextureShader) 98 | }() 99 | } 100 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/RenderComponent.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RenderComponent.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 03.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import SwiftBGFX 11 | #if os(OSX) || os(iOS) || os(tvOS) 12 | import Darwin 13 | #else 14 | import Glibc 15 | #endif 16 | 17 | /** 18 | * Base protocol for all render components 19 | * 20 | * All render components must have material. 21 | */ 22 | public protocol RenderableComponent: Component { 23 | /** 24 | * Customizable material that will be used to draw geometry. 25 | * 26 | * @see Material 27 | */ 28 | var material: Material { get set } 29 | 30 | /** 31 | * Local z order that indicates drawing order between owner's renderable components. 32 | */ 33 | var zOrder: Int { get set } 34 | 35 | /** 36 | Implement this method to add custom rendering code to your node. 37 | 38 | @note You should only use Fiber2D's Renderer API to modify the render state and shaders. For further info, please see the Renderer documentation. 39 | @warning You **must not** call `super.draw(in:transform:)` 40 | 41 | @param renderer The Renderer instance to use for drawing. 42 | @param transform The parent node's transform. 43 | @see Renderer 44 | */ 45 | func draw(in renderer: Renderer, transform: Matrix4x4f) 46 | } 47 | 48 | // 49 | // MARK: Default renderers 50 | // 51 | 52 | public class QuadRenderer: ComponentBase, RenderableComponent { 53 | public var material: Material 54 | 55 | public var zOrder: Int = 0 56 | 57 | /// Geometry to be rendered. 58 | /// Must be exactly 4 vertices long, index buffer is ignored 59 | public var geometry = Geometry(vertexBuffer: [RendererVertex](repeating: RendererVertex(), 60 | count: 4), 61 | indexBuffer: []) 62 | 63 | public init(material: Material) { 64 | self.material = material 65 | super.init() 66 | } 67 | 68 | public func draw(in renderer: Renderer, transform: Matrix4x4f) { 69 | let vertices = geometry.vertexBuffer.map { $0.transformed(transform) } 70 | let vb = TransientVertexBuffer(count: 4, layout: RendererVertex.layout) 71 | memcpy(vb.data, vertices, 4 * MemoryLayout.size) 72 | 73 | for pass in material.technique.passes { 74 | material.apply() 75 | bgfx.setVertexBuffer(vb) 76 | bgfx.setIndexBuffer(QuadRenderer.indexBuffer) 77 | bgfx.setRenderState(pass.renderState, colorRgba: 0x0) 78 | renderer.submit(shader: pass.program) 79 | } 80 | } 81 | 82 | public static let indexBuffer: IndexBuffer = { 83 | // We have 2 triangles, 6 indices 84 | let retVal: [UInt16] = [0, 1, 2, 0, 2, 3] 85 | let memory = MemoryBlock(data: retVal) 86 | return IndexBuffer(memory: memory) 87 | }() 88 | } 89 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/Renderer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Renderer.swift 3 | // Fiber2D 4 | // 5 | // Created by Stuart Carnie on 9/8/16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import SwiftBGFX 11 | 12 | // All there requires more consideration 13 | public protocol Renderer { 14 | // TODO: Abstract from SwiftBGFX 15 | func submit(shader: Program) 16 | func enqueueClear(color: vec4) 17 | func prepare(withProjection: Matrix4x4f) 18 | func flush() 19 | 20 | // MARK: - render objects 21 | func makeFrameBufferObject() -> FrameBufferObject 22 | func beginRenderTexture(_ rt: RenderTexture) 23 | func endRenderTexture() 24 | 25 | // TODO: Push group, pop group 26 | // TODO: Compute shader support 27 | } 28 | 29 | var currentRenderer: Renderer? 30 | 31 | public protocol RendererState { 32 | 33 | } 34 | 35 | public protocol FrameBufferObject { 36 | } 37 | 38 | public protocol RendererBuffer { 39 | mutating func setVertex(index: Int, vertex: RendererVertex) 40 | mutating func setTriangle(index: Int, v1: UInt16, v2: UInt16, v3: UInt16) 41 | } 42 | 43 | public struct RendererVertex { 44 | var position: Vector4f 45 | var texCoord1, texCoord2: Vector2f 46 | var color: Vector4f 47 | 48 | public init() { 49 | position = vec4(0) 50 | texCoord1 = vec2.zero 51 | texCoord2 = vec2.zero 52 | color = vec4(0) 53 | } 54 | 55 | public init(position: vec4, texCoord1: vec2, texCoord2: vec2, color: vec4) { 56 | self.position = position 57 | self.texCoord1 = texCoord1 58 | self.texCoord2 = texCoord2 59 | self.color = color 60 | } 61 | 62 | public func transformed(_ m: Matrix4x4f) -> RendererVertex { 63 | return RendererVertex(position: m * position, texCoord1: texCoord1, texCoord2: texCoord2, color: color) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/Technique.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Technique.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 24.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public final class Technique { 10 | internal(set) public var name = "" 11 | internal(set) public var passes = [Pass]() 12 | 13 | /** Adds a new pass to the Technique. 14 | Order matters. First added, first rendered 15 | */ 16 | public func add(pass: Pass) { 17 | passes.append(pass) 18 | } 19 | } 20 | 21 | public extension Technique { 22 | public static let positionColor: Technique = { 23 | let retVal = Technique() 24 | retVal.name = "DefaultTechnique: positionColor" 25 | retVal.add(pass: .positionColor) 26 | return retVal 27 | }() 28 | 29 | public static let positionTexture: Technique = { 30 | let retVal = Technique() 31 | retVal.name = "DefaultTechnique: positionTexture" 32 | retVal.add(pass: .positionTexture) 33 | return retVal 34 | }() 35 | } 36 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/Texture+UV.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Texture+UV.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 04.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | public extension Texture { 12 | /// Returns an array of 4 elements that represents UV coordinates 13 | /// Return order: [bottom left, bottom right, top right, top left] 14 | public func uv(for rect: Rect, rotated: Bool, xFlipped flipX: Bool, yFlipped flipY: Bool) -> SpriteTexCoordSet { 15 | // Need to convert the texel coords for the texel stretch hack. (Bah) 16 | let scale = self.contentScale 17 | let rect = rect.scaled(by: scale) 18 | let sizeInPixels = self.sizeInPixels 19 | let atlasWidth = sizeInPixels.width 20 | let atlasHeight = sizeInPixels.height 21 | 22 | if rotated { 23 | var left = rect.origin.x / atlasWidth 24 | var right = (rect.origin.x + rect.size.height) / atlasWidth 25 | var bottom = rect.origin.y / atlasHeight 26 | var top = (rect.origin.y + rect.size.width) / atlasHeight 27 | 28 | if flipX { 29 | swap(&top, &bottom) 30 | } 31 | if flipY { 32 | swap(&left, &right) 33 | } 34 | return SpriteTexCoordSet(bl: vec2(left, top), 35 | br: vec2(left, bottom), 36 | tr: vec2(right, bottom), 37 | tl: vec2(right, top)) 38 | } else { 39 | var left = rect.origin.x / atlasWidth 40 | var right = (rect.origin.x + rect.size.width) / atlasWidth 41 | var bottom = rect.origin.y / atlasHeight 42 | var top = (rect.origin.y + rect.size.height) / atlasHeight 43 | 44 | if flipX { 45 | swap(&left, &right) 46 | } 47 | if flipY { 48 | swap(&top, &bottom) 49 | } 50 | return SpriteTexCoordSet(bl: vec2(left, bottom), 51 | br: vec2(right, bottom), 52 | tr: vec2(right, top), 53 | tl: vec2(left, top)) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/Texture.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Texture.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 02.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import SwiftBGFX 11 | 12 | internal typealias BGFXTexture = SwiftBGFX.Texture 13 | 14 | public class Texture { 15 | internal var texture: BGFXTexture 16 | internal var contentSizeInPixels: Size = .zero 17 | 18 | /** 19 | Content scale of the texture. 20 | */ 21 | internal(set) public var contentScale: Float = 1.0 22 | 23 | /** 24 | Content size of the texture. 25 | This may not be sizeInPixels/contentSize. A texture might be padded to a size that is a power of two on some Android hardware. 26 | */ 27 | public var contentSize: Size { 28 | return contentSizeInPixels * (1.0 / contentScale) 29 | } 30 | 31 | /** 32 | Size of the texture in pixels. 33 | */ 34 | public var sizeInPixels: Size { 35 | return Size(Float(texture.info.width), Float(texture.info.height)) 36 | } 37 | 38 | /** 39 | A sprite frame that covers the whole texture. 40 | */ 41 | public var spriteFrame: SpriteFrame { 42 | if _spriteFrame == nil { 43 | _spriteFrame = SpriteFrame(texture: self, rect: Rect(size: contentSize), rotated: false, trimOffset: .zero, untrimmedSize: contentSize) 44 | } 45 | 46 | return _spriteFrame! 47 | } 48 | private var _spriteFrame: SpriteFrame? = nil 49 | 50 | internal init(bgfxTexture: BGFXTexture) { 51 | self.texture = bgfxTexture 52 | } 53 | 54 | public static func load(from filename: String) -> Texture? { 55 | return TextureCache.shared.addImage(from: filename) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/TextureCache.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextureCache.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 02.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | /** Singleton that handles the loading of textures. Once the texture is loaded, the next time it will return 10 | * a reference of the previously loaded texture reducing GPU & CPU memory. 11 | */ 12 | public class TextureCache { 13 | /** Returns ths shared instance of the cache. */ 14 | public static let shared = TextureCache() 15 | 16 | internal var textures = [String: Texture]() 17 | 18 | /** 19 | * Returns a Texture object given an file image. 20 | * 21 | * If the file image was not previously loaded, it will create a new Texture 22 | * object and it will return it. It will use the filename as a key. 23 | * Otherwise it will return a reference of a previously loaded image. 24 | * 25 | * Supported image extensions: .png 26 | * 27 | * @param fileimage Image file to load. 28 | * 29 | * @return A Texture object. 30 | */ 31 | public func addImage(from filename: String) -> Texture? { 32 | let tex = textures[filename] 33 | 34 | guard tex == nil else { 35 | return tex 36 | } 37 | 38 | guard let file = FileLocator.shared.fileWithResolutionSearch(named: filename) else { 39 | print("Couldn't find file: \(filename)") 40 | return nil 41 | } 42 | 43 | let image = Image(file: file) 44 | let texture = Texture.make(from: image) 45 | textures[filename] = texture 46 | 47 | return texture 48 | } 49 | 50 | // TODO temporary method. 51 | public func add(texture: Texture, for key: String) { 52 | textures[key] = texture 53 | } 54 | 55 | /** 56 | * Returns an already created texture. Returns nil if the texture doesn't exist. 57 | * 58 | * @param key Key to look for. 59 | * 60 | * @return Texture from cache. 61 | */ 62 | public func texture(for key: String) -> Texture? { 63 | return textures[key] 64 | } 65 | } 66 | 67 | // MARK: Remove 68 | public extension TextureCache { 69 | /** Purges the dictionary of loaded textures. 70 | * Call this method if you receive the "Memory Warning". 71 | * In the short term: it will free some resources preventing your app from being killed. 72 | * In the medium term: it will allocate more resources. 73 | * In the long term: it will be the same. 74 | */ 75 | public func removeAllTextures() { 76 | textures.removeAll() 77 | } 78 | 79 | /** Removes unused textures. 80 | * Textures that have a retain count of 1 will be deleted. 81 | * It is convenient to call this method after when starting a new Scene. 82 | */ 83 | public func removeUnusedTextures() { 84 | textures.removeUnusedObjects() 85 | } 86 | 87 | /** 88 | * Deletes a texture from the cache given a texture. 89 | * 90 | * @param texture Texture to remove from cache. 91 | */ 92 | public func remove(texture: Texture) { 93 | for (k, v) in textures { 94 | if v === texture { 95 | textures[k] = nil 96 | } 97 | } 98 | } 99 | 100 | /** 101 | * Deletes a texture from the cache given a its key name. 102 | * 103 | * @param key Texture key to remove from cache. 104 | */ 105 | public func removeTexture(for key: String) { 106 | textures.removeValue(forKey: key) 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/bgfx/BGFXRenderer+RenderTexture.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BGFXRenderer+RenderTexture.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 05.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftBGFX 10 | 11 | // Ugly sketch, but should work 12 | // Will not handle nested RTTs, I think 13 | internal extension BGFXRenderer { 14 | internal func beginRenderTexture(_ rt: RenderTexture) { 15 | // Push current view ID 16 | viewStack.append(currentViewID) 17 | currentViewID = currentRenderTargetViewID 18 | 19 | if currentTree == nil { 20 | // Means this is a top-level tree 21 | currentTree = Tree(value: currentRenderTargetViewID) 22 | rtTrees.append(currentTree!) 23 | } else { 24 | // Means we are creating +1 level of nested RTs 25 | // Create new entry 26 | let newTree = Tree(value: currentRenderTargetViewID) 27 | 28 | // put that as a child of current tree 29 | currentTree!.add(child: newTree) 30 | // Make that new tree a new current one 31 | currentTree = newTree 32 | 33 | // Assign every time 34 | currentFrameHasNestedRTS = true 35 | } 36 | 37 | bgfx.set(viewMode: .sequental, for: currentViewID) 38 | 39 | let rtPixelSize = rt.pixelSize 40 | bgfx.setViewRect(viewId: currentViewID, x: 0, y: 0, 41 | width: UInt16(rtPixelSize.width), height: UInt16(rtPixelSize.height)) 42 | bgfx.setViewFrameBuffer(viewId: currentViewID, buffer: rt.framebuffer!) 43 | bgfx.setViewClear(viewId: currentViewID, options: [.color], rgba: rt.clearColor.uint32Representation, depth: 1.0, stencil: 0) 44 | bgfx.touch(currentViewID) 45 | 46 | bgfx.setViewTransform(viewId: currentViewID, proj: rt.projection) 47 | 48 | currentRenderTargetViewID += 1 49 | } 50 | 51 | internal func endRenderTexture() { 52 | // Pop current view ID 53 | currentViewID = viewStack.removeLast() 54 | if currentTree == nil { 55 | fatalError("Can't pop RTs group as we don't have none") 56 | } 57 | currentTree = currentTree!.parent 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Fiber2D/Renderer/bgfx/BGFXRenderer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BGFXRenderer.swift 3 | // Fiber2D 4 | // 5 | // Created by Stuart Carnie on 9/11/16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import Cbgfx 11 | import SwiftBGFX 12 | 13 | internal let ROOT_RTT_ID = UInt8(0) 14 | internal let ROOT_VIEW_ID = UInt8(190) 15 | 16 | internal class BGFXRenderer: Renderer { 17 | internal var viewStack = [UInt8]() 18 | 19 | internal var currentViewID = ROOT_VIEW_ID 20 | 21 | internal var currentRenderTargetViewID = ROOT_RTT_ID 22 | 23 | internal var framesToUpdateStats = 10 24 | internal var frameCount = 0 25 | internal var gpuFreq = 0.0 26 | internal var cpuFreq = 0.0 27 | 28 | internal var rtTrees = [Tree]() 29 | internal var currentTree: Tree? 30 | internal var currentFrameHasNestedRTS = false 31 | 32 | init() { 33 | bgfx.frame() 34 | 35 | bgfx.debug = [.text] 36 | } 37 | 38 | func enqueueClear(color: vec4) { 39 | bgfx.setViewClear(viewId: currentViewID, options: [.color, .depth], rgba: color.uint32Representation, depth: 1.0, stencil: 0) 40 | } 41 | 42 | func prepare(withProjection proj: Matrix4x4f) { 43 | bgfx.set(viewMode: .sequental, for: currentViewID) 44 | bgfx.setViewRect(viewId: currentViewID, x: 0, y: 0, ratio: .equal) 45 | bgfx.touch(currentViewID) 46 | 47 | bgfx.setViewTransform(viewId: currentViewID, proj: proj) 48 | 49 | // Prepare stuff for RTs 50 | if currentFrameHasNestedRTS { 51 | bgfx.clearViewRemap() 52 | } 53 | rtTrees.removeAll(keepingCapacity: true) 54 | currentFrameHasNestedRTS = false 55 | } 56 | 57 | public func submit(shader: Program) { 58 | bgfx.submit(currentViewID, program: shader) 59 | } 60 | 61 | func flush() { 62 | frameCount = (frameCount + 1) % framesToUpdateStats 63 | if frameCount == 0 { 64 | let stats = bgfx.stats 65 | 66 | gpuFreq = Double(stats.gpuTimeEnd - stats.gpuTimeBegin) / 1000 67 | cpuFreq = Double(stats.cpuTimeEnd - stats.cpuTimeBegin) / 1000 68 | } 69 | 70 | bgfx.debugTextClear() 71 | bgfx.debugTextPrint(x: 0, y: 1, foreColor: .white, backColor: .darkGray, format: "Fiber2D BGFX Renderer") 72 | bgfx.debugTextPrint(x: 0, y: 2, foreColor: .white, backColor: .darkGray, format: "CPU: \(cpuFreq)") 73 | bgfx.debugTextPrint(x: 0, y: 3, foreColor: .white, backColor: .darkGray, format: "GPU: \(gpuFreq)") 74 | 75 | if currentFrameHasNestedRTS { 76 | let treeViews = rtTrees.childrenFirstTraverse() 77 | var newViewOrder = [UInt8](repeating: 0, count: treeViews.count) 78 | for i in 0.. FrameBufferObject { 91 | return SwiftBGFX.FrameBuffer(ratio: .equal, format: .bgra8) 92 | } 93 | } 94 | 95 | extension SwiftBGFX.FrameBuffer: FrameBufferObject { 96 | 97 | } 98 | 99 | public extension RendererVertex { 100 | public static let layout: VertexLayout = { 101 | let l = VertexLayout() 102 | l.begin() 103 | .add(attrib: .position, num: 4, type: .float) 104 | .add(attrib: .texCoord0, num: 2, type: .float) 105 | .add(attrib: .texCoord1, num: 2, type: .float) 106 | .add(attrib: .color0, num: 4, type: .float, normalized: true) 107 | .end() 108 | 109 | return l 110 | }() 111 | } 112 | -------------------------------------------------------------------------------- /Fiber2D/ResponderManager+Mouse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResponderManager+Mouse.swift 3 | // Fiber2D-iOS 4 | // 5 | // Created by Andrey Volodin on 08.01.17. 6 | // 7 | // 8 | 9 | #if os(macOS) || os(Linux) 10 | import SwiftMath 11 | 12 | public extension ResponderManager { 13 | 14 | internal func executeOnEachResponder(_ block: (Responder) -> Void, screenPosition: Point) { 15 | Director.pushCurrentDirector(director) 16 | // scan through responders, and find first one 17 | for responder in responderList.lazy.reversed() { 18 | // check for hit test 19 | if responder.hitTest(worldPosition: screenPosition) { 20 | self.currentEventProcessed = true 21 | block(responder) 22 | // if mouse was accepted, break 23 | break 24 | } 25 | } 26 | Director.popCurrentDirector() 27 | } 28 | 29 | internal func cancel(responder: RunningResponder) { 30 | runningResponderList.removeObject(responder) 31 | } 32 | 33 | // finds a responder object for an event 34 | internal func responder(for button: MouseButton) -> RunningResponder? { 35 | for touchEntry in runningResponderList { 36 | if touchEntry.button == button { 37 | return touchEntry 38 | } 39 | } 40 | return nil 41 | } 42 | 43 | // adds a responder object ( running responder ) to the responder object list 44 | internal func add(responder: Responder, withButton button: MouseButton) { 45 | // create a new input object 46 | let touchEntry = RunningResponder(target: responder) 47 | touchEntry.button = button 48 | runningResponderList.append(touchEntry) 49 | } 50 | 51 | } 52 | #endif 53 | -------------------------------------------------------------------------------- /Fiber2D/Scene+Systems.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Scene+Systems.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 14.10.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public extension Scene { 10 | public func register(system: System) { 11 | let idx = systems.first { s in s === system } 12 | 13 | guard idx == nil else { 14 | return 15 | } 16 | 17 | systems.append(system) 18 | 19 | if let s = system as? Updatable & Pausable { 20 | scheduler.schedule(updatable: s) 21 | } 22 | 23 | if let s = system as? FixedUpdatable & Pausable { 24 | scheduler.schedule(fixedUpdatable: s) 25 | } 26 | system.onAdd(to: self) 27 | } 28 | 29 | public func remove(system: System) { 30 | systems.removeObject(system) 31 | system.onRemove() 32 | } 33 | 34 | public func system(for component: Component) -> System? { 35 | for s in systems { 36 | if s.wants(component: component) { 37 | return s 38 | } 39 | } 40 | 41 | return nil 42 | } 43 | 44 | public func system(for type: U.Type) -> U? 45 | where U: System { 46 | for s in systems { 47 | if let retVal = s as? U { 48 | return retVal 49 | } 50 | } 51 | 52 | return nil 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /Fiber2D/Scene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Scene.swift 3 | // 4 | // Created by Andrey Volodin on 22.07.16. 5 | // Copyright © 2016. All rights reserved. 6 | // 7 | 8 | import SwiftMath 9 | 10 | /** Scene is a subclass of Node. The scene represents the root node of the node hierarchy. 11 | */ 12 | open class Scene: Node { 13 | // Override these with self and stored properties 14 | override public var scene: Scene { 15 | return self 16 | } 17 | 18 | override public var director: Director! { 19 | get { 20 | return _director 21 | } 22 | set { 23 | _director = newValue 24 | } 25 | } 26 | 27 | private var _director: Director! 28 | 29 | override var scheduler: Scheduler { 30 | get { 31 | return _scheduler 32 | } 33 | set { 34 | _scheduler = newValue 35 | } 36 | } 37 | 38 | private var _scheduler: Scheduler! 39 | 40 | /** 41 | * Invoked automatically when the OS view has been resized. 42 | * 43 | * @param The new size of the view after it has been resized. 44 | */ 45 | public let onViewDidResize = Event() 46 | 47 | /** 48 | Delegate that calculates the projection matrix for this scene. 49 | The default value is an ProjectionOrthographic delegate that goes from (0, 0) to the screen's size in points. 50 | */ 51 | //var projectionDelegate: ProjectionDelegate? 52 | 53 | /** 54 | Projection matrix for this scene. This value is overridden if the projectionDelegate is set. 55 | Defaults to the identity matrix. 56 | */ 57 | public var projection: Matrix4x4f { 58 | get { 59 | //return projectionDelegate?.projection ?? _projection 60 | return _projection } 61 | set { _projection = newValue } 62 | } 63 | private var _projection: Matrix4x4f! 64 | 65 | internal(set) public var systems = [System]() 66 | 67 | /// @name Creating a Scene 68 | 69 | /// Initialize the scene. 70 | public init(size: Size) { 71 | super.init() 72 | self.contentSize = size 73 | self.anchorPoint = .zero 74 | self.colorRGBA = .black 75 | self.color = .black 76 | self._scheduler = Scheduler() 77 | self._projection = Matrix4x4f.orthoProjection(for: self) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Fiber2D/Scheduling.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Scheduling.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 28.08.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public typealias Time = Float 10 | 11 | extension Timer { 12 | func forEach(block: (Timer) -> Void) { 13 | var timer: Timer? = self 14 | while timer != nil { 15 | block(timer!) 16 | timer = timer!.next 17 | } 18 | } 19 | 20 | func removeRecursive(skip: Timer) -> Timer? { 21 | if self === skip { 22 | return self.next 23 | } else { 24 | self.next = self.next?.removeRecursive(skip: skip) 25 | return self 26 | } 27 | } 28 | } 29 | 30 | // Targets are things that can have update: and fixedUpdate: methods called by the scheduler. 31 | // Scheduled blocks (Timers) can be associated with a target to inherit their priority and paused state. 32 | internal final class ScheduledTarget { 33 | weak var target: Node? 34 | var timers: Timer? 35 | var actions = [ActionContainer]() 36 | var empty: Bool { 37 | return timers == nil && !enableUpdates 38 | } 39 | var hasActions: Bool { 40 | return !actions.isEmpty 41 | } 42 | var paused = false { 43 | didSet { 44 | if paused != oldValue { 45 | let pause = self.paused 46 | timers?.forEach { $0.paused = pause } 47 | } 48 | } 49 | } 50 | var enableUpdates = false 51 | 52 | func invalidateTimers() { 53 | timers?.forEach { $0.invalidate() } 54 | } 55 | 56 | func add(action: ActionContainer) { 57 | actions.append(action) 58 | } 59 | 60 | func removeAction(by tag: Int) { 61 | actions = actions.filter { 62 | $0.tag != tag 63 | } 64 | } 65 | 66 | func remove(timer: Timer) { 67 | timers = timers?.removeRecursive(skip: timer) 68 | } 69 | 70 | init(target: Node) { 71 | self.target = target 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Fiber2D/Setup.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Setup.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 02.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public class Setup { 10 | public static let shared = Setup() 11 | 12 | /** 13 | Global content scale for the app. 14 | This is the number of pixels on the screen that are equivalent to a point in Fiber2D. 15 | */ 16 | public var contentScale: Float = 1.0 17 | 18 | /** 19 | Minimum content scale of assets such as textures, TTF labels or render textures. 20 | Normally you want this value to be the same as the contentScale, but on Mac you may want a higher value since the user could resize the window. 21 | */ 22 | public var assetScale: Float = 1.0 23 | 24 | /** 25 | UI scaling factor. Positions and content sizes are scale by this factor if the position type is set to UIScale. 26 | This is useful for creating UIs that have the same physical size (ex: centimeters) on different devices. 27 | This also affects the loading of assets marked as having a UIScale. 28 | */ 29 | public var UIScale: Float = 1.0 30 | 31 | /** 32 | Default fixed update interval that will be used when initializing schedulers. 33 | */ 34 | public var fixedUpdateInterval: Float = 1.0 / 60.0 35 | } 36 | -------------------------------------------------------------------------------- /Fiber2D/Sprite9SliceNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Sprite9SliceNode.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 05.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | open class Sprite9SliceNode: Node { 12 | public var sprite: Sprite9Slice? { 13 | if let src = getComponent(by: Sprite9SliceRenderComponent.self) { 14 | return src.sprite 15 | } 16 | return nil 17 | } 18 | 19 | public convenience init(imageNamed: String) { 20 | self.init(sprite: Sprite9Slice(imageNamed: imageNamed)) 21 | } 22 | 23 | public init(sprite: Sprite9Slice) { 24 | super.init() 25 | self.anchorPoint = p2d(0.5, 0.5) 26 | let src = Sprite9SliceRenderComponent(sprite: sprite) 27 | 28 | self.contentSizeInPoints = sprite.spriteFrame.untrimmedSize 29 | add(component: src) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Fiber2D/SpriteFrame.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SpriteFrame.swift 3 | // 4 | // Created by Andrey Volodin on 23.07.16. 5 | // Copyright © 2016. All rights reserved. 6 | // 7 | 8 | import SwiftMath 9 | 10 | /** 11 | A SpriteFrame contains the texture and rectangle of the texture to be used by a Sprite. 12 | You can easily modify the sprite frame of a Sprite using the following handy method: 13 | let frame = SpriteFrame.with(imageName: "jump.png") 14 | sprite.spriteFrame = frame 15 | */ 16 | public final class SpriteFrame { 17 | /// @name Creating a Sprite Frame 18 | 19 | /** 20 | * Create and return a sprite frame object from the specified image name. On first attempt it will check the internal texture/frame cache 21 | * and if not available will then try and create the frame from an image file of the same name. 22 | * 23 | * @param imageName Image name. 24 | * 25 | * @return The SpriteFrame Object. 26 | */ 27 | public static func with(imageName: String) -> SpriteFrame! { 28 | return SpriteFrameCache.shared.spriteFrame(by: imageName) 29 | } 30 | 31 | /** 32 | * Initializes and returns a sprite frame object from the specified texture, texture rectangle, rotation status, offset and originalSize values. 33 | * 34 | * @param texture Texture to use. 35 | * @param rect Texture rectangle (in points) to use. 36 | * @param rotated Is rectangle rotated? 37 | * @param trimOffset Offset (in points) to use. 38 | * @param untrimmedSize Original size (in points) before being trimmed. 39 | * 40 | * @return An initialized SpriteFrame Object. 41 | * @see Texture 42 | */ 43 | public init(texture: Texture!, rect: Rect, rotated: Bool, trimOffset: Point, untrimmedSize: Size) { 44 | self._texture = texture 45 | self.rect = rect 46 | self.trimOffset = trimOffset 47 | self.untrimmedSize = untrimmedSize 48 | self.isRotated = rotated 49 | } 50 | 51 | /** Texture used by the frame. 52 | @see Texture */ 53 | public var texture: Texture { 54 | return _texture ?? lazyTexture 55 | } 56 | internal var _texture: Texture? 57 | 58 | /** Texture image file name used to create the texture. Set by the sprite frame cache */ 59 | internal(set) public var textureFilename: String = "" { 60 | didSet { 61 | // Make sure any previously loaded texture is cleared. 62 | self._texture = nil 63 | self._lazyTexture = nil 64 | } 65 | } 66 | 67 | internal var lazyTexture: Texture { 68 | if _lazyTexture == nil && textureFilename != "" { 69 | _lazyTexture = TextureCache.shared.addImage(from: textureFilename) 70 | _texture = _lazyTexture 71 | } 72 | return texture 73 | } 74 | private var _lazyTexture: Texture? 75 | 76 | /** Rectangle of the frame within the texture, in points. */ 77 | public let rect: Rect 78 | 79 | /** Returns whether or not the texture rectangle is rotated. Sprite sheet editors may rotate sprite frames in a texture to fit more sprites in the same atlas. */ 80 | public let isRotated: Bool 81 | 82 | /** To save space in a spritesheet, the transparent edges of a frame may be trimmed. This is the original size in points of a frame before it was trimmed. */ 83 | public let untrimmedSize: Size 84 | 85 | /** To save space in a spritesheet, the transparent edges of a frame may be trimmed. This is offset of the sprite caused by trimming in points. */ 86 | public let trimOffset: Point 87 | 88 | public var description: String { 89 | return " rotated:\(isRotated) offset = \(trimOffset.description))" 90 | } 91 | 92 | /** 93 | Purge all unused spriteframes from the cache. 94 | */ 95 | public static func purgeCache() { 96 | SpriteFrameCache.shared.removeUnusedSpriteFrames() 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Fiber2D/SpriteNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SpriteNode.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 04.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | /** 12 | * SpriteNode draws a Texture on the screen. 13 | * 14 | * The default anchorPoint in SpriteNode is (0.5, 0.5). 15 | */ 16 | open class SpriteNode: Node { 17 | 18 | public var sprite: Sprite? { 19 | if let src = getComponent(by: SpriteRenderComponent.self) { 20 | return src.sprite 21 | } 22 | return nil 23 | } 24 | 25 | public convenience init(imageNamed: String) { 26 | self.init(sprite: Sprite(imageNamed: imageNamed)) 27 | } 28 | 29 | public init(sprite: Sprite) { 30 | super.init() 31 | self.anchorPoint = p2d(0.5, 0.5) 32 | let src = SpriteRenderComponent(sprite: sprite) 33 | 34 | self.contentSizeInPoints = sprite.spriteFrame.untrimmedSize 35 | add(component: src) 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Fiber2D/System.swift: -------------------------------------------------------------------------------- 1 | // 2 | // System.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 26.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public protocol System: class, Pausable { 10 | 11 | func onAdd(to scene: Scene) 12 | func onRemove() 13 | 14 | /** 15 | * Component related methods 16 | */ 17 | func add(component: Component) 18 | func remove(component: Component) 19 | 20 | /** Returns true if system needs to know about certain type of components 21 | * This method is called for every component that is added to the node 22 | * Ex. implementation for PhysicsSystem will look like this: 23 | * *** public func wants(component: Component) -> Bool { 24 | * *** return component is PhysicsBody 25 | * *** } 26 | * @note that if multiple systems will want same type of components, 27 | * it will lead to undefined behaviour 28 | */ 29 | func wants(component: Component) -> Bool 30 | } 31 | 32 | // default implementations AKA optional methods 33 | public extension System { 34 | func onAdd(to scene: Scene) {} 35 | func onRemove() {} 36 | } 37 | 38 | public struct ComponentNode where T: ComponentBase { 39 | unowned let node: Node 40 | weak var component: T? 41 | 42 | var children = [ComponentNode]() 43 | } 44 | 45 | public extension Node { 46 | public func subtree(of type: T.Type) -> ComponentNode 47 | where T: Component { 48 | let body = self.getComponent(by: type) 49 | var children = [ComponentNode]() 50 | for c in self.children { 51 | let subtree = c.subtree(of: type) 52 | if subtree.component != nil || subtree.children.count > 0 { 53 | children.append(subtree) 54 | } 55 | } 56 | 57 | return ComponentNode(node: self, component: body, children: children) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Fiber2D/Texture+Image.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Texture+Image.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 28.10.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftBGFX 10 | import SwiftMath 11 | import Foundation 12 | 13 | public extension Texture { 14 | public static func make(from image: Image) -> Texture { 15 | let w = UInt16(image.sizeInPixels.width) 16 | let h = UInt16(image.sizeInPixels.height) 17 | let size = UInt32(w * h) * UInt32(MemoryLayout.size / MemoryLayout.size) 18 | let memoryBlock = MemoryBlock(size: size) 19 | image.pixelData?.copyBytes(to: memoryBlock.data, count: Int(size)) 20 | 21 | let tex = Texture(bgfxTexture: BGFXTexture.make2D(width: w, height: h, 22 | mipCount: 1, format: .bgra8, 23 | memory: memoryBlock)) 24 | tex.contentScale = image.contentScale 25 | tex.contentSizeInPixels = image.sizeInPixels 26 | return tex 27 | } 28 | 29 | // TODO: Should have more parameters 30 | public static func makeRenderTexture(of size: Size) -> Texture { 31 | let w = UInt16(size.width) 32 | let h = UInt16(size.height) 33 | 34 | let tex = BGFXTexture.make2D(width: w, height: h, mipCount: 1, format: .bgra8, options: [.renderTarget, .clampU, .clampV], memory: nil) 35 | 36 | let retVal = Texture(bgfxTexture: tex) 37 | retVal.contentScale = Setup.shared.assetScale 38 | retVal.contentSizeInPixels = size 39 | return retVal 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Fiber2D/ViewportNode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewportNode.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 13.10.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | #if os(iOS) || os(tvOS) || os(macOS) 11 | import Darwin 12 | #else 13 | import Glibc 14 | #endif 15 | 16 | public class ViewportNode: Node { 17 | public var projection = Matrix4x4f.identity 18 | 19 | /** 20 | * Node that controls the camera's transform (position/rotation/zoom) 21 | */ 22 | public var camera: Camera! 23 | 24 | /** 25 | * User assignable node that holds the content that the viewport will show. 26 | */ 27 | public var contentNode: Node { 28 | get { return camera.children.first! } 29 | set { 30 | contentNode.removeFromParent() 31 | camera.add(child: newValue) 32 | } 33 | } 34 | 35 | /** 36 | * Create a viewport with the size of the screen and an empty contentNode. 37 | */ 38 | convenience override init() { 39 | self.init(contentNode: Node()) 40 | } 41 | 42 | /** 43 | * Create a viewport with the given size and content node. Uses a orthographic projection. Initially the viewport is screen-sized. 44 | * 45 | * @param contentNode Provide the content node. Its children are drawn into the viewport. 46 | * 47 | * @return The ViewportNode 48 | */ 49 | init(contentNode: Node) { 50 | super.init() 51 | contentSize = Director.current.viewSize 52 | camera = Camera(viewport: self) 53 | add(child: camera) 54 | camera.add(child: contentNode) 55 | 56 | projection = Matrix4x4f.orthoProjection(for: self) 57 | } 58 | 59 | // Convenience constructors to create screen sized viewports. 60 | public static func centered(size: Size) -> ViewportNode { 61 | let viewport = ViewportNode() 62 | viewport.camera.position = size * 0.5 63 | 64 | let s = viewport.contentSizeInPoints 65 | viewport.projection = Matrix4x4f.ortho(left: -s.width / 2, right: s.width / 2, 66 | bottom: -s.height / 2, top: s.height / 2, 67 | near: 1024, far: -1024) 68 | return viewport 69 | } 70 | 71 | override func visit(_ renderer: Renderer, parentTransform: Matrix4x4f) { 72 | guard visible else { 73 | return 74 | } 75 | 76 | let size = contentSizeInPoints 77 | let w = size.width 78 | let h = size.height 79 | let viewportTransform = parentTransform * nodeToParentMatrix 80 | let v0 = viewportTransform.multiplyAndProject(v: vec3(0, 0, 0)) 81 | let v1 = viewportTransform.multiplyAndProject(v: vec3(w, 0, 0)) 82 | let v2 = viewportTransform.multiplyAndProject(v: vec3(w, h, 0)) 83 | let v3 = viewportTransform.multiplyAndProject(v: vec3(0, h, 0)) 84 | 85 | let fbSize = Director.current.viewSizeInPixels 86 | let hw = fbSize.width / 2.0 87 | let hh = fbSize.width / 2.0 88 | 89 | var minx = floorf(hw + hw*min(min(v0.x, v1.x), min(v2.x, v3.x))) 90 | var maxx = floorf(hw + hw*max(max(v0.x, v1.x), max(v2.x, v3.x))) 91 | var miny = floorf(hh + hh*min(min(v0.y, v1.y), min(v2.y, v3.y))) 92 | var maxy = floorf(hh + hh*max(max(v0.y, v1.y), max(v2.y, v3.y))) 93 | 94 | minx = max(0, minx) 95 | miny = max(0, miny) 96 | maxx = min(maxx, fbSize.width) 97 | maxy = min(maxy, fbSize.height) 98 | 99 | // TODO: Push group of draw calls with the viewport of (minx, miny, maxx - minx, maxy - miny) 100 | let transform = camera.cameraMatrix 101 | sortAllChildren() 102 | for c in camera.children { 103 | c.visit(renderer, parentTransform: transform) 104 | } 105 | 106 | // TODO: Pop group here (or push further, in bgfx terms), 107 | // restore viewport to backbuffer's default 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Fiber2D/protocols/BehaviourProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BehaviourProtocol.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 25.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public protocol Pausable { 10 | var paused: Bool { get set } 11 | } 12 | 13 | public protocol Updatable: class, Prioritized { 14 | func update(delta: Time) 15 | } 16 | 17 | public protocol FixedUpdatable: class, Prioritized { 18 | func fixedUpdate(delta: Time) 19 | } 20 | 21 | // TODO: Isn't really used anywhere yet 22 | public protocol LateUpdatable: class, Prioritized { 23 | func lateUpdate(delta: Time) 24 | } 25 | -------------------------------------------------------------------------------- /Fiber2D/protocols/Cloneable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Cloneable.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 25.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public protocol Cloneable { 10 | /// Returns new object that is a clone of a given instance 11 | var clone: Self { get } 12 | } 13 | -------------------------------------------------------------------------------- /Fiber2D/protocols/DirectorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DirectorView.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 09.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | // purposefully undocumented: used only internally 12 | // Protocol for a view that Director will use to render into. 13 | public protocol DirectorView: class { 14 | var sizeInPixels: Size { get } 15 | var size: Size { get } 16 | // Prepare the view to render a new frame. 17 | func beginFrame() 18 | 19 | // Schedule a block to be invoked when the frame completes. 20 | // The block may not be invoked from the main thread. 21 | // @param handler The completion block. The block takes no arguments and has no return value. 22 | func add(frameCompletionHandler handler: @escaping () -> ()) 23 | } 24 | -------------------------------------------------------------------------------- /Fiber2D/protocols/Prioritized.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Prioritized.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 25.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public protocol Prioritized { 10 | // Used to break ties for scheduled blocks, updated: and fixedUpdate: methods. 11 | // Targets are sorted by priority so lower priorities are called first. 12 | // The priority value for a given object should be constant. 13 | var priority: Int { get } 14 | } 15 | 16 | public extension Prioritized { 17 | var priority: Int { 18 | return 0 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Fiber2D/protocols/Tagged.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tagged.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 03.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public protocol Tagged { 10 | var tag: Int { get set } 11 | } 12 | -------------------------------------------------------------------------------- /Fiber2D/typedefs/enums/CullMode.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CullMode.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 24.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftBGFX 10 | 11 | public struct CullMode { 12 | internal let renderState: RenderStateOptions 13 | /// Don't perform culling of back faces. 14 | public static let none = CullMode(renderState: RenderStateOptions.noCulling) 15 | /// Perform culling of clockwise faces. 16 | public static let clockwise = CullMode(renderState: RenderStateOptions.cullClockwise) 17 | /// Perform culling of counter-clockwise faces. 18 | public static let counterClockwise = CullMode(renderState: RenderStateOptions.cullCounterclockwise) 19 | } 20 | 21 | -------------------------------------------------------------------------------- /Fiber2D/typedefs/enums/UnitTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnitTypes.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 29.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | /** Scale types alter how a node's scale property values are interpreted. Used by, for instance, [Node setScaleType:]. */ 10 | public enum ScaleType { 11 | /** Scale is assumed to be in points */ 12 | case points, 13 | /** Scale is assumed to be in UI points */ 14 | scaled 15 | } 16 | 17 | /** Position unit types alter how a node's position property values are interpreted. Used by, for instance, Node.positionType */ 18 | public enum PositionUnit { 19 | /// Position is set in points (this is the default) 20 | case points, 21 | /// Position is UI points, on iOS this corresponds to the native point system 22 | uiPoints, 23 | 24 | /// Position is a normalized value multiplied by the content size of the parent's container 25 | normalized 26 | } 27 | 28 | /** Size unit types alter how a node's contentSize property values are interpreted. Used by, for instance, Node.contentSizeType */ 29 | public enum SizeUnit { 30 | /// Content size is set in points (this is the default) 31 | case points, 32 | 33 | /// Position is UI points, on iOS this corresponds to the native point system 34 | uiPoints, 35 | 36 | /// Content size is a normalized value (percentage) multiplied by the content size of the parent's container 37 | normalized, 38 | 39 | /// Content size is the size of the parents container inset by the supplied value 40 | insetPoints, 41 | 42 | /// Content size is the size of the parents container inset by the supplied value multiplied by the UIScaleFactor (as defined by Director) 43 | insetUIPoints 44 | } 45 | 46 | /** Reference corner determines a node's origin and affects how the position property values are interpreted. Used by, for instance, Node.positionType. */ 47 | public enum PositionReferencePoint { 48 | /// Position is relative to the bottom left corner of the parent container (this is the default) 49 | case bottomLeft, 50 | 51 | /// Position is relative to the top left corner of the parent container 52 | topLeft, 53 | 54 | /// Position is relative to the top right corner of the parent container 55 | topRight, 56 | 57 | /// Position is relative to the bottom right corner of the parent container 58 | bottomRight 59 | } 60 | 61 | /** Position type compines PositionUnit and PositionReferenceCorner. */ 62 | public struct PositionType { 63 | public let xUnit: PositionUnit 64 | public let yUnit: PositionUnit 65 | public let corner: PositionReferencePoint 66 | 67 | public init(xUnit: PositionUnit, yUnit: PositionUnit, corner: PositionReferencePoint) { 68 | self.xUnit = xUnit 69 | self.yUnit = yUnit 70 | self.corner = corner 71 | } 72 | 73 | public var isBasicPoints: Bool { 74 | return xUnit == .points 75 | && yUnit == .points 76 | && corner == .bottomLeft 77 | } 78 | 79 | public static let points = PositionType(xUnit: .points, yUnit: .points, corner: .bottomLeft) 80 | public static let uiPoints = PositionType(xUnit: .uiPoints, yUnit: .uiPoints, corner: .bottomLeft) 81 | public static let normalized = PositionType(xUnit: .normalized, yUnit: .normalized, corner: .bottomLeft) 82 | } 83 | 84 | /** Position type compines SizeUnit. */ 85 | public struct SizeType { 86 | public let xUnit: SizeUnit 87 | public let yUnit: SizeUnit 88 | 89 | public init(xUnit: SizeUnit, yUnit: SizeUnit) { 90 | self.xUnit = xUnit 91 | self.yUnit = yUnit 92 | } 93 | 94 | public var isBasicPoints: Bool { 95 | return xUnit == .points 96 | && yUnit == .points 97 | } 98 | 99 | public static let points = SizeType(xUnit: .points, yUnit: .points) 100 | public static let uiPoints = SizeType(xUnit: .uiPoints, yUnit: .uiPoints) 101 | public static let normalized = SizeType(xUnit: .normalized, yUnit: .normalized) 102 | } 103 | -------------------------------------------------------------------------------- /Fiber2D/typedefs/structs/Input.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Input.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 08.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | 11 | public struct Input { 12 | public var screenPosition: Point 13 | 14 | #if os(OSX) || os(Linux) || os(Windows) 15 | public var mouseButton: MouseButton 16 | #endif 17 | 18 | #if os(iOS) || os(Android) 19 | public var force: Float = 1.0 20 | #endif 21 | } 22 | 23 | public extension Input { 24 | public func location(in node: Node) -> Point { 25 | return node.convertToNodeSpace(screenPosition) 26 | } 27 | } 28 | 29 | public enum MouseButton { 30 | // Indicates that none button is currently pressed on a mouse 31 | case none 32 | case left 33 | case right 34 | case other 35 | } 36 | 37 | public enum Key { 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Fiber2D/typedefs/structs/Tree.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Tree.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 18.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | internal final class Tree { 10 | public var value: T 11 | 12 | fileprivate(set) public weak var parent: Tree? 13 | fileprivate(set) public var children: [Tree] = [] 14 | 15 | public init(value: T) { 16 | self.value = value 17 | } 18 | 19 | public func add(child: Tree) { 20 | guard child.parent == nil else { 21 | fatalError("Can't add a child that already has a parent") 22 | } 23 | child.parent = self 24 | children.append(child) 25 | } 26 | } 27 | 28 | internal typealias UInt8Tree = Tree 29 | 30 | internal extension Array where Element: UInt8Tree { 31 | internal func childrenFirstTraverse() -> [UInt8] { 32 | var retVal = [UInt8]() 33 | 34 | for e in self { 35 | recursivelyPutChildren(from: e, into: &retVal) 36 | } 37 | return retVal 38 | } 39 | 40 | } 41 | 42 | fileprivate func recursivelyPutChildren(from tree: Tree, into array: inout [UInt8]) { 43 | for c in tree.children { 44 | recursivelyPutChildren(from: c, into: &array) 45 | } 46 | 47 | array.append(tree.value) 48 | } 49 | -------------------------------------------------------------------------------- /Fiber2D/typedefs/structs/WeakBox.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WeakBox.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 02.11.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | public struct WeakBox where T: AnyObject { 10 | public weak var value: T? 11 | 12 | public init(_ val: T) { 13 | self.value = val 14 | } 15 | } 16 | 17 | public extension Dictionary where Value: AnyObject { 18 | public mutating func removeUnusedObjects() { 19 | var weakDict = [Key: WeakBox]() 20 | 21 | for (k, v) in self { 22 | weakDict[k] = WeakBox(v) 23 | } 24 | 25 | removeAll() 26 | 27 | for (k, v) in weakDict { 28 | if let frame = v.value { 29 | self[k] = frame 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Fiber2D/utils/ArrayExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArrayExtensions.swift 3 | // cocos2d-tests 4 | // 5 | // Created by Andrey Volodin on 07.06.16. 6 | // Copyright © 2016 Cocos2d. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension Array { 12 | @discardableResult 13 | // FIXME: We need to get rid of this 14 | // The whole thing is very ugly and does not work the same on all platforms 15 | // We need to maintain this because Swift still can't treat :class protocol as AnyObject 16 | mutating func removeObject(_ obj: AnyObject) -> Bool { 17 | var idx = 0 18 | for e in self { 19 | #if os(iOS) || os(tvOS) 20 | if (e as AnyObject) === obj { 21 | remove(at: idx) 22 | return true 23 | } 24 | #else 25 | if (e as! AnyObject) === obj { 26 | remove(at: idx) 27 | return true 28 | } 29 | #endif 30 | idx += 1 31 | } 32 | 33 | return false 34 | } 35 | } 36 | 37 | public extension ContiguousArray where Element: AnyObject { 38 | @discardableResult 39 | mutating func remove(object: AnyObject) -> Bool { 40 | var idx = 0 41 | for e in self { 42 | if e === object { 43 | remove(at: idx) 44 | return true 45 | } 46 | idx += 1 47 | } 48 | 49 | return false 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | SWIFT_FLAGS_COMMON = -Xswiftc -Iexternal/SwiftBGFX/3rdparty/bgfx/3rdparty/khronos \ 3 | -Xswiftc -Iexternal/SwiftBGFX/3rdparty/bx/include \ 4 | -Xswiftc -Iexternal/SwiftBGFX/3rdparty/bgfx/3rdparty \ 5 | -Xlinker -lc++ \ 6 | -Xlinker -lbgfxDebug -Xlinker -lbxDebug -Xlinker -lbimgDebug -Xlinker -lz \ 7 | -Xcc -DCP_USE_CGTYPES=0 8 | 9 | APPLE_FLAGS = -Xlinker -framework -Xlinker Foundation 10 | IOS_FLAGS = -Xlinker -Lexternal/SwiftBGFX/3rdparty/bgfx/.build/ios-arm64/bin \ 11 | -Xlinker -framework -Xlinker OpenGLES -Xlinker -framework -Xlinker UIKit 12 | MACOS_FLAGS = -Xlinker -framework -Xlinker AppKit -Xlinker -framework -Xlinker Quartz \ 13 | -Xlinker -Lexternal/SwiftBGFX/3rdparty/bgfx/.build/osx64_clang/bin \ 14 | -Xcc -Iexternal/SwiftBGFX/3rdparty/bx/include/compat/osx 15 | ANDROID_FLAGS = -Xswiftc -I$(ANDROID_NDK_HOME)/sources/android/native_app_glue/ \ 16 | -Xcc -Idemo/platform/android/android-project/jni/SDL2-2.0.5/include \ 17 | -Xcc -I$(ANDROID_NDK_HOME)/platforms/android-21/arch-arm/usr/include \ 18 | -Xswiftc -I$(ANDROID_SWIFT_SOURCE)/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation \ 19 | -Xswiftc -I$(ANDROID_SWIFT_SOURCE)/swift-corelibs-foundation \ 20 | -Xswiftc -I$(ANDROID_SWIFT_SOURCE)/swift-corelibs-foundation/closure \ 21 | -Xswiftc -target -Xswiftc armv7-none-linux-androideabi \ 22 | -Xswiftc -sdk -Xswiftc $(ANDROID_NDK_HOME)/platforms/android-21/arch-arm \ 23 | -Xswiftc -DNOSIMD \ 24 | -Xlinker -L/usr/local/lib/swift/android/ \ 25 | -Xlinker -L$(ANDROID_SWIFT_SOURCE)/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation/ \ 26 | -Xlinker -L$(ANDROID_NDK_HOME)/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a \ 27 | -Xlinker -L$(ANDROID_NDK_HOME)/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/ \ 28 | -Xlinker -L$(ANDROID_NDK_HOME)/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/lib/armv7-a/ \ 29 | -Xlinker -L$(ANDROID_LIBICONV)/armeabi-v7a \ 30 | -Xlinker -Ldemo/platform/android/android-project/libs/armeabi-v7a/ \ 31 | -Xlinker -Lexternal/SwiftBGFX/3rdparty/bgfx/.build/android-arm/bin \ 32 | -Xlinker -lgcc -Xlinker -ldispatch -Xlinker -lFoundation \ 33 | -Xlinker -latomic -Xlinker -licui18n -Xlinker -licuuc \ 34 | -Xlinker --sysroot=$(ANDROID_NDK_HOME)/platforms/android-21/arch-arm/ 35 | 36 | CC_FLAGS_METAL = -Xcc -DBGFX_CONFIG_RENDERER_METAL=1 37 | SWIFT_FLAGS_METAL = -Xlinker -framework -Xlinker Metal -Xlinker -framework -Xlinker MetalKit 38 | 39 | macos: 40 | swift build $(SWIFT_FLAGS_COMMON) $(MACOS_FLAGS) $(CC_FLAGS_METAL) $(SWIFT_FLAGS_METAL) $(APPLE_FLAGS) 41 | 42 | android: 43 | swift build $(SWIFT_FLAGS_COMMON) $(ANDROID_FLAGS) 44 | 45 | xcodeproj-ios: 46 | swift package \ 47 | $(SWIFT_FLAGS_COMMON) $(SWIFT_FLAGS_METAL) $(CC_FLAGS_METAL) $(IOS_FLAGS) $(APPLE_FLAGS) \ 48 | generate-xcodeproj --xcconfig-overrides xcode/ios-overrides.xcconfig \ 49 | --output Fiber2D-iOS.xcodeproj 50 | 51 | xcodeproj-macos: 52 | swift package $(SWIFT_FLAGS_COMMON) $(SWIFT_FLAGS_METAL) $(CC_FLAGS_METAL) $(MACOS_FLAGS) \ 53 | generate-xcodeproj --xcconfig-overrides xcode/macos-overrides.xcconfig \ 54 | --output xcode/Fiber2D-macOS.xcodeproj 55 | 56 | clean: 57 | swift build --clean 58 | 59 | .PHONY: clean xcodeproj-ios xcodeproj-macos macos android 60 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "Fiber2D", 6 | products: [ 7 | .library(name: "Fiber2D", type: .static, targets: ["Fiber2D"]), 8 | .executable(name: "Fiber2D-macOS", targets: ["Fiber2D-macOSDemo"]) 9 | ], 10 | dependencies: [ 11 | .package(url: "https://github.com/s1ddok/CChipmunk2D", .upToNextMinor(from: "2.0.0")), 12 | .package(url: "https://github.com/s1ddok/Cpng", .upToNextMinor(from: "2.0.0")), 13 | .package(url: "external/SwiftBGFX", .upToNextMinor(from: "2.0.0")), 14 | // Add this for Linux/Android or macOS (not recommended): 15 | // https://github.com/s1ddok/CSDL2 1.0.0 16 | ], 17 | targets: [ 18 | .target( 19 | name: "Fiber2D", 20 | dependencies: [ 21 | "Cpng", 22 | "CChipmunk2D", 23 | "SwiftBGFX" 24 | ], 25 | path: ".", 26 | sources: ["Fiber2D"] 27 | ), 28 | .target( 29 | name: "Fiber2D-macOSDemo", 30 | dependencies: ["Fiber2D"], 31 | path: "./demo", 32 | sources: ["MainScene.swift", 33 | "UserComponents.swift", 34 | "platform/apple/Fiber2D-demo/main.swift", 35 | "platform/apple/Fiber2D-demo/AppDelegate.swift", 36 | "platform/apple/Fiber2D-demo/MetalView.swift"]) 37 | ], 38 | swiftLanguageVersions: [4] 39 | ) 40 | 41 | -------------------------------------------------------------------------------- /demo/InputScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InputScene.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 25.01.17. 6 | // Copyright © 2017 s1ddok. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | -------------------------------------------------------------------------------- /demo/PhysicsScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsScene.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 28.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import Fiber2D 10 | import SwiftMath 11 | 12 | public class PhysicsScene: Scene { 13 | 14 | var physicsSystem: PhysicsSystem! 15 | 16 | override init(size: Size) { 17 | super.init(size: size) 18 | 19 | let material = PhysicsMaterial.default 20 | let colors: [Color] = [.red, .blue, .green, .orange] 21 | 22 | let world = PhysicsWorld(rootNode: self) 23 | physicsSystem = PhysicsSystem(world: world) 24 | register(system: physicsSystem) 25 | 26 | let ground = ColorNode() 27 | ground.contentSize = Size(1.0, 0.1) 28 | ground.contentSizeType = SizeType.normalized 29 | ground.color = .orange 30 | add(child: ground) 31 | 32 | let boxBody = PhysicsBody.box(size: ground.contentSizeInPoints, material: material) 33 | boxBody.isDynamic = false 34 | ground.add(component: boxBody) 35 | 36 | let pikeSize = Size(620, 32) 37 | let pike1 = ColorNode() 38 | pike1.contentSize = pikeSize 39 | pike1.color = .white 40 | pike1.position = p2d(320, 400) 41 | add(child: pike1) 42 | let boxBody1 = PhysicsBody.box(size: pikeSize, material: material) 43 | boxBody1.isDynamic = false 44 | pike1.add(component: boxBody1) 45 | 46 | for _ in 0...10 { 47 | let node = Node() 48 | node.contentSize = Size(128, 128) 49 | node.position = p2d(0.5, 0.5) 50 | node.positionType = .normalized 51 | node.rotation = Angle(degrees: Float.random(0, 180)) 52 | 53 | let colorNode = ColorNode() 54 | colorNode.position = p2d(0.5, 1.5) 55 | colorNode.positionType = .normalized 56 | colorNode.color = colors[Int.random(0, colors.count - 1)] 57 | colorNode.contentSize = Size(32, 32) 58 | node.add(child: colorNode) 59 | 60 | let rotateForever = ActionRotateBy(angle: 15°).continously(duration: Float.random(0.5, 2)).repeatForever 61 | node.run(action: rotateForever) 62 | add(child: node) 63 | } 64 | 65 | let spawnSquares = ActionCallBlock { [unowned self] in 66 | let squareSize = Size(22, 22) 67 | let physicsSquare = ColorNode() 68 | physicsSquare.color = colors[Int.random(0, colors.count - 1)] 69 | physicsSquare.contentSize = squareSize 70 | let physicsBody = PhysicsBody.box(size: squareSize, material: material) 71 | physicsBody.isDynamic = true 72 | physicsBody.isGravityEnabled = true 73 | physicsSquare.add(component: physicsBody) 74 | 75 | physicsSquare.position = self.contentSize * vec2(Float.random(0, 1), 1.0) 76 | self.add(child: physicsSquare) 77 | }.instantly.then(ActionWait(for: 1.0)).repeat(times: 100) 78 | 79 | self.run(action: spawnSquares) 80 | 81 | 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /demo/UserComponents.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserComponents.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 27.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import Fiber2D 10 | 11 | public class UpdateComponent: ComponentBase, Updatable { 12 | 13 | override init() { 14 | super.init() 15 | tag = 97 16 | } 17 | 18 | public func update(delta: Time) { 19 | //print("I'm updatable component. I'm updated with: \(delta)") 20 | } 21 | } 22 | 23 | public class FixedUpdateComponent: ComponentBase, FixedUpdatable { 24 | override init() { 25 | super.init() 26 | tag = 98 27 | } 28 | public func fixedUpdate(delta: Time) { 29 | //print("I'm fixed updatable component. I'm updated with \(delta)") 30 | } 31 | } 32 | 33 | public class EnterComponent: ComponentBase { 34 | override init() { 35 | super.init() 36 | tag = 96 37 | } 38 | 39 | public override func onAdd(to owner: Node) { 40 | super.onAdd(to: owner) 41 | 42 | owner.onEnter.subscribe(on: self, callback: EnterComponent.onEnter(self)) 43 | } 44 | 45 | fileprivate func onEnter() { 46 | print("Owner did enter the active scene") 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /demo/ViewportScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewportScene.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 15.10.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import Cocoa 11 | import Fiber2D 12 | 13 | class CustomBehaviour: ComponentBase, Updatable { 14 | let vps: ViewportScene 15 | 16 | init(v: ViewportScene) { 17 | vps = v 18 | } 19 | 20 | func update(delta: Time) { 21 | vps.viewport.camera.position = vps.cn.positionInPoints 22 | } 23 | } 24 | 25 | class ViewportScene: Scene { 26 | var viewport: ViewportNode! 27 | let cn = Sprite(imageNamed: "circle.png")//ColorNode() 28 | 29 | override init(size: Size) { 30 | super.init(size: size) 31 | 32 | let container = Node() 33 | container.contentSizeInPoints = Size(1048, 1048) 34 | 35 | //cn.contentSize = Size(62.0, 32.0) 36 | cn.positionType = .normalized 37 | cn.position = p2d(0.5, 0.5) 38 | //cn.anchorPoint = cn.position 39 | //cn.color = .red 40 | container.add(child: cn) 41 | viewport = ViewportNode.centered(size: size) 42 | viewport.contentNode = container 43 | add(child: viewport) 44 | 45 | let bl = ColorNode() 46 | bl.contentSize = Size(32.0, 32.0) 47 | bl.position = .zero 48 | bl.color = .blue 49 | container.add(child: bl) 50 | 51 | let tr = ColorNode() 52 | tr.contentSize = Size(32.0, 32.0) 53 | tr.position = p2d(1.0, 1.0) 54 | tr.positionType = .normalized 55 | tr.color = .blue 56 | container.add(child: tr) 57 | 58 | let placeholder = ColorNode() 59 | placeholder.contentSizeType = .normalized 60 | placeholder.contentSize = Size(1.0, 1.0) 61 | //container.add(child: placeholder) 62 | add(component: CustomBehaviour(v: self)) 63 | } 64 | 65 | /*override func inputBegan(_ input: Input) { 66 | viewport.camera.position = viewport.camera.position - vec2(32.0, 32.0) 67 | print(viewport.camera.children.first!.positionInPoints) 68 | } 69 | 70 | override func inputDragged(_ input: Input) { 71 | viewport.camera.positionInPoints = input.location(in: self) 72 | } 73 | 74 | override func keyDown(_ theEvent: NSEvent) { 75 | 76 | switch theEvent.keyCode { 77 | /*case 123: 78 | viewport.camera.positionInPoints = viewport.camera.positionInPoints - vec2(10.0, 0.0) 79 | case 124: 80 | viewport.camera.positionInPoints = viewport.camera.positionInPoints + vec2(10.0, 0.0) 81 | case 125: 82 | viewport.camera.positionInPoints = viewport.camera.positionInPoints - vec2(0.0, 10.0) 83 | case 126: 84 | viewport.camera.positionInPoints = viewport.camera.positionInPoints + vec2(0.0, 10.0) 85 | default: 86 | ()*/ 87 | case 123: 88 | cn.position = cn.position - vec2(0.01, 0.0) 89 | case 124: 90 | cn.position = cn.position + vec2(0.01, 0.0) 91 | case 125: 92 | cn.position = cn.position - vec2(0.0, 0.01) 93 | case 126: 94 | cn.position = cn.position + vec2(0.0, 0.01) 95 | default: 96 | () 97 | } 98 | }*/ 99 | } 100 | -------------------------------------------------------------------------------- /demo/images/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s1ddok/Fiber2D/fcd5e96a716553c78302359dcbe5ef83106b7673/demo/images/circle.png -------------------------------------------------------------------------------- /demo/images/ninepatch_bubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s1ddok/Fiber2D/fcd5e96a716553c78302359dcbe5ef83106b7673/demo/images/ninepatch_bubble.png -------------------------------------------------------------------------------- /demo/platform/android/build.sh: -------------------------------------------------------------------------------- 1 | cd f2dc 2 | swift build \ 3 | -Xcc -I../../../../external/SwiftBGFX/3rdparty/bgfx/3rdparty/khronos \ 4 | -Xcc -I../../../../external/SwiftBGFX/3rdparty/bx/include \ 5 | -Xcc -I../../../../external/SwiftBGFX/3rdparty/bgfx/3rdparty \ 6 | -Xcc -DCP_USE_CGTYPES=0 \ 7 | -Xcc -I$ANDROID_NDK_HOME/platforms/android-21/arch-arm/usr/include \ 8 | -Xswiftc -I$ANDROID_NDK_HOME/sources/android/native_app_glue/ \ 9 | -Xswiftc -I$ANDROID_SWIFT_SOURCE/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation \ 10 | -Xswiftc -I$ANDROID_SWIFT_SOURCE/swift-corelibs-foundation \ 11 | -Xswiftc -I$ANDROID_SWIFT_SOURCE/swift-corelibs-foundation/closure \ 12 | -Xswiftc -I../android-project/jni/SDL2-2.0.5/include \ 13 | -Xswiftc -target -Xswiftc armv7-none-linux-androideabi \ 14 | -Xswiftc -sdk -Xswiftc $ANDROID_NDK_HOME/platforms/android-21/arch-arm \ 15 | -Xswiftc -DNOSIMD \ 16 | -Xlinker -L/usr/local/lib/swift/android/ \ 17 | -Xlinker -L$ANDROID_SWIFT_SOURCE/build/Ninja-ReleaseAssert/foundation-linux-x86_64/Foundation/ \ 18 | -Xlinker -L$ANDROID_NDK_HOME/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a \ 19 | -Xlinker -L$ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/ \ 20 | -Xlinker -L$ANDROID_NDK_HOME/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/arm-linux-androideabi/lib/armv7-a/ \ 21 | -Xlinker -L$ANDROID_LIBICONV/armeabi-v7a \ 22 | -Xlinker -L../android-project/libs/armeabi-v7a/ \ 23 | -Xlinker -L../../../../external/SwiftBGFX/3rdparty/bgfx/.build/android-arm/bin \ 24 | -Xlinker -lgcc -Xlinker -ldispatch -Xlinker -lFoundation \ 25 | -Xlinker -latomic -Xlinker -licui18n -Xlinker -licuuc \ 26 | -Xlinker -lc++_shared -Xlinker -lbgfxDebug -Xlinker -lz \ 27 | -Xlinker --sysroot=$ANDROID_NDK_HOME/platforms/android-21/arch-arm/ 28 | 29 | cp -f .build/debug/libFiber2D.so ../android-project/libs/armeabi-v7a/libFiber2D.so 30 | cp -f .build/debug/libf2dc.so ../android-project/libs/armeabi-v7a/libf2dc.so 31 | cp -f .build/debug/libCbgfx.so ../android-project/libs/armeabi-v7a/libCbgfx.so 32 | cp -f .build/debug/libCpng.so ../android-project/libs/armeabi-v7a/libCpng.so 33 | cp -f .build/debug/libCChipmunk2D.so ../android-project/libs/armeabi-v7a/libCChipmunk2D.so 34 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "f2dc", 5 | dependencies: [ 6 | .Package(url: "https://github.com/s1ddok/CSDL2", majorVersion: 1), 7 | .Package(url: "https://github.com/s1ddok/CAndroidAppGlue", majorVersion: 1), 8 | .Package(url: "../../../../", Version(0, 0, 1)) 9 | ] 10 | ) 11 | 12 | let ar = Product(name: "f2dc", type: .Library(.Dynamic), modules: "f2dc") 13 | products.append(ar) 14 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/EventType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Event.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 08.01.17. 6 | // 7 | // 8 | 9 | import CSDL2 10 | 11 | public struct EventType: Equatable { 12 | internal let type: SDL_EventType 13 | 14 | public init(_ type: SDL_EventType) { 15 | self.type = type 16 | } 17 | 18 | public static let audioDeviceAdded = EventType(SDL_AUDIODEVICEADDED) 19 | public static let audioDeviceRemoved = EventType(SDL_AUDIODEVICEREMOVED) 20 | public static let controllerAxisMotion = EventType(SDL_CONTROLLERAXISMOTION) 21 | public static let controllerButtonDown = EventType(SDL_CONTROLLERBUTTONDOWN) 22 | public static let controllerButtonUp = EventType(SDL_CONTROLLERBUTTONUP) 23 | public static let controllerDeviceAdded = EventType(SDL_CONTROLLERDEVICEADDED) 24 | public static let controllerDeviceRemoved = EventType(SDL_CONTROLLERDEVICEREMOVED) 25 | public static let controllerDeviceRemapped = EventType(SDL_CONTROLLERDEVICEREMAPPED) 26 | public static let dropFile = EventType(SDL_DROPFILE) 27 | public static let joyAxisMotion = EventType(SDL_JOYAXISMOTION) 28 | public static let joyBallMotion = EventType(SDL_JOYBALLMOTION) 29 | public static let joyHatMotion = EventType(SDL_JOYHATMOTION) 30 | public static let joyButtonDown = EventType(SDL_JOYBUTTONDOWN) 31 | public static let joyButtonUp = EventType(SDL_JOYBUTTONUP) 32 | public static let joyDeviceAdded = EventType(SDL_JOYDEVICEADDED) 33 | public static let joyDeviceRemoved = EventType(SDL_JOYDEVICEREMOVED) 34 | public static let keyUp = EventType(SDL_KEYUP) 35 | public static let keyDown = EventType(SDL_KEYDOWN) 36 | public static let mouseButtonDown = EventType(SDL_MOUSEBUTTONDOWN) 37 | public static let mouseButtonUp = EventType(SDL_MOUSEBUTTONUP) 38 | public static let mouseMotion = EventType(SDL_MOUSEMOTION) 39 | public static let mouseWheel = EventType(SDL_MOUSEWHEEL) 40 | public static let fingerDown = EventType(SDL_FINGERDOWN) 41 | public static let fingerMotion = EventType(SDL_FINGERMOTION) 42 | public static let fingerUp = EventType(SDL_FINGERUP) 43 | public static let quit = EventType(SDL_QUIT) 44 | public static let sysWMEvent = EventType(SDL_SYSWMEVENT) 45 | public static let textEditing = EventType(SDL_TEXTEDITING) 46 | public static let textInput = EventType(SDL_TEXTINPUT) 47 | public static let userEvent = EventType(SDL_USEREVENT) 48 | public static let windowEvent = EventType(SDL_WINDOWEVENT) 49 | 50 | public static func from(event: SDL_Event) -> EventType { 51 | return EventType(SDL_EventType(event.type)) 52 | } 53 | public static func ==(lhs: EventType, rhs: EventType) -> Bool { 54 | return lhs.type == rhs.type 55 | } 56 | 57 | public static func ==(lhs: EventType, rhs: SDL_EventType) -> Bool { 58 | return lhs.type == rhs 59 | } 60 | 61 | public static func ==(lhs: SDL_EventType, rhs: EventType) -> Bool { 62 | return lhs == rhs.type 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/InputScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InputScene.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 25.01.17. 6 | // Copyright © 2017 s1ddok. All rights reserved. 7 | // 8 | 9 | import SwiftMath 10 | import Fiber2D 11 | 12 | public class DragTransformComponent: Responder { 13 | public override func inputDragged(_ input: Input) { 14 | let sceneSize = owner!.scene!.contentSizeInPoints 15 | let inputLocation = input.location(in: self.owner!.scene!) 16 | self.owner!.position = inputLocation 17 | self.owner!.rotation = Angle(degrees: 180 * input.screenPosition.x / sceneSize.width) 18 | self.owner!.scale = 2 * input.screenPosition.y / sceneSize.height 19 | } 20 | } 21 | 22 | public class InputScene: Scene { 23 | 24 | public override init(size: Size) { 25 | super.init(size: size) 26 | 27 | let square = ColorNode(color: .red, size: Size(64, 64)) 28 | square.anchorPoint = vec2(0.5, 0.5) 29 | square.position = boundingBox.size * 0.5 30 | square.responder = DragTransformComponent() 31 | self.add(child:square) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/PhysicsScene.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhysicsScene.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 28.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import Fiber2D 10 | import SwiftMath 11 | 12 | public class PhysicsScene: Scene { 13 | 14 | var physicsSystem: PhysicsSystem! 15 | 16 | override init(size: Size) { 17 | super.init(size: size) 18 | 19 | let material = PhysicsMaterial.default 20 | let colors: [Color] = [.red, .blue, .green, .orange] 21 | 22 | let world = PhysicsWorld(rootNode: self) 23 | physicsSystem = PhysicsSystem(world: world) 24 | register(system: physicsSystem) 25 | 26 | let ground = ColorNode() 27 | ground.contentSize = Size(1.0, 0.1) 28 | ground.contentSizeType = SizeType.normalized 29 | ground.color = .orange 30 | add(child: ground) 31 | 32 | let boxBody = PhysicsBody.box(size: ground.contentSizeInPoints, material: material) 33 | boxBody.isDynamic = false 34 | ground.add(component: boxBody) 35 | 36 | let pikeSize = Size(620, 32) 37 | let pike1 = ColorNode() 38 | pike1.contentSize = pikeSize 39 | pike1.color = .white 40 | pike1.position = p2d(320, 400) 41 | add(child: pike1) 42 | let boxBody1 = PhysicsBody.box(size: pikeSize, material: material) 43 | boxBody1.isDynamic = false 44 | pike1.add(component: boxBody1) 45 | 46 | for _ in 0...10 { 47 | let node = Node() 48 | node.contentSize = Size(128, 128) 49 | node.position = p2d(0.5, 0.5) 50 | node.positionType = .normalized 51 | node.rotation = Angle(degrees: Float.random(0, 180)) 52 | 53 | let colorNode = ColorNode() 54 | colorNode.position = p2d(0.5, 1.5) 55 | colorNode.positionType = .normalized 56 | colorNode.color = colors[Int.random(0, colors.count - 1)] 57 | colorNode.contentSize = Size(32, 32) 58 | node.add(child: colorNode) 59 | 60 | let rotateForever = ActionRotateBy(angle: 15°).continously(duration: Float.random(0.5, 2)).repeatForever 61 | node.run(action: rotateForever) 62 | add(child: node) 63 | } 64 | 65 | let spawnSquares = ActionCallBlock { [unowned self] in 66 | let squareSize = Size(22, 22) 67 | let physicsSquare = ColorNode() 68 | physicsSquare.color = colors[Int.random(0, colors.count - 1)] 69 | physicsSquare.contentSize = squareSize 70 | let physicsBody = PhysicsBody.box(size: squareSize, material: material) 71 | physicsBody.isDynamic = true 72 | physicsBody.isGravityEnabled = true 73 | physicsSquare.add(component: physicsBody) 74 | 75 | physicsSquare.position = self.contentSize * vec2(Float.random(0, 1), 1.0) 76 | self.add(child: physicsSquare) 77 | }.instantly.then(ActionCallBlock{}.continously(duration: 0.5)).repeat(times: 100) 78 | 79 | self.run(action: spawnSquares) 80 | 81 | 82 | 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/Surface.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Surface.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 15.12.16. 6 | // 7 | // 8 | 9 | import CSDL2 10 | 11 | public class Surface { 12 | internal let handle: UnsafeMutablePointer 13 | 14 | public init(handle: UnsafeMutablePointer) { 15 | self.handle = handle 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/Window+Fiber2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Window+Fiber2D.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 15.12.16. 6 | // 7 | // 8 | 9 | import SwiftMath 10 | import Fiber2D 11 | 12 | extension Window: DirectorView { 13 | public func add(frameCompletionHandler handler: @escaping () -> ()) { } 14 | 15 | public var sizeInPixels: Size { 16 | return Size(width, height) 17 | } 18 | 19 | public var size: Size { 20 | return Size(width, height) 21 | } 22 | 23 | // Prepare the view to render a new frame. 24 | public func beginFrame() {} 25 | 26 | // Present the current frame to the display. 27 | public func presentFrame() {} 28 | } 29 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/Window.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Window.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 14.12.16. 6 | // 7 | // 8 | 9 | import CSDL2 10 | import SwiftMath 11 | import Foundation 12 | 13 | func CSDL_GetError() -> String { 14 | return String(cString: SDL_GetError()) 15 | } 16 | 17 | public struct WindowFlags: OptionSet { 18 | public let rawValue: UInt32 19 | 20 | public init(rawValue: UInt32) { 21 | self.rawValue = rawValue 22 | } 23 | 24 | static let fullscreen = WindowFlags(rawValue: SDL_WINDOW_FULLSCREEN.rawValue) 25 | static let openGL = WindowFlags(rawValue: SDL_WINDOW_OPENGL.rawValue) 26 | static let shown = WindowFlags(rawValue: SDL_WINDOW_SHOWN.rawValue) 27 | static let hidden = WindowFlags(rawValue: SDL_WINDOW_HIDDEN.rawValue) 28 | static let borderless = WindowFlags(rawValue: SDL_WINDOW_BORDERLESS.rawValue) 29 | static let resizable = WindowFlags(rawValue: SDL_WINDOW_RESIZABLE.rawValue) 30 | static let ninimised = WindowFlags(rawValue: SDL_WINDOW_MINIMIZED.rawValue) 31 | static let saximised = WindowFlags(rawValue: SDL_WINDOW_MAXIMIZED.rawValue) 32 | static let inputGrabbed = WindowFlags(rawValue: SDL_WINDOW_INPUT_GRABBED.rawValue) 33 | static let inputFocus = WindowFlags(rawValue: SDL_WINDOW_INPUT_FOCUS.rawValue) 34 | static let mouseFocus = WindowFlags(rawValue: SDL_WINDOW_MOUSE_FOCUS.rawValue) 35 | static let fullscreenDesktop = WindowFlags(rawValue: SDL_WINDOW_FULLSCREEN_DESKTOP.rawValue) 36 | static let foreign = WindowFlags(rawValue: SDL_WINDOW_FOREIGN.rawValue) 37 | static let allowHighDPI = WindowFlags(rawValue: SDL_WINDOW_ALLOW_HIGHDPI.rawValue) 38 | static let mouseCapture = WindowFlags(rawValue: SDL_WINDOW_MOUSE_CAPTURE.rawValue) 39 | } 40 | 41 | let WindowPosUndefined = SDL_WINDOWPOS_UNDEFINED_MASK | 0 42 | let WindowPosCentered = SDL_WINDOWPOS_CENTERED_MASK | 0 43 | 44 | public class Window { 45 | 46 | let handle: OpaquePointer 47 | 48 | public init(title: String = "Untitled", origin: Point, size: Size, flags: WindowFlags) { 49 | guard let handle = SDL_CreateWindow(title, 50 | Int32(origin.x), Int32(origin.y), 51 | Int32(size.width), Int32(size.height), 52 | flags.rawValue) else { 53 | NSLog(CSDL_GetError()) 54 | fatalError("") 55 | } 56 | 57 | self.handle = handle 58 | 59 | } 60 | 61 | deinit { 62 | SDL_DestroyWindow(handle) 63 | } 64 | 65 | public var title: String { 66 | get { 67 | return String(describing: SDL_GetWindowTitle(handle)) 68 | } 69 | set(newTitle) { 70 | SDL_SetWindowTitle(handle, newTitle) 71 | } 72 | } 73 | 74 | public var id: UInt32 { 75 | return SDL_GetWindowID(handle) 76 | } 77 | 78 | public var width: Int { 79 | var width: Int32 = 0 80 | SDL_GetWindowSize(handle, &width, nil) 81 | return Int(width) 82 | } 83 | 84 | public var height: Int { 85 | var height: Int32 = 0 86 | SDL_GetWindowSize(handle, nil, &height) 87 | return Int(height) 88 | } 89 | 90 | public lazy var surface: Surface = { 91 | let surfaceHandle = SDL_GetWindowSurface(self.handle)! 92 | return Surface(handle: surfaceHandle) 93 | }() 94 | 95 | public func show() { 96 | SDL_ShowWindow(handle) 97 | } 98 | 99 | public func hide() { 100 | SDL_HideWindow(handle) 101 | } 102 | 103 | public func update() { 104 | SDL_UpdateWindowSurface(handle) 105 | } 106 | 107 | public func updateRects() { 108 | // TODO: implement using SDL_UpdateWindowSurfaceRects() 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/WindowMock.swift: -------------------------------------------------------------------------------- 1 | 2 | import SwiftMath 3 | import Fiber2D 4 | 5 | class WindowMock: DirectorView { 6 | let a = 0 7 | 8 | public func add(frameCompletionHandler handler: @escaping () -> ()) { } 9 | 10 | public var sizeInPixels: Size { 11 | return Size(1280, 720) 12 | } 13 | 14 | public var size: Size { 15 | return Size(1280, 720) 16 | } 17 | 18 | // Prepare the view to render a new frame. 19 | public func beginFrame() {} 20 | 21 | // Present the current frame to the display. 22 | public func presentFrame() {} 23 | } 24 | -------------------------------------------------------------------------------- /demo/platform/android/f2dc/Sources/gameMain.swift: -------------------------------------------------------------------------------- 1 | import CSDL2 2 | import SwiftMath 3 | import SwiftBGFX 4 | import Fiber2D 5 | import CAndroidAppGlue 6 | import Foundation 7 | 8 | @_cdecl("SDL_main") 9 | public func SDL_main(argc: Int32, argv: OpaquePointer) -> Int32 { 10 | var pd = PlatformData() 11 | 12 | #if os(OSX) 13 | 14 | pd.ndt = nil 15 | // Hack around C anonymous structs, will see if it works... 16 | var cocoa = wmi.info.cocoa 17 | let pointer = UnsafeMutableRawPointer(&cocoa) 18 | pd.nwh = pointer.assumingMemoryBound(to: UnsafeMutableRawPointer.self).pointee 19 | 20 | #endif 21 | 22 | #if os(Linux) 23 | 24 | let window = Window(title: "Fiber2D-SDL", origin: .zero, size: Size(1024, 768), flags: [.shown]) 25 | 26 | var wmi = SDL_SysWMinfo() 27 | SDL_SysWMinfo_init_version(&wmi) 28 | print(SDL_GetWindowWMInfo(window.handle, &wmi)) 29 | 30 | 31 | pd.ndt = SDL_SysWMinfo_get_x11_display(&wmi) 32 | pd.nwh = SDL_SysWMinfo_get_x11_window(&wmi) 33 | 34 | #endif 35 | 36 | #if os(Android) 37 | let _window = Window(title: "Fiber2D-SDL", origin: .zero, size: Size(1280, 720), flags: [.shown, .resizable]) 38 | //pd.nwh = SDL_SysWMinfo_get_android_window(&wmi) 39 | pd.nwh = CAPG_GetNativeWindow() 40 | 41 | #endif 42 | 43 | SDL_Init(SDL_INIT_EVENTS) 44 | 45 | bgfx.setPlatformData(pd) 46 | let locator = FileLocator.shared 47 | locator.untaggedContentScale = 4 48 | locator.searchPaths = [ "/Users/s1ddok/Documents/Projects/GitHub/Fiber2D/demo/Resources"] 49 | 50 | let window = WindowMock() 51 | 52 | bgfx.renderFrame() 53 | bgfx.initialize() 54 | bgfx.reset(width: UInt16(window.sizeInPixels.width), height: UInt16(window.sizeInPixels.height), options: [.vsync]) 55 | 56 | let director: Director = Director(view: window) 57 | Director.pushCurrentDirector(director) 58 | //let scene = PhysicsScene(size: director.designSize) 59 | let scene = InputScene(size: director.designSize) 60 | scene.color = .red 61 | director.present(scene: scene) 62 | Director.popCurrentDirector() 63 | 64 | var running = true 65 | var event = SDL_Event() 66 | while running { 67 | Director.pushCurrentDirector(director) 68 | while SDL_PollEvent(&event) != 0 { 69 | switch EventType.from(event: event) { 70 | case EventType.fingerDown: 71 | let innerEvent = event.tfinger 72 | director.responderManager.fingerDown(event: innerEvent) 73 | case EventType.fingerUp: 74 | let innerEvent = event.tfinger 75 | director.responderManager.fingerUp(event: innerEvent) 76 | case EventType.fingerMotion: 77 | let innerEvent = event.tfinger 78 | director.responderManager.fingerMoved(event: innerEvent) 79 | case EventType.quit: 80 | running = true 81 | default: 82 | break 83 | } 84 | } 85 | Director.popCurrentDirector() 86 | 87 | director.mainLoopBody() 88 | } 89 | 90 | return 0 91 | } 92 | -------------------------------------------------------------------------------- /demo/platform/apple/.swift-version: -------------------------------------------------------------------------------- 1 | DEVELOPMENT-SNAPSHOT-2017-01-04-a 2 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo-iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Fiber2D-demo-iOS 4 | // 5 | // Created by Andrey Volodin on 30.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftBGFX 11 | import Fiber2D 12 | 13 | @UIApplicationMain 14 | class AppDelegate: UIResponder, UIApplicationDelegate { 15 | 16 | var window: UIWindow? 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 19 | Setup.shared.contentScale = 2.0 20 | //;2*[_view convertSizeToBacking:NSMakeSize(1, 1)].width; 21 | Setup.shared.assetScale = Setup.shared.contentScale 22 | Setup.shared.UIScale = 0.5 23 | 24 | self.window = UIWindow(frame: UIScreen.main.bounds) 25 | guard let window = window else { 26 | fatalError("Window must be present at this time") 27 | } 28 | 29 | let rect: CGRect = window.bounds 30 | 31 | let view: MetalView = MetalView(frame: rect) 32 | 33 | let locator = FileLocator.shared 34 | locator.untaggedContentScale = 4 35 | locator.searchPaths = [ Bundle.main.resourcePath!, Bundle.main.resourcePath! + "/images" ] 36 | 37 | var pd = PlatformData() 38 | pd.nwh = UnsafeMutableRawPointer(Unmanaged.passRetained(view).toOpaque()) 39 | pd.context = UnsafeMutableRawPointer(Unmanaged.passRetained(view.device!).toOpaque()) 40 | bgfx.setPlatformData(pd) 41 | bgfx.renderFrame() 42 | bgfx.initialize(type: .metal) 43 | bgfx.reset(width: UInt16(rect.width), height: UInt16(rect.height), options: [.vsync, .flipAfterRender]) 44 | 45 | let vc = UIViewController() 46 | vc.view = view 47 | window.rootViewController = vc 48 | window.makeKeyAndVisible() 49 | let director: Director = view.director 50 | Director.pushCurrentDirector(director) 51 | //director.present(scene: PhysicsScene(size: director.designSize)) 52 | director.present(scene: MainScene(size: director.designSize)) 53 | //director.present(scene: ViewportScene(size: director.designSize)) 54 | Director.popCurrentDirector() 55 | return true 56 | } 57 | 58 | func applicationWillResignActive(_ application: UIApplication) { 59 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 60 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 61 | } 62 | 63 | func applicationDidEnterBackground(_ application: UIApplication) { 64 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 65 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 66 | } 67 | 68 | func applicationWillEnterForeground(_ application: UIApplication) { 69 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 70 | } 71 | 72 | func applicationDidBecomeActive(_ application: UIApplication) { 73 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 74 | } 75 | 76 | func applicationWillTerminate(_ application: UIApplication) { 77 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 78 | } 79 | 80 | 81 | } 82 | 83 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo-iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo-iOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo-iOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo-iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationLandscapeLeft 34 | UIInterfaceOrientationLandscapeRight 35 | 36 | UISupportedInterfaceOrientations~ipad 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationPortraitUpsideDown 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo-iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Fiber2D-demo-iOS 4 | // 5 | // Created by Andrey Volodin on 30.12.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 25.07.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import SwiftBGFX 11 | import Fiber2D 12 | 13 | class AppDelegate: NSObject, NSApplicationDelegate { 14 | 15 | var window: NSWindow! 16 | var director: Director! 17 | var renderer: Renderer! 18 | 19 | func applicationDidFinishLaunching(_ aNotification: Notification) { 20 | Setup.shared.contentScale = 2.0 21 | //;2*[_view convertSizeToBacking:NSMakeSize(1, 1)].width; 22 | Setup.shared.assetScale = Setup.shared.contentScale 23 | Setup.shared.UIScale = 0.5 24 | let rect: CGRect = CGRect(x: 0, y: 0, width: 1280, height: 720) 25 | window = NSWindow(contentRect: rect, styleMask: [.closable, .resizable, .titled], backing: .buffered, defer: false, screen: NSScreen.main) 26 | 27 | let view: MetalView = MetalView(frame: rect) 28 | view.wantsBestResolutionOpenGLSurface = true 29 | self.window.contentView = view 30 | 31 | let locator = FileLocator.shared 32 | locator.untaggedContentScale = 4 33 | // This is this way only for demo purposes. Real applications should use `.app` format of distribution and provide Bundle.main based paths 34 | locator.searchPaths = [ /*Bundle.main.resourcePath!*/ "../../demo/" + "/images" ] 35 | 36 | window.center() 37 | window.makeFirstResponder(view) 38 | window.makeKeyAndOrderFront(window) 39 | 40 | var pd = PlatformData() 41 | pd.nwh = UnsafeMutableRawPointer(Unmanaged.passRetained(view).toOpaque()) 42 | pd.context = UnsafeMutableRawPointer(Unmanaged.passRetained(view.device!).toOpaque()) 43 | bgfx.setPlatformData(pd) 44 | 45 | bgfx.initialize(type: .metal) 46 | bgfx.reset(width: 1280, height: 720, options: [.vsync, .flipAfterRender]) 47 | 48 | self.window.acceptsMouseMovedEvents = true 49 | let director: Director = view.director 50 | Director.pushCurrentDirector(director) 51 | //director.present(scene: MinimalScene(size: director.designSize)) 52 | //director.present(scene: PhysicsScene(size: director.designSize)) 53 | director.present(scene: MainScene(size: director.designSize)) 54 | //director.present(scene: ViewportScene(size: director.designSize)) 55 | Director.popCurrentDirector() 56 | } 57 | 58 | func applicationWillTerminate(_ aNotification: Notification) { 59 | // Insert code here to tear down your application 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2016 s1ddok. All rights reserved. 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /demo/platform/apple/Fiber2D-demo/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 09.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import AppKit 11 | 12 | let delegate = AppDelegate() 13 | let app = NSApplication.shared 14 | app.delegate = delegate 15 | app.setActivationPolicy(.regular) 16 | app.activate(ignoringOtherApps: true) 17 | app.performSelector(onMainThread: #selector(NSApplication.run), 18 | with: nil, waitUntilDone: true) 19 | -------------------------------------------------------------------------------- /demo/platform/sdl/Makefile: -------------------------------------------------------------------------------- 1 | SHARED_FLAGS = -Xlinker -lFiber2D \ 2 | -Xswiftc -I../../../.build/debug \ 3 | -Xswiftc -I../../../external/Cpng/Cpng/include \ 4 | -Xswiftc -I../../../external/CChipmunk2D/CChipmunk2D/include \ 5 | -Xlinker -L../../../.build/debug \ 6 | -Xcc -DCP_USE_CGTYPES=0 7 | 8 | MACOS_SDL_FLAGS = -Xswiftc -I/usr/local/include -Xlinker -L/usr/local/lib 9 | LINUX_SDL_FLAGS = -Xswiftc -I/usr/include \ 10 | -Xlinker -L/usr/lib -Xlinker -lGL -Xlinker -lX11 11 | 12 | macos: 13 | swift build $(SHARED_FLAGS) $(MACOS_SDL_FLAGS) 14 | cp ../../../.build/debug/*.dylib .build/debug 15 | 16 | xcodeproj-macos: 17 | swift package $(SHARED_FLAGS) $(MACOS_SDL_FLAGS) \ 18 | generate-xcodeproj 19 | 20 | .PHONY: macos 21 | -------------------------------------------------------------------------------- /demo/platform/sdl/Package.swift: -------------------------------------------------------------------------------- 1 | import PackageDescription 2 | 3 | let package = Package( 4 | name: "Fiber2D-demo", 5 | dependencies: [ 6 | .Package(url: "https://github.com/s1ddok/CSDL2", Version(1, 0, 0)) 7 | ] 8 | ) 9 | -------------------------------------------------------------------------------- /demo/platform/sdl/Sources/EventType.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Event.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 08.01.17. 6 | // 7 | // 8 | 9 | import CSDL2 10 | 11 | public struct EventType: Equatable { 12 | internal let type: SDL_EventType 13 | 14 | public init(_ type: SDL_EventType) { 15 | self.type = type 16 | } 17 | 18 | public static let audioDeviceAdded = EventType(SDL_AUDIODEVICEADDED) 19 | public static let audioDeviceRemoved = EventType(SDL_AUDIODEVICEREMOVED) 20 | public static let controllerAxisMotion = EventType(SDL_CONTROLLERAXISMOTION) 21 | public static let controllerButtonDown = EventType(SDL_CONTROLLERBUTTONDOWN) 22 | public static let controllerButtonUp = EventType(SDL_CONTROLLERBUTTONUP) 23 | public static let controllerDeviceAdded = EventType(SDL_CONTROLLERDEVICEADDED) 24 | public static let controllerDeviceRemoved = EventType(SDL_CONTROLLERDEVICEREMOVED) 25 | public static let controllerDeviceRemapped = EventType(SDL_CONTROLLERDEVICEREMAPPED) 26 | public static let dropFile = EventType(SDL_DROPFILE) 27 | public static let joyAxisMotion = EventType(SDL_JOYAXISMOTION) 28 | public static let joyBallMotion = EventType(SDL_JOYBALLMOTION) 29 | public static let joyHatMotion = EventType(SDL_JOYHATMOTION) 30 | public static let joyButtonDown = EventType(SDL_JOYBUTTONDOWN) 31 | public static let joyButtonUp = EventType(SDL_JOYBUTTONUP) 32 | public static let joyDeviceAdded = EventType(SDL_JOYDEVICEADDED) 33 | public static let joyDeviceRemoved = EventType(SDL_JOYDEVICEREMOVED) 34 | public static let keyUp = EventType(SDL_KEYUP) 35 | public static let keyDown = EventType(SDL_KEYDOWN) 36 | public static let mouseButtonDown = EventType(SDL_MOUSEBUTTONDOWN) 37 | public static let mouseButtonUp = EventType(SDL_MOUSEBUTTONUP) 38 | public static let mouseMotion = EventType(SDL_MOUSEMOTION) 39 | public static let mouseWheel = EventType(SDL_MOUSEWHEEL) 40 | public static let quit = EventType(SDL_QUIT) 41 | public static let sysWMEvent = EventType(SDL_SYSWMEVENT) 42 | public static let textEditing = EventType(SDL_TEXTEDITING) 43 | public static let textInput = EventType(SDL_TEXTINPUT) 44 | public static let userEvent = EventType(SDL_USEREVENT) 45 | public static let windowEvent = EventType(SDL_WINDOWEVENT) 46 | 47 | public static func ==(lhs: EventType, rhs: EventType) -> Bool { 48 | return lhs.type == rhs.type 49 | } 50 | 51 | public static func ==(lhs: EventType, rhs: SDL_EventType) -> Bool { 52 | return lhs.type == rhs 53 | } 54 | 55 | public static func ==(lhs: SDL_EventType, rhs: EventType) -> Bool { 56 | return lhs == rhs.type 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /demo/platform/sdl/Sources/Surface.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Surface.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 15.12.16. 6 | // 7 | // 8 | 9 | import CSDL2 10 | 11 | public class Surface { 12 | internal let handle: UnsafeMutablePointer 13 | 14 | public init(handle: UnsafeMutablePointer) { 15 | self.handle = handle 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /demo/platform/sdl/Sources/UserComponents.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserComponents.swift 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 27.09.16. 6 | // Copyright © 2016 s1ddok. All rights reserved. 7 | // 8 | 9 | import Fiber2D 10 | 11 | public class UpdateComponent: ComponentBase, Updatable { 12 | 13 | override init() { 14 | super.init() 15 | tag = 97 16 | } 17 | 18 | public func update(delta: Time) { 19 | //print("I'm updatable component. I'm updated with: \(delta)") 20 | } 21 | } 22 | 23 | public class FixedUpdateComponent: ComponentBase, FixedUpdatable { 24 | override init() { 25 | super.init() 26 | tag = 98 27 | } 28 | public func fixedUpdate(delta: Time) { 29 | //print("I'm fixed updatable component. I'm updated with \(delta)") 30 | } 31 | } 32 | 33 | public class EnterComponent: ComponentBase { 34 | override init() { 35 | super.init() 36 | tag = 96 37 | } 38 | 39 | public override func onAdd(to owner: Node) { 40 | super.onAdd(to: owner) 41 | 42 | owner.onEnter.subscribe(on: self, callback: EnterComponent.onEnter(self)) 43 | } 44 | 45 | fileprivate func onEnter() { 46 | print("Owner did enter the active scene") 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /demo/platform/sdl/Sources/Window+Fiber2D.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Window+Fiber2D.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 15.12.16. 6 | // 7 | // 8 | 9 | import SwiftMath 10 | import Fiber2D 11 | 12 | extension Window: DirectorView { 13 | public func add(frameCompletionHandler handler: @escaping () -> ()) { } 14 | 15 | public var sizeInPixels: Size { 16 | return Size(width, height) 17 | } 18 | 19 | public var size: Size { 20 | return Size(width, height) 21 | } 22 | 23 | // Prepare the view to render a new frame. 24 | public func beginFrame() {} 25 | 26 | // Present the current frame to the display. 27 | public func presentFrame() {} 28 | } 29 | -------------------------------------------------------------------------------- /demo/platform/sdl/Sources/Window.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Window.swift 3 | // Fiber2D-demo 4 | // 5 | // Created by Andrey Volodin on 14.12.16. 6 | // 7 | // 8 | 9 | import CSDL2 10 | import SwiftMath 11 | 12 | public struct WindowFlags: OptionSet { 13 | public let rawValue: UInt32 14 | 15 | public init(rawValue: UInt32) { 16 | self.rawValue = rawValue 17 | } 18 | 19 | static let fullscreen = WindowFlags(rawValue: SDL_WINDOW_FULLSCREEN.rawValue) 20 | static let openGL = WindowFlags(rawValue: SDL_WINDOW_OPENGL.rawValue) 21 | static let shown = WindowFlags(rawValue: SDL_WINDOW_SHOWN.rawValue) 22 | static let hidden = WindowFlags(rawValue: SDL_WINDOW_HIDDEN.rawValue) 23 | static let borderless = WindowFlags(rawValue: SDL_WINDOW_BORDERLESS.rawValue) 24 | static let resizable = WindowFlags(rawValue: SDL_WINDOW_RESIZABLE.rawValue) 25 | static let ninimised = WindowFlags(rawValue: SDL_WINDOW_MINIMIZED.rawValue) 26 | static let saximised = WindowFlags(rawValue: SDL_WINDOW_MAXIMIZED.rawValue) 27 | static let inputGrabbed = WindowFlags(rawValue: SDL_WINDOW_INPUT_GRABBED.rawValue) 28 | static let inputFocus = WindowFlags(rawValue: SDL_WINDOW_INPUT_FOCUS.rawValue) 29 | static let mouseFocus = WindowFlags(rawValue: SDL_WINDOW_MOUSE_FOCUS.rawValue) 30 | static let fullscreenDesktop = WindowFlags(rawValue: SDL_WINDOW_FULLSCREEN_DESKTOP.rawValue) 31 | static let foreign = WindowFlags(rawValue: SDL_WINDOW_FOREIGN.rawValue) 32 | static let allowHighDPI = WindowFlags(rawValue: SDL_WINDOW_ALLOW_HIGHDPI.rawValue) 33 | static let mouseCapture = WindowFlags(rawValue: SDL_WINDOW_MOUSE_CAPTURE.rawValue) 34 | } 35 | 36 | let WindowPosUndefined = SDL_WINDOWPOS_UNDEFINED_MASK | 0 37 | let WindowPosCentered = SDL_WINDOWPOS_CENTERED_MASK | 0 38 | 39 | public class Window { 40 | 41 | let handle: OpaquePointer 42 | 43 | public init(title: String = "Untitled", origin: Point, size: Size, flags: WindowFlags) { 44 | handle = SDL_CreateWindow(title, 45 | Int32(origin.x), Int32(origin.y), 46 | Int32(size.width), Int32(size.height), 47 | flags.rawValue) 48 | 49 | } 50 | 51 | deinit { 52 | SDL_DestroyWindow(handle) 53 | } 54 | 55 | public var title: String { 56 | get { 57 | return String(describing: SDL_GetWindowTitle(handle)) 58 | } 59 | set(newTitle) { 60 | SDL_SetWindowTitle(handle, newTitle) 61 | } 62 | } 63 | 64 | public var id: UInt32 { 65 | return SDL_GetWindowID(handle) 66 | } 67 | 68 | public var width: Int { 69 | var width: Int32 = 0 70 | SDL_GetWindowSize(handle, &width, nil) 71 | return Int(width) 72 | } 73 | 74 | public var height: Int { 75 | var height: Int32 = 0 76 | SDL_GetWindowSize(handle, nil, &height) 77 | return Int(height) 78 | } 79 | 80 | public lazy var surface: Surface = { 81 | let surfaceHandle = SDL_GetWindowSurface(self.handle)! 82 | return Surface(handle: surfaceHandle) 83 | }() 84 | 85 | public func show() { 86 | SDL_ShowWindow(handle) 87 | } 88 | 89 | public func hide() { 90 | SDL_HideWindow(handle) 91 | } 92 | 93 | public func update() { 94 | SDL_UpdateWindowSurface(handle) 95 | } 96 | 97 | public func updateRects() { 98 | // TODO: implement using SDL_UpdateWindowSurfaceRects() 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /demo/platform/sdl/Sources/main.swift: -------------------------------------------------------------------------------- 1 | import CSDL2 2 | import SwiftMath 3 | import SwiftBGFX 4 | import Fiber2D 5 | 6 | let window = Window(title: "Fiber2D-SDL", origin: .zero, size: Size(1024, 768), flags: [.shown]) 7 | 8 | var wmi = SDL_SysWMinfo() 9 | SDL_SysWMinfo_init_version(&wmi) 10 | print(SDL_GetWindowWMInfo(window.handle, &wmi)) 11 | var pd = PlatformData() 12 | 13 | #if os(OSX) 14 | pd.ndt = nil 15 | // Hack around C anonymous structs, will see if it works... 16 | var cocoa = wmi.info.cocoa 17 | let pointer = UnsafeMutableRawPointer(&cocoa) 18 | pd.nwh = pointer.assumingMemoryBound(to: UnsafeMutableRawPointer.self).pointee 19 | 20 | #endif 21 | 22 | #if os(Linux) 23 | 24 | pd.ndt = SDL_SysWMinfo_get_x11_display(&wmi) 25 | pd.nwh = SDL_SysWMinfo_get_x11_window(&wmi) 26 | 27 | #endif 28 | 29 | bgfx.setPlatformData(pd) 30 | let locator = FileLocator.shared 31 | locator.untaggedContentScale = 4 32 | locator.searchPaths = [ "/Users/s1ddok/Documents/Projects/GitHub/Fiber2D/demo/images"] 33 | 34 | bgfx.renderFrame() 35 | bgfx.initialize() 36 | bgfx.reset(width: 1024, height: 768, options: [.vsync]) 37 | 38 | var event = SDL_Event() 39 | var running = true 40 | 41 | let director: Director = Director(view: window) 42 | Director.pushCurrentDirector(director) 43 | director.present(scene: MainScene(size: director.designSize)) 44 | Director.popCurrentDirector() 45 | 46 | while running { 47 | director.mainLoopBody() 48 | } 49 | -------------------------------------------------------------------------------- /shaders/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.bin 3 | -------------------------------------------------------------------------------- /shaders/compile_shaders.sh: -------------------------------------------------------------------------------- 1 | ./shaderc -f f2d_builtin_postexture.sc --platform osx \ 2 | --varyingdef varying.def.sc -i ../external/SwiftBGFX/3rdparty/bgfx/src \ 3 | -o f2d_postex_mtl.bin --bin2c --type fragment -p metal 4 | 5 | ./shaderc -f f2d_builtin_postexture.sc --platform linux \ 6 | --varyingdef varying.def.sc -i ../external/SwiftBGFX/3rdparty/bgfx/src \ 7 | -o f2d_postex_gl.bin --bin2c --type fragment 8 | 9 | ./shaderc -f f2d_builtin_poscolor.sc --platform osx \ 10 | --varyingdef varying.def.sc -i ../external/SwiftBGFX/3rdparty/bgfx/src \ 11 | -o f2d_poscolor_mtl.bin --bin2c --type fragment -p metal 12 | 13 | ./shaderc -f f2d_builtin_poscolor.sc --platform linux \ 14 | --varyingdef varying.def.sc -i ../external/SwiftBGFX/3rdparty/bgfx/src \ 15 | -o f2d_poscolor_gl.bin --bin2c --type fragment 16 | 17 | ./shaderc -f f2d_builtin_vertex.sc --platform osx \ 18 | --varyingdef varying.def.sc -i ../external/SwiftBGFX/3rdparty/bgfx/src \ 19 | -o f2d_vertex_mtl.bin --bin2c --type vertex -p metal 20 | 21 | ./shaderc -f f2d_builtin_vertex.sc --platform linux \ 22 | --varyingdef varying.def.sc -i ../external/SwiftBGFX/3rdparty/bgfx/src \ 23 | -o f2d_vertex_gl.bin --bin2c --type vertex 24 | -------------------------------------------------------------------------------- /shaders/f2d_builtin_poscolor.sc: -------------------------------------------------------------------------------- 1 | $input v_color0, v_texcoord0 2 | 3 | #include "bgfx_shader.sh" 4 | 5 | void main() 6 | { 7 | gl_FragColor = v_color0; 8 | } 9 | -------------------------------------------------------------------------------- /shaders/f2d_builtin_postexture.sc: -------------------------------------------------------------------------------- 1 | $input v_color0, v_texcoord0 2 | 3 | // Default position texture shader 4 | 5 | #include "bgfx_shader.sh" 6 | 7 | SAMPLER2D(s_texColor, 0); 8 | 9 | void main() 10 | { 11 | gl_FragColor = mul(v_color0, texture2D(s_texColor, v_texcoord0)); 12 | } 13 | -------------------------------------------------------------------------------- /shaders/f2d_builtin_vertex.sc: -------------------------------------------------------------------------------- 1 | $input a_position, a_texcoord0, a_texcoord1, a_color0 2 | $output v_texcoord0, v_color0 3 | 4 | void main() 5 | { 6 | gl_Position = a_position; 7 | v_texcoord0 = a_texcoord0; 8 | v_color0 = a_color0; 9 | } 10 | -------------------------------------------------------------------------------- /shaders/shaderc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/s1ddok/Fiber2D/fcd5e96a716553c78302359dcbe5ef83106b7673/shaders/shaderc -------------------------------------------------------------------------------- /shaders/varying.def.sc: -------------------------------------------------------------------------------- 1 | vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0); 2 | vec2 v_texcoord1 : TEXCOORD1 = vec2(0.0, 0.0); 3 | vec4 v_color0 : COLOR0 = vec4(1.0, 1.0, 1.0, 1.0); 4 | 5 | vec4 a_position : POSITION; 6 | vec2 a_texcoord0 : TEXCOORD0; 7 | vec2 a_texcoord1 : TEXCOORD0; 8 | vec4 a_color0 : COLOR0; 9 | -------------------------------------------------------------------------------- /xcode/ios-overrides.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // ios-overrides.xcconfig 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 30.12.16. 6 | // 7 | // 8 | 9 | // Disable code signing for successful device builds with Xcode 8. Frameworks do 10 | // need to be signed, but they don't need to be signed at compile time because 11 | // they'll be re-signed when you include them in your app. 12 | CODE_SIGNING_REQUIRED = NO 13 | CODE_SIGN_IDENTITY = 14 | 15 | // Whether this framework should define an LLVM module 16 | DEFINES_MODULE = YES 17 | 18 | // Disallows use of APIs that are not available to app extensions and linking to 19 | // frameworks that have not been built with this setting enabled. 20 | APPLICATION_EXTENSION_API_ONLY = YES 21 | 22 | // The base SDK to use (if no version is specified, the latest is assumed) 23 | SDKROOT = iphoneos 24 | 25 | // Supported device families (1 is iPhone, 2 is iPad) 26 | SUPPORTED_PLATFORMS = iphonesimulator iphoneos 27 | SWIFT_TREAT_WARNINGS_AS_ERRORS = YES 28 | 29 | GCC_PREPROCESSOR_DEFINITIONS = CP_USE_CGTYPES=0 30 | 31 | IPHONEOS_DEPLOYMENT_TARGET = 9.0 32 | ENABLE_BITCODE = NO 33 | -------------------------------------------------------------------------------- /xcode/macos-overrides.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // macos-overrides.xcconfig 3 | // Fiber2D 4 | // 5 | // Created by Andrey Volodin on 07.01.17. 6 | // 7 | // 8 | 9 | GCC_PREPROCESSOR_DEFINITIONS = CP_USE_CGTYPES=0 10 | 11 | // Intermediate build files go here 12 | PROJECT_TEMP_DIR = $(SRCROOT)/build/$(PROJECT_NAME).build 13 | 14 | // Build-related files for the active build configuration go here 15 | CONFIGURATION_BUILD_DIR = $(SRCROOT)/build/$CONFIGURATION 16 | 17 | // The final product executables and other build products go here 18 | BUILT_PRODUCTS_DIR = $(SRCROOT)/build/$CONFIGURATION 19 | 20 | MACOSX_DEPLOYMENT_TARGET = 10.11 21 | 22 | SWIFT_VERSION = 4.0 23 | --------------------------------------------------------------------------------