diff --git a/odin/gui_diagnostics.txt b/odin/gui_diagnostics.txt new file mode 100644 index 0000000..b98c245 --- /dev/null +++ b/odin/gui_diagnostics.txt @@ -0,0 +1 @@ +screen=Story workflow=Story_Input next=generate script local dirty=no autosave=yes(20s) content=pages:0,panels:0,layouts:0,chars:0 paths=P:yes,E:yes project=./gui_project.comic.json export=./gui_export.pdf log=0,newest uptime=38.2s \ No newline at end of file diff --git a/odin/gui_project.comic.json b/odin/gui_project.comic.json index 794f190..1b5bf82 100644 --- a/odin/gui_project.comic.json +++ b/odin/gui_project.comic.json @@ -14,26 +14,510 @@ "target_audience": "general", "art_style": "manga", "script": { - "title": "", - "synopsis": "", + "title": "Midnight Rush", + "synopsis": "Generated comic synopsis", "characters": [ ], "pages": [ + { + "page_number": 1, + "layout_type": 0, + "panels": [ + { + "panel_id": "panel_001_001", + "panel_number": 1, + "shot_type": 2, + "description": "Wide shot of New York City skyline at night, neon lights reflecting on wet streets. Two cars, a red Ferrari and a black Lamborghini, are side by side at a traffic light on a multi-lane avenue.", + "characters_present": [ + ], + "dialogue": [ + + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_001_002", + "panel_number": 2, + "shot_type": 2, + "description": "Close-up on the Ferrari driver, a young man in a leather jacket with a determined expression. His hand grips the gear shift.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "This is it.", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_001_003", + "panel_number": 3, + "shot_type": 2, + "description": "Close-up on the Lamborghini driver, a woman with sunglasses and a smirk. She revs the engine.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "Ready to lose, pretty boy?", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_001_004", + "panel_number": 4, + "shot_type": 2, + "description": "Traffic light turns green. Both cars accelerate, tires screeching, smoke billowing. Speed lines emphasize motion.", + "characters_present": [ + + ], + "dialogue": [ + + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_001_005", + "panel_number": 5, + "shot_type": 2, + "description": "Medium shot of the cars weaving through traffic. The Ferrari barely misses a taxi, sparks flying from the curb.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "Whoa!", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_001_006", + "panel_number": 6, + "shot_type": 2, + "description": "The Lamborghini cuts in front of a bus, horn blaring. The driver laughs.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "Ha! Too slow!", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + } + ] + }, + { + "page_number": 2, + "layout_type": 0, + "panels": [ + { + "panel_id": "panel_002_001", + "panel_number": 1, + "shot_type": 2, + "description": "Both cars enter a sharp curve. The Ferrari drifts close to a parked car, side mirror clipping it off. Glass shatters.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "Sorry!", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_002_002", + "panel_number": 2, + "shot_type": 2, + "description": "The Lamborghini takes the inside line, gaining a car length. The Ferrari driver grits his teeth.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "See ya!", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_002_003", + "panel_number": 3, + "shot_type": 2, + "description": "Straightaway ahead. The Ferrari spots a shortcut through an alley. He swerves into it.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "Not yet!", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_002_004", + "panel_number": 4, + "shot_type": 2, + "description": "The alley is narrow, trash cans flying as the Ferrari speeds through. A cat jumps out of the way.", + "characters_present": [ + + ], + "dialogue": [ + + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_002_005", + "panel_number": 5, + "shot_type": 2, + "description": "The Ferrari exits the alley just ahead of the Lamborghini. Both cars race toward the finish line (a bridge entrance).", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "What?!", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + }, + { + "panel_id": "panel_002_006", + "panel_number": 6, + "shot_type": 2, + "description": "The Ferrari crosses the bridge first, winning. The drivers slow down, windows rolled down. The woman nods in respect.", + "characters_present": [ + + ], + "dialogue": [ + { + "speaker_id": "", + "text": "Nice move.", + "bubble_type": 0, + "emotion": 4 + }, + { + "speaker_id": "", + "text": "You're not bad yourself.", + "bubble_type": 0, + "emotion": 4 + } + ], + "caption": "", + "sound_effects": [ + + ], + "transition_from_previous": 0 + } + ] + } ] }, "characters": [ ], "panel_images": { - + "panel_001_003": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_003_panel_001_003.png", + "width": 1024, + "height": 1024, + "seed": 3, + "prompt": "local panel 3" + }, + "panel_002_001": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_007_panel_002_001.png", + "width": 1024, + "height": 1024, + "seed": 7, + "prompt": "local panel 7" + }, + "panel_002_006": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_012_panel_002_006.png", + "width": 1024, + "height": 1024, + "seed": 12, + "prompt": "local panel 12" + }, + "panel_001_004": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_004_panel_001_004.png", + "width": 1024, + "height": 1024, + "seed": 4, + "prompt": "local panel 4" + }, + "panel_002_005": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_011_panel_002_005.png", + "width": 1024, + "height": 1024, + "seed": 11, + "prompt": "local panel 11" + }, + "panel_001_005": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_005_panel_001_005.png", + "width": 1024, + "height": 1024, + "seed": 5, + "prompt": "local panel 5" + }, + "panel_002_004": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_010_panel_002_004.png", + "width": 1024, + "height": 1024, + "seed": 10, + "prompt": "local panel 10" + }, + "panel_001_006": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_006_panel_001_006.png", + "width": 1024, + "height": 1024, + "seed": 6, + "prompt": "local panel 6" + }, + "panel_001_001": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_001_panel_001_001.png", + "width": 1024, + "height": 1024, + "seed": 1, + "prompt": "local panel 1" + }, + "panel_002_003": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_009_panel_002_003.png", + "width": 1024, + "height": 1024, + "seed": 9, + "prompt": "local panel 9" + }, + "panel_001_002": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_002_panel_001_002.png", + "width": 1024, + "height": 1024, + "seed": 2, + "prompt": "local panel 2" + }, + "panel_002_002": { + "url": "file:///tmp/comic-gui-local-panels-0387429411/panel_008_panel_002_002.png", + "width": 1024, + "height": 1024, + "seed": 8, + "prompt": "local panel 8" + } }, "panel_errors": { }, "page_layouts": [ - + { + "page_number": 1, + "pattern_id": "grid-2x2", + "panels": [ + { + "panel_id": "panel_001_001", + "panel_number": 1, + "layout_cell": { + "x": 0.02000000, + "y": 0.02000000, + "w": 0.47000000, + "h": 0.47000000 + } + }, + { + "panel_id": "panel_001_002", + "panel_number": 2, + "layout_cell": { + "x": 0.50999999, + "y": 0.02000000, + "w": 0.47000000, + "h": 0.47000000 + } + }, + { + "panel_id": "panel_001_003", + "panel_number": 3, + "layout_cell": { + "x": 0.02000000, + "y": 0.50999999, + "w": 0.47000000, + "h": 0.47000000 + } + }, + { + "panel_id": "panel_001_004", + "panel_number": 4, + "layout_cell": { + "x": 0.50999999, + "y": 0.50999999, + "w": 0.47000000, + "h": 0.47000000 + } + } + ], + "width": 2480, + "height": 3508 + }, + { + "page_number": 2, + "pattern_id": "dialogue-heavy", + "panels": [ + { + "panel_id": "panel_001_005", + "panel_number": 5, + "layout_cell": { + "x": 0.02000000, + "y": 0.02000000, + "w": 0.47000000, + "h": 0.22000000 + } + }, + { + "panel_id": "panel_001_006", + "panel_number": 6, + "layout_cell": { + "x": 0.50999999, + "y": 0.02000000, + "w": 0.47000000, + "h": 0.22000000 + } + }, + { + "panel_id": "panel_002_001", + "panel_number": 1, + "layout_cell": { + "x": 0.02000000, + "y": 0.25999999, + "w": 0.47000000, + "h": 0.22000000 + } + }, + { + "panel_id": "panel_002_002", + "panel_number": 2, + "layout_cell": { + "x": 0.50999999, + "y": 0.25999999, + "w": 0.47000000, + "h": 0.22000000 + } + }, + { + "panel_id": "panel_002_003", + "panel_number": 3, + "layout_cell": { + "x": 0.02000000, + "y": 0.50000000, + "w": 0.47000000, + "h": 0.22000000 + } + }, + { + "panel_id": "panel_002_004", + "panel_number": 4, + "layout_cell": { + "x": 0.50999999, + "y": 0.50000000, + "w": 0.47000000, + "h": 0.22000000 + } + }, + { + "panel_id": "panel_002_005", + "panel_number": 5, + "layout_cell": { + "x": 0.02000000, + "y": 0.74000001, + "w": 0.47000000, + "h": 0.22000000 + } + }, + { + "panel_id": "panel_002_006", + "panel_number": 6, + "layout_cell": { + "x": 0.50999999, + "y": 0.74000001, + "w": 0.47000000, + "h": 0.22000000 + } + } + ], + "width": 2480, + "height": 3508 + } ], "speech_bubbles": { @@ -42,7 +526,7 @@ "page_size": 0, "color_profile": 0, "workflow": { - "current_step": 0, + "current_step": 5, "completed_steps": [ ], diff --git a/odin/gui_session_report.txt b/odin/gui_session_report.txt index ee55f3e..942db87 100644 Binary files a/odin/gui_session_report.txt and b/odin/gui_session_report.txt differ diff --git a/odin/src/gui/clay_layout.odin b/odin/src/gui/clay_layout.odin index 222ad57..b2f3760 100644 --- a/odin/src/gui/clay_layout.odin +++ b/odin/src/gui/clay_layout.odin @@ -6,7 +6,6 @@ import "core:fmt" import "core:math" import "core:strings" import rl "vendor:raylib" -import "../shared" // --- Font IDs (indices into raylib_fonts) --- CLAY_FONT_BODY :: u16(0) diff --git a/odin/src/gui/runtime.odin b/odin/src/gui/runtime.odin index 9d479db..c1e5da1 100644 --- a/odin/src/gui/runtime.odin +++ b/odin/src/gui/runtime.odin @@ -301,7 +301,6 @@ run_gui_app :: proc(state: ^core.Comic_State) -> shared.App_Error { // ─── Clay Layout Declaration ────────────────────────────── main_w := shared.compute_main_width(screen_w) status_w := (main_w - 2) / 2 - lower_y := shared.compute_lower_y(screen_h) clay.BeginLayout() @@ -317,11 +316,11 @@ run_gui_app :: proc(state: ^core.Comic_State) -> shared.App_Error { if clay.UI(clay.ID("MainArea"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}, layoutDirection = .TopToBottom}, }) { - declare_topbar(&app, main_w, screen_w) - declare_project_setup(&app, main_w) + declare_topbar(&app) + declare_project_setup(&app) declare_actions_row(&app, can_generate_panels, can_layout, can_export, project_path_ok, export_path_ok, has_deepseek_key) - declare_status_card(&app, status_w, lower_y) - declare_detail_area(&app, main_w, status_w, screen_w, lower_y, lower_y - 140, compact_mode) + declare_status_card(&app) + declare_detail_area(&app, status_w) } } @@ -399,7 +398,7 @@ declare_sidebar :: proc(app: ^GUI_App_State, screen_h: i32) { } // ─── Topbar Declaration ────────────────────────────────────────── -declare_topbar :: proc(app: ^GUI_App_State, main_w: i32, screen_w: i32) { +declare_topbar :: proc(app: ^GUI_App_State) { if clay.UI(clay.ID("Topbar"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingFit({min = 72, max = 72})}, padding = {top = 12, right = 20, bottom = 12, left = 20}, childGap = 16, childAlignment = {y = .Center}}, backgroundColor = CLAY_BG_TOPBAR, @@ -468,7 +467,7 @@ declare_topbar :: proc(app: ^GUI_App_State, main_w: i32, screen_w: i32) { } // ─── Project Setup Declaration ───────────────────────────────────── -declare_project_setup :: proc(app: ^GUI_App_State, main_w: i32) { +declare_project_setup :: proc(app: ^GUI_App_State) { if clay.UI(clay.ID("ProjectSetup"))(clay_card_style()) { clay_title_text("Project Setup") // Story Idea @@ -577,7 +576,7 @@ declare_actions_row :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can } // ─── Status Card ────────────────────────────────────────────────── -declare_status_card :: proc(app: ^GUI_App_State, status_w: i32, lower_y: i32) { +declare_status_card :: proc(app: ^GUI_App_State) { ready_count, total_count := ready_stage_count(app.controller) progress := f32(0) if total_count > 0 { progress = f32(ready_count) / f32(total_count) } @@ -624,7 +623,7 @@ declare_status_card :: proc(app: ^GUI_App_State, status_w: i32, lower_y: i32) { } // ─── Detail Area ────────────────────────────────────────────────── -declare_detail_area :: proc(app: ^GUI_App_State, main_w, status_w, screen_w, lower_y, summary_y: i32, compact_mode: bool) { +declare_detail_area :: proc(app: ^GUI_App_State, status_w: i32) { if clay.UI(clay.ID("DetailArea"))({ layout = {sizing = {width = clay.SizingGrow({}), height = clay.SizingGrow({})}, layoutDirection = .LeftToRight, childGap = 2}, }) { @@ -635,35 +634,6 @@ declare_detail_area :: proc(app: ^GUI_App_State, main_w, status_w, screen_w, low cornerRadius = clay.CornerRadiusAll(CLAY_RADIUS_MD), }) { declare_screen_summary(app) - screen := app.controller.active_screen - if screen == .Script || screen == .Layout || screen == .Panels || screen == .Bubbles { - show_txt := "Show:Top" - sort_txt := "Sort:Asc" - if screen == .Script { - if app.summary_opts.script_show_all { show_txt = "Show:All" } - if app.summary_opts.script_desc { sort_txt = "Sort:Desc" } - } else { - if app.summary_opts.layout_show_all { show_txt = "Show:All" } - if app.summary_opts.layout_desc { sort_txt = "Sort:Desc" } - } - if clay.UI(clay.ID("SummaryBtnRow"))({layout = clay_row_layout()}) { - declare_button_small("btn_summary_show", show_txt) - declare_button_small("btn_summary_sort", sort_txt) - if screen == .Script { - declare_button_small("btn_summary_prev", "< Pg") - declare_button_small("btn_summary_next", "Pg >") - } else if screen == .Panels { - declare_button_small("btn_summary_prev", "< Pn") - declare_button_small("btn_summary_next", "Pn >") - } else if screen == .Layout { - declare_button_small("btn_summary_prev", "< Ly") - declare_button_small("btn_summary_next", "Ly >") - } else if screen == .Bubbles { - declare_button_small("btn_summary_prev", "< Pn") - declare_button_small("btn_summary_next", "Pn >") - } - } - } } // Detail/log panel (right) — detail panels or action log @@ -1483,8 +1453,10 @@ declare_layout_detail :: proc(app: ^GUI_App_State) { }) { for i in 0.. 100 { w_pct = 100 } else if w_pct < 0 { w_pct = 0 } + h_pct := f32(cell.h * 100); if h_pct > 100 { h_pct = 100 } else if h_pct < 0 { h_pct = 0 } if clay.UI(clay.ID(fmt.tprintf("wire_cell_%d", i)))({ - layout = {sizing = {width = clay.SizingPercent(f32(cell.w * 100)), height = clay.SizingPercent(f32(cell.h * 100))}, padding = {top = 2, left = 2, right = 2, bottom = 2}}, + layout = {sizing = {width = clay.SizingPercent(w_pct), height = clay.SizingPercent(h_pct)}, padding = {top = 2, left = 2, right = 2, bottom = 2}}, backgroundColor = CLAY_ACCENT_SURFACE, cornerRadius = clay.CornerRadiusAll(2), border = {color = CLAY_ACCENT_MUTED, width = clay.BorderOutside(1)},