use std::time::SystemTime;
use crossterm::{event::KeyCode, style::ContentStyle};
use mimalloc::MiMalloc;
use tortuise::{
buffer::{Buffer, Cell, Event},
file::FileManager,
input::InputManager,
scene::switch_scenes,
script::{ScriptContext, ScriptDeclaration, ScriptManager},
};
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
fn get_timestamp() -> u128 {
SystemTime::UNIX_EPOCH.elapsed().unwrap().as_nanos()
}
fn init_first_frame<'a>(_: &mut ScriptContext<'a>, state: &mut Box<[u8]>) {
*state = Box::from(get_timestamp().to_ne_bytes());
}
fn render_frame_rate<'a>(ctx: &mut ScriptContext<'a>, state: &mut Box<[u8]>) {
puffin::profile_function!();
ctx.buffer.cells.clear();
let end = get_timestamp();
let last_frame_start = u128::from_ne_bytes(*state.as_array().unwrap());
let frame_time = end - last_frame_start + 1;
let digits = [
frame_time % 1_000_000 / 100_000,
frame_time % 100_000 / 10_000,
frame_time % 10_000 / 1_000,
frame_time % 1_000 / 100,
frame_time % 100 / 10,
frame_time % 10,
];
for (x, digit) in digits.into_iter().enumerate() {
ctx.buffer.cells.push(Cell {
character: char::from_digit(digit as u32, 10).unwrap(),
x: x as u16,
y: 0,
z: 0,
style: ContentStyle::new(),
});
}
*state = Box::from(end.to_ne_bytes());
}
fn exit_on_escape(ctx: &mut ScriptContext, _: &mut Box<[u8]>) {
puffin::profile_function!();
if ctx.input.is_key_pressed_this_frame(KeyCode::Esc) {
ctx.exit();
}
}
fn main() {
let stdout = Box::new(std::io::stdout().lock());
let mut buffer = Buffer::new(stdout).unwrap();
let mut input = InputManager::new();
let mut context = ScriptContext {
buffer: &mut buffer,
input: &input,
};
let scripts = [
ScriptDeclaration::Static {
start: Some(init_first_frame),
update: Some(render_frame_rate),
end: None,
},
ScriptDeclaration::Static {
start: None,
update: Some(exit_on_escape),
end: None,
},
];
let mut scripts = ScriptManager::new(&scripts);
let mut files = FileManager::default();
let manifest = files
.load_file(Box::from("manifest.toml".as_ref()))
.unwrap()
.unwrap_manifest()
.clone();
switch_scenes(
&manifest.scenes,
&mut scripts,
&mut context,
&mut files,
manifest.first_scene,
);
let server_addr = format!("127.0.0.1:{}", puffin_http::DEFAULT_PORT);
let _puffin_server = puffin_http::Server::new(&server_addr).unwrap();
puffin::set_scopes_on(true);
buffer
.render_loop(|buffer, event| match event {
Event::Key(event) => {
if event.is_press() {
input.press_key(event.code);
}
}
Event::Render => {
let mut context = ScriptContext {
buffer,
input: &input,
};
scripts.run_scripts(&mut context);
input.reset_next_frame();
puffin::GlobalProfiler::lock().new_frame();
}
})
.unwrap();
}
|