Generates a Godot scene from Node

This commit is contained in:
2026-08-26 09:16:19 -07:00
parent c9e1993b65
commit 6c3ef41a57
6 changed files with 291 additions and 3 deletions
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
+3 -2
View File
@@ -3,9 +3,10 @@
import PackageDescription import PackageDescription
let package = Package( let package = Package(
name: "logic", name: "Logic",
platforms: [ platforms: [
.macOS(.v14) .macOS(.v14),
.iOS(.v17)
], ],
products: [ products: [
.library( .library(
+13 -1
View File
@@ -1,2 +1,14 @@
import Foundation //
// Logic.swift
// Logic
//
// Created by Alex Loren on 8/26/26.
//
import SwiftGodot import SwiftGodot
#initSwiftExtension(cdecl: "swift_entry_point", types: [
NodeRotator.self,
PhysicsRotator.self,
World.self
])
@@ -0,0 +1,20 @@
//
// NodeRotator.swift
// Logic
//
// Created by Alex Loren on 8/26/26.
//
import SwiftGodot
@Godot
class NodeRotator: Node3D {
// MARK: - Properties
public var axis: Vector3 = .zero
public var speed: Double = 5
// MARK: - Functions
public override func _physicsProcess(delta: Double) {
rotate(axis: axis.normalized(), angle: speed * delta)
}
}
@@ -0,0 +1,20 @@
//
// PhysicsRotator.swift
// Logic
//
// Created by Alex Loren on 8/26/26.
//
import SwiftGodot
@Godot
class PhysicsRotator: AnimatableBody3D {
// MARK: - Properties
public var axis: Vector3 = .zero
public var speed: Double = 5
// MARK: - Functions
public override func _physicsProcess(delta: Double) {
rotate(axis: axis.normalized(), angle: speed * delta)
}
}
+228
View File
@@ -0,0 +1,228 @@
//
// World.swift
// Logic
//
// Created by Alex Loren on 8/26/26.
//
import SwiftGodot
@Godot
class World: Node {
// MARK: - Properties
private var lightColors: [String] = [
"#95FDDE",
"#8029F8",
"#ED4881"
]
private var randomLightColor: Color {
get {
if let color = lightColors.randomElement(), Color.htmlIsValid(color: color) {
return Color.html(rgba: color)
}
print("Failed to get random light color, returning white.")
return .white
}
}
// MARK: - Functions
override func _enterTree() {
assemble()
}
func assemble() {
let camera = createCamera(at: Vector3(x: 0, y: -1.75, z: 4.5))
camera.environment = createEnvironment()
addChild(node: camera)
addChild(node: createRotatingWalls())
addChild(node: createPhysicsBounds())
for _ in 1...200 {
let sphere = createSphereRigidBody()
addChild(node: sphere)
sphere.globalPosition = getRandomPosition()
}
for _ in 1...100 {
let box = createBoxRigidBody(size: 0.2)
addChild(node: box)
box.globalPosition = getRandomPosition()
}
for index in 0...2 {
let rotator = createNodeRotator()
let light = createLight(range: 15, color: Color.html(rgba: lightColors[index]))
rotator.addChild(node: light)
light.position = getRandomPosition(lower: 3, upper: 4)
addChild(node: rotator)
}
}
@discardableResult private func createCamera(at position: Vector3 = Vector3(x: 0, y: 0, z: 5)) -> Camera3D {
let camera = Camera3D()
camera.current = true
camera.position = position
return camera
}
@discardableResult private func createRotatingWalls() -> Node3D {
let rotator = PhysicsRotator()
rotator.axis = Vector3(x: 1, y: 1, z: 1)
rotator.speed = 0.5
// Top and bottom walls
rotator.addChild(node: createCollidableWall(at: Vector3(x: 0, y: 2.5, z: 0)))
rotator.addChild(node: createCollidableWall(at: Vector3(x: 0, y: -2.5, z: 0)))
// Front and back walls
rotator.addChild(node: createCollidableWall(at: Vector3(x: 2.5, y: 0, z: 0), rotation: Vector3(x: 0, y: 0, z: 90)))
rotator.addChild(node: createCollidableWall(at: Vector3(x: -2.5, y: 0, z: 0), rotation: Vector3(x: 0, y: 0, z: 90)))
// Left and right walls
rotator.addChild(node: createCollidableWall(at: Vector3(x: 0, y: 0, z: 2.5), rotation: Vector3(x: 0, y: 90, z: 90)))
rotator.addChild(node: createCollidableWall(at: Vector3(x: 0, y: 0, z: -2.5), rotation: Vector3(x: 0, y: 90, z: 90)))
return rotator
}
@discardableResult private func createCollidableWall(at position: Vector3, rotation: Vector3 = .zero) -> CollisionShape3D {
let shape = BoxShape3D()
shape.size = Vector3(x: 5, y: 0.5, z: 5)
let collider = CollisionShape3D()
collider.shape = shape
collider.position = position
collider.rotationDegrees = rotation
return collider
}
@discardableResult private func createSphereRigidBody(radius: Double = 0.1, randomize: Bool = true, randomScale: Double = 0.05) -> RigidBody3D {
let definedRadius = !randomize ? radius : Double.random(in: (radius - randomScale)...(radius + randomScale))
let shape = SphereShape3D()
shape.radius = definedRadius
let collider = CollisionShape3D()
collider.shape = shape
let mesh = SphereMesh()
mesh.radius = definedRadius
mesh.height = definedRadius * 2
mesh.radialSegments = 8
mesh.rings = 8
let meshInstance = MeshInstance3D()
meshInstance.mesh = mesh
meshInstance.materialOverride = createMaterial()
let material = PhysicsMaterial()
material.bounce = 0.8
let body = RigidBody3D()
body.physicsMaterialOverride = material
body.addChild(node: collider)
body.addChild(node: meshInstance)
return body
}
@discardableResult private func createBoxRigidBody(size: Float = 0.1, randomize: Bool = true, randomScale: Float = 0.05) -> RigidBody3D {
let definedSize = !randomize ? size : Float.random(in: (size - randomScale)...(size + randomScale))
let shape = BoxShape3D()
shape.size = Vector3(x: definedSize, y: definedSize, z: definedSize)
let collider = CollisionShape3D()
collider.shape = shape
let mesh = BoxMesh()
mesh.size = Vector3(x: definedSize, y: definedSize, z: definedSize)
let meshInstance = MeshInstance3D()
meshInstance.mesh = mesh
meshInstance.materialOverride = createMaterial()
let material = PhysicsMaterial()
material.bounce = 0.8
let body = RigidBody3D()
body.physicsMaterialOverride = material
body.addChild(node: collider)
body.addChild(node: meshInstance)
return body
}
@discardableResult private func createLight(range: Double = 5, color: Color = .white) -> OmniLight3D {
let light = OmniLight3D()
light.omniRange = range
light.omniShadowMode = .cube
light.shadowEnabled = true
light.lightColor = color
light.lightEnergy = 5
return light
}
@discardableResult private func createNodeRotator() -> NodeRotator {
let randomOnAxis: [Float] = [
Float(Int.random(in: -1...1)),
Float(Int.random(in: -1...1)),
Float(Int.random(in: -1...1))
]
let rotator = NodeRotator()
rotator.axis = Vector3(x: randomOnAxis[0], y: randomOnAxis[1], z: randomOnAxis[2])
rotator.speed = Double.random(in: 0.3...0.6)
return rotator
}
private func createMaterial() -> StandardMaterial3D {
let material = StandardMaterial3D()
material.diffuseMode = .lambertWrap
return material
}
@discardableResult private func createEnvironment() -> Environment {
let environment = Environment()
environment.backgroundMode = .color
environment.backgroundColor = .black
environment.glowEnabled = true
environment.glowIntensity = 0.6
environment.glowStrength = 1.75
return environment
}
private func createPhysicsBounds() -> Area3D {
let shape = SphereShape3D()
shape.radius = 10
let collider = CollisionShape3D()
collider.shape = shape
let area = Area3D()
area.addChild(node: collider)
area.bodyExited.connect { [weak self] body in
guard let self, let body = body as? RigidBody3D else {
return
}
body.getChildren().forEach { child in
if let collider = child as? CollisionShape3D {
switch collider.shape {
case is SphereShape3D:
let sphere = self.createSphereRigidBody()
addChild(node: sphere)
sphere.globalPosition = self.getRandomPosition()
break
case is BoxShape3D:
let box = self.createBoxRigidBody()
addChild(node: box)
box.globalPosition = self.getRandomPosition()
default:
break
}
}
}
body.queueFree()
}
return area
}
private func getRandomPosition(in range: Float = 2) -> Vector3 {
return .init(x: Float.random(in: -range...range), y: Float.random(in: -range...range), z: Float.random(in: -range...range))
}
private func getRandomPosition(lower: Float = 1, upper: Float = 3) -> Vector3{
return .init(x: .random(in: lower...upper), y: .random(in: lower...upper), z: .random(in: lower...upper))
}
}