Initial commit.
This commit is contained in:
commit
2d531dafa9
8
SModule
Normal file
8
SModule
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
Import('env')
|
||||
|
||||
LIB_CONFIG = {
|
||||
'CPPPATH': [env.Dir('public')]
|
||||
}
|
||||
|
||||
Return('LIB_CONFIG')
|
94
public/sdlpp/common.hpp
Normal file
94
public/sdlpp/common.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_COMMON_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_COMMON_HPP_INCLUDED 1
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <span>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <mijin/debug/assert.hpp>
|
||||
#include <mijin/util/bitflags.hpp>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <mijin/util/winundef.hpp>
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
template<typename THandle, typename TConcrete>
|
||||
class Base
|
||||
{
|
||||
protected:
|
||||
THandle* mHandle = nullptr;
|
||||
protected:
|
||||
Base() noexcept = default;
|
||||
explicit Base(THandle* handle) noexcept : mHandle(handle) {}
|
||||
Base(const Base&) noexcept = default;
|
||||
Base(Base&& other) noexcept : mHandle(std::exchange(other.mHandle, nullptr)) {}
|
||||
|
||||
Base& operator=(const Base&) noexcept = default;
|
||||
Base& operator=(Base&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
static_cast<TConcrete&>(*this).destroy();
|
||||
mHandle = std::exchange(other.mHandle, nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
~Base() noexcept
|
||||
{
|
||||
static_cast<TConcrete&>(*this).destroy();
|
||||
}
|
||||
auto operator<=>(const Base& other) const noexcept = default;
|
||||
|
||||
operator THandle*() const noexcept { return mHandle; }
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return mHandle != nullptr;
|
||||
}
|
||||
bool operator!() const noexcept
|
||||
{
|
||||
return mHandle == nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename THandle, typename TConcrete>
|
||||
class BaseWithDevice : public Base<THandle, TConcrete>
|
||||
{
|
||||
protected:
|
||||
SDL_GPUDevice* mDevice = nullptr;
|
||||
protected:
|
||||
BaseWithDevice() noexcept = default;
|
||||
BaseWithDevice(THandle* handle, SDL_GPUDevice* device) noexcept : Base<THandle, TConcrete>(handle), mDevice(device) {}
|
||||
BaseWithDevice(BaseWithDevice&& other) noexcept : Base<THandle, TConcrete>(std::exchange(other.mHandle, nullptr)),
|
||||
mDevice(std::exchange(other.mDevice, nullptr)){}
|
||||
|
||||
BaseWithDevice& operator=(BaseWithDevice&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
mDevice = std::exchange(other.mDevice, nullptr);
|
||||
Base<THandle, TConcrete>::operator=(std::move(other));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
BaseWithDevice(const BaseWithDevice&) = delete;
|
||||
BaseWithDevice& operator=(const BaseWithDevice&) = delete;
|
||||
auto operator<=>(const BaseWithDevice& other) const noexcept = default;
|
||||
};
|
||||
|
||||
class SDLError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
SDLError() : std::runtime_error(SDL_GetError()) {}
|
||||
};
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_COMMON_HPP_INCLUDED)
|
145
public/sdlpp/event.hpp
Normal file
145
public/sdlpp/event.hpp
Normal file
@ -0,0 +1,145 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_EVENT_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_EVENT_HPP_INCLUDED 1
|
||||
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
#include "./common.hpp"
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
//
|
||||
// flags
|
||||
//
|
||||
struct MouseButtonFlags : mijin::BitFlags<MouseButtonFlags>
|
||||
{
|
||||
bool left : 1 = false;
|
||||
bool middle : 1 = false;
|
||||
bool right : 1 = false;
|
||||
bool x1 : 1 = false;
|
||||
bool x2 : 1 = false;
|
||||
|
||||
static MouseButtonFlags from(SDL_MouseButtonFlags base) noexcept
|
||||
{
|
||||
return std::bit_cast<MouseButtonFlags>(static_cast<std::uint8_t>(base));
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// structs
|
||||
//
|
||||
struct Event
|
||||
{
|
||||
Uint64 timestamp;
|
||||
|
||||
template<typename TBase>
|
||||
explicit Event(const TBase& base) noexcept : timestamp(base.timestamp) {}
|
||||
};
|
||||
|
||||
struct KeyboardEvent : Event
|
||||
{
|
||||
SDL_WindowID windowID;
|
||||
SDL_KeyboardID which;
|
||||
SDL_Scancode scancode;
|
||||
SDL_Keycode key;
|
||||
SDL_Keymod mod;
|
||||
bool down;
|
||||
bool repeat;
|
||||
|
||||
explicit KeyboardEvent(const SDL_KeyboardEvent& base) noexcept : Event(base), windowID(base.windowID),
|
||||
which(base.which), scancode(base.scancode), key(base.key), mod(base.mod), down(base.down), repeat(base.repeat)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct MouseButtonEvent : Event
|
||||
{
|
||||
SDL_WindowID windowID;
|
||||
SDL_MouseID which;
|
||||
Uint8 button;
|
||||
bool down;
|
||||
Uint8 clicks;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
MouseButtonEvent(const SDL_MouseButtonEvent& base) noexcept : Event(base), windowID(base.windowID), which(base.which),
|
||||
button(base.button), down(base.down), clicks(base.clicks), x(base.x), y(base.y)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct MouseMotionEvent : Event
|
||||
{
|
||||
SDL_WindowID windowID;
|
||||
SDL_MouseID which;
|
||||
MouseButtonFlags state;
|
||||
float x;
|
||||
float y;
|
||||
float xrel;
|
||||
float yrel;
|
||||
|
||||
MouseMotionEvent(const SDL_MouseMotionEvent& base) noexcept : Event(base), windowID(base.windowID), which(base.which),
|
||||
state(MouseButtonFlags::from(base.state)), x(base.x), y(base.y), xrel(base.xrel), yrel(base.yrel)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct GamepadButtonEvent : Event
|
||||
{
|
||||
SDL_JoystickID which;
|
||||
Uint8 button;
|
||||
bool down;
|
||||
|
||||
GamepadButtonEvent(const SDL_GamepadButtonEvent& base) noexcept : Event(base), which(base.which), button(base.button),
|
||||
down(base.down)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct QuitEvent : Event
|
||||
{
|
||||
explicit QuitEvent(const SDL_QuitEvent& base) noexcept : Event(base) {}
|
||||
};
|
||||
|
||||
using sdl_event_t = std::variant<
|
||||
KeyboardEvent,
|
||||
MouseButtonEvent,
|
||||
MouseMotionEvent,
|
||||
GamepadButtonEvent,
|
||||
QuitEvent
|
||||
>;
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::optional<sdl_event_t> pollEvent() noexcept
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
case SDL_EVENT_KEY_UP:
|
||||
return KeyboardEvent(event.key);
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
return MouseButtonEvent(event.button);
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
return MouseMotionEvent(event.motion);
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
return GamepadButtonEvent(event.gbutton);
|
||||
case SDL_EVENT_QUIT:
|
||||
return QuitEvent(event.quit);
|
||||
default:
|
||||
// can't translate this yet
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_EVENT_HPP_INCLUDED)
|
68
public/sdlpp/gamepad.hpp
Normal file
68
public/sdlpp/gamepad.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_GAMEPAD_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_GAMEPAD_HPP_INCLUDED 1
|
||||
|
||||
#include "./common.hpp"
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
enum class GamepadAxis
|
||||
{
|
||||
INVALID = SDL_GAMEPAD_AXIS_INVALID,
|
||||
LEFTX = SDL_GAMEPAD_AXIS_LEFTX,
|
||||
LEFTY = SDL_GAMEPAD_AXIS_LEFTY,
|
||||
RIGHTX = SDL_GAMEPAD_AXIS_RIGHTX,
|
||||
RIGHTY = SDL_GAMEPAD_AXIS_RIGHTY,
|
||||
LEFT_TRIGGER = SDL_GAMEPAD_AXIS_LEFT_TRIGGER,
|
||||
RIGHT_TRIGGER = SDL_GAMEPAD_AXIS_RIGHT_TRIGGER,
|
||||
};
|
||||
|
||||
class Gamepad : public Base<SDL_Gamepad, Gamepad>
|
||||
{
|
||||
public:
|
||||
Gamepad() noexcept = default;
|
||||
Gamepad(Gamepad&&) noexcept = default;
|
||||
|
||||
Gamepad& operator=(Gamepad&&) = default;
|
||||
|
||||
void open(SDL_JoystickID instanceID)
|
||||
{
|
||||
MIJIN_ASSERT(mHandle == nullptr, "Gamepad already opened.");
|
||||
mHandle = SDL_OpenGamepad(instanceID);
|
||||
if (mHandle == nullptr)
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
if (mHandle != nullptr)
|
||||
{
|
||||
SDL_CloseGamepad(mHandle);
|
||||
mHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
Sint16 getAxis(GamepadAxis axis) const noexcept
|
||||
{
|
||||
return SDL_GetGamepadAxis(mHandle, static_cast<SDL_GamepadAxis>(axis));
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::vector<SDL_JoystickID> getGamepads() noexcept
|
||||
{
|
||||
int count = 0;
|
||||
SDL_JoystickID* gamepads = SDL_GetGamepads(&count);
|
||||
std::vector<SDL_JoystickID> result;
|
||||
result.resize(count);
|
||||
std::copy_n(gamepads, count, result.begin());
|
||||
return result;
|
||||
}
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_GAMEPAD_HPP_INCLUDED)
|
1210
public/sdlpp/gpu.hpp
Normal file
1210
public/sdlpp/gpu.hpp
Normal file
File diff suppressed because it is too large
Load Diff
20
public/sdlpp/keyboard.hpp
Normal file
20
public/sdlpp/keyboard.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_KEYBOARD_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_KEYBOARD_HPP_INCLUDED 1
|
||||
|
||||
#include "./common.hpp"
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
[[nodiscard]]
|
||||
inline std::span<const bool> getKeyboardState() noexcept
|
||||
{
|
||||
int numkeys = 0;
|
||||
const bool* states = SDL_GetKeyboardState(&numkeys);
|
||||
return {states, static_cast<std::size_t>(numkeys)};
|
||||
}
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_KEYBOARD_HPP_INCLUDED)
|
74
public/sdlpp/vulkan.hpp
Normal file
74
public/sdlpp/vulkan.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDLPP_PUBLIC_SDLPP_VULKAN_HPP_INCLUDED)
|
||||
#define SDLPP_PUBLIC_SDLPP_VULKAN_HPP_INCLUDED 1
|
||||
|
||||
#include "./common.hpp"
|
||||
|
||||
#include <SDL3/SDL_vulkan.h>
|
||||
#include "suna/vulkan/vkwrapper.hpp" // TODO: this shouldn't be in a generic sdlpp header
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
struct VkSurfaceCreateArgs
|
||||
{
|
||||
SDL_Window* window;
|
||||
VkInstance instance;
|
||||
};
|
||||
|
||||
class VkSurface : public Base<std::remove_pointer_t<VkSurfaceKHR>, VkSurface>
|
||||
{
|
||||
private:
|
||||
VkInstance mInstance = nullptr;
|
||||
public:
|
||||
VkSurface() noexcept = default;
|
||||
VkSurface(const VkSurface&) = delete;
|
||||
VkSurface(VkSurface&& other) noexcept : Base(std::move(other)), mInstance(std::exchange(other.mInstance, nullptr)) {}
|
||||
|
||||
VkSurface& operator=(const VkSurface&) = delete;
|
||||
VkSurface& operator=(VkSurface&& other) noexcept
|
||||
{
|
||||
Base::operator=(std::move(other));
|
||||
mInstance = std::exchange(other.mInstance, nullptr);
|
||||
return *this;
|
||||
}
|
||||
auto operator<=>(const VkSurface& other) const noexcept = default;
|
||||
|
||||
operator vk::SurfaceKHR() const noexcept { return mHandle; }
|
||||
|
||||
void create(const VkSurfaceCreateArgs& args)
|
||||
{
|
||||
MIJIN_ASSERT(mHandle == nullptr, "VkSurface has already been created.");
|
||||
if (!SDL_Vulkan_CreateSurface(args.window, args.instance, nullptr, &mHandle))
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
mInstance = args.instance;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if (mHandle != nullptr)
|
||||
{
|
||||
SDL_Vulkan_DestroySurface(mInstance, mHandle, nullptr);
|
||||
mHandle = nullptr;
|
||||
mInstance = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
inline std::span<const char* const> getVulkanInstanceExtensions()
|
||||
{
|
||||
Uint32 count = 0;
|
||||
const char* const* extensions = SDL_Vulkan_GetInstanceExtensions(&count);
|
||||
if (extensions == nullptr)
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
return {extensions, count};
|
||||
}
|
||||
} // namespace suna
|
||||
|
||||
#endif // !defined(SDLPP_PUBLIC_SDLPP_VULKAN_HPP_INCLUDED)
|
113
public/sdlpp/window.hpp
Normal file
113
public/sdlpp/window.hpp
Normal file
@ -0,0 +1,113 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_WINDOW_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_WINDOW_HPP_INCLUDED 1
|
||||
|
||||
#include "./common.hpp"
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
struct WindowFlags : mijin::BitFlags<WindowFlags>
|
||||
{
|
||||
bool fullscreen : 1; // 0x0000000000000001 /**< window is in fullscreen mode */
|
||||
bool opengl : 1; // 0x0000000000000002 /**< window usable with OpenGL context */
|
||||
bool occluded : 1; // 0x0000000000000004 /**< window is occluded */
|
||||
bool hidden : 1; // 0x0000000000000008 /**< window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow( is required for it to become visible */
|
||||
bool borderless : 1; // 0x0000000000000010 /**< no window decoration */
|
||||
bool resizable : 1; // 0x0000000000000020 /**< window can be resized */
|
||||
bool minimized : 1; // 0x0000000000000040 /**< window is minimized */
|
||||
bool maximized : 1; // 0x0000000000000080 /**< window is maximized */
|
||||
bool mouse_grabbed : 1; // 0x0000000000000100 /**< window has grabbed mouse input */
|
||||
bool input_focus : 1; // 0x0000000000000200 /**< window has input focus */
|
||||
bool mouse_focus : 1; // 0x0000000000000400 /**< window has mouse focus */
|
||||
bool external : 1; // 0x0000000000000800 /**< window not created by SDL */
|
||||
bool modal : 1; // 0x0000000000001000 /**< window is modal */
|
||||
bool high_pixel_density : 1; // 0x0000000000002000 /**< window uses high pixel density back buffer if possible */
|
||||
bool mouse_capture : 1; // 0x0000000000004000 /**< window has mouse captured (unrelated to MOUSE_GRABBED */
|
||||
bool mouse_relative_mode : 1; // 0x0000000000008000 /**< window has relative mode enabled */
|
||||
bool always_on_top : 1; // 0x0000000000010000 /**< window should always be above others */
|
||||
bool utility : 1; // 0x0000000000020000 /**< window should be treated as a utility window, not showing in the task bar and window list */
|
||||
bool tooltip : 1; // 0x0000000000040000 /**< window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window */
|
||||
bool popup_menu : 1; // 0x0000000000080000 /**< window should be treated as a popup menu, requires a parent window */
|
||||
bool keyboard_grabbed : 1; // 0x0000000000100000 /**< window has grabbed keyboard input */
|
||||
bool unused0 : 1; // 0x0000000000200000
|
||||
bool unused1 : 1; // 0x0000000000400000
|
||||
bool unused2 : 1; // 0x0000000000800000
|
||||
bool unused3 : 1; // 0x0000000001000000
|
||||
bool unused4 : 1; // 0x0000000002000000
|
||||
bool unused5 : 1; // 0x0000000004000000
|
||||
bool unused6 : 1; // 0x0000000008000000
|
||||
bool vulkan : 1; // 0x0000000010000000 /**< window usable for Vulkan surface */
|
||||
bool metal : 1; // 0x0000000020000000 /**< window usable for Metal view */
|
||||
bool transparent : 1; // 0x0000000040000000 /**< window with transparent buffer */
|
||||
bool notFocusable : 1; // 0x0000000080000000 /**< window should not be focusable */
|
||||
|
||||
constexpr operator SDL_WindowFlags () const noexcept
|
||||
{
|
||||
return std::bit_cast<std::uint32_t>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
struct WindowCreateArgs
|
||||
{
|
||||
const char* title = "Window";
|
||||
int width = 1280;
|
||||
int height = 720;
|
||||
WindowFlags flags = {};
|
||||
};
|
||||
|
||||
class Window : public Base<SDL_Window, Window>
|
||||
{
|
||||
public:
|
||||
Window() noexcept = default;
|
||||
Window(const Window&) = delete;
|
||||
Window(Window&& other) noexcept : Base(std::move(other)) {}
|
||||
|
||||
Window& operator=(const Window&) = delete;
|
||||
Window& operator=(Window&& other) noexcept
|
||||
{
|
||||
Base::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
auto operator<=>(const Window& other) const noexcept = default;
|
||||
|
||||
void create(const WindowCreateArgs& args = {})
|
||||
{
|
||||
MIJIN_ASSERT(mHandle == nullptr, "Window has already been created.");
|
||||
mHandle = SDL_CreateWindow(args.title, args.width, args.height, args.flags);
|
||||
if (mHandle == nullptr)
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
if (mHandle != nullptr)
|
||||
{
|
||||
SDL_DestroyWindow(mHandle);
|
||||
mHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool setRelativeMouseMode(bool enabled)
|
||||
{
|
||||
return SDL_SetWindowRelativeMouseMode(mHandle, enabled);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::pair<int, int> getSizeInPixels() const
|
||||
{
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
if (!SDL_GetWindowSizeInPixels(mHandle, &width, &height))
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
return {width, height};
|
||||
}
|
||||
};
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_WINDOW_HPP_INCLUDED)
|
Loading…
x
Reference in New Issue
Block a user