Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions Sources/GameWidget/Display.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//
// File.swift
//
//
// Created by rrbox on 2022/07/24.
//

import SpriteKit

/// SingleWidgetDisplay の place により生成され, 二つの WidgetList(一方は Display)を保持します.
public struct RecursiveDisplay<T: WidgetList, U: WidgetList>: Widget, WidgetList {

var first: T
var second: U

public func place<V: WidgetList>(@GroupBuilder block: () -> V) -> RecursiveDisplay<Self, V> {
.init(first: self, second: block())
}

public func widgetNodes() -> [SKNode] {
self.first.widgetNodes() + self.second.widgetNodes()
}

public func node() -> SKNode {
let result = SKNode()

for node in self.first.widgetNodes() + self.second.widgetNodes() {
result.addChild(node)
}

return result
}

}

/// 一つの widget から RecursiveDisplay を生成するためのラッパー.
/// Display の place により生成され, 一つの WidgetList を保持します.
public struct SingleWidgetDisplay<T: WidgetList>: Widget, WidgetList {

var widgetList: T

public func place<U: WidgetList>(@GroupBuilder block: () -> U) -> RecursiveDisplay<Self, U> {
RecursiveDisplay(first: self, second: block())
}

public func widgetNodes() -> [SKNode] {
self.widgetList.widgetNodes()
}

public func node() -> SKNode {
let result = SKNode()
for node in self.widgetList.widgetNodes() {
result.addChild(node)
}
return result
}

}

/// Widget のレイアウトの起点. place メソッドチェーンで無制限に Widget を配置できます.
/// - note: 一回の place メソッドで配置可能な widget の数は 10 個までです.
public struct Display: Widget {

public init() {}

public func place<T: WidgetList>(@GroupBuilder block: () -> T) -> SingleWidgetDisplay<T> {
SingleWidgetDisplay(widgetList: block())
}

public func node() -> SKNode {
fatalError("display has no widget")
}

}

6 changes: 3 additions & 3 deletions Sources/GameWidget/Entity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import GameplayKit

final private class UserInterfaceBaseNode: GKSKNodeComponent {}

final public class UserInterfaceDisplay: GKSKNodeComponent {
final public class UserInterfaceDisplay<T: Widget>: GKSKNodeComponent {

init(_ display: Display) {
init(_ display: T) {
super.init(node: display.node())
}

Expand All @@ -29,7 +29,7 @@ final public class UserInterfaceDisplay: GKSKNodeComponent {

}

public func makeUserInterfaceEntity(camera: SKNode, display: Display) -> GKEntity {
public func makeUserInterfaceEntity<T: Widget>(camera: SKNode, display: T) -> GKEntity {
let result = GKEntity()
result.addComponent(UserInterfaceBaseNode(node: camera))
result.addComponent(UserInterfaceDisplay(display))
Expand Down
196 changes: 196 additions & 0 deletions Sources/GameWidget/Group.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
//
// File.swift
//
//
// Created by rrbox on 2022/07/24.
//

import CoreGraphics
import SpriteKit

@resultBuilder public struct GroupBuilder {

public static func buildBlock<C0: Widget>(_ c0: C0) -> some WidgetList {
Single(widget: c0)
}

public static func buildBlock<C0: Widget, C1: Widget>(_ c0: C0, _ c1: C1) -> some WidgetList{
Single(widget: c0)
.append(c1)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget>(_ c0: C0, _ c1: C1, _ c2: C2) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget, C3: Widget>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
.append(c3)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget, C3: Widget, C4: Widget>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
.append(c3)
.append(c4)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget, C3: Widget, C4: Widget, C5: Widget>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
.append(c3)
.append(c4)
.append(c5)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget, C3: Widget, C4: Widget, C5: Widget, C6: Widget>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
.append(c3)
.append(c4)
.append(c5)
.append(c6)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget, C3: Widget, C4: Widget, C5: Widget, C6: Widget, C7: Widget>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
.append(c3)
.append(c4)
.append(c5)
.append(c6)
.append(c7)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget, C3: Widget, C4: Widget, C5: Widget, C6: Widget, C7: Widget, C8: Widget>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
.append(c3)
.append(c4)
.append(c5)
.append(c6)
.append(c7)
.append(c8)
}

public static func buildBlock<C0: Widget, C1: Widget, C2: Widget, C3: Widget, C4: Widget, C5: Widget, C6: Widget, C7: Widget, C8: Widget, C9: Widget>(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3, _ c4: C4, _ c5: C5, _ c6: C6, _ c7: C7, _ c8: C8, _ c9: C9) -> some WidgetList {
Single(widget: c0)
.append(c1)
.append(c2)
.append(c3)
.append(c4)
.append(c5)
.append(c6)
.append(c7)
.append(c8)
.append(c9)
}

}

public protocol WidgetList {
func widgetNodes() -> [SKNode]
}

/// 再帰可能. widget のペアです. オーバーヘッドはありません.
public struct RecursiveGroup<T: WidgetList, U: Widget>: WidgetList {

var first: T
var second: U

func append<V: Widget>(_ newWidget: V) -> RecursiveGroup<Self, V> {
.init(first: self, second: newWidget)
}

public func widgetNodes() -> [SKNode] {
var result = self.first.widgetNodes()
self.second.addTo(parent: &result)
return result
}

}

// 一つの widget から RecursiveGroup を生成するためのラッパー.
struct Single<T: Widget>: WidgetList {

var widget: T

func append<U: Widget>(_ newWidget: U) -> RecursiveGroup<Self, U> {
.init(first: self, second: newWidget)
}

func widgetNodes() -> [SKNode] {
var result = [SKNode]()
self.widget.addTo(parent: &result)
return result
}

}

/// 10 個以下の widget を一つの widget としてまとめます. 座標, スケール, 回転を内包するコンテンツと共に調整することができます.
/// - note: 数値をもつため, 40バイトのメモリを必要とします.
public struct Node<Content: WidgetList>: NodeWidget, WidgetList {

public var position: CGPoint = .zero
public var zRotation: CGFloat = .zero
public var xScale: CGFloat = 1
public var yScale: CGFloat = 1

var content: Content

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

public func widgetNodes() -> [SKNode] {
var result = [SKNode]()
self.addTo(parent: &result)
return result
}

public func node() -> SKNode {
let result = SKNode()
for i in self.content.widgetNodes() {
result.addChild(i)
}
return result
}

}

/// widget 数を増やす際に使用します. 10 個以下の widget を内包することができます.
/// - note: モディファイアはありませんが, メモリのオーバーヘッドがありません.
public struct Extension<Content: WidgetList>: Widget, WidgetList {

var content: Content

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

public func widgetNodes() -> [SKNode] {
self.content.widgetNodes()
}

public func node() -> SKNode {
fatalError("Extension は node を生成しません.")
}

public func addTo(parent list: inout [SKNode]) {
for node in self.content.widgetNodes() {
list.append(node)
}
}

}


Loading