Adds ComputerManager so no write access to the computer directly happens.
ComputerManager has a thread to run the CPU whenever its told to either step or run. It can be told to stop the CPU too. Cycle count and keystate feedback is available along with read-only of the computer from status()
This commit is contained in:
parent
902d5c1875
commit
d829b9f03f
@ -81,6 +81,7 @@ impl Chip8Computer {
|
|||||||
let new_location = current_index + offset;
|
let new_location = current_index + offset;
|
||||||
self.memory.poke(new_location, new_value);
|
self.memory.poke(new_location, new_value);
|
||||||
}
|
}
|
||||||
|
self.registers.set_pc(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step_system(&mut self) -> &mut Chip8Computer {
|
pub fn step_system(&mut self) -> &mut Chip8Computer {
|
||||||
|
|||||||
127
gemma/src/chip8/computer_manager.rs
Normal file
127
gemma/src/chip8/computer_manager.rs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
use std::sync::mpsc::{channel, Sender};
|
||||||
|
use std::thread;
|
||||||
|
use std::thread::{sleep, JoinHandle, Thread};
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
use crate::chip8::computer::Chip8Computer;
|
||||||
|
use crate::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction;
|
||||||
|
|
||||||
|
pub enum ManagerDumpables {
|
||||||
|
Video,
|
||||||
|
Registers,
|
||||||
|
Keyboard
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Chip8ComputerManager {
|
||||||
|
pub core_should_run: bool,
|
||||||
|
pub one_step: bool,
|
||||||
|
pub core_cycle_timer: bool,
|
||||||
|
pub core_last_cycle_start: Instant,
|
||||||
|
computer: Chip8Computer
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Chip8ComputerManager {
|
||||||
|
fn default() -> Self {
|
||||||
|
Chip8ComputerManager {
|
||||||
|
core_should_run: false,
|
||||||
|
one_step: true,
|
||||||
|
core_cycle_timer: false,
|
||||||
|
core_last_cycle_start: Instant::now() ,
|
||||||
|
computer: Chip8Computer::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Chip8ComputerManager {
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.computer.reset();
|
||||||
|
}
|
||||||
|
pub fn new() -> Chip8ComputerManager {
|
||||||
|
let core_handle = thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
let start_time = Instant::now();
|
||||||
|
println!("Core Thread starting at {start_time:?}");
|
||||||
|
|
||||||
|
|
||||||
|
let sleep_time = Instant::now().duration_since(start_time).as_millis();
|
||||||
|
println!("Core Thread sleeping for {sleep_time}ms");
|
||||||
|
sleep(Duration::from_millis((16 - sleep_time) as u64));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Chip8ComputerManager::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(managed: &mut Chip8ComputerManager) {
|
||||||
|
managed.core_should_run = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop(managed: &mut Chip8ComputerManager) {
|
||||||
|
managed.core_should_run = false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(managed: &mut Chip8ComputerManager) {
|
||||||
|
managed.one_step = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn state(&mut self) -> &Chip8Computer {
|
||||||
|
&self.computer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick( &mut self) {
|
||||||
|
println!("STARTING TICK");
|
||||||
|
if self.one_step | self.core_should_run {
|
||||||
|
self.core_last_cycle_start = Instant::now();
|
||||||
|
self.computer.step_system();
|
||||||
|
println!("SYSTEM STEP");
|
||||||
|
};
|
||||||
|
if self.one_step {
|
||||||
|
println!("SYSTEM HALTED AFTER 1 STEP");
|
||||||
|
// stop the CPU for the next cycle, we are only
|
||||||
|
// wanting one step.
|
||||||
|
self.one_step = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn press_key(&mut self, key_index: u8) {
|
||||||
|
self.computer.keypad.push_key(key_index);
|
||||||
|
}
|
||||||
|
pub fn release_key(&mut self, key_index: u8) {
|
||||||
|
self.computer.keypad.release_key(key_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sound(managed: &Chip8ComputerManager) -> bool {
|
||||||
|
managed.computer.sound_timer.current() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait_for_instruction(&mut self) {
|
||||||
|
self.computer.state = WaitingForInstruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_key_pressed(&self, key_index: u8) -> bool {
|
||||||
|
self.computer.keypad.pressed(key_index)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_cycles(&self) -> i32 {
|
||||||
|
self.computer.num_cycles
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_bytes_to_system_memory(&mut self, bytes_to_load: Vec<u8>) {
|
||||||
|
self.computer.load_bytes_to_memory(0x200, &bytes_to_load);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump_to_string(&self, dump_type: ManagerDumpables) -> String {
|
||||||
|
match dump_type {
|
||||||
|
ManagerDumpables::Video => {
|
||||||
|
self.computer.video_memory.format_as_string()
|
||||||
|
}
|
||||||
|
ManagerDumpables::Registers => {
|
||||||
|
self.computer.registers.format_as_string()
|
||||||
|
}
|
||||||
|
ManagerDumpables::Keyboard => {
|
||||||
|
self.computer.keypad.format_as_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
use log::{debug, trace};
|
use log::{debug};
|
||||||
use crate::constants::{CHIP8_VIDEO_MEMORY, CHIP8_VIDEO_WIDTH};
|
use crate::constants::{CHIP8_VIDEO_MEMORY, CHIP8_VIDEO_WIDTH};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -85,12 +85,7 @@ impl Chip8Video {
|
|||||||
|
|
||||||
impl Default for Chip8Video {
|
impl Default for Chip8Video {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
debug!("DEFAULT VIDEO PREPARED");
|
Chip8Video { memory: [false; CHIP8_VIDEO_MEMORY], has_frame_changed: false }
|
||||||
|
|
||||||
let new_struct = Chip8Video { memory: [false; CHIP8_VIDEO_MEMORY], has_frame_changed: false };
|
|
||||||
println!("NEW DEFAULT MEMORY : {}", new_struct.format_as_string());
|
|
||||||
|
|
||||||
new_struct.clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,8 @@ pub mod chip8 {
|
|||||||
pub mod registers;
|
pub mod registers;
|
||||||
|
|
||||||
pub mod stack;
|
pub mod stack;
|
||||||
|
|
||||||
|
pub mod computer_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
@ -1,11 +1,12 @@
|
|||||||
|
use std::ops::Range;
|
||||||
|
use gemma::chip8::computer_manager::Chip8ComputerManager;
|
||||||
|
|
||||||
pub struct GemmaEGuiState {
|
pub struct GemmaEGuiState {
|
||||||
pub display_video: bool,
|
pub display_video: bool,
|
||||||
pub display_memory: bool,
|
pub display_memory: bool,
|
||||||
pub display_registers: bool,
|
pub display_registers: bool,
|
||||||
pub memory_view_min: i32,
|
pub memory_view: Range<i32>,
|
||||||
pub memory_view_max: i32,
|
pub computer: Chip8ComputerManager,
|
||||||
pub is_running: bool,
|
|
||||||
pub selected_rom_filename: String
|
pub selected_rom_filename: String
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,9 +16,8 @@ impl Default for GemmaEGuiState {
|
|||||||
display_video: true,
|
display_video: true,
|
||||||
display_memory: true,
|
display_memory: true,
|
||||||
display_registers: true,
|
display_registers: true,
|
||||||
memory_view_min: 0x00,
|
memory_view: 0x00..0x200,
|
||||||
memory_view_max: 0x100,
|
computer: Chip8ComputerManager::new(),
|
||||||
is_running: false,
|
|
||||||
selected_rom_filename: String::new()
|
selected_rom_filename: String::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ use gemma::{
|
|||||||
use imgui::*;
|
use imgui::*;
|
||||||
use sys::{ImColor, ImVec2, ImVector_ImU32};
|
use sys::{ImColor, ImVec2, ImVector_ImU32};
|
||||||
use rand::random;
|
use rand::random;
|
||||||
|
use gemma::chip8::computer_manager::Chip8ComputerManager;
|
||||||
use gemma::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction;
|
use gemma::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction;
|
||||||
use gemma::chip8::system_memory::Chip8SystemMemory;
|
use gemma::chip8::system_memory::Chip8SystemMemory;
|
||||||
use support::{emmagui_support::GemmaImguiSupport, ui_state::ImGuiUiState};
|
use support::{emmagui_support::GemmaImguiSupport, ui_state::ImGuiUiState};
|
||||||
@ -27,7 +28,7 @@ const LIN_KEYS: [(u16, u8); 0x10] = [(537, 0x01),(538, 0x02),(539, 0x03),(540, 0
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
let mut system = Chip8Computer::default();
|
let mut system = Chip8ComputerManager::default();
|
||||||
let mut ui_state = ImGuiUiState::default();
|
let mut ui_state = ImGuiUiState::default();
|
||||||
|
|
||||||
support::simple_init(file!(), move |_, ui| {
|
support::simple_init(file!(), move |_, ui| {
|
||||||
@ -35,61 +36,51 @@ fn main() {
|
|||||||
|
|
||||||
// Key Checks
|
// Key Checks
|
||||||
let down_keys = ui.io().keys_down;
|
let down_keys = ui.io().keys_down;
|
||||||
|
|
||||||
|
// START DEBUG CODE TO DISPLAY WHAT KEYS WE TRAPPED
|
||||||
for (idx, val) in down_keys.iter().enumerate() {
|
for (idx, val) in down_keys.iter().enumerate() {
|
||||||
if *val {
|
if *val {
|
||||||
println!("{idx} = {val}");
|
println!("{idx} = {val}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// END DEBUG CODE
|
||||||
|
|
||||||
|
|
||||||
for (key_code, key_reg) in LIN_KEYS {
|
for (key_code, key_reg) in LIN_KEYS {
|
||||||
if down_keys[key_code as usize] {
|
if down_keys[key_code as usize] {
|
||||||
system.keypad.push_key(key_reg);
|
system.press_key(key_reg);
|
||||||
system.state = WaitingForInstruction;
|
system.press_key(key_reg);
|
||||||
|
system.wait_for_instruction();
|
||||||
} else {
|
} else {
|
||||||
// do we need to release it?
|
// do we need to release it?
|
||||||
if system.keypad.pressed(key_reg) {
|
|
||||||
system.keypad.release_key(key_reg);
|
if system.is_key_pressed(key_reg) {
|
||||||
|
system.release_key(key_reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next Tick Check
|
system.tick();
|
||||||
let time_since_last_tick = current_time.duration_since(ui_state.last_frame_instant).as_millis();
|
|
||||||
if ui_state.is_running && time_since_last_tick > ui_state.frame_time as u128 {
|
|
||||||
match system.state {
|
|
||||||
gemma::chip8::cpu_states::Chip8CpuStates::WaitingForInstruction => {
|
|
||||||
// this is the 'regular' mode for the CPU when we get here
|
|
||||||
system.step_system();
|
|
||||||
},
|
|
||||||
gemma::chip8::cpu_states::Chip8CpuStates::WaitingForKey => {
|
|
||||||
// waiting for a keychange...
|
|
||||||
},
|
|
||||||
gemma::chip8::cpu_states::Chip8CpuStates::ExecutingInstruction => { // should never see this.
|
|
||||||
},
|
|
||||||
gemma::chip8::cpu_states::Chip8CpuStates::Error => {
|
|
||||||
panic!("System in undefined state.");
|
|
||||||
},
|
|
||||||
}
|
|
||||||
ui_state.last_frame_instant = current_time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GUI Parts
|
// GUI Parts
|
||||||
if ui_state.show_video {
|
if ui_state.show_video {
|
||||||
GemmaImguiSupport::video_display(&system, &ui_state, ui);
|
GemmaImguiSupport::video_display(&system.state(), &ui_state, ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
GemmaImguiSupport::system_controls(&mut system, &mut ui_state, ui);
|
GemmaImguiSupport::system_controls(&mut system, &mut ui_state, ui);
|
||||||
|
|
||||||
if ui_state.show_registers {
|
if ui_state.show_registers {
|
||||||
GemmaImguiSupport::registers_view(&system, ui);
|
GemmaImguiSupport::registers_view(&system.state(), ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui_state.show_memory {
|
if ui_state.show_memory {
|
||||||
let active_instruction = system.registers.peek_pc();
|
let active_instruction = system.state().registers.peek_pc();
|
||||||
GemmaImguiSupport::hex_memory_display(system.memory.clone(), (0x100, 0x10), active_instruction as i16, ui);
|
GemmaImguiSupport::hex_memory_display(system.state().memory.clone(), (0x100, 0x10), active_instruction as i16, ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui_state.show_keypad {
|
if ui_state.show_keypad {
|
||||||
GemmaImguiSupport::keypad_display(&system, ui);
|
GemmaImguiSupport::keypad_display(&system.state(), ui);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,13 @@ use std::time::Duration;
|
|||||||
use imgui::{Condition, ImColor32, Ui};
|
use imgui::{Condition, ImColor32, Ui};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use gemma::chip8::computer::Chip8Computer;
|
use gemma::chip8::computer::Chip8Computer;
|
||||||
|
use gemma::chip8::computer_manager::Chip8ComputerManager;
|
||||||
|
use gemma::chip8::computer_manager::ManagerDumpables::{Keyboard, Registers, Video};
|
||||||
|
use gemma::chip8::keypad::Keypad;
|
||||||
use gemma::chip8::system_memory::Chip8SystemMemory;
|
use gemma::chip8::system_memory::Chip8SystemMemory;
|
||||||
use gemma::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH};
|
use gemma::constants::{CHIP8_VIDEO_HEIGHT, CHIP8_VIDEO_WIDTH};
|
||||||
use crate::ImGuiUiState;
|
use crate::ImGuiUiState;
|
||||||
|
use crate::support::gui_file_list::GuiFileList;
|
||||||
use super::ui_state;
|
use super::ui_state;
|
||||||
|
|
||||||
pub struct GemmaImguiSupport {}
|
pub struct GemmaImguiSupport {}
|
||||||
@ -18,35 +21,6 @@ pub struct GemmaImguiSupport {}
|
|||||||
const CELL_WIDTH: i32 = 5i32;
|
const CELL_WIDTH: i32 = 5i32;
|
||||||
const CELL_HEIGHT: i32 = 5i32;
|
const CELL_HEIGHT: i32 = 5i32;
|
||||||
|
|
||||||
struct GuiFileList {}
|
|
||||||
|
|
||||||
impl GuiFileList {
|
|
||||||
pub fn display_path(root: PathBuf, selected_filename: &String, ui: &Ui) -> String {
|
|
||||||
let mut working_filename = selected_filename.clone();
|
|
||||||
ui.text(format!("Displaying {}", root.to_str().unwrap_or("Unable to parse path")));
|
|
||||||
|
|
||||||
let mut known_files: Vec<OsString> = vec![];
|
|
||||||
|
|
||||||
for entry in read_dir(root.as_path()).unwrap() {
|
|
||||||
known_files.push(entry.unwrap().file_name());
|
|
||||||
}
|
|
||||||
|
|
||||||
known_files.sort();
|
|
||||||
|
|
||||||
for (index, entry) in known_files.iter().enumerate() {
|
|
||||||
let mut working_select = ui.selectable_config(format!("{}", entry.clone().into_string().unwrap()));
|
|
||||||
if entry.to_str().unwrap().to_string() == selected_filename.as_str().to_string() {
|
|
||||||
working_select = working_select.selected(true);
|
|
||||||
}
|
|
||||||
if working_select.build() {
|
|
||||||
debug!("SELECTED {index} / {entry:?}");
|
|
||||||
working_filename = entry.clone().into_string().unwrap();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
working_filename
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GemmaImguiSupport {
|
impl GemmaImguiSupport {
|
||||||
pub fn keypad_display(system_to_display: &Chip8Computer, ui: &Ui) {
|
pub fn keypad_display(system_to_display: &Chip8Computer, ui: &Ui) {
|
||||||
ui.text("Keypad");
|
ui.text("Keypad");
|
||||||
@ -96,12 +70,13 @@ impl GemmaImguiSupport {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
pub fn system_controls(system_to_control: &mut Chip8Computer, gui_state: &mut ImGuiUiState, ui: &Ui) {
|
pub fn system_controls(system_to_control: &mut Chip8ComputerManager, gui_state: &mut ImGuiUiState, ui: &Ui) {
|
||||||
|
// let mut state: Chip8Computer = system_to_control;
|
||||||
ui.window("!!!! CONTROLS !!!!")
|
ui.window("!!!! CONTROLS !!!!")
|
||||||
.size([345.0, 200.0], Condition::FirstUseEver)
|
.size([345.0, 200.0], Condition::FirstUseEver)
|
||||||
.build(|| {
|
.build(|| {
|
||||||
/* System Step Counter */
|
/* System Step Counter */
|
||||||
ui.text(format!("Step {:04x}", system_to_control.num_cycles).as_str());
|
ui.text(format!("Step {:04x}", system_to_control.num_cycles()).as_str());
|
||||||
|
|
||||||
/* ROM Lister */
|
/* ROM Lister */
|
||||||
let new_filename = GuiFileList::display_path(PathBuf::from("resources/roms"), &gui_state.filename_to_load, ui);
|
let new_filename = GuiFileList::display_path(PathBuf::from("resources/roms"), &gui_state.filename_to_load, ui);
|
||||||
@ -112,43 +87,39 @@ impl GemmaImguiSupport {
|
|||||||
}
|
}
|
||||||
if ui.button("Load Program") {
|
if ui.button("Load Program") {
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
|
|
||||||
debug!("PREPARING TO LOAD {}", gui_state.filename_to_load);
|
debug!("PREPARING TO LOAD {}", gui_state.filename_to_load);
|
||||||
// let mut input_file = File::open(Path::new("./1-chip8-logo.ch8")).expect("put 1-chip8-logo.ch8 in this directory");
|
// let mut input_file = File::open(Path::new("./1-chip8-logo.ch8")).expect("put 1-chip8-logo.ch8 in this directory");
|
||||||
let mut input_file = File::open(Path::new(&("resources/roms/".to_string() + &gui_state.filename_to_load))).expect("put 1-chip8-logo.ch8 in this directory");
|
let mut input_file = File::open(Path::new(&("resources/roms/".to_string() + &gui_state.filename_to_load))).expect("put 1-chip8-logo.ch8 in this directory");
|
||||||
input_file.read_to_end(&mut buffer).expect("unable to read file");
|
input_file.read_to_end(&mut buffer).expect("unable to read file");
|
||||||
system_to_control.load_bytes_to_memory(0x200, (&buffer).into());
|
system_to_control.load_bytes_to_system_memory((&*buffer).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
if ui.button("Step") {
|
if ui.button("Step") {
|
||||||
system_to_control.step_system();
|
system_to_control.one_step = true;
|
||||||
};
|
};
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
if ui.button("Run") {
|
if ui.button("Run") {
|
||||||
gui_state.is_running = true;
|
system_to_control.core_should_run = true;
|
||||||
debug!("STARTING THE SYSTEM");
|
|
||||||
}
|
}
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
if ui.button("Stop") {
|
if ui.button("Stop") {
|
||||||
gui_state.is_running = false;
|
system_to_control.core_should_run = false;
|
||||||
debug!("STOPPING THE SYSTEM");
|
|
||||||
}
|
}
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
if ui.button("Reset") {
|
if ui.button("Reset") {
|
||||||
gui_state.is_running = false;
|
system_to_control.reset();
|
||||||
*system_to_control = Chip8Computer::new();
|
|
||||||
}
|
}
|
||||||
if ui.button("Dump Video Memory") {
|
if ui.button("Dump Video Memory") {
|
||||||
println!("{}", system_to_control.dump_video_to_string());
|
println!("{}", system_to_control.dump_to_string(Video));
|
||||||
}
|
}
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
if ui.button("Dump Keypad State") {
|
if ui.button("Dump Keypad State") {
|
||||||
debug!("{}", system_to_control.dump_keypad_to_string());
|
debug!("{}", system_to_control.dump_to_string(Keyboard));
|
||||||
}
|
}
|
||||||
ui.same_line();
|
ui.same_line();
|
||||||
if ui.button("Dump Registers") {
|
if ui.button("Dump Registers") {
|
||||||
debug!("{}", system_to_control.dump_registers_to_string());
|
debug!("{}", system_to_control.dump_to_string(Registers));
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
|
|||||||
34
gemmaimgui/src/bin/support/gui_file_list.rs
Normal file
34
gemmaimgui/src/bin/support/gui_file_list.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use std::ffi::OsString;
|
||||||
|
use std::fs::read_dir;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use imgui::Ui;
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
|
pub struct GuiFileList {}
|
||||||
|
|
||||||
|
impl GuiFileList {
|
||||||
|
pub fn display_path(root: PathBuf, selected_filename: &String, ui: &Ui) -> String {
|
||||||
|
let mut working_filename = selected_filename.clone();
|
||||||
|
ui.text(format!("Displaying {}", root.to_str().unwrap_or("Unable to parse path")));
|
||||||
|
|
||||||
|
let mut known_files: Vec<OsString> = vec![];
|
||||||
|
|
||||||
|
for entry in read_dir(root.as_path()).unwrap() {
|
||||||
|
known_files.push(entry.unwrap().file_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
known_files.sort();
|
||||||
|
|
||||||
|
for (index, entry) in known_files.iter().enumerate() {
|
||||||
|
let mut working_select = ui.selectable_config(format!("{}", entry.clone().into_string().unwrap()));
|
||||||
|
if entry.to_str().unwrap().to_string() == selected_filename.as_str().to_string() {
|
||||||
|
working_select = working_select.selected(true);
|
||||||
|
}
|
||||||
|
if working_select.build() {
|
||||||
|
debug!("SELECTED {index} / {entry:?}");
|
||||||
|
working_filename = entry.clone().into_string().unwrap();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
working_filename
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,6 @@ use glium::glutin::surface::WindowSurface;
|
|||||||
use glium::{Display, Surface};
|
use glium::{Display, Surface};
|
||||||
use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui};
|
use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui};
|
||||||
use imgui_glium_renderer::Renderer;
|
use imgui_glium_renderer::Renderer;
|
||||||
use imgui_winit_support::winit::dpi::LogicalSize;
|
|
||||||
use imgui_winit_support::winit::event::{Event, WindowEvent};
|
use imgui_winit_support::winit::event::{Event, WindowEvent};
|
||||||
use imgui_winit_support::winit::event_loop::EventLoop;
|
use imgui_winit_support::winit::event_loop::EventLoop;
|
||||||
use imgui_winit_support::winit::window::WindowBuilder;
|
use imgui_winit_support::winit::window::WindowBuilder;
|
||||||
@ -12,6 +11,8 @@ use std::time::Instant;
|
|||||||
|
|
||||||
pub mod ui_state;
|
pub mod ui_state;
|
||||||
pub mod emmagui_support;
|
pub mod emmagui_support;
|
||||||
|
mod gui_file_list;
|
||||||
|
|
||||||
use copypasta::{ClipboardContext, ClipboardProvider};
|
use copypasta::{ClipboardContext, ClipboardProvider};
|
||||||
use imgui::ClipboardBackend;
|
use imgui::ClipboardBackend;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user