use crate::stage::Stage;
use ::uxn::{Backend, Uxn};
use eframe::egui;
use varvara::Varvara;
pub struct UxnPanel<'a> {
pub stage: Stage<'a>,
focused: bool,
last_response_id: Option<egui::Id>,
}
impl<'a> UxnPanel<'a> {
pub fn last_response_id(&self) -> egui::Id {
self.last_response_id
.unwrap_or_else(|| egui::Id::new("uxn_panel_default"))
}
pub fn set_rom_bytes(&mut self, data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
self.stage.load_rom(data)
}
pub fn set_sym_bytes(&mut self, data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
self.stage.load_symbols(data)
}
pub fn set_rom_path<P: AsRef<std::path::Path>>(&mut self, path: P) {
self.stage.load_rom_with_path(path);
}
pub fn new(
_ctx: &egui::Context,
rom: Option<&[u8]>,
size: (u16, u16),
texture_name: String,
transparent: Option<String>,
) -> Self {
let ram = Box::new([0u8; 65536]);
let ram_for_leak = ram.clone();
let ram_static: &'a mut [u8; 65536] = Box::leak(ram_for_leak);
let vm = Uxn::new(ram_static, Backend::Interpreter);
let dev = Varvara::default();
let (_tx, rx) = std::sync::mpsc::channel();
let mut stage = Stage::new(
vm,
dev,
rx,
crate::stage::StageConfig {
size,
scale: 1.0,
rom_title: texture_name,
transparent,
color_transform_name: "invert".to_string(),
color_params: vec![],
effects: crate::stage::EffectsConfig {
efxt: 3.0,
effect_mode: 0,
effect_order: (0..crate::effects::EFFECT_COUNT).collect(),
efx: None,
efxmode: None,
efx_ndx: 0,
last_effect_switch: 0.0,
},
fit_mode: "contain".to_string(),
mouse_mode: crate::stage::MouseDragMode::None,
mouse_resize: crate::stage::MouseResizeMode::None,
},
None,
);
if let Some(rom) = rom {
let _ = stage.load_rom(rom);
}
Self {
stage,
focused: false,
last_response_id: None,
}
}
pub fn is_focused(&self) -> bool {
self.focused
}
pub fn handle_input(&mut self, input: &egui::InputState, rect: egui::Rect) {
self.stage.handle_input(input, rect);
}
pub fn show(&mut self, ui: &mut egui::Ui) -> egui::Response {
let panel_size =
egui::Vec2::new(self.stage.size.0 as f32, self.stage.size.1 as f32) * self.stage.scale;
let (rect_id, rect) = ui.allocate_space(panel_size);
let response = ui.interact(rect, rect_id, egui::Sense::click_and_drag());
if response.clicked() {
response.request_focus();
}
let input = ui.ctx().input(|i| i.clone());
if response.hovered() {
self.stage
.handle_mouse_input(ui.ctx(), &input, &response, rect);
}
self.focused = response.has_focus();
if self.focused {
self.stage.handle_input(&input, rect);
self.stage.handle_usb_input();
}
self.stage.step();
self.stage.update_texture(ui.ctx());
self.stage.draw_at(ui, rect);
self.last_response_id = Some(response.id);
response
}
}