This commit is contained in:
deepCurse 2025-02-05 11:34:55 -04:00
parent fd8b343683
commit 4c0fa9e6ee
Signed by: u1
GPG key ID: AD770D25A908AFF4
29 changed files with 2812 additions and 1172 deletions

960
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@
name = "minemod"
version = "0.1.0"
edition = "2024"
default-run = "minemod"
[package.metadata.vita]
title_id = "PKDC10002"
@ -52,29 +53,46 @@ tracing = { version = "0.1.41", features = [
] }
tracing-subscriber = "0.3.19"
log = "0.4.25"
pretty_env_logger = "0.5.0"
anyhow = "1.0.95"
thiserror = "2.0.11"
cgmath = "0.18.0"
png = "0.17.16"
glam = "0.29.2"
#image_full = { package = "image", version = "0.25.5" }
#image = { version = "0.25.5", default-features = false }
#image_dds = "0.7.1"
tbc = "0.3.0"
png = "0.17.16" # temporary
tobj = { version = "4.0.2", features = ["log"] }
rand = "0.9.0"
[target.'cfg(any(target_os = "windows",target_os = "linux",target_os = "macos"))'.dependencies]
tokio = { version = "1.43.0", features = ["full"] }
glfw = "0.59.0"
#glfw = {version = "0.59.0", default-features = false, features = ["raw-window-handle-v0-6"]} # we literally just need the window management parts # nevermind this crashes immediately
## OPENGL
glutin = "0.32.2"
glutin-winit = "0.5.0"
#glutin-winit = "0.5.0" # no winit >:(
raw-window-handle = "0.6.2"
winit = { version = "0.30.0", features = ["rwh_06"] }
drm = "0.14.1"
# winit is hereby banished from this realm because it pissed me off >:(
# its designed around mobile and desktop, but its mobile side sticks around even when its only being used for desktop and theres no way to cut it out
# on top of its piss poor documentation around the breaking changes in update 0.3
#winit = { version = "0.30.0", features = ["rwh_06"] }
#drm = "0.14.1" # unix only
## END OPENGL
## VULKAN
vulkanalia = { version = "0.26.0", features = [
"libloading",
"provisional",
"window",
] }
# kept for now so the vulkan demo works (also the tutorial is using it so once the tutorial is done and i fully understand how vulkan works i will be tossing winit fully and reworking the vulkan structure to better suit the engine)
old_winit = { package = "winit", version = "0.29" } # dont update, many many breaking changes with no guides
ctrlc = "3.4.5"
tokio = { version = "1.43.0", features = ["full"] }
## END VULKAN
[target.'cfg(target_family = "wasm")'.dependencies]
wgpu = "24.0.0"
@ -83,7 +101,6 @@ wgpu = "24.0.0"
vitasdk-sys = { version = "0.3.3", features = ["all-stubs"] }
concat-idents = "1.1.5"
libc = "0.2.153"
rand = "0.8.5"
tokio = { version = "1.36.0", features = [
"fs",
"macros",
@ -98,6 +115,8 @@ tokio = { version = "1.36.0", features = [
] }
[target.'cfg(target_os = "windows")'.dependencies]
gfx-backend-dx12 = "0.9.1"
gfx-backend-dx11 = "0.9.0"
[target.'cfg(target_os = "linux")'.dependencies]

9
src/bin/bcntool.rs Normal file
View file

@ -0,0 +1,9 @@
use log::*;
// This tool will be used to convert any common image format to BCn of a specified level or BC1 by default.
fn main() {
pretty_env_logger::formatted_timed_builder().filter_level(LevelFilter::Info).init();
info!("We support BC1, BC3, and BC4 via the tbc crate.");
info!("Unfortunately this tool is not currently implemented.");
unimplemented!();
}

View file

@ -1,16 +1,104 @@
pub(crate) trait GraphicsCommander {}
use std::collections::HashMap;
use glam::Vec3;
use crate::graphics_engines::Renderable;
pub struct Cataclysm {
game_objects:Vec<GameObject>,
pub chunks:HashMap<(u32, u32, u32), CataclysmChunk>,
}
pub struct GameObject {
pos:(f64, f64, f64),
pub struct CataclysmChunk {
pub simple_blocks:HashMap<(u8, u8, u8), SimpleBlock>,
pub fancy_blocks: HashMap<Vec3, FancyBlock>,
pub smart_blocks: HashMap<Vec3, SmartBlock>,
pub entities: Vec<Entity>,
}
pub enum ModelKind {
Cube,
Complex(),
impl Cataclysm {
pub const CHUNK_SIZE:u8 = 32;
pub const ENTITY_RUN_LIMIT:u8 = 5;
pub const WORLD_SIZE:(u8, u8) = (2, 2);
pub fn new() -> Self {
Self {
chunks: HashMap::new()
}
}
}
pub struct ResourceReference {}
impl CataclysmChunk {
pub fn new() -> Self {
Self {
simple_blocks: HashMap::new(),
fancy_blocks: HashMap::new(),
smart_blocks: HashMap::new(),
entities: vec![],
}
}
}
pub struct SimpleBlock {
}
impl Renderable for SimpleBlock {
#[rustfmt::skip]
fn vertext_data<'a>() -> (&'a [f32], &'a [u32]) {
(&[
-1.0, -1.0, 0.5, //0
1.0, -1.0, 0.5, //1
-1.0, 1.0, 0.5, //2
1.0, 1.0, 0.5, //3
-1.0, -1.0, -0.5, //4
1.0, -1.0, -0.5, //5
-1.0, 1.0, -0.5, //6
1.0, 1.0, -0.5 //7
],
&[
//Top
2, 6, 7,
2, 3, 7,
//Bottom
0, 4, 5,
0, 1, 5,
//Left
0, 2, 6,
0, 4, 6,
//Right
1, 3, 7,
1, 5, 7,
//Front
0, 2, 3,
0, 1, 3,
//Back
4, 6, 7,
4, 5, 7
]
)
}
}
pub struct FancyBlock {
pub pos:Vec3,
}
pub struct SmartBlock {
pub pos:Vec3,
}
pub struct Entity {
pub pos:Vec3,
}
//pub enum ModelKind {
// Cube,
// Complex(),
//}
//pub struct ResourceReference {}

View file

@ -1,6 +1,15 @@
use anyhow::Result;
use glfw::PWindow;
use crate::cataclysm::Cataclysm;
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
pub mod vulkan;
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
pub mod vulkan_gc;
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
pub mod opengl;
@ -11,3 +20,45 @@ pub mod opengl;
#[cfg(target_os = "windows")] pub mod directx;
#[cfg(target_os = "vita")] pub mod gxm;
pub trait Renderable {
fn vertext_data<'a>() -> (&'a [f32], &'a [u32]);
}
#[repr(C)]
#[derive(Debug, Clone, Default)]
pub struct VertexData {
verts: Box<[f32]>,
indices:Box<[u32]>,
}
#[allow(unused)]
pub trait GraphicsCommander {
fn suspend_rendering(&mut self);
fn resume_rendering(&mut self);
// will need a reference to game engine objects
// replace with generic draw call? draw call will draw instructions to image, image may be framebuffer or not, allows gpu accelerated dynamic texture stuff
fn render(&mut self, window:&mut PWindow, cataclysm:&mut Cataclysm) -> Result<()>;
/// This function will clear all existing vbos and replace them with its own.
fn register_vbos(&mut self, data:&[VertexData]);
// make generic for assets?
fn register_texture(&mut self);
fn destroy_texture(&mut self);
// cleans up all data from memory, used when exiting or switching graphics backends
//fn cleanup(&mut self);
fn exit(&mut self);
}
#[allow(unused)]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum GMode {
Vulkan,
OpenGL,
#[cfg(target_os = "macos")]
Metal,
#[cfg(target_os = "windows")]
DirectX,
}

View file

@ -1,36 +1,18 @@
use std::error::Error;
use std::ffi::CStr;
use std::ffi::CString;
use std::num::NonZeroU32;
use std::ops::Deref;
use crate::cataclysm::Cataclysm;
use gl::types::GLfloat;
use raw_window_handle::HasWindowHandle;
use winit::application::ApplicationHandler;
use winit::event::KeyEvent;
use winit::event::WindowEvent;
use winit::event_loop::ActiveEventLoop;
use winit::keyboard::Key;
use winit::keyboard::NamedKey;
use winit::window::Window;
use winit::window::WindowAttributes;
use super::GraphicsCommander;
use glutin::config::Config;
use glutin::config::ConfigTemplateBuilder;
use glutin::config::GetGlConfig;
use glutin::context::ContextApi;
use glutin::context::ContextAttributesBuilder;
use glutin::context::NotCurrentContext;
use glutin::context::PossiblyCurrentContext;
use glutin::context::Version;
use glutin::display::GetGlDisplay;
use glutin::prelude::*;
use glutin::surface::Surface;
use glutin::surface::SwapInterval;
use glutin::surface::WindowSurface;
use anyhow::Result;
use glutin_winit::DisplayBuilder;
use glutin_winit::GlWindow;
use glam::vec2;
use glam::vec3;
use glam::Vec2;
use glam::Vec3;
use glfw::Context;
use glfw::PWindow;
use log::*;
pub mod gl {
#![allow(clippy::all)]
@ -39,276 +21,136 @@ pub mod gl {
pub use Gles2 as Gl;
}
pub fn main(event_loop:winit::event_loop::EventLoop<()>) -> Result<(), Box<dyn Error>> {
// The template will match only the configurations supporting rendering
// to windows.
//
// XXX We force transparency only on macOS, given that EGL on X11 doesn't
// have it, but we still want to show window. The macOS situation is like
// that, because we can query only one config at a time on it, but all
// normal platforms will return multiple configs, so we can find the config
// with transparency ourselves inside the `reduce`.
let template = ConfigTemplateBuilder::new().with_alpha_size(8).with_transparency(cfg!(target_os = "macos"));
impl GraphicsCommander for Renderer {
fn suspend_rendering(&mut self) {
}
let display_builder = DisplayBuilder::new().with_window_attributes(Some(window_attributes()));
fn resume_rendering(&mut self) {
}
let mut app = App::new(template, display_builder);
event_loop.run_app(&mut app)?;
fn render(&mut self, window:&mut glfw::PWindow, cataclysm:&mut Cataclysm) -> anyhow::Result<()> {
let (red, green, blue, alpha) = (0.0125, 0.0094, 0.0071, 1.0);
trace!("Clearing screen with color {red}|{green}|{blue}|{alpha}.");
unsafe {
self.gl.UseProgram(self.program);
app.exit_state
}
trace!("Bind.");
self.gl.BindVertexArray(self.vao);
self.gl.BindBuffer(gl::ARRAY_BUFFER, self.vbo);
impl ApplicationHandler for App {
fn resumed(&mut self, event_loop:&ActiveEventLoop) {
let (window, gl_config) = match &self.gl_display {
// We just created the event loop, so initialize the display, pick the config, and
// create the context.
GlDisplayCreationState::Builder(display_builder) => {
let (window, gl_config) = match display_builder.clone().build(event_loop, self.template.clone(), gl_config_picker) {
Ok((window, gl_config)) => (window.unwrap(), gl_config),
Err(err) => {
self.exit_state = Err(err);
event_loop.exit();
return;
},
};
println!("Picked a config with {} samples", gl_config.num_samples());
// Mark the display as initialized to not recreate it on resume, since the
// display is valid until we explicitly destroy it.
self.gl_display = GlDisplayCreationState::Init;
// Create gl context.
self.gl_context = Some(create_gl_context(&window, &gl_config).treat_as_possibly_current());
(window, gl_config)
},
GlDisplayCreationState::Init => {
println!("Recreating window in `resumed`");
// Pick the config which we already use for the context.
let gl_config = self.gl_context.as_ref().unwrap().config();
match glutin_winit::finalize_window(event_loop, window_attributes(), &gl_config) {
Ok(window) => (window, gl_config),
Err(err) => {
self.exit_state = Err(err.into());
event_loop.exit();
return;
},
}
},
};
let attrs = window.build_surface_attributes(Default::default()).expect("Failed to build surface attributes");
let gl_surface = unsafe { gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() };
// The context needs to be current for the Renderer to set up shaders and
// buffers. It also performs function loading, which needs a current context on
// WGL.
let gl_context = self.gl_context.as_ref().unwrap();
gl_context.make_current(&gl_surface).unwrap();
self.renderer.get_or_insert_with(|| Renderer::new(&gl_config.display()));
// Try setting vsync.
if let Err(res) = gl_surface.set_swap_interval(gl_context, SwapInterval::Wait(NonZeroU32::new(1).unwrap())) {
eprintln!("Error setting vsync: {res:?}");
trace!("ClearColor.");
self.gl.ClearColor(red, green, blue, alpha);
trace!("Clear.");
self.gl.Clear(gl::COLOR_BUFFER_BIT);
trace!("DrawArrays.");
self.gl.DrawArrays(gl::TRIANGLES, 0, 3);
}
trace!("Done clearing screen.");
assert!(self.state.replace(AppState { gl_surface, window }).is_none());
window.swap_buffers();
Ok(())
}
fn suspended(&mut self, _event_loop:&ActiveEventLoop) {
// This event is only raised on Android, where the backing NativeWindow for a GL
// Surface can appear and disappear at any moment.
println!("Android window removed");
fn register_texture(&mut self) { todo!() }
// Destroy the GL Surface and un-current the GL Context before ndk-glue releases
// the window back to the system.
self.state = None;
fn destroy_texture(&mut self) { todo!() }
// Make context not current.
self.gl_context = Some(self.gl_context.take().unwrap().make_not_current().unwrap().treat_as_possibly_current());
}
//fn cleanup(&mut self) { todo!() }
fn window_event(&mut self, event_loop:&ActiveEventLoop, _window_id:winit::window::WindowId, event:WindowEvent) {
match event {
WindowEvent::Resized(size) if size.width != 0 && size.height != 0 => {
// Some platforms like EGL require resizing GL surface to update the size
// Notable platforms here are Wayland and macOS, other don't require it
// and the function is no-op, but it's wise to resize it for portability
// reasons.
if let Some(AppState { gl_surface, window: _ }) = self.state.as_ref() {
let gl_context = self.gl_context.as_ref().unwrap();
gl_surface.resize(gl_context, NonZeroU32::new(size.width).unwrap(), NonZeroU32::new(size.height).unwrap());
let renderer = self.renderer.as_ref().unwrap();
renderer.resize(size.width as i32, size.height as i32);
}
},
WindowEvent::CloseRequested |
WindowEvent::KeyboardInput {
event: KeyEvent {
logical_key: Key::Named(NamedKey::Escape),
..
},
..
} => event_loop.exit(),
_ => (),
fn exit(&mut self) {
trace!("Destroying OpenGL instance.");
unsafe {
self.gl.DeleteProgram(self.program);
for vbo in self.vbos.iter().take(self.vbos.len()) {
self.gl.DeleteBuffers(1, vbo);
}
self.gl.DeleteVertexArrays(1, &self.vao);
}
}
fn exiting(&mut self, _event_loop:&ActiveEventLoop) {
// NOTE: The handling below is only needed due to nvidia on Wayland to not crash
// on exit due to nvidia driver touching the Wayland display from on
// `exit` hook.
let _gl_display = self.gl_context.take().unwrap().display();
// Clear the window.
self.state = None;
#[cfg(egl_backend)]
#[allow(irrefutable_let_patterns)]
if let glutin::display::Display::Egl(display) = _gl_display {
fn register_vbos(&mut self, data:&[super::VertexData]) {
for data in data {
trace!("Creating OpenGL VAO.");
unsafe {
display.terminate();
let mut vao = std::mem::zeroed();
self.gl.GenVertexArrays(1, &mut vao);
self.gl.BindVertexArray(vao);
}
trace!("Creating OpenGL VBO.");
unsafe {
let mut vbo = std::mem::zeroed();
self.gl.GenBuffers(1, &mut vbo);
self.gl.BindBuffer(gl::ARRAY_BUFFER, vbo);
self.gl.BufferData(
gl::ARRAY_BUFFER,
(VERTEX_DATA.len() * std::mem::size_of::<Vertex>()) as gl::types::GLsizeiptr,
VERTEX_DATA.as_ptr() as *const _,
gl::STATIC_DRAW,
);
}
unsafe {
trace!("Applying shader attributes.");
let pos_attrib = self.gl.GetAttribLocation( self.program, b"position\0".as_ptr() as *const _);
let color_attrib = self.gl.GetAttribLocation(self.program, b"color\0".as_ptr() as *const _);
self.gl.VertexAttribPointer(
pos_attrib as gl::types::GLuint,
2,
gl::FLOAT,
0,
std::mem::size_of::<Vertex>() as gl::types::GLsizei,
std::ptr::null(),
);
self.gl.VertexAttribPointer(
color_attrib as gl::types::GLuint,
3,
gl::FLOAT,
0,
5 * std::mem::size_of::<f32>() as gl::types::GLsizei,
(2 * std::mem::size_of::<f32>()) as *const () as *const _,
);
self.gl.EnableVertexAttribArray(pos_attrib as gl::types::GLuint);
self.gl.EnableVertexAttribArray(color_attrib as gl::types::GLuint);
}
}
}
fn about_to_wait(&mut self, _event_loop:&ActiveEventLoop) {
if let Some(AppState { gl_surface, window }) = self.state.as_ref() {
let gl_context = self.gl_context.as_ref().unwrap();
let renderer = self.renderer.as_ref().unwrap();
renderer.draw();
window.request_redraw();
gl_surface.swap_buffers(gl_context).unwrap();
}
}
}
fn create_gl_context(window:&Window, gl_config:&Config) -> NotCurrentContext {
let raw_window_handle = window.window_handle().ok().map(|wh| wh.as_raw());
// The context creation part.
let context_attributes = ContextAttributesBuilder::new().build(raw_window_handle);
// Since glutin by default tries to create OpenGL core context, which may not be
// present we should try gles.
let fallback_context_attributes = ContextAttributesBuilder::new()
.with_context_api(ContextApi::Gles(None))
.build(raw_window_handle);
// There are also some old devices that support neither modern OpenGL nor GLES.
// To support these we can try and create a 2.1 context.
let legacy_context_attributes = ContextAttributesBuilder::new()
.with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1))))
.build(raw_window_handle);
// Reuse the uncurrented context from a suspended() call if it exists, otherwise
// this is the first time resumed() is called, where the context still
// has to be created.
let gl_display = gl_config.display();
unsafe {
gl_display.create_context(gl_config, &context_attributes).unwrap_or_else(|_| {
gl_display.create_context(gl_config, &fallback_context_attributes).unwrap_or_else(|_| {
gl_display
.create_context(gl_config, &legacy_context_attributes)
.expect("failed to create context")
})
})
}
}
fn window_attributes() -> WindowAttributes {
Window::default_attributes()
.with_transparent(true)
.with_title("Glutin triangle gradient example (press Escape to exit)")
}
enum GlDisplayCreationState {
/// The display was not build yet.
Builder(DisplayBuilder),
/// The display was already created for the application.
Init,
}
struct App {
template: ConfigTemplateBuilder,
renderer: Option<Renderer>,
// NOTE: `AppState` carries the `Window`, thus it should be dropped after everything else.
state: Option<AppState>,
gl_context:Option<PossiblyCurrentContext>,
gl_display:GlDisplayCreationState,
exit_state:Result<(), Box<dyn Error>>,
}
impl App {
fn new(template:ConfigTemplateBuilder, display_builder:DisplayBuilder) -> Self {
Self {
template,
gl_display:GlDisplayCreationState::Builder(display_builder),
exit_state:Ok(()),
gl_context:None,
state:None,
renderer:None,
}
}
}
struct AppState {
gl_surface:Surface<WindowSurface>,
// NOTE: Window should be dropped after all resources created using its
// raw-window-handle.
window: Window,
}
// Find the config with the maximum number of samples, so our triangle will be
// smooth.
pub fn gl_config_picker(configs:Box<dyn Iterator<Item=Config>+'_>) -> Config {
configs
.reduce(|accum, config| {
let transparency_check = config.supports_transparency().unwrap_or(false) & !accum.supports_transparency().unwrap_or(false);
if transparency_check || config.num_samples() > accum.num_samples() {
config
} else {
accum
}
})
.unwrap()
}
use std::ffi::CStr;
use std::ops::Deref;
pub struct Renderer {
program:gl::types::GLuint,
vao: gl::types::GLuint,
vbo: gl::types::GLuint,
vbos: Vec<gl::types::GLuint>,
//vbo: gl::types::GLuint,
gl: gl::Gl,
}
impl Renderer {
pub fn new<D:GlDisplay>(gl_display:&D) -> Self {
pub fn create(window:&mut PWindow) -> Result<Self> {
trace!("Creating OpenGL renderer instance.");
unsafe {
let gl = gl::Gl::load_with(|symbol| {
let symbol = CString::new(symbol).unwrap();
gl_display.get_proc_address(symbol.as_c_str()).cast()
});
let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol));
if let Some(renderer) = get_gl_string(&gl, gl::RENDERER) {
println!("Running on {}", renderer.to_string_lossy());
info!("Running on {}", renderer.to_string_lossy());
}
if let Some(version) = get_gl_string(&gl, gl::VERSION) {
println!("OpenGL Version {}", version.to_string_lossy());
info!("OpenGL Version {}", version.to_string_lossy());
}
if let Some(shaders_version) = get_gl_string(&gl, gl::SHADING_LANGUAGE_VERSION) {
println!("Shaders version on {}", shaders_version.to_string_lossy());
info!("Shaders version on {}", shaders_version.to_string_lossy());
}
trace!("Loading shaders.");
let vertex_shader = create_shader(&gl, gl::VERTEX_SHADER, VERTEX_SHADER_SOURCE);
let fragment_shader = create_shader(&gl, gl::FRAGMENT_SHADER, FRAGMENT_SHADER_SOURCE);
trace!("Creating OpenGL shader program.");
let program = gl.CreateProgram();
gl.AttachShader(program, vertex_shader);
@ -318,60 +160,12 @@ impl Renderer {
gl.UseProgram(program);
trace!("Deleting shader objects.");
gl.DeleteShader(vertex_shader);
gl.DeleteShader(fragment_shader);
let mut vao = std::mem::zeroed();
gl.GenVertexArrays(1, &mut vao);
gl.BindVertexArray(vao);
let mut vbo = std::mem::zeroed();
gl.GenBuffers(1, &mut vbo);
gl.BindBuffer(gl::ARRAY_BUFFER, vbo);
gl.BufferData(
gl::ARRAY_BUFFER,
(VERTEX_DATA.len() * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr,
VERTEX_DATA.as_ptr() as *const _,
gl::STATIC_DRAW,
);
let pos_attrib = gl.GetAttribLocation(program, b"position\0".as_ptr() as *const _);
let color_attrib = gl.GetAttribLocation(program, b"color\0".as_ptr() as *const _);
gl.VertexAttribPointer(
pos_attrib as gl::types::GLuint,
2,
gl::FLOAT,
0,
5 * std::mem::size_of::<f32>() as gl::types::GLsizei,
std::ptr::null(),
);
gl.VertexAttribPointer(
color_attrib as gl::types::GLuint,
3,
gl::FLOAT,
0,
5 * std::mem::size_of::<f32>() as gl::types::GLsizei,
(2 * std::mem::size_of::<f32>()) as *const () as *const _,
);
gl.EnableVertexAttribArray(pos_attrib as gl::types::GLuint);
gl.EnableVertexAttribArray(color_attrib as gl::types::GLuint);
Self { program, vao, vbo, gl }
}
}
pub fn draw(&self) { self.draw_with_clear_color(0.1, 0.1, 0.1, 0.9) }
pub fn draw_with_clear_color(&self, red:GLfloat, green:GLfloat, blue:GLfloat, alpha:GLfloat) {
unsafe {
self.gl.UseProgram(self.program);
self.gl.BindVertexArray(self.vao);
self.gl.BindBuffer(gl::ARRAY_BUFFER, self.vbo);
self.gl.ClearColor(red, green, blue, alpha);
self.gl.Clear(gl::COLOR_BUFFER_BIT);
self.gl.DrawArrays(gl::TRIANGLES, 0, 3);
trace!("OpenGL renderer instance created.");
Ok(Self { program, vao, vbos:vec![], gl })
}
}
@ -388,16 +182,6 @@ impl Deref for Renderer {
fn deref(&self) -> &Self::Target { &self.gl }
}
impl Drop for Renderer {
fn drop(&mut self) {
unsafe {
self.gl.DeleteProgram(self.program);
self.gl.DeleteBuffers(1, &self.vbo);
self.gl.DeleteVertexArrays(1, &self.vao);
}
}
}
unsafe fn create_shader(gl:&gl::Gl, shader:gl::types::GLenum, source:&[u8]) -> gl::types::GLuint {
let shader = gl.CreateShader(shader);
gl.ShaderSource(shader, 1, [source.as_ptr().cast()].as_ptr(), std::ptr::null());
@ -412,12 +196,72 @@ fn get_gl_string(gl:&gl::Gl, variant:gl::types::GLenum) -> Option<&'static CStr>
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
struct Vertex {
pos: Vec2,
color:Vec3,
}
#[rustfmt::skip]
static VERTEX_DATA: [f32; 15] = [
-0.5, -0.5, 1.0, 0.0, 0.0,
0.0, 0.5, 0.0, 1.0, 0.0,
0.5, -0.5, 0.0, 0.0, 1.0,
static VERTEX_DATA: [Vertex; 3] = [
//-0.5, -0.5, 1.0, 0.0, 0.0,
// 0.0, 0.5, 0.0, 1.0, 0.0,
// 0.5, -0.5, 0.0, 0.0, 1.0,
Vertex::new(vec2(-0.5, -0.5), vec3(0.3, 0.0, 1.0)),
Vertex::new(vec2(0.5, 0.5), vec3(0.3, 0.0, 1.0)),
Vertex::new(vec2(0.5, -0.5), vec3(0.3, 0.0, 1.0)),
//Vertex::new(vec2(-0.5, 0.5), vec3(0.3, 0.0, 1.0)),
];
impl Vertex {
const fn new(pos:Vec2, color:Vec3) -> Self { Self { pos, color } }
//fn binding_description() -> vk::VertexInputBindingDescription {
// vk::VertexInputBindingDescription::builder()
// .binding(0)
// .stride(size_of::<Vertex>() as u32)
// .input_rate(vk::VertexInputRate::VERTEX)
// .build()
//}
//fn attribute_descriptions() -> [vk::VertexInputAttributeDescription; 2] {
// let pos = vk::VertexInputAttributeDescription::builder()
// .binding(0)
// .location(0)
// .format(vk::Format::R32G32_SFLOAT)
// .offset(0)
// .build();
// let color = vk::VertexInputAttributeDescription::builder()
// .binding(0)
// .location(1)
// .format(vk::Format::R32G32B32_SFLOAT)
// .offset(size_of::<Vec2f>() as u32)
// .build();
// [pos, color]
//}
}
const VERTEX_SHADER_SOURCE2:&[u8] = b"
#version 450
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
mat4 view;
mat4 proj;
} ubo;
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor;
void main() {
gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 1.0);
fragColor = inColor;
}
\0";
const VERTEX_SHADER_SOURCE:&[u8] = b"
#version 100
@ -429,8 +273,20 @@ attribute vec3 color;
varying vec3 v_color;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
v_color = color;
gl_Position = vec4(position, 0.0, 1.0);
v_color = color;
}
\0";
const FRAGMENT_SHADER_SOURCE2:&[u8] = b"
#version 450
layout(location = 0) in vec3 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor, 1.0);
}
\0";

View file

@ -29,7 +29,12 @@ use vulkanalia::vk::ExtDebugUtilsExtension;
use vulkanalia::vk::KhrSurfaceExtension;
use vulkanalia::vk::KhrSwapchainExtension;
use old_winit::dpi::LogicalSize;
use old_winit::event::Event;
use old_winit::event::WindowEvent;
use old_winit::event_loop::EventLoop;
use old_winit::window::Window;
use old_winit::window::WindowBuilder;
type Vec2f = cgmath::Vector2<f32>;
type Vec3f = cgmath::Vector3<f32>;
@ -84,6 +89,73 @@ macro_rules! const_shaders {
};
}
pub fn start() -> Result<()> {
info!("Initializing event loop and winit window instance.");
// Window
let event_loop = EventLoop::new()?;
let window = WindowBuilder::new()
.with_title("WHAT")
.with_inner_size(LogicalSize::new(1024, 768))
.build(&event_loop)?;
info!("Creating app and starting event loop.");
// App
let mut app = unsafe { App::create(&window)? };
let mut minimized = false;
//let shutdown_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(shutdown_rx)));
event_loop.run(move |event, elwt| {
//let mut shutdown_rx_guard = shutdown_rx.lock().unwrap();
//if let Some(receiver) = shutdown_rx_guard.as_mut() {
// if receiver.try_recv().is_ok() {
// info!("Closing event loop and destroying Vulkan instance.");
// elwt.exit();
// unsafe {
// app.device.device_wait_idle().unwrap();
// app.destroy();
// }
// return;
// }
//}
match event {
// Request a redraw when all events were processed.
Event::AboutToWait => window.request_redraw(),
Event::WindowEvent { event, .. } => match event {
// Render a frame if our Vulkan app is not being destroyed.
WindowEvent::RedrawRequested if !elwt.exiting() && !minimized => {
unsafe { app.render(&window) }.unwrap();
},
WindowEvent::Resized(size) =>
if size.width == 0 || size.height == 0 {
minimized = true;
} else {
minimized = false;
app.resized = true;
},
// Destroy our Vulkan app.
WindowEvent::CloseRequested => {
info!("Closing event loop and destroying Vulkan instance.");
elwt.exit();
unsafe {
app.device.device_wait_idle().unwrap();
app.destroy();
}
},
_ => {},
},
_ => {},
}
})?;
Ok(())
}
/// Our Vulkan app.
#[derive(Clone, Debug)]
pub(crate) struct App {
@ -1398,7 +1470,7 @@ unsafe fn copy_buffer_to_image(device:&Device, data:&AppData, buffer:vk::Buffer,
unsafe fn create_texture_image_view(device:&Device, data:&mut AppData) -> Result<()> {
data.texture_image_view = create_image_view(device, data.texture_image, vk::Format::R8G8B8A8_SRGB)?;
Ok(())
}

File diff suppressed because it is too large Load diff

View file

@ -1,116 +0,0 @@
use std::process::exit;
use anyhow::Result;
use log::*;
use vulkanalia::prelude::v1_0::*;
use old_winit::dpi::LogicalSize;
use old_winit::event::Event;
use old_winit::event::WindowEvent;
use old_winit::event_loop::EventLoop;
use old_winit::window::WindowBuilder;
use crate::graphics_engines;
use crate::graphics_engines::vulkan::App;
const WINDOW_TITLE:&'static str = "MineMod";
const GRAPHICS_MODE:GMode = GMode::OpenGL;
enum GMode {
Vulkan,
OpenGL,
}
pub fn main() -> Result<()> {
super::init_logging();
info!("Registering CTRLC hook.");
let (shutdown_tx, shutdown_rx) = std::sync::mpsc::channel();
ctrlc::set_handler(move || {
shutdown_tx.send(()).expect("Failed to send shutdown signal");
})
.expect("Error setting Ctrl-C handler");
match GRAPHICS_MODE {
GMode::Vulkan => {
info!("Initializing event loop and winit window instance.");
// Window
let event_loop = EventLoop::new()?;
let window = WindowBuilder::new()
.with_title(WINDOW_TITLE)
.with_inner_size(LogicalSize::new(1024, 768))
.build(&event_loop)?;
info!("Creating app and starting event loop.");
// App
let mut app = unsafe { App::create(&window)? };
let mut minimized = false;
let shutdown_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(shutdown_rx)));
event_loop.run(move |event, elwt| {
let mut shutdown_rx_guard = shutdown_rx.lock().unwrap();
if let Some(receiver) = shutdown_rx_guard.as_mut() {
if receiver.try_recv().is_ok() {
info!("Closing event loop and destroying Vulkan instance.");
elwt.exit();
unsafe {
app.device.device_wait_idle().unwrap();
app.destroy();
}
return;
}
}
match event {
// Request a redraw when all events were processed.
Event::AboutToWait => window.request_redraw(),
Event::WindowEvent { event, .. } => match event {
// Render a frame if our Vulkan app is not being destroyed.
WindowEvent::RedrawRequested if !elwt.exiting() && !minimized => {
unsafe { app.render(&window) }.unwrap();
},
WindowEvent::Resized(size) =>
if size.width == 0 || size.height == 0 {
minimized = true;
} else {
minimized = false;
app.resized = true;
},
// Destroy our Vulkan app.
WindowEvent::CloseRequested => {
info!("Closing event loop and destroying Vulkan instance.");
elwt.exit();
unsafe {
app.device.device_wait_idle().unwrap();
app.destroy();
}
},
_ => {},
},
_ => {},
}
})?;
},
GMode::OpenGL => {
if let Err(error) = graphics_engines::opengl::main(winit::event_loop::EventLoop::new()?) {
error!("gl error {error}");
exit(-1);
}
},
}
info!("Exiting program.");
Ok(())
}

View file

@ -1,96 +0,0 @@
use anyhow::Result;
use log::*;
use vulkanalia::prelude::v1_0::*;
use winit::dpi::LogicalSize;
use winit::event::Event;
use winit::event::WindowEvent;
use winit::event_loop::EventLoop;
use winit::window::WindowBuilder;
use crate::graphics_engines::vulkan::App;
const WINDOW_TITLE:&'static str = "MineMod";
pub fn main() -> Result<()> {
super::init_logging();
info!("Registering CTRLC hook.");
let (shutdown_tx, shutdown_rx) = std::sync::mpsc::channel();
ctrlc::set_handler(move || {
shutdown_tx.send(()).expect("Failed to send shutdown signal");
})
.expect("Error setting Ctrl-C handler");
info!("Initializing event loop and winit window instance.");
// Window
let event_loop = EventLoop::new()?;
let window = WindowBuilder::new()
.with_title(WINDOW_TITLE)
.with_inner_size(LogicalSize::new(1024, 768))
.build(&event_loop)?;
info!("Creating app and starting event loop.");
// App
let mut app = unsafe { App::create(&window)? };
let mut minimized = false;
let shutdown_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(shutdown_rx)));
event_loop.run(move |event, elwt| {
let mut shutdown_rx_guard = shutdown_rx.lock().unwrap();
if let Some(receiver) = shutdown_rx_guard.as_mut() {
if receiver.try_recv().is_ok() {
info!("Closing event loop and destroying Vulkan instance.");
elwt.exit();
unsafe {
app.device.device_wait_idle().unwrap();
app.destroy();
}
return;
}
}
match event {
// Request a redraw when all events were processed.
Event::AboutToWait => window.request_redraw(),
Event::WindowEvent { event, .. } => match event {
// Render a frame if our Vulkan app is not being destroyed.
WindowEvent::RedrawRequested if !elwt.exiting() && !minimized => {
unsafe { app.render(&window) }.unwrap();
},
WindowEvent::Resized(size) =>
if size.width == 0 || size.height == 0 {
minimized = true;
} else {
minimized = false;
app.resized = true;
},
// Destroy our Vulkan app.
WindowEvent::CloseRequested => {
info!("Closing event loop and destroying Vulkan instance.");
elwt.exit();
unsafe {
app.device.device_wait_idle().unwrap();
app.destroy();
}
},
_ => {},
},
_ => {},
}
})?;
info!("Exiting program.");
Ok(())
}

View file

@ -1,4 +1,4 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
//#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![deny(clippy::unwrap_used)]
#![allow(
// dead_code,
@ -8,8 +8,33 @@
unsafe_op_in_unsafe_fn
)]
mod audio_engines;
mod cataclysm;
mod graphics_engines;
mod input_systems;
mod targets;
/// i hope you will forgive me for these crimes, but as far as i can tell this is the best way
/// to handle all these platforms with wildly different requirements and capabilities
pub use targets::*;
// Logging is currently common across all platforms so it may live here
fn init_logging() {
tracing_subscriber::fmt()
.compact()
.with_timer(tracing_subscriber::fmt::time::uptime())
.with_ansi(true)
.with_level(true)
.with_thread_names(true)
.with_max_level(if cfg!(debug_assertions) {
tracing::level_filters::LevelFilter::DEBUG
} else {
tracing::level_filters::LevelFilter::INFO
})
.init();
// pretty_env_logger::init_timed();
}
// NOTE use crate:: for things in engine that depend on the target platform
// this allows an incredibly easy way to handle gui and others per platform
@ -38,58 +63,3 @@ mod graphics_engines;
// test BCn vs raw formats
// research why texture atlases exist, it seems like an easy way to reduce the allocation calls since they are limited, and it seems to provide better usage of memory overall
// Planned system targets
#[cfg(target_os = "linux")] mod linux;
#[cfg(target_os = "linux")] pub use linux::*;
#[cfg(target_os = "windows")] mod windows;
#[cfg(target_os = "windows")] pub use windows::*;
#[cfg(target_os = "macos")] mod mac;
#[cfg(target_os = "macos")] pub use mac::*;
#[cfg(target_family = "wasm")] mod wasm;
#[cfg(target_family = "wasm")] pub use wasm::*;
#[cfg(target_os = "vita")] mod vita;
#[cfg(target_os = "vita")] pub use vita::*;
// Potential system targets
// bindgen, cc, https://github.com/rust-console
// switch // c lib: libnx, crate: rust-switch, toolchain: devkitPro
// #[cfg(target_os = "horizon")]
// mod switch;
// #[cfg(target_os = "horizon")]
// pub use switch::*;
// ps3 // sdk: PSL1GHT, target: powerpc64-unknown-linux-gnu
// #[cfg(target_os = "psl1ght")]
// mod ps3;
// #[cfg(target_os = "psl1ght")]
// pub use ps3::*;
// x360 // c lib: libxenon, make custom spec for xenon target
// #[cfg(target_os = "xenon")]
// mod x369;
// #[cfg(target_os = "xenon")]
// pub use x360::*;
// wii // toolchain: devkitPPC, target: powerpc-unknown-eabi, c lib: libogc
// #[cfg(target_os = "wii")]
// mod wii;
// #[cfg(target_os = "wii")]
// pub use wii::*;
fn init_logging() {
tracing_subscriber::fmt()
.compact()
.with_timer(tracing_subscriber::fmt::time::uptime())
.with_ansi(true)
.with_level(true)
// .with_thread_ids(true)
.with_thread_names(true)
.with_max_level(if cfg!(debug_assertions) {
tracing::level_filters::LevelFilter::DEBUG
} else {
tracing::level_filters::LevelFilter::INFO
})
.init();
// pretty_env_logger::init_timed();
}

View file

@ -0,0 +1,13 @@
//use anyhow::Result;
//use log::*;
//use winit::event_loop::EventLoop;
//pub fn main() -> Result<()> {
// crate::init_logging();
// Ok(())
//}

View file

@ -0,0 +1,96 @@
//use anyhow::Result;
//use log::*;
//use vulkanalia::prelude::v1_0::*;
//use winit::dpi::LogicalSize;
//use winit::event::Event;
//use winit::event::WindowEvent;
//use winit::event_loop::EventLoop;
//use winit::window::WindowBuilder;
//use crate::graphics_engines::vulkan::App;
//const WINDOW_TITLE:&'static str = "MineMod";
//pub fn main() -> Result<()> {
// super::init_logging();
// info!("Registering CTRLC hook.");
// let (shutdown_tx, shutdown_rx) = std::sync::mpsc::channel();
// ctrlc::set_handler(move || {
// shutdown_tx.send(()).expect("Failed to send shutdown signal");
// })
// .expect("Error setting Ctrl-C handler");
// info!("Initializing event loop and winit window instance.");
// // Window
// let event_loop = EventLoop::new()?;
// let window = WindowBuilder::new()
// .with_title(WINDOW_TITLE)
// .with_inner_size(LogicalSize::new(1024, 768))
// .build(&event_loop)?;
// info!("Creating app and starting event loop.");
// // App
// let mut app = unsafe { App::create(&window)? };
// let mut minimized = false;
// let shutdown_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(shutdown_rx)));
// event_loop.run(move |event, elwt| {
// let mut shutdown_rx_guard = shutdown_rx.lock().unwrap();
// if let Some(receiver) = shutdown_rx_guard.as_mut() {
// if receiver.try_recv().is_ok() {
// info!("Closing event loop and destroying Vulkan instance.");
// elwt.exit();
// unsafe {
// app.device.device_wait_idle().unwrap();
// app.destroy();
// }
// return;
// }
// }
// match event {
// // Request a redraw when all events were processed.
// Event::AboutToWait => window.request_redraw(),
// Event::WindowEvent { event, .. } => match event {
// // Render a frame if our Vulkan app is not being destroyed.
// WindowEvent::RedrawRequested if !elwt.exiting() && !minimized => {
// unsafe { app.render(&window) }.unwrap();
// },
// WindowEvent::Resized(size) =>
// if size.width == 0 || size.height == 0 {
// minimized = true;
// } else {
// minimized = false;
// app.resized = true;
// },
// // Destroy our Vulkan app.
// WindowEvent::CloseRequested => {
// info!("Closing event loop and destroying Vulkan instance.");
// elwt.exit();
// unsafe {
// app.device.device_wait_idle().unwrap();
// app.destroy();
// }
// },
// _ => {},
// },
// _ => {},
// }
// })?;
// info!("Exiting program.");
// Ok(())
//}

166
src/targets/desktop/mod.rs Normal file
View file

@ -0,0 +1,166 @@
use anyhow::Result;
use glfw::Action;
use glfw::Context;
use glfw::Key;
use log::*;
use crate::cataclysm::Cataclysm;
use crate::cataclysm::CataclysmChunk;
use crate::cataclysm::SimpleBlock;
use crate::graphics_engines::GMode;
use crate::graphics_engines::GraphicsCommander;
//#[cfg(target_os = "linux")] mod linux;
//#[cfg(target_os = "linux")] pub use linux::*;
//#[cfg(target_os = "windows")] mod windows;
//#[cfg(target_os = "windows")] pub use windows::*;
//#[cfg(target_os = "macos")] mod mac;
//#[cfg(target_os = "macos")] pub use mac::*;
pub const WINDOW_TITLE:&'static str = "MineMod";
pub const WINDOW_DECORATION_LEFT:bool = false;
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
crate::init_logging();
info!("Registering ^C hook.");
let (shutdown_tx, shutdown_rx) = std::sync::mpsc::channel();
ctrlc::set_handler(move || {
shutdown_tx.send(()).expect("Failed to send shutdown signal");
})
.expect("Error setting Ctrl-C handler");
let mut glfw = glfw::init(|err, string| match err {
// we dont give a shit because we supply our own render system
glfw::Error::NoWindowContext /*| glfw::Error::NoError*/ => warn!("GLFW Error: {err} {string}"),
_ => panic!("GLFW Error! {err}, {string}"),
})?;
let graphics_mode = GMode::OpenGL;
// if we do not want to use opengl, disable it
if graphics_mode != GMode::OpenGL {
glfw.window_hint(glfw::WindowHint::ClientApi(glfw::ClientApiHint::NoApi));
}
if let GMode::OpenGL = graphics_mode {}
let (mut window, events) = if let Some(glfw) = glfw.create_window(1024, 768, &WINDOW_TITLE, glfw::WindowMode::Windowed) {
glfw
} else {
return Err("Could not create glfw window!".into());
};
window.set_key_polling(true);
window.make_current();
let mut cmd = /*Some(*/make_graphics_commander(graphics_mode, &mut window)?/*)*/;
let mut game_world = Cataclysm::new();
game_world.chunks.insert((0, 0, 0), CataclysmChunk::new());
for x in 0..Cataclysm::CHUNK_SIZE {
for y in 0..Cataclysm::CHUNK_SIZE {
for z in 0..Cataclysm::CHUNK_SIZE {
game_world.chunks.get_mut(&(0, 0, 0)).unwrap().simple_blocks.insert((x, y, z), SimpleBlock {});
}
}
}
//'mainloop: while !window.should_close() {
loop {
if shutdown_rx.try_recv().is_ok() {
info!("^C triggered.");
window.set_should_close(true);
}
// Swap front and back buffers
//window.swap_buffers(); // cannot be used
// dont flood the logs
//std::thread::sleep(Duration::from_secs(1));
trace!("Polling GLFW events.");
// Poll for and process events
glfw.poll_events();
for (e, event) in glfw::flush_messages(&events) {
info!("GLFW Event: {:?}", event);
match event {
//glfw::WindowEvent::FramebufferSize(x, y) => {},
//glfw::WindowEvent::Close => window.set_should_close(true),
// minimize? doesnt appear to be
glfw::WindowEvent::Iconify(e) =>
//if let Some(cmd) = graphics_commander.as_mut() {
if e {
cmd.suspend_rendering();
} else {
cmd.resume_rendering();
},
//},
glfw::WindowEvent::Key(key, _, Action::Press, _) => match key {
Key::Escape | Key::Q => window.set_should_close(true),
//Key::E => {
//if let Some(cmd) = graphics_commander.as_mut() {
// cmd.exit();
//}
//let _gc = graphics_commander.take();
//match graphics_mode {
// GMode::Vulkan => graphics_mode = GMode::OpenGL,
// GMode::OpenGL => graphics_mode = GMode::Vulkan,
// #[cfg(target_os = "macos")]
// GMode::Metal => todo!(),
// #[cfg(target_os = "windows")]
// GMode::DirectX => todo!(),
//}
//graphics_commander = Some(make_graphics_commander(graphics_mode, &mut window)?);
//},
_ => (),
},
event => {
dbg!(event);
},
}
}
if window.should_close() {
info!("Breaking loop.");
break;
}
//if let Some(cmd) = graphics_commander.as_mut() {
trace!("Rendering.");
//cmd.render_simple_blocks(game_world.chunks.get_mut(&(0, 0, 0)).unwrap().simple_blocks);
cmd.render(&mut window, &mut game_world)?;
//}
}
//if let Some(cmd) = graphics_commander.as_mut() {
info!("Closing GC instance.");
cmd.exit();
//}
info!("Exiting.");
Ok(())
}
fn make_graphics_commander(graphics_mode:GMode, window:&mut glfw::PWindow) -> Result<Box<dyn GraphicsCommander>> {
Ok(match graphics_mode {
GMode::Vulkan => Box::new(unsafe { crate::graphics_engines::vulkan_gc::App::create(&window)? }),
GMode::OpenGL => Box::new(crate::graphics_engines::opengl::Renderer::create(window)?),
#[cfg(target_os = "macos")]
GMode::Metal => todo!(),
#[cfg(target_os = "windows")]
GMode::DirectX => todo!(),
})
}
//fn make_glfw() -> Result<glfw::Glfw, Box<dyn std::error::Error>> {
// Ok(glfw)
//}

View file

@ -0,0 +1,96 @@
//use anyhow::Result;
//use log::*;
//use vulkanalia::prelude::v1_0::*;
//use winit::dpi::LogicalSize;
//use winit::event::Event;
//use winit::event::WindowEvent;
//use winit::event_loop::EventLoop;
//use winit::window::WindowBuilder;
//use crate::graphics_engines::vulkan::App;
//const WINDOW_TITLE:&'static str = "MineMod";
//pub fn main() -> Result<()> {
// super::init_logging();
// info!("Registering CTRLC hook.");
// let (shutdown_tx, shutdown_rx) = std::sync::mpsc::channel::<()>();
// ctrlc::set_handler(move || {
// shutdown_tx.send(()).expect("Failed to send shutdown signal");
// })
// .expect("Error setting Ctrl-C handler");
// info!("Initializing event loop and winit window instance.");
// // Window
// let event_loop = EventLoop::new()?;
// let window = WindowBuilder::new()
// .with_title(WINDOW_TITLE)
// .with_inner_size(LogicalSize::new(1024, 768))
// .build(&event_loop)?;
// info!("Creating app and starting event loop.");
// // App
// let mut app = unsafe { App::create(&window)? };
// let mut minimized = false;
// let shutdown_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(shutdown_rx)));
// event_loop.run(move |event, elwt| {
// let mut shutdown_rx_guard = shutdown_rx.lock().unwrap();
// if let Some(receiver) = shutdown_rx_guard.as_mut() {
// if receiver.try_recv().is_ok() {
// info!("Closing event loop and destroying Vulkan instance.");
// elwt.exit();
// unsafe {
// app.device.device_wait_idle().unwrap();
// app.destroy();
// }
// return;
// }
// }
// match event {
// // Request a redraw when all events were processed.
// Event::AboutToWait => window.request_redraw(),
// Event::WindowEvent { event, .. } => match event {
// // Render a frame if our Vulkan app is not being destroyed.
// WindowEvent::RedrawRequested if !elwt.exiting() && !minimized => {
// unsafe { app.render(&window) }.unwrap();
// },
// WindowEvent::Resized(size) =>
// if size.width == 0 || size.height == 0 {
// minimized = true;
// } else {
// minimized = false;
// app.resized = true;
// },
// // Destroy our Vulkan app.
// WindowEvent::CloseRequested => {
// info!("Closing event loop and destroying Vulkan instance.");
// elwt.exit();
// unsafe {
// app.device.device_wait_idle().unwrap();
// app.destroy();
// }
// },
// _ => {},
// },
// _ => {},
// }
// })?;
// info!("Exiting program.");
// Ok(())
//}

37
src/targets/mod.rs Normal file
View file

@ -0,0 +1,37 @@
// Planned system targets
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
mod desktop;
#[cfg(any(target_os = "linux", target_os = "windows", target_os = "macos"))]
pub use desktop::*;
// wasm may count for desktop? it does not need windowing however
//#[cfg(target_family = "wasm")] mod wasm;
//#[cfg(target_family = "wasm")] pub use wasm::*;
//#[cfg(target_os = "vita")] mod vita;
//#[cfg(target_os = "vita")] pub use vita::*;
// Potential system targets
// bindgen, cc, https://github.com/rust-console
// switch // c lib: libnx, crate: rust-switch, toolchain: devkitPro
// #[cfg(target_os = "horizon")]
// mod switch;
// #[cfg(target_os = "horizon")]
// pub use switch::*;
// ps3 // sdk: PSL1GHT, target: powerpc64-unknown-linux-gnu
// #[cfg(target_os = "psl1ght")]
// mod ps3;
// #[cfg(target_os = "psl1ght")]
// pub use ps3::*;
// x360 // c lib: libxenon, make custom spec for xenon target
// #[cfg(target_os = "xenon")]
// mod x369;
// #[cfg(target_os = "xenon")]
// pub use x360::*;
// wii // toolchain: devkitPPC, target: powerpc-unknown-eabi, c lib: libogc
// #[cfg(target_os = "wii")]
// mod wii;
// #[cfg(target_os = "wii")]
// pub use wii::*;

View file

@ -1,96 +0,0 @@
use anyhow::Result;
use log::*;
use vulkanalia::prelude::v1_0::*;
use winit::dpi::LogicalSize;
use winit::event::Event;
use winit::event::WindowEvent;
use winit::event_loop::EventLoop;
use winit::window::WindowBuilder;
use crate::graphics_engines::vulkan::App;
const WINDOW_TITLE:&'static str = "MineMod";
pub fn main() -> Result<()> {
super::init_logging();
info!("Registering CTRLC hook.");
let (shutdown_tx, shutdown_rx) = std::sync::mpsc::channel::<()>();
ctrlc::set_handler(move || {
shutdown_tx.send(()).expect("Failed to send shutdown signal");
})
.expect("Error setting Ctrl-C handler");
info!("Initializing event loop and winit window instance.");
// Window
let event_loop = EventLoop::new()?;
let window = WindowBuilder::new()
.with_title(WINDOW_TITLE)
.with_inner_size(LogicalSize::new(1024, 768))
.build(&event_loop)?;
info!("Creating app and starting event loop.");
// App
let mut app = unsafe { App::create(&window)? };
let mut minimized = false;
let shutdown_rx = std::sync::Arc::new(std::sync::Mutex::new(Some(shutdown_rx)));
event_loop.run(move |event, elwt| {
let mut shutdown_rx_guard = shutdown_rx.lock().unwrap();
if let Some(receiver) = shutdown_rx_guard.as_mut() {
if receiver.try_recv().is_ok() {
info!("Closing event loop and destroying Vulkan instance.");
elwt.exit();
unsafe {
app.device.device_wait_idle().unwrap();
app.destroy();
}
return;
}
}
match event {
// Request a redraw when all events were processed.
Event::AboutToWait => window.request_redraw(),
Event::WindowEvent { event, .. } => match event {
// Render a frame if our Vulkan app is not being destroyed.
WindowEvent::RedrawRequested if !elwt.exiting() && !minimized => {
unsafe { app.render(&window) }.unwrap();
},
WindowEvent::Resized(size) =>
if size.width == 0 || size.height == 0 {
minimized = true;
} else {
minimized = false;
app.resized = true;
},
// Destroy our Vulkan app.
WindowEvent::CloseRequested => {
info!("Closing event loop and destroying Vulkan instance.");
elwt.exit();
unsafe {
app.device.device_wait_idle().unwrap();
app.destroy();
}
},
_ => {},
},
_ => {},
}
})?;
info!("Exiting program.");
Ok(())
}