Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import SpriteKit
import GameplayKit

/// Positions the crosshair (in the center).
class CrosshairHUDPositioningComponent: GKComponent, FrameSizeDependent {
private var node: SKNode? {
entity?.component(ofType: SpriteNodeComponent.self)?.node
}

func onUpdateFrame(to frame: CGRect) {
DispatchQueue.main.async { [self] in
node?.position = CGPoint(x: frame.midX, y: frame.midY)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import SpriteKit
import GameplayKit

class DebugHUDLoadComponent: GKComponent {
class DebugHUDLoadComponent: GKComponent, FrameSizeDependent {
private var lastEnabled: Bool = false
private let padding: CGFloat = 5

private var node: SKLabelNode? {
entity?.component(ofType: SpriteNodeComponent.self)?.node as? SKLabelNode
Expand Down Expand Up @@ -52,6 +53,12 @@ class DebugHUDLoadComponent: GKComponent {
lastEnabled = isEnabled
}

func onUpdateFrame(to frame: CGRect) {
DispatchQueue.main.async { [self] in
node?.position = CGPoint(x: frame.minX + padding, y: frame.maxY - padding)
}
}

private func format(pos: BlockPos3) -> String {
"x \(pos.x), y \(pos.y), z \(pos.z)"
}
Expand Down
6 changes: 6 additions & 0 deletions MiniBlocks.swiftpm/Sources/Component/FrameSizeDependent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import SpriteKit

/// Indicates that the implementing component is dependent on the frame's size.
protocol FrameSizeDependent {
func onUpdateFrame(to frame: CGRect)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import SpriteKit
import GameplayKit

/// Renders the hotbar for a player from the world model to a SpriteKit node.
class HotbarHUDLoadComponent: GKComponent {
class HotbarHUDLoadComponent: GKComponent, FrameSizeDependent {
/// The inventory last rendered to a SpriteKit node.
private var lastInventory: Inventory?
/// The slot selection last rendered to a SpriteKit node.
Expand Down Expand Up @@ -73,4 +73,10 @@ class HotbarHUDLoadComponent: GKComponent {
private func slotLineThickness(for i: Int) -> CGFloat {
playerInfo?.selectedHotbarSlot == i ? selectedSlotLineThickness : normalSlotLineThickness
}

func onUpdateFrame(to frame: CGRect) {
DispatchQueue.main.async { [self] in
node?.position = CGPoint(x: frame.midX, y: frame.minY)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import SpriteKit
import GameplayKit

/// Positions the pause overlay.
class PauseHUDPositioningComponent: GKComponent, FrameSizeDependent {
private var node: SKNode? {
entity?.component(ofType: SpriteNodeComponent.self)?.node
}

private var backgroundNode: SKShapeNode? {
node?.childNode(withName: "pauseHUDBackground") as? SKShapeNode
}

func onUpdateFrame(to frame: CGRect) {
DispatchQueue.main.async { [self] in
node?.position = CGPoint(x: frame.midX, y: frame.midY)
// TODO: Update size
}
}
}
2 changes: 1 addition & 1 deletion MiniBlocks.swiftpm/Sources/Entity/CrosshairHUDEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import GameplayKit
func makeCrosshairHUDEntity(size: CGFloat = 20, thickness: CGFloat = 2, in frame: CGRect) -> GKEntity {
// Create node
let node = makeCrosshairHUDNode(size: size, thickness: thickness)
node.position = CGPoint(x: frame.midX, y: frame.midY)

// Create entity
let entity = GKEntity()
entity.addComponent(SpriteNodeComponent(node: node))
entity.addComponent(MouseCaptureVisibilityComponent(visibleWhenCaptured: true))
entity.addComponent(CrosshairHUDPositioningComponent())

return entity
}
2 changes: 0 additions & 2 deletions MiniBlocks.swiftpm/Sources/Entity/DebugHUDEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import GameplayKit

func makeDebugHUDEntity(in frame: CGRect, playerEntity: GKEntity, fontSize: CGFloat = 15) -> GKEntity {
// Create node
let padding: CGFloat = 5
let node = SKLabelNode()
node.fontColor = .white
node.fontName = NodeConstants.fontName
node.fontSize = fontSize
node.position = CGPoint(x: frame.minX + padding, y: frame.maxY - padding)
node.numberOfLines = 0
node.verticalAlignmentMode = .top
node.horizontalAlignmentMode = .left
Expand Down
1 change: 0 additions & 1 deletion MiniBlocks.swiftpm/Sources/Entity/HotbarHUDEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import GameplayKit
func makeHotbarHUDEntity(in frame: CGRect, playerEntity: GKEntity) -> GKEntity {
// Create node
let node = SKNode()
node.position = CGPoint(x: frame.midX, y: frame.minY)

// Create entity
let entity = GKEntity()
Expand Down
2 changes: 1 addition & 1 deletion MiniBlocks.swiftpm/Sources/Entity/PauseHUDEntity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import GameplayKit
func makePauseHUDEntity(in frame: CGRect, fontSize: CGFloat = 28) -> GKEntity {
// Create node
let node = makePauseHUDNode(size: frame.size, fontSize: fontSize)
node.position = CGPoint(x: frame.midX, y: frame.midY)

// Create entity
let entity = GKEntity()
entity.addComponent(SpriteNodeComponent(node: node))
entity.addComponent(MouseCaptureVisibilityComponent(visibleWhenCaptured: false))
entity.addComponent(PauseHUDPositioningComponent())

return entity
}
1 change: 1 addition & 0 deletions MiniBlocks.swiftpm/Sources/Node/PauseHUDNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import SpriteKit

private func makeBackgroundNode(size: CGSize) -> SKNode {
let node = SKShapeNode(rect: CGRect(center: CGPoint(x: 0, y: 0), size: size))
node.name = "pauseHUDBackground"
node.strokeColor = .clear
node.lineWidth = 0
node.fillColor = .black.withAlphaComponent(0.92)
Expand Down
43 changes: 41 additions & 2 deletions MiniBlocks.swiftpm/Sources/View/MiniBlocksViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public final class MiniBlocksViewController: ViewController, SCNSceneRendererDel
// MARK: View properties

private var sceneView: MiniBlocksSceneView!
private let sceneFrame: CGRect?
private var sceneFrame: CGRect?
private var inputSensivity: SceneFloat = 1

#if canImport(AppKit)
Expand Down Expand Up @@ -122,7 +122,6 @@ public final class MiniBlocksViewController: ViewController, SCNSceneRendererDel

// Create overlay scene
overlayScene = sceneFrame.map { SKScene(size: $0.size) } ?? SKScene()
overlayScene.scaleMode = .aspectFill
overlayScene.isUserInteractionEnabled = false

// Add light
Expand Down Expand Up @@ -267,6 +266,13 @@ public final class MiniBlocksViewController: ViewController, SCNSceneRendererDel
}
#endif

// Perform initial layout if frame size dependent
if let sceneFrame = sceneFrame {
for case let component as FrameSizeDependent in entity.components {
component.onUpdateFrame(to: sceneFrame)
}
}

// Add components to their corresponding systems
playerControlComponentSystem.addComponent(foundIn: entity)
playerPositioningComponentSystem.addComponent(foundIn: entity)
Expand Down Expand Up @@ -737,5 +743,38 @@ public final class MiniBlocksViewController: ViewController, SCNSceneRendererDel
}

#endif

// MARK: View resizing

private func onRelayout() {
let frame = view.frame

if frame.size != overlayScene.size {
sceneFrame = frame
overlayScene.size = frame.size

for entity in entities {
for case let component as FrameSizeDependent in entity.components {
component.onUpdateFrame(to: frame)
}
}
}
}

#if canImport(AppKit)

public override func viewWillLayout() {
onRelayout()
}

#endif

#if canImport(UIKit)

public override func viewWillLayoutSubviews() {
onRelayout()
}

#endif
}

18 changes: 18 additions & 0 deletions MiniBlocks/MiniBlocks.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
35D8D9EE278B3F470056ACAA /* TextureLeaves.png in Resources */ = {isa = PBXBuildFile; fileRef = 35D8D9ED278B3F470056ACAA /* TextureLeaves.png */; };
35D9E8A1278887960058F0E6 /* SunEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D9E8A0278887960058F0E6 /* SunEntity.swift */; };
35D9E8A3278888190058F0E6 /* AmbientLightEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35D9E8A2278888190058F0E6 /* AmbientLightEntity.swift */; };
35DDED6F2817703C007E9CFD /* FrameSizeDependent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35DDED6E2817703C007E9CFD /* FrameSizeDependent.swift */; };
35DDED702817703C007E9CFD /* FrameSizeDependent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35DDED6E2817703C007E9CFD /* FrameSizeDependent.swift */; };
35DDED72281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35DDED71281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift */; };
35DDED73281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35DDED71281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift */; };
35DDED7528177B50007E9CFD /* PauseHUDPositioningComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35DDED7428177B50007E9CFD /* PauseHUDPositioningComponent.swift */; };
35DDED7628177B50007E9CFD /* PauseHUDPositioningComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35DDED7428177B50007E9CFD /* PauseHUDPositioningComponent.swift */; };
35E7F3EA27867ED10067F0F7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35E7F3E927867ED10067F0F7 /* AppDelegate.swift */; };
35E7F3F027867ED20067F0F7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35E7F3EF27867ED20067F0F7 /* Assets.xcassets */; };
35E7F40C278682C60067F0F7 /* MiniBlocksScene.scn in Resources */ = {isa = PBXBuildFile; fileRef = 35E7F40A278682C60067F0F7 /* MiniBlocksScene.scn */; };
Expand Down Expand Up @@ -306,6 +312,9 @@
35D8D9ED278B3F470056ACAA /* TextureLeaves.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = TextureLeaves.png; path = ../../MiniBlocks.swiftpm/Resources/TextureLeaves.png; sourceTree = "<group>"; };
35D9E8A0278887960058F0E6 /* SunEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SunEntity.swift; path = ../../MiniBlocks.swiftpm/Sources/Entity/SunEntity.swift; sourceTree = "<group>"; };
35D9E8A2278888190058F0E6 /* AmbientLightEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AmbientLightEntity.swift; path = ../../MiniBlocks.swiftpm/Sources/Entity/AmbientLightEntity.swift; sourceTree = "<group>"; };
35DDED6E2817703C007E9CFD /* FrameSizeDependent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FrameSizeDependent.swift; path = ../../MiniBlocks.swiftpm/Sources/Component/FrameSizeDependent.swift; sourceTree = "<group>"; };
35DDED71281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrosshairHUDPositioningComponent.swift; path = ../../MiniBlocks.swiftpm/Sources/Component/CrosshairHUDPositioningComponent.swift; sourceTree = "<group>"; };
35DDED7428177B50007E9CFD /* PauseHUDPositioningComponent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PauseHUDPositioningComponent.swift; path = ../../MiniBlocks.swiftpm/Sources/Component/PauseHUDPositioningComponent.swift; sourceTree = "<group>"; };
35E7F3E627867ED10067F0F7 /* MiniBlocks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MiniBlocks.app; sourceTree = BUILT_PRODUCTS_DIR; };
35E7F3E927867ED10067F0F7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
35E7F3EF27867ED20067F0F7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -421,9 +430,12 @@
35D3491F27FF3AB1000F0CC2 /* HotbarHUDControlComponent.swift */,
35D3492827FF45EB000F0CC2 /* ControlPadHUDControlComponent.swift */,
355006CD27A0C0710021A0BE /* DebugHUDLoadComponent.swift */,
35DDED71281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift */,
35DDED7428177B50007E9CFD /* PauseHUDPositioningComponent.swift */,
3554CB0427F51F0E000EE620 /* AchievementHUDLoadComponent.swift */,
3540752127F2A6EE00887E01 /* MouseCaptureVisibilityComponent.swift */,
35D3491C27FF3A07000F0CC2 /* TouchInteractable.swift */,
35DDED6E2817703C007E9CFD /* FrameSizeDependent.swift */,
);
name = Component;
sourceTree = "<group>";
Expand Down Expand Up @@ -749,6 +761,8 @@
35391BC8278BC5D800B22954 /* ChunkConstants.swift in Sources */,
35D3492A27FF45EB000F0CC2 /* ControlPadHUDControlComponent.swift in Sources */,
357EB0CD279640B00004CA6E /* Debouncer.swift in Sources */,
35DDED7628177B50007E9CFD /* PauseHUDPositioningComponent.swift in Sources */,
35DDED702817703C007E9CFD /* FrameSizeDependent.swift in Sources */,
35F2680427F76C7D00CC458C /* HandNodeComponent.swift in Sources */,
35A5552D278C3AE0006FA70D /* Item.swift in Sources */,
35A55529278C3AE0006FA70D /* EmptyWorldGenerator.swift in Sources */,
Expand Down Expand Up @@ -803,6 +817,7 @@
35391BE3278BC5F400B22954 /* PlayerEntity.swift in Sources */,
35391BE2278BC5F400B22954 /* AmbientLightEntity.swift in Sources */,
3540751A27F2A06300887E01 /* PauseHUDEntity.swift in Sources */,
35DDED73281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift in Sources */,
3572145127957B56003C640F /* Vec3Convertible.swift in Sources */,
35391BE6278BC5F700B22954 /* MiniBlocksSceneView.swift in Sources */,
35391BAF278BC5A800B22954 /* AppDelegate.swift in Sources */,
Expand Down Expand Up @@ -844,6 +859,8 @@
35EA353E2788A57C0066DD82 /* WorldAssociationComponent.swift in Sources */,
35D3492927FF45EB000F0CC2 /* ControlPadHUDControlComponent.swift in Sources */,
357EB0CC279640B00004CA6E /* Debouncer.swift in Sources */,
35DDED7528177B50007E9CFD /* PauseHUDPositioningComponent.swift in Sources */,
35DDED6F2817703C007E9CFD /* FrameSizeDependent.swift in Sources */,
35F2680327F76C7D00CC458C /* HandNodeComponent.swift in Sources */,
35A55530278C3AE0006FA70D /* WorldGeneratorType.swift in Sources */,
35A55526278C3AE0006FA70D /* NatureWorldGenerator.swift in Sources */,
Expand Down Expand Up @@ -898,6 +915,7 @@
35A55528278C3AE0006FA70D /* EmptyWorldGenerator.swift in Sources */,
35EA352627889CBE0066DD82 /* GridIterator2.swift in Sources */,
3540751927F2A06300887E01 /* PauseHUDEntity.swift in Sources */,
35DDED72281778EC007E9CFD /* CrosshairHUDPositioningComponent.swift in Sources */,
3572145027957B56003C640F /* Vec3Convertible.swift in Sources */,
35D9E8A3278888190058F0E6 /* AmbientLightEntity.swift in Sources */,
35A0C298278753AE00FA8570 /* Throttler.swift in Sources */,
Expand Down