diff --git a/Diffusion-macOS/PromptView.swift b/Diffusion-macOS/PromptView.swift index 21df81d..a8fdd49 100644 --- a/Diffusion-macOS/PromptView.swift +++ b/Diffusion-macOS/PromptView.swift @@ -24,11 +24,6 @@ struct PromptView: View { static let modelNames = models.map { $0.modelVersion } @State private var model = Settings.shared.currentModel.modelVersion - @State private var positivePrompt = "Labrador in the style of Vermeer" - @State private var negativePrompt = "" - @State private var steps = 25.0 - @State private var numImages = 1.0 - @State private var seed = 386.0 @State private var disclosedPrompt = true // TODO: refactor download with similar code in Loading.swift (iOS) @@ -94,11 +89,11 @@ struct PromptView: View { DisclosureGroup(isExpanded: $disclosedPrompt) { Group { - TextField("Positive prompt", text: $positivePrompt, + TextField("Positive prompt", text: $generation.positivePrompt, axis: .vertical).lineLimit(5) .textFieldStyle(.squareBorder) .listRowInsets(EdgeInsets(top: 0, leading: -20, bottom: 0, trailing: 20)) - TextField("Negative prompt", text: $negativePrompt, + TextField("Negative prompt", text: $generation.negativePrompt, axis: .vertical).lineLimit(5) .textFieldStyle(.squareBorder) }.padding(.leading, 10) @@ -109,10 +104,10 @@ struct PromptView: View { Divider() DisclosureGroup { - CompactSlider(value: $steps, in: 0...150, step: 5) { + CompactSlider(value: $generation.steps, in: 0...150, step: 5) { Text("Steps") Spacer() - Text("\(Int(steps))") + Text("\(Int(generation.steps))") }.padding(.leading, 10) } label: { Label("Step count", systemImage: "square.3.layers.3d.down.left").foregroundColor(.secondary) @@ -120,20 +115,20 @@ struct PromptView: View { Divider() DisclosureGroup() { - CompactSlider(value: $numImages, in: 0...10, step: 1) { + CompactSlider(value: $generation.numImages, in: 0...10, step: 1) { Text("Number of Images") Spacer() - Text("\(Int(numImages))") + Text("\(Int(generation.numImages))") }.padding(.leading, 10) } label: { Label("Number of images", systemImage: "photo.stack").foregroundColor(.secondary) } Divider() DisclosureGroup() { - CompactSlider(value: $seed, in: 0...1000, step: 1) { + CompactSlider(value: $generation.seed, in: 0...1000, step: 1) { Text("Random seed") Spacer() - Text("\(Int(seed))") + Text("\(Int(generation.seed))") }.padding(.leading, 10) } label: { Label("Random Seed", systemImage: "leaf").foregroundColor(.secondary) diff --git a/Diffusion-macOS/StatusView.swift b/Diffusion-macOS/StatusView.swift index cc4c90e..57ae3d4 100644 --- a/Diffusion-macOS/StatusView.swift +++ b/Diffusion-macOS/StatusView.swift @@ -17,9 +17,8 @@ struct StatusView: View { generation.state = .running(nil) let interval: TimeInterval? let image: CGImage? - let prompt = "Portrait of cat in a tuxedo, oil on canvas" - (image, interval) = await generation.generate(prompt: prompt) ?? (nil, nil) - generation.state = .complete(prompt, image, interval) + (image, interval) = await generation.generate() ?? (nil, nil) + generation.state = .complete(generation.positivePrompt, image, interval) } } @@ -75,7 +74,6 @@ struct StatusView: View { } .buttonStyle(.borderedProminent) - // Generation state AnyView(generationStatusView()) } case .failed: diff --git a/Diffusion/State.swift b/Diffusion/State.swift index d90e5a9..488e6df 100644 --- a/Diffusion/State.swift +++ b/Diffusion/State.swift @@ -34,12 +34,21 @@ class GenerationContext: ObservableObject { } } @Published var state: GenerationState = .startup + + @Published var positivePrompt = "Labrador in the style of Vermeer" + @Published var negativePrompt = "" + + // FIXME: Double to support the slider component + @Published var steps = 25.0 + @Published var numImages = 1.0 + @Published var seed = 0.0 private var progressSubscriber: Cancellable? - func generate(prompt: String, steps: Int = 25, seed: UInt32? = nil) async -> (CGImage, TimeInterval)? { + func generate() async -> (CGImage, TimeInterval)? { guard let pipeline = pipeline else { return nil } - return try? pipeline.generate(prompt: prompt, scheduler: scheduler, numInferenceSteps: steps, seed: seed) + let seed = self.seed > 0 ? UInt32(self.seed) : nil + return try? pipeline.generate(prompt: positivePrompt, scheduler: scheduler, numInferenceSteps: Int(steps), seed: seed) } } diff --git a/Diffusion/Views/TextToImage.swift b/Diffusion/Views/TextToImage.swift index d0962d8..e05fdc5 100644 --- a/Diffusion/Views/TextToImage.swift +++ b/Diffusion/Views/TextToImage.swift @@ -10,9 +10,6 @@ import SwiftUI import Combine import StableDiffusion -// TODO: bind to UI controls -let steps = 25 -let seed: UInt32? = nil /// Presents "Share" + "Save" buttons on Mac; just "Share" on iOS/iPadOS. /// This is because I didn't find a way for "Share" to show a Save option when running on macOS. @@ -96,23 +93,21 @@ struct ImageWithPlaceholder: View { struct TextToImage: View { @EnvironmentObject var generation: GenerationContext - @State private var prompt = "Labrador in the style of Vermeer" - func submit() { if case .running = generation.state { return } Task { generation.state = .running(nil) let interval: TimeInterval? let image: CGImage? - (image, interval) = await generation.generate(prompt: prompt, steps: steps, seed: seed) ?? (nil, nil) - generation.state = .complete(prompt, image, interval) + (image, interval) = await generation.generate() ?? (nil, nil) + generation.state = .complete(generation.positivePrompt, image, interval) } } var body: some View { VStack { HStack { - TextField("Prompt", text: $prompt) + TextField("Prompt", text: $generation.positivePrompt) .textFieldStyle(.roundedBorder) .onSubmit { submit()