From 00488c7e8d7e93406c3bcf2264d7c7239c3a5516 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 6 Apr 2026 16:39:48 +0300 Subject: feat: Gemini panel script drives comic panels in narrative order, v0.25.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously story text was split mechanically into 5 sections and each panel was guessed from raw prose — causing repeated compositions and incoherent plots. Now GenerateFull requests a 20-entry panel visual script (P1-A…P5-D) from Gemini in the same API call as the story and bible. Each panel gets an explicit 1-2 sentence description of WHO/WHAT/WHERE/expression, written in chronological story order. buildStoryPagePrompt now uses these descriptions to drive the image model directly ("Draw each panel EXACTLY as described") instead of "scene N from the excerpt". Falls back to excerpt-driven prompts when the script is absent or incomplete. Co-Authored-By: Claude Sonnet 4.6 --- internal/story/runner.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'internal/story/runner.go') diff --git a/internal/story/runner.go b/internal/story/runner.go index e5e9aa5..c9571a6 100644 --- a/internal/story/runner.go +++ b/internal/story/runner.go @@ -173,7 +173,7 @@ func (r *Runner) Run(batchFile string) error { fmt.Fprintf(os.Stderr, "Warning: could not write theme file: %v\n", err) } - r.drawComicPages(result.StoryText, result.Bible, slug, entries) + r.drawComicPages(result.StoryText, result.Bible, slug, entries, result.PanelScript) // Narration is opt-in (--narrate flag). Skip entirely when not requested // so runs complete faster and don't consume TTS quota unnecessarily. @@ -184,12 +184,16 @@ func (r *Runner) Run(batchFile string) error { return r.handleNarration(result.StoryText, slug, comicsDir) } -// drawComicPages generates the 5 comic images and assembles them into a PDF. -// entries carries the vocabulary words so panels can visually feature and label them. +// drawComicPages generates all 12 comic pages and assembles them into a PDF. +// panelScript carries the explicit per-panel visual descriptions from Gemini so +// each panel illustrates the correct story beat in narrative order. // Errors are non-fatal — story.txt is always accessible regardless of image failures. -func (r *Runner) drawComicPages(storyText, bible, titleSlug string, entries []batch.WordEntry) { +func (r *Runner) drawComicPages(storyText, bible, titleSlug string, entries []batch.WordEntry, panelScript [][]string) { fmt.Printf("Generating %d comic pages...\n", storyPageCount+galleryPageCount+2) // cover + story + gallery + back - paths, err := r.artist.DrawComicPages(storyText, bible, titleSlug, entries) + if len(panelScript) > 0 { + fmt.Println(" Panel script ready — panels will follow narrative order.") + } + paths, err := r.artist.DrawComicPages(storyText, bible, titleSlug, entries, panelScript) if err != nil { fmt.Fprintf(os.Stderr, "Warning: comic page generation failed: %v\n", err) } -- cgit v1.2.3