82 lines
2.5 KiB
Swift
82 lines
2.5 KiB
Swift
//
|
||
// Project.swift
|
||
// GasTankAR
|
||
//
|
||
// Created by Dennis Nemec on 25.08.26.
|
||
//
|
||
|
||
import Foundation
|
||
import SwiftData
|
||
import ARKit
|
||
|
||
@Model
|
||
final class Project {
|
||
/// Identifier given by the user for the project. In DOCUframe terms
|
||
/// it is the LeadID.
|
||
var leadID: String
|
||
|
||
/// Customer name to link the project to.
|
||
var customerName: String
|
||
|
||
var creationDate: Date
|
||
|
||
/// Der für das Projekt ausgewählte Tank. Jedes Projekt hat genau einen Tank.
|
||
/// `Tank` ist `Codable`, daher persistiert SwiftData das direkt als Attribut.
|
||
var tank: Tank
|
||
|
||
/// Archivierte `ARWorldMap` (via `NSKeyedArchiver`). Wegen der Größe extern gespeichert.
|
||
@Attribute(.externalStorage) var worldMapData: Data?
|
||
|
||
/// Welt-Transform des platzierten Tanks (Position, Rotation, Skalierung) als
|
||
/// 16 Floats (spaltenweise). Zusammen mit der WorldMap wird der Tank so wiederhergestellt.
|
||
var tankTransform: [Float]?
|
||
|
||
/// Im AR-Modus aufgenommene Fotos. Werden beim Löschen des Projekts mitentfernt.
|
||
@Relationship(deleteRule: .cascade, inverse: \ProjectPhoto.project)
|
||
var photos: [ProjectPhoto] = []
|
||
|
||
init(
|
||
leadID: String,
|
||
customerName: String,
|
||
creationDate: Date,
|
||
tank: Tank = Tank(),
|
||
worldMapData: Data? = nil,
|
||
tankTransform: [Float]? = nil
|
||
) {
|
||
self.leadID = leadID
|
||
self.customerName = customerName
|
||
self.creationDate = creationDate
|
||
self.tank = tank
|
||
self.worldMapData = worldMapData
|
||
self.tankTransform = tankTransform
|
||
}
|
||
|
||
/// Human-readable title combining the lead identifier and customer name.
|
||
var title: String {
|
||
"\(leadID) – \(customerName)"
|
||
}
|
||
|
||
/// Up to two uppercased initials derived from the customer name, for use as an avatar.
|
||
var initials: String {
|
||
let letters = customerName
|
||
.split(whereSeparator: { $0 == " " || $0 == "&" })
|
||
.prefix(2)
|
||
.compactMap { $0.first }
|
||
return String(letters).uppercased()
|
||
}
|
||
|
||
/// Gespeicherte Session der getrackten Welt. (De-)serialisiert `worldMapData`.
|
||
/// Berechnete Property – wird von SwiftData nicht persistiert.
|
||
var worldMap: ARWorldMap? {
|
||
get {
|
||
guard let worldMapData else { return nil }
|
||
return try? NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, from: worldMapData)
|
||
}
|
||
set {
|
||
worldMapData = newValue.flatMap {
|
||
try? NSKeyedArchiver.archivedData(withRootObject: $0, requiringSecureCoding: true)
|
||
}
|
||
}
|
||
}
|
||
}
|