Implement color picker
This commit is contained in:
		
							parent
							
								
									761b434108
								
							
						
					
					
						commit
						1bac3dedab
					
				| 
						 | 
				
			
			@ -3,8 +3,9 @@ use crate::{
 | 
			
		|||
    emulator::{EmulatorClient, EmulatorCommand, SimId},
 | 
			
		||||
};
 | 
			
		||||
use egui::{
 | 
			
		||||
    menu, Button, CentralPanel, Color32, Context, Frame, Response, Sense, TopBottomPanel, Ui, Vec2,
 | 
			
		||||
    ViewportBuilder, ViewportCommand, ViewportId, WidgetText,
 | 
			
		||||
    ecolor::HexColor, menu, Align2, Button, CentralPanel, Color32, Context, Frame, Layout,
 | 
			
		||||
    Response, Sense, TopBottomPanel, Ui, Vec2, ViewportBuilder, ViewportCommand, ViewportId,
 | 
			
		||||
    WidgetText, Window,
 | 
			
		||||
};
 | 
			
		||||
use winit::event_loop::EventLoopProxy;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,7 @@ pub struct GameWindow {
 | 
			
		|||
    display_mode: DisplayMode,
 | 
			
		||||
    colors: [Color32; 2],
 | 
			
		||||
    screen: Option<GameScreen>,
 | 
			
		||||
    color_picker: Option<ColorPickerState>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl GameWindow {
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +48,7 @@ impl GameWindow {
 | 
			
		|||
            display_mode: DisplayMode::Anaglyph,
 | 
			
		||||
            colors: COLOR_PRESETS[0],
 | 
			
		||||
            screen: None,
 | 
			
		||||
            color_picker: None,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -148,8 +151,26 @@ impl GameWindow {
 | 
			
		|||
                for preset in COLOR_PRESETS {
 | 
			
		||||
                    if ui.color_pair_button(preset[0], preset[1]).clicked() {
 | 
			
		||||
                        self.colors = preset;
 | 
			
		||||
                        ui.close_menu();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                ui.with_layout(ui.layout().with_cross_align(egui::Align::Center), |ui| {
 | 
			
		||||
                    if ui.button("Custom").clicked() {
 | 
			
		||||
                        let color_str = |color: Color32| {
 | 
			
		||||
                            format!("{:02x}{:02x}{:02x}", color.r(), color.g(), color.b())
 | 
			
		||||
                        };
 | 
			
		||||
                        let is_running = self.client.is_running(self.sim_id);
 | 
			
		||||
                        if is_running {
 | 
			
		||||
                            self.client.send_command(EmulatorCommand::Pause);
 | 
			
		||||
                        }
 | 
			
		||||
                        self.color_picker = Some(ColorPickerState {
 | 
			
		||||
                            color_codes: [color_str(self.colors[0]), color_str(self.colors[1])],
 | 
			
		||||
                            just_opened: true,
 | 
			
		||||
                            unpause_on_close: is_running,
 | 
			
		||||
                        });
 | 
			
		||||
                        ui.close_menu();
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        ui.menu_button("Audio", |ui| {
 | 
			
		||||
| 
						 | 
				
			
			@ -195,6 +216,29 @@ impl GameWindow {
 | 
			
		|||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn show_color_picker(&mut self, ui: &mut Ui) {
 | 
			
		||||
        let Some(state) = self.color_picker.as_mut() else {
 | 
			
		||||
            return;
 | 
			
		||||
        };
 | 
			
		||||
        let open = ui
 | 
			
		||||
            .horizontal(|ui| {
 | 
			
		||||
                let left_color = ui.color_picker(&mut self.colors[0], &mut state.color_codes[0]);
 | 
			
		||||
                if state.just_opened {
 | 
			
		||||
                    left_color.request_focus();
 | 
			
		||||
                    state.just_opened = false;
 | 
			
		||||
                }
 | 
			
		||||
                let right_color = ui.color_picker(&mut self.colors[1], &mut state.color_codes[1]);
 | 
			
		||||
                left_color.has_focus() || right_color.has_focus()
 | 
			
		||||
            })
 | 
			
		||||
            .inner;
 | 
			
		||||
        if !open {
 | 
			
		||||
            if state.unpause_on_close {
 | 
			
		||||
                self.client.send_command(EmulatorCommand::Resume);
 | 
			
		||||
            }
 | 
			
		||||
            self.color_picker = None;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl AppWindow for GameWindow {
 | 
			
		||||
| 
						 | 
				
			
			@ -220,6 +264,15 @@ impl AppWindow for GameWindow {
 | 
			
		|||
                    self.show_menu(ctx, ui);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        if self.color_picker.is_some() {
 | 
			
		||||
            Window::new("Color Picker")
 | 
			
		||||
                .title_bar(false)
 | 
			
		||||
                .resizable(false)
 | 
			
		||||
                .anchor(Align2::CENTER_CENTER, Vec2::ZERO)
 | 
			
		||||
                .show(ctx, |ui| {
 | 
			
		||||
                    self.show_color_picker(ui);
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
        let frame = Frame::central_panel(&ctx.style()).fill(Color32::BLACK);
 | 
			
		||||
        CentralPanel::default().frame(frame).show(ctx, |ui| {
 | 
			
		||||
            if let Some(screen) = self.screen.as_mut() {
 | 
			
		||||
| 
						 | 
				
			
			@ -259,6 +312,8 @@ trait UiExt {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    fn color_pair_button(&mut self, left: Color32, right: Color32) -> Response;
 | 
			
		||||
 | 
			
		||||
    fn color_picker(&mut self, color: &mut Color32, hex: &mut String) -> Response;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl UiExt for Ui {
 | 
			
		||||
| 
						 | 
				
			
			@ -283,4 +338,29 @@ impl UiExt for Ui {
 | 
			
		|||
        self.painter().rect_stroke(rect, 0.0, style.fg_stroke);
 | 
			
		||||
        response
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn color_picker(&mut self, color: &mut Color32, hex: &mut String) -> Response {
 | 
			
		||||
        self.allocate_ui_with_layout(
 | 
			
		||||
            Vec2::new(100.0, 130.0),
 | 
			
		||||
            Layout::top_down_justified(egui::Align::Center),
 | 
			
		||||
            |ui| {
 | 
			
		||||
                let (rect, _) = ui.allocate_at_least(Vec2::new(100.0, 100.0), Sense::hover());
 | 
			
		||||
                ui.painter().rect_filled(rect, 0.0, *color);
 | 
			
		||||
                let resp = ui.text_edit_singleline(hex);
 | 
			
		||||
                if resp.changed() {
 | 
			
		||||
                    if let Ok(new_color) = HexColor::from_str_without_hash(hex) {
 | 
			
		||||
                        *color = new_color.color();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                resp
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
        .inner
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ColorPickerState {
 | 
			
		||||
    color_codes: [String; 2],
 | 
			
		||||
    just_opened: bool,
 | 
			
		||||
    unpause_on_close: bool,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue