summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 14e3925f9ebc178f7675a2d82dc52586b49eb27d (plain)
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();
}