mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-25 11:44:25 +03:00
display text entry boxes in the middle of the screen, not as part of the bottom OSD
This commit is contained in:
parent
d9eef240aa
commit
1d7417e851
@ -188,3 +188,11 @@ One UI plugin at a time:
|
||||
- https://docs.rs/euclid/0.19.0/euclid/struct.TypedTransform2D.html
|
||||
- https://www.reddit.com/r/rust/comments/6sukcw/is_it_possible_to_to_create_an_ortho_view_in_glium/ has a direct example of affine transformation
|
||||
- https://www.reddit.com/r/gamedev/comments/4mn9ly/3d_matrix_transformation_question_rotating/
|
||||
|
||||
## Wizard
|
||||
|
||||
API looks like coroutines/continuations, but it just works by replaying
|
||||
previous answers. The caller could even build a branching workflow -- as long
|
||||
as the calls to the wizard are deterministic.
|
||||
|
||||
Menus are super awkward -- drawing extra effects, mainly.
|
||||
|
@ -65,7 +65,7 @@ impl DrawPolygonState {
|
||||
&& input.key_pressed(Key::Return, "confirm the polygon's shape")
|
||||
{
|
||||
new_state = Some(DrawPolygonState::NamingPolygon(
|
||||
TextBox::new_prefilled(name.clone()),
|
||||
TextBox::new_prefilled("Name this polygon", name.clone()),
|
||||
pts.clone(),
|
||||
));
|
||||
}
|
||||
@ -115,9 +115,6 @@ impl DrawPolygonState {
|
||||
).expect("Saving polygon selection failed");
|
||||
println!("Saved {}", path);
|
||||
new_state = Some(DrawPolygonState::Empty);
|
||||
} else {
|
||||
osd.pad_if_nonempty();
|
||||
tb.populate_osd(osd);
|
||||
}
|
||||
input.consume_event();
|
||||
}
|
||||
@ -159,8 +156,9 @@ impl DrawPolygonState {
|
||||
}
|
||||
DrawPolygonState::DrawingPoints(pts, current_idx, _) => (pts, *current_idx),
|
||||
DrawPolygonState::MovingPoint(pts, idx, _) => (pts, Some(*idx)),
|
||||
DrawPolygonState::NamingPolygon(_, pts) => {
|
||||
DrawPolygonState::NamingPolygon(tb, pts) => {
|
||||
g.draw_polygon(blue, &Polygon::new(pts));
|
||||
tb.draw(g, canvas);
|
||||
return;
|
||||
}
|
||||
DrawPolygonState::ListingPolygons(menu, polygons) => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use colors::{ColorScheme, Colors};
|
||||
use ezgui::{TextBox, TextOSD, UserInput};
|
||||
use ezgui::{Canvas, GfxCtx, TextBox, UserInput};
|
||||
use graphics::types::Color;
|
||||
use objects::{Ctx, ID};
|
||||
use piston::input::Key;
|
||||
@ -26,20 +26,19 @@ impl SearchState {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn event(&mut self, input: &mut UserInput, osd: &mut TextOSD) -> bool {
|
||||
pub fn event(&mut self, input: &mut UserInput) -> bool {
|
||||
let mut new_state: Option<SearchState> = None;
|
||||
match self {
|
||||
SearchState::Empty => {
|
||||
if input.unimportant_key_pressed(Key::Slash, "start searching") {
|
||||
new_state = Some(SearchState::EnteringSearch(TextBox::new()));
|
||||
new_state = Some(SearchState::EnteringSearch(TextBox::new(
|
||||
"Search for what?",
|
||||
)));
|
||||
}
|
||||
}
|
||||
SearchState::EnteringSearch(tb) => {
|
||||
if tb.event(input.use_event_directly()) {
|
||||
new_state = Some(SearchState::FilterOSM(tb.line.clone()));
|
||||
} else {
|
||||
osd.pad_if_nonempty();
|
||||
tb.populate_osd(osd);
|
||||
}
|
||||
input.consume_event();
|
||||
}
|
||||
@ -60,6 +59,12 @@ impl SearchState {
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx, canvas: &Canvas) {
|
||||
if let SearchState::EnteringSearch(tb) = self {
|
||||
tb.draw(g, canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Colorizer for SearchState {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ezgui::{Canvas, TextBox, TextOSD, UserInput};
|
||||
use ezgui::{Canvas, GfxCtx, TextBox, UserInput};
|
||||
use geom::Pt2D;
|
||||
use map_model::{AreaID, BuildingID, IntersectionID, LaneID, Map, ParcelID, RoadID};
|
||||
use objects::ID;
|
||||
@ -20,23 +20,19 @@ impl WarpState {
|
||||
sim: &Sim,
|
||||
canvas: &mut Canvas,
|
||||
selected: &mut Option<ID>,
|
||||
osd: &mut TextOSD,
|
||||
) -> bool {
|
||||
let mut new_state: Option<WarpState> = None;
|
||||
match self {
|
||||
WarpState::Empty => {
|
||||
if input.unimportant_key_pressed(Key::J, "start searching for something to warp to")
|
||||
{
|
||||
new_state = Some(WarpState::EnteringSearch(TextBox::new()));
|
||||
new_state = Some(WarpState::EnteringSearch(TextBox::new("Warp to what?")));
|
||||
}
|
||||
}
|
||||
WarpState::EnteringSearch(tb) => {
|
||||
if tb.event(input.use_event_directly()) {
|
||||
warp(tb.line.clone(), map, sim, canvas, selected);
|
||||
new_state = Some(WarpState::Empty);
|
||||
} else {
|
||||
osd.pad_if_nonempty();
|
||||
tb.populate_osd(osd);
|
||||
}
|
||||
input.consume_event();
|
||||
}
|
||||
@ -49,6 +45,12 @@ impl WarpState {
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx, canvas: &Canvas) {
|
||||
if let WarpState::EnteringSearch(tb) = self {
|
||||
tb.draw(g, canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Colorizer for WarpState {}
|
||||
|
@ -70,6 +70,9 @@ impl WizardSample {
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(ref tb) = wizard.tb {
|
||||
tb.draw(g, canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,7 +196,6 @@ impl Wizard {
|
||||
&mut self,
|
||||
query: &str,
|
||||
input: &mut UserInput,
|
||||
osd: &mut TextOSD,
|
||||
parser: Box<Fn(String) -> Option<R>>,
|
||||
) -> Option<R> {
|
||||
assert!(self.alive);
|
||||
@ -204,7 +206,7 @@ impl Wizard {
|
||||
}
|
||||
|
||||
if self.tb.is_none() {
|
||||
self.tb = Some(TextBox::new());
|
||||
self.tb = Some(TextBox::new(query));
|
||||
}
|
||||
|
||||
let done = self.tb.as_mut().unwrap().event(input.use_event_directly());
|
||||
@ -220,9 +222,6 @@ impl Wizard {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
osd.pad_if_nonempty();
|
||||
osd.add_line(query.to_string());
|
||||
self.tb.as_ref().unwrap().populate_osd(osd);
|
||||
None
|
||||
}
|
||||
}
|
||||
@ -250,7 +249,6 @@ impl<'a> WrappedWizard<'a> {
|
||||
if let Some(num) = self.wizard.input_with_text_box(
|
||||
query,
|
||||
self.input,
|
||||
self.osd,
|
||||
Box::new(|line| line.parse::<usize>().ok()),
|
||||
) {
|
||||
self.wizard.state_usize.push(num);
|
||||
@ -264,12 +262,10 @@ impl<'a> WrappedWizard<'a> {
|
||||
if !self.ready_tick.is_empty() {
|
||||
return self.ready_tick.pop_front();
|
||||
}
|
||||
if let Some(tick) = self.wizard.input_with_text_box(
|
||||
query,
|
||||
self.input,
|
||||
self.osd,
|
||||
Box::new(|line| Tick::parse(&line)),
|
||||
) {
|
||||
if let Some(tick) =
|
||||
self.wizard
|
||||
.input_with_text_box(query, self.input, Box::new(|line| Tick::parse(&line)))
|
||||
{
|
||||
self.wizard.state_tick.push(tick);
|
||||
Some(tick)
|
||||
} else {
|
||||
@ -284,7 +280,6 @@ impl<'a> WrappedWizard<'a> {
|
||||
if let Some(percent) = self.wizard.input_with_text_box(
|
||||
query,
|
||||
self.input,
|
||||
self.osd,
|
||||
Box::new(|line| {
|
||||
line.parse::<f64>().ok().and_then(|num| {
|
||||
if num >= 0.0 && num <= 1.0 {
|
||||
|
@ -199,15 +199,14 @@ impl UIWrapper {
|
||||
&mut ui.sim,
|
||||
)
|
||||
}),
|
||||
Box::new(|ui, input, osd| ui.search_state.event(input, osd)),
|
||||
Box::new(|ui, input, osd| {
|
||||
Box::new(|ui, input, _osd| ui.search_state.event(input)),
|
||||
Box::new(|ui, input, _osd| {
|
||||
ui.warp.event(
|
||||
input,
|
||||
&ui.map,
|
||||
&ui.sim,
|
||||
&mut ui.canvas,
|
||||
&mut ui.current_selection,
|
||||
osd,
|
||||
)
|
||||
}),
|
||||
Box::new(|ui, input, _osd| {
|
||||
@ -463,6 +462,8 @@ impl UI {
|
||||
self.color_picker.draw(&self.canvas, g);
|
||||
self.draw_polygon.draw(g, &self.canvas);
|
||||
self.wizard_sample.draw(g, &self.canvas);
|
||||
self.search_state.draw(g, &self.canvas);
|
||||
self.warp.draw(g, &self.canvas);
|
||||
|
||||
self.canvas.draw_osd_notification(g, osd);
|
||||
}
|
||||
|
@ -1,33 +1,37 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use keys::key_to_char;
|
||||
use piston::input::{Button, ButtonEvent, Event, Key, PressEvent, ReleaseEvent};
|
||||
use TextOSD;
|
||||
use {Canvas, GfxCtx, TextOSD};
|
||||
|
||||
// TODO right now, only a single line
|
||||
|
||||
pub struct TextBox {
|
||||
prompt: String,
|
||||
// TODO A rope would be cool.
|
||||
// TODO dont be pub
|
||||
pub line: String,
|
||||
cursor_x: usize,
|
||||
shift_pressed: bool,
|
||||
}
|
||||
|
||||
impl TextBox {
|
||||
pub fn new() -> TextBox {
|
||||
TextBox::new_prefilled(String::from(""))
|
||||
pub fn new(prompt: &str) -> TextBox {
|
||||
TextBox::new_prefilled(prompt, String::from(""))
|
||||
}
|
||||
|
||||
pub fn new_prefilled(line: String) -> TextBox {
|
||||
pub fn new_prefilled(prompt: &str, line: String) -> TextBox {
|
||||
TextBox {
|
||||
prompt: prompt.to_string(),
|
||||
line,
|
||||
cursor_x: 0,
|
||||
shift_pressed: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn populate_osd(&self, osd: &mut TextOSD) {
|
||||
pub fn draw(&self, g: &mut GfxCtx, canvas: &Canvas) {
|
||||
let mut osd = TextOSD::new();
|
||||
osd.add_highlighted_line(self.prompt.clone());
|
||||
osd.add_line_with_cursor(self.line.clone(), self.cursor_x);
|
||||
canvas.draw_centered_text(g, osd);
|
||||
}
|
||||
|
||||
// TODO a way to abort out
|
||||
|
Loading…
Reference in New Issue
Block a user