No longer living in borrow checker hell for gfx
This commit is contained in:
parent
36f0744e31
commit
d2372772f0
@ -1,14 +1,16 @@
|
||||
use raylib::{RaylibHandle, prelude::{RaylibDrawHandle, RaylibMode2D}};
|
||||
|
||||
use crate::utilities::non_ref_raylib::HackedRaylibHandle;
|
||||
|
||||
|
||||
pub trait FrameUpdate {
|
||||
fn update(&mut self, raylib: &RaylibHandle, delta_seconds: f32);
|
||||
}
|
||||
|
||||
pub trait ScreenSpaceRender {
|
||||
fn render_screen_space(&self, raylib: &mut RaylibDrawHandle);
|
||||
fn render_screen_space(&self, raylib: &mut HackedRaylibHandle);
|
||||
}
|
||||
|
||||
pub trait WorldSpaceRender {
|
||||
fn render_world_space(&self, raylib: &mut RaylibMode2D<RaylibDrawHandle>);
|
||||
fn render_world_space(&self, raylib: &mut RaylibMode2D<HackedRaylibHandle>);
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
#![feature(derive_default_enum)]
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
cell::{Cell, RefCell},
|
||||
ops::Deref,
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use discord_sdk::activity::ActivityBuilder;
|
||||
use raylib::prelude::*;
|
||||
@ -14,11 +20,14 @@ use utilities::{
|
||||
|
||||
use crate::{
|
||||
context::GameContext,
|
||||
scenes::{build_screen_state_machine, RenderContext},
|
||||
utilities::shaders::{
|
||||
scenes::build_screen_state_machine,
|
||||
utilities::{
|
||||
non_ref_raylib::HackedRaylibHandle,
|
||||
shaders::{
|
||||
shader::ShaderWrapper,
|
||||
util::{dynamic_screen_texture::DynScreenTexture, render_texture::render_to_texture},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#[macro_use]
|
||||
@ -73,8 +82,11 @@ pub async fn game_begin() {
|
||||
build_screen_state_machine().expect("Could not init state main state machine");
|
||||
|
||||
// Build the game context
|
||||
let mut context = RefCell::new(GameContext::new());
|
||||
let mut context = Rc::new(RefCell::new(GameContext::new()));
|
||||
|
||||
let mut raylib_handle: RefCell<HackedRaylibHandle>;
|
||||
let raylib_thread;
|
||||
{
|
||||
let (mut rl, thread) = raylib::init()
|
||||
.size(640, 480)
|
||||
.title(&game_config.name)
|
||||
@ -83,11 +95,15 @@ pub async fn game_begin() {
|
||||
.resizable()
|
||||
.build();
|
||||
rl.set_exit_key(None);
|
||||
raylib_handle = RefCell::new(rl.into());
|
||||
raylib_thread = thread;
|
||||
}
|
||||
|
||||
// Create a dynamic texture to draw to for processing by shaders
|
||||
info!("Allocating a resizable texture for the screen");
|
||||
let mut dynamic_texture =
|
||||
DynScreenTexture::new(&mut rl, &thread).expect("Failed to allocate a screen texture");
|
||||
DynScreenTexture::new(&mut raylib_handle.borrow_mut(), &raylib_thread)
|
||||
.expect("Failed to allocate a screen texture");
|
||||
|
||||
// Load the pixel art shader
|
||||
info!("Loading the pixel art shader");
|
||||
@ -95,40 +111,44 @@ pub async fn game_begin() {
|
||||
None,
|
||||
Some(StaticGameData::get("shaders/pixelart.fs")).expect("Failed to load pixelart.fs"),
|
||||
vec!["viewport"],
|
||||
&mut rl,
|
||||
&thread,
|
||||
&mut raylib_handle.borrow_mut(),
|
||||
&raylib_thread,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
info!("Starting the render loop");
|
||||
while !rl.window_should_close() {
|
||||
while !raylib_handle.borrow().window_should_close() {
|
||||
// Profile the main game loop
|
||||
puffin::profile_scope!("main_loop");
|
||||
puffin::GlobalProfiler::lock().new_frame();
|
||||
|
||||
// Update the GPU texture that we draw to. This handles screen resizing and some other stuff
|
||||
dynamic_texture.update(&mut rl, &thread).unwrap();
|
||||
dynamic_texture
|
||||
.update(&mut raylib_handle.borrow_mut(), &raylib_thread)
|
||||
.unwrap();
|
||||
|
||||
// Switch into draw mode
|
||||
let mut d = rl.begin_drawing(&thread);
|
||||
// Switch into draw mode (using unsafe code here to avoid borrow checker hell)
|
||||
unsafe {
|
||||
raylib::ffi::BeginDrawing();
|
||||
}
|
||||
// let mut d = rl.begin_drawing(&thread);
|
||||
|
||||
// Fetch the screen size once to work with in render code
|
||||
let screen_size = Vector2::new(d.get_screen_width() as f32, d.get_screen_height() as f32);
|
||||
let screen_size = Vector2::new(
|
||||
raylib_handle.borrow().get_screen_width() as f32,
|
||||
raylib_handle.borrow().get_screen_height() as f32,
|
||||
);
|
||||
|
||||
// Update the pixel shader to correctly handle the screen size
|
||||
pixel_shader.set_variable("viewport", screen_size).unwrap();
|
||||
|
||||
// Build render context
|
||||
{
|
||||
let render_ctx = RefCell::new((RefCell::new(d), context));
|
||||
|
||||
// Render the game via the pixel shader
|
||||
render_to_texture(&mut dynamic_texture, || {
|
||||
// Profile the internal render code
|
||||
puffin::profile_scope!("internal_shaded_render");
|
||||
|
||||
// Run a state machine iteration
|
||||
let result = game_state_machine.run(&render_ctx);
|
||||
let result = game_state_machine.run(&raylib_handle);
|
||||
|
||||
if let Err(err) = result {
|
||||
error!("Main state machine encountered an error while running!");
|
||||
@ -137,9 +157,17 @@ pub async fn game_begin() {
|
||||
panic!("{:?}", err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Send the texture to the GPU to be drawn
|
||||
pixel_shader.process_texture_and_render(&mut d, &thread, &dynamic_texture);
|
||||
pixel_shader.process_texture_and_render(
|
||||
&mut raylib_handle.borrow_mut(),
|
||||
&raylib_thread,
|
||||
&dynamic_texture,
|
||||
);
|
||||
|
||||
// We MUST end draw mode
|
||||
unsafe {
|
||||
raylib::ffi::EndDrawing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
use dirty_fsm::{Action, ActionFlag};
|
||||
use raylib::{
|
||||
color::Color,
|
||||
prelude::{RaylibDraw, RaylibDrawHandle},
|
||||
};
|
||||
use raylib::{color::Color, prelude::RaylibDraw, RaylibHandle};
|
||||
use tracing::{debug, error, info, trace};
|
||||
|
||||
use crate::{context::GameContext, gfx::render_layer::ScreenSpaceRender};
|
||||
use crate::{gfx::render_layer::ScreenSpaceRender, utilities::non_ref_raylib::HackedRaylibHandle};
|
||||
|
||||
use super::{RenderContext, Scenes, ScreenError};
|
||||
use super::{Scenes, ScreenError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FsmErrorScreen {}
|
||||
@ -21,16 +18,13 @@ impl FsmErrorScreen {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Rl> Action<Scenes, ScreenError, RefCell<(RefCell<Rl>, RefCell<GameContext>)>> for FsmErrorScreen
|
||||
where
|
||||
Rl: RaylibDraw,
|
||||
{
|
||||
impl Action<Scenes, ScreenError, RefCell<HackedRaylibHandle>> for FsmErrorScreen {
|
||||
fn on_register(&mut self) -> Result<(), ScreenError> {
|
||||
debug!("Registered");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn on_first_run(&mut self, context: &RefCell<(RefCell<Rl>, RefCell<GameContext>)>) -> Result<(), ScreenError> {
|
||||
fn on_first_run(&mut self, context: &RefCell<HackedRaylibHandle>) -> Result<(), ScreenError> {
|
||||
debug!("Running FsmErrorScreen for the first time");
|
||||
Ok(())
|
||||
}
|
||||
@ -38,9 +32,10 @@ where
|
||||
fn execute(
|
||||
&mut self,
|
||||
delta: &chrono::Duration,
|
||||
context: &RefCell<(RefCell<Rl>, RefCell<GameContext>)>,
|
||||
context: &RefCell<HackedRaylibHandle>,
|
||||
) -> Result<dirty_fsm::ActionFlag<Scenes>, ScreenError> {
|
||||
trace!("execute() called on FsmErrorScreen, but we have not logic");
|
||||
trace!("execute() called on FsmErrorScreen");
|
||||
self.render_screen_space(&mut context.borrow_mut());
|
||||
Ok(ActionFlag::Continue)
|
||||
}
|
||||
|
||||
@ -51,7 +46,7 @@ where
|
||||
}
|
||||
|
||||
impl ScreenSpaceRender for FsmErrorScreen {
|
||||
fn render_screen_space(&self, raylib: &mut raylib::prelude::RaylibDrawHandle) {
|
||||
fn render_screen_space(&self, raylib: &mut HackedRaylibHandle) {
|
||||
raylib.clear_background(Color::RED);
|
||||
|
||||
// Render a warning message
|
||||
|
@ -1,20 +1,24 @@
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
cell::{Cell, RefCell, RefMut},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use dirty_fsm::{Action, StateMachine};
|
||||
use raylib::{RaylibHandle, prelude::{RaylibDraw, RaylibDrawHandle}};
|
||||
|
||||
use crate::{
|
||||
context::GameContext,
|
||||
gfx::render_layer::{FrameUpdate, ScreenSpaceRender, WorldSpaceRender},
|
||||
use raylib::{
|
||||
prelude::{RaylibDraw, RaylibDrawHandle},
|
||||
RaylibHandle,
|
||||
};
|
||||
|
||||
use crate::{context::GameContext, gfx::render_layer::{FrameUpdate, ScreenSpaceRender, WorldSpaceRender}, utilities::non_ref_raylib::HackedRaylibHandle};
|
||||
|
||||
use self::fsm_error_screen::FsmErrorScreen;
|
||||
|
||||
pub mod fsm_error_screen;
|
||||
// pub mod loading_screen;
|
||||
|
||||
/// Data passed to all scenes upon render
|
||||
pub type RenderContext<'a, 'b> = (&'b mut RaylibDrawHandle<'a>, &'b mut GameContext);
|
||||
// pub type RenderContext<'a, 'b> = (&'b mut RaylibDrawHandle<'a>, &'b mut GameContext);
|
||||
|
||||
/// Defines all scenes
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash)]
|
||||
@ -29,8 +33,11 @@ pub enum Scenes {
|
||||
pub enum ScreenError {}
|
||||
|
||||
/// Build the state machine for all scenes
|
||||
pub fn build_screen_state_machine<Rl>(
|
||||
) -> Result<StateMachine<Scenes, ScreenError, RefCell<(RefCell<Rl>, RefCell<GameContext>)>>, ScreenError> where Rl: RaylibDraw {
|
||||
pub fn build_screen_state_machine() -> Result<
|
||||
// StateMachine<Scenes, ScreenError, RefCell<(NonRefDrawHandle, Rc<RefCell<GameContext>>)>>,
|
||||
StateMachine<Scenes, ScreenError, RefCell<HackedRaylibHandle>>,
|
||||
ScreenError,
|
||||
> {
|
||||
let mut machine = StateMachine::new();
|
||||
machine.add_action(Scenes::FsmErrorScreen, FsmErrorScreen::new())?;
|
||||
Ok(machine)
|
||||
|
@ -3,3 +3,4 @@ pub mod datastore;
|
||||
pub mod game_config;
|
||||
pub mod math;
|
||||
pub mod shaders;
|
||||
pub mod non_ref_raylib;
|
||||
|
27
game/src/utilities/non_ref_raylib.rs
Normal file
27
game/src/utilities/non_ref_raylib.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use std::{borrow::Borrow, cell::{Cell, RefCell, RefMut}, ops::{Deref, DerefMut}, rc::Rc, sync::Arc};
|
||||
|
||||
use raylib::{prelude::RaylibDraw, RaylibHandle};
|
||||
|
||||
pub struct HackedRaylibHandle(RaylibHandle);
|
||||
|
||||
impl RaylibDraw for HackedRaylibHandle {}
|
||||
|
||||
impl From<RaylibHandle> for HackedRaylibHandle {
|
||||
fn from(handle: RaylibHandle) -> Self {
|
||||
Self(handle)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for HackedRaylibHandle {
|
||||
type Target = RaylibHandle;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for HackedRaylibHandle {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
@ -14,6 +14,8 @@ use raylib::{
|
||||
};
|
||||
use rust_embed::EmbeddedFile;
|
||||
|
||||
use crate::utilities::non_ref_raylib::HackedRaylibHandle;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ShaderError {
|
||||
#[error(transparent)]
|
||||
@ -76,13 +78,12 @@ impl ShaderWrapper {
|
||||
}
|
||||
|
||||
/// Handles rendering a texture to the screen via the shader. If run inside another shader context, this *should* chain with it.
|
||||
pub fn process_texture_and_render<H>(
|
||||
pub fn process_texture_and_render(
|
||||
&self,
|
||||
raylib: &mut H,
|
||||
raylib: &mut HackedRaylibHandle,
|
||||
_thread: &RaylibThread,
|
||||
texture: &RenderTexture2D,
|
||||
) where
|
||||
H: RaylibShaderModeExt + RaylibDraw,
|
||||
)
|
||||
{
|
||||
puffin::profile_function!();
|
||||
// Create a shader context to work under
|
||||
|
Reference in New Issue
Block a user