package main import "time" // ProjectData is the top-level structure serialized to project.json inside a .former directory. type ProjectData struct { ID string `json:"id"` Name string `json:"name"` Type string `json:"type,omitempty"` // "pcb" or "surfacewrap"; empty = legacy pcb CreatedAt time.Time `json:"createdAt"` Version int `json:"version"` Stencil *StencilData `json:"stencil,omitempty"` Enclosure *EnclosureData `json:"enclosure,omitempty"` VectorWrap *VectorWrapData `json:"vectorWrap,omitempty"` Structural *StructuralData `json:"structural,omitempty"` ScanHelper *ScanHelperData `json:"scanHelper,omitempty"` Object *ObjectData `json:"object,omitempty"` Settings ProjectSettings `json:"settings"` } // ObjectData stores the 3D object reference for Surface Wrap projects. type ObjectData struct { ModelFile string `json:"modelFile,omitempty"` ModelType string `json:"modelType,omitempty"` // "stl" or "scad" WallThickness float64 `json:"wallThickness"` } type ProjectSettings struct { ShowGrid bool `json:"showGrid"` TraditionalControls bool `json:"traditionalControls"` } type StencilData struct { GerberFile string `json:"gerberFile,omitempty"` OutlineFile string `json:"outlineFile,omitempty"` StencilHeight float64 `json:"stencilHeight"` WallHeight float64 `json:"wallHeight"` WallThickness float64 `json:"wallThickness"` DPI float64 `json:"dpi"` Exports []string `json:"exports"` } type EnclosureData struct { GerberFiles map[string]string `json:"gerberFiles"` DrillPath string `json:"drillPath,omitempty"` NPTHPath string `json:"npthPath,omitempty"` EdgeCutsFile string `json:"edgeCutsFile"` CourtyardFile string `json:"courtyardFile,omitempty"` SoldermaskFile string `json:"soldermaskFile,omitempty"` FabFile string `json:"fabFile,omitempty"` Config EnclosureConfig `json:"config"` Exports []string `json:"exports"` BoardW float64 `json:"boardW"` BoardH float64 `json:"boardH"` ProjectName string `json:"projectName,omitempty"` Cutouts []Cutout `json:"cutouts,omitempty"` SideCutouts []SideCutout `json:"sideCutouts,omitempty"` LidCutouts []LidCutout `json:"lidCutouts,omitempty"` } // MigrateCutouts returns the unified cutouts list, converting legacy fields if needed. func (ed *EnclosureData) MigrateCutouts() []Cutout { if len(ed.Cutouts) > 0 { return ed.Cutouts } var result []Cutout for _, sc := range ed.SideCutouts { result = append(result, Cutout{ ID: randomID(), Surface: "side", SideNum: sc.Side, X: sc.X, Y: sc.Y, Width: sc.Width, Height: sc.Height, CornerRadius: sc.CornerRadius, SourceLayer: sc.Layer, }) } for _, lc := range ed.LidCutouts { surface := "top" if lc.Plane == "tray" { surface = "bottom" } result = append(result, Cutout{ ID: randomID(), Surface: surface, X: lc.MinX, Y: lc.MinY, Width: lc.MaxX - lc.MinX, Height: lc.MaxY - lc.MinY, IsDado: lc.IsDado, Depth: lc.Depth, Shape: lc.Shape, }) } return result } type VectorWrapData struct { SVGFile string `json:"svgFile,omitempty"` ModelFile string `json:"modelFile,omitempty"` ModelType string `json:"modelType,omitempty"` SVGWidth float64 `json:"svgWidth"` SVGHeight float64 `json:"svgHeight"` GridCols int `json:"gridCols,omitempty"` GridRows int `json:"gridRows,omitempty"` GridPoints [][2]float64 `json:"gridPoints,omitempty"` TranslateX float64 `json:"translateX"` TranslateY float64 `json:"translateY"` Rotation float64 `json:"rotation"` ScaleX float64 `json:"scaleX"` ScaleY float64 `json:"scaleY"` Opacity float64 `json:"opacity"` ZOffset float64 `json:"zOffset"` } type StructuralData struct { SVGFile string `json:"svgFile,omitempty"` Pattern string `json:"pattern"` CellSize float64 `json:"cellSize"` WallThick float64 `json:"wallThick"` Height float64 `json:"height"` ShellThick float64 `json:"shellThick"` } type ScanHelperData struct { PageWidth float64 `json:"pageWidth"` PageHeight float64 `json:"pageHeight"` GridSpacing float64 `json:"gridSpacing"` PagesWide int `json:"pagesWide"` PagesTall int `json:"pagesTall"` DPI float64 `json:"dpi"` } // RecentEntry tracks a recently-opened project for the landing page. type RecentEntry struct { Path string `json:"path"` Name string `json:"name"` LastOpened time.Time `json:"lastOpened"` }