Skip to content

Commit a0dee1b

Browse files
committed
Fix window issues
1 parent be35cb9 commit a0dee1b

File tree

9 files changed

+96
-32
lines changed

9 files changed

+96
-32
lines changed

Sources/GateEngine/Game.swift

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ import GameMath
4242
}
4343
self.addPlatformSystems()
4444
self.delegate.didFinishLaunching(game: self, options: [])
45-
#if GATEENGINE_SUPPORTS_MULTIWINDOW
45+
#if !GATEENGINE_PLATFORM_SINGLETHREADED
4646
self.gameLoop()
4747
#endif
4848
}
@@ -55,25 +55,18 @@ import GameMath
5555
self.insertSystem(AudioSystem.self)
5656
self.insertSystem(CacheSystem.self)
5757
}
58-
59-
#if GATEENGINE_SUPPORTS_MULTIWINDOW
60-
internal var windowsThatRequestedDraw: [(window: Window, deltaTime: Float)] = []
58+
59+
#if !GATEENGINE_PLATFORM_SINGLETHREADED
6160
private var previousTime: Double = 0
6261
internal func gameLoop() {
6362
Task(priority: .high) {@MainActor in
6463
let now: Double = Game.shared.internalPlatform.systemTime()
65-
let deltaTime: Double = now - previousTime
64+
let deltaTime: Double = now - self.previousTime
6665
self.previousTime = now
6766
if self.ecs.shouldRenderAfterUpdate(withTimePassed: Float(deltaTime)) {
68-
self.renderingIsPermitted = true
69-
for pair: (window: Window, deltaTime: Float) in windowsThatRequestedDraw {
70-
self.ecs.updateRendering(withTimePassed: pair.deltaTime, window: pair.window)
71-
pair.window.didDrawSomething = true
72-
}
73-
self.renderingIsPermitted = false
67+
self.windowManager.drawWindows()
7468
}
75-
windowsThatRequestedDraw.removeAll(keepingCapacity: true)
76-
gameLoop()
69+
self.gameLoop()
7770
}
7871
}
7972
#endif

Sources/GateEngine/System/Platforms/Apple/AppKit/AppKitPlatform.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ import System
8484
}
8585
return Double(time.tv_sec) + (Double(time.tv_nsec) / 1e+9)
8686
}
87+
88+
var supportsMultipleWindows: Bool {
89+
return true
90+
}
8791
}
8892

8993
extension AppKitPlatform {

Sources/GateEngine/System/Platforms/Apple/UIKit/UIKitPlatform.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ class UIKitPlatform: InternalPlatform {
7575
}
7676
return Double(time.tv_sec) + (Double(time.tv_nsec) / 1e+9)
7777
}
78+
79+
var supportsMultipleWindows: Bool {
80+
return false
81+
}
7882
}
7983

8084
internal final class UIKItAppDelegate: NSObject, UIApplicationDelegate {

Sources/GateEngine/System/Platforms/Platform.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public protocol Platform {
1818

1919
func systemTime() -> Double
2020
func main()
21+
22+
var supportsMultipleWindows: Bool {get}
2123
}
2224

2325
@_transparent

Sources/GateEngine/System/Platforms/WASI/WASI/WASIWindow.swift

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ class WASIWindow: WindowBacking {
3232

3333
var title: String? {
3434
get {
35-
fatalError()
35+
return nil
3636
}
3737
set {
38-
fatalError()
38+
// can't
3939
}
4040
}
4141

@@ -62,9 +62,9 @@ class WASIWindow: WindowBacking {
6262
self.window.vSyncCalled()
6363
_ = globalThis.window.requestAnimationFrame(callback: vSync(_:))
6464
}
65+
6566
@MainActor func show() {
6667
self.state = .shown
67-
print("Show")
6868
vSync(0)
6969
addListeners()
7070
}
@@ -123,31 +123,55 @@ class WASIWindow: WindowBacking {
123123
}
124124
canvas.addEventListener(type: "mouseenter") { event in
125125
let event = DOM.MouseEvent(unsafelyWrapping: event.jsObject)
126-
let position: Position2 = Position2(x: Float(event.pageX), y: Float(event.pageY))
126+
let position: Position2 = {
127+
var position = Position2(x: Float(event.pageX), y: Float(event.pageY))
128+
if let pixelRatio = globalThis.document.defaultView?.devicePixelRatio {
129+
position *= Float(pixelRatio)
130+
}
131+
return position
132+
}()
127133
Task {@MainActor in
128134
self.window.delegate?.mouseChange(event: .entered, position: position, window: self.window)
129135
}
130136
event.preventDefault()
131137
}
132138
canvas.addEventListener(type: "mousemove") { event in
133139
let event = DOM.MouseEvent(unsafelyWrapping: event.jsObject)
134-
let position: Position2 = Position2(x: Float(event.pageX), y: Float(event.pageY))
140+
let position: Position2 = {
141+
var position = Position2(x: Float(event.pageX), y: Float(event.pageY))
142+
if let pixelRatio = globalThis.document.defaultView?.devicePixelRatio {
143+
position *= Float(pixelRatio)
144+
}
145+
return position
146+
}()
135147
Task {@MainActor in
136148
self.window.delegate?.mouseChange(event: .moved, position: position, window: self.window)
137149
}
138150
event.preventDefault()
139151
}
140152
canvas.addEventListener(type: "mouseleave") { event in
141153
let event = DOM.MouseEvent(unsafelyWrapping: event.jsObject)
142-
let position: Position2 = Position2(x: Float(event.pageX), y: Float(event.pageY))
154+
let position: Position2 = {
155+
var position = Position2(x: Float(event.pageX), y: Float(event.pageY))
156+
if let pixelRatio = globalThis.document.defaultView?.devicePixelRatio {
157+
position *= Float(pixelRatio)
158+
}
159+
return position
160+
}()
143161
Task {@MainActor in
144162
self.window.delegate?.mouseChange(event: .exited, position: position, window: self.window)
145163
}
146164
event.preventDefault()
147165
}
148166
canvas.addEventListener(type: "mousedown") { event in
149167
let event = DOM.MouseEvent(unsafelyWrapping: event.jsObject)
150-
let position: Position2 = Position2(x: Float(event.pageX), y: Float(event.pageY))
168+
let position: Position2 = {
169+
var position = Position2(x: Float(event.pageX), y: Float(event.pageY))
170+
if let pixelRatio = globalThis.document.defaultView?.devicePixelRatio {
171+
position *= Float(pixelRatio)
172+
}
173+
return position
174+
}()
151175
let button: MouseButton = self.mouseButton(fromEvent: event)
152176
Task {@MainActor in
153177
self.window.delegate?.mouseClick(event: .buttonDown, button: button, count: nil, position: position, window: self.window)
@@ -156,7 +180,13 @@ class WASIWindow: WindowBacking {
156180
}
157181
canvas.addEventListener(type: "mouseup") { event in
158182
let event = DOM.MouseEvent(unsafelyWrapping: event.jsObject)
159-
let position: Position2 = Position2(x: Float(event.pageX), y: Float(event.pageY))
183+
let position: Position2 = {
184+
var position = Position2(x: Float(event.pageX), y: Float(event.pageY))
185+
if let pixelRatio = globalThis.document.defaultView?.devicePixelRatio {
186+
position *= Float(pixelRatio)
187+
}
188+
return position
189+
}()
160190
let button: MouseButton = self.mouseButton(fromEvent: event)
161191
Task {@MainActor in
162192
self.window.delegate?.mouseClick(event: .buttonUp, button: button, count: nil ,position: position, window: self.window)

Sources/GateEngine/System/Platforms/WASI/WASIPlatform.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ class WASIPlatform: InternalPlatform {
126126
#endif
127127
}
128128

129+
var supportsMultipleWindows: Bool {
130+
return false
131+
}
132+
129133
func setupDocument() {
130134
globalThis.onbeforeunload = { event -> String? in
131135
Game.shared.willTerminate()
@@ -196,4 +200,8 @@ extension DOM.Navigator {
196200
}
197201
}
198202

203+
#if os(WASI) && !GATEENGINE_PLATFORM_SINGLETHREADED
204+
#error("WASI must be single threaded.")
205+
#endif
206+
199207
#endif

Sources/GateEngine/System/Platforms/Win32/Win32Platform.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ import Foundation
9797
func systemTime() -> Double {
9898
return Date.timeIntervalSinceReferenceDate
9999
}
100+
101+
var supportsMultipleWindows: Bool {
102+
return true
103+
}
100104
}
101105

102106
extension Win32Platform {

Sources/GateEngine/System/Window.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ internal extension Window {
157157
#elseif os(WASI)
158158
return WASIWindow(identifier: identifier, style: style, window: self)
159159
#elseif os(Android)
160-
#error("Not implemented")
160+
#error("Not implemented")
161161
#else
162162
#error("Not implemented")
163163
#endif

Sources/GateEngine/System/WindowManager.swift

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,15 @@ import GameMath
2323
return windows.first(where: {$0.identifier.caseInsensitiveCompare(identifier) == .orderedSame})
2424
}
2525

26-
public func createWindow(identifier: String, style: WindowStyle) throws {
26+
@discardableResult
27+
public func createWindow(identifier: String, style: WindowStyle) throws -> Window {
2728
guard game.isHeadless == false else {throw "[GateEngine] Cannot create a window when running headless."}
2829
precondition(game.renderingIsPermitted, "A window can only be created from a RenderingSystem.")
29-
#if !GATEENGINE_SUPPORTS_MULTIWINDOW
30+
#if GATEENGINE_PLATFORM_SINGLETHREADED
31+
// Single threaded platforms can only ever have 1 window
3032
guard windows.isEmpty else {throw "This platform doesn't support multiple windows."}
33+
#else
34+
guard game.internalPlatform.supportsMultipleWindows || windows.isEmpty else {throw "This platform doesn't support multiple windows."}
3135
#endif
3236
guard identifierIsUnused(identifier) else {throw "Window with identifier \"\(identifier)\" already exists."}
3337
let window: Window = Window(identifier: identifier, style: style)
@@ -37,6 +41,7 @@ import GameMath
3741
}
3842
window.delegate = self
3943
window.show()
44+
return window
4045
}
4146

4247
internal func removeWindow(_ identifier: String) {
@@ -59,20 +64,34 @@ import GameMath
5964
}
6065
return true
6166
}
67+
68+
internal var windowsThatRequestedDraw: [(window: Window, deltaTime: Float)] = []
69+
70+
@inline(__always)
71+
func drawWindows() {
72+
game.renderingIsPermitted = true
73+
for pair: (window: Window, deltaTime: Float) in windowsThatRequestedDraw {
74+
game.ecs.updateRendering(withTimePassed: pair.deltaTime, window: pair.window)
75+
pair.window.didDrawSomething = true
76+
}
77+
game.renderingIsPermitted = false
78+
self.windowsThatRequestedDraw.removeAll(keepingCapacity: true)
79+
}
6280
}
6381

6482
extension WindowManager: WindowDelegate {
6583
func window(_ window: Window, wantsUpdateForTimePassed deltaTime: Float) {
66-
#if GATEENGINE_SUPPORTS_MULTIWINDOW
67-
window.didDrawSomething = false
68-
self.game.renderingIsPermitted = true
69-
game.windowsThatRequestedDraw.append((window, deltaTime))
70-
self.game.renderingIsPermitted = false
71-
#else
7284
window.didDrawSomething = false
73-
if self.game.ecs.shouldRenderAfterUpdate(withTimePassed: deltaTime) {
85+
if let index = windowsThatRequestedDraw.firstIndex(where: {$0.window == window}) {
86+
// If the window dropped a frame, add the next deltaTime
87+
self.windowsThatRequestedDraw[index].deltaTime += deltaTime
88+
}else{
89+
self.windowsThatRequestedDraw.append((window, deltaTime))
90+
}
91+
#if GATEENGINE_PLATFORM_SINGLETHREADED || os(WASI)
92+
if game.ecs.shouldRenderAfterUpdate(withTimePassed: Float(deltaTime)) {
7493
window.didDrawSomething = true
75-
self.game.ecs.updateRendering(withTimePassed: deltaTime, window: window)
94+
self.drawWindows()
7695
}
7796
#endif
7897
}

0 commit comments

Comments
 (0)