From e8b5398d8f9a2d4fa9ed339fec774badc270979f Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Wed, 26 Aug 2026 21:37:56 +0100 Subject: All views seem to work ok --- ShedCalc/BOMController.swift | 153 ++++++++++++++++++++++++++++++++++++++++ ShedCalc/BOMView.swift | 48 ++++++------- ShedCalc/ParamModel.swift | 40 +++++++++-- ShedCalc/ParamView.swift | 101 ++++++++++++++++++++++++-- ShedCalc/RenderController.swift | 106 +++++++++++++++++++++++----- ShedCalc/RenderModel.swift | 4 +- ShedCalc/RenderView.swift | 39 +++++++--- 7 files changed, 423 insertions(+), 68 deletions(-) (limited to 'ShedCalc') diff --git a/ShedCalc/BOMController.swift b/ShedCalc/BOMController.swift index fa05eeb..be70a65 100644 --- a/ShedCalc/BOMController.swift +++ b/ShedCalc/BOMController.swift @@ -4,4 +4,157 @@ // // Created by Jacky Jack on 01/08/2026. // +import SwiftUI +import Combine +private func roundUpPieces(_ value: Float) -> Int { + Int(value.rounded(.up)) +} + +private func roundUpPieces(_ value: Double) -> Int { + Int(value.rounded(.up)) +} + +struct MaterialItem: Identifiable { + let materialName: String + let pricePerMeter: Double + let totalMeters: Double + let totalPrice: Double + let metersPerPiece: Double + let totalPieces: Double + + let id = UUID() +} +class BOMController { + + func calcBOM(from paramModel: ParamModel) -> [MaterialItem] { + var items: [MaterialItem] = [] + items.append(calcOSB(from: paramModel)) + items.append(calcWallTimber2x4(from: paramModel)) + items.append(calcFloorTimber2x4(from: paramModel)) + items.append(calcRoofTimber2x4(from: paramModel)) + items.append(calcRoofFelt(from: paramModel)) + items.append(calcWeatherWrap(from: paramModel)) + items.append(calcCladding(from: paramModel)) + return items + } + + private func calcOSB(from paramModel: ParamModel) -> MaterialItem { + let totalOSBarea = paramModel.floorArea() + let OSBPrice = totalOSBarea*paramModel.OSBSheetPrice + let OSBPricePerMeter = paramModel.OSBSheetPrice / (1.2*2.4) + let totalPieces = roundUpPieces(totalOSBarea / (1.2*2.4)) + return MaterialItem( + materialName: "OSB", + pricePerMeter: Double(OSBPricePerMeter), + totalMeters: Double(totalOSBarea), + totalPrice: Double(totalPieces)*Double(paramModel.OSBSheetPrice), + metersPerPiece:Double(paramModel.OSBSheetPrice), + totalPieces: Double(totalPieces)) + } + + private func calcWallTimber2x4(from paramModel: ParamModel) -> MaterialItem { + let totalLength = paramModel.totalWallBeamLength() + let timberBeamPrice = paramModel.timberBeamPrice + let totalPrice = totalLength*timberBeamPrice + let pieceSize = paramModel.timberLengthSize + let totalPieces = roundUpPieces(totalLength/pieceSize) + return MaterialItem( + materialName: "2x4", + pricePerMeter: Double(timberBeamPrice), + totalMeters: Double(totalLength), + totalPrice: Double(totalPrice), + metersPerPiece:Double(pieceSize), + totalPieces: Double(totalPieces) + ) + } + private func calcFloorTimber2x4(from paramModel: ParamModel) -> MaterialItem { + let joistLength = paramModel.totalJoistBeamLength() * 2 + let spacersLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace + let timberBeamPrice = paramModel.timberBeamPrice + let totalLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace + let totalPrice = totalLength*timberBeamPrice + let pieceSize = Double(paramModel.timberLengthSize) + let totalPieces = roundUpPieces(totalLength/pieceSize) + return MaterialItem( + materialName: "Floor 2x4", + pricePerMeter: Double(timberBeamPrice), + totalMeters: Double(totalLength), + totalPrice: Double(totalPrice), + metersPerPiece:Double(pieceSize), + totalPieces: Double(totalPieces) + ) + } + + private func calcRoofTimber2x4(from paramModel: ParamModel) -> MaterialItem { + let joistLength = paramModel.totalJoistBeamLength() * 2 + let spacersLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace + let timberBeamPrice = paramModel.timberBeamPrice + let totalLength = Double(paramModel.lengthBeamNum())*paramModel.beamSpace + let totalPrice = totalLength*timberBeamPrice + let pieceSize = Double(paramModel.timberLengthSize) + let totalPieces = roundUpPieces(totalLength/pieceSize) + return MaterialItem( + materialName: "Roof 2x4", + pricePerMeter: Double(timberBeamPrice), + totalMeters: Double(totalLength), + totalPrice: Double(totalPrice), + metersPerPiece:Double(pieceSize), + totalPieces: Double(totalPieces) + ) + } + + private func calcRoofFelt(from paramModel: ParamModel) -> MaterialItem { + let roofArea = paramModel.roofArea() + let feltRollArea = Double(paramModel.feltWidth)*Double(paramModel.feltLength) + var feltPricePerMeter:Double = 0.0 + if paramModel.feltPrice > 0.0 { + feltPricePerMeter = Double(paramModel.feltPrice) / feltRollArea + } + let totalPieces = roundUpPieces(Double(roofArea)/Double(feltRollArea)) + + let totalPrice = Double(totalPieces) * paramModel.feltPrice + + return MaterialItem( + materialName: "Roof Felt", + pricePerMeter: Double(feltPricePerMeter), + totalMeters: Double(roofArea), + totalPrice: Double(totalPrice), + metersPerPiece:Double(feltRollArea), + totalPieces: Double(totalPieces) + ) + } + + private func calcWeatherWrap(from paramModel: ParamModel) -> MaterialItem { + + return MaterialItem( + materialName: "Weather Wrap", + pricePerMeter: Double(0.1), + totalMeters: Double(0.1), + totalPrice: Double(0.1), + metersPerPiece:Double(0.1), + totalPieces: Double(0.1) + ) + } + + private func calcCladding(from paramModel: ParamModel) -> MaterialItem { + let wallArea = Double(paramModel.length*paramModel.height)*2 + Double(paramModel.width*paramModel.height)*2 + let singleCladArea = paramModel.claddingLength * (Double(paramModel.claddingWidth) - paramModel.claddingOverlap) + let claddingPieces = wallArea/singleCladArea + let totalPieces = roundUpPieces(claddingPieces) + let totalPrice = Double(totalPieces) * paramModel.claddingPrice + return MaterialItem( + materialName: "Cladding", + pricePerMeter: Double(paramModel.claddingPrice), + totalMeters: Double(claddingPieces*paramModel.claddingLength), + totalPrice: Double(totalPrice), + metersPerPiece:Double(paramModel.claddingLength), + totalPieces: Double(totalPieces) + ) + } + + private func calcBeam(from paramModel: ParamModel) -> MaterialItem { + return MaterialItem(materialName: "2x4", pricePerMeter: 1.0, totalMeters: 10, totalPrice: 100, metersPerPiece: 1.2, totalPieces: 11.2) + } + +} diff --git a/ShedCalc/BOMView.swift b/ShedCalc/BOMView.swift index 1bb6523..2cde6f3 100644 --- a/ShedCalc/BOMView.swift +++ b/ShedCalc/BOMView.swift @@ -8,29 +8,25 @@ import SwiftUI import Combine -struct Materials: Identifiable { - let materialName: String - let pricePerMeter: Double - let totalMeters: Double - let totalPrice: Double - let metersPerPiece: Double - let totalPieces: Double - - let id = UUID() -} - - - struct BOMView: View { @Environment(ParamModel.self) private var paramModel + private let bomController = BOMController() - @State private var materials = [ - Materials(materialName: "2x4", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), - Materials(materialName: "OSB", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), - Materials(materialName: "Roof Felt", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), - Materials(materialName: "Nails", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), - Materials(materialName: "Cladding", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23) - ] + private var materials: [MaterialItem] { + bomController.calcBOM(from: paramModel) + } + + private var totalPrice: Double { + materials.reduce(0) { $0 + $1.totalPrice } + } + + /*@State private var materials = [ + MaterialItem(materialName: "2x4", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), + MaterialItem(materialName: "OSB", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), + MaterialItem(materialName: "Roof Felt", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), + MaterialItem(materialName: "Nails", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23), + MaterialItem(materialName: "Cladding", pricePerMeter: 1.2, totalMeters: 10, totalPrice: 12, metersPerPiece: 4.8, totalPieces: 23) + ]*/ var body: some View { VStack { @@ -39,14 +35,11 @@ struct BOMView: View { VStack { Table(materials) { TableColumn("Material", value: \.materialName) - TableColumn("Price per m") { material in - Text(material.pricePerMeter, format: .number.precision(.fractionLength(2))) - } TableColumn("Total m") { material in Text(material.totalMeters, format: .number.precision(.fractionLength(2))) } - TableColumn("Total price") { material in - Text(material.totalPrice, format: .number.precision(.fractionLength(2))) + TableColumn("Price per m") { material in + Text(material.pricePerMeter, format: .number.precision(.fractionLength(2))) } TableColumn("m per Piece") { material in Text(material.metersPerPiece, format: .number.precision(.fractionLength(2))) @@ -54,10 +47,13 @@ struct BOMView: View { TableColumn("Pieces") { material in Text(material.totalPieces, format: .number) } + TableColumn("Total price") { material in + Text(material.totalPrice, format: .number.precision(.fractionLength(2))) + } } } HStack { - Text("Total price: 0.00") + Text("Total price: \(totalPrice, format: .number.precision(.fractionLength(2)))") } } } diff --git a/ShedCalc/ParamModel.swift b/ShedCalc/ParamModel.swift index 4935bcd..f3cbbd7 100644 --- a/ShedCalc/ParamModel.swift +++ b/ShedCalc/ParamModel.swift @@ -10,20 +10,30 @@ import Observation @Observable class ParamModel { - var width: Float = 1.0 - var height: Float = 1.0 - var length: Float = 1.0 - var beamSpace: Float = 0.6 + var width: Double = 3.0 + var height: Double = 1.0 + var length: Double = 1.0 + var beamSpace: Double = 0.6 + var OSBSheetPrice: Double = 0.0 + var timberBeamPrice: Double = 0.0 + var timberLengthSize: Double = 2.4 + var feltPrice: Double = 0.0 + var feltWidth: Double = 1.0 + var feltLength: Double = 10 + var claddingPrice: Double = 0.1 + var claddingLength: Double = 0.1 + var claddingWidth: Double = 0.1 + var claddingOverlap: Double = 0.1 - func floorArea() -> Float { + func floorArea() -> Double { return width*length } - func roofArea() -> Float { + func roofArea() -> Double { return width*length } - func dimensions() -> SIMD3 { + func dimensions() -> SIMD3 { return [width,length,height] } @@ -34,4 +44,20 @@ class ParamModel { func lengthBeamNum() -> Int { return Int(length/beamSpace) + 1 } + + func setBeamSpace(_ bs: Double) { + self.beamSpace = bs + } + + func totalWallBeams() -> Int { + return 2 * (widthBeamNum() + lengthBeamNum()) + } + + func totalWallBeamLength() -> Double { + return Double(totalWallBeams()) * self.height + } + + func totalJoistBeamLength() -> Double { + return Double(widthBeamNum())*beamSpace + } } diff --git a/ShedCalc/ParamView.swift b/ShedCalc/ParamView.swift index 3e27978..1f02856 100644 --- a/ShedCalc/ParamView.swift +++ b/ShedCalc/ParamView.swift @@ -16,19 +16,51 @@ struct ParamView: View { @Bindable var paramModel = paramModel VStack { HStack { - Text("All in meters") + Text("Set shed dimensions") } HStack { Text("Width") - TextField("Width", value: $paramModel.width, format: .number) + TextField("Width", value: Binding( + get: { paramModel.width }, + set: { newValue in + if !newValue.isNaN && !newValue.isInfinite && newValue > 0.5 { + paramModel.width = newValue + } + } + ), format: .number.precision(.fractionLength(2))) + } + HStack { + Text("Length") + TextField("Length", value: Binding( + get: { paramModel.length }, + set: { newValue in + if !newValue.isNaN && !newValue.isInfinite && newValue > 0.5 { + paramModel.length = newValue + } + } + ), format: .number.precision(.fractionLength(2))) } HStack { Text("Height") - TextField("Height", value: $paramModel.height, format: .number) + TextField("Height", value: Binding( + get: { paramModel.height }, + set: { newValue in + if !newValue.isNaN && !newValue.isInfinite && newValue > 0.5 { + paramModel.height = newValue + } + } + ), format: .number.precision(.fractionLength(2))) } HStack { - Text("Length") - TextField("Length", value: $paramModel.length, format: .number) + Text("Spacing") + TextField("Spacing", value: Binding( + get: { paramModel.beamSpace }, + set: { newValue in + if !newValue.isNaN && !newValue.isInfinite && newValue > 0.15 { + paramModel.beamSpace = newValue + } + } + ), format: .number.precision(.fractionLength(2))) } HStack { Text("Total floor area: \(paramModel.floorArea(), specifier: "%.2f") m^2") @@ -36,6 +68,65 @@ struct ParamView: View { HStack { Text("Total roof area: \(paramModel.roofArea(), specifier: "%.2f") m^2") } + HStack { + Text("Total wall beams: \(paramModel.totalWallBeams()) ") + } + HStack { + Text("Set Timber Prices") + } + HStack { + Text("OSB per sheet price") + TextField("per sheet", value: Binding( + get: { paramModel.OSBSheetPrice }, + set: { newValue in + if !newValue.isNaN && !newValue.isInfinite && newValue > 0.15 { + paramModel.beamSpace = newValue + } + } + ), format: .number) + } + HStack { + Text("Beam price per meter") + TextField("per meter", value: Binding( + get: { paramModel.timberBeamPrice }, + set: { newValue in + if !newValue.isNaN && !newValue.isInfinite && newValue > 0.0 { + paramModel.timberBeamPrice = newValue + } + } + ), format: .number) + + Text("Piece size") + TextField("per meter", value: Binding( + get: { paramModel.timberLengthSize }, + set: { newValue in + if !newValue.isNaN && !newValue.isInfinite && newValue > 0.0 { + paramModel.timberLengthSize = newValue + } + } + ), format: .number) + } + HStack { + Text("Felt price") + TextField("per meter", value: $paramModel.feltPrice, format: .number) + Text("Felt width") + TextField("per meter", value: $paramModel.feltWidth, format: .number) + Text("Felt length") + TextField("per meter", value: $paramModel.feltLength, format: .number) + } + HStack { + Text("Cladding dimensions and price") + } + HStack { + Text("Cladding price per meter") + TextField("", value: $paramModel.claddingPrice, format: .number) + Text("Length") + TextField("", value: $paramModel.claddingLength, format: .number) + Text("Width") + TextField("", value: $paramModel.claddingWidth, format: .number) + Text("Overlap") + TextField("", value: $paramModel.claddingOverlap, format: .number) + } } } } diff --git a/ShedCalc/RenderController.swift b/ShedCalc/RenderController.swift index 1a57cb0..8ceef21 100644 --- a/ShedCalc/RenderController.swift +++ b/ShedCalc/RenderController.swift @@ -8,23 +8,25 @@ import SwiftUI import RealityKit -let BEAM_2x4_WIDTH: Float = 0.02 -let BEAM_2x4_LENGTH: Float = 0.04 +let BEAM_2x4_WIDTH: Double = 0.02 +let BEAM_2x4_LENGTH: Double = 0.04 struct BeamData { let id: String - let position: SIMD3 - let height: Float - let rotation: SIMD3 + let position: SIMD3 + let height: Double + let rotation: SIMD3 } class RenderController { - func createScene(dimensions: SIMD3, rotation: SIMD2) -> Entity { + var beamMaxId = 0 + + func createScene(dimensions: SIMD3, rotation: SIMD2) -> Entity { let scene = Entity() scene.name = "scene" - let box = createBox(dimensions: [1,1,1]) - scene.addChild(box) + //let box = createBox(dimensions: [1,1,1]) + //scene.addChild(box) let beam0 = createBeam2x4(position: [1,1,0], height: 2.4, rotate: [90,0,0], id: "beam0") scene.addChild(beam0) @@ -69,12 +71,12 @@ class RenderController { func handleDragGesture( _ value: DragGesture.Value, lastDrag: CGSize, - currentRotation: SIMD2 - ) -> (rotation: SIMD2, drag: CGSize) { - let dx = Float(value.translation.width - lastDrag.width) * 0.01 - let dy = Float(value.translation.height - lastDrag.height) * 0.01 + currentRotation: SIMD2 + ) -> (rotation: SIMD2, drag: CGSize) { + let dx = Double(value.translation.width - lastDrag.width) * 0.01 + let dy = Double(value.translation.height - lastDrag.height) * 0.01 - let newRotation = SIMD2( + let newRotation = SIMD2( currentRotation.x + dy, currentRotation.y + dx ) @@ -94,9 +96,9 @@ class RenderController { return box } - private func createBeam2x4(position: SIMD3, height: Float, rotate: SIMD3, id: String) -> ModelEntity { + private func createBeam2x4(position: SIMD3, height: Double, rotate: SIMD3, id: String) -> ModelEntity { let box = ModelEntity( - mesh: .generateBox(size: SIMD3(BEAM_2x4_WIDTH,BEAM_2x4_LENGTH,height), cornerRadius: 0.02), + mesh: .generateBox(size: SIMD3(Float(BEAM_2x4_WIDTH),Float(BEAM_2x4_LENGTH),Float(height)), cornerRadius: 0.02), materials: [SimpleMaterial(color: .yellow, isMetallic: false)] ) //box.look(at: position, from: lookFrom, relativeTo: nil) @@ -113,24 +115,90 @@ class RenderController { return box } - func generateShedWall(position: SIMD3, height: Float, widthNum: Int, lengthNum: Int, spaceBeem: Float) -> [BeamData] { + func generateShedWall(position: SIMD3, height: Double, widthNum: Int, lengthNum: Int, spaceBeam: Double) -> [BeamData] { var beams: [BeamData] = [] var id: Int = 0 //Wall 0 for i in 0...widthNum { - let x0 = Float(i)*spaceBeem - beams.append(BeamData(id: "beam\(id)", position: [x0,position.y, position.z], height: height, rotation: [90,0,0])) + let x0 = Double(i)*spaceBeam + beams.append(BeamData(id: "beam-\(id)", position: [position.x+x0,position.y, position.z], height: height, rotation: [90,0,0])) id += 1 } //Wall 1 + for i in 0...widthNum { + let x0 = Double(i)*spaceBeam + beams.append(BeamData(id: "beam-\(id)", position: [position.x+x0,position.y, position.z + Double(lengthNum)*spaceBeam], height: height, rotation: [90,0,0])) + //print("\(id)") + id += 1 + } //Wall 2 + for i in 0...lengthNum { + let z0 = Double(i)*spaceBeam + beams.append(BeamData(id: "beam-\(id)", position: [position.x,position.y, position.z + z0], height: height, rotation: [90,90,0])) + //print("\(id)") + id += 1 + } //Wall 3 + for i in 0...lengthNum { + let z0 = Double(i)*spaceBeam + beams.append(BeamData(id: "beam-\(id)", position: [position.x+Double(widthNum)*spaceBeam,position.y, position.z + z0], height: height, rotation: [90,90,0])) + //print("\(id)") + id += 1 + } + + self.beamMaxId = id + return beams + } + + func generateShedFloor(position: SIMD3, height: Double, width: Double, widthNum: Int, spaceBeam: Double) -> [BeamData] { + var beams: [BeamData] = [] + var id = self.beamMaxId+1 + + //all space + for i in 0...widthNum { + let x0 = Double(i)*spaceBeam + let length = width + beams.append(BeamData(id: "beam-\(id)", position:[position.x+x0,position.y-height/2, position.z+length/2], height: length, rotation: [0,0,0])) + id += 1 + } + + //2 beams for length + let length = Double(widthNum)*spaceBeam + beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2, position.y-height/2, position.z], height: length, rotation: [0,90,0])) + id += 1 + beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2,position.y-height/2, position.z+width], height: length, rotation: [0,90,0])) + id += 1 + + self.beamMaxId = id + return beams + } + + func generateShedRoof(position: SIMD3, height: Double, width: Double, widthNum: Int, spaceBeam: Double) -> [BeamData] { + var beams: [BeamData] = [] + var id = self.beamMaxId+1 + + //all space + for i in 0...widthNum { + let x0 = Double(i)*spaceBeam + let length = width + beams.append(BeamData(id: "beam-\(id)", position:[position.x+x0,position.y+height/2, position.z+length/2], height: length, rotation: [0,0,0])) + id += 1 + } + + //2 beams for length + let length = Double(widthNum)*spaceBeam + beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2, position.y+height/2, position.z], height: length, rotation: [0,90,0])) + id += 1 + beams.append(BeamData(id: "beam-\(id)", position:[position.x+length/2,position.y+height/2, position.z+width], height: length, rotation: [0,90,0])) + id += 1 + + self.beamMaxId = id return beams } func createBeams(_ beams: [BeamData]) -> [ModelEntity] { return beams.map { beam in - createBeam2x4(position: beam.position, height: beam.height, rotate: beam.rotation, id: beam.id) + createBeam2x4(position: SIMD3(beam.position), height: beam.height, rotate: SIMD3(beam.rotation), id: beam.id) } } diff --git a/ShedCalc/RenderModel.swift b/ShedCalc/RenderModel.swift index 86c5a1d..7a74d6e 100644 --- a/ShedCalc/RenderModel.swift +++ b/ShedCalc/RenderModel.swift @@ -9,8 +9,8 @@ import Combine class RenderModel: ObservableObject { // Scene rotation - @Published var rotationX: Float = 0.4 - @Published var rotationY: Float = 0.6 + @Published var rotationX: Double = 0.4 + @Published var rotationY: Double = 0.6 func reset() { rotationX = 0.4 diff --git a/ShedCalc/RenderView.swift b/ShedCalc/RenderView.swift index a143e99..b71b741 100644 --- a/ShedCalc/RenderView.swift +++ b/ShedCalc/RenderView.swift @@ -31,23 +31,44 @@ struct RenderView: View { //content.addChild(beam) //draw all beams - let beamData = renderController.generateShedWall(position: [0,0,0], height: paramModel.height, widthNum: paramModel.widthBeamNum(), lengthNum: paramModel.lengthBeamNum(), spaceBeem: paramModel.beamSpace) - //content.add(beams) - let beams = renderController.createBeams(beamData) - beams.forEach { scene.addChild($0) } + let beamData = renderController.generateShedWall(position: [0,0,0], height: paramModel.height, widthNum: paramModel.widthBeamNum(), lengthNum: paramModel.lengthBeamNum(), spaceBeam: paramModel.beamSpace) + let wallBeams = renderController.createBeams(beamData) + wallBeams.forEach { scene.addChild($0) } + + //let floorBeamData = renderController.generateShedFloor(position: [0,0,0], width: Float(1.0), widthNum: paramModel.widthBeamNum(), spaceBeam: paramModel.beamSpace) + //let floorBeams = renderController.createBeams(floorBeamData) + //floorBeams.forEach { scene.addChild($0) } } update: { content in // Update box geometry directly in the scene - if let scene = content.entities.first(where: { $0.name == "scene" }), - let box = scene.findEntity(named: "box") as? ModelEntity { - box.model?.mesh = .generateBox(size: paramModel.dimensions(), cornerRadius: 0.02) + //if let scene = content.entities.first(where: { $0.name == "scene" }), + //let box = scene.findEntity(named: "box") as? ModelEntity { + //box.model?.mesh = .generateBox(size: paramModel.dimensions(), cornerRadius: 0.02) + //} + if let scene = content.entities.first(where: { $0.name == "scene"}) { + let oldBeams = scene.children.filter { $0.name.hasPrefix("beam-") } + oldBeams.forEach { $0.removeFromParent() } + + let beamData = renderController.generateShedWall(position: [0,0,0], height: paramModel.height, widthNum: paramModel.widthBeamNum(), lengthNum: paramModel.lengthBeamNum(), spaceBeam: paramModel.beamSpace) + let beams = renderController.createBeams(beamData) + beams.forEach { scene.addChild($0) } + + let floorBeamData = renderController.generateShedFloor(position: [0,0,0], height: paramModel.height, width: Double(paramModel.lengthBeamNum())*paramModel.beamSpace, widthNum: paramModel.widthBeamNum(), spaceBeam: paramModel.beamSpace) + let floorBeams = renderController.createBeams(floorBeamData) + floorBeams.forEach { scene.addChild($0) } + + let roofBeamData = renderController.generateShedRoof(position: [0,0,0], height: paramModel.height, width: Double(paramModel.lengthBeamNum())*paramModel.beamSpace, widthNum: paramModel.widthBeamNum(), spaceBeam: paramModel.beamSpace) + let roofBeams = renderController.createBeams(roofBeamData) + roofBeams.forEach { scene.addChild($0) } } + // Update scene rotation directly if let scene = content.entities.first(where: { $0.name == "scene" }) { - let xRot = simd_quatf(angle: viewModel.rotationX, axis: [1, 0, 0]) - let yRot = simd_quatf(angle: viewModel.rotationY, axis: [0, 1, 0]) + let xRot = simd_quatf(angle: Float(viewModel.rotationX), axis: [1, 0, 0]) + let yRot = simd_quatf(angle: Float(viewModel.rotationY), axis: [0, 1, 0]) scene.transform.rotation = yRot * xRot } + //update amount of beams }.gesture( DragGesture() .onChanged { value in -- cgit v1.2.3