Implement color picker
This commit is contained in:
		
							parent
							
								
									761b434108
								
							
						
					
					
						commit
						1bac3dedab
					
				| 
						 | 
					@ -3,8 +3,9 @@ use crate::{
 | 
				
			||||||
    emulator::{EmulatorClient, EmulatorCommand, SimId},
 | 
					    emulator::{EmulatorClient, EmulatorCommand, SimId},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use egui::{
 | 
					use egui::{
 | 
				
			||||||
    menu, Button, CentralPanel, Color32, Context, Frame, Response, Sense, TopBottomPanel, Ui, Vec2,
 | 
					    ecolor::HexColor, menu, Align2, Button, CentralPanel, Color32, Context, Frame, Layout,
 | 
				
			||||||
    ViewportBuilder, ViewportCommand, ViewportId, WidgetText,
 | 
					    Response, Sense, TopBottomPanel, Ui, Vec2, ViewportBuilder, ViewportCommand, ViewportId,
 | 
				
			||||||
 | 
					    WidgetText, Window,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use winit::event_loop::EventLoopProxy;
 | 
					use winit::event_loop::EventLoopProxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +36,7 @@ pub struct GameWindow {
 | 
				
			||||||
    display_mode: DisplayMode,
 | 
					    display_mode: DisplayMode,
 | 
				
			||||||
    colors: [Color32; 2],
 | 
					    colors: [Color32; 2],
 | 
				
			||||||
    screen: Option<GameScreen>,
 | 
					    screen: Option<GameScreen>,
 | 
				
			||||||
 | 
					    color_picker: Option<ColorPickerState>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl GameWindow {
 | 
					impl GameWindow {
 | 
				
			||||||
| 
						 | 
					@ -46,6 +48,7 @@ impl GameWindow {
 | 
				
			||||||
            display_mode: DisplayMode::Anaglyph,
 | 
					            display_mode: DisplayMode::Anaglyph,
 | 
				
			||||||
            colors: COLOR_PRESETS[0],
 | 
					            colors: COLOR_PRESETS[0],
 | 
				
			||||||
            screen: None,
 | 
					            screen: None,
 | 
				
			||||||
 | 
					            color_picker: None,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,8 +151,26 @@ impl GameWindow {
 | 
				
			||||||
                for preset in COLOR_PRESETS {
 | 
					                for preset in COLOR_PRESETS {
 | 
				
			||||||
                    if ui.color_pair_button(preset[0], preset[1]).clicked() {
 | 
					                    if ui.color_pair_button(preset[0], preset[1]).clicked() {
 | 
				
			||||||
                        self.colors = preset;
 | 
					                        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| {
 | 
					        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 {
 | 
					impl AppWindow for GameWindow {
 | 
				
			||||||
| 
						 | 
					@ -220,6 +264,15 @@ impl AppWindow for GameWindow {
 | 
				
			||||||
                    self.show_menu(ctx, ui);
 | 
					                    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);
 | 
					        let frame = Frame::central_panel(&ctx.style()).fill(Color32::BLACK);
 | 
				
			||||||
        CentralPanel::default().frame(frame).show(ctx, |ui| {
 | 
					        CentralPanel::default().frame(frame).show(ctx, |ui| {
 | 
				
			||||||
            if let Some(screen) = self.screen.as_mut() {
 | 
					            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_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 {
 | 
					impl UiExt for Ui {
 | 
				
			||||||
| 
						 | 
					@ -283,4 +338,29 @@ impl UiExt for Ui {
 | 
				
			||||||
        self.painter().rect_stroke(rect, 0.0, style.fg_stroke);
 | 
					        self.painter().rect_stroke(rect, 0.0, style.fg_stroke);
 | 
				
			||||||
        response
 | 
					        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