127 lines
3.9 KiB
Swift
127 lines
3.9 KiB
Swift
// HeaderBar.swift
|
|
// Top bar with mode selector, Add menu, layout picker, and viewport shading.
|
|
|
|
import SwiftUI
|
|
|
|
struct HeaderBar: View {
|
|
@Binding var currentMode: EditMode
|
|
@Binding var layout: ViewportLayout
|
|
let context: MetalContext
|
|
|
|
var body: some View {
|
|
HStack(spacing: 12) {
|
|
// App icon
|
|
Image(systemName: "cube.fill")
|
|
.font(.title3)
|
|
.foregroundStyle(.orange)
|
|
|
|
Divider().frame(height: 20)
|
|
|
|
// Mode picker
|
|
Menu {
|
|
ForEach(EditMode.allCases) { mode in
|
|
Button {
|
|
currentMode = mode
|
|
} label: {
|
|
Label(mode.rawValue, systemImage: mode.icon)
|
|
}
|
|
}
|
|
} label: {
|
|
Label(currentMode.rawValue, systemImage: currentMode.icon)
|
|
.font(.subheadline.weight(.medium))
|
|
.padding(.horizontal, 10)
|
|
.padding(.vertical, 6)
|
|
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 6))
|
|
}
|
|
|
|
Divider().frame(height: 20)
|
|
|
|
// Add mesh menu
|
|
Menu {
|
|
ForEach(PrimitiveType.allCases) { prim in
|
|
Button {
|
|
context.addPrimitive(prim)
|
|
} label: {
|
|
Label(prim.rawValue, systemImage: prim.icon)
|
|
}
|
|
}
|
|
} label: {
|
|
Label("Add", systemImage: "plus.circle")
|
|
.font(.subheadline.weight(.medium))
|
|
.padding(.horizontal, 10)
|
|
.padding(.vertical, 6)
|
|
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 6))
|
|
}
|
|
|
|
// Delete
|
|
Button {
|
|
context.deleteSelected()
|
|
} label: {
|
|
Image(systemName: "trash")
|
|
.font(.subheadline)
|
|
}
|
|
.tint(.secondary)
|
|
|
|
Spacer()
|
|
|
|
// Layout picker
|
|
Menu {
|
|
ForEach(ViewportLayout.allCases) { vl in
|
|
Button {
|
|
withAnimation(.easeInOut(duration: 0.2)) {
|
|
layout = vl
|
|
}
|
|
} label: {
|
|
Label(vl.rawValue, systemImage: vl.icon)
|
|
}
|
|
}
|
|
} label: {
|
|
Image(systemName: layout.icon)
|
|
.font(.subheadline)
|
|
.padding(6)
|
|
.background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 6))
|
|
}
|
|
|
|
// Viewport shading
|
|
HStack(spacing: 4) {
|
|
shadingButton(icon: "square.grid.3x3", label: "Wireframe")
|
|
shadingButton(icon: "cube.fill", label: "Solid")
|
|
shadingButton(icon: "circle.lefthalf.filled", label: "Material")
|
|
shadingButton(icon: "sun.max.fill", label: "Rendered")
|
|
}
|
|
}
|
|
.padding(.horizontal, 16)
|
|
.padding(.vertical, 8)
|
|
.background(.ultraThinMaterial)
|
|
}
|
|
|
|
private func shadingButton(icon: String, label: String) -> some View {
|
|
Button {} label: {
|
|
Image(systemName: icon)
|
|
.font(.caption)
|
|
.frame(width: 28, height: 28)
|
|
}
|
|
.tint(.secondary)
|
|
.accessibilityLabel(label)
|
|
}
|
|
}
|
|
|
|
// MARK: - Edit Mode
|
|
|
|
enum EditMode: String, CaseIterable, Identifiable {
|
|
case object = "Object Mode"
|
|
case edit = "Edit Mode"
|
|
case sculpt = "Sculpt Mode"
|
|
case texture = "Texture Paint"
|
|
|
|
var id: String { rawValue }
|
|
|
|
var icon: String {
|
|
switch self {
|
|
case .object: "arrow.up.left.and.arrow.down.right"
|
|
case .edit: "pencil.and.outline"
|
|
case .sculpt: "paintbrush.pointed.fill"
|
|
case .texture: "paintbrush.fill"
|
|
}
|
|
}
|
|
}
|