mirror of https://github.com/AxioDL/metaforce.git
Automatically remap controllers; separate cxxbridge build files
This commit is contained in:
parent
ed4d38073b
commit
8286f006cf
|
@ -31,24 +31,24 @@ fn main() {
|
|||
let cxx_flag = "-std=c++17";
|
||||
#[cfg(all(unix, not(any(target_os = "macos", target_os = "ios"))))]
|
||||
let cxx_flag = "-std=gnu++17";
|
||||
cxx_build::bridge("src/lib.rs")
|
||||
cxx_build::bridge("src/cxxbridge.rs")
|
||||
.include("include")
|
||||
.include(zeus_include.clone())
|
||||
.flag(cxx_flag)
|
||||
.compile("aurora");
|
||||
println!("cargo:rerun-if-changed=src/lib.rs");
|
||||
cxx_build::bridge("src/shaders/mod.rs")
|
||||
println!("cargo:rerun-if-changed=src/cxxbridge.rs");
|
||||
cxx_build::bridge("src/shaders/cxxbridge.rs")
|
||||
.include("include")
|
||||
.include(zeus_include.clone())
|
||||
.flag(cxx_flag)
|
||||
.compile("aurora_shaders");
|
||||
println!("cargo:rerun-if-changed=src/shaders/mod.rs");
|
||||
cxx_build::bridge("src/imgui.rs")
|
||||
println!("cargo:rerun-if-changed=src/shaders/cxxbridge.rs");
|
||||
cxx_build::bridge("src/imgui/cxxbridge.rs")
|
||||
.include("include")
|
||||
.include(zeus_include.clone())
|
||||
.include(imgui_include.clone())
|
||||
.include(imgui_engine_include.clone())
|
||||
.flag(cxx_flag)
|
||||
.compile("aurora_imgui");
|
||||
println!("cargo:rerun-if-changed=src/imgui.rs");
|
||||
println!("cargo:rerun-if-changed=src/imgui/cxxbridge.rs");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
use sdl2::controller::{Axis, Button};
|
||||
|
||||
use crate::{
|
||||
app_run, get_args, get_backend, get_backend_string, get_dxt_compression_supported,
|
||||
get_window_size,
|
||||
sdl::{get_controller_player_index, set_controller_player_index},
|
||||
set_fullscreen, set_window_title, App, WindowContext,
|
||||
};
|
||||
|
||||
#[cxx::bridge(namespace = "aurora")]
|
||||
pub(crate) mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("aurora.hpp");
|
||||
pub(crate) type AppDelegate;
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("lib.hpp");
|
||||
pub(crate) fn App_onAppLaunched(cb: Pin<&mut AppDelegate>);
|
||||
pub(crate) fn App_onAppIdle(cb: Pin<&mut AppDelegate>, dt: f32) -> bool;
|
||||
pub(crate) fn App_onAppDraw(cb: Pin<&mut AppDelegate>);
|
||||
pub(crate) fn App_onAppPostDraw(cb: Pin<&mut AppDelegate>);
|
||||
pub(crate) fn App_onAppWindowResized(cb: Pin<&mut AppDelegate>, size: &WindowSize);
|
||||
pub(crate) fn App_onAppWindowMoved(cb: Pin<&mut AppDelegate>, x: i32, y: i32);
|
||||
pub(crate) fn App_onAppExiting(cb: Pin<&mut AppDelegate>);
|
||||
// Input
|
||||
pub(crate) fn App_onCharKeyDown(cb: Pin<&mut AppDelegate>, code: u8, is_repeat: bool);
|
||||
pub(crate) fn App_onCharKeyUp(cb: Pin<&mut AppDelegate>, code: u8);
|
||||
pub(crate) fn App_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 {
|
||||
pub(crate) inner: Box<WindowContext>,
|
||||
}
|
||||
|
||||
pub struct WindowSize {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Backend {
|
||||
Invalid,
|
||||
Vulkan,
|
||||
Metal,
|
||||
D3D12,
|
||||
D3D11,
|
||||
OpenGL,
|
||||
WebGPU,
|
||||
}
|
||||
|
||||
pub enum ElementState {
|
||||
Pressed,
|
||||
Released,
|
||||
}
|
||||
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Other,
|
||||
}
|
||||
|
||||
pub enum SpecialKey {
|
||||
None = 0,
|
||||
F1 = 1,
|
||||
F2 = 2,
|
||||
F3 = 3,
|
||||
F4 = 4,
|
||||
F5 = 5,
|
||||
F6 = 6,
|
||||
F7 = 7,
|
||||
F8 = 8,
|
||||
F9 = 9,
|
||||
F10 = 10,
|
||||
F11 = 11,
|
||||
F12 = 12,
|
||||
Esc = 13,
|
||||
Enter = 14,
|
||||
Backspace = 15,
|
||||
Insert = 16,
|
||||
Delete = 17,
|
||||
Home = 18,
|
||||
End = 19,
|
||||
PgUp = 20,
|
||||
PgDown = 21,
|
||||
Left = 22,
|
||||
Right = 23,
|
||||
Up = 24,
|
||||
Down = 25,
|
||||
Tab = 26,
|
||||
}
|
||||
|
||||
pub struct KeyboardInput {
|
||||
pub scancode: u32,
|
||||
pub state: ElementState,
|
||||
// pub
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
pub struct Icon {
|
||||
pub data: Vec<u8>,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
type WindowContext;
|
||||
type App;
|
||||
fn app_run(mut delegate: UniquePtr<AppDelegate>, icon: Icon);
|
||||
fn get_args() -> Vec<String>;
|
||||
fn get_window_size() -> WindowSize;
|
||||
fn set_window_title(title: &CxxString);
|
||||
fn get_dxt_compression_supported() -> bool;
|
||||
fn get_backend() -> Backend;
|
||||
fn get_backend_string() -> &'static str;
|
||||
fn set_fullscreen(v: bool);
|
||||
fn get_controller_player_index(which: u32) -> i32;
|
||||
fn set_controller_player_index(which: u32, index: i32);
|
||||
}
|
||||
}
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
use crate::{
|
||||
gpu::DeviceHolder,
|
||||
imgui::{ImGuiEngine_AddTexture, ImGuiState},
|
||||
};
|
||||
|
||||
#[cxx::bridge(namespace = "metaforce")]
|
||||
pub(crate) mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("ImGuiEngine.hpp");
|
||||
pub(crate) fn ImGuiEngine_Initialize(scale: f32);
|
||||
pub(crate) fn ImGuiEngine_AddTextures(state: &mut ImGuiState, device: &DeviceHolder);
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
type ImGuiState;
|
||||
type DeviceHolder;
|
||||
fn ImGuiEngine_AddTexture(
|
||||
state: &mut ImGuiState,
|
||||
device: &DeviceHolder,
|
||||
width: u32,
|
||||
height: u32,
|
||||
data: &[u8],
|
||||
) -> usize;
|
||||
}
|
||||
}
|
|
@ -1,25 +1,8 @@
|
|||
use cxxbridge::ffi;
|
||||
|
||||
use crate::{gpu::DeviceHolder, imgui_backend};
|
||||
|
||||
#[cxx::bridge(namespace = "metaforce")]
|
||||
mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("ImGuiEngine.hpp");
|
||||
pub(crate) fn ImGuiEngine_Initialize(scale: f32);
|
||||
pub(crate) fn ImGuiEngine_AddTextures(state: &mut ImGuiState, device: &DeviceHolder);
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
type ImGuiState;
|
||||
type DeviceHolder;
|
||||
fn ImGuiEngine_AddTexture(
|
||||
state: &mut ImGuiState,
|
||||
device: &DeviceHolder,
|
||||
width: u32,
|
||||
height: u32,
|
||||
data: &[u8],
|
||||
) -> usize;
|
||||
}
|
||||
}
|
||||
mod cxxbridge;
|
||||
|
||||
pub struct ImGuiState {
|
||||
pub(crate) context: imgui::Context,
|
|
@ -3,8 +3,12 @@
|
|||
#![allow(unused_variables)]
|
||||
#![allow(unused_unsafe)]
|
||||
|
||||
use std::{collections::HashMap, time::Instant};
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use cxxbridge::ffi;
|
||||
use sdl2::{
|
||||
controller::{Axis, Button, GameController},
|
||||
event::Event as SDLEvent,
|
||||
|
@ -17,220 +21,29 @@ use winit::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
ffi::{SpecialKey, WindowSize},
|
||||
gpu::{create_depth_texture, create_render_texture, initialize_gpu, DeviceHolder},
|
||||
imgui::{initialize_imgui, ImGuiState},
|
||||
sdl::{
|
||||
get_controller_player_index, initialize_sdl, poll_sdl_events, remap_controller_layout,
|
||||
set_controller_player_index, SdlState,
|
||||
},
|
||||
shaders::render_into_pass,
|
||||
};
|
||||
|
||||
mod cxxbridge;
|
||||
mod gpu;
|
||||
mod imgui;
|
||||
mod imgui_backend;
|
||||
mod sdl;
|
||||
mod shaders;
|
||||
mod util;
|
||||
mod zeus;
|
||||
|
||||
#[cxx::bridge(namespace = "aurora")]
|
||||
mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("aurora.hpp");
|
||||
pub(crate) type AppDelegate;
|
||||
}
|
||||
|
||||
unsafe extern "C++" {
|
||||
include!("lib.hpp");
|
||||
pub(crate) fn App_onAppLaunched(cb: Pin<&mut AppDelegate>);
|
||||
pub(crate) fn App_onAppIdle(cb: Pin<&mut AppDelegate>, dt: f32) -> bool;
|
||||
pub(crate) fn App_onAppDraw(cb: Pin<&mut AppDelegate>);
|
||||
pub(crate) fn App_onAppPostDraw(cb: Pin<&mut AppDelegate>);
|
||||
pub(crate) fn App_onAppWindowResized(cb: Pin<&mut AppDelegate>, size: &WindowSize);
|
||||
pub(crate) fn App_onAppWindowMoved(cb: Pin<&mut AppDelegate>, x: i32, y: i32);
|
||||
pub(crate) fn App_onAppExiting(cb: Pin<&mut AppDelegate>);
|
||||
// Input
|
||||
pub(crate) fn App_onCharKeyDown(cb: Pin<&mut AppDelegate>, code: u8, is_repeat: bool);
|
||||
pub(crate) fn App_onCharKeyUp(cb: Pin<&mut AppDelegate>, code: u8);
|
||||
pub(crate) fn App_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 {
|
||||
pub(crate) inner: Box<WindowContext>,
|
||||
}
|
||||
|
||||
pub struct WindowSize {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Backend {
|
||||
Invalid,
|
||||
Vulkan,
|
||||
Metal,
|
||||
D3D12,
|
||||
D3D11,
|
||||
OpenGL,
|
||||
WebGPU,
|
||||
}
|
||||
|
||||
pub enum ElementState {
|
||||
Pressed,
|
||||
Released,
|
||||
}
|
||||
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
Right,
|
||||
Middle,
|
||||
Other,
|
||||
}
|
||||
|
||||
pub enum SpecialKey {
|
||||
None = 0,
|
||||
F1 = 1,
|
||||
F2 = 2,
|
||||
F3 = 3,
|
||||
F4 = 4,
|
||||
F5 = 5,
|
||||
F6 = 6,
|
||||
F7 = 7,
|
||||
F8 = 8,
|
||||
F9 = 9,
|
||||
F10 = 10,
|
||||
F11 = 11,
|
||||
F12 = 12,
|
||||
Esc = 13,
|
||||
Enter = 14,
|
||||
Backspace = 15,
|
||||
Insert = 16,
|
||||
Delete = 17,
|
||||
Home = 18,
|
||||
End = 19,
|
||||
PgUp = 20,
|
||||
PgDown = 21,
|
||||
Left = 22,
|
||||
Right = 23,
|
||||
Up = 24,
|
||||
Down = 25,
|
||||
Tab = 26,
|
||||
}
|
||||
|
||||
pub struct KeyboardInput {
|
||||
pub scancode: u32,
|
||||
pub state: ElementState,
|
||||
// pub
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
pub struct Icon {
|
||||
pub data: Vec<u8>,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
type WindowContext;
|
||||
type App;
|
||||
fn app_run(mut delegate: UniquePtr<AppDelegate>, icon: Icon);
|
||||
fn get_args() -> Vec<String>;
|
||||
fn get_window_size() -> WindowSize;
|
||||
fn set_window_title(title: &CxxString);
|
||||
fn get_dxt_compression_supported() -> bool;
|
||||
fn get_backend() -> Backend;
|
||||
fn get_backend_string() -> &'static str;
|
||||
fn set_fullscreen(v: bool);
|
||||
fn get_controller_player_index(which: u32) -> i32;
|
||||
fn set_controller_player_index(which: u32, index: i32);
|
||||
}
|
||||
}
|
||||
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>,
|
||||
sdl: SdlState,
|
||||
}
|
||||
|
||||
pub struct WindowContext {
|
||||
|
@ -246,29 +59,21 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
|
|||
env_logger::init();
|
||||
log::info!("Running app");
|
||||
let event_loop = winit::event_loop::EventLoop::new();
|
||||
let window_icon = winit::window::Icon::from_rgba(icon.data, icon.width, icon.height).expect("Failed to load icon");
|
||||
let window_icon = winit::window::Icon::from_rgba(icon.data, icon.width, icon.height)
|
||||
.expect("Failed to load icon");
|
||||
let window = winit::window::WindowBuilder::new()
|
||||
.with_inner_size(winit::dpi::LogicalSize::new(1280, 720))
|
||||
.with_window_icon(Some(window_icon))
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
let sdl = sdl2::init().unwrap();
|
||||
let sdl_events = sdl.event_pump().unwrap();
|
||||
let controller = sdl.game_controller().unwrap();
|
||||
let sdl = initialize_sdl();
|
||||
let gpu = initialize_gpu(&window);
|
||||
let imgui = initialize_imgui(&window, &gpu);
|
||||
let mut special_keys_pressed: [bool; 512] = [false; 512];
|
||||
shaders::construct_state(gpu.device.clone(), gpu.queue.clone(), &gpu.config);
|
||||
let app = App {
|
||||
window: ffi::Window { inner: Box::new(WindowContext { window }) },
|
||||
gpu,
|
||||
imgui,
|
||||
sdl,
|
||||
sdl_events,
|
||||
sdl_controller_sys: controller,
|
||||
sdl_open_controllers: Default::default(),
|
||||
};
|
||||
let window_size = WindowSize {
|
||||
let app =
|
||||
App { window: ffi::Window { inner: Box::new(WindowContext { window }) }, gpu, imgui, sdl };
|
||||
let window_size = ffi::WindowSize {
|
||||
width: app.gpu.surface_config.width,
|
||||
height: app.gpu.surface_config.height,
|
||||
};
|
||||
|
@ -290,57 +95,10 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
|
|||
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 { .. } => {
|
||||
if !poll_sdl_events(&mut app.sdl, &mut delegate) {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// winit event loop
|
||||
*control_flow = ControlFlow::Poll;
|
||||
|
@ -361,7 +119,7 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
|
|||
&app.gpu.surface_config,
|
||||
&app.gpu.config,
|
||||
);
|
||||
let window_size = WindowSize {
|
||||
let window_size = ffi::WindowSize {
|
||||
width: app.gpu.surface_config.width,
|
||||
height: app.gpu.surface_config.height,
|
||||
};
|
||||
|
@ -382,35 +140,35 @@ fn app_run(mut delegate: cxx::UniquePtr<ffi::AppDelegate>, icon: ffi::Icon) {
|
|||
} => {
|
||||
// TODO: Handle normal keys, this will require a refactor in game runtime code
|
||||
let special_key = match key {
|
||||
VirtualKeyCode::F1 => SpecialKey::F1,
|
||||
VirtualKeyCode::F2 => SpecialKey::F2,
|
||||
VirtualKeyCode::F3 => SpecialKey::F3,
|
||||
VirtualKeyCode::F4 => SpecialKey::F4,
|
||||
VirtualKeyCode::F5 => SpecialKey::F5,
|
||||
VirtualKeyCode::F6 => SpecialKey::F6,
|
||||
VirtualKeyCode::F7 => SpecialKey::F7,
|
||||
VirtualKeyCode::F8 => SpecialKey::F8,
|
||||
VirtualKeyCode::F9 => SpecialKey::F9,
|
||||
VirtualKeyCode::F10 => SpecialKey::F10,
|
||||
VirtualKeyCode::F11 => SpecialKey::F11,
|
||||
VirtualKeyCode::F12 => SpecialKey::F12,
|
||||
VirtualKeyCode::Escape => SpecialKey::Esc,
|
||||
VirtualKeyCode::Return => SpecialKey::Enter,
|
||||
VirtualKeyCode::Back => SpecialKey::Backspace,
|
||||
VirtualKeyCode::Insert => SpecialKey::Insert,
|
||||
VirtualKeyCode::Delete => SpecialKey::Delete,
|
||||
VirtualKeyCode::Home => SpecialKey::Home,
|
||||
VirtualKeyCode::PageUp => SpecialKey::PgUp,
|
||||
VirtualKeyCode::PageDown => SpecialKey::PgDown,
|
||||
VirtualKeyCode::Left => SpecialKey::Left,
|
||||
VirtualKeyCode::Right => SpecialKey::Right,
|
||||
VirtualKeyCode::Up => SpecialKey::Up,
|
||||
VirtualKeyCode::Down => SpecialKey::Down,
|
||||
VirtualKeyCode::Tab => SpecialKey::Tab,
|
||||
_ => SpecialKey::None,
|
||||
VirtualKeyCode::F1 => ffi::SpecialKey::F1,
|
||||
VirtualKeyCode::F2 => ffi::SpecialKey::F2,
|
||||
VirtualKeyCode::F3 => ffi::SpecialKey::F3,
|
||||
VirtualKeyCode::F4 => ffi::SpecialKey::F4,
|
||||
VirtualKeyCode::F5 => ffi::SpecialKey::F5,
|
||||
VirtualKeyCode::F6 => ffi::SpecialKey::F6,
|
||||
VirtualKeyCode::F7 => ffi::SpecialKey::F7,
|
||||
VirtualKeyCode::F8 => ffi::SpecialKey::F8,
|
||||
VirtualKeyCode::F9 => ffi::SpecialKey::F9,
|
||||
VirtualKeyCode::F10 => ffi::SpecialKey::F10,
|
||||
VirtualKeyCode::F11 => ffi::SpecialKey::F11,
|
||||
VirtualKeyCode::F12 => ffi::SpecialKey::F12,
|
||||
VirtualKeyCode::Escape => ffi::SpecialKey::Esc,
|
||||
VirtualKeyCode::Return => ffi::SpecialKey::Enter,
|
||||
VirtualKeyCode::Back => ffi::SpecialKey::Backspace,
|
||||
VirtualKeyCode::Insert => ffi::SpecialKey::Insert,
|
||||
VirtualKeyCode::Delete => ffi::SpecialKey::Delete,
|
||||
VirtualKeyCode::Home => ffi::SpecialKey::Home,
|
||||
VirtualKeyCode::PageUp => ffi::SpecialKey::PgUp,
|
||||
VirtualKeyCode::PageDown => ffi::SpecialKey::PgDown,
|
||||
VirtualKeyCode::Left => ffi::SpecialKey::Left,
|
||||
VirtualKeyCode::Right => ffi::SpecialKey::Right,
|
||||
VirtualKeyCode::Up => ffi::SpecialKey::Up,
|
||||
VirtualKeyCode::Down => ffi::SpecialKey::Down,
|
||||
VirtualKeyCode::Tab => ffi::SpecialKey::Tab,
|
||||
_ => ffi::SpecialKey::None,
|
||||
};
|
||||
|
||||
if special_key != SpecialKey::None {
|
||||
if special_key != ffi::SpecialKey::None {
|
||||
let pressed = state == ElementState::Pressed;
|
||||
let repeat = special_keys_pressed[key as usize] == pressed;
|
||||
special_keys_pressed[key as usize] = pressed;
|
||||
|
@ -596,25 +354,3 @@ fn set_fullscreen(v: bool) {
|
|||
None
|
||||
});
|
||||
}
|
||||
|
||||
fn get_controller_player_index(which: u32) -> i32 {
|
||||
let mut result: i32 = -1;
|
||||
for (key, value) in &get_app().sdl_open_controllers {
|
||||
if value.instance_id() == which {
|
||||
result = value.player_index();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result as i32
|
||||
}
|
||||
|
||||
fn set_controller_player_index(which: u32, index: i32) {
|
||||
|
||||
for (key, value) in &get_app().sdl_open_controllers {
|
||||
if value.instance_id() == which {
|
||||
value.set_player_index(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
use sdl2::{
|
||||
controller::{Axis, GameController},
|
||||
event::Event,
|
||||
GameControllerSubsystem, Sdl,
|
||||
};
|
||||
|
||||
use crate::{cxxbridge::ffi, get_app};
|
||||
|
||||
pub(crate) struct SdlState {
|
||||
context: Sdl,
|
||||
events: sdl2::EventPump,
|
||||
controller_sys: GameControllerSubsystem,
|
||||
open_controllers: HashMap<u32, GameController>,
|
||||
}
|
||||
|
||||
pub(crate) fn initialize_sdl() -> SdlState {
|
||||
let context = sdl2::init().unwrap();
|
||||
let events = context.event_pump().unwrap();
|
||||
let controller_sys = context.game_controller().unwrap();
|
||||
SdlState { context, events, controller_sys, open_controllers: Default::default() }
|
||||
}
|
||||
|
||||
pub(crate) fn poll_sdl_events(
|
||||
state: &mut SdlState,
|
||||
delegate: &mut cxx::UniquePtr<ffi::AppDelegate>,
|
||||
) -> bool {
|
||||
for event in state.events.poll_iter() {
|
||||
match event {
|
||||
Event::ControllerDeviceAdded { which, .. } => {
|
||||
match state.controller_sys.open(which) {
|
||||
Ok(controller) => {
|
||||
log::info!("Opened SDL controller \"{}\"", controller.name());
|
||||
if let Some(new_mapping) = remap_controller_layout(controller.mapping()) {
|
||||
state
|
||||
.controller_sys
|
||||
.add_mapping(new_mapping.as_str())
|
||||
.expect("Failed to overwrite mapping");
|
||||
}
|
||||
state.open_controllers.insert(controller.instance_id(), controller);
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("Failed to open SDL controller {} ({:?})", which, err);
|
||||
}
|
||||
}
|
||||
// TODO app connected event
|
||||
}
|
||||
Event::ControllerDeviceRemoved { which, .. } => {
|
||||
state.open_controllers.remove(&which);
|
||||
// TODO app disconnected event
|
||||
}
|
||||
Event::ControllerButtonDown { which, button, .. } => unsafe {
|
||||
ffi::App_onControllerButton(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
which,
|
||||
button.into(),
|
||||
true,
|
||||
);
|
||||
},
|
||||
Event::ControllerButtonUp { which, button, .. } => unsafe {
|
||||
ffi::App_onControllerButton(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
which,
|
||||
button.into(),
|
||||
false,
|
||||
);
|
||||
},
|
||||
Event::ControllerAxisMotion { which, axis, value, .. } => unsafe {
|
||||
ffi::App_onControllerAxis(
|
||||
delegate.as_mut().unwrap_unchecked(),
|
||||
which,
|
||||
axis.into(),
|
||||
value,
|
||||
);
|
||||
},
|
||||
// SDL overrides exit signals
|
||||
Event::Quit { .. } => {
|
||||
return false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fn remap_controller_layout(mapping: String) -> Option<String> {
|
||||
let mut new_mapping = String::with_capacity(mapping.len());
|
||||
let mut entries = BTreeMap::<&str, &str>::new();
|
||||
for (i, v) in mapping.split(',').enumerate() {
|
||||
if i < 2 {
|
||||
if i > 0 {
|
||||
new_mapping.push(',');
|
||||
}
|
||||
new_mapping.push_str(v);
|
||||
continue;
|
||||
}
|
||||
let split = v.splitn(2, ':').collect::<Vec<&str>>();
|
||||
if split.len() != 2 {
|
||||
panic!("Invalid mapping entry: {}", v);
|
||||
}
|
||||
entries.insert(split[0], split[1]);
|
||||
}
|
||||
if entries.contains_key("rightshoulder") && !entries.contains_key("leftshoulder") {
|
||||
log::debug!("Remapping GameCube controller layout");
|
||||
// TODO trigger buttons may differ per platform
|
||||
entries.insert("leftshoulder", "b11");
|
||||
let z_button = entries.insert("rightshoulder", "b10").unwrap();
|
||||
entries.insert("back", z_button);
|
||||
} else if entries.contains_key("leftshoulder")
|
||||
&& entries.contains_key("rightshoulder")
|
||||
&& entries.contains_key("back")
|
||||
{
|
||||
log::debug!("Controller has standard layout");
|
||||
return None;
|
||||
} else {
|
||||
log::error!("Controller has unsupported layout: {}", mapping);
|
||||
return None;
|
||||
}
|
||||
for (k, v) in entries {
|
||||
new_mapping.push(',');
|
||||
new_mapping.push_str(k);
|
||||
new_mapping.push(':');
|
||||
new_mapping.push_str(v);
|
||||
}
|
||||
return Some(new_mapping);
|
||||
}
|
||||
|
||||
pub(crate) fn get_controller_player_index(which: u32) -> i32 {
|
||||
get_app().sdl.open_controllers.get(&which).map_or(-1, |c| c.player_index())
|
||||
}
|
||||
|
||||
pub(crate) fn set_controller_player_index(which: u32, index: i32) {
|
||||
if let Some(c) = get_app().sdl.open_controllers.get(&which) {
|
||||
c.set_player_index(index);
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@ pub(crate) fn construct_state(
|
|||
device: &wgpu::Device,
|
||||
_queue: &wgpu::Queue,
|
||||
buffers: &BuiltBuffers,
|
||||
graphics_config: &GraphicsConfig,
|
||||
) -> State {
|
||||
let shader = device.create_shader_module(&include_wgsl!("shader.wgsl"));
|
||||
let uniform_size = wgpu::BufferSize::new(std::mem::size_of::<Uniform>() as u64);
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
use crate::shaders::{
|
||||
aabb::queue_aabb,
|
||||
fog_volume_filter::queue_fog_volume_filter,
|
||||
fog_volume_plane::queue_fog_volume_plane,
|
||||
model::{add_material_set, add_model},
|
||||
movie_player::queue_movie_player,
|
||||
resolve_color, resolve_depth, set_scissor, set_viewport,
|
||||
texture::{
|
||||
create_dynamic_texture_2d, create_render_texture, create_static_texture_2d, drop_texture,
|
||||
write_texture,
|
||||
},
|
||||
textured_quad::{queue_textured_quad, queue_textured_quad_verts},
|
||||
update_fog_state, update_model_view, update_projection,
|
||||
};
|
||||
|
||||
#[cxx::bridge]
|
||||
pub(crate) mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("zeus/CVector2f.hpp");
|
||||
include!("zeus/CVector3f.hpp");
|
||||
include!("zeus/CVector4f.hpp");
|
||||
include!("zeus/CMatrix4f.hpp");
|
||||
include!("zeus/CColor.hpp");
|
||||
include!("zeus/CRectangle.hpp");
|
||||
include!("zeus/CAABox.hpp");
|
||||
#[namespace = "zeus"]
|
||||
type CVector2f = crate::zeus::CVector2f;
|
||||
#[namespace = "zeus"]
|
||||
type CVector3f = crate::zeus::CVector3f;
|
||||
#[namespace = "zeus"]
|
||||
type CVector4f = crate::zeus::CVector4f;
|
||||
#[namespace = "zeus"]
|
||||
type CMatrix4f = crate::zeus::CMatrix4f;
|
||||
#[namespace = "zeus"]
|
||||
type CColor = crate::zeus::CColor;
|
||||
#[namespace = "zeus"]
|
||||
type CRectangle = crate::zeus::CRectangle;
|
||||
#[namespace = "zeus"]
|
||||
type CAABox = crate::zeus::CAABox;
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) enum CameraFilterType {
|
||||
Passthru,
|
||||
Multiply,
|
||||
Invert,
|
||||
Add,
|
||||
Subtract,
|
||||
Blend,
|
||||
Widescreen,
|
||||
SceneAdd,
|
||||
NoColor,
|
||||
InvDstMultiply,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) enum ZTest {
|
||||
Never,
|
||||
Less,
|
||||
Equal,
|
||||
LEqual,
|
||||
Greater,
|
||||
NEqual,
|
||||
GEqual,
|
||||
Always,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum TextureFormat {
|
||||
RGBA8,
|
||||
R8,
|
||||
R32Float,
|
||||
DXT1,
|
||||
DXT3,
|
||||
DXT5,
|
||||
BPTC,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum TextureClampMode {
|
||||
Repeat,
|
||||
ClampToEdge,
|
||||
ClampToWhite,
|
||||
ClampToBlack,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) struct TextureRef {
|
||||
pub(crate) id: u32,
|
||||
pub(crate) render: bool,
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub(crate) enum FogMode {
|
||||
None = 0x00,
|
||||
|
||||
PerspLin = 0x02,
|
||||
PerspExp = 0x04,
|
||||
PerspExp2 = 0x05,
|
||||
PerspRevExp = 0x06,
|
||||
PerspRevExp2 = 0x07,
|
||||
|
||||
OrthoLin = 0x0A,
|
||||
OrthoExp = 0x0C,
|
||||
OrthoExp2 = 0x0D,
|
||||
OrthoRevExp = 0x0E,
|
||||
OrthoRevExp2 = 0x0F,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) struct FogState {
|
||||
#[cxx_name = "m_color"]
|
||||
pub(crate) color: CColor,
|
||||
#[cxx_name = "m_A"]
|
||||
pub(crate) a: f32,
|
||||
#[cxx_name = "m_B"]
|
||||
pub(crate) b: f32,
|
||||
#[cxx_name = "m_C"]
|
||||
pub(crate) c: f32,
|
||||
#[cxx_name = "m_mode"]
|
||||
pub(crate) mode: FogMode,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) struct ClipRect {
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) struct MaterialPassInfo {
|
||||
tex_idx: u32,
|
||||
constant_color: CColor,
|
||||
has_constant_color: bool, // would love to use Option...
|
||||
uv_source: u8,
|
||||
uv_anim_type: u8,
|
||||
uv_anim_params: [f32; 9],
|
||||
normalize: bool, // TODO might be static based on uv type?
|
||||
sample_alpha: bool,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct MaterialInfo {
|
||||
pass_info: [MaterialPassInfo; 8],
|
||||
texture_ids: Vec<TextureRef>,
|
||||
shader_type: u8,
|
||||
blend_mode: u8,
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
extern "Rust" {
|
||||
fn update_model_view(mv: CMatrix4f, mv_inv: CMatrix4f);
|
||||
fn update_projection(proj: CMatrix4f);
|
||||
fn update_fog_state(state: FogState);
|
||||
fn set_viewport(rect: CRectangle, znear: f32, zfar: f32);
|
||||
fn set_scissor(x: u32, y: u32, w: u32, h: u32);
|
||||
|
||||
fn resolve_color(rect: ClipRect, bind: u32, clear_depth: bool);
|
||||
fn resolve_depth(rect: ClipRect, bind: u32);
|
||||
|
||||
fn add_material_set(materials: Vec<MaterialInfo>) -> u32;
|
||||
fn add_model(verts: &[u8], indices: &[u8]) -> u32;
|
||||
|
||||
fn queue_aabb(aabb: CAABox, color: CColor, z_only: bool);
|
||||
fn queue_fog_volume_plane(verts: &CxxVector<CVector4f>, pass: u8);
|
||||
fn queue_fog_volume_filter(color: CColor, two_way: bool);
|
||||
fn queue_textured_quad_verts(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_comparison: ZTest,
|
||||
z_test: bool,
|
||||
color: CColor,
|
||||
pos: &[CVector3f],
|
||||
uvs: &[CVector2f],
|
||||
lod: f32,
|
||||
);
|
||||
fn queue_textured_quad(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_comparison: ZTest,
|
||||
z_test: bool,
|
||||
color: CColor,
|
||||
uv_scale: f32,
|
||||
rect: CRectangle,
|
||||
z: f32,
|
||||
);
|
||||
fn queue_movie_player(
|
||||
tex_y: TextureRef,
|
||||
tex_u: TextureRef,
|
||||
tex_v: TextureRef,
|
||||
color: CColor,
|
||||
h_pad: f32,
|
||||
v_pad: f32,
|
||||
);
|
||||
|
||||
fn create_static_texture_2d(
|
||||
width: u32,
|
||||
height: u32,
|
||||
mips: u32,
|
||||
format: TextureFormat,
|
||||
data: &[u8],
|
||||
label: &str,
|
||||
) -> TextureRef;
|
||||
fn create_dynamic_texture_2d(
|
||||
width: u32,
|
||||
height: u32,
|
||||
mips: u32,
|
||||
format: TextureFormat,
|
||||
label: &str,
|
||||
) -> TextureRef;
|
||||
fn create_render_texture(
|
||||
width: u32,
|
||||
height: u32,
|
||||
// clamp_mode: TextureClampMode,
|
||||
color_bind_count: u32,
|
||||
depth_bind_count: u32,
|
||||
label: &str,
|
||||
) -> TextureRef;
|
||||
fn write_texture(handle: TextureRef, data: &[u8]);
|
||||
fn drop_texture(handle: TextureRef);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl bytemuck::Zeroable for ffi::FogMode {}
|
||||
unsafe impl bytemuck::Pod for ffi::FogMode {}
|
||||
unsafe impl bytemuck::Zeroable for ffi::FogState {}
|
||||
unsafe impl bytemuck::Pod for ffi::FogState {}
|
||||
impl Default for ffi::FogState {
|
||||
fn default() -> Self {
|
||||
Self { color: Default::default(), a: 0.0, b: 0.5, c: 0.0, mode: ffi::FogMode::None }
|
||||
}
|
||||
}
|
||||
impl Into<u32> for ffi::TextureFormat {
|
||||
// noinspection RsUnreachablePatterns
|
||||
fn into(self) -> u32 {
|
||||
match self {
|
||||
ffi::TextureFormat::RGBA8 => 1,
|
||||
ffi::TextureFormat::R8 => 2,
|
||||
ffi::TextureFormat::R32Float => 3,
|
||||
ffi::TextureFormat::DXT1 => 4,
|
||||
ffi::TextureFormat::DXT3 => 5,
|
||||
ffi::TextureFormat::DXT5 => 6,
|
||||
ffi::TextureFormat::BPTC => 7,
|
||||
_ => panic!("Invalid texture format {:?}", self),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,32 +5,20 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
|
||||
use aabb::queue_aabb;
|
||||
use bytemuck::Pod;
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use cxx::{type_id, ExternType};
|
||||
use fog_volume_filter::queue_fog_volume_filter;
|
||||
use fog_volume_plane::queue_fog_volume_plane;
|
||||
use model::{add_material_set, add_model};
|
||||
use movie_player::queue_movie_player;
|
||||
use texture::{
|
||||
create_dynamic_texture_2d, create_render_texture, create_static_texture_2d, drop_texture,
|
||||
write_texture,
|
||||
};
|
||||
use textured_quad::{queue_textured_quad, queue_textured_quad_verts};
|
||||
use cxx::ExternType;
|
||||
use cxxbridge::ffi;
|
||||
use twox_hash::Xxh3Hash64;
|
||||
use wgpu::RenderPipeline;
|
||||
|
||||
use crate::{
|
||||
gpu::GraphicsConfig,
|
||||
shaders::{
|
||||
ffi::{TextureFormat, TextureRef},
|
||||
texture::{RenderTexture, TextureWithView},
|
||||
},
|
||||
shaders::texture::{RenderTexture, TextureWithView},
|
||||
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, IDENTITY_MATRIX4F},
|
||||
};
|
||||
|
||||
mod aabb;
|
||||
mod cxxbridge;
|
||||
mod fog_volume_filter;
|
||||
mod fog_volume_plane;
|
||||
mod model;
|
||||
|
@ -38,245 +26,6 @@ mod movie_player;
|
|||
mod texture;
|
||||
mod textured_quad;
|
||||
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("zeus/CVector2f.hpp");
|
||||
include!("zeus/CVector3f.hpp");
|
||||
include!("zeus/CVector4f.hpp");
|
||||
include!("zeus/CMatrix4f.hpp");
|
||||
include!("zeus/CColor.hpp");
|
||||
include!("zeus/CRectangle.hpp");
|
||||
include!("zeus/CAABox.hpp");
|
||||
#[namespace = "zeus"]
|
||||
type CVector2f = crate::zeus::CVector2f;
|
||||
#[namespace = "zeus"]
|
||||
type CVector3f = crate::zeus::CVector3f;
|
||||
#[namespace = "zeus"]
|
||||
type CVector4f = crate::zeus::CVector4f;
|
||||
#[namespace = "zeus"]
|
||||
type CMatrix4f = crate::zeus::CMatrix4f;
|
||||
#[namespace = "zeus"]
|
||||
type CColor = crate::zeus::CColor;
|
||||
#[namespace = "zeus"]
|
||||
type CRectangle = crate::zeus::CRectangle;
|
||||
#[namespace = "zeus"]
|
||||
type CAABox = crate::zeus::CAABox;
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) enum CameraFilterType {
|
||||
Passthru,
|
||||
Multiply,
|
||||
Invert,
|
||||
Add,
|
||||
Subtract,
|
||||
Blend,
|
||||
Widescreen,
|
||||
SceneAdd,
|
||||
NoColor,
|
||||
InvDstMultiply,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) enum ZTest {
|
||||
Never,
|
||||
Less,
|
||||
Equal,
|
||||
LEqual,
|
||||
Greater,
|
||||
NEqual,
|
||||
GEqual,
|
||||
Always
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum TextureFormat {
|
||||
RGBA8,
|
||||
R8,
|
||||
R32Float,
|
||||
DXT1,
|
||||
DXT3,
|
||||
DXT5,
|
||||
BPTC,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum TextureClampMode {
|
||||
Repeat,
|
||||
ClampToEdge,
|
||||
ClampToWhite,
|
||||
ClampToBlack,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone, Hash)]
|
||||
pub(crate) struct TextureRef {
|
||||
pub(crate) id: u32,
|
||||
pub(crate) render: bool,
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub(crate) enum FogMode {
|
||||
None = 0x00,
|
||||
|
||||
PerspLin = 0x02,
|
||||
PerspExp = 0x04,
|
||||
PerspExp2 = 0x05,
|
||||
PerspRevExp = 0x06,
|
||||
PerspRevExp2 = 0x07,
|
||||
|
||||
OrthoLin = 0x0A,
|
||||
OrthoExp = 0x0C,
|
||||
OrthoExp2 = 0x0D,
|
||||
OrthoRevExp = 0x0E,
|
||||
OrthoRevExp2 = 0x0F,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) struct FogState {
|
||||
#[cxx_name = "m_color"]
|
||||
pub(crate) color: CColor,
|
||||
#[cxx_name = "m_A"]
|
||||
pub(crate) a: f32,
|
||||
#[cxx_name = "m_B"]
|
||||
pub(crate) b: f32,
|
||||
#[cxx_name = "m_C"]
|
||||
pub(crate) c: f32,
|
||||
#[cxx_name = "m_mode"]
|
||||
pub(crate) mode: FogMode,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) struct ClipRect {
|
||||
x: i32,
|
||||
y: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) struct MaterialPassInfo {
|
||||
tex_idx: u32,
|
||||
constant_color: CColor,
|
||||
has_constant_color: bool, // would love to use Option...
|
||||
uv_source: u8,
|
||||
uv_anim_type: u8,
|
||||
uv_anim_params: [f32; 9],
|
||||
normalize: bool, // TODO might be static based on uv type?
|
||||
sample_alpha: bool,
|
||||
}
|
||||
#[namespace = "aurora::shaders"]
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct MaterialInfo {
|
||||
pass_info: [MaterialPassInfo; 8],
|
||||
texture_ids: Vec<TextureRef>,
|
||||
shader_type: u8,
|
||||
blend_mode: u8,
|
||||
}
|
||||
|
||||
#[namespace = "aurora::shaders"]
|
||||
extern "Rust" {
|
||||
fn update_model_view(mv: CMatrix4f, mv_inv: CMatrix4f);
|
||||
fn update_projection(proj: CMatrix4f);
|
||||
fn update_fog_state(state: FogState);
|
||||
fn set_viewport(rect: CRectangle, znear: f32, zfar: f32);
|
||||
fn set_scissor(x: u32, y: u32, w: u32, h: u32);
|
||||
|
||||
fn resolve_color(rect: ClipRect, bind: u32, clear_depth: bool);
|
||||
fn resolve_depth(rect: ClipRect, bind: u32);
|
||||
|
||||
fn add_material_set(materials: Vec<MaterialInfo>) -> u32;
|
||||
fn add_model(verts: &[u8], indices: &[u8]) -> u32;
|
||||
|
||||
fn queue_aabb(aabb: CAABox, color: CColor, z_only: bool);
|
||||
fn queue_fog_volume_plane(verts: &CxxVector<CVector4f>, pass: u8);
|
||||
fn queue_fog_volume_filter(color: CColor, two_way: bool);
|
||||
fn queue_textured_quad_verts(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_comparison: ZTest,
|
||||
z_test: bool,
|
||||
color: CColor,
|
||||
pos: &[CVector3f],
|
||||
uvs: &[CVector2f],
|
||||
lod: f32,
|
||||
);
|
||||
fn queue_textured_quad(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_comparison: ZTest,
|
||||
z_test: bool,
|
||||
color: CColor,
|
||||
uv_scale: f32,
|
||||
rect: CRectangle,
|
||||
z: f32,
|
||||
);
|
||||
fn queue_movie_player(
|
||||
tex_y: TextureRef,
|
||||
tex_u: TextureRef,
|
||||
tex_v: TextureRef,
|
||||
color: CColor,
|
||||
h_pad: f32,
|
||||
v_pad: f32,
|
||||
);
|
||||
|
||||
fn create_static_texture_2d(
|
||||
width: u32,
|
||||
height: u32,
|
||||
mips: u32,
|
||||
format: TextureFormat,
|
||||
data: &[u8],
|
||||
label: &str,
|
||||
) -> TextureRef;
|
||||
fn create_dynamic_texture_2d(
|
||||
width: u32,
|
||||
height: u32,
|
||||
mips: u32,
|
||||
format: TextureFormat,
|
||||
label: &str,
|
||||
) -> TextureRef;
|
||||
fn create_render_texture(
|
||||
width: u32,
|
||||
height: u32,
|
||||
// clamp_mode: TextureClampMode,
|
||||
color_bind_count: u32,
|
||||
depth_bind_count: u32,
|
||||
label: &str,
|
||||
) -> TextureRef;
|
||||
fn write_texture(handle: TextureRef, data: &[u8]);
|
||||
fn drop_texture(handle: TextureRef);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl bytemuck::Zeroable for ffi::FogMode {}
|
||||
unsafe impl bytemuck::Pod for ffi::FogMode {}
|
||||
unsafe impl bytemuck::Zeroable for ffi::FogState {}
|
||||
unsafe impl bytemuck::Pod for ffi::FogState {}
|
||||
impl Default for ffi::FogState {
|
||||
fn default() -> Self {
|
||||
Self { color: Default::default(), a: 0.0, b: 0.5, c: 0.0, mode: ffi::FogMode::None }
|
||||
}
|
||||
}
|
||||
impl Into<u32> for ffi::TextureFormat {
|
||||
// noinspection RsUnreachablePatterns
|
||||
fn into(self) -> u32 {
|
||||
match self {
|
||||
TextureFormat::RGBA8 => 1,
|
||||
TextureFormat::R8 => 2,
|
||||
TextureFormat::R32Float => 3,
|
||||
TextureFormat::DXT1 => 4,
|
||||
TextureFormat::DXT3 => 5,
|
||||
TextureFormat::DXT5 => 6,
|
||||
TextureFormat::BPTC => 7,
|
||||
_ => panic!("Invalid texture format {:?}", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum ColoredStripMode {
|
||||
Alpha,
|
||||
|
@ -397,7 +146,7 @@ pub(crate) fn construct_state(
|
|||
mapped_at_creation: false,
|
||||
}),
|
||||
};
|
||||
let aabb = aabb::construct_state(&device, &queue, &buffers);
|
||||
let aabb = aabb::construct_state(&device, &queue, &buffers, graphics_config);
|
||||
let textured_quad = textured_quad::construct_state(&device, &queue, &buffers, graphics_config);
|
||||
let movie_player = movie_player::construct_state(&device, &queue, &buffers, graphics_config);
|
||||
let mut state = RenderState {
|
||||
|
@ -422,6 +171,9 @@ pub(crate) fn construct_state(
|
|||
for config in textured_quad::INITIAL_PIPELINES {
|
||||
construct_pipeline(&mut state, config);
|
||||
}
|
||||
for config in movie_player::INITIAL_PIPELINES {
|
||||
construct_pipeline(&mut state, config);
|
||||
}
|
||||
unsafe {
|
||||
STATE = Some(state);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::hash::Hash;
|
||||
|
||||
use crate::shaders::ffi::MaterialInfo;
|
||||
use crate::shaders::cxxbridge::ffi;
|
||||
|
||||
struct MaterialShaderData {
|
||||
shader_type: u32, // 5 values (incl. Invalid)
|
||||
|
@ -37,5 +37,5 @@ struct ModelPipelineConfig {
|
|||
render_alpha_update: bool,
|
||||
}
|
||||
|
||||
pub(crate) fn add_material_set(materials: Vec<MaterialInfo>) -> u32 { return u32::MAX; }
|
||||
pub(crate) fn add_material_set(materials: Vec<ffi::MaterialInfo>) -> u32 { return u32::MAX; }
|
||||
pub(crate) fn add_model(verts: &[u8], indices: &[u8]) -> u32 { return u32::MAX; }
|
||||
|
|
|
@ -11,14 +11,12 @@ use crate::{
|
|||
get_app,
|
||||
gpu::GraphicsConfig,
|
||||
shaders::{
|
||||
bind_pipeline,
|
||||
ffi::{CameraFilterType, TextureRef, ZTest},
|
||||
pipeline_ref, push_draw_command, push_uniform, push_verts,
|
||||
texture::create_sampler,
|
||||
BuiltBuffers, PipelineCreateCommand, PipelineHolder, PipelineRef, ShaderDrawCommand, STATE,
|
||||
bind_pipeline, cxxbridge::ffi, 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, CVector4f},
|
||||
zeus::{CColor, CMatrix4f},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -216,9 +214,9 @@ struct Vert {
|
|||
}
|
||||
|
||||
pub(crate) fn queue_movie_player(
|
||||
tex_y: TextureRef,
|
||||
tex_u: TextureRef,
|
||||
tex_v: TextureRef,
|
||||
tex_y: ffi::TextureRef,
|
||||
tex_u: ffi::TextureRef,
|
||||
tex_v: ffi::TextureRef,
|
||||
color: CColor,
|
||||
h_pad: f32,
|
||||
v_pad: f32,
|
||||
|
|
|
@ -10,7 +10,7 @@ use wgpu::{util::DeviceExt, ImageDataLayout};
|
|||
use crate::{
|
||||
get_app,
|
||||
shaders::{
|
||||
ffi::{TextureFormat, TextureRef},
|
||||
cxxbridge::ffi::{TextureFormat, TextureRef},
|
||||
STATE,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -7,11 +7,9 @@ use crate::{
|
|||
get_app,
|
||||
gpu::GraphicsConfig,
|
||||
shaders::{
|
||||
bind_pipeline,
|
||||
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,
|
||||
bind_pipeline, cxxbridge::ffi, get_combined_matrix, pipeline_ref, push_draw_command,
|
||||
push_uniform, push_verts, texture::create_sampler, BuiltBuffers, PipelineCreateCommand,
|
||||
PipelineHolder, PipelineRef, ShaderDrawCommand, STATE,
|
||||
},
|
||||
util::{align, Vec2, Vec3},
|
||||
zeus::{CColor, CMatrix4f, CRectangle, CVector2f, CVector3f, CVector4f},
|
||||
|
@ -22,13 +20,13 @@ pub(crate) struct DrawData {
|
|||
pipeline: PipelineRef,
|
||||
vert_range: Range<u64>,
|
||||
uniform_range: Range<u64>,
|
||||
texture: TextureRef,
|
||||
texture: ffi::TextureRef,
|
||||
}
|
||||
|
||||
#[derive(Hash)]
|
||||
pub(crate) struct PipelineConfig {
|
||||
filter_type: CameraFilterType,
|
||||
z_comparison: ZTest,
|
||||
filter_type: ffi::CameraFilterType,
|
||||
z_comparison: ffi::ZTest,
|
||||
z_test: bool,
|
||||
}
|
||||
pub(crate) const INITIAL_PIPELINES: &[PipelineCreateCommand] = &[
|
||||
|
@ -134,7 +132,7 @@ pub(crate) fn construct_pipeline(
|
|||
config: &PipelineConfig,
|
||||
) -> PipelineHolder {
|
||||
let (blend_component, alpha_write) = match config.filter_type {
|
||||
CameraFilterType::Multiply => (
|
||||
ffi::CameraFilterType::Multiply => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::Zero,
|
||||
dst_factor: wgpu::BlendFactor::Src,
|
||||
|
@ -142,7 +140,7 @@ pub(crate) fn construct_pipeline(
|
|||
},
|
||||
true,
|
||||
),
|
||||
CameraFilterType::Add => (
|
||||
ffi::CameraFilterType::Add => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::One,
|
||||
|
@ -150,7 +148,7 @@ pub(crate) fn construct_pipeline(
|
|||
},
|
||||
false,
|
||||
),
|
||||
CameraFilterType::Subtract => (
|
||||
ffi::CameraFilterType::Subtract => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::One,
|
||||
|
@ -158,7 +156,7 @@ pub(crate) fn construct_pipeline(
|
|||
},
|
||||
false,
|
||||
),
|
||||
CameraFilterType::Blend => (
|
||||
ffi::CameraFilterType::Blend => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::SrcAlpha,
|
||||
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
|
||||
|
@ -166,7 +164,7 @@ pub(crate) fn construct_pipeline(
|
|||
},
|
||||
false,
|
||||
),
|
||||
CameraFilterType::InvDstMultiply => (
|
||||
ffi::CameraFilterType::InvDstMultiply => (
|
||||
wgpu::BlendComponent {
|
||||
src_factor: wgpu::BlendFactor::Zero,
|
||||
dst_factor: wgpu::BlendFactor::OneMinusSrc,
|
||||
|
@ -197,14 +195,14 @@ pub(crate) fn construct_pipeline(
|
|||
format: graphics.depth_format,
|
||||
depth_write_enabled: config.z_test,
|
||||
depth_compare: match config.z_comparison {
|
||||
ZTest::Never => wgpu::CompareFunction::Never,
|
||||
ZTest::Less => wgpu::CompareFunction::Less,
|
||||
ZTest::Equal => wgpu::CompareFunction::Equal,
|
||||
ZTest::LEqual => wgpu::CompareFunction::LessEqual,
|
||||
ZTest::Greater => wgpu::CompareFunction::Greater,
|
||||
ZTest::NEqual => wgpu::CompareFunction::NotEqual,
|
||||
ZTest::GEqual => wgpu::CompareFunction::GreaterEqual,
|
||||
ZTest::Always => wgpu::CompareFunction::Always,
|
||||
ffi::ZTest::Never => wgpu::CompareFunction::Never,
|
||||
ffi::ZTest::Less => wgpu::CompareFunction::Less,
|
||||
ffi::ZTest::Equal => wgpu::CompareFunction::Equal,
|
||||
ffi::ZTest::LEqual => wgpu::CompareFunction::LessEqual,
|
||||
ffi::ZTest::Greater => wgpu::CompareFunction::Greater,
|
||||
ffi::ZTest::NEqual => wgpu::CompareFunction::NotEqual,
|
||||
ffi::ZTest::GEqual => wgpu::CompareFunction::GreaterEqual,
|
||||
ffi::ZTest::Always => wgpu::CompareFunction::Always,
|
||||
_ => todo!(),
|
||||
},
|
||||
stencil: Default::default(),
|
||||
|
@ -251,17 +249,20 @@ struct Vert {
|
|||
}
|
||||
|
||||
pub(crate) fn queue_textured_quad(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_comparison: ZTest,
|
||||
filter_type: ffi::CameraFilterType,
|
||||
texture: ffi::TextureRef,
|
||||
z_comparison: ffi::ZTest,
|
||||
z_test: bool,
|
||||
color: CColor,
|
||||
uv_scale: f32,
|
||||
rect: CRectangle,
|
||||
z: f32,
|
||||
) {
|
||||
let pipeline =
|
||||
pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig { filter_type, z_comparison, z_test }));
|
||||
let pipeline = pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig {
|
||||
filter_type,
|
||||
z_comparison,
|
||||
z_test,
|
||||
}));
|
||||
let vert_range = push_verts(&[
|
||||
Vert { pos: Vec3::new(0.0, 0.0, z), uv: Vec2::new(0.0, 0.0) },
|
||||
Vert { pos: Vec3::new(0.0, 1.0, z), uv: Vec2::new(0.0, uv_scale) },
|
||||
|
@ -283,9 +284,9 @@ pub(crate) fn queue_textured_quad(
|
|||
}
|
||||
|
||||
pub(crate) fn queue_textured_quad_verts(
|
||||
filter_type: CameraFilterType,
|
||||
texture: TextureRef,
|
||||
z_comparison: ZTest,
|
||||
filter_type: ffi::CameraFilterType,
|
||||
texture: ffi::TextureRef,
|
||||
z_comparison: ffi::ZTest,
|
||||
z_test: bool,
|
||||
color: CColor,
|
||||
pos: &[CVector3f],
|
||||
|
@ -296,8 +297,11 @@ pub(crate) fn queue_textured_quad_verts(
|
|||
panic!("Invalid pos/uv sizes: {}/{}", pos.len(), uvs.len());
|
||||
}
|
||||
|
||||
let pipeline =
|
||||
pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig { filter_type, z_comparison, z_test }));
|
||||
let pipeline = pipeline_ref(&PipelineCreateCommand::TexturedQuad(PipelineConfig {
|
||||
filter_type,
|
||||
z_comparison,
|
||||
z_test,
|
||||
}));
|
||||
let vert_range = push_verts(
|
||||
&pos.iter()
|
||||
.zip(uvs)
|
||||
|
@ -310,7 +314,7 @@ pub(crate) fn queue_textured_quad_verts(
|
|||
}
|
||||
|
||||
fn push_textured_quad(
|
||||
texture: TextureRef,
|
||||
texture: ffi::TextureRef,
|
||||
pipeline: PipelineRef,
|
||||
vert_range: Range<u64>,
|
||||
uniform_range: Range<u64>,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use cxx::{type_id, ExternType};
|
||||
|
||||
use crate::util::{Vec2, Vec3};
|
||||
|
||||
#[derive(Debug, Copy, Clone, Pod, Zeroable, Default)]
|
||||
|
@ -172,57 +173,21 @@ impl From<CMatrix4f> for cgmath::Matrix4<f32> {
|
|||
}
|
||||
|
||||
impl From<Vec2<f32>> for CVector2f {
|
||||
fn from(v: Vec2<f32>) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
_p1: 0.0,
|
||||
_p2: 0.0
|
||||
}
|
||||
}
|
||||
fn from(v: Vec2<f32>) -> Self { Self { x: v.x, y: v.y, _p1: 0.0, _p2: 0.0 } }
|
||||
}
|
||||
impl From<CVector2f> for Vec2<f32> {
|
||||
fn from(v: CVector2f) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
}
|
||||
}
|
||||
fn from(v: CVector2f) -> Self { Self { x: v.x, y: v.y } }
|
||||
}
|
||||
impl From<&CVector2f> for Vec2<f32> {
|
||||
fn from(v: &CVector2f) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
}
|
||||
}
|
||||
fn from(v: &CVector2f) -> Self { Self { x: v.x, y: v.y } }
|
||||
}
|
||||
|
||||
impl From<Vec3<f32>> for CVector3f {
|
||||
fn from(v: Vec3<f32>) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
z: v.z,
|
||||
_p: 0.0,
|
||||
}
|
||||
}
|
||||
fn from(v: Vec3<f32>) -> Self { Self { x: v.x, y: v.y, z: v.z, _p: 0.0 } }
|
||||
}
|
||||
impl From<CVector3f> for Vec3<f32> {
|
||||
fn from(v: CVector3f) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
z: v.z,
|
||||
}
|
||||
}
|
||||
fn from(v: CVector3f) -> Self { Self { x: v.x, y: v.y, z: v.z } }
|
||||
}
|
||||
impl From<&CVector3f> for Vec3<f32> {
|
||||
fn from(v: &CVector3f) -> Self {
|
||||
Self {
|
||||
x: v.x,
|
||||
y: v.y,
|
||||
z: v.z,
|
||||
}
|
||||
}
|
||||
fn from(v: &CVector3f) -> Self { Self { x: v.x, y: v.y, z: v.z } }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue