Import Oxide engine (Stages 0–10) under MIT license

Full project snapshot migrated to new Gitea remote without history:
engine, editor, physics, script, examples, tests, docs, and assets.
Relicensed from GPLv3 to MIT and updated repo URLs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Homer Simpson
2026-07-05 20:41:02 +02:00
parent 2afb56b329
commit 9eead719b0
157 changed files with 47270 additions and 2 deletions
+133
View File
@@ -0,0 +1,133 @@
//! The [`WindowApp`] trait and per-callback context.
use winit::event::WindowEvent;
use winit::window::Window;
use crate::input::InputState;
use crate::math::Color;
use crate::render::{Gpu, RenderContext};
/// An application driven by the engine's event loop.
///
/// Implement this and pass the value to [`run`](super::run). All methods have
/// empty defaults so minimal apps only override what they need. Per frame the
/// engine calls [`event`](Self::event) for each pending window event, then
/// [`update`](Self::update), then clears and presents the surface.
///
/// This trait is the **window-event handler** — the per-frame plumbing between
/// `winit` and a renderer. It is distinct from the engine's
/// [`App`](crate::app::App) **container**, which owns the scene, assets, and
/// scheduled systems. The editor's main loop typically implements this trait
/// on a struct that *also* owns an `oxide_engine::app::App`.
pub trait WindowApp {
/// Called once, after the window and GPU context exist but before the
/// first frame.
fn init(&mut self, ctx: &mut AppCtx<'_>) {
let _ = ctx;
}
/// Called for every raw window event (keyboard, mouse, resize, focus, …).
///
/// Events the engine itself reacts to (close request, resize) are still
/// forwarded here afterwards, so apps observe everything.
fn event(&mut self, ctx: &mut AppCtx<'_>, event: &WindowEvent) {
let _ = (ctx, event);
}
/// Called once per frame, before the frame is rendered.
fn update(&mut self, ctx: &mut AppCtx<'_>) {
let _ = ctx;
}
/// Called each frame after the surface has been cleared and before it is
/// presented, so the app can record its own draw commands into the frame.
///
/// This is the hook editor/overlay UI (egui) and, in later stages, the
/// scene renderer draw through. The surface is cleared with
/// [`LoadOp::Clear`](wgpu::LoadOp::Clear) *before* this runs; record passes
/// here with [`LoadOp::Load`](wgpu::LoadOp::Load) to draw on top of the
/// clear color rather than wiping it.
fn render(&mut self, ctx: &RenderCtx<'_>) {
let _ = ctx;
}
}
/// Per-frame rendering context passed to [`WindowApp::render`].
///
/// Unlike [`AppCtx`], this borrows the GPU and surface immutably: by the time
/// the draw hook runs the frame's surface texture is already acquired, so the
/// app receives the handles it needs to record additional passes into
/// [`view`](Self::view) without re-entering the render context.
pub struct RenderCtx<'a> {
/// The GPU device/queue to record and submit commands with.
pub gpu: &'a Gpu,
/// The current frame's surface texture view (the render target).
pub view: &'a wgpu::TextureView,
/// The window being rendered, e.g. for input/UI integration that needs it.
pub window: &'a Window,
/// The surface's texture format, needed to build matching pipelines.
pub surface_format: wgpu::TextureFormat,
/// Surface size in physical pixels (`width`, `height`).
pub size: (u32, u32),
}
/// Engine state handed to every [`WindowApp`] callback.
pub struct AppCtx<'a> {
pub(crate) render: &'a mut RenderContext,
pub(crate) window: &'a Window,
pub(crate) exit: &'a mut bool,
pub(crate) input: &'a InputState,
/// Seconds elapsed since the previous frame (`0.0` during
/// [`App::init`] and the first frame).
pub dt: f32,
}
impl AppCtx<'_> {
/// The render context driving the window surface.
pub fn render(&mut self) -> &mut RenderContext {
self.render
}
/// Sets the color the surface is cleared to, effective next frame.
pub fn set_clear_color(&mut self, color: Color) {
self.render.set_clear_color(color);
}
/// The current clear color.
pub fn clear_color(&self) -> Color {
self.render.clear_color()
}
/// Current surface size in physical pixels.
pub fn size(&self) -> (u32, u32) {
self.render.size()
}
/// Sets the window title.
pub fn set_title(&self, title: &str) {
self.window.set_title(title);
}
/// The window being driven, e.g. to construct UI/input integration that
/// needs a window handle.
pub fn window(&self) -> &Window {
self.window
}
/// Asks the event loop to exit after the current callback returns.
pub fn request_exit(&mut self) {
*self.exit = true;
}
/// The per-frame input snapshot.
///
/// Reflects every keyboard / mouse / scroll event delivered since the
/// previous frame's `update` returned. In [`WindowApp::event`] callbacks
/// it includes the event currently being delivered (the runner pumps it
/// before invoking the callback). In [`WindowApp::update`] it is the
/// accumulated state for the new frame; the runner clears edges (pressed/
/// released, mouse delta, scroll) automatically after `update` returns.
pub fn input(&self) -> &InputState {
self.input
}
}