Skip to content

Commit

Permalink
Widget system for ui
Browse files Browse the repository at this point in the history
  • Loading branch information
SpectralDragon committed Jun 9, 2024
1 parent 65e78a0 commit b4f319b
Show file tree
Hide file tree
Showing 57 changed files with 1,505 additions and 160 deletions.
4 changes: 2 additions & 2 deletions Sources/AdaEditor/AdaEditorApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import AdaEngine
struct AdaEditorApp: App {

var scene: some AppScene {
GameAppScene {
ManySpritesExampleScene()
WidgetGroup {
ContentWidget()
}
.windowMode(.windowed)
.windowTitle("AdaEngine")
Expand Down
4 changes: 2 additions & 2 deletions Sources/AdaEditor/Scenes/GameScene2D.swift
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ extension GameScene2D {
var attributes = TextAttributeContainer()
attributes.foregroundColor = .red
attributes.outlineColor = .black
attributes.font = Font.system(weight: .italic)
attributes.font = FontResource.system(weight: .italic)

var text = AttributedText("Hello, Ada Engine!\n", attributes: attributes)

attributes.font = Font.system(weight: .regular)
attributes.font = FontResource.system(weight: .regular)
attributes.foregroundColor = .purple
attributes.kern = -0.03

Expand Down
40 changes: 40 additions & 0 deletions Sources/AdaEditor/Scenes/UIViewTestScene.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// UIViewTestScene.swift
//
//
// Created by Vladislav Prusakov on 07.06.2024.
//

import AdaEngine

struct ContentWidget: Widget {

@WidgetContext(\.font) private var font

@State private var int = 0
@State private var double = 0.0

var body: some Widget {
HStack {
Text("Hello World")

CustomWidget()

Text("Hello World")

}

Text("Hello World")
}
}

struct CustomWidget: Widget {

@State private var string = ""

var body: some Widget {
Text("Hello World")

Text("Hello World")
}
}
2 changes: 1 addition & 1 deletion Sources/AdaEditor/UI/EditorWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import AdaEngine

class EditorWindow: Window {
class EditorWindow: UIWindow {
override func windowDidReady() {
self.title = "Ada Editor"

Expand Down
2 changes: 1 addition & 1 deletion Sources/AdaEngine/Application/AppCreate/AppScene.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public extension AppScene {
}

/// Set the window presentation mode.
func windowMode(_ mode: Window.Mode) -> some AppScene {
func windowMode(_ mode: UIWindow.Mode) -> some AppScene {
return self.modifier(WindowModeSceneModifier(windowMode: mode))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

/// Describe default scene configuration settings for the app
struct _AppSceneConfiguration {
var minimumSize: Size = Window.defaultMinimumSize
var windowMode: Window.Mode = .fullscreen
var minimumSize: Size = UIWindow.defaultMinimumSize
var windowMode: UIWindow.Mode = .fullscreen
var isSingleWindow: Bool = false
var title: String?
var useDefaultRenderPlugins: Bool = true
Expand All @@ -24,7 +24,7 @@ protocol InternalAppScene {
/// Create a window with given configuration.
/// - Throws: Any error.
/// - Returns: The configured window.
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> Window
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> UIWindow

/// Collect all modification of default scene configuration.
/// - NOTE: We use this method for ``SceneModifier`` interface.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct MinimumWindowSizeSceneModifier: SceneModifier {
/// Set the window mode.
struct WindowModeSceneModifier: SceneModifier {

let windowMode: Window.Mode
let windowMode: UIWindow.Mode

func modify(_ configuration: inout _AppSceneConfiguration) {
configuration.windowMode = self.windowMode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extension ModifiedScene: InternalAppScene {
(self.scene as? InternalAppScene)?._buildConfiguration(&configuration)
}

func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> Window {
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> UIWindow {
try await (self.scene as! InternalAppScene)._makeWindow(with: configuration)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ public struct GUIAppScene: AppScene {

public var scene: Never { fatalError() }

let window: () -> Window
let window: () -> UIWindow

/// Create a new app scene for GUI application.
/// - Parameters window: ``Window`` which will be presented on screen
public init(window: @escaping () -> Window) {
public init(window: @escaping () -> UIWindow) {
self.window = window
}

}

extension GUIAppScene: InternalAppScene {
@MainActor
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> Window {
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> UIWindow {
let window = window()

if window.frame.size == .zero {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ public struct GameAppScene: AppScene {

extension GameAppScene: InternalAppScene {
@MainActor
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> Window {
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> UIWindow {
let scene = try await self.gameScene()

let frame = Rect(origin: .zero, size: configuration.minimumSize)
let window = Window(frame: frame)
let window = UIWindow(frame: frame)

let gameSceneView = SceneView(scene: scene, frame: frame)
window.addSubview(gameSceneView)
Expand Down
37 changes: 37 additions & 0 deletions Sources/AdaEngine/Application/AppCreate/Scenes/WidgetGroup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// WidgetGroup.swift
// AdaEngine
//
// Created by Vladislav Prusakov on 08.06.2024.
//

public struct WidgetGroup<Content: Widget>: AppScene {

public var scene: Never { fatalError() }

let content: Content

public init(@WidgetBuilder content: () -> Content) {
self.content = content()
}
}

extension WidgetGroup: InternalAppScene {
@MainActor
func _makeWindow(with configuration: _AppSceneConfiguration) async throws -> UIWindow {
let frame = Rect(origin: .zero, size: configuration.minimumSize)
let window = UIWindow(frame: frame)

let gameSceneView = UIWidgetView(rootView: self.content)
window.addSubview(gameSceneView)

window.setWindowMode(configuration.windowMode)
window.minSize = configuration.minimumSize

if let title = configuration.title {
window.title = title
}

return window
}
}
2 changes: 1 addition & 1 deletion Sources/AdaEngine/Application/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ open class Application {
#endif
}

@MainActor(unsafe) public internal(set) var windowManager: WindowManager = WindowManager()
@MainActor(unsafe) public internal(set) var windowManager: UIWindowManager = UIWindowManager()

/// Contains world which can render on screen.
@RenderGraphActor public let renderWorld = RenderWorld()
Expand Down
4 changes: 2 additions & 2 deletions Sources/AdaEngine/Platforms/Apple/MetalView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import MetalKit

open class MetalView: MTKView {

let windowID: Window.ID
let windowID: UIWindow.ID

#if MACOS
var currentTrackingArea: NSTrackingArea?
#endif

public init(windowId: Window.ID, frame: CGRect) {
public init(windowId: UIWindow.ID, frame: CGRect) {
self.windowID = windowId
super.init(frame: frame, device: nil)
}
Expand Down
20 changes: 10 additions & 10 deletions Sources/AdaEngine/Platforms/Apple/macOS/MacOSWindowManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ import AppKit
import Math

// swiftlint:disable cyclomatic_complexity
final class MacOSWindowManager: WindowManager {
final class MacOSWindowManager: UIWindowManager {

private lazy var nsWindowDelegate = NSWindowDelegateObject(windowManager: self)

public nonisolated override init() { }

override func createWindow(for window: Window) {
override func createWindow(for window: UIWindow) {

let minSize = Window.defaultMinimumSize
let minSize = UIWindow.defaultMinimumSize

let frame = window.frame
let size = frame.size == .zero ? minSize : frame.size
Expand Down Expand Up @@ -57,7 +57,7 @@ final class MacOSWindowManager: WindowManager {
super.createWindow(for: window)
}

override func showWindow(_ window: Window, isFocused: Bool) {
override func showWindow(_ window: UIWindow, isFocused: Bool) {
guard let nsWindow = window.systemWindow as? NSWindow else {
fatalError("System window not exist.")
}
Expand All @@ -73,7 +73,7 @@ final class MacOSWindowManager: WindowManager {
self.setActiveWindow(window)
}

override func setWindowMode(_ window: Window, mode: Window.Mode) {
override func setWindowMode(_ window: UIWindow, mode: UIWindow.Mode) {
guard let nsWindow = window.systemWindow as? NSWindow else {
fatalError("System window not exist.")
}
Expand All @@ -86,7 +86,7 @@ final class MacOSWindowManager: WindowManager {
}
}

override func closeWindow(_ window: Window) {
override func closeWindow(_ window: UIWindow) {
guard let nsWindow = window.systemWindow as? NSWindow else {
fatalError("System window not exist.")
}
Expand All @@ -96,14 +96,14 @@ final class MacOSWindowManager: WindowManager {
nsWindow.close()
}

override func resizeWindow(_ window: Window, size: Size) {
override func resizeWindow(_ window: UIWindow, size: Size) {
let nsWindow = window.systemWindow as? NSWindow

let cgSize = CGSize(width: CGFloat(size.width), height: CGFloat(size.height))
nsWindow?.setContentSize(cgSize)
}

override func setMinimumSize(_ size: Size, for window: Window) {
override func setMinimumSize(_ size: Size, for window: UIWindow) {
guard let nsWindow = window.systemWindow as? NSWindow else {
fatalError("System window not exist.")
}
Expand All @@ -114,7 +114,7 @@ final class MacOSWindowManager: WindowManager {
nsWindow.minSize = minSize
}

override func getScreen(for window: Window) -> Screen? {
override func getScreen(for window: UIWindow) -> Screen? {
guard let nsWindow = window.systemWindow as? NSWindow, let screen = nsWindow.screen else {
return nil
}
Expand Down Expand Up @@ -277,7 +277,7 @@ final class MacOSWindowManager: WindowManager {
self.mouseMode
}

func findWindow(for nsWindow: NSWindow) -> Window? {
func findWindow(for nsWindow: NSWindow) -> UIWindow? {
return self.windows.first {
($0.systemWindow as? NSWindow) === nsWindow
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,20 @@ class MetalRenderBackend: RenderBackend {
self.commandQueue = self.context.physicalDevice.makeCommandQueue()!
}

func createWindow(_ windowId: Window.ID, for view: RenderView, size: SizeInt) throws {
func createWindow(_ windowId: UIWindow.ID, for view: RenderView, size: SizeInt) throws {
let mtlView = (view as! MetalView)
try self.context.createRenderWindow(with: windowId, view: mtlView, size: size)
}

func resizeWindow(_ windowId: Window.ID, newSize: SizeInt) throws {
func resizeWindow(_ windowId: UIWindow.ID, newSize: SizeInt) throws {
guard newSize.width > 0 && newSize.height > 0 else {
return
}

self.context.updateSizeForRenderWindow(windowId, size: newSize)
}

func destroyWindow(_ windowId: Window.ID) throws {
func destroyWindow(_ windowId: UIWindow.ID) throws {
guard self.context.windows[windowId] != nil else {
return
}
Expand Down Expand Up @@ -337,7 +337,7 @@ extension MetalRenderBackend {

extension MetalRenderBackend {

func beginDraw(for window: Window.ID, clearColor: Color) -> DrawList {
func beginDraw(for window: UIWindow.ID, clearColor: Color) -> DrawList {
guard let window = self.context.windows[window] else {
fatalError("Render Window not exists.")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extension MetalRenderBackend {

final class Context {

private(set) var windows: [Window.ID: RenderWindow] = [:]
private(set) var windows: [UIWindow.ID: RenderWindow] = [:]

let physicalDevice: MTLDevice

Expand All @@ -27,7 +27,7 @@ extension MetalRenderBackend {

// MARK: - Methods

func createRenderWindow(with id: Window.ID, view: MetalView, size: SizeInt) throws {
func createRenderWindow(with id: UIWindow.ID, view: MetalView, size: SizeInt) throws {
if self.windows[id] != nil {
throw ContextError.creationWindowAlreadyExists
}
Expand All @@ -51,7 +51,7 @@ extension MetalRenderBackend {
self.windows[id] = window
}

func updateSizeForRenderWindow(_ windowId: Window.ID, size: SizeInt) {
func updateSizeForRenderWindow(_ windowId: UIWindow.ID, size: SizeInt) {
guard let window = self.windows[windowId] else {
assertionFailure("Not found window by id \(windowId)")
return
Expand All @@ -60,7 +60,7 @@ extension MetalRenderBackend {
// window.view?.drawableSize = size.toCGSize
}

func destroyWindow(by id: Window.ID) {
func destroyWindow(by id: UIWindow.ID) {
guard self.windows[id] != nil else {
assertionFailure("Not found window by id \(id)")
return
Expand Down
8 changes: 4 additions & 4 deletions Sources/AdaEngine/Rendering/Backends/RenderBackend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ protocol RenderBackend: AnyObject {
/// Register a new render window for render backend.
/// Window in this case is entity that managed a drawables (aka swapchain).
/// - Throws: Throw error if something went wrong.
func createWindow(_ windowId: Window.ID, for view: RenderView, size: SizeInt) throws
func createWindow(_ windowId: UIWindow.ID, for view: RenderView, size: SizeInt) throws

/// Resize registred render window.
/// - Throws: Throw error if window is not registred.
func resizeWindow(_ windowId: Window.ID, newSize: SizeInt) throws
func resizeWindow(_ windowId: UIWindow.ID, newSize: SizeInt) throws

/// Destroy render window from render backend.
/// - Throws: Throw error if window is not registred.
func destroyWindow(_ windowId: Window.ID) throws
func destroyWindow(_ windowId: UIWindow.ID) throws

/// Begin rendering a frame for all windows.
func beginFrame() throws
Expand Down Expand Up @@ -86,7 +86,7 @@ protocol RenderBackend: AnyObject {

/// Begin draw for window.
/// - Returns: ``DrawList`` which contains information about drawing.
func beginDraw(for window: Window.ID, clearColor: Color) -> DrawList
func beginDraw(for window: UIWindow.ID, clearColor: Color) -> DrawList

/// Begin draw to framebuffer.
/// - Returns: ``DrawList`` which contains information about drawing.
Expand Down
Loading

0 comments on commit b4f319b

Please sign in to comment.