1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use geom::Percent;
use map_gui::tools::open_browser;
use widgetry::{
    Btn, EventCtx, GeomBatch, GfxCtx, Key, Line, Outcome, Panel, State, Text, TextExt, Widget,
};

use crate::levels::Level;
use crate::{App, Transition};

pub struct TitleScreen {
    panel: Panel,
}

impl TitleScreen {
    pub fn new(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
        let mut level_buttons = Vec::new();
        for (idx, level) in app.session.levels.iter().enumerate() {
            if idx < app.session.levels_unlocked {
                level_buttons.push(unlocked_level(ctx, app, level, idx));
            } else {
                level_buttons.push(locked_level(ctx, app, level, idx));
            }
        }

        Box::new(TitleScreen {
            panel: Panel::new(Widget::col(vec![
                Btn::svg_def("system/assets/tools/quit.svg")
                    .build(ctx, "quit", Key::Escape)
                    .align_right(),
                Line("A/B STREET")
                    .big_heading_plain()
                    .draw(ctx)
                    .centered_horiz(),
                Line("15 Minute Santa")
                    .display_title()
                    .draw(ctx)
                    .centered_horiz(),
                Text::from(Line(
                    "Time for Santa to deliver presents in Seattle! But... 2020 has thoroughly \
                     squashed any remaining magic out of the world, so your sleigh can only hold \
                     so many presents at a time. When you run out, refill from a store. Those are \
                     close to where people live... right?",
                ))
                .wrap_to_pct(ctx, 50)
                .draw(ctx)
                .centered_horiz(),
                Widget::custom_row(level_buttons).flex_wrap(ctx, Percent::int(80)),
                "Created by Dustin Carlino, Yuwen Li, & Michael Kirk"
                    .draw_text(ctx)
                    .centered_horiz(),
                Btn::plaintext("Santa made by @parallaxcreativedesign")
                    .build(
                        ctx,
                        "open https://www.instagram.com/parallaxcreativedesign/",
                        None,
                    )
                    .centered_horiz(),
            ]))
            .exact_size_percent(90, 85)
            .build_custom(ctx),
        })
    }
}

impl State<App> for TitleScreen {
    fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
        match self.panel.event(ctx) {
            Outcome::Clicked(x) => match x.as_ref() {
                "quit" => {
                    return Transition::Pop;
                }
                x => {
                    if let Some(url) = x.strip_prefix("open ") {
                        open_browser(url.to_string());
                        return Transition::Keep;
                    }

                    for level in &app.session.levels {
                        if x == level.title {
                            return Transition::Push(crate::before_level::Picker::new(
                                ctx,
                                app,
                                level.clone(),
                            ));
                        }
                    }
                    panic!("Unknown action {}", x);
                }
            },
            _ => {}
        }

        app.session.update_music(ctx);

        Transition::Keep
    }

    fn draw(&self, g: &mut GfxCtx, app: &App) {
        self.panel.draw(g);
        app.session.music.draw(g);
    }
}

// TODO Preview the map, add padding, add the linear gradient...
fn locked_level(ctx: &mut EventCtx, app: &App, level: &Level, idx: usize) -> Widget {
    let mut txt = Text::new().bg(app.cs.unzoomed_bike);
    txt.add(Line(format!("LEVEL {}", idx + 1)).small_heading());
    txt.add(Line(&level.title).small_heading());
    txt.add(Line(&level.description));
    let mut batch = txt.wrap_to_pct(ctx, 15).render_to_batch(ctx.prerender);
    let hitbox = batch.get_bounds().get_rectangle();
    let center = hitbox.center();
    batch.push(app.cs.fade_map_dark, hitbox);
    batch.append(
        GeomBatch::load_svg(ctx.prerender, "system/assets/tools/locked.svg").centered_on(center),
    );
    Widget::draw_batch(ctx, batch)
}

fn unlocked_level(ctx: &mut EventCtx, app: &App, level: &Level, idx: usize) -> Widget {
    let mut txt = Text::new().bg(app.cs.unzoomed_bike);
    txt.add(Line(format!("LEVEL {}", idx + 1)).small_heading());
    txt.add(Line(&level.title).small_heading());
    txt.add(Line(&level.description));
    Btn::plaintext_custom(&level.title, txt.wrap_to_pct(ctx, 15)).build_def(ctx, None)
}