More input and rendering implementations

This commit is contained in:
Phillip Stephens 2022-02-13 13:32:52 -08:00
parent 7ee8f6e01d
commit 615204f71f
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
24 changed files with 863 additions and 245 deletions

1
Graphics/Cargo.lock generated
View File

@ -97,6 +97,7 @@ dependencies = [
"android_logger",
"bindgen",
"binrw",
"bitflags",
"bytemuck",
"bytemuck_derive",
"cgmath",

View File

@ -29,6 +29,7 @@ smallvec = "1.7.0"
scopeguard = "1.1.0"
twox-hash = "1.6.2"
winit = "0.26.1"
bitflags = "1.3.2"
# custom sdl2
sdl2 = { git = "https://github.com/encounter/rust-sdl2.git", rev = "f39d7a7549fd59bebb1fb42ec12973200bb3080b", features = ["no-link", "hidapi"] }

View File

@ -4,9 +4,59 @@
#include <cinttypes>
#include <type_traits>
#include <vector>
#ifndef ENABLE_BITWISE_ENUM
#define ENABLE_BITWISE_ENUM(type) \
constexpr type operator|(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return type(static_cast<T>(a) | static_cast<T>(b)); \
} \
constexpr type operator&(type a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
return type(static_cast<T>(a) & static_cast<T>(b)); \
} \
constexpr type& operator|=(type& a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) | static_cast<T>(b)); \
return a; \
} \
constexpr type& operator&=(type& a, type b) noexcept { \
using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) & static_cast<T>(b)); \
return a; \
} \
constexpr type operator~(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return type(~static_cast<T>(key)); \
} \
constexpr bool True(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<T>(key) != 0; \
} \
constexpr bool False(type key) noexcept { \
using T = std::underlying_type_t<type>; \
return static_cast<T>(key) == 0; \
}
#endif
namespace aurora {
enum class SpecialKey : uint8_t;
enum class ModifierKey : uint16_t {
None = 0,
LeftShift = 1 << 0,
RightShift = 1 << 1,
LeftControl = 1 << 2,
RightControl = 1 << 3,
LeftAlt = 1 << 3,
RightAlt = 1 << 4,
LeftGui = 1 << 5,
RightGui = 1 << 6,
Num = 1 << 7,
Caps = 1 << 8,
Mode = 1 << 9,
// SDL has a reserved value we don't need
};
ENABLE_BITWISE_ENUM(ModifierKey);
enum class ControllerButton : uint8_t;
enum class ControllerAxis : uint8_t;
@ -30,10 +80,10 @@ struct AppDelegate {
virtual void onAppExiting() noexcept = 0;
// Input
virtual void onCharKeyDown(uint8_t charCode, bool isRepeat) noexcept = 0;
virtual void onCharKeyUp(uint8_t charCode) noexcept = 0;
virtual void onSpecialKeyDown(SpecialKey key, bool isRepeat) noexcept = 0;
virtual void onSpecialKeyUp(SpecialKey key) noexcept = 0;
virtual void onCharKeyDown(uint8_t charCode, ModifierKey mods, bool isRepeat) noexcept = 0;
virtual void onCharKeyUp(uint8_t charCode, ModifierKey mods) noexcept = 0;
virtual void onSpecialKeyDown(SpecialKey key, ModifierKey mods, bool isRepeat) noexcept = 0;
virtual void onSpecialKeyUp(SpecialKey key, ModifierKey mods) noexcept = 0;
// Controller
virtual void onControllerAdded(uint32_t which) noexcept = 0;
@ -41,27 +91,28 @@ struct AppDelegate {
virtual void onControllerButton(uint32_t which, ControllerButton button, bool pressed) noexcept = 0;
virtual void onControllerAxis(uint32_t which, ControllerAxis axis, int16_t value) noexcept = 0;
// virtual void resized([[maybe_unused]] const WindowSize& rect, [[maybe_unused]] bool sync) noexcept {}
// virtual void mouseDown([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] EMouseButton button,
// [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void mouseUp([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] EMouseButton button,
// [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void mouseMove([[maybe_unused]] const SWindowCoord& coord) noexcept {}
// virtual void mouseEnter([[maybe_unused]] const SWindowCoord& coord) noexcept {}
// virtual void mouseLeave([[maybe_unused]] const SWindowCoord& coord) noexcept {}
// virtual void scroll([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] const SScrollDelta& scroll) noexcept {}
//
// virtual void touchDown([[maybe_unused]] const STouchCoord& coord, [[maybe_unused]] uintptr_t tid) noexcept {}
// virtual void touchUp([[maybe_unused]] const STouchCoord& coord, [[maybe_unused]] uintptr_t tid) noexcept {}
// virtual void touchMove([[maybe_unused]] const STouchCoord& coord, [[maybe_unused]] uintptr_t tid) noexcept {}
//
// virtual void charKeyDown([[maybe_unused]] unsigned long charCode, [[maybe_unused]] EModifierKey mods,
// [[maybe_unused]] bool isRepeat) noexcept {}
// virtual void charKeyUp([[maybe_unused]] unsigned long charCode, [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void specialKeyDown([[maybe_unused]] ESpecialKey key, [[maybe_unused]] EModifierKey mods,
// [[maybe_unused]] bool isRepeat) noexcept {}
// virtual void specialKeyUp([[maybe_unused]] ESpecialKey key, [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void modKeyDown([[maybe_unused]] EModifierKey mod, [[maybe_unused]] bool isRepeat) noexcept {}
// virtual void modKeyUp([[maybe_unused]] EModifierKey mod) noexcept {}
// virtual void resized([[maybe_unused]] const WindowSize& rect, [[maybe_unused]] bool sync) noexcept {}
// virtual void mouseDown([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] EMouseButton button,
// [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void mouseUp([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] EMouseButton button,
// [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void mouseMove([[maybe_unused]] const SWindowCoord& coord) noexcept {}
// virtual void mouseEnter([[maybe_unused]] const SWindowCoord& coord) noexcept {}
// virtual void mouseLeave([[maybe_unused]] const SWindowCoord& coord) noexcept {}
// virtual void scroll([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] const SScrollDelta& scroll)
// noexcept {}
//
// virtual void touchDown([[maybe_unused]] const STouchCoord& coord, [[maybe_unused]] uintptr_t tid) noexcept {}
// virtual void touchUp([[maybe_unused]] const STouchCoord& coord, [[maybe_unused]] uintptr_t tid) noexcept {}
// virtual void touchMove([[maybe_unused]] const STouchCoord& coord, [[maybe_unused]] uintptr_t tid) noexcept {}
//
// virtual void charKeyDown([[maybe_unused]] unsigned long charCode, [[maybe_unused]] EModifierKey mods,
// [[maybe_unused]] bool isRepeat) noexcept {}
// virtual void charKeyUp([[maybe_unused]] unsigned long charCode, [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void specialKeyDown([[maybe_unused]] ESpecialKey key, [[maybe_unused]] EModifierKey mods,
// [[maybe_unused]] bool isRepeat) noexcept {}
// virtual void specialKeyUp([[maybe_unused]] ESpecialKey key, [[maybe_unused]] EModifierKey mods) noexcept {}
// virtual void modKeyDown([[maybe_unused]] EModifierKey mod, [[maybe_unused]] bool isRepeat) noexcept {}
// virtual void modKeyUp([[maybe_unused]] EModifierKey mod) noexcept {}
};
} // namespace aurora

View File

@ -10,10 +10,10 @@ void App_onAppWindowResized(AppDelegate& cb, const WindowSize& size) noexcept;
void App_onAppWindowMoved(AppDelegate& cb, int32_t x, int32_t y) noexcept;
void App_onAppExiting(AppDelegate& cb) noexcept;
// Input
void App_onCharKeyDown(AppDelegate& cb, uint8_t code, bool isRepeat) noexcept;
void App_onCharKeyUp(AppDelegate& cb, uint8_t code) noexcept;
void App_onSpecialKeyDown(AppDelegate& cb, SpecialKey key, bool isRepeat) noexcept;
void App_onSpecialKeyUp(AppDelegate& cb, SpecialKey key) noexcept;
void App_onCharKeyDown(AppDelegate& cb, uint8_t code, std::uint16_t mods, bool isRepeat) noexcept;
void App_onCharKeyUp(AppDelegate& cb, uint8_t code, std::uint16_t mods) noexcept;
void App_onSpecialKeyDown(AppDelegate& cb, SpecialKey key, std::uint16_t mods, bool isRepeat) noexcept;
void App_onSpecialKeyUp(AppDelegate& cb, SpecialKey key, std::uint16_t mods) noexcept;
// Controller
void App_onControllerAdded(AppDelegate& cb, uint32_t which) noexcept;
void App_onControllerRemoved(AppDelegate& cb, uint32_t which) noexcept;

View File

@ -5,35 +5,27 @@ void App_onAppLaunched(AppDelegate& cb) noexcept { return cb.onAppLaunched(); }
bool App_onAppIdle(AppDelegate& cb, float dt) noexcept { return cb.onAppIdle(dt); }
void App_onAppDraw(AppDelegate& cb) noexcept { cb.onAppDraw(); }
void App_onAppPostDraw(AppDelegate& cb) noexcept { cb.onAppPostDraw(); }
void App_onAppWindowResized(AppDelegate& cb, const WindowSize& size) noexcept {
cb.onAppWindowResized(size);
}
void App_onAppWindowMoved(AppDelegate& cb, int32_t x, int32_t y) noexcept {
cb.onAppWindowMoved(x, y);
}
void App_onAppWindowResized(AppDelegate& cb, const WindowSize& size) noexcept { cb.onAppWindowResized(size); }
void App_onAppWindowMoved(AppDelegate& cb, int32_t x, int32_t y) noexcept { cb.onAppWindowMoved(x, y); }
void App_onAppExiting(AppDelegate& cb) noexcept { cb.onAppExiting(); }
// Input
void App_onCharKeyDown(AppDelegate& cb, uint8_t code, bool isRepeat) noexcept {
cb.onCharKeyDown(code, isRepeat);
void App_onCharKeyDown(AppDelegate& cb, uint8_t code, std::uint16_t mods, bool isRepeat) noexcept {
cb.onCharKeyDown(code, static_cast<ModifierKey>(mods), isRepeat);
}
void App_onCharKeyUp(AppDelegate& cb, uint8_t code) noexcept {
cb.onCharKeyUp(code);
void App_onCharKeyUp(AppDelegate& cb, uint8_t code, std::uint16_t mods) noexcept {
cb.onCharKeyUp(code, static_cast<ModifierKey>(mods));
}
void App_onSpecialKeyDown(AppDelegate& cb, SpecialKey key, bool isRepeat) noexcept {
cb.onSpecialKeyDown(key, isRepeat);
void App_onSpecialKeyDown(AppDelegate& cb, SpecialKey key, std::uint16_t mods, bool isRepeat) noexcept {
cb.onSpecialKeyDown(key, static_cast<ModifierKey>(mods), isRepeat);
}
void App_onSpecialKeyUp(AppDelegate& cb, SpecialKey key) noexcept {
cb.onSpecialKeyUp(key);
void App_onSpecialKeyUp(AppDelegate& cb, SpecialKey key, std::uint16_t mods) noexcept {
cb.onSpecialKeyUp(key, static_cast<ModifierKey>(mods));
}
// Controller
void App_onControllerAdded(AppDelegate& cb, uint32_t which) noexcept {
cb.onControllerAdded(which);
}
void App_onControllerRemoved(AppDelegate& cb, uint32_t which) noexcept {
cb.onControllerRemoved(which);
}
void App_onControllerAdded(AppDelegate& cb, uint32_t which) noexcept { cb.onControllerAdded(which); }
void App_onControllerRemoved(AppDelegate& cb, uint32_t which) noexcept { cb.onControllerRemoved(which); }
void App_onControllerButton(AppDelegate& cb, uint32_t which, ControllerButton button, bool pressed) noexcept {
cb.onControllerButton(which, button, pressed);
}

View File

@ -1,15 +1,15 @@
use sdl2::controller::{Axis, Button};
use crate::{
app_run, get_args, get_backend, get_backend_string, get_dxt_compression_supported,
App, app_run, get_args, get_backend, get_backend_string,
get_dxt_compression_supported,
get_window_size,
sdl::{
get_controller_name,
get_controller_player_index,
set_controller_player_index,
is_controller_gamecube,
get_controller_name
},
set_fullscreen, set_window_title, App, WindowContext,
set_controller_player_index,
}, set_fullscreen, set_window_title, WindowContext,
};
#[cxx::bridge(namespace = "aurora")]
@ -29,14 +29,27 @@ pub(crate) mod ffi {
pub(crate) fn App_onAppWindowMoved(cb: Pin<&mut AppDelegate>, x: i32, y: i32);
pub(crate) fn App_onAppExiting(cb: Pin<&mut AppDelegate>);
// Input
pub(crate) fn App_onCharKeyDown(cb: Pin<&mut AppDelegate>, code: u8, is_repeat: bool);
pub(crate) fn App_onCharKeyUp(cb: Pin<&mut AppDelegate>, code: u8);
pub(crate) fn App_onCharKeyDown(cb: Pin<&mut AppDelegate>,
code: u8,
mods: u16,
is_repeat: bool,
);
pub(crate) fn App_onCharKeyUp(
cb: Pin<&mut AppDelegate>,
code: u8,
mods: u16,
);
pub(crate) fn App_onSpecialKeyDown(
cb: Pin<&mut AppDelegate>,
key: SpecialKey,
keymod: u16,
is_repeat: bool,
);
pub(crate) fn App_onSpecialKeyUp(cb: Pin<&mut AppDelegate>, key: SpecialKey);
pub(crate) fn App_onSpecialKeyUp(
cb: Pin<&mut AppDelegate>,
key: SpecialKey,
mods: u16,
);
// Controller
pub(crate) fn App_onControllerAdded(cb: Pin<&mut AppDelegate>, which: u32);
pub(crate) fn App_onControllerRemoved(cb: Pin<&mut AppDelegate>, which: u32);
@ -100,26 +113,70 @@ pub(crate) mod ffi {
F10 = 10,
F11 = 11,
F12 = 12,
Esc = 13,
Enter = 14,
Backspace = 15,
Insert = 16,
Delete = 17,
Home = 18,
End = 19,
PgUp = 20,
PgDown = 21,
Left = 22,
Right = 23,
Up = 24,
Down = 25,
Tab = 26,
}
pub struct KeyboardInput {
pub scancode: u32,
pub state: ElementState,
// pub
F13 = 13,
F14 = 14,
F15 = 15,
F16 = 16,
F17 = 17,
F18 = 18,
F19 = 19,
F20 = 20,
F21 = 21,
F22 = 22,
F23 = 23,
F24 = 24,
Esc = 25,
Enter = 26,
Backspace = 27,
Insert = 28,
Delete = 29,
Home = 30,
End = 31,
PgUp = 32,
PgDown = 33,
Left = 34,
Right = 35,
Up = 36,
Down = 37,
Tab = 38,
PrintScreen = 39,
ScrollLock = 40,
Pause = 41,
NumLockClear = 42,
KpDivide = 43,
KpMultiply = 44,
KpMinus = 45,
KpPlus = 46,
KpEnter = 47,
KpNum0 = 48,
KpNum1 = 49,
KpNum2 = 51,
KpNum3 = 52,
KpNum4 = 53,
KpNum5 = 54,
KpNum6 = 55,
KpNum7 = 56,
KpNum8 = 57,
KpNum9 = 58,
KpPercent = 59,
KpPeriod = 60,
KpComma = 61,
KpEquals = 62,
Application = 63,
Power = 64,
Execute = 65,
Help = 66,
Menu = 67,
Select = 68,
Stop = 69,
Again = 70,
Undo = 71,
Cut = 72,
Paste = 73,
Find = 74,
VolumeUp = 75,
VolumeDown = 76,
MAX,
}
pub enum ControllerButton {

View File

@ -2,6 +2,7 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(unused_unsafe)]
#![allow(non_upper_case_globals)]
use std::time::Instant;
@ -58,7 +59,6 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
let sdl = initialize_sdl();
let gpu = initialize_gpu(&window);
let imgui = initialize_imgui(&window, &gpu);
let mut special_keys_pressed: [bool; 512] = [false; 512];
shaders::construct_state(gpu.device.clone(), gpu.queue.clone(), &gpu.config);
let app =
App { window: ffi::Window { inner: Box::new(WindowContext { window }) }, gpu, imgui, sdl };
@ -119,65 +119,6 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
Event::WindowEvent { event: WindowEvent::Moved(loc), .. } => unsafe {
ffi::App_onAppWindowMoved(delegate.as_mut().unwrap_unchecked(), loc.x, loc.y);
},
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input: KeyboardInput { scancode, virtual_keycode: Some(key), state, .. },
..
},
..
} => {
// TODO: Handle normal keys, this will require a refactor in game runtime code
let special_key = match key {
VirtualKeyCode::F1 => ffi::SpecialKey::F1,
VirtualKeyCode::F2 => ffi::SpecialKey::F2,
VirtualKeyCode::F3 => ffi::SpecialKey::F3,
VirtualKeyCode::F4 => ffi::SpecialKey::F4,
VirtualKeyCode::F5 => ffi::SpecialKey::F5,
VirtualKeyCode::F6 => ffi::SpecialKey::F6,
VirtualKeyCode::F7 => ffi::SpecialKey::F7,
VirtualKeyCode::F8 => ffi::SpecialKey::F8,
VirtualKeyCode::F9 => ffi::SpecialKey::F9,
VirtualKeyCode::F10 => ffi::SpecialKey::F10,
VirtualKeyCode::F11 => ffi::SpecialKey::F11,
VirtualKeyCode::F12 => ffi::SpecialKey::F12,
VirtualKeyCode::Escape => ffi::SpecialKey::Esc,
VirtualKeyCode::Return => ffi::SpecialKey::Enter,
VirtualKeyCode::Back => ffi::SpecialKey::Backspace,
VirtualKeyCode::Insert => ffi::SpecialKey::Insert,
VirtualKeyCode::Delete => ffi::SpecialKey::Delete,
VirtualKeyCode::Home => ffi::SpecialKey::Home,
VirtualKeyCode::PageUp => ffi::SpecialKey::PgUp,
VirtualKeyCode::PageDown => ffi::SpecialKey::PgDown,
VirtualKeyCode::Left => ffi::SpecialKey::Left,
VirtualKeyCode::Right => ffi::SpecialKey::Right,
VirtualKeyCode::Up => ffi::SpecialKey::Up,
VirtualKeyCode::Down => ffi::SpecialKey::Down,
VirtualKeyCode::Tab => ffi::SpecialKey::Tab,
_ => ffi::SpecialKey::None,
};
if special_key != ffi::SpecialKey::None {
let pressed = state == ElementState::Pressed;
let repeat = special_keys_pressed[key as usize] == pressed;
special_keys_pressed[key as usize] = pressed;
unsafe {
if pressed {
ffi::App_onSpecialKeyDown(
delegate.as_mut().unwrap_unchecked(),
special_key,
repeat,
);
} else {
ffi::App_onSpecialKeyUp(
delegate.as_mut().unwrap_unchecked(),
special_key,
);
}
}
}
}
Event::MainEventsCleared => {
log::trace!("Requesting redraw");
window_ctx.window.request_redraw();

View File

@ -1,12 +1,13 @@
use std::collections::{BTreeMap, HashMap};
use bitflags::bitflags;
use sdl2::{
controller::{Axis, GameController},
event::Event,
GameControllerSubsystem, Sdl,
};
use sdl2::keyboard::{Keycode, Mod};
use crate::{cxxbridge::ffi, get_app};
use crate::ffi::SpecialKey;
pub(crate) struct SdlState {
context: Sdl,
@ -21,6 +22,126 @@ pub(crate) fn initialize_sdl() -> SdlState {
let controller_sys = context.game_controller().unwrap();
SdlState { context, events, controller_sys, open_controllers: Default::default() }
}
bitflags! {
pub struct ModifierKey : u16 {
const None = 0;
const LeftShift = 0x0001;
const RightShift = 0x0002;
const LeftControl = 0x0004;
const RightControl = 0x0008;
const LeftAlt = 0x0010;
const RightAlt = 0x0020;
const LeftGui = 0x0040;
const RightGui = 0x0080;
const Num = 0x0100;
const Caps = 0x0200;
const Mode = 0x0400;
// SDL has a reserved value we don't need
}
}
fn translate_modifiers(keymod: Mod) -> ModifierKey {
let mut use_mod: ModifierKey = ModifierKey::None;
if keymod.contains(Mod::LSHIFTMOD) {
use_mod.insert(ModifierKey::LeftShift);
}
if keymod.contains(Mod::RSHIFTMOD) {
use_mod.insert(ModifierKey::RightShift);
}
if keymod.contains(Mod::LCTRLMOD) {
use_mod.insert(ModifierKey::LeftControl);
}
if keymod.contains(Mod::RCTRLMOD) {
use_mod.insert(ModifierKey::RightControl);
}
if keymod.contains(Mod::LALTMOD) {
use_mod.insert(ModifierKey::LeftAlt);
}
if keymod.contains(Mod::RALTMOD) {
use_mod.insert(ModifierKey::RightAlt);
}
if keymod.contains(Mod::LGUIMOD) {
use_mod.insert(ModifierKey::LeftGui);
}
if keymod.contains(Mod::RGUIMOD) {
use_mod.insert(ModifierKey::RightGui);
}
if keymod.contains(Mod::NUMMOD) {
use_mod.insert(ModifierKey::Num);
}
if keymod.contains(Mod::CAPSMOD) {
use_mod.insert(ModifierKey::Caps);
}
if keymod.contains(Mod::MODEMOD) {
use_mod.insert(ModifierKey::Mode);
}
use_mod as ModifierKey
}
fn translate_special_key(keycode: Keycode) -> ffi::SpecialKey {
match keycode {
Keycode::F1 => ffi::SpecialKey::F1,
Keycode::F2 => ffi::SpecialKey::F2,
Keycode::F3 => ffi::SpecialKey::F3,
Keycode::F4 => ffi::SpecialKey::F4,
Keycode::F5 => ffi::SpecialKey::F5,
Keycode::F6 => ffi::SpecialKey::F6,
Keycode::F7 => ffi::SpecialKey::F7,
Keycode::F8 => ffi::SpecialKey::F8,
Keycode::F9 => ffi::SpecialKey::F9,
Keycode::F10 => ffi::SpecialKey::F10,
Keycode::F11 => ffi::SpecialKey::F11,
Keycode::F12 => ffi::SpecialKey::F12,
Keycode::F13 => ffi::SpecialKey::F13,
Keycode::F14 => ffi::SpecialKey::F14,
Keycode::F15 => ffi::SpecialKey::F15,
Keycode::F16 => ffi::SpecialKey::F16,
Keycode::F17 => ffi::SpecialKey::F17,
Keycode::F18 => ffi::SpecialKey::F18,
Keycode::F19 => ffi::SpecialKey::F19,
Keycode::F20 => ffi::SpecialKey::F20,
Keycode::F21 => ffi::SpecialKey::F21,
Keycode::F22 => ffi::SpecialKey::F22,
Keycode::F23 => ffi::SpecialKey::F23,
Keycode::F24 => ffi::SpecialKey::F23,
Keycode::Escape => ffi::SpecialKey::Esc,
Keycode::Return => ffi::SpecialKey::Enter,
Keycode::Backspace => ffi::SpecialKey::Backspace,
Keycode::Insert => ffi::SpecialKey::Insert,
Keycode::Delete => ffi::SpecialKey::Delete,
Keycode::Home => ffi::SpecialKey::Home,
Keycode::End => ffi::SpecialKey::End,
Keycode::PageUp => ffi::SpecialKey::PgUp,
Keycode::PageDown => ffi::SpecialKey::PgDown,
Keycode::Left => ffi::SpecialKey::Left,
Keycode::Right => ffi::SpecialKey::Right,
Keycode::Up => ffi::SpecialKey::Up,
Keycode::Down => ffi::SpecialKey::Down,
Keycode::Tab => ffi::SpecialKey::Tab,
Keycode::PrintScreen => ffi::SpecialKey::PrintScreen,
Keycode::ScrollLock => ffi::SpecialKey::ScrollLock,
Keycode::Pause => ffi::SpecialKey::Pause,
Keycode::NumLockClear => ffi::SpecialKey::NumLockClear,
Keycode::KpDivide => ffi::SpecialKey::KpDivide,
Keycode::KpMultiply => ffi::SpecialKey::KpMultiply,
Keycode::KpMinus => ffi::SpecialKey::KpMinus,
Keycode::KpPlus => ffi::SpecialKey::KpPlus,
Keycode::KpEquals => ffi::SpecialKey::KpEquals,
Keycode::Kp0 => ffi::SpecialKey::KpNum0,
Keycode::Kp1 => ffi::SpecialKey::KpNum1,
Keycode::Kp2 => ffi::SpecialKey::KpNum2,
Keycode::Kp3 => ffi::SpecialKey::KpNum3,
Keycode::Kp4 => ffi::SpecialKey::KpNum4,
Keycode::Kp5 => ffi::SpecialKey::KpNum5,
Keycode::Kp6 => ffi::SpecialKey::KpNum6,
Keycode::Kp7 => ffi::SpecialKey::KpNum7,
Keycode::Kp8 => ffi::SpecialKey::KpNum8,
Keycode::Kp9 => ffi::SpecialKey::KpNum9,
Keycode::KpPeriod => ffi::SpecialKey::KpPeriod,
_ => ffi::SpecialKey::None,
}
}
pub(crate) fn poll_sdl_events(
state: &mut SdlState,
@ -75,6 +196,48 @@ pub(crate) fn poll_sdl_events(
value,
);
},
Event::KeyDown { keycode, keymod, repeat, .. } => {
let special_key = translate_special_key(keycode.unwrap());
let use_mod = translate_modifiers(keymod);
if special_key != ffi::SpecialKey::None {
unsafe {
ffi::App_onSpecialKeyDown(delegate.as_mut().unwrap_unchecked(),
special_key,
use_mod.bits,
repeat);
}
} else {
let tmp = keycode.unwrap() as u8;
if tmp >= '\x20' as u8 && tmp <= 'z' as u8 {
unsafe {
ffi::App_onCharKeyDown(delegate.as_mut().unwrap_unchecked(),
tmp,
use_mod.bits,
repeat);
}
}
}
},
Event::KeyUp { keycode, keymod, .. } => {
let special_key = translate_special_key(keycode.unwrap());
let use_mod = translate_modifiers(keymod);
if special_key != ffi::SpecialKey::None {
unsafe {
ffi::App_onSpecialKeyUp(delegate.as_mut().unwrap_unchecked(),
special_key,
use_mod.bits);
}
} else {
let tmp = keycode.unwrap() as u8;
if tmp >= '\x20' as u8 && tmp <= 'z' as u8 {
unsafe {
ffi::App_onCharKeyUp(delegate.as_mut().unwrap_unchecked(),
tmp,
use_mod.bits);
}
}
}
},
// SDL overrides exit signals
Event::Quit { .. } => {
return false;
@ -142,7 +305,6 @@ pub(crate) fn is_controller_gamecube(which: u32) -> bool {
.map_or(false, |c| c.name()
.to_lowercase()
.eq("nintendo gamecube controller"))
}
pub(crate) fn get_controller_name(which: u32) -> String {

View File

@ -0,0 +1,319 @@
use std::{collections::HashMap, hash::Hash, ops::Range};
use bytemuck_derive::{Pod, Zeroable};
use wgpu::{include_wgsl, vertex_attr_array};
use crate::{
get_app,
gpu::GraphicsConfig,
shaders::{
bind_pipeline, cxxbridge::ffi, get_combined_matrix, pipeline_ref, push_draw_command,
push_uniform, push_verts, texture::create_sampler, BuiltBuffers, PipelineCreateCommand,
PipelineHolder, PipelineRef, ShaderDrawCommand, STATE,
},
util::{align, Vec2, Vec3},
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, CVector4f},
};
#[derive(Debug, Clone)]
pub(crate) struct DrawData {
pipeline: PipelineRef,
vert_range: Range<u64>,
uniform_range: Range<u64>,
}
#[derive(Hash)]
pub(crate) struct PipelineConfig {
filter_type: ffi::CameraFilterType,
z_comparison: ffi::ZTest,
z_test: bool,
}
pub(crate) const INITIAL_PIPELINES: &[PipelineCreateCommand] = &[
// PipelineCreateCommand::ColoredQuad(PipelineConfig { z_only: false }),
// PipelineCreateCommand::ColoredQuad(PipelineConfig { z_only: true }),
];
pub(crate) struct State {
shader: wgpu::ShaderModule,
uniform_layout: wgpu::BindGroupLayout,
uniform_bind_group: wgpu::BindGroup,
sampler: wgpu::Sampler,
pipeline_layout: wgpu::PipelineLayout,
}
pub(crate) fn construct_state(
device: &wgpu::Device,
_queue: &wgpu::Queue,
buffers: &BuiltBuffers,
graphics_config: &GraphicsConfig,
) -> State {
let shader = device.create_shader_module(&include_wgsl!("shader.wgsl"));
let uniform_alignment = device.limits().min_uniform_buffer_offset_alignment;
let uniform_size = wgpu::BufferSize::new(align(
std::mem::size_of::<Uniform>() as u64,
uniform_alignment as u64,
));
let uniform_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("Colored Quad Uniform Bind Group Layout"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: true,
min_binding_size: uniform_size,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: None,
},
],
});
let sampler = create_sampler(device, wgpu::AddressMode::Repeat, None);
let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Colored Quad Uniform Bind Group"),
layout: &uniform_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
buffer: &buffers.uniform_buffer,
offset: 0, // dynamic
size: uniform_size,
}),
},
wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Sampler(&sampler) },
],
});
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("Colored Quad Pipeline Layout"),
bind_group_layouts: &[&uniform_layout],
push_constant_ranges: &[],
});
State {
shader,
uniform_layout,
uniform_bind_group,
sampler,
pipeline_layout,
}
}
pub(crate) fn construct_pipeline(
device: &wgpu::Device,
graphics: &GraphicsConfig,
state: &State,
config: &PipelineConfig,
) -> PipelineHolder {
let (blend_component, alpha_write) = match config.filter_type {
ffi::CameraFilterType::Multiply => (
wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::Zero,
dst_factor: wgpu::BlendFactor::Src,
operation: wgpu::BlendOperation::Add,
},
true,
),
ffi::CameraFilterType::Add => (
wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::One,
operation: wgpu::BlendOperation::Add,
},
false,
),
ffi::CameraFilterType::Subtract => (
wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::One,
operation: wgpu::BlendOperation::Subtract,
},
false,
),
ffi::CameraFilterType::Blend => (
wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
operation: wgpu::BlendOperation::Add,
},
false,
),
ffi::CameraFilterType::InvDstMultiply => (
wgpu::BlendComponent {
src_factor: wgpu::BlendFactor::Zero,
dst_factor: wgpu::BlendFactor::OneMinusSrc,
operation: wgpu::BlendOperation::Add,
},
true,
),
_ => todo!(),
};
PipelineHolder {
pipeline: device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: Some("Colored Quad Pipeline"),
layout: Some(&state.pipeline_layout),
vertex: wgpu::VertexState {
module: &state.shader,
entry_point: "vs_main",
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vert>() as u64,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &vertex_attr_array![0 => Float32x3],
}],
},
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleStrip,
..Default::default()
},
depth_stencil: Some(wgpu::DepthStencilState {
format: graphics.depth_format,
depth_write_enabled: config.z_test,
depth_compare: match config.z_comparison {
ffi::ZTest::Never => wgpu::CompareFunction::Never,
ffi::ZTest::Less => wgpu::CompareFunction::Less,
ffi::ZTest::Equal => wgpu::CompareFunction::Equal,
ffi::ZTest::LEqual => wgpu::CompareFunction::LessEqual,
ffi::ZTest::Greater => wgpu::CompareFunction::Greater,
ffi::ZTest::NEqual => wgpu::CompareFunction::NotEqual,
ffi::ZTest::GEqual => wgpu::CompareFunction::GreaterEqual,
ffi::ZTest::Always => wgpu::CompareFunction::Always,
_ => todo!(),
},
stencil: Default::default(),
bias: Default::default(),
}),
multisample: wgpu::MultisampleState {
count: graphics.msaa_samples,
..Default::default()
},
fragment: Some(wgpu::FragmentState {
module: &state.shader,
entry_point: "fs_main",
targets: &[wgpu::ColorTargetState {
format: graphics.color_format,
blend: Some(wgpu::BlendState {
color: blend_component,
alpha: blend_component,
}),
write_mask: if alpha_write {
wgpu::ColorWrites::ALL
} else {
wgpu::ColorWrites::COLOR
},
}],
}),
multiview: None,
}),
}
}
#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)]
#[repr(C)]
struct Uniform {
xf: CMatrix4f,
color: CColor,
}
#[derive(Pod, Zeroable, Copy, Clone, Default, Debug)]
#[repr(C)]
struct Vert {
pos: Vec3<f32>,
//norm: Vec3<f32>,
}
pub(crate) fn queue_colored_quad(
filter_type: ffi::CameraFilterType,
z_comparison: ffi::ZTest,
z_test: bool,
color: CColor,
rect: CRectangle,
z: f32,
) {
let pipeline = pipeline_ref(&PipelineCreateCommand::ColoredQuad(PipelineConfig {
filter_type,
z_comparison,
z_test,
}));
let vert_range = push_verts(&[
Vert { pos: Vec3::new(0.0, 0.0, z) },
Vert { pos: Vec3::new(0.0, 1.0, z) },
Vert { pos: Vec3::new(1.0, 0.0, z) },
Vert { pos: Vec3::new(1.0, 1.0, z) },
]);
let uniform_range = push_uniform(&Uniform {
xf: CMatrix4f::new(
CVector4f::new(rect.size.x * 2.0, 0.0, 0.0, 0.0),
CVector4f::new(0.0, rect.size.y * 2.0, 0.0, 0.0),
CVector4f::new(0.0, 0.0, 1.0, 0.0),
CVector4f::new(rect.position.x * 2.0 - 1.0, rect.position.y * 2.0 - 1.0, 0.0, 1.0),
),
color,
});
push_colored_quad(pipeline, vert_range, uniform_range);
}
pub(crate) fn queue_colored_quad_verts(
filter_type: ffi::CameraFilterType,
z_comparison: ffi::ZTest,
z_test: bool,
color: CColor,
pos: &[CVector3f],
) {
if pos.len() != 4 {
panic!("Invalid pos: {}", pos.len());
}
let pipeline = pipeline_ref(&PipelineCreateCommand::ColoredQuad(PipelineConfig {
filter_type,
z_comparison,
z_test,
}));
let vert_range = push_verts(
&pos.iter().map(|pos| Vert { pos: pos.into() })
.collect::<Vec<Vert>>(),
);
let uniform_range = push_uniform(&Uniform { xf: get_combined_matrix(), color});
push_colored_quad(pipeline, vert_range, uniform_range);
}
fn push_colored_quad(
pipeline: PipelineRef,
vert_range: Range<u64>,
uniform_range: Range<u64>,
) {
// TODO defer bind group creation to draw time or another thread?
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
push_draw_command(ShaderDrawCommand::ColoredQuad(DrawData {
pipeline,
vert_range,
uniform_range,
}));
}
pub(crate) fn draw_colored_quad<'a>(
data: &DrawData,
state: &'a State,
pass: &mut wgpu::RenderPass<'a>,
buffers: &'a BuiltBuffers,
) {
if !bind_pipeline(data.pipeline, pass) {
return;
}
// Uniform bind group
pass.set_bind_group(0, &state.uniform_bind_group, &[
data.uniform_range.start as wgpu::DynamicOffset
]);
// Vertex buffer
pass.set_vertex_buffer(0, buffers.vertex_buffer.slice(data.vert_range.clone()));
pass.draw(0..4, 0..1);
}

View File

@ -0,0 +1,24 @@
struct Uniform {
xf: mat4x4<f32>;
color: vec4<f32>;
};
@group(0) @binding(0)
var<uniform> ubuf: Uniform;
struct VertexOutput {
@builtin(position) pos: vec4<f32>;
//@builtin(normal) norm: vec4<f32>;
};
@stage(vertex)
fn vs_main(@location(0) in_pos: vec3<f32>) -> VertexOutput {//, @location(1) in_norm: vec3<f32>) -> VertexOutput {
var out: VertexOutput;
out.pos = ubuf.xf * vec4<f32>(in_pos, 1.0);
//out.norm = in_norm;
return out;
}
@stage(fragment)
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
return ubuf.color;
}

View File

@ -10,6 +10,7 @@ use crate::shaders::{
write_texture,
},
textured_quad::{queue_textured_quad, queue_textured_quad_verts},
colored_quad::{queue_colored_quad, queue_colored_quad_verts},
update_fog_state, update_model_view, update_projection,
};
@ -190,6 +191,21 @@ pub(crate) mod ffi {
rect: CRectangle,
z: f32,
);
fn queue_colored_quad_verts(
filter_type: CameraFilterType,
z_comparison: ZTest,
z_test: bool,
color: CColor,
pos: &[CVector3f],
);
fn queue_colored_quad(
filter_type: CameraFilterType,
z_comparison: ZTest,
z_test: bool,
color: CColor,
rect: CRectangle,
z: f32,
);
fn queue_movie_player(
tex_y: TextureRef,
tex_u: TextureRef,

View File

@ -25,6 +25,7 @@ mod model;
mod movie_player;
mod texture;
mod textured_quad;
mod colored_quad;
#[derive(Debug, Copy, Clone)]
enum ColoredStripMode {
@ -33,6 +34,7 @@ enum ColoredStripMode {
FullAdditive,
Subtractive,
}
#[derive(Debug, Copy, Clone)]
struct ColoredStripVert {
position: CVector3f,
@ -46,6 +48,7 @@ enum Command {
SetScissor(u32, u32, u32, u32),
Draw(ShaderDrawCommand),
}
#[derive(Debug, Clone)]
enum ShaderDrawCommand {
Aabb(aabb::DrawData),
@ -53,21 +56,17 @@ enum ShaderDrawCommand {
amount: f32,
clear_depth: bool,
},
ColoredQuadFilter {
filter_type: ffi::CameraFilterType,
color: CColor,
rect: CRectangle,
},
ColoredQuad(colored_quad::DrawData),
ColoredStripFilter {
mode: ColoredStripMode,
verts: Vec<ColoredStripVert>,
color: CColor,
},
Decal {/* TODO */},
ElementGen {/* TODO */},
EnergyBar {/* TODO */},
EnvFx {/* TODO */},
FluidPlane {/* TODO */},
Decal { /* TODO */ },
ElementGen { /* TODO */ },
EnergyBar { /* TODO */ },
EnvFx { /* TODO */ },
FluidPlane { /* TODO */ },
FogVolumeFilter {
two_way: bool,
color: CColor,
@ -76,8 +75,8 @@ enum ShaderDrawCommand {
pass: u8,
verts: Vec<CVector3f>,
},
LineRenderer {/* TODO */},
MapSurface {/* TODO */},
LineRenderer { /* TODO */ },
MapSurface { /* TODO */ },
Model {
pipeline_id: u32,
material_id: u32,
@ -88,13 +87,13 @@ enum ShaderDrawCommand {
model_flags: u32,
},
MoviePlayer(movie_player::DrawData),
NES {/* TODO */},
ParticleSwoosh {/* TODO */},
PhazonSuitFilter {/* TODO */},
RadarPaint {/* TODO */},
RandomStaticFilter {/* TODO */},
ScanLinesFilter {/* TODO */},
TextSupport {/* TODO */},
NES { /* TODO */ },
ParticleSwoosh { /* TODO */ },
PhazonSuitFilter { /* TODO */ },
RadarPaint { /* TODO */ },
RandomStaticFilter { /* TODO */ },
ScanLinesFilter { /* TODO */ },
TextSupport { /* TODO */ },
TexturedQuad(textured_quad::DrawData),
ThermalCold,
ThermalHot,
@ -123,9 +122,11 @@ struct RenderState {
render_textures: HashMap<u32, RenderTexture>,
// Shader states
aabb: aabb::State,
colored_quad: colored_quad::State,
textured_quad: textured_quad::State,
movie_player: movie_player::State,
}
pub(crate) fn construct_state(
device: Arc<wgpu::Device>,
queue: Arc<wgpu::Queue>,
@ -147,6 +148,7 @@ pub(crate) fn construct_state(
}),
};
let aabb = aabb::construct_state(&device, &queue, &buffers, graphics_config);
let colored_quad = colored_quad::construct_state(&device, &queue, &buffers, graphics_config);
let textured_quad = textured_quad::construct_state(&device, &queue, &buffers, graphics_config);
let movie_player = movie_player::construct_state(&device, &queue, &buffers, graphics_config);
let mut state = RenderState {
@ -162,6 +164,7 @@ pub(crate) fn construct_state(
textures: Default::default(),
render_textures: Default::default(),
aabb,
colored_quad,
textured_quad,
movie_player,
};
@ -268,18 +271,22 @@ struct PipelineRef {
pub(crate) enum PipelineCreateCommand {
Aabb(aabb::PipelineConfig),
ColoredQuad(colored_quad::PipelineConfig),
TexturedQuad(textured_quad::PipelineConfig),
MoviePlayer(movie_player::PipelineConfig),
}
#[inline(always)]
fn hash_with_seed<T: Hash>(value: &T, seed: u64) -> u64 {
let mut state = Xxh3Hash64::with_seed(seed);
value.hash(&mut state);
state.finish()
}
fn construct_pipeline(state: &mut RenderState, cmd: &PipelineCreateCommand) -> u64 {
let id = match cmd {
PipelineCreateCommand::Aabb(ref config) => hash_with_seed(config, 0xAABB),
PipelineCreateCommand::ColoredQuad(ref config) => hash_with_seed(config, 0xC013B),
PipelineCreateCommand::TexturedQuad(ref config) => hash_with_seed(config, 0xEEAD),
PipelineCreateCommand::MoviePlayer(ref config) => hash_with_seed(config, 0xFAAE),
};
@ -291,6 +298,12 @@ fn construct_pipeline(state: &mut RenderState, cmd: &PipelineCreateCommand) -> u
&state.aabb,
config,
),
PipelineCreateCommand::ColoredQuad(ref config) => colored_quad::construct_pipeline(
state.device.as_ref(),
&state.graphics_config,
&state.colored_quad,
config,
),
PipelineCreateCommand::TexturedQuad(ref config) => textured_quad::construct_pipeline(
state.device.as_ref(),
&state.graphics_config,
@ -356,6 +369,9 @@ pub(crate) fn render_into_pass(pass: &mut wgpu::RenderPass) {
ShaderDrawCommand::Aabb(data) => {
aabb::draw_aabb(data, &state.aabb, pass, &state.buffers);
}
ShaderDrawCommand::ColoredQuad(data) => {
colored_quad::draw_colored_quad(data, &state.colored_quad, pass, &state.buffers);
}
ShaderDrawCommand::TexturedQuad(data) => {
textured_quad::draw_textured_quad(
data,
@ -385,22 +401,29 @@ fn update_model_view(mv: CMatrix4f, mv_inv: CMatrix4f) {
global_buffers.global_current.mv_inv = mv_inv;
global_buffers.global_dirty = true;
}
fn update_projection(proj: CMatrix4f) {
let global_buffers = unsafe { &mut GLOBAL_BUFFERS };
global_buffers.global_current.proj = proj;
global_buffers.global_dirty = true;
}
fn update_fog_state(state: ffi::FogState) {
let global_buffers = unsafe { &mut GLOBAL_BUFFERS };
global_buffers.global_current.fog = state;
global_buffers.global_dirty = true;
}
fn get_projection_matrix() -> CMatrix4f {
let global_buffers = unsafe { &GLOBAL_BUFFERS };
global_buffers.global_current.proj
}
fn get_combined_matrix() -> CMatrix4f {
let global_buffers = unsafe { &GLOBAL_BUFFERS };
CMatrix4f::from(
cgmath::Matrix4::from(global_buffers.global_current.mv)
* cgmath::Matrix4::from(global_buffers.global_current.proj),
cgmath::Matrix4::from(global_buffers.global_current.proj)
* cgmath::Matrix4::from(global_buffers.global_current.mv),
)
}
@ -417,10 +440,12 @@ fn push_draw_command(cmd: ShaderDrawCommand) {
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
state.commands.push_back(Command::Draw(cmd));
}
fn set_viewport(rect: CRectangle, znear: f32, zfar: f32) {
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
state.commands.push_back(Command::SetViewport(rect, znear, zfar));
}
fn set_scissor(x: u32, y: u32, w: u32, h: u32) {
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
state.commands.push_back(Command::SetScissor(x, y, w, h));
@ -429,6 +454,7 @@ fn set_scissor(x: u32, y: u32, w: u32, h: u32) {
fn resolve_color(rect: ffi::ClipRect, bind: u32, clear_depth: bool) {
// TODO
}
fn resolve_depth(rect: ffi::ClipRect, bind: u32) {
// TODO
}

View File

@ -3,7 +3,6 @@
#include <numeric>
#include <iostream>
#include "boo/boo.hpp"
#include "logvisor/logvisor.hpp"
#include "ImGuiEngine.hpp"
@ -144,7 +143,7 @@ static std::string CPUFeatureString(const zeus::CPUInfo& cpuInf) {
#endif
return features;
}
#if 0
struct WindowCallback : boo::IWindowCallback {
friend struct Application;
@ -246,28 +245,27 @@ private:
void destroyed() override { m_windowInvalid = true; }
};
#endif
struct Application : aurora::AppDelegate {
private:
WindowCallback m_windowCallback;
hecl::Runtime::FileStoreManager& m_fileMgr;
hecl::CVarManager& m_cvarManager;
hecl::CVarCommons& m_cvarCommons;
ImGuiConsole m_imGuiConsole;
std::string m_errorString;
// boo::ObjToken<boo::ITextureR> m_renderTex;
std::string m_deferredProject;
bool m_projectInitialized = false;
// std::unique_ptr<hecl::Database::Project> m_proj;
std::optional<amuse::BooBackendVoiceAllocator> m_amuseAllocWrapper;
std::unique_ptr<boo::IAudioVoiceEngine> m_voiceEngine;
// std::unique_ptr<hecl::PipelineConverterBase> m_pipelineConv;
Limiter m_limiter{};
bool m_noShaderWarmup = false;
bool m_firstFrame = true;
bool m_fullscreenToggleRequested = false;
bool m_quitRequested = false;
using delta_clock = std::chrono::high_resolution_clock;
std::chrono::time_point<delta_clock> m_prevFrameTime;
@ -361,9 +359,9 @@ public:
OPTICK_FRAME("MainThread");
// Check if fullscreen has been toggled, if so set the fullscreen cvar accordingly
if (m_windowCallback.m_fullscreenToggleRequested) {
if (m_fullscreenToggleRequested) {
m_cvarCommons.m_fullscreen->fromBoolean(!m_cvarCommons.getFullscreen());
m_windowCallback.m_fullscreenToggleRequested = false;
m_fullscreenToggleRequested = false;
}
// Check if the user has modified the fullscreen CVar, if so set fullscreen state accordingly
@ -397,6 +395,14 @@ public:
m_imGuiConsole.ShowAboutWindow(false, m_errorString);
}
if (m_quitRequested) {
if (g_mainMP1) {
g_mainMP1->Quit();
} else {
return false;
}
}
return true;
}
@ -469,48 +475,48 @@ public:
CDvdFile::Shutdown();
}
void onCharKeyDown(uint8_t code, bool isRepeat) noexcept override {
void onCharKeyDown(uint8_t code, aurora::ModifierKey mods, bool isRepeat) noexcept override {
Log.report(logvisor::Info, FMT_STRING("DEBUG CHAR KEYS: '{}', isRepeat {}"), static_cast<char>(code), isRepeat);
// if (!ImGuiWindowCallback::m_keyboardCaptured && g_mainMP1) {
if (g_mainMP1) {
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
as->charKeyDown(code, boo::EModifierKey::None, isRepeat);
as->charKeyDown(code, mods, isRepeat);
}
}
// }
}
void onCharKeyUp(uint8_t code) noexcept override {
void onCharKeyUp(uint8_t code, aurora::ModifierKey mods) noexcept override {
Log.report(logvisor::Info, FMT_STRING("DEBUG CHAR KEYS: '{}'"), static_cast<char>(code));
if (g_mainMP1) {
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
as->charKeyUp(code, boo::EModifierKey::None);
as->charKeyUp(code, mods);
}
}
}
void onSpecialKeyDown(aurora::SpecialKey key, bool isRepeat) noexcept override {
void onSpecialKeyDown(aurora::SpecialKey key, aurora::ModifierKey mods, bool isRepeat) noexcept override {
Log.report(logvisor::Info, FMT_STRING("DEBUG KEYS: SpecialKey {}, isRepeat {}"), key, isRepeat);
/* TODO: Temporarily convert the aurora enum to boo's until we refactor everything */
if (g_mainMP1) {
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
as->specialKeyDown(boo::ESpecialKey(key), boo::EModifierKey::None, isRepeat);
as->specialKeyDown(key, mods, isRepeat);
}
}
if (True(mods & (aurora::ModifierKey::LeftAlt | aurora::ModifierKey::RightAlt))) {
if (key == aurora::SpecialKey::Enter) {
m_fullscreenToggleRequested = true;
} else if (key == aurora::SpecialKey::F4) {
m_quitRequested = true;
}
}
// if (True(mods & boo::EModifierKey::Alt)) {
// if (key == boo::ESpecialKey::Enter) {
// m_fullscreenToggleRequested = true;
// } else if (key == boo::ESpecialKey::F4) {
// m_windowInvalid = true;
// }
// }
}
void onSpecialKeyUp(aurora::SpecialKey key) noexcept override {
void onSpecialKeyUp(aurora::SpecialKey key, aurora::ModifierKey mods) noexcept override {
/* TODO: Temporarily convert the aurora enum to boo's until we refactor everything */
if (g_mainMP1) {
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
as->specialKeyUp(boo::ESpecialKey(key), boo::EModifierKey::None);
as->specialKeyUp(key, mods);
}
}
}

View File

@ -1,4 +1,9 @@
#include "Runtime/GuiSys/CGuiPane.hpp"
#include "Runtime/GuiSys/CGuiWidgetDrawParms.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
#include <aurora_shaders.h>
namespace metaforce {
@ -7,32 +12,45 @@ CGuiPane::CGuiPane(const CGuiWidgetParms& parms, const zeus::CVector2f& dim, con
CGuiPane::InitializeBuffers();
}
void CGuiPane::Draw(const CGuiWidgetDrawParms& parms) {
CGraphics::SetModelMatrix(x34_worldXF * zeus::CTransform::Translate(xc8_scaleCenter));
if (GetIsVisible()) {
auto col = xa8_color2;
col.a() = parms.x0_alphaMod * xa8_color2.a();
aurora::shaders::queue_colored_quad_verts(aurora::shaders::CameraFilterType::Blend, aurora::shaders::ZTest::Always,
false, col, {xc0_verts.data(), xc0_verts.size()});
}
CGuiWidget::Draw(parms);
}
void CGuiPane::ScaleDimensions(const zeus::CVector3f& scale) {
InitializeBuffers();
for (TexShaderVert& v : xc0_verts) {
v.m_pos -= xc8_scaleCenter;
v.m_pos *= scale;
v.m_pos += xc8_scaleCenter;
for (auto& vert : xc0_verts) {
vert -= xc8_scaleCenter;
vert *= scale;
vert += xc8_scaleCenter;
}
}
void CGuiPane::SetDimensions(const zeus::CVector2f& dim, bool initVBO) {
void CGuiPane::SetDimensions(const zeus::CVector2f& dim, bool initBuffers) {
xb8_dim = dim;
if (initVBO)
if (initBuffers)
InitializeBuffers();
}
zeus::CVector2f CGuiPane::GetDimensions() const { return xb8_dim; }
void CGuiPane::InitializeBuffers() {
if (xc0_verts.size() < 4)
xc0_verts.resize(4);
#if 0
if (xc0_verts == nullptr) {
xc0_verts = new float[3 * 4];
}
#endif
xc0_verts[0].assign(-xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f);
xc0_verts[1].assign(-xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f);
xc0_verts[2].assign(xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f);
xc0_verts[3].assign(xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f);
xc0_verts[0].m_pos.assign(-xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f);
xc0_verts[1].m_pos.assign(-xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f);
xc0_verts[2].m_pos.assign(xb8_dim.x() * 0.5f, 0.f, xb8_dim.y() * 0.5f);
xc0_verts[3].m_pos.assign(xb8_dim.x() * 0.5f, 0.f, -xb8_dim.y() * 0.5f);
}
void CGuiPane::WriteData(COutputStream& out, bool flag) const {}

View File

@ -14,13 +14,8 @@ class CGuiPane : public CGuiWidget {
protected:
zeus::CVector2f xb8_dim;
struct TexShaderVert {
zeus::CVector3f m_pos;
zeus::CVector2f m_uv;
};
/* Originally a vert-buffer pointer for GX */
std::vector<TexShaderVert> xc0_verts;
// u32 x104_ = 4; /* vert count */
std::array<zeus::CVector3f, 4> xc0_verts;
zeus::CVector3f xc8_scaleCenter;
@ -28,6 +23,7 @@ public:
CGuiPane(const CGuiWidgetParms& parms, const zeus::CVector2f& dim, const zeus::CVector3f& scaleCenter);
FourCC GetWidgetTypeID() const override { return FOURCC('PANE'); }
void Draw(const CGuiWidgetDrawParms& parms) override;
virtual void ScaleDimensions(const zeus::CVector3f& scale);
virtual void SetDimensions(const zeus::CVector2f& dim, bool initVBO);
virtual zeus::CVector2f GetDimensions() const;

View File

@ -17,13 +17,13 @@ constexpr std::array<zeus::CVector3f, 4> NormalPoints{{
{1.f, 0.f, 0.f},
{0.f, 0.f, 0.f},
}};
bool testProjectedLine(const zeus::CVector2f& a, const zeus::CVector2f& b, const zeus::CVector2f& point) {
const zeus::CVector2f normal = (b - a).perpendicularVector().normalized();
return point.dot(normal) >= a.dot(normal);
}
} // Anonymous namespace
bool CGuiTextPane::sDrawPaneRects = true;
CGuiTextPane::CGuiTextPane(const CGuiWidgetParms& parms, CSimplePool* sp, const zeus::CVector2f& dim,
const zeus::CVector3f& vec, CAssetId fontId, const CGuiTextProperties& props,
const zeus::CColor& fontCol, const zeus::CColor& outlineCol, s32 extentX, s32 extentY)
@ -46,6 +46,10 @@ void CGuiTextPane::SetDimensions(const zeus::CVector2f& dim, bool initVBO) {
void CGuiTextPane::ScaleDimensions(const zeus::CVector3f& scale) {}
void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) {
if (sDrawPaneRects) {
CGuiPane::Draw({0.2f * parms.x0_alphaMod, parms.x4_cameraOffset});
}
if (!GetIsVisible()) {
return;
}
@ -53,19 +57,19 @@ void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) {
zeus::CVector2f dims = GetDimensions();
if (xd4_textSupport.x34_extentX) {
if (xd4_textSupport.x34_extentX != 0) {
dims.x() /= float(xd4_textSupport.x34_extentX);
} else {
dims.x() = 0.f;
}
if (xd4_textSupport.x38_extentY) {
if (xd4_textSupport.x38_extentY != 0) {
dims.y() /= float(xd4_textSupport.x38_extentY);
} else {
dims.y() = 0.f;
}
const zeus::CTransform local = zeus::CTransform::Translate(xc0_verts.front().m_pos + xc8_scaleCenter) *
const zeus::CTransform local = zeus::CTransform::Translate(xc0_verts.front() + xc8_scaleCenter) *
zeus::CTransform::Scale(dims.x(), 1.f, dims.y());
CGraphics::SetModelMatrix(x34_worldXF * local);
@ -98,7 +102,7 @@ void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) {
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha,
ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear);
xd4_textSupport.Render();
xd4_textSupport.SetGeometryColor(geomCol * zeus::CColor(geomCol.a, geomCol.a, geomCol.a, 1.f));
xd4_textSupport.SetGeometryColor(geomCol * zeus::CColor(geomCol.a(), geomCol.a(), geomCol.a(), 1.f));
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One,
ERglBlendFactor::One, ERglLogicOp::Clear);
xd4_textSupport.Render();
@ -111,7 +115,7 @@ void CGuiTextPane::Draw(const CGuiWidgetDrawParms& parms) {
bool CGuiTextPane::TestCursorHit(const zeus::CMatrix4f& vp, const zeus::CVector2f& point) const {
const zeus::CVector2f dims = GetDimensions();
const zeus::CTransform local = zeus::CTransform::Translate(xc0_verts.front().m_pos + xc8_scaleCenter) *
const zeus::CTransform local = zeus::CTransform::Translate(xc0_verts.front() + xc8_scaleCenter) *
zeus::CTransform::Scale(dims.x(), 1.f, dims.y());
const zeus::CMatrix4f mvp = vp * (x34_worldXF * local).toMatrix4f();

View File

@ -9,6 +9,7 @@
namespace metaforce {
class CGuiTextPane : public CGuiPane {
static bool sDrawPaneRects;
CGuiTextSupport xd4_textSupport;
public:

View File

@ -1,6 +1,10 @@
#include "Runtime/Graphics/CGraphics.hpp"
#include "Runtime/GuiSys/CGuiWidget.hpp"
#include "Runtime/GuiSys/CGuiFrame.hpp"
#include <aurora.h>
#include <aurora_shaders.h>
#include <logvisor/logvisor.hpp>
namespace metaforce {
@ -111,7 +115,7 @@ void CGuiWidget::Update(float dt) {
sib->Update(dt);
}
void CGuiWidget::Draw(const CGuiWidgetDrawParms&) {}
void CGuiWidget::Draw(const CGuiWidgetDrawParms& parms) {}
void CGuiWidget::ProcessUserInput(const CFinalInput& input) {}
void CGuiWidget::Touch() {}

View File

@ -128,10 +128,10 @@ CFinalInput::CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData&
, x23_enableAnaRightNegYP(DRADown() && !prevInput.DRADown())
, x24_anaLeftTriggerP(DLTrigger() && !prevInput.DLTrigger())
, x28_anaRightTriggerP(DRTrigger() && !prevInput.DRTrigger())
, x2c_b31_DPUp(data.m_specialKeys[size_t(boo::ESpecialKey::Up)])
, x2d_b24_DPRight(data.m_specialKeys[size_t(boo::ESpecialKey::Right)])
, x2d_b25_DPDown(data.m_specialKeys[size_t(boo::ESpecialKey::Down)])
, x2d_b26_DPLeft(data.m_specialKeys[size_t(boo::ESpecialKey::Left)])
, x2c_b31_DPUp(data.m_specialKeys[size_t(aurora::SpecialKey::Up)])
, x2d_b24_DPRight(data.m_specialKeys[size_t(aurora::SpecialKey::Right)])
, x2d_b25_DPDown(data.m_specialKeys[size_t(aurora::SpecialKey::Down)])
, x2d_b26_DPLeft(data.m_specialKeys[size_t(aurora::SpecialKey::Left)])
, x2d_b28_PA(DA() && !prevInput.DA())
, x2d_b29_PB(DB() && !prevInput.DB())
, x2d_b30_PX(DX() && !prevInput.DX())

View File

@ -67,22 +67,22 @@ public:
void mouseMove(const boo::SWindowCoord& coord) { m_data.m_mouseCoord = coord; }
void scroll(const boo::SWindowCoord&, const boo::SScrollDelta& scroll) { m_data.m_accumScroll += scroll; }
void charKeyDown(unsigned long charCode, boo::EModifierKey, bool) {
void charKeyDown(uint8_t charCode, aurora::ModifierKey, bool) {
charCode = tolower(charCode);
if (charCode > 255)
return;
m_data.m_charKeys[charCode] = true;
}
void charKeyUp(unsigned long charCode, boo::EModifierKey mods) {
void charKeyUp(uint8_t charCode, aurora::ModifierKey mods) {
charCode = tolower(charCode);
if (charCode > 255)
return;
m_data.m_charKeys[charCode] = false;
}
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey, bool) { m_data.m_specialKeys[size_t(key)] = true; }
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey) { m_data.m_specialKeys[size_t(key)] = false; }
void modKeyDown(boo::EModifierKey mod, bool) { m_data.m_modMask = m_data.m_modMask | mod; }
void modKeyUp(boo::EModifierKey mod) { m_data.m_modMask = m_data.m_modMask & ~mod; }
void specialKeyDown(aurora::SpecialKey key, aurora::ModifierKey, bool) { m_data.m_specialKeys[size_t(key)] = true; }
void specialKeyUp(aurora::SpecialKey key, aurora::ModifierKey) { m_data.m_specialKeys[size_t(key)] = false; }
void modKeyDown(aurora::ModifierKey mod, bool) { m_data.m_modMask = m_data.m_modMask | mod; }
void modKeyUp(aurora::ModifierKey mod) { m_data.m_modMask = m_data.m_modMask & ~mod; }
void reset() { m_data.m_accumScroll.zeroOut(); }

View File

@ -2,14 +2,15 @@
#include <array>
#include <boo/IWindow.hpp>
#include "aurora.h"
namespace metaforce {
struct CKeyboardMouseControllerData {
std::array<bool, 256> m_charKeys{};
std::array<bool, static_cast<size_t>(boo::ESpecialKey::MAX)> m_specialKeys{};
std::array<bool, static_cast<size_t>(aurora::SpecialKey::MAX)> m_specialKeys{};
std::array<bool, 6> m_mouseButtons{};
boo::EModifierKey m_modMask = boo::EModifierKey::None;
aurora::ModifierKey m_modMask = aurora::ModifierKey::None;
boo::SWindowCoord m_mouseCoord;
boo::SScrollDelta m_accumScroll;
};

View File

@ -2045,16 +2045,8 @@ void CFrontEndUI::Draw() {
x38_pressStart->GetHeight() / 480.f * vPad);
zeus::CColor color = zeus::skWhite;
color.a() = x64_pressStartAlpha;
aurora::shaders::queue_textured_quad(
aurora::shaders::CameraFilterType::Add,
x38_pressStart->GetTexture()->ref,
aurora::shaders::ZTest::Always,
false,
color,
1.f,
rect,
0.f
);
aurora::shaders::queue_textured_quad(aurora::shaders::CameraFilterType::Add, x38_pressStart->GetTexture()->ref,
aurora::shaders::ZTest::Always, false, color, 1.f, rect, 0.f);
}
if (xc0_attractCount > 0) {
@ -2065,7 +2057,9 @@ void CFrontEndUI::Draw() {
/* To black */
zeus::CColor color = zeus::skBlack;
color.a() = 1.f - x58_fadeBlackTimer;
m_fadeToBlack.draw(color);
zeus::CRectangle rect(0, 0, 1, 1);
aurora::shaders::queue_colored_quad(aurora::shaders::CameraFilterType::Blend, aurora::shaders::ZTest::Always,
false, color, rect, 0.f);
}
}
@ -2075,12 +2069,16 @@ void CFrontEndUI::Draw() {
/* To black */
zeus::CColor color = zeus::skBlack;
color.a() = zeus::clamp(0.f, 1.f - x58_fadeBlackTimer, 1.f);
m_fadeToBlack.draw(color);
zeus::CRectangle rect(0, 0, 1, 1);
aurora::shaders::queue_colored_quad(aurora::shaders::CameraFilterType::Blend, aurora::shaders::ZTest::Always,
false, color, rect, 0.f);
} else if (x50_curScreen == EScreen::Title && x54_nextScreen == EScreen::Title) {
/* From black with 30-sec skip to title */
zeus::CColor color = zeus::skBlack;
color.a() = 1.f - zeus::clamp(0.f, 30.f - x58_fadeBlackTimer, 1.f);
m_fadeToBlack.draw(color);
zeus::CRectangle rect(0, 0, 1, 1);
aurora::shaders::queue_colored_quad(aurora::shaders::CameraFilterType::Blend, aurora::shaders::ZTest::Always,
false, color, rect, 0.f);
}
}

View File

@ -224,17 +224,17 @@ CGameArchitectureSupport::~CGameArchitectureSupport() {
CStreamAudioManager::Shutdown();
}
void CGameArchitectureSupport::charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) {
void CGameArchitectureSupport::charKeyDown(uint8_t charCode, aurora::ModifierKey mods, bool isRepeat) {
x30_inputGenerator.charKeyDown(charCode, mods, isRepeat);
// m_parent.m_console->handleCharCode(charCode, mods, isRepeat);
}
void CGameArchitectureSupport::specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
void CGameArchitectureSupport::specialKeyDown(aurora::SpecialKey key, aurora::ModifierKey mods, bool isRepeat) {
x30_inputGenerator.specialKeyDown(key, mods, isRepeat);
// m_parent.m_console->handleSpecialKeyDown(key, mods, isRepeat);
}
void CGameArchitectureSupport::specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) {
void CGameArchitectureSupport::specialKeyUp(aurora::SpecialKey key, aurora::ModifierKey mods) {
x30_inputGenerator.specialKeyUp(key, mods);
// m_parent.m_console->handleSpecialKeyUp(key, mods);
}

View File

@ -157,13 +157,13 @@ public:
void scroll(const boo::SWindowCoord& coord, const boo::SScrollDelta& scroll) {
x30_inputGenerator.scroll(coord, scroll);
}
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat);
void charKeyUp(unsigned long charCode, boo::EModifierKey mods) { x30_inputGenerator.charKeyUp(charCode, mods); }
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat);
void charKeyDown(uint8_t charCode, aurora::ModifierKey mods, bool isRepeat);
void charKeyUp(uint8_t charCode, aurora::ModifierKey mods) { x30_inputGenerator.charKeyUp(charCode, mods); }
void specialKeyDown(aurora::SpecialKey key, aurora::ModifierKey mods, bool isRepeat);
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods);
void modKeyDown(boo::EModifierKey mod, bool isRepeat) { x30_inputGenerator.modKeyDown(mod, isRepeat); }
void modKeyUp(boo::EModifierKey mod) { x30_inputGenerator.modKeyUp(mod); }
void specialKeyUp(aurora::SpecialKey key, aurora::ModifierKey mods);
void modKeyDown(aurora::ModifierKey mod, bool isRepeat) { x30_inputGenerator.modKeyDown(mod, isRepeat); }
void modKeyUp(aurora::ModifierKey mod) { x30_inputGenerator.modKeyUp(mod); }
void PreloadAudio();
bool LoadAudio();