mirror of https://github.com/AxioDL/metaforce.git
SDL controller input
This commit is contained in:
parent
938852afd8
commit
a1482b4743
|
@ -57,3 +57,6 @@
|
|||
[submodule "extern/imgui"]
|
||||
path = extern/imgui
|
||||
url = https://github.com/ocornut/imgui.git
|
||||
[submodule "extern/SDL"]
|
||||
path = extern/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
|
|
|
@ -481,21 +481,8 @@ target_include_directories(hecl-light PRIVATE ${CMAKE_SOURCE_DIR})
|
|||
target_link_libraries(hecl-full PRIVATE zeus nod)
|
||||
target_link_libraries(hecl-light PRIVATE zeus nod)
|
||||
|
||||
#bintoc(CModelShaders.common.glsl.cpp Shaders/CModelShaders.common.glsl CMODELSHADERS_COMMON_GLSL)
|
||||
#bintoc(CModelShaders.vert.glsl.cpp Shaders/CModelShaders.vert.glsl CMODELSHADERS_VERT_GLSL)
|
||||
#bintoc(CModelShaders.frag.glsl.cpp Shaders/CModelShaders.frag.glsl CMODELSHADERS_FRAG_GLSL)
|
||||
#bintoc(CModelShaders.common.hlsl.cpp Shaders/CModelShaders.common.hlsl CMODELSHADERS_COMMON_HLSL)
|
||||
#bintoc(CModelShaders.vert.hlsl.cpp Shaders/CModelShaders.vert.hlsl CMODELSHADERS_VERT_HLSL)
|
||||
#bintoc(CModelShaders.frag.hlsl.cpp Shaders/CModelShaders.frag.hlsl CMODELSHADERS_FRAG_HLSL)
|
||||
#bintoc(CModelShaders.common.metal.cpp Shaders/CModelShaders.common.metal CMODELSHADERS_COMMON_METAL)
|
||||
#bintoc(CModelShaders.vert.metal.cpp Shaders/CModelShaders.vert.metal CMODELSHADERS_VERT_METAL)
|
||||
#bintoc(CModelShaders.frag.metal.cpp Shaders/CModelShaders.frag.metal CMODELSHADERS_FRAG_METAL)
|
||||
#add_library(CModelShaders
|
||||
# CModelShaders.common.glsl.cpp CModelShaders.vert.glsl.cpp CModelShaders.frag.glsl.cpp
|
||||
# CModelShaders.common.hlsl.cpp CModelShaders.vert.hlsl.cpp CModelShaders.frag.hlsl.cpp
|
||||
# CModelShaders.common.metal.cpp CModelShaders.vert.metal.cpp CModelShaders.frag.metal.cpp)
|
||||
#target_link_libraries(CModelShaders PUBLIC zeus)
|
||||
#target_link_libraries(shader_CModelShaders PUBLIC CModelShaders)
|
||||
add_subdirectory(extern/SDL EXCLUDE_FROM_ALL)
|
||||
target_compile_options(SDL2-static PRIVATE -Wno-implicit-fallthrough)
|
||||
|
||||
if(NOT TARGET atdna)
|
||||
# Import native atdna if cross-compiling
|
||||
|
|
|
@ -116,6 +116,7 @@ dependencies = [
|
|||
"num_enum",
|
||||
"pollster",
|
||||
"scopeguard",
|
||||
"sdl2",
|
||||
"smallvec",
|
||||
"twox-hash",
|
||||
"wasm-bindgen-futures",
|
||||
|
@ -1439,6 +1440,27 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96311ef4a16462c757bb6a39152c40f58f31cd2602a40fceb937e2bc34e6cbab"
|
||||
|
||||
[[package]]
|
||||
name = "sdl2"
|
||||
version = "0.35.2"
|
||||
source = "git+https://github.com/encounter/rust-sdl2.git?rev=e282ef3acd7fcb4b2ba16863a7a0a7a8439f9335#e282ef3acd7fcb4b2ba16863a7a0a7a8439f9335"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"sdl2-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sdl2-sys"
|
||||
version = "0.35.2"
|
||||
source = "git+https://github.com/encounter/rust-sdl2.git?rev=e282ef3acd7fcb4b2ba16863a7a0a7a8439f9335#e282ef3acd7fcb4b2ba16863a7a0a7a8439f9335"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.132"
|
||||
|
@ -1703,6 +1725,12 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
|
|
|
@ -29,6 +29,8 @@ smallvec = "1.7.0"
|
|||
scopeguard = "1.1.0"
|
||||
twox-hash = "1.6.2"
|
||||
winit = "0.26.1"
|
||||
# custom sdl2
|
||||
sdl2 = { git = "https://github.com/encounter/rust-sdl2.git", rev = "e282ef3acd7fcb4b2ba16863a7a0a7a8439f9335", features = ["no-link", "hidapi"] }
|
||||
|
||||
[dependencies.imgui]
|
||||
git = "https://github.com/imgui-rs/imgui-rs"
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace aurora {
|
||||
enum class SpecialKey : std::uint8_t;
|
||||
enum class SpecialKey : uint8_t;
|
||||
enum class ControllerButton : uint8_t;
|
||||
enum class ControllerAxis : uint8_t;
|
||||
|
||||
struct WindowSize;
|
||||
|
||||
|
@ -24,14 +26,18 @@ struct AppDelegate {
|
|||
virtual void onAppDraw() noexcept = 0;
|
||||
virtual void onAppPostDraw() noexcept = 0;
|
||||
virtual void onAppWindowResized(const WindowSize& size) noexcept = 0;
|
||||
virtual void onAppWindowMoved(std::int32_t x, std::int32_t y) noexcept = 0;
|
||||
virtual void onAppWindowMoved(int32_t x, int32_t y) noexcept = 0;
|
||||
virtual void onAppExiting() noexcept = 0;
|
||||
|
||||
// Input
|
||||
virtual void onCharKeyDown(std::uint8_t charCode, bool is_repeat) noexcept = 0;
|
||||
virtual void onCharKeyUp(std::uint8_t charCode) noexcept = 0;
|
||||
virtual void onSpecialKeyDown(const SpecialKey& key, bool is_repeat) noexcept = 0;
|
||||
virtual void onSpecialKeyUp(const SpecialKey& key) noexcept = 0;
|
||||
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;
|
||||
|
||||
// Controller
|
||||
virtual void onControllerButton(uint32_t idx, ControllerButton button, bool pressed) noexcept = 0;
|
||||
virtual void onControllerAxis(uint32_t idx, 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,
|
||||
|
|
|
@ -6,12 +6,15 @@ void App_onAppLaunched(AppDelegate& cb) noexcept;
|
|||
bool App_onAppIdle(AppDelegate& cb, float dt) noexcept;
|
||||
void App_onAppDraw(AppDelegate& cb) noexcept;
|
||||
void App_onAppPostDraw(AppDelegate& cb) noexcept;
|
||||
void App_onAppWindowResized(AppDelegate& cb, const WindowSize& size) noexcept;
|
||||
void App_onAppWindowMoved(AppDelegate& cb, std::int32_t x, std::int32_t y) noexcept;
|
||||
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, std::uint8_t code, bool is_repeat) noexcept;
|
||||
void App_onCharKeyUp(AppDelegate& cb, std::uint8_t code) noexcept;
|
||||
void App_onSpecialKeyDown(AppDelegate& cb, const SpecialKey& key, bool is_repeat);
|
||||
void App_onSpecialKeyUp(AppDelegate& cb, const SpecialKey& key);
|
||||
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;
|
||||
// Controller
|
||||
void App_onControllerButton(AppDelegate& cb, uint32_t idx, ControllerButton button, bool pressed) noexcept;
|
||||
void App_onControllerAxis(AppDelegate& cb, uint32_t idx, ControllerAxis axis, int16_t value) noexcept;
|
||||
} // namespace aurora
|
||||
|
|
|
@ -8,22 +8,30 @@ 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, std::int32_t x, std::int32_t y) noexcept {
|
||||
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, std::uint8_t code, bool is_repeat) noexcept {
|
||||
cb.onCharKeyDown(code, is_repeat);
|
||||
void App_onCharKeyDown(AppDelegate& cb, uint8_t code, bool isRepeat) noexcept {
|
||||
cb.onCharKeyDown(code, isRepeat);
|
||||
}
|
||||
void App_onCharKeyUp(AppDelegate& cb, std::uint8_t code) noexcept {
|
||||
void App_onCharKeyUp(AppDelegate& cb, uint8_t code) noexcept {
|
||||
cb.onCharKeyUp(code);
|
||||
}
|
||||
void App_onSpecialKeyDown(AppDelegate& cb, const SpecialKey& key, bool is_repeat) {
|
||||
cb.onSpecialKeyDown(key, is_repeat);
|
||||
void App_onSpecialKeyDown(AppDelegate& cb, SpecialKey key, bool isRepeat) noexcept {
|
||||
cb.onSpecialKeyDown(key, isRepeat);
|
||||
}
|
||||
void App_onSpecialKeyUp(AppDelegate& cb, const SpecialKey& key) {
|
||||
void App_onSpecialKeyUp(AppDelegate& cb, SpecialKey key) noexcept {
|
||||
cb.onSpecialKeyUp(key);
|
||||
}
|
||||
|
||||
// Controller
|
||||
void App_onControllerButton(AppDelegate& cb, uint32_t idx, ControllerButton button, bool pressed) noexcept {
|
||||
cb.onControllerButton(idx, button, pressed);
|
||||
}
|
||||
void App_onControllerAxis(AppDelegate& cb, uint32_t idx, ControllerAxis axis, int16_t value) noexcept {
|
||||
cb.onControllerAxis(idx, axis, value);
|
||||
}
|
||||
} // namespace aurora
|
||||
|
|
|
@ -3,29 +3,32 @@
|
|||
#![allow(unused_variables)]
|
||||
#![allow(unused_unsafe)]
|
||||
|
||||
use std::{collections::HashMap, time::Instant};
|
||||
|
||||
use sdl2::{
|
||||
controller::{Axis, Button, GameController},
|
||||
event::Event as SDLEvent,
|
||||
GameControllerSubsystem, Sdl,
|
||||
};
|
||||
use wgpu::Backend;
|
||||
use winit::{
|
||||
event::{ElementState, Event, KeyboardInput, WindowEvent},
|
||||
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
||||
event_loop::ControlFlow,
|
||||
};
|
||||
use winit::event::VirtualKeyCode;
|
||||
|
||||
use std::{num::NonZeroU8, time::Instant, collections::HashMap};
|
||||
|
||||
use crate::{
|
||||
ffi::WindowSize,
|
||||
gpu::{create_depth_texture, create_render_texture, DeviceHolder, initialize_gpu},
|
||||
imgui::{ImGuiState, initialize_imgui},
|
||||
ffi::{SpecialKey, WindowSize},
|
||||
gpu::{create_depth_texture, create_render_texture, initialize_gpu, DeviceHolder},
|
||||
imgui::{initialize_imgui, ImGuiState},
|
||||
shaders::render_into_pass,
|
||||
};
|
||||
use crate::ffi::SpecialKey;
|
||||
|
||||
mod gpu;
|
||||
mod imgui;
|
||||
mod imgui_backend;
|
||||
mod shaders;
|
||||
mod zeus;
|
||||
mod util;
|
||||
mod zeus;
|
||||
|
||||
#[cxx::bridge(namespace = "aurora")]
|
||||
mod ffi {
|
||||
|
@ -46,8 +49,25 @@ mod ffi {
|
|||
// 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_onSpecialKeyDown(cb: Pin<&mut AppDelegate>, key: &SpecialKey, is_repeat: bool);
|
||||
pub(crate) fn App_onSpecialKeyUp(cb: Pin<&mut AppDelegate>, key: &SpecialKey);
|
||||
pub(crate) fn App_onSpecialKeyDown(
|
||||
cb: Pin<&mut AppDelegate>,
|
||||
key: SpecialKey,
|
||||
is_repeat: bool,
|
||||
);
|
||||
pub(crate) fn App_onSpecialKeyUp(cb: Pin<&mut AppDelegate>, key: SpecialKey);
|
||||
// Controller
|
||||
pub(crate) fn App_onControllerButton(
|
||||
cb: Pin<&mut AppDelegate>,
|
||||
idx: u32,
|
||||
button: ControllerButton,
|
||||
pressed: bool,
|
||||
);
|
||||
pub(crate) fn App_onControllerAxis(
|
||||
cb: Pin<&mut AppDelegate>,
|
||||
idx: u32,
|
||||
axis: ControllerAxis,
|
||||
value: i16,
|
||||
);
|
||||
}
|
||||
|
||||
pub struct Window {
|
||||
|
@ -118,6 +138,35 @@ mod ffi {
|
|||
// pub
|
||||
}
|
||||
|
||||
pub enum ControllerButton {
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
Back,
|
||||
Guide,
|
||||
Start,
|
||||
LeftStick,
|
||||
RightStick,
|
||||
LeftShoulder,
|
||||
RightShoulder,
|
||||
DPadUp,
|
||||
DPadDown,
|
||||
DPadLeft,
|
||||
DPadRight,
|
||||
Other,
|
||||
MAX,
|
||||
}
|
||||
pub enum ControllerAxis {
|
||||
LeftX,
|
||||
LeftY,
|
||||
RightX,
|
||||
RightY,
|
||||
TriggerLeft,
|
||||
TriggerRight,
|
||||
MAX,
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
type WindowContext;
|
||||
type App;
|
||||
|
@ -131,11 +180,50 @@ mod ffi {
|
|||
fn set_fullscreen(v: bool);
|
||||
}
|
||||
}
|
||||
impl From<Button> for ffi::ControllerButton {
|
||||
fn from(button: Button) -> Self {
|
||||
match button {
|
||||
Button::A => ffi::ControllerButton::A,
|
||||
Button::B => ffi::ControllerButton::B,
|
||||
Button::X => ffi::ControllerButton::X,
|
||||
Button::Y => ffi::ControllerButton::Y,
|
||||
Button::Back => ffi::ControllerButton::Back,
|
||||
Button::Guide => ffi::ControllerButton::Guide,
|
||||
Button::Start => ffi::ControllerButton::Start,
|
||||
Button::LeftStick => ffi::ControllerButton::LeftStick,
|
||||
Button::RightStick => ffi::ControllerButton::RightStick,
|
||||
Button::LeftShoulder => ffi::ControllerButton::LeftShoulder,
|
||||
Button::RightShoulder => ffi::ControllerButton::RightShoulder,
|
||||
Button::DPadUp => ffi::ControllerButton::DPadUp,
|
||||
Button::DPadDown => ffi::ControllerButton::DPadDown,
|
||||
Button::DPadLeft => ffi::ControllerButton::DPadLeft,
|
||||
Button::DPadRight => ffi::ControllerButton::DPadRight,
|
||||
_ => ffi::ControllerButton::Other,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl From<Axis> for ffi::ControllerAxis {
|
||||
fn from(axis: Axis) -> Self {
|
||||
match axis {
|
||||
Axis::LeftX => ffi::ControllerAxis::LeftX,
|
||||
Axis::LeftY => ffi::ControllerAxis::LeftY,
|
||||
Axis::RightX => ffi::ControllerAxis::RightX,
|
||||
Axis::RightY => ffi::ControllerAxis::RightY,
|
||||
Axis::TriggerLeft => ffi::ControllerAxis::TriggerLeft,
|
||||
Axis::TriggerRight => ffi::ControllerAxis::TriggerRight,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
window: ffi::Window,
|
||||
gpu: DeviceHolder,
|
||||
imgui: ImGuiState,
|
||||
// SDL
|
||||
sdl: Sdl,
|
||||
sdl_events: sdl2::EventPump,
|
||||
sdl_controller_sys: GameControllerSubsystem,
|
||||
sdl_open_controllers: HashMap<u32, GameController>,
|
||||
}
|
||||
|
||||
pub struct WindowContext {
|
||||
|
@ -152,11 +240,22 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
log::info!("Running app");
|
||||
let event_loop = winit::event_loop::EventLoop::new();
|
||||
let window = winit::window::WindowBuilder::new().build(&event_loop).unwrap();
|
||||
let sdl = sdl2::init().unwrap();
|
||||
let sdl_events = sdl.event_pump().unwrap();
|
||||
let controller = sdl.game_controller().unwrap();
|
||||
let gpu = initialize_gpu(&window);
|
||||
let imgui = initialize_imgui(&window, &gpu);
|
||||
let mut special_keys_pressed : [bool; 512] = [false; 512];
|
||||
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};
|
||||
let app = App {
|
||||
window: ffi::Window { inner: Box::new(WindowContext { window }) },
|
||||
gpu,
|
||||
imgui,
|
||||
sdl,
|
||||
sdl_events,
|
||||
sdl_controller_sys: controller,
|
||||
sdl_open_controllers: Default::default(),
|
||||
};
|
||||
unsafe {
|
||||
APP.replace(app);
|
||||
ffi::App_onAppLaunched(delegate.as_mut().unwrap());
|
||||
|
@ -173,9 +272,62 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
let window_ctx = get_window_context();
|
||||
let gpu = &mut app.gpu;
|
||||
|
||||
// SDL event loop
|
||||
for event in app.sdl_events.poll_iter() {
|
||||
// log::info!("SDL event: {:?}", event);
|
||||
match event {
|
||||
SDLEvent::ControllerDeviceAdded { which, .. } => {
|
||||
match app.sdl_controller_sys.open(which) {
|
||||
Ok(controller) => {
|
||||
log::info!("Opened SDL controller \"{}\"", controller.name());
|
||||
app.sdl_open_controllers.insert(which, controller);
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Failed to open SDL controller {} ({:?})", which, err);
|
||||
}
|
||||
}
|
||||
// TODO app connected event
|
||||
}
|
||||
SDLEvent::ControllerDeviceRemoved { which, .. } => {
|
||||
app.sdl_open_controllers.remove(&which);
|
||||
// TODO app disconnected event
|
||||
}
|
||||
SDLEvent::ControllerButtonDown { which, button, .. } => unsafe {
|
||||
ffi::App_onControllerButton(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
which,
|
||||
button.into(),
|
||||
true,
|
||||
);
|
||||
},
|
||||
SDLEvent::ControllerButtonUp { which, button, .. } => unsafe {
|
||||
ffi::App_onControllerButton(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
which,
|
||||
button.into(),
|
||||
false,
|
||||
);
|
||||
},
|
||||
SDLEvent::ControllerAxisMotion { which, axis, value, .. } => unsafe {
|
||||
ffi::App_onControllerAxis(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
which,
|
||||
axis.into(),
|
||||
value,
|
||||
);
|
||||
},
|
||||
// SDL overrides exit signals
|
||||
SDLEvent::Quit { .. } => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// winit event loop
|
||||
*control_flow = ControlFlow::Poll;
|
||||
match event {
|
||||
Event::NewEvents(_) => {}
|
||||
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
|
@ -192,28 +344,23 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
&app.gpu.surface_config,
|
||||
&app.gpu.config,
|
||||
);
|
||||
let window_size = WindowSize {
|
||||
width: app.gpu.surface_config.width,
|
||||
height: app.gpu.surface_config.height,
|
||||
};
|
||||
unsafe {
|
||||
let window_size = WindowSize { width: app.gpu.surface_config.width, height: app.gpu.surface_config.height };
|
||||
|
||||
ffi::App_onAppWindowResized(delegate.as_mut().unwrap(), &window_size);
|
||||
}
|
||||
}
|
||||
Event::WindowEvent { event: WindowEvent::Moved(loc), .. } => {
|
||||
unsafe {
|
||||
ffi::App_onAppWindowMoved(delegate.as_mut().unwrap(), loc.x, loc.y);
|
||||
ffi::App_onAppWindowResized(delegate.as_mut().unwrap_unchecked(), &window_size);
|
||||
}
|
||||
}
|
||||
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,
|
||||
event:
|
||||
WindowEvent::KeyboardInput {
|
||||
input: KeyboardInput { scancode, virtual_keycode: Some(key), state, .. },
|
||||
..
|
||||
},
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
// TODO: Handle normal keys, this will require a refactor in game runtime code
|
||||
|
@ -253,18 +400,20 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
|
||||
unsafe {
|
||||
if pressed {
|
||||
ffi::App_onSpecialKeyDown(delegate.as_mut().unwrap(), &special_key, repeat);
|
||||
ffi::App_onSpecialKeyDown(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
special_key,
|
||||
repeat,
|
||||
);
|
||||
} else {
|
||||
ffi::App_onSpecialKeyUp(delegate.as_mut().unwrap(), &special_key);
|
||||
ffi::App_onSpecialKeyUp(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
special_key,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::WindowEvent { .. } => {}
|
||||
Event::DeviceEvent { .. } => {}
|
||||
Event::UserEvent(_) => {}
|
||||
Event::Suspended => {}
|
||||
Event::Resumed => {}
|
||||
Event::MainEventsCleared => {
|
||||
log::trace!("Requesting redraw");
|
||||
window_ctx.window.request_redraw();
|
||||
|
@ -301,7 +450,7 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
|
||||
#[allow(unused_unsafe)] // rust bug?
|
||||
unsafe {
|
||||
ffi::App_onAppDraw(delegate.as_mut().unwrap());
|
||||
ffi::App_onAppDraw(delegate.as_mut().unwrap_unchecked());
|
||||
}
|
||||
|
||||
let fb_view =
|
||||
|
@ -357,15 +506,15 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
|||
|
||||
#[allow(unused_unsafe)] // rust bug?
|
||||
unsafe {
|
||||
ffi::App_onAppPostDraw(delegate.as_mut().unwrap());
|
||||
ffi::App_onAppPostDraw(delegate.as_mut().unwrap_unchecked());
|
||||
}
|
||||
}
|
||||
Event::RedrawEventsCleared => {}
|
||||
Event::LoopDestroyed => unsafe {
|
||||
ffi::App_onAppExiting(delegate.as_mut().unwrap());
|
||||
ffi::App_onAppExiting(delegate.as_mut().unwrap_unchecked());
|
||||
APP.take();
|
||||
return;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
imgui.platform.handle_event(imgui.context.io_mut(), &window_ctx.window, &event);
|
||||
|
|
|
@ -7,16 +7,15 @@ use crate::{
|
|||
get_app,
|
||||
gpu::GraphicsConfig,
|
||||
shaders::{
|
||||
get_combined_matrix,
|
||||
bind_pipeline,
|
||||
BuiltBuffers,
|
||||
ffi::{CameraFilterType, TextureRef, ZTest}, pipeline_ref, PipelineCreateCommand, PipelineHolder, PipelineRef,
|
||||
push_draw_command, push_uniform, push_verts, ShaderDrawCommand, STATE,
|
||||
ffi::{CameraFilterType, TextureRef, ZTest},
|
||||
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},
|
||||
};
|
||||
use crate::shaders::texture::create_sampler;
|
||||
use crate::util::{align, Vec2, Vec3};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct DrawData {
|
||||
|
@ -56,40 +55,46 @@ pub(crate) fn construct_state(
|
|||
) -> 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_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("Textured 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,
|
||||
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,
|
||||
},
|
||||
count: None,
|
||||
}, wgpu::BindGroupLayoutEntry {
|
||||
binding: 1,
|
||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||
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("Textured 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),
|
||||
}],
|
||||
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 texture_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
label: Some("Textured Quad Texture Bind Group Layout"),
|
||||
|
@ -170,7 +175,6 @@ pub(crate) fn construct_pipeline(
|
|||
),
|
||||
_ => todo!(),
|
||||
};
|
||||
log::warn!("VERT SIZE: {}", std::mem::size_of::<Vert>() as u64);
|
||||
PipelineHolder {
|
||||
pipeline: device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: Some("Textured Quad Pipeline"),
|
||||
|
@ -271,12 +275,38 @@ pub(crate) fn queue_textured_quad(
|
|||
push_textured_quad(texture, pipeline, vert_range, uniform_range);
|
||||
}
|
||||
|
||||
pub(crate) fn queue_textured_quad_verts(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_test: ZTest,
|
||||
color: CColor,
|
||||
pos: &[CVector3f],
|
||||
uvs: &[CVector2f],
|
||||
lod: f32,
|
||||
) {
|
||||
if pos.len() != 4 || uvs.len() != 4 {
|
||||
panic!("Invalid pos/uv sizes: {}/{}", pos.len(), uvs.len());
|
||||
}
|
||||
|
||||
let pipeline =
|
||||
pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig { filter_type, z_test }));
|
||||
let vert_range = push_verts(
|
||||
&pos.iter()
|
||||
.zip(uvs)
|
||||
.map(|(pos, uv)| Vert { pos: pos.into(), uv: uv.into() })
|
||||
.collect::<Vec<Vert>>(),
|
||||
);
|
||||
let uniform_range = push_uniform(&Uniform { xf: get_combined_matrix(), color, lod: 0.0 });
|
||||
|
||||
push_textured_quad(texture, pipeline, vert_range, uniform_range);
|
||||
}
|
||||
|
||||
fn push_textured_quad(
|
||||
texture: TextureRef,
|
||||
pipeline: PipelineRef,
|
||||
vert_range: Range<u64>,
|
||||
uniform_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() };
|
||||
let groups = &mut state.textured_quad.texture_bind_groups;
|
||||
|
|
|
@ -189,6 +189,14 @@ impl From<CVector2f> for Vec2<f32> {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl From<&CVector2f> for Vec2<f32> {
|
||||
fn from(v: &CVector2f) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec3<f32>> for CVector3f {
|
||||
fn from(v: Vec3<f32>) -> Self {
|
||||
|
@ -209,3 +217,12 @@ impl From<CVector3f> for Vec3<f32> {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl From<&CVector3f> for Vec3<f32> {
|
||||
fn from(v: &CVector3f) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
z: v.z,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -437,6 +437,19 @@ public:
|
|||
void onAppWindowMoved(std::int32_t x, std::int32_t y) noexcept override {
|
||||
// TODO: implement this
|
||||
}
|
||||
|
||||
void onControllerButton(uint32_t idx, aurora::ControllerButton button, bool pressed) noexcept override {
|
||||
if (auto* input = g_InputGenerator) {
|
||||
input->controllerButton(idx, button, pressed);
|
||||
}
|
||||
}
|
||||
|
||||
void onControllerAxis(uint32_t idx, aurora::ControllerAxis axis, int16_t value) noexcept override {
|
||||
if (auto* input = g_InputGenerator) {
|
||||
input->controllerAxis(idx, axis, value);
|
||||
}
|
||||
}
|
||||
|
||||
void onAppExiting() noexcept override {
|
||||
m_imGuiConsole.Shutdown();
|
||||
if (g_mainMP1) {
|
||||
|
@ -451,12 +464,12 @@ public:
|
|||
CDvdFile::Shutdown();
|
||||
}
|
||||
|
||||
void onCharKeyDown(uint8_t code, bool is_repeat) noexcept override {
|
||||
Log.report(logvisor::Info, FMT_STRING("DEBUG CHAR KEYS: '{}', is_repeat {}"), static_cast<char>(code), is_repeat);
|
||||
void onCharKeyDown(uint8_t code, 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, is_repeat);
|
||||
as->charKeyDown(code, boo::EModifierKey::None, isRepeat);
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
@ -471,12 +484,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void onSpecialKeyDown(const aurora::SpecialKey& key, bool is_repeat) noexcept override {
|
||||
Log.report(logvisor::Info, FMT_STRING("DEBUG KEYS: SpecialKey {}, is_repeat {}"), key, is_repeat);
|
||||
void onSpecialKeyDown(aurora::SpecialKey key, 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, is_repeat);
|
||||
as->specialKeyDown(boo::ESpecialKey(key), boo::EModifierKey::None, isRepeat);
|
||||
}
|
||||
}
|
||||
// if (True(mods & boo::EModifierKey::Alt)) {
|
||||
|
@ -488,7 +501,7 @@ public:
|
|||
// }
|
||||
}
|
||||
|
||||
void onSpecialKeyUp(const aurora::SpecialKey& key) noexcept override {
|
||||
void onSpecialKeyUp(aurora::SpecialKey key) 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()) {
|
||||
|
|
|
@ -136,7 +136,7 @@ endfunction()
|
|||
|
||||
set(RUNTIME_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(RUNTIME_LIBRARIES ${HECL_APPLICATION_REPS_TARGETS_LIST} RetroDataSpec AssetNameMapNull NESEmulator
|
||||
libjpeg-turbo jbus kabufuda discord-rpc logvisor OptickCore imgui aurora)
|
||||
libjpeg-turbo jbus kabufuda discord-rpc logvisor OptickCore imgui aurora SDL2-static)
|
||||
|
||||
add_runtime_common_library(RuntimeCommon ${RUNTIME_SOURCES_A})
|
||||
target_include_directories(RuntimeCommon PUBLIC ${RUNTIME_INCLUDES})
|
||||
|
|
|
@ -14,7 +14,7 @@ zeus::CMatrix4f g_PlatformMatrix;
|
|||
|
||||
/* used in the original to look up fixed-point dividends on a
|
||||
* MIDI-style volume scale (0-127) -> (n/0x8000) */
|
||||
static const u16 StaticVolumeLookup[] = {
|
||||
static const std::array<u16, 128> StaticVolumeLookup = {
|
||||
0x0000, 0x0002, 0x0008, 0x0012, 0x0020, 0x0032, 0x0049, 0x0063, 0x0082, 0x00A4, 0x00CB, 0x00F5, 0x0124,
|
||||
0x0157, 0x018E, 0x01C9, 0x0208, 0x024B, 0x0292, 0x02DD, 0x032C, 0x037F, 0x03D7, 0x0432, 0x0492, 0x04F5,
|
||||
0x055D, 0x05C9, 0x0638, 0x06AC, 0x0724, 0x07A0, 0x0820, 0x08A4, 0x092C, 0x09B8, 0x0A48, 0x0ADD, 0x0B75,
|
||||
|
|
|
@ -6,16 +6,61 @@ namespace metaforce {
|
|||
|
||||
CFinalInput::CFinalInput() = default;
|
||||
|
||||
CFinalInput::CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput,
|
||||
//CFinalInput::CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput,
|
||||
// float leftDiv, float rightDiv)
|
||||
//: x0_dt(dt)
|
||||
//, x4_controllerIdx(cIdx)
|
||||
//, x8_anaLeftX(zeus::clamp(-1.0f, data.m_leftStick[0] / 72.0f / leftDiv, 1.0f))
|
||||
//, xc_anaLeftY(zeus::clamp(-1.0f, data.m_leftStick[1] / 72.0f / leftDiv, 1.0f))
|
||||
//, x10_anaRightX(zeus::clamp(-1.0f, data.m_rightStick[0] / 59.0f / rightDiv, 1.0f))
|
||||
//, x14_anaRightY(zeus::clamp(-1.0f, data.m_rightStick[1] / 59.0f / rightDiv, 1.0f))
|
||||
//, x18_anaLeftTrigger(data.m_analogTriggers[0] * 0.007f)
|
||||
//, x1c_anaRightTrigger(data.m_analogTriggers[1] * 0.007f)
|
||||
//, x20_enableAnaLeftXP(DLARight() && !prevInput.DLARight())
|
||||
//, x20_enableAnaLeftNegXP(DLALeft() && !prevInput.DLALeft())
|
||||
//, x21_enableAnaLeftYP(DLAUp() && !prevInput.DLAUp())
|
||||
//, x21_enableAnaLeftNegYP(DLADown() && !prevInput.DLADown())
|
||||
//, x22_enableAnaRightXP(DRARight() && !prevInput.DRARight())
|
||||
//, x22_enableAnaRightNegXP(DRALeft() && !prevInput.DRALeft())
|
||||
//, x23_enableAnaRightYP(DRAUp() && !prevInput.DRAUp())
|
||||
//, x23_enableAnaRightNegYP(DRADown() && !prevInput.DRADown())
|
||||
//, x24_anaLeftTriggerP(DLTrigger() && !prevInput.DLTrigger())
|
||||
//, x28_anaRightTriggerP(DRTrigger() && !prevInput.DRTrigger())
|
||||
//, x2c_b24_A(data.m_btns & uint16_t(boo::EDolphinControllerButtons::A))
|
||||
//, x2c_b25_B(data.m_btns & uint16_t(boo::EDolphinControllerButtons::B))
|
||||
//, x2c_b26_X(data.m_btns & uint16_t(boo::EDolphinControllerButtons::X))
|
||||
//, x2c_b27_Y(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Y))
|
||||
//, x2c_b28_Z(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Z))
|
||||
//, x2c_b29_L(data.m_btns & uint16_t(boo::EDolphinControllerButtons::L))
|
||||
//, x2c_b30_R(data.m_btns & uint16_t(boo::EDolphinControllerButtons::R))
|
||||
//, x2c_b31_DPUp(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Up))
|
||||
//, x2d_b24_DPRight(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Right))
|
||||
//, x2d_b25_DPDown(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Down))
|
||||
//, x2d_b26_DPLeft(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Left))
|
||||
//, x2d_b27_Start(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Start))
|
||||
//, x2d_b28_PA(DA() && !prevInput.DA())
|
||||
//, x2d_b29_PB(DB() && !prevInput.DB())
|
||||
//, x2d_b30_PX(DX() && !prevInput.DX())
|
||||
//, x2d_b31_PY(DY() && !prevInput.DY())
|
||||
//, x2e_b24_PZ(DZ() && !prevInput.DZ())
|
||||
//, x2e_b25_PL(DL() && !prevInput.DL())
|
||||
//, x2e_b26_PR(DR() && !prevInput.DR())
|
||||
//, x2e_b27_PDPUp(DDPUp() && !prevInput.DDPUp())
|
||||
//, x2e_b28_PDPRight(DDPRight() && !prevInput.DDPRight())
|
||||
//, x2e_b29_PDPDown(DDPDown() && !prevInput.DDPDown())
|
||||
//, x2e_b30_PDPLeft(DDPLeft() && !prevInput.DDPLeft())
|
||||
//, x2e_b31_PStart(DStart() && !prevInput.DStart()) {}
|
||||
|
||||
CFinalInput::CFinalInput(int cIdx, float dt, const SAuroraControllerState& data, const CFinalInput& prevInput,
|
||||
float leftDiv, float rightDiv)
|
||||
: x0_dt(dt)
|
||||
, x4_controllerIdx(cIdx)
|
||||
, x8_anaLeftX(zeus::clamp(-1.0f, data.m_leftStick[0] / 72.0f / leftDiv, 1.0f))
|
||||
, xc_anaLeftY(zeus::clamp(-1.0f, data.m_leftStick[1] / 72.0f / leftDiv, 1.0f))
|
||||
, x10_anaRightX(zeus::clamp(-1.0f, data.m_rightStick[0] / 59.0f / rightDiv, 1.0f))
|
||||
, x14_anaRightY(zeus::clamp(-1.0f, data.m_rightStick[1] / 59.0f / rightDiv, 1.0f))
|
||||
, x18_anaLeftTrigger(data.m_analogTriggers[0] * 0.007f)
|
||||
, x1c_anaRightTrigger(data.m_analogTriggers[1] * 0.007f)
|
||||
, x8_anaLeftX(zeus::clamp(-1.0f, data.m_axes[size_t(aurora::ControllerAxis::LeftX)] / 72.0f / leftDiv, 1.0f))
|
||||
, xc_anaLeftY(zeus::clamp(-1.0f, data.m_axes[size_t(aurora::ControllerAxis::LeftY)] / 72.0f / leftDiv, 1.0f))
|
||||
, x10_anaRightX(zeus::clamp(-1.0f, data.m_axes[size_t(aurora::ControllerAxis::RightX)] / 59.0f / rightDiv, 1.0f))
|
||||
, x14_anaRightY(zeus::clamp(-1.0f, data.m_axes[size_t(aurora::ControllerAxis::RightY)] / 59.0f / rightDiv, 1.0f))
|
||||
, x18_anaLeftTrigger(data.m_axes[size_t(aurora::ControllerAxis::TriggerLeft)] * 0.007f)
|
||||
, x1c_anaRightTrigger(data.m_axes[size_t(aurora::ControllerAxis::TriggerRight)] * 0.007f)
|
||||
, x20_enableAnaLeftXP(DLARight() && !prevInput.DLARight())
|
||||
, x20_enableAnaLeftNegXP(DLALeft() && !prevInput.DLALeft())
|
||||
, x21_enableAnaLeftYP(DLAUp() && !prevInput.DLAUp())
|
||||
|
@ -26,18 +71,18 @@ CFinalInput::CFinalInput(int cIdx, float dt, const boo::DolphinControllerState&
|
|||
, x23_enableAnaRightNegYP(DRADown() && !prevInput.DRADown())
|
||||
, x24_anaLeftTriggerP(DLTrigger() && !prevInput.DLTrigger())
|
||||
, x28_anaRightTriggerP(DRTrigger() && !prevInput.DRTrigger())
|
||||
, x2c_b24_A(data.m_btns & uint16_t(boo::EDolphinControllerButtons::A))
|
||||
, x2c_b25_B(data.m_btns & uint16_t(boo::EDolphinControllerButtons::B))
|
||||
, x2c_b26_X(data.m_btns & uint16_t(boo::EDolphinControllerButtons::X))
|
||||
, x2c_b27_Y(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Y))
|
||||
, x2c_b28_Z(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Z))
|
||||
, x2c_b29_L(data.m_btns & uint16_t(boo::EDolphinControllerButtons::L))
|
||||
, x2c_b30_R(data.m_btns & uint16_t(boo::EDolphinControllerButtons::R))
|
||||
, x2c_b31_DPUp(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Up))
|
||||
, x2d_b24_DPRight(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Right))
|
||||
, x2d_b25_DPDown(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Down))
|
||||
, x2d_b26_DPLeft(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Left))
|
||||
, x2d_b27_Start(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Start))
|
||||
, x2c_b24_A(data.m_btns[size_t(aurora::ControllerButton::A)])
|
||||
, x2c_b25_B(data.m_btns[size_t(aurora::ControllerButton::B)])
|
||||
, x2c_b26_X(data.m_btns[size_t(aurora::ControllerButton::X)])
|
||||
, x2c_b27_Y(data.m_btns[size_t(aurora::ControllerButton::Y)])
|
||||
, x2c_b28_Z(data.m_btns[size_t(aurora::ControllerButton::RightShoulder)])
|
||||
, x2c_b29_L(data.m_axes[size_t(aurora::ControllerAxis::TriggerLeft)] > 29490)
|
||||
, x2c_b30_R(data.m_axes[size_t(aurora::ControllerAxis::TriggerRight)] > 29490)
|
||||
, x2c_b31_DPUp(data.m_btns[size_t(aurora::ControllerButton::DPadUp)])
|
||||
, x2d_b24_DPRight(data.m_btns[size_t(aurora::ControllerButton::DPadRight)])
|
||||
, x2d_b25_DPDown(data.m_btns[size_t(aurora::ControllerButton::DPadDown)])
|
||||
, x2d_b26_DPLeft(data.m_btns[size_t(aurora::ControllerButton::DPadLeft)])
|
||||
, x2d_b27_Start(data.m_btns[size_t(aurora::ControllerButton::Start)])
|
||||
, x2d_b28_PA(DA() && !prevInput.DA())
|
||||
, x2d_b29_PB(DB() && !prevInput.DB())
|
||||
, x2d_b30_PX(DX() && !prevInput.DX())
|
||||
|
|
|
@ -2,13 +2,20 @@
|
|||
|
||||
#include <array>
|
||||
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
#include "Runtime/Input/CKeyboardMouseController.hpp"
|
||||
#include "Runtime/RetroTypes.hpp"
|
||||
|
||||
#include <boo/inputdev/DolphinSmashAdapter.hpp>
|
||||
#include "aurora.h"
|
||||
|
||||
//#include <boo/inputdev/DolphinSmashAdapter.hpp>
|
||||
|
||||
namespace metaforce {
|
||||
|
||||
struct SAuroraControllerState {
|
||||
std::array<int16_t, size_t(aurora::ControllerAxis::MAX)> m_axes{};
|
||||
std::bitset<size_t(aurora::ControllerButton::MAX)> m_btns{};
|
||||
};
|
||||
|
||||
struct CFinalInput {
|
||||
float x0_dt = 0.0f;
|
||||
u32 x4_controllerIdx = 0;
|
||||
|
@ -72,7 +79,9 @@ struct CFinalInput {
|
|||
float m_rightMul = 1.f;
|
||||
|
||||
CFinalInput();
|
||||
CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput, float leftDiv,
|
||||
// CFinalInput(int cIdx, float dt, const boo::DolphinControllerState& data, const CFinalInput& prevInput, float leftDiv,
|
||||
// float rightDiv);
|
||||
CFinalInput(int cIdx, float dt, const SAuroraControllerState& data, const CFinalInput& prevInput, float leftDiv,
|
||||
float rightDiv);
|
||||
CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& data, const CFinalInput& prevInput);
|
||||
|
||||
|
|
|
@ -11,33 +11,31 @@ void CInputGenerator::Update(float dt, CArchitectureQueue& queue) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Keyboard/Mouse first */
|
||||
CFinalInput kbInput = getFinalInput(0, dt);
|
||||
bool kbUsed = false;
|
||||
const CFinalInput& kbInput = getFinalInput(0, dt);
|
||||
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, kbInput));
|
||||
|
||||
/* Dolphin controllers next */
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
bool connected;
|
||||
EStatusChange change = m_dolphinCb.getStatusChange(i, connected);
|
||||
if (change != EStatusChange::NoChange)
|
||||
queue.Push(MakeMsg::CreateControllerStatus(EArchMsgTarget::Game, i, connected));
|
||||
if (connected) {
|
||||
CFinalInput input = m_dolphinCb.getFinalInput(i, dt, m_leftDiv, m_rightDiv);
|
||||
if (i == 0) /* Merge KB input with first controller */
|
||||
{
|
||||
input |= kbInput;
|
||||
kbUsed = true;
|
||||
}
|
||||
m_lastUpdate = input;
|
||||
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, input));
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < 4; ++i) {
|
||||
// bool connected;
|
||||
// EStatusChange change = m_dolphinCb.getStatusChange(i, connected);
|
||||
// if (change != EStatusChange::NoChange)
|
||||
// queue.Push(MakeMsg::CreateControllerStatus(EArchMsgTarget::Game, i, connected));
|
||||
// if (connected) {
|
||||
// CFinalInput input = m_dolphinCb.getFinalInput(i, dt, m_leftDiv, m_rightDiv);
|
||||
// if (i == 0) /* Merge KB input with first controller */
|
||||
// {
|
||||
// input |= kbInput;
|
||||
// kbUsed = true;
|
||||
// }
|
||||
// m_lastUpdate = input;
|
||||
// queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, input));
|
||||
// }
|
||||
// }
|
||||
|
||||
/* Send straight keyboard input if no first controller present */
|
||||
if (!kbUsed) {
|
||||
m_lastUpdate = kbInput;
|
||||
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, kbInput));
|
||||
}
|
||||
// /* Send straight keyboard input if no first controller present */
|
||||
// if (!kbUsed) {
|
||||
// m_lastUpdate = kbInput;
|
||||
// }
|
||||
}
|
||||
|
||||
} // namespace metaforce
|
||||
|
|
|
@ -16,7 +16,7 @@ enum class EIOPort { Zero, One, Two, Three };
|
|||
|
||||
enum class EMotorState { Stop, Rumble, StopHard };
|
||||
|
||||
class CInputGenerator : public boo::DeviceFinder {
|
||||
class CInputGenerator /*: public boo::DeviceFinder*/ {
|
||||
enum class EStatusChange { NoChange = 0, Connected = 1, Disconnected = 2 };
|
||||
|
||||
/* When the sticks are used as logical (digital) input,
|
||||
|
@ -25,10 +25,14 @@ class CInputGenerator : public boo::DeviceFinder {
|
|||
float m_leftDiv;
|
||||
float m_rightDiv;
|
||||
CKeyboardMouseControllerData m_data;
|
||||
SAuroraControllerState m_state;
|
||||
|
||||
CFinalInput m_lastUpdate;
|
||||
const CFinalInput& getFinalInput(unsigned idx, float dt) {
|
||||
m_lastUpdate = CFinalInput(idx, dt, m_data, m_lastUpdate);
|
||||
auto input = CFinalInput(idx, dt, m_data, m_lastUpdate);
|
||||
// Merge controller input with kb/m input
|
||||
input |= CFinalInput(idx, dt, m_state, m_lastUpdate, m_leftDiv, m_rightDiv);
|
||||
m_lastUpdate = input;
|
||||
return m_lastUpdate;
|
||||
}
|
||||
|
||||
|
@ -36,13 +40,22 @@ class CInputGenerator : public boo::DeviceFinder {
|
|||
|
||||
public:
|
||||
CInputGenerator(float leftDiv, float rightDiv)
|
||||
: boo::DeviceFinder({dev_typeid(DolphinSmashAdapter)}), m_leftDiv(leftDiv), m_rightDiv(rightDiv) {}
|
||||
: /*boo::DeviceFinder({dev_typeid(DolphinSmashAdapter)}),*/ m_leftDiv(leftDiv), m_rightDiv(rightDiv) {}
|
||||
|
||||
~CInputGenerator() override {
|
||||
if (smashAdapter) {
|
||||
smashAdapter->setCallback(nullptr);
|
||||
smashAdapter->closeDevice();
|
||||
}
|
||||
// ~CInputGenerator() override {
|
||||
// if (smashAdapter) {
|
||||
// smashAdapter->setCallback(nullptr);
|
||||
// smashAdapter->closeDevice();
|
||||
// }
|
||||
// }
|
||||
|
||||
void controllerButton(uint32_t idx, aurora::ControllerButton button, bool pressed) noexcept {
|
||||
// TODO check idx
|
||||
m_state.m_btns.set(size_t(button), pressed);
|
||||
}
|
||||
void controllerAxis(uint32_t idx, aurora::ControllerAxis axis, int16_t value) noexcept {
|
||||
// TODO check idx
|
||||
m_state.m_axes[size_t(axis)] = value;
|
||||
}
|
||||
|
||||
/* Keyboard and mouse events are delivered on the main game
|
||||
|
@ -79,103 +92,77 @@ public:
|
|||
|
||||
void reset() { m_data.m_accumScroll.zeroOut(); }
|
||||
|
||||
/* Input via the smash adapter is received asynchronously on a USB
|
||||
* report thread. This class atomically exchanges that data to the
|
||||
* game thread as needed */
|
||||
struct DolphinSmashAdapterCallback : boo::IDolphinSmashAdapterCallback {
|
||||
std::array<std::atomic<EStatusChange>, 4> m_statusChanges;
|
||||
std::array<bool, 4> m_connected{};
|
||||
std::array<boo::DolphinControllerState, 4> m_states;
|
||||
std::mutex m_stateLock;
|
||||
void controllerConnected(unsigned idx, boo::EDolphinControllerType) override {
|
||||
/* Controller thread */
|
||||
m_statusChanges[idx].store(EStatusChange::Connected);
|
||||
}
|
||||
void controllerDisconnected(unsigned idx) override {
|
||||
/* Controller thread */
|
||||
std::unique_lock lk{m_stateLock};
|
||||
m_statusChanges[idx].store(EStatusChange::Disconnected);
|
||||
m_states[idx].reset();
|
||||
}
|
||||
void controllerUpdate(unsigned idx, boo::EDolphinControllerType,
|
||||
const boo::DolphinControllerState& state) override {
|
||||
/* Controller thread */
|
||||
std::unique_lock lk{m_stateLock};
|
||||
m_states[idx] = state;
|
||||
}
|
||||
// /* Input via the smash adapter is received asynchronously on a USB
|
||||
// * report thread. This class atomically exchanges that data to the
|
||||
// * game thread as needed */
|
||||
// struct DolphinSmashAdapterCallback : boo::IDolphinSmashAdapterCallback {
|
||||
// std::array<std::atomic<EStatusChange>, 4> m_statusChanges;
|
||||
// std::array<bool, 4> m_connected{};
|
||||
// std::array<boo::DolphinControllerState, 4> m_states;
|
||||
// std::mutex m_stateLock;
|
||||
// void controllerConnected(unsigned idx, boo::EDolphinControllerType) override {
|
||||
// /* Controller thread */
|
||||
// m_statusChanges[idx].store(EStatusChange::Connected);
|
||||
// }
|
||||
// void controllerDisconnected(unsigned idx) override {
|
||||
// /* Controller thread */
|
||||
// std::unique_lock lk{m_stateLock};
|
||||
// m_statusChanges[idx].store(EStatusChange::Disconnected);
|
||||
// m_states[idx].reset();
|
||||
// }
|
||||
// void controllerUpdate(unsigned idx, boo::EDolphinControllerType,
|
||||
// const boo::DolphinControllerState& state) override {
|
||||
// /* Controller thread */
|
||||
// std::unique_lock lk{m_stateLock};
|
||||
// m_states[idx] = state;
|
||||
// }
|
||||
//
|
||||
// std::array<CFinalInput, 4> m_lastUpdates;
|
||||
// const CFinalInput& getFinalInput(unsigned idx, float dt, float leftDiv, float rightDiv) {
|
||||
// /* Game thread */
|
||||
// std::unique_lock lk{m_stateLock};
|
||||
// boo::DolphinControllerState state = m_states[idx];
|
||||
// lk.unlock();
|
||||
// state.clamp(); /* PADClamp equivalent */
|
||||
// m_lastUpdates[idx] = CFinalInput(idx, dt, state, m_lastUpdates[idx], leftDiv, rightDiv);
|
||||
// return m_lastUpdates[idx];
|
||||
// }
|
||||
// EStatusChange getStatusChange(unsigned idx, bool& connected) {
|
||||
// /* Game thread */
|
||||
// EStatusChange ch = m_statusChanges[idx].exchange(EStatusChange::NoChange);
|
||||
// if (ch == EStatusChange::Connected)
|
||||
// m_connected[idx] = true;
|
||||
// else if (ch == EStatusChange::Disconnected)
|
||||
// m_connected[idx] = false;
|
||||
// connected = m_connected[idx];
|
||||
// return ch;
|
||||
// }
|
||||
// } m_dolphinCb;
|
||||
|
||||
std::array<CFinalInput, 4> m_lastUpdates;
|
||||
const CFinalInput& getFinalInput(unsigned idx, float dt, float leftDiv, float rightDiv) {
|
||||
/* Game thread */
|
||||
std::unique_lock lk{m_stateLock};
|
||||
boo::DolphinControllerState state = m_states[idx];
|
||||
lk.unlock();
|
||||
state.clamp(); /* PADClamp equivalent */
|
||||
m_lastUpdates[idx] = CFinalInput(idx, dt, state, m_lastUpdates[idx], leftDiv, rightDiv);
|
||||
return m_lastUpdates[idx];
|
||||
}
|
||||
EStatusChange getStatusChange(unsigned idx, bool& connected) {
|
||||
/* Game thread */
|
||||
EStatusChange ch = m_statusChanges[idx].exchange(EStatusChange::NoChange);
|
||||
if (ch == EStatusChange::Connected)
|
||||
m_connected[idx] = true;
|
||||
else if (ch == EStatusChange::Disconnected)
|
||||
m_connected[idx] = false;
|
||||
connected = m_connected[idx];
|
||||
return ch;
|
||||
}
|
||||
} m_dolphinCb;
|
||||
|
||||
/* Device connection/disconnection events are handled on a separate thread
|
||||
* using the relevant OS API. This thread blocks in a loop until an event is
|
||||
* received. Device pointers should only be manipulated by this thread using
|
||||
* the deviceConnected() and deviceDisconnected() callbacks. */
|
||||
std::shared_ptr<boo::DolphinSmashAdapter> smashAdapter;
|
||||
void deviceConnected(boo::DeviceToken& tok) override {
|
||||
/* Device listener thread */
|
||||
if (!smashAdapter) {
|
||||
auto dev = tok.openAndGetDevice();
|
||||
if (dev && dev->getTypeHash() == dev_typeid(DolphinSmashAdapter)) {
|
||||
smashAdapter = std::static_pointer_cast<boo::DolphinSmashAdapter>(tok.openAndGetDevice());
|
||||
smashAdapter->setCallback(&m_dolphinCb);
|
||||
}
|
||||
}
|
||||
}
|
||||
void deviceDisconnected(boo::DeviceToken&, boo::DeviceBase* device) override {
|
||||
if (smashAdapter.get() == device)
|
||||
smashAdapter.reset();
|
||||
}
|
||||
// /* Device connection/disconnection events are handled on a separate thread
|
||||
// * using the relevant OS API. This thread blocks in a loop until an event is
|
||||
// * received. Device pointers should only be manipulated by this thread using
|
||||
// * the deviceConnected() and deviceDisconnected() callbacks. */
|
||||
// std::shared_ptr<boo::DolphinSmashAdapter> smashAdapter;
|
||||
// void deviceConnected(boo::DeviceToken& tok) override {
|
||||
// /* Device listener thread */
|
||||
// if (!smashAdapter) {
|
||||
// auto dev = tok.openAndGetDevice();
|
||||
// if (dev && dev->getTypeHash() == dev_typeid(DolphinSmashAdapter)) {
|
||||
// smashAdapter = std::static_pointer_cast<boo::DolphinSmashAdapter>(tok.openAndGetDevice());
|
||||
// smashAdapter->setCallback(&m_dolphinCb);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// void deviceDisconnected(boo::DeviceToken&, boo::DeviceBase* device) override {
|
||||
// if (smashAdapter.get() == device)
|
||||
// smashAdapter.reset();
|
||||
// }
|
||||
void SetMotorState(EIOPort port, EMotorState state) {
|
||||
if (smashAdapter) {
|
||||
switch (state) {
|
||||
case EMotorState::Stop:
|
||||
smashAdapter->stopRumble(unsigned(port));
|
||||
break;
|
||||
case EMotorState::Rumble:
|
||||
smashAdapter->startRumble(unsigned(port));
|
||||
break;
|
||||
case EMotorState::StopHard:
|
||||
smashAdapter->stopRumble(unsigned(port), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// TODO aurora
|
||||
}
|
||||
void ControlAllMotors(const std::array<EMotorState, 4>& states) {
|
||||
if (smashAdapter) {
|
||||
for (size_t i = 0; i < states.size(); ++i) {
|
||||
switch (states[i]) {
|
||||
case EMotorState::Stop:
|
||||
smashAdapter->stopRumble(i);
|
||||
break;
|
||||
case EMotorState::Rumble:
|
||||
smashAdapter->startRumble(i);
|
||||
break;
|
||||
case EMotorState::StopHard:
|
||||
smashAdapter->stopRumble(i, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO aurora
|
||||
}
|
||||
|
||||
/* This is where the game thread enters */
|
||||
|
|
|
@ -100,7 +100,7 @@ CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, boo::IAudioVoi
|
|||
, x44_guiSys(*g_ResFactory, *g_SimplePool, CGuiSys::EUsageMode::Zero) {
|
||||
auto* m = static_cast<CMain*>(g_Main);
|
||||
|
||||
x30_inputGenerator.startScanning();
|
||||
// x30_inputGenerator.startScanning();
|
||||
g_InputGenerator = &x30_inputGenerator;
|
||||
|
||||
CAudioSys::SysSetVolume(0x7f);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 53091e36a3b418e33133bae2f018954c006f86b8
|
Loading…
Reference in New Issue