mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 04:35:51 +03:00
tie together a popup menu and a button in a really simple way. move some
info and location things there
This commit is contained in:
parent
00253d2783
commit
7574869798
@ -13,6 +13,8 @@ pub enum ContainerOrientation {
|
||||
TopLeft,
|
||||
TopRight,
|
||||
Centered,
|
||||
// Place the widget this percentage along the width of the screen
|
||||
Top(f64),
|
||||
}
|
||||
|
||||
pub fn stack_vertically(
|
||||
@ -39,6 +41,7 @@ pub fn stack_vertically(
|
||||
pt.y -= total_height / 2.0;
|
||||
pt
|
||||
}
|
||||
ContainerOrientation::Top(percent) => ScreenPt::new(canvas.window_width * percent, 0.0),
|
||||
};
|
||||
for (w, dims) in widgets.into_iter().zip(dims_per_widget) {
|
||||
w.set_pos(top_left, total_width);
|
||||
|
@ -20,8 +20,8 @@ pub use crate::runner::{run, EventLoopMode, Settings, GUI};
|
||||
pub use crate::screen_geom::{ScreenDims, ScreenPt, ScreenRectangle};
|
||||
pub use crate::text::{Line, Text, TextSpan, HOTKEY_COLOR};
|
||||
pub use crate::widgets::{
|
||||
Autocomplete, Choice, ItemSlider, ModalMenu, NewScroller, Scroller, Slider, SliderWithTextBox,
|
||||
Warper, WarpingItemSlider, Wizard, WrappedWizard,
|
||||
Autocomplete, Choice, ItemSlider, MenuUnderButton, ModalMenu, NewScroller, Scroller, Slider,
|
||||
SliderWithTextBox, Warper, WarpingItemSlider, Wizard, WrappedWizard,
|
||||
};
|
||||
|
||||
pub enum InputResult<T: Clone> {
|
||||
|
@ -110,8 +110,13 @@ const ICON_BACKGROUND: Color = Color::grey(0.5);
|
||||
const ICON_BACKGROUND_SELECTED: Color = Color::YELLOW;
|
||||
|
||||
impl Button {
|
||||
fn show_hide_btn(icon: &str, tooltip: &str, ctx: &EventCtx) -> Button {
|
||||
let radius = ctx.canvas.line_height / 2.0;
|
||||
pub fn icon_btn(
|
||||
icon: &str,
|
||||
radius: f64,
|
||||
tooltip: &str,
|
||||
key: Option<MultiKey>,
|
||||
ctx: &EventCtx,
|
||||
) -> Button {
|
||||
let circle = Circle::new(Pt2D::new(radius, radius), Distance::meters(radius));
|
||||
|
||||
let mut normal = GeomBatch::new();
|
||||
@ -122,15 +127,27 @@ impl Button {
|
||||
hovered.push(ICON_BACKGROUND_SELECTED, circle.to_polygon());
|
||||
hovered.push(ctx.canvas.texture(icon), circle.to_polygon());
|
||||
|
||||
// TODO Arbitrarilyish the first user to be event()'d will eat this key.
|
||||
Button::new(normal, hovered, hotkey(Key::Tab), tooltip, ctx)
|
||||
Button::new(normal, hovered, key, tooltip, ctx)
|
||||
}
|
||||
|
||||
pub fn show_btn(ctx: &EventCtx, tooltip: &str) -> Button {
|
||||
Button::show_hide_btn("assets/ui/show.png", tooltip, ctx)
|
||||
// TODO Arbitrarilyish the first user to be event()'d will eat this key.
|
||||
Button::icon_btn(
|
||||
"assets/ui/show.png",
|
||||
ctx.canvas.line_height / 2.0,
|
||||
tooltip,
|
||||
hotkey(Key::Tab),
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn hide_btn(ctx: &EventCtx, tooltip: &str) -> Button {
|
||||
Button::show_hide_btn("assets/ui/hide.png", tooltip, ctx)
|
||||
Button::icon_btn(
|
||||
"assets/ui/hide.png",
|
||||
ctx.canvas.line_height / 2.0,
|
||||
tooltip,
|
||||
hotkey(Key::Tab),
|
||||
ctx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
122
ezgui/src/widgets/menu_under_button.rs
Normal file
122
ezgui/src/widgets/menu_under_button.rs
Normal file
@ -0,0 +1,122 @@
|
||||
use crate::layout::{ContainerOrientation, Widget};
|
||||
use crate::widgets::{Button, PopupMenu};
|
||||
use crate::{layout, Choice, EventCtx, GfxCtx, InputResult, MultiKey, ScreenDims, ScreenPt, Text};
|
||||
|
||||
// TODO Ideally:
|
||||
// - Pause sim while this is active
|
||||
// - Grey out inactive items like ModalMenu
|
||||
// Right now the uses of this don't really need this.
|
||||
pub struct MenuUnderButton {
|
||||
button: Button,
|
||||
menu: PopupMenu<()>,
|
||||
expanded: bool,
|
||||
chosen_action: Option<String>,
|
||||
// TODO Hackish. While unexpanded.
|
||||
unexpanded_choices: Vec<(MultiKey, String)>,
|
||||
standalone_layout: ContainerOrientation,
|
||||
}
|
||||
|
||||
impl MenuUnderButton {
|
||||
pub fn new(
|
||||
icon: &str,
|
||||
title: &str,
|
||||
choices: Vec<(Option<MultiKey>, &str)>,
|
||||
percent_along_top_of_screen: f64,
|
||||
ctx: &EventCtx,
|
||||
) -> MenuUnderButton {
|
||||
let mut m = MenuUnderButton {
|
||||
button: Button::icon_btn(icon, 32.0, title, None, ctx),
|
||||
menu: PopupMenu::new(
|
||||
Text::prompt(title),
|
||||
choices
|
||||
.iter()
|
||||
.map(|(mk, name)| Choice::new(*name, ()).multikey(*mk))
|
||||
.collect(),
|
||||
ctx,
|
||||
),
|
||||
expanded: false,
|
||||
chosen_action: None,
|
||||
unexpanded_choices: choices
|
||||
.into_iter()
|
||||
.filter_map(|(mk, name)| {
|
||||
if let Some(key) = mk {
|
||||
Some((key, name.to_string()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
standalone_layout: ContainerOrientation::Top(percent_along_top_of_screen),
|
||||
};
|
||||
m.menu.disable_standalone_layout();
|
||||
m
|
||||
}
|
||||
|
||||
pub fn event(&mut self, ctx: &mut EventCtx) {
|
||||
if let Some(ref c) = self.chosen_action {
|
||||
panic!("Nothing consumed action {}", c);
|
||||
}
|
||||
|
||||
layout::stack_vertically(self.standalone_layout, ctx.canvas, vec![self]);
|
||||
|
||||
self.button.event(ctx);
|
||||
if self.expanded {
|
||||
match self.menu.event(ctx) {
|
||||
InputResult::StillActive => {}
|
||||
InputResult::Done(name, _) => {
|
||||
self.chosen_action = Some(name);
|
||||
self.expanded = false;
|
||||
}
|
||||
InputResult::Canceled => {
|
||||
self.expanded = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.button.clicked() {
|
||||
self.expanded = true;
|
||||
} else {
|
||||
for (mk, name) in &self.unexpanded_choices {
|
||||
if ctx.input.new_was_pressed(*mk) {
|
||||
self.chosen_action = Some(name.to_string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx) {
|
||||
self.button.draw(g);
|
||||
if self.expanded {
|
||||
self.menu.draw(g);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn action(&mut self, label: &str) -> bool {
|
||||
if let Some(ref action) = self.chosen_action {
|
||||
if label == action {
|
||||
self.chosen_action = None;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for MenuUnderButton {
|
||||
fn get_dims(&self) -> ScreenDims {
|
||||
self.button.get_dims()
|
||||
}
|
||||
|
||||
fn set_pos(&mut self, top_left: ScreenPt, total_width: f64) {
|
||||
self.button.set_pos(top_left, total_width);
|
||||
// TODO Brittle centering depends where these buttons are being placed right now
|
||||
self.menu.set_pos(
|
||||
ScreenPt::new(
|
||||
top_left.x - self.menu.get_dims().width / 2.0,
|
||||
top_left.y + self.get_dims().height,
|
||||
),
|
||||
total_width,
|
||||
);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ mod autocomplete;
|
||||
mod button;
|
||||
mod context_menu;
|
||||
mod log_scroller;
|
||||
mod menu_under_button;
|
||||
mod modal_menu;
|
||||
mod popup_menu;
|
||||
mod screenshot;
|
||||
@ -14,6 +15,7 @@ mod wizard;
|
||||
pub use self::autocomplete::Autocomplete;
|
||||
pub use self::button::Button;
|
||||
pub(crate) use self::context_menu::ContextMenu;
|
||||
pub use self::menu_under_button::MenuUnderButton;
|
||||
pub use self::modal_menu::ModalMenu;
|
||||
pub(crate) use self::popup_menu::PopupMenu;
|
||||
pub(crate) use self::screenshot::{screenshot_current, screenshot_everything};
|
||||
|
@ -32,6 +32,12 @@ impl<T: Clone> PopupMenu<T> {
|
||||
m
|
||||
}
|
||||
|
||||
// It's part of something bigger
|
||||
pub fn disable_standalone_layout(&mut self) {
|
||||
assert!(self.standalone_layout.is_some());
|
||||
self.standalone_layout = None;
|
||||
}
|
||||
|
||||
pub fn event(&mut self, ctx: &mut EventCtx) -> InputResult<T> {
|
||||
if let Some(o) = self.standalone_layout {
|
||||
layout::stack_vertically(o, ctx.canvas, vec![self]);
|
||||
@ -59,8 +65,12 @@ impl<T: Clone> PopupMenu<T> {
|
||||
}
|
||||
{
|
||||
let choice = &self.choices[self.current_idx];
|
||||
if ctx.input.left_mouse_button_pressed() && choice.active {
|
||||
return InputResult::Done(choice.label.clone(), choice.data.clone());
|
||||
if ctx.input.left_mouse_button_pressed() {
|
||||
if choice.active && ctx.canvas.get_cursor_in_map_space().is_none() {
|
||||
return InputResult::Done(choice.label.clone(), choice.data.clone());
|
||||
} else {
|
||||
return InputResult::Canceled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -407,6 +407,11 @@ impl<T: Clone> Choice<T> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn multikey(mut self, mk: Option<MultiKey>) -> Choice<T> {
|
||||
self.hotkey = mk;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn active(mut self, active: bool) -> Choice<T> {
|
||||
self.active = active;
|
||||
self
|
||||
|
BIN
game/assets/ui/location.png
Normal file
BIN
game/assets/ui/location.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
@ -8,7 +8,8 @@ use crate::render::MIN_ZOOM_FOR_DETAIL;
|
||||
use crate::ui::{PerMapUI, UI};
|
||||
use abstutil::Timer;
|
||||
use ezgui::{
|
||||
hotkey, lctrl, Color, EventCtx, EventLoopMode, GeomBatch, GfxCtx, Key, Line, ModalMenu, Text,
|
||||
hotkey, lctrl, Color, EventCtx, EventLoopMode, GeomBatch, GfxCtx, Key, Line, MenuUnderButton,
|
||||
ModalMenu, Text,
|
||||
};
|
||||
use geom::{Circle, Distance, Line, PolyLine};
|
||||
use map_model::{Map, LANE_THICKNESS};
|
||||
@ -18,6 +19,7 @@ use sim::{Sim, SimOptions, TripID};
|
||||
pub struct ABTestMode {
|
||||
menu: ModalMenu,
|
||||
speed: SpeedControls,
|
||||
info_tools: MenuUnderButton,
|
||||
primary_agent_tools: AgentTools,
|
||||
secondary_agent_tools: AgentTools,
|
||||
diff_trip: Option<DiffOneTrip>,
|
||||
@ -39,28 +41,33 @@ impl ABTestMode {
|
||||
(hotkey(Key::S), "swap"),
|
||||
(hotkey(Key::D), "diff all trips"),
|
||||
(hotkey(Key::A), "stop diffing trips"),
|
||||
(hotkey(Key::Q), "scoreboard"),
|
||||
(hotkey(Key::O), "save state"),
|
||||
// TODO load arbitrary savestate
|
||||
],
|
||||
vec![
|
||||
(hotkey(Key::Escape), "quit"),
|
||||
(lctrl(Key::D), "debug mode"),
|
||||
(hotkey(Key::J), "warp"),
|
||||
(hotkey(Key::K), "navigate"),
|
||||
(hotkey(Key::Semicolon), "change agent colorscheme"),
|
||||
(hotkey(Key::SingleQuote), "shortcuts"),
|
||||
(hotkey(Key::F1), "take a screenshot"),
|
||||
],
|
||||
],
|
||||
ctx,
|
||||
),
|
||||
speed: SpeedControls::new(ctx, true),
|
||||
info_tools: MenuUnderButton::new(
|
||||
"assets/ui/info.png",
|
||||
"Info",
|
||||
vec![
|
||||
(hotkey(Key::Q), "scoreboard"),
|
||||
(hotkey(Key::Semicolon), "change agent colorscheme"),
|
||||
],
|
||||
0.5,
|
||||
ctx,
|
||||
),
|
||||
primary_agent_tools: AgentTools::new(),
|
||||
secondary_agent_tools: AgentTools::new(),
|
||||
diff_trip: None,
|
||||
diff_all: None,
|
||||
common: CommonState::new(),
|
||||
common: CommonState::new(ctx),
|
||||
test_name: test_name.to_string(),
|
||||
flipped: false,
|
||||
}
|
||||
@ -95,6 +102,7 @@ impl State for ABTestMode {
|
||||
self.menu.set_info(ctx, txt);
|
||||
}
|
||||
self.menu.event(ctx);
|
||||
self.info_tools.event(ctx);
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if ctx.redo_mouseover() {
|
||||
@ -125,7 +133,7 @@ impl State for ABTestMode {
|
||||
self.flipped = !self.flipped;
|
||||
}
|
||||
|
||||
if self.menu.action("scoreboard") {
|
||||
if self.info_tools.action("scoreboard") {
|
||||
return Transition::Push(Box::new(score::Scoreboard::new(
|
||||
ctx,
|
||||
&ui.primary,
|
||||
@ -133,7 +141,10 @@ impl State for ABTestMode {
|
||||
)));
|
||||
}
|
||||
|
||||
if let Some(t) = self.primary_agent_tools.event(ctx, ui, &mut self.menu) {
|
||||
if let Some(t) =
|
||||
self.primary_agent_tools
|
||||
.event(ctx, ui, &mut self.menu, &mut self.info_tools)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -212,6 +223,7 @@ impl State for ABTestMode {
|
||||
self.menu.draw(g);
|
||||
self.speed.draw(g);
|
||||
self.primary_agent_tools.draw(g, ui);
|
||||
self.info_tools.draw(g);
|
||||
}
|
||||
|
||||
fn on_suspend(&mut self, ctx: &mut EventCtx, _: &mut UI) {
|
||||
|
@ -3,7 +3,7 @@ use crate::common::{ColorLegend, RouteExplorer, TripExplorer};
|
||||
use crate::game::{Transition, WizardState};
|
||||
use crate::render::{AgentColorScheme, MIN_ZOOM_FOR_DETAIL};
|
||||
use crate::ui::UI;
|
||||
use ezgui::{hotkey, Choice, EventCtx, GfxCtx, Key, ModalMenu};
|
||||
use ezgui::{hotkey, Choice, EventCtx, GfxCtx, Key, MenuUnderButton, ModalMenu};
|
||||
use geom::{Duration, Pt2D};
|
||||
use sim::{TripID, TripResult};
|
||||
use std::cell::RefCell;
|
||||
@ -29,6 +29,7 @@ impl AgentTools {
|
||||
ctx: &mut EventCtx,
|
||||
ui: &UI,
|
||||
menu: &mut ModalMenu,
|
||||
info_menu: &mut MenuUnderButton,
|
||||
) -> Option<Transition> {
|
||||
if self.following.is_none() {
|
||||
if let Some(agent) = ui
|
||||
@ -87,7 +88,7 @@ impl AgentTools {
|
||||
}
|
||||
self.route_viewer.event(ctx, ui, menu);
|
||||
|
||||
if menu.action("change agent colorscheme") {
|
||||
if info_menu.action("change agent colorscheme") {
|
||||
return Some(Transition::Push(WizardState::new(Box::new(
|
||||
|wiz, ctx, ui| {
|
||||
let (_, acs) = wiz.wrap(ctx).choose("Which colorscheme for agents?", || {
|
||||
|
@ -26,21 +26,33 @@ use crate::helpers::ID;
|
||||
use crate::render::DrawOptions;
|
||||
use crate::ui::UI;
|
||||
use ezgui::{
|
||||
Color, EventCtx, EventLoopMode, GfxCtx, HorizontalAlignment, Key, Line, ModalMenu, Text,
|
||||
VerticalAlignment,
|
||||
hotkey, Color, EventCtx, EventLoopMode, GfxCtx, HorizontalAlignment, Key, Line,
|
||||
MenuUnderButton, ModalMenu, Text, VerticalAlignment,
|
||||
};
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
pub struct CommonState {
|
||||
associated: associated::ShowAssociatedState,
|
||||
turn_cycler: turn_cycler::TurnCyclerState,
|
||||
location_tools: MenuUnderButton,
|
||||
}
|
||||
|
||||
impl CommonState {
|
||||
pub fn new() -> CommonState {
|
||||
pub fn new(ctx: &EventCtx) -> CommonState {
|
||||
CommonState {
|
||||
associated: associated::ShowAssociatedState::Inactive,
|
||||
turn_cycler: turn_cycler::TurnCyclerState::Inactive,
|
||||
location_tools: MenuUnderButton::new(
|
||||
"assets/ui/location.png",
|
||||
"Location",
|
||||
vec![
|
||||
(hotkey(Key::J), "warp"),
|
||||
(hotkey(Key::K), "navigate"),
|
||||
(hotkey(Key::SingleQuote), "shortcuts"),
|
||||
],
|
||||
0.4,
|
||||
ctx,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,13 +62,15 @@ impl CommonState {
|
||||
ui: &mut UI,
|
||||
menu: &mut ModalMenu,
|
||||
) -> Option<Transition> {
|
||||
if menu.action("warp") {
|
||||
self.location_tools.event(ctx);
|
||||
|
||||
if self.location_tools.action("warp") {
|
||||
return Some(Transition::Push(warp::EnteringWarp::new()));
|
||||
}
|
||||
if menu.action("navigate") {
|
||||
if self.location_tools.action("navigate") {
|
||||
return Some(Transition::Push(Box::new(navigate::Navigator::new(ui))));
|
||||
}
|
||||
if menu.action("shortcuts") {
|
||||
if self.location_tools.action("shortcuts") {
|
||||
return Some(Transition::Push(shortcuts::ChoosingShortcut::new()));
|
||||
}
|
||||
|
||||
@ -85,6 +99,7 @@ impl CommonState {
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx, ui: &UI) {
|
||||
self.turn_cycler.draw(g, ui);
|
||||
self.location_tools.draw(g);
|
||||
|
||||
CommonState::draw_osd(g, ui, &ui.primary.current_selection);
|
||||
}
|
||||
|
@ -58,15 +58,12 @@ impl DebugMode {
|
||||
],
|
||||
vec![
|
||||
(hotkey(Key::Escape), "return to previous mode"),
|
||||
(hotkey(Key::J), "warp"),
|
||||
(hotkey(Key::K), "navigate"),
|
||||
(hotkey(Key::SingleQuote), "shortcuts"),
|
||||
(hotkey(Key::F1), "take a screenshot"),
|
||||
],
|
||||
],
|
||||
ctx,
|
||||
),
|
||||
common: CommonState::new(),
|
||||
common: CommonState::new(ctx),
|
||||
connected_roads: connected_roads::ShowConnectedRoads::new(),
|
||||
objects: objects::ObjectDebugger::new(),
|
||||
hidden: HashSet::new(),
|
||||
|
@ -29,7 +29,7 @@ impl EditMode {
|
||||
ui.primary.reset_sim();
|
||||
|
||||
EditMode {
|
||||
common: CommonState::new(),
|
||||
common: CommonState::new(ctx),
|
||||
menu: ModalMenu::new(
|
||||
"Map Edit Mode",
|
||||
vec![
|
||||
@ -41,9 +41,6 @@ impl EditMode {
|
||||
(hotkey(Key::Escape), "quit"),
|
||||
(lctrl(Key::S), "sandbox mode"),
|
||||
(lctrl(Key::D), "debug mode"),
|
||||
(hotkey(Key::J), "warp"),
|
||||
(hotkey(Key::K), "navigate"),
|
||||
(hotkey(Key::SingleQuote), "shortcuts"),
|
||||
(hotkey(Key::F1), "take a screenshot"),
|
||||
],
|
||||
],
|
||||
|
@ -123,15 +123,12 @@ impl ScenarioManager {
|
||||
],
|
||||
vec![
|
||||
(hotkey(Key::Escape), "quit"),
|
||||
(hotkey(Key::J), "warp"),
|
||||
(hotkey(Key::K), "navigate"),
|
||||
(hotkey(Key::SingleQuote), "shortcuts"),
|
||||
(hotkey(Key::F1), "take a screenshot"),
|
||||
],
|
||||
],
|
||||
ctx,
|
||||
),
|
||||
common: CommonState::new(),
|
||||
common: CommonState::new(ctx),
|
||||
scenario,
|
||||
trips_from_bldg,
|
||||
trips_to_bldg,
|
||||
@ -282,7 +279,8 @@ impl State for ScenarioManager {
|
||||
}
|
||||
|
||||
self.menu.draw(g);
|
||||
// TODO Weird to not draw common (turn cycler), but we want the custom OSD...
|
||||
self.common.draw(g, ui);
|
||||
// TODO Just cover up common's OSD with ours...
|
||||
|
||||
if let Some(ID::Building(b)) = ui.primary.current_selection {
|
||||
let mut osd = CommonState::default_osd(ID::Building(b), ui);
|
||||
|
@ -6,7 +6,7 @@ use crate::render::DrawOptions;
|
||||
use crate::sandbox::SandboxMode;
|
||||
use crate::ui::{ShowEverything, UI};
|
||||
use abstutil::{prettyprint_usize, Counter};
|
||||
use ezgui::{Choice, Color, EventCtx, GfxCtx, Line, ModalMenu, Text};
|
||||
use ezgui::{Choice, Color, EventCtx, GfxCtx, Line, MenuUnderButton, Text};
|
||||
use geom::Duration;
|
||||
use map_model::PathStep;
|
||||
use sim::ParkingSpot;
|
||||
@ -27,7 +27,7 @@ impl Analytics {
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
ui: &UI,
|
||||
menu: &mut ModalMenu,
|
||||
menu: &mut MenuUnderButton,
|
||||
trip_stats: &TripStats,
|
||||
) -> Option<Transition> {
|
||||
if menu.action("change analytics overlay") {
|
||||
|
@ -11,13 +11,15 @@ use crate::game::{State, Transition, WizardState};
|
||||
use crate::helpers::ID;
|
||||
use crate::ui::{ShowEverything, UI};
|
||||
use ezgui::{
|
||||
hotkey, lctrl, Choice, EventCtx, EventLoopMode, GfxCtx, Key, Line, ModalMenu, Text, Wizard,
|
||||
hotkey, lctrl, Choice, EventCtx, EventLoopMode, GfxCtx, Key, Line, MenuUnderButton, ModalMenu,
|
||||
Text, Wizard,
|
||||
};
|
||||
use geom::Duration;
|
||||
use sim::Sim;
|
||||
|
||||
pub struct SandboxMode {
|
||||
speed: SpeedControls,
|
||||
info_tools: MenuUnderButton,
|
||||
agent_tools: AgentTools,
|
||||
pub time_travel: time_travel::InactiveTimeTravel,
|
||||
trip_stats: trip_stats::TripStats,
|
||||
@ -30,13 +32,24 @@ impl SandboxMode {
|
||||
pub fn new(ctx: &mut EventCtx, ui: &UI) -> SandboxMode {
|
||||
SandboxMode {
|
||||
speed: SpeedControls::new(ctx, true),
|
||||
info_tools: MenuUnderButton::new(
|
||||
"assets/ui/info.png",
|
||||
"Info",
|
||||
vec![
|
||||
(hotkey(Key::Q), "scoreboard"),
|
||||
(hotkey(Key::L), "change analytics overlay"),
|
||||
(hotkey(Key::Semicolon), "change agent colorscheme"),
|
||||
],
|
||||
0.5,
|
||||
ctx,
|
||||
),
|
||||
agent_tools: AgentTools::new(),
|
||||
time_travel: time_travel::InactiveTimeTravel::new(),
|
||||
trip_stats: trip_stats::TripStats::new(
|
||||
ui.primary.current_flags.sim_flags.opts.record_stats,
|
||||
),
|
||||
analytics: analytics::Analytics::Inactive,
|
||||
common: CommonState::new(),
|
||||
common: CommonState::new(ctx),
|
||||
menu: ModalMenu::new(
|
||||
"Sandbox Mode",
|
||||
vec![
|
||||
@ -48,19 +61,11 @@ impl SandboxMode {
|
||||
(hotkey(Key::X), "reset sim"),
|
||||
(hotkey(Key::S), "start a scenario"),
|
||||
],
|
||||
vec![
|
||||
(hotkey(Key::T), "start time traveling"),
|
||||
(hotkey(Key::Q), "scoreboard"),
|
||||
(hotkey(Key::L), "change analytics overlay"),
|
||||
(hotkey(Key::Semicolon), "change agent colorscheme"),
|
||||
],
|
||||
vec![(hotkey(Key::T), "start time traveling")],
|
||||
vec![
|
||||
(hotkey(Key::Escape), "quit"),
|
||||
(lctrl(Key::D), "debug mode"),
|
||||
(lctrl(Key::E), "edit mode"),
|
||||
(hotkey(Key::J), "warp"),
|
||||
(hotkey(Key::K), "navigate"),
|
||||
(hotkey(Key::SingleQuote), "shortcuts"),
|
||||
(hotkey(Key::F1), "take a screenshot"),
|
||||
],
|
||||
],
|
||||
@ -84,6 +89,7 @@ impl State for SandboxMode {
|
||||
self.menu.set_info(ctx, txt);
|
||||
}
|
||||
self.menu.event(ctx);
|
||||
self.info_tools.event(ctx);
|
||||
|
||||
ctx.canvas.handle_event(ctx.input);
|
||||
if ctx.redo_mouseover() {
|
||||
@ -94,7 +100,7 @@ impl State for SandboxMode {
|
||||
}
|
||||
if let Some(t) = self
|
||||
.analytics
|
||||
.event(ctx, ui, &mut self.menu, &self.trip_stats)
|
||||
.event(ctx, ui, &mut self.info_tools, &self.trip_stats)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
@ -103,13 +109,16 @@ impl State for SandboxMode {
|
||||
return Transition::Push(new_state);
|
||||
}
|
||||
|
||||
if let Some(t) = self.agent_tools.event(ctx, ui, &mut self.menu) {
|
||||
if let Some(t) = self
|
||||
.agent_tools
|
||||
.event(ctx, ui, &mut self.menu, &mut self.info_tools)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
if ui.primary.current_selection.is_none() && self.menu.action("start time traveling") {
|
||||
return self.time_travel.start(ctx, ui);
|
||||
}
|
||||
if self.menu.action("scoreboard") {
|
||||
if self.info_tools.action("scoreboard") {
|
||||
return Transition::Push(Box::new(score::Scoreboard::new(ctx, ui)));
|
||||
}
|
||||
|
||||
@ -233,6 +242,7 @@ impl State for SandboxMode {
|
||||
self.common.draw(g, ui);
|
||||
self.menu.draw(g);
|
||||
self.speed.draw(g);
|
||||
self.info_tools.draw(g);
|
||||
}
|
||||
|
||||
fn on_suspend(&mut self, ctx: &mut EventCtx, _: &mut UI) {
|
||||
|
@ -28,6 +28,7 @@ impl UI {
|
||||
("assets/ui/hamburger.png", TextureType::Stretch),
|
||||
("assets/ui/hide.png", TextureType::Stretch),
|
||||
("assets/ui/info.png", TextureType::Stretch),
|
||||
("assets/ui/location.png", TextureType::Stretch),
|
||||
("assets/ui/show.png", TextureType::Stretch),
|
||||
];
|
||||
let skip_textures = if flags.textures {
|
||||
|
Loading…
Reference in New Issue
Block a user