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"]
|
[submodule "extern/imgui"]
|
||||||
path = extern/imgui
|
path = extern/imgui
|
||||||
url = https://github.com/ocornut/imgui.git
|
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-full PRIVATE zeus nod)
|
||||||
target_link_libraries(hecl-light PRIVATE zeus nod)
|
target_link_libraries(hecl-light PRIVATE zeus nod)
|
||||||
|
|
||||||
#bintoc(CModelShaders.common.glsl.cpp Shaders/CModelShaders.common.glsl CMODELSHADERS_COMMON_GLSL)
|
add_subdirectory(extern/SDL EXCLUDE_FROM_ALL)
|
||||||
#bintoc(CModelShaders.vert.glsl.cpp Shaders/CModelShaders.vert.glsl CMODELSHADERS_VERT_GLSL)
|
target_compile_options(SDL2-static PRIVATE -Wno-implicit-fallthrough)
|
||||||
#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)
|
|
||||||
|
|
||||||
if(NOT TARGET atdna)
|
if(NOT TARGET atdna)
|
||||||
# Import native atdna if cross-compiling
|
# Import native atdna if cross-compiling
|
||||||
|
|
|
@ -116,6 +116,7 @@ dependencies = [
|
||||||
"num_enum",
|
"num_enum",
|
||||||
"pollster",
|
"pollster",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
|
"sdl2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"twox-hash",
|
"twox-hash",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
|
@ -1439,6 +1440,27 @@ version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96311ef4a16462c757bb6a39152c40f58f31cd2602a40fceb937e2bc34e6cbab"
|
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]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.132"
|
version = "1.0.132"
|
||||||
|
@ -1703,6 +1725,12 @@ version = "0.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version-compare"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
|
|
|
@ -29,6 +29,8 @@ smallvec = "1.7.0"
|
||||||
scopeguard = "1.1.0"
|
scopeguard = "1.1.0"
|
||||||
twox-hash = "1.6.2"
|
twox-hash = "1.6.2"
|
||||||
winit = "0.26.1"
|
winit = "0.26.1"
|
||||||
|
# custom sdl2
|
||||||
|
sdl2 = { git = "https://github.com/encounter/rust-sdl2.git", rev = "e282ef3acd7fcb4b2ba16863a7a0a7a8439f9335", features = ["no-link", "hidapi"] }
|
||||||
|
|
||||||
[dependencies.imgui]
|
[dependencies.imgui]
|
||||||
git = "https://github.com/imgui-rs/imgui-rs"
|
git = "https://github.com/imgui-rs/imgui-rs"
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cinttypes>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cinttypes>
|
|
||||||
|
|
||||||
namespace aurora {
|
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;
|
struct WindowSize;
|
||||||
|
|
||||||
|
@ -24,14 +26,18 @@ struct AppDelegate {
|
||||||
virtual void onAppDraw() noexcept = 0;
|
virtual void onAppDraw() noexcept = 0;
|
||||||
virtual void onAppPostDraw() noexcept = 0;
|
virtual void onAppPostDraw() noexcept = 0;
|
||||||
virtual void onAppWindowResized(const WindowSize& size) 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;
|
virtual void onAppExiting() noexcept = 0;
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
virtual void onCharKeyDown(std::uint8_t charCode, bool is_repeat) noexcept = 0;
|
virtual void onCharKeyDown(uint8_t charCode, bool isRepeat) noexcept = 0;
|
||||||
virtual void onCharKeyUp(std::uint8_t charCode) noexcept = 0;
|
virtual void onCharKeyUp(uint8_t charCode) noexcept = 0;
|
||||||
virtual void onSpecialKeyDown(const SpecialKey& key, bool is_repeat) noexcept = 0;
|
virtual void onSpecialKeyDown(SpecialKey key, bool isRepeat) noexcept = 0;
|
||||||
virtual void onSpecialKeyUp(const SpecialKey& key) 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 resized([[maybe_unused]] const WindowSize& rect, [[maybe_unused]] bool sync) noexcept {}
|
||||||
// virtual void mouseDown([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] EMouseButton button,
|
// virtual void mouseDown([[maybe_unused]] const SWindowCoord& coord, [[maybe_unused]] EMouseButton button,
|
||||||
|
|
|
@ -7,11 +7,14 @@ bool App_onAppIdle(AppDelegate& cb, float dt) noexcept;
|
||||||
void App_onAppDraw(AppDelegate& cb) noexcept;
|
void App_onAppDraw(AppDelegate& cb) noexcept;
|
||||||
void App_onAppPostDraw(AppDelegate& cb) noexcept;
|
void App_onAppPostDraw(AppDelegate& cb) noexcept;
|
||||||
void App_onAppWindowResized(AppDelegate& cb, const WindowSize& size) 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_onAppWindowMoved(AppDelegate& cb, int32_t x, int32_t y) noexcept;
|
||||||
void App_onAppExiting(AppDelegate& cb) noexcept;
|
void App_onAppExiting(AppDelegate& cb) noexcept;
|
||||||
// Input
|
// Input
|
||||||
void App_onCharKeyDown(AppDelegate& cb, std::uint8_t code, bool is_repeat) noexcept;
|
void App_onCharKeyDown(AppDelegate& cb, uint8_t code, bool isRepeat) noexcept;
|
||||||
void App_onCharKeyUp(AppDelegate& cb, std::uint8_t code) noexcept;
|
void App_onCharKeyUp(AppDelegate& cb, uint8_t code) noexcept;
|
||||||
void App_onSpecialKeyDown(AppDelegate& cb, const SpecialKey& key, bool is_repeat);
|
void App_onSpecialKeyDown(AppDelegate& cb, SpecialKey key, bool isRepeat) noexcept;
|
||||||
void App_onSpecialKeyUp(AppDelegate& cb, const SpecialKey& key);
|
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
|
} // namespace aurora
|
||||||
|
|
|
@ -8,22 +8,30 @@ void App_onAppPostDraw(AppDelegate& cb) noexcept { cb.onAppPostDraw(); }
|
||||||
void App_onAppWindowResized(AppDelegate& cb, const WindowSize& size) noexcept {
|
void App_onAppWindowResized(AppDelegate& cb, const WindowSize& size) noexcept {
|
||||||
cb.onAppWindowResized(size);
|
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);
|
cb.onAppWindowMoved(x, y);
|
||||||
}
|
}
|
||||||
void App_onAppExiting(AppDelegate& cb) noexcept { cb.onAppExiting(); }
|
void App_onAppExiting(AppDelegate& cb) noexcept { cb.onAppExiting(); }
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
void App_onCharKeyDown(AppDelegate& cb, std::uint8_t code, bool is_repeat) noexcept {
|
void App_onCharKeyDown(AppDelegate& cb, uint8_t code, bool isRepeat) noexcept {
|
||||||
cb.onCharKeyDown(code, is_repeat);
|
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);
|
cb.onCharKeyUp(code);
|
||||||
}
|
}
|
||||||
void App_onSpecialKeyDown(AppDelegate& cb, const SpecialKey& key, bool is_repeat) {
|
void App_onSpecialKeyDown(AppDelegate& cb, SpecialKey key, bool isRepeat) noexcept {
|
||||||
cb.onSpecialKeyDown(key, is_repeat);
|
cb.onSpecialKeyDown(key, isRepeat);
|
||||||
}
|
}
|
||||||
void App_onSpecialKeyUp(AppDelegate& cb, const SpecialKey& key) {
|
void App_onSpecialKeyUp(AppDelegate& cb, SpecialKey key) noexcept {
|
||||||
cb.onSpecialKeyUp(key);
|
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
|
} // namespace aurora
|
||||||
|
|
|
@ -3,29 +3,32 @@
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![allow(unused_unsafe)]
|
#![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 wgpu::Backend;
|
||||||
use winit::{
|
use winit::{
|
||||||
event::{ElementState, Event, KeyboardInput, WindowEvent},
|
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
||||||
event_loop::ControlFlow,
|
event_loop::ControlFlow,
|
||||||
};
|
};
|
||||||
use winit::event::VirtualKeyCode;
|
|
||||||
|
|
||||||
use std::{num::NonZeroU8, time::Instant, collections::HashMap};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ffi::WindowSize,
|
ffi::{SpecialKey, WindowSize},
|
||||||
gpu::{create_depth_texture, create_render_texture, DeviceHolder, initialize_gpu},
|
gpu::{create_depth_texture, create_render_texture, initialize_gpu, DeviceHolder},
|
||||||
imgui::{ImGuiState, initialize_imgui},
|
imgui::{initialize_imgui, ImGuiState},
|
||||||
shaders::render_into_pass,
|
shaders::render_into_pass,
|
||||||
};
|
};
|
||||||
use crate::ffi::SpecialKey;
|
|
||||||
|
|
||||||
mod gpu;
|
mod gpu;
|
||||||
mod imgui;
|
mod imgui;
|
||||||
mod imgui_backend;
|
mod imgui_backend;
|
||||||
mod shaders;
|
mod shaders;
|
||||||
mod zeus;
|
|
||||||
mod util;
|
mod util;
|
||||||
|
mod zeus;
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "aurora")]
|
#[cxx::bridge(namespace = "aurora")]
|
||||||
mod ffi {
|
mod ffi {
|
||||||
|
@ -46,8 +49,25 @@ mod ffi {
|
||||||
// Input
|
// Input
|
||||||
pub(crate) fn App_onCharKeyDown(cb: Pin<&mut AppDelegate>, code: u8, is_repeat: bool);
|
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_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_onSpecialKeyDown(
|
||||||
pub(crate) fn App_onSpecialKeyUp(cb: Pin<&mut AppDelegate>, key: &SpecialKey);
|
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 {
|
pub struct Window {
|
||||||
|
@ -118,6 +138,35 @@ mod ffi {
|
||||||
// pub
|
// 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" {
|
extern "Rust" {
|
||||||
type WindowContext;
|
type WindowContext;
|
||||||
type App;
|
type App;
|
||||||
|
@ -131,11 +180,50 @@ mod ffi {
|
||||||
fn set_fullscreen(v: bool);
|
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 {
|
pub struct App {
|
||||||
window: ffi::Window,
|
window: ffi::Window,
|
||||||
gpu: DeviceHolder,
|
gpu: DeviceHolder,
|
||||||
imgui: ImGuiState,
|
imgui: ImGuiState,
|
||||||
|
// SDL
|
||||||
|
sdl: Sdl,
|
||||||
|
sdl_events: sdl2::EventPump,
|
||||||
|
sdl_controller_sys: GameControllerSubsystem,
|
||||||
|
sdl_open_controllers: HashMap<u32, GameController>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WindowContext {
|
pub struct WindowContext {
|
||||||
|
@ -152,11 +240,22 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
||||||
log::info!("Running app");
|
log::info!("Running app");
|
||||||
let event_loop = winit::event_loop::EventLoop::new();
|
let event_loop = winit::event_loop::EventLoop::new();
|
||||||
let window = winit::window::WindowBuilder::new().build(&event_loop).unwrap();
|
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 gpu = initialize_gpu(&window);
|
||||||
let imgui = initialize_imgui(&window, &gpu);
|
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);
|
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 {
|
unsafe {
|
||||||
APP.replace(app);
|
APP.replace(app);
|
||||||
ffi::App_onAppLaunched(delegate.as_mut().unwrap());
|
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 window_ctx = get_window_context();
|
||||||
let gpu = &mut app.gpu;
|
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;
|
*control_flow = ControlFlow::Poll;
|
||||||
match event {
|
match event {
|
||||||
Event::NewEvents(_) => {}
|
|
||||||
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
|
Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
|
@ -192,26 +344,21 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
||||||
&app.gpu.surface_config,
|
&app.gpu.surface_config,
|
||||||
&app.gpu.config,
|
&app.gpu.config,
|
||||||
);
|
);
|
||||||
|
let window_size = WindowSize {
|
||||||
|
width: app.gpu.surface_config.width,
|
||||||
|
height: app.gpu.surface_config.height,
|
||||||
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let window_size = WindowSize { width: app.gpu.surface_config.width, height: app.gpu.surface_config.height };
|
ffi::App_onAppWindowResized(delegate.as_mut().unwrap_unchecked(), &window_size);
|
||||||
|
|
||||||
ffi::App_onAppWindowResized(delegate.as_mut().unwrap(), &window_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::WindowEvent { event: WindowEvent::Moved(loc), .. } => {
|
Event::WindowEvent { event: WindowEvent::Moved(loc), .. } => unsafe {
|
||||||
unsafe {
|
ffi::App_onAppWindowMoved(delegate.as_mut().unwrap_unchecked(), loc.x, loc.y);
|
||||||
ffi::App_onAppWindowMoved(delegate.as_mut().unwrap(), loc.x, loc.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Event::WindowEvent {
|
|
||||||
event: WindowEvent::KeyboardInput {
|
|
||||||
input:
|
|
||||||
KeyboardInput {
|
|
||||||
scancode,
|
|
||||||
virtual_keycode: Some(key),
|
|
||||||
state,
|
|
||||||
..
|
|
||||||
},
|
},
|
||||||
|
Event::WindowEvent {
|
||||||
|
event:
|
||||||
|
WindowEvent::KeyboardInput {
|
||||||
|
input: KeyboardInput { scancode, virtual_keycode: Some(key), state, .. },
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
..
|
..
|
||||||
|
@ -253,18 +400,20 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if pressed {
|
if pressed {
|
||||||
ffi::App_onSpecialKeyDown(delegate.as_mut().unwrap(), &special_key, repeat);
|
ffi::App_onSpecialKeyDown(
|
||||||
|
delegate.as_mut().unwrap_unchecked(),
|
||||||
|
special_key,
|
||||||
|
repeat,
|
||||||
|
);
|
||||||
} else {
|
} 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 => {
|
Event::MainEventsCleared => {
|
||||||
log::trace!("Requesting redraw");
|
log::trace!("Requesting redraw");
|
||||||
window_ctx.window.request_redraw();
|
window_ctx.window.request_redraw();
|
||||||
|
@ -301,7 +450,7 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
||||||
|
|
||||||
#[allow(unused_unsafe)] // rust bug?
|
#[allow(unused_unsafe)] // rust bug?
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::App_onAppDraw(delegate.as_mut().unwrap());
|
ffi::App_onAppDraw(delegate.as_mut().unwrap_unchecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
let fb_view =
|
let fb_view =
|
||||||
|
@ -357,15 +506,15 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>) {
|
||||||
|
|
||||||
#[allow(unused_unsafe)] // rust bug?
|
#[allow(unused_unsafe)] // rust bug?
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::App_onAppPostDraw(delegate.as_mut().unwrap());
|
ffi::App_onAppPostDraw(delegate.as_mut().unwrap_unchecked());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::RedrawEventsCleared => {}
|
|
||||||
Event::LoopDestroyed => unsafe {
|
Event::LoopDestroyed => unsafe {
|
||||||
ffi::App_onAppExiting(delegate.as_mut().unwrap());
|
ffi::App_onAppExiting(delegate.as_mut().unwrap_unchecked());
|
||||||
APP.take();
|
APP.take();
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
imgui.platform.handle_event(imgui.context.io_mut(), &window_ctx.window, &event);
|
imgui.platform.handle_event(imgui.context.io_mut(), &window_ctx.window, &event);
|
||||||
|
|
|
@ -7,16 +7,15 @@ use crate::{
|
||||||
get_app,
|
get_app,
|
||||||
gpu::GraphicsConfig,
|
gpu::GraphicsConfig,
|
||||||
shaders::{
|
shaders::{
|
||||||
get_combined_matrix,
|
|
||||||
bind_pipeline,
|
bind_pipeline,
|
||||||
BuiltBuffers,
|
ffi::{CameraFilterType, TextureRef, ZTest},
|
||||||
ffi::{CameraFilterType, TextureRef, ZTest}, pipeline_ref, PipelineCreateCommand, PipelineHolder, PipelineRef,
|
get_combined_matrix, pipeline_ref, push_draw_command, push_uniform, push_verts,
|
||||||
push_draw_command, push_uniform, push_verts, ShaderDrawCommand, STATE,
|
texture::create_sampler,
|
||||||
|
BuiltBuffers, PipelineCreateCommand, PipelineHolder, PipelineRef, ShaderDrawCommand, STATE,
|
||||||
},
|
},
|
||||||
|
util::{align, Vec2, Vec3},
|
||||||
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, CVector4f},
|
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, CVector4f},
|
||||||
};
|
};
|
||||||
use crate::shaders::texture::create_sampler;
|
|
||||||
use crate::util::{align, Vec2, Vec3};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct DrawData {
|
pub(crate) struct DrawData {
|
||||||
|
@ -56,10 +55,14 @@ pub(crate) fn construct_state(
|
||||||
) -> State {
|
) -> State {
|
||||||
let shader = device.create_shader_module(&include_wgsl!("shader.wgsl"));
|
let shader = device.create_shader_module(&include_wgsl!("shader.wgsl"));
|
||||||
let uniform_alignment = device.limits().min_uniform_buffer_offset_alignment;
|
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 {
|
let uniform_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
label: Some("Textured Quad Uniform Bind Group Layout"),
|
label: Some("Textured Quad Uniform Bind Group Layout"),
|
||||||
entries: &[wgpu::BindGroupLayoutEntry {
|
entries: &[
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
visibility: wgpu::ShaderStages::VERTEX_FRAGMENT,
|
||||||
ty: wgpu::BindingType::Buffer {
|
ty: wgpu::BindingType::Buffer {
|
||||||
|
@ -68,28 +71,30 @@ pub(crate) fn construct_state(
|
||||||
min_binding_size: uniform_size,
|
min_binding_size: uniform_size,
|
||||||
},
|
},
|
||||||
count: None,
|
count: None,
|
||||||
}, wgpu::BindGroupLayoutEntry {
|
},
|
||||||
|
wgpu::BindGroupLayoutEntry {
|
||||||
binding: 1,
|
binding: 1,
|
||||||
visibility: wgpu::ShaderStages::FRAGMENT,
|
visibility: wgpu::ShaderStages::FRAGMENT,
|
||||||
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
|
||||||
count: None,
|
count: None,
|
||||||
}],
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
let sampler = create_sampler(device, wgpu::AddressMode::Repeat, None);
|
let sampler = create_sampler(device, wgpu::AddressMode::Repeat, None);
|
||||||
let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||||
label: Some("Textured Quad Uniform Bind Group"),
|
label: Some("Textured Quad Uniform Bind Group"),
|
||||||
layout: &uniform_layout,
|
layout: &uniform_layout,
|
||||||
entries: &[wgpu::BindGroupEntry {
|
entries: &[
|
||||||
|
wgpu::BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
|
||||||
buffer: &buffers.uniform_buffer,
|
buffer: &buffers.uniform_buffer,
|
||||||
offset: 0, // dynamic
|
offset: 0, // dynamic
|
||||||
size: uniform_size,
|
size: uniform_size,
|
||||||
}),
|
}),
|
||||||
}, wgpu::BindGroupEntry {
|
},
|
||||||
binding: 1,
|
wgpu::BindGroupEntry { binding: 1, resource: wgpu::BindingResource::Sampler(&sampler) },
|
||||||
resource: wgpu::BindingResource::Sampler(&sampler),
|
],
|
||||||
}],
|
|
||||||
});
|
});
|
||||||
let texture_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
let texture_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||||
label: Some("Textured Quad Texture Bind Group Layout"),
|
label: Some("Textured Quad Texture Bind Group Layout"),
|
||||||
|
@ -170,7 +175,6 @@ pub(crate) fn construct_pipeline(
|
||||||
),
|
),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
log::warn!("VERT SIZE: {}", std::mem::size_of::<Vert>() as u64);
|
|
||||||
PipelineHolder {
|
PipelineHolder {
|
||||||
pipeline: device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
pipeline: device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||||
label: Some("Textured Quad Pipeline"),
|
label: Some("Textured Quad Pipeline"),
|
||||||
|
@ -271,12 +275,38 @@ pub(crate) fn queue_textured_quad(
|
||||||
push_textured_quad(texture, pipeline, vert_range, uniform_range);
|
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(
|
fn push_textured_quad(
|
||||||
texture: TextureRef,
|
texture: TextureRef,
|
||||||
pipeline: PipelineRef,
|
pipeline: PipelineRef,
|
||||||
vert_range: Range<u64>,
|
vert_range: Range<u64>,
|
||||||
uniform_range: Range<u64>
|
uniform_range: Range<u64>,
|
||||||
){
|
) {
|
||||||
// TODO defer bind group creation to draw time or another thread?
|
// TODO defer bind group creation to draw time or another thread?
|
||||||
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
let state = unsafe { STATE.as_mut().unwrap_unchecked() };
|
||||||
let groups = &mut state.textured_quad.texture_bind_groups;
|
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 {
|
impl From<Vec3<f32>> for CVector3f {
|
||||||
fn from(v: Vec3<f32>) -> Self {
|
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 {
|
void onAppWindowMoved(std::int32_t x, std::int32_t y) noexcept override {
|
||||||
// TODO: implement this
|
// 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 {
|
void onAppExiting() noexcept override {
|
||||||
m_imGuiConsole.Shutdown();
|
m_imGuiConsole.Shutdown();
|
||||||
if (g_mainMP1) {
|
if (g_mainMP1) {
|
||||||
|
@ -451,12 +464,12 @@ public:
|
||||||
CDvdFile::Shutdown();
|
CDvdFile::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onCharKeyDown(uint8_t code, bool is_repeat) noexcept override {
|
void onCharKeyDown(uint8_t code, bool isRepeat) noexcept override {
|
||||||
Log.report(logvisor::Info, FMT_STRING("DEBUG CHAR KEYS: '{}', is_repeat {}"), static_cast<char>(code), is_repeat);
|
Log.report(logvisor::Info, FMT_STRING("DEBUG CHAR KEYS: '{}', isRepeat {}"), static_cast<char>(code), isRepeat);
|
||||||
// if (!ImGuiWindowCallback::m_keyboardCaptured && g_mainMP1) {
|
// if (!ImGuiWindowCallback::m_keyboardCaptured && g_mainMP1) {
|
||||||
if (g_mainMP1) {
|
if (g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
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 {
|
void onSpecialKeyDown(aurora::SpecialKey key, bool isRepeat) noexcept override {
|
||||||
Log.report(logvisor::Info, FMT_STRING("DEBUG KEYS: SpecialKey {}, is_repeat {}"), key, is_repeat);
|
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 */
|
/* TODO: Temporarily convert the aurora enum to boo's until we refactor everything */
|
||||||
if (g_mainMP1) {
|
if (g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
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)) {
|
// 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 */
|
/* TODO: Temporarily convert the aurora enum to boo's until we refactor everything */
|
||||||
if (g_mainMP1) {
|
if (g_mainMP1) {
|
||||||
if (MP1::CGameArchitectureSupport* as = g_mainMP1->GetArchSupport()) {
|
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_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
set(RUNTIME_LIBRARIES ${HECL_APPLICATION_REPS_TARGETS_LIST} RetroDataSpec AssetNameMapNull NESEmulator
|
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})
|
add_runtime_common_library(RuntimeCommon ${RUNTIME_SOURCES_A})
|
||||||
target_include_directories(RuntimeCommon PUBLIC ${RUNTIME_INCLUDES})
|
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
|
/* used in the original to look up fixed-point dividends on a
|
||||||
* MIDI-style volume scale (0-127) -> (n/0x8000) */
|
* 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,
|
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,
|
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,
|
0x055D, 0x05C9, 0x0638, 0x06AC, 0x0724, 0x07A0, 0x0820, 0x08A4, 0x092C, 0x09B8, 0x0A48, 0x0ADD, 0x0B75,
|
||||||
|
|
|
@ -6,16 +6,61 @@ namespace metaforce {
|
||||||
|
|
||||||
CFinalInput::CFinalInput() = default;
|
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)
|
float leftDiv, float rightDiv)
|
||||||
: x0_dt(dt)
|
: x0_dt(dt)
|
||||||
, x4_controllerIdx(cIdx)
|
, x4_controllerIdx(cIdx)
|
||||||
, x8_anaLeftX(zeus::clamp(-1.0f, data.m_leftStick[0] / 72.0f / leftDiv, 1.0f))
|
, 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_leftStick[1] / 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_rightStick[0] / 59.0f / rightDiv, 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_rightStick[1] / 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_analogTriggers[0] * 0.007f)
|
, x18_anaLeftTrigger(data.m_axes[size_t(aurora::ControllerAxis::TriggerLeft)] * 0.007f)
|
||||||
, x1c_anaRightTrigger(data.m_analogTriggers[1] * 0.007f)
|
, x1c_anaRightTrigger(data.m_axes[size_t(aurora::ControllerAxis::TriggerRight)] * 0.007f)
|
||||||
, x20_enableAnaLeftXP(DLARight() && !prevInput.DLARight())
|
, x20_enableAnaLeftXP(DLARight() && !prevInput.DLARight())
|
||||||
, x20_enableAnaLeftNegXP(DLALeft() && !prevInput.DLALeft())
|
, x20_enableAnaLeftNegXP(DLALeft() && !prevInput.DLALeft())
|
||||||
, x21_enableAnaLeftYP(DLAUp() && !prevInput.DLAUp())
|
, x21_enableAnaLeftYP(DLAUp() && !prevInput.DLAUp())
|
||||||
|
@ -26,18 +71,18 @@ CFinalInput::CFinalInput(int cIdx, float dt, const boo::DolphinControllerState&
|
||||||
, x23_enableAnaRightNegYP(DRADown() && !prevInput.DRADown())
|
, x23_enableAnaRightNegYP(DRADown() && !prevInput.DRADown())
|
||||||
, x24_anaLeftTriggerP(DLTrigger() && !prevInput.DLTrigger())
|
, x24_anaLeftTriggerP(DLTrigger() && !prevInput.DLTrigger())
|
||||||
, x28_anaRightTriggerP(DRTrigger() && !prevInput.DRTrigger())
|
, x28_anaRightTriggerP(DRTrigger() && !prevInput.DRTrigger())
|
||||||
, x2c_b24_A(data.m_btns & uint16_t(boo::EDolphinControllerButtons::A))
|
, x2c_b24_A(data.m_btns[size_t(aurora::ControllerButton::A)])
|
||||||
, x2c_b25_B(data.m_btns & uint16_t(boo::EDolphinControllerButtons::B))
|
, x2c_b25_B(data.m_btns[size_t(aurora::ControllerButton::B)])
|
||||||
, x2c_b26_X(data.m_btns & uint16_t(boo::EDolphinControllerButtons::X))
|
, x2c_b26_X(data.m_btns[size_t(aurora::ControllerButton::X)])
|
||||||
, x2c_b27_Y(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Y))
|
, x2c_b27_Y(data.m_btns[size_t(aurora::ControllerButton::Y)])
|
||||||
, x2c_b28_Z(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Z))
|
, x2c_b28_Z(data.m_btns[size_t(aurora::ControllerButton::RightShoulder)])
|
||||||
, x2c_b29_L(data.m_btns & uint16_t(boo::EDolphinControllerButtons::L))
|
, x2c_b29_L(data.m_axes[size_t(aurora::ControllerAxis::TriggerLeft)] > 29490)
|
||||||
, x2c_b30_R(data.m_btns & uint16_t(boo::EDolphinControllerButtons::R))
|
, x2c_b30_R(data.m_axes[size_t(aurora::ControllerAxis::TriggerRight)] > 29490)
|
||||||
, x2c_b31_DPUp(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Up))
|
, x2c_b31_DPUp(data.m_btns[size_t(aurora::ControllerButton::DPadUp)])
|
||||||
, x2d_b24_DPRight(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Right))
|
, x2d_b24_DPRight(data.m_btns[size_t(aurora::ControllerButton::DPadRight)])
|
||||||
, x2d_b25_DPDown(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Down))
|
, x2d_b25_DPDown(data.m_btns[size_t(aurora::ControllerButton::DPadDown)])
|
||||||
, x2d_b26_DPLeft(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Left))
|
, x2d_b26_DPLeft(data.m_btns[size_t(aurora::ControllerButton::DPadLeft)])
|
||||||
, x2d_b27_Start(data.m_btns & uint16_t(boo::EDolphinControllerButtons::Start))
|
, x2d_b27_Start(data.m_btns[size_t(aurora::ControllerButton::Start)])
|
||||||
, x2d_b28_PA(DA() && !prevInput.DA())
|
, x2d_b28_PA(DA() && !prevInput.DA())
|
||||||
, x2d_b29_PB(DB() && !prevInput.DB())
|
, x2d_b29_PB(DB() && !prevInput.DB())
|
||||||
, x2d_b30_PX(DX() && !prevInput.DX())
|
, x2d_b30_PX(DX() && !prevInput.DX())
|
||||||
|
|
|
@ -2,13 +2,20 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "Runtime/RetroTypes.hpp"
|
|
||||||
#include "Runtime/Input/CKeyboardMouseController.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 {
|
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 {
|
struct CFinalInput {
|
||||||
float x0_dt = 0.0f;
|
float x0_dt = 0.0f;
|
||||||
u32 x4_controllerIdx = 0;
|
u32 x4_controllerIdx = 0;
|
||||||
|
@ -72,7 +79,9 @@ struct CFinalInput {
|
||||||
float m_rightMul = 1.f;
|
float m_rightMul = 1.f;
|
||||||
|
|
||||||
CFinalInput();
|
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);
|
float rightDiv);
|
||||||
CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& data, const CFinalInput& prevInput);
|
CFinalInput(int cIdx, float dt, const CKeyboardMouseControllerData& data, const CFinalInput& prevInput);
|
||||||
|
|
||||||
|
|
|
@ -11,33 +11,31 @@ void CInputGenerator::Update(float dt, CArchitectureQueue& queue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keyboard/Mouse first */
|
const CFinalInput& kbInput = getFinalInput(0, dt);
|
||||||
CFinalInput kbInput = getFinalInput(0, dt);
|
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, kbInput));
|
||||||
bool kbUsed = false;
|
|
||||||
|
|
||||||
/* Dolphin controllers next */
|
/* Dolphin controllers next */
|
||||||
for (int i = 0; i < 4; ++i) {
|
// for (int i = 0; i < 4; ++i) {
|
||||||
bool connected;
|
// bool connected;
|
||||||
EStatusChange change = m_dolphinCb.getStatusChange(i, connected);
|
// EStatusChange change = m_dolphinCb.getStatusChange(i, connected);
|
||||||
if (change != EStatusChange::NoChange)
|
// if (change != EStatusChange::NoChange)
|
||||||
queue.Push(MakeMsg::CreateControllerStatus(EArchMsgTarget::Game, i, connected));
|
// queue.Push(MakeMsg::CreateControllerStatus(EArchMsgTarget::Game, i, connected));
|
||||||
if (connected) {
|
// if (connected) {
|
||||||
CFinalInput input = m_dolphinCb.getFinalInput(i, dt, m_leftDiv, m_rightDiv);
|
// CFinalInput input = m_dolphinCb.getFinalInput(i, dt, m_leftDiv, m_rightDiv);
|
||||||
if (i == 0) /* Merge KB input with first controller */
|
// if (i == 0) /* Merge KB input with first controller */
|
||||||
{
|
// {
|
||||||
input |= kbInput;
|
// input |= kbInput;
|
||||||
kbUsed = true;
|
// kbUsed = true;
|
||||||
}
|
// }
|
||||||
m_lastUpdate = input;
|
// m_lastUpdate = input;
|
||||||
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, input));
|
// queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, input));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/* Send straight keyboard input if no first controller present */
|
// /* Send straight keyboard input if no first controller present */
|
||||||
if (!kbUsed) {
|
// if (!kbUsed) {
|
||||||
m_lastUpdate = kbInput;
|
// m_lastUpdate = kbInput;
|
||||||
queue.Push(MakeMsg::CreateUserInput(EArchMsgTarget::Game, kbInput));
|
// }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -16,7 +16,7 @@ enum class EIOPort { Zero, One, Two, Three };
|
||||||
|
|
||||||
enum class EMotorState { Stop, Rumble, StopHard };
|
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 };
|
enum class EStatusChange { NoChange = 0, Connected = 1, Disconnected = 2 };
|
||||||
|
|
||||||
/* When the sticks are used as logical (digital) input,
|
/* When the sticks are used as logical (digital) input,
|
||||||
|
@ -25,10 +25,14 @@ class CInputGenerator : public boo::DeviceFinder {
|
||||||
float m_leftDiv;
|
float m_leftDiv;
|
||||||
float m_rightDiv;
|
float m_rightDiv;
|
||||||
CKeyboardMouseControllerData m_data;
|
CKeyboardMouseControllerData m_data;
|
||||||
|
SAuroraControllerState m_state;
|
||||||
|
|
||||||
CFinalInput m_lastUpdate;
|
CFinalInput m_lastUpdate;
|
||||||
const CFinalInput& getFinalInput(unsigned idx, float dt) {
|
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;
|
return m_lastUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,13 +40,22 @@ class CInputGenerator : public boo::DeviceFinder {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CInputGenerator(float leftDiv, float rightDiv)
|
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 {
|
// ~CInputGenerator() override {
|
||||||
if (smashAdapter) {
|
// if (smashAdapter) {
|
||||||
smashAdapter->setCallback(nullptr);
|
// smashAdapter->setCallback(nullptr);
|
||||||
smashAdapter->closeDevice();
|
// 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
|
/* Keyboard and mouse events are delivered on the main game
|
||||||
|
@ -79,103 +92,77 @@ public:
|
||||||
|
|
||||||
void reset() { m_data.m_accumScroll.zeroOut(); }
|
void reset() { m_data.m_accumScroll.zeroOut(); }
|
||||||
|
|
||||||
/* Input via the smash adapter is received asynchronously on a USB
|
// /* Input via the smash adapter is received asynchronously on a USB
|
||||||
* report thread. This class atomically exchanges that data to the
|
// * report thread. This class atomically exchanges that data to the
|
||||||
* game thread as needed */
|
// * game thread as needed */
|
||||||
struct DolphinSmashAdapterCallback : boo::IDolphinSmashAdapterCallback {
|
// struct DolphinSmashAdapterCallback : boo::IDolphinSmashAdapterCallback {
|
||||||
std::array<std::atomic<EStatusChange>, 4> m_statusChanges;
|
// std::array<std::atomic<EStatusChange>, 4> m_statusChanges;
|
||||||
std::array<bool, 4> m_connected{};
|
// std::array<bool, 4> m_connected{};
|
||||||
std::array<boo::DolphinControllerState, 4> m_states;
|
// std::array<boo::DolphinControllerState, 4> m_states;
|
||||||
std::mutex m_stateLock;
|
// std::mutex m_stateLock;
|
||||||
void controllerConnected(unsigned idx, boo::EDolphinControllerType) override {
|
// void controllerConnected(unsigned idx, boo::EDolphinControllerType) override {
|
||||||
/* Controller thread */
|
// /* Controller thread */
|
||||||
m_statusChanges[idx].store(EStatusChange::Connected);
|
// m_statusChanges[idx].store(EStatusChange::Connected);
|
||||||
}
|
// }
|
||||||
void controllerDisconnected(unsigned idx) override {
|
// void controllerDisconnected(unsigned idx) override {
|
||||||
/* Controller thread */
|
// /* Controller thread */
|
||||||
std::unique_lock lk{m_stateLock};
|
// std::unique_lock lk{m_stateLock};
|
||||||
m_statusChanges[idx].store(EStatusChange::Disconnected);
|
// m_statusChanges[idx].store(EStatusChange::Disconnected);
|
||||||
m_states[idx].reset();
|
// m_states[idx].reset();
|
||||||
}
|
// }
|
||||||
void controllerUpdate(unsigned idx, boo::EDolphinControllerType,
|
// void controllerUpdate(unsigned idx, boo::EDolphinControllerType,
|
||||||
const boo::DolphinControllerState& state) override {
|
// const boo::DolphinControllerState& state) override {
|
||||||
/* Controller thread */
|
// /* Controller thread */
|
||||||
std::unique_lock lk{m_stateLock};
|
// std::unique_lock lk{m_stateLock};
|
||||||
m_states[idx] = state;
|
// 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;
|
// /* Device connection/disconnection events are handled on a separate thread
|
||||||
const CFinalInput& getFinalInput(unsigned idx, float dt, float leftDiv, float rightDiv) {
|
// * using the relevant OS API. This thread blocks in a loop until an event is
|
||||||
/* Game thread */
|
// * received. Device pointers should only be manipulated by this thread using
|
||||||
std::unique_lock lk{m_stateLock};
|
// * the deviceConnected() and deviceDisconnected() callbacks. */
|
||||||
boo::DolphinControllerState state = m_states[idx];
|
// std::shared_ptr<boo::DolphinSmashAdapter> smashAdapter;
|
||||||
lk.unlock();
|
// void deviceConnected(boo::DeviceToken& tok) override {
|
||||||
state.clamp(); /* PADClamp equivalent */
|
// /* Device listener thread */
|
||||||
m_lastUpdates[idx] = CFinalInput(idx, dt, state, m_lastUpdates[idx], leftDiv, rightDiv);
|
// if (!smashAdapter) {
|
||||||
return m_lastUpdates[idx];
|
// auto dev = tok.openAndGetDevice();
|
||||||
}
|
// if (dev && dev->getTypeHash() == dev_typeid(DolphinSmashAdapter)) {
|
||||||
EStatusChange getStatusChange(unsigned idx, bool& connected) {
|
// smashAdapter = std::static_pointer_cast<boo::DolphinSmashAdapter>(tok.openAndGetDevice());
|
||||||
/* Game thread */
|
// smashAdapter->setCallback(&m_dolphinCb);
|
||||||
EStatusChange ch = m_statusChanges[idx].exchange(EStatusChange::NoChange);
|
// }
|
||||||
if (ch == EStatusChange::Connected)
|
// }
|
||||||
m_connected[idx] = true;
|
// }
|
||||||
else if (ch == EStatusChange::Disconnected)
|
// void deviceDisconnected(boo::DeviceToken&, boo::DeviceBase* device) override {
|
||||||
m_connected[idx] = false;
|
// if (smashAdapter.get() == device)
|
||||||
connected = m_connected[idx];
|
// smashAdapter.reset();
|
||||||
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();
|
|
||||||
}
|
|
||||||
void SetMotorState(EIOPort port, EMotorState state) {
|
void SetMotorState(EIOPort port, EMotorState state) {
|
||||||
if (smashAdapter) {
|
// TODO aurora
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void ControlAllMotors(const std::array<EMotorState, 4>& states) {
|
void ControlAllMotors(const std::array<EMotorState, 4>& states) {
|
||||||
if (smashAdapter) {
|
// TODO aurora
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is where the game thread enters */
|
/* 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) {
|
, x44_guiSys(*g_ResFactory, *g_SimplePool, CGuiSys::EUsageMode::Zero) {
|
||||||
auto* m = static_cast<CMain*>(g_Main);
|
auto* m = static_cast<CMain*>(g_Main);
|
||||||
|
|
||||||
x30_inputGenerator.startScanning();
|
// x30_inputGenerator.startScanning();
|
||||||
g_InputGenerator = &x30_inputGenerator;
|
g_InputGenerator = &x30_inputGenerator;
|
||||||
|
|
||||||
CAudioSys::SysSetVolume(0x7f);
|
CAudioSys::SysSetVolume(0x7f);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 53091e36a3b418e33133bae2f018954c006f86b8
|
Loading…
Reference in New Issue