90 lines
2.8 KiB
Swift
90 lines
2.8 KiB
Swift
// ContentView.swift
|
|
// Root layout — header, tool sidebar, multi-viewport, properties, status bar.
|
|
|
|
import SwiftUI
|
|
|
|
struct ContentView: View {
|
|
@State private var context = MetalContext()
|
|
@State private var currentMode: EditMode = .object
|
|
@State private var activeTool: ViewportTool = .cursor
|
|
@State private var showProperties = true
|
|
@State private var showOutliner = true
|
|
|
|
var body: some View {
|
|
GeometryReader { geo in
|
|
VStack(spacing: 0) {
|
|
// ── Top bar ──
|
|
HeaderBar(
|
|
currentMode: $currentMode,
|
|
layout: $context.viewportLayout,
|
|
context: context
|
|
)
|
|
|
|
// ── Main area ──
|
|
HStack(spacing: 0) {
|
|
// Left tool strip
|
|
ToolSidebar(activeTool: $activeTool)
|
|
|
|
// Center: viewport(s)
|
|
MultiViewportView(
|
|
renderers: context.renderers,
|
|
layout: context.viewportLayout
|
|
)
|
|
|
|
// Right side: outliner + properties
|
|
if showProperties || showOutliner {
|
|
rightPanel(height: geo.size.height)
|
|
}
|
|
}
|
|
|
|
// ── Bottom status ──
|
|
StatusBar(mode: currentMode, sceneGraph: context.sceneGraph)
|
|
}
|
|
}
|
|
.ignoresSafeArea(.keyboard)
|
|
.preferredColorScheme(.dark)
|
|
.toolbar {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
HStack(spacing: 12) {
|
|
Button {
|
|
withAnimation(.easeInOut(duration: 0.2)) {
|
|
showOutliner.toggle()
|
|
}
|
|
} label: {
|
|
Image(systemName: "list.bullet")
|
|
}
|
|
|
|
Button {
|
|
withAnimation(.easeInOut(duration: 0.2)) {
|
|
showProperties.toggle()
|
|
}
|
|
} label: {
|
|
Image(systemName: "sidebar.trailing")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private func rightPanel(height: CGFloat) -> some View {
|
|
VStack(spacing: 0) {
|
|
if showOutliner {
|
|
OutlinerPanel(sceneGraph: context.sceneGraph)
|
|
.frame(height: height * 0.3)
|
|
}
|
|
|
|
if showOutliner && showProperties {
|
|
Divider()
|
|
}
|
|
|
|
if showProperties {
|
|
PropertiesPanel(
|
|
isExpanded: $showProperties,
|
|
sceneGraph: context.sceneGraph
|
|
)
|
|
}
|
|
}
|
|
.frame(width: 260)
|
|
}
|
|
}
|