Implement color picker

This commit is contained in:
Simon Gellis 2024-12-03 20:34:13 -05:00
parent 761b434108
commit 1bac3dedab
1 changed files with 82 additions and 2 deletions

View File

@ -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,
} }