A lot of input.
This commit is contained in:
parent
f364998933
commit
a2bd91226f
246
private/sdl_gpu_test/5_input/app.cpp
Normal file
246
private/sdl_gpu_test/5_input/app.cpp
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
|
||||||
|
#include "./app.hpp"
|
||||||
|
|
||||||
|
#include "../util/mesh.hpp"
|
||||||
|
|
||||||
|
#include <glm/mat4x4.hpp>
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
#include "../sdlpp/keyboard.hpp"
|
||||||
|
#include "../util/mesh.hpp"
|
||||||
|
|
||||||
|
namespace sdl_gpu_test
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
inline constexpr float Y_POS_MIN = -10.f;
|
||||||
|
inline constexpr float Y_POS_MAX = 10.f;
|
||||||
|
inline constexpr Uint16 AXIS_DEADZONE = 5000;
|
||||||
|
|
||||||
|
struct VertexShaderParameters
|
||||||
|
{
|
||||||
|
glm::mat4 worldToView;
|
||||||
|
glm::mat4 viewToClip;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputApp::init(const AppInitArgs& args)
|
||||||
|
{
|
||||||
|
Application::init(args);
|
||||||
|
|
||||||
|
// create shaders
|
||||||
|
const sdlpp::GPUShader vertexShader = loadShader("shaders/glsl/textured_3dtriangles_from_buffer.vert.spv", {
|
||||||
|
.format = sdlpp::GPUShaderFormat::SPIRV,
|
||||||
|
.stage = sdlpp::GPUShaderStage::VERTEX,
|
||||||
|
.numUniformBuffers = 1
|
||||||
|
});
|
||||||
|
const sdlpp::GPUShader fragmentShader = loadShader("shaders/glsl/color_from_texture.frag.spv", {
|
||||||
|
.format = sdlpp::GPUShaderFormat::SPIRV,
|
||||||
|
.stage = sdlpp::GPUShaderStage::FRAGMENT,
|
||||||
|
.numSamplers = 1,
|
||||||
|
.numUniformBuffers = 1
|
||||||
|
});
|
||||||
|
|
||||||
|
// create depth buffer
|
||||||
|
mDepthBuffer.create(mDevice, {
|
||||||
|
.format = sdlpp::GPUTextureFormat::D16_UNORM,
|
||||||
|
.usage = sdlpp::GPUTextureUsageFlags{.depthStencilTarget = true},
|
||||||
|
.width = 1280,
|
||||||
|
.height = 720
|
||||||
|
});
|
||||||
|
|
||||||
|
// create graphics pipeline
|
||||||
|
std::array colorTargetsDescs = {
|
||||||
|
sdlpp::GPUColorTargetDescription{
|
||||||
|
.format = mDevice.getSwapchainTextureFormat(mWindow),
|
||||||
|
.blendState = {
|
||||||
|
.enableBlend = true,
|
||||||
|
.srcColorBlendfactor = sdlpp::GPUBlendFactor::SRC_ALPHA,
|
||||||
|
.dstColorBlendfactor = sdlpp::GPUBlendFactor::ONE_MINUS_SRC_ALPHA,
|
||||||
|
.colorBlendOp = sdlpp::GPUBlendOp::ADD,
|
||||||
|
.srcAlphaBlendfactor = sdlpp::GPUBlendFactor::ONE,
|
||||||
|
.dstAlphaBlendfactor = sdlpp::GPUBlendFactor::ZERO,
|
||||||
|
.alphaBlendOp = sdlpp::GPUBlendOp::ADD
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::array vertexBindings = {
|
||||||
|
sdlpp::GPUVertexBinding{
|
||||||
|
.index = 0,
|
||||||
|
.pitch = sizeof(Vertex)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::array vertexAttributes = {
|
||||||
|
sdlpp::GPUVertexAttribute{
|
||||||
|
.location = 0,
|
||||||
|
.bindingIndex = 0,
|
||||||
|
.format = sdlpp::GPUVertexElementFormat::FLOAT3,
|
||||||
|
.offset = offsetof(Vertex, pos)
|
||||||
|
},
|
||||||
|
sdlpp::GPUVertexAttribute{
|
||||||
|
.location = 1,
|
||||||
|
.bindingIndex = 0,
|
||||||
|
.format = sdlpp::GPUVertexElementFormat::FLOAT2,
|
||||||
|
.offset = offsetof(Vertex, texcoord)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mPipeline.create(mDevice, {
|
||||||
|
.vertexShader = vertexShader,
|
||||||
|
.fragmentShader = fragmentShader,
|
||||||
|
.vertexInputState = {
|
||||||
|
.vertexBindings = vertexBindings,
|
||||||
|
.vertexAttributes = vertexAttributes
|
||||||
|
},
|
||||||
|
.rasterizerState = {
|
||||||
|
.cullMode = sdlpp::GPUCullMode::BACK
|
||||||
|
},
|
||||||
|
.targetInfo = {
|
||||||
|
.colorTargetDescriptions = colorTargetsDescs,
|
||||||
|
.depthStencilFormat = sdlpp::GPUTextureFormat::D16_UNORM
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// load the mesh
|
||||||
|
const Mesh mesh = loadMesh(mFileSystem.getPath("meshes/cube.obj"));
|
||||||
|
mNumVertices = static_cast<Uint32>(mesh.vertices.size());
|
||||||
|
|
||||||
|
// create vertex buffer
|
||||||
|
mVertexBuffer.create(mDevice, {
|
||||||
|
.usage = {.vertex = true},
|
||||||
|
.size = static_cast<Uint32>(mesh.vertices.size() * sizeof(Vertex))
|
||||||
|
});
|
||||||
|
uploadVertexData(mVertexBuffer, std::span(mesh.vertices.begin(), mesh.vertices.end()));
|
||||||
|
|
||||||
|
// create texture and sampler
|
||||||
|
sdlpp::GPUTextureCreateArgs textureArgs = {
|
||||||
|
.format = sdlpp::GPUTextureFormat::R8G8B8A8_UNORM_SRGB,
|
||||||
|
.usage = {.sampler = true}
|
||||||
|
};
|
||||||
|
mTexture = loadTexture("bitmaps/cube.png", textureArgs);
|
||||||
|
mSampler.create(mDevice, {});
|
||||||
|
|
||||||
|
// open gamepad
|
||||||
|
const std::vector<SDL_JoystickID> gamepads = sdlpp::getGamepads();
|
||||||
|
if (!gamepads.empty())
|
||||||
|
{
|
||||||
|
mGamepad.open(gamepads[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputApp::update(const AppUpdateArgs& args)
|
||||||
|
{
|
||||||
|
Application::update(args);
|
||||||
|
|
||||||
|
sdlpp::GPUCommandBuffer cmdBuffer = mDevice.acquireCommandBuffer();
|
||||||
|
Uint32 swapchainWidth = 0, swapchainHeight = 0;
|
||||||
|
const sdlpp::GPUTexture swapchainTexture = cmdBuffer.acquireSwapchainTexture(mWindow, swapchainWidth, swapchainHeight);
|
||||||
|
|
||||||
|
if (swapchainWidth != mLastSwapchainWidth || swapchainHeight != mLastSwapchainHeight)
|
||||||
|
{
|
||||||
|
mDepthBuffer.destroy();
|
||||||
|
mDepthBuffer.create(mDevice, {
|
||||||
|
.format = sdlpp::GPUTextureFormat::D16_UNORM,
|
||||||
|
.usage = sdlpp::GPUTextureUsageFlags{.depthStencilTarget = true},
|
||||||
|
.width = swapchainWidth,
|
||||||
|
.height = swapchainHeight
|
||||||
|
});
|
||||||
|
mLastSwapchainWidth = swapchainWidth;
|
||||||
|
mLastSwapchainHeight = swapchainHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::span<const SDL_bool> keystates = sdlpp::getKeyboardState();
|
||||||
|
if (keystates[SDL_SCANCODE_LEFT])
|
||||||
|
{
|
||||||
|
mRotation -= 40.f * args.tickSeconds;
|
||||||
|
}
|
||||||
|
if (keystates[SDL_SCANCODE_RIGHT])
|
||||||
|
{
|
||||||
|
mRotation += 40.f * args.tickSeconds;
|
||||||
|
}
|
||||||
|
if (keystates[SDL_SCANCODE_UP])
|
||||||
|
{
|
||||||
|
mYPos -= 2.f * args.tickSeconds;
|
||||||
|
}
|
||||||
|
if (keystates[SDL_SCANCODE_DOWN])
|
||||||
|
{
|
||||||
|
mYPos += 2.f * args.tickSeconds;
|
||||||
|
}
|
||||||
|
if (mGamepad)
|
||||||
|
{
|
||||||
|
const Sint16 xAxis = mGamepad.getAxis(sdlpp::GamepadAxis::LEFTX);
|
||||||
|
if (std::abs(xAxis) > AXIS_DEADZONE)
|
||||||
|
{
|
||||||
|
mRotation += 0.001f * args.tickSeconds * static_cast<float>(xAxis);
|
||||||
|
}
|
||||||
|
const Sint16 yAxis = mGamepad.getAxis(sdlpp::GamepadAxis::LEFTY);
|
||||||
|
if (std::abs(yAxis) > AXIS_DEADZONE)
|
||||||
|
{
|
||||||
|
mYPos += 0.0002f * args.tickSeconds * yAxis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (mRotation >= 360.f) { mRotation -= 360.f; }
|
||||||
|
while (mRotation < 0.f) { mRotation += 360.f; }
|
||||||
|
mYPos = std::clamp(mYPos, Y_POS_MIN, Y_POS_MAX);
|
||||||
|
|
||||||
|
const VertexShaderParameters vertexShaderParameters = {
|
||||||
|
.worldToView = glm::lookAt(glm::vec3(2.f, mYPos, 2.f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 1.f, 0.f))
|
||||||
|
* glm::rotate(glm::mat4(1.f), glm::radians(mRotation), glm::vec3(0.f, 1.f, 0.f)),
|
||||||
|
.viewToClip = glm::perspectiveFov(
|
||||||
|
/* fov = */ glm::radians(90.f),
|
||||||
|
/* width = */ static_cast<float>(swapchainWidth),
|
||||||
|
/* height = */ static_cast<float>(swapchainHeight),
|
||||||
|
/* zNear = */ 0.1f,
|
||||||
|
/* zFar = */ 100.f
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array colorTargets = {sdlpp::GPUColorTargetInfo{
|
||||||
|
.texture = swapchainTexture,
|
||||||
|
.clearColor = {.r = 0.f, .g = 0.f, .b = 0.f, .a = 1.f},
|
||||||
|
.loadOp = sdlpp::GPULoadOp::CLEAR,
|
||||||
|
}};
|
||||||
|
sdlpp::GPURenderPass renderPass = cmdBuffer.beginRenderPass({
|
||||||
|
.colorTargetInfos = colorTargets,
|
||||||
|
.depthStencilTargetInfo = sdlpp::GPUDepthStencilTargetInfo{
|
||||||
|
.texture = mDepthBuffer,
|
||||||
|
.loadOp = sdlpp::GPULoadOp::CLEAR
|
||||||
|
}
|
||||||
|
});
|
||||||
|
static const glm::vec4 WHITE(1.f, 1.f, 1.f, 1.f);
|
||||||
|
cmdBuffer.pushFragmentUniformData(0, std::span(&WHITE, 1));
|
||||||
|
cmdBuffer.pushVertexUniformData(0, std::span(&vertexShaderParameters, 1));
|
||||||
|
renderPass.bindFragmentSampler({.texture = mTexture, .sampler = mSampler});
|
||||||
|
renderPass.bindGraphicsPipeline(mPipeline);
|
||||||
|
renderPass.bindVertexBuffer({.buffer = mVertexBuffer});
|
||||||
|
renderPass.drawPrimitives({.numVertices = mNumVertices});
|
||||||
|
renderPass.end();
|
||||||
|
cmdBuffer.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputApp::handleKeyboardEvent(const sdlpp::KeyboardEvent& event)
|
||||||
|
{
|
||||||
|
switch (event.key)
|
||||||
|
{
|
||||||
|
case SDLK_Q:
|
||||||
|
if (!event.down)
|
||||||
|
{
|
||||||
|
mRunning = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InputApp::handleMouseMotionEvent(const sdlpp::MouseMotionEvent& event)
|
||||||
|
{
|
||||||
|
if (event.state.left)
|
||||||
|
{
|
||||||
|
mRotation += 0.5f * event.xrel;
|
||||||
|
mYPos = std::clamp(mYPos + 0.02f * event.yrel, Y_POS_MIN, Y_POS_MAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
private/sdl_gpu_test/5_input/app.hpp
Normal file
34
private/sdl_gpu_test/5_input/app.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_5_INPUT_APP_HPP_INCLUDED)
|
||||||
|
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_5_INPUT_APP_HPP_INCLUDED 1
|
||||||
|
|
||||||
|
#include "../application.hpp"
|
||||||
|
#include "../sdlpp/gamepad.hpp"
|
||||||
|
|
||||||
|
namespace sdl_gpu_test
|
||||||
|
{
|
||||||
|
class InputApp : public Application
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
sdlpp::GPUBuffer mVertexBuffer;
|
||||||
|
sdlpp::GPUTexture mDepthBuffer;
|
||||||
|
sdlpp::GPUGraphicsPipeline mPipeline;
|
||||||
|
sdlpp::GPUTexture mTexture;
|
||||||
|
sdlpp::GPUSampler mSampler;
|
||||||
|
sdlpp::Gamepad mGamepad;
|
||||||
|
Uint32 mNumVertices = 0;
|
||||||
|
Uint32 mLastSwapchainWidth = 1280;
|
||||||
|
Uint32 mLastSwapchainHeight = 720;
|
||||||
|
float mRotation = 0.f;
|
||||||
|
float mYPos = 1.5f;
|
||||||
|
public:
|
||||||
|
void init(const AppInitArgs& args) override;
|
||||||
|
void update(const AppUpdateArgs& args) override;
|
||||||
|
void handleKeyboardEvent(const sdlpp::KeyboardEvent& event) override;
|
||||||
|
void handleMouseMotionEvent(const sdlpp::MouseMotionEvent& event) override;
|
||||||
|
};
|
||||||
|
} // namespace sdl_gpu_test
|
||||||
|
|
||||||
|
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_5_INPUT_APP_HPP_INCLUDED)
|
@ -13,6 +13,7 @@ src_files = Split("""
|
|||||||
2_triangle_with_texcoords/app.cpp
|
2_triangle_with_texcoords/app.cpp
|
||||||
3_textured_quad/app.cpp
|
3_textured_quad/app.cpp
|
||||||
4_textured_cube/app.cpp
|
4_textured_cube/app.cpp
|
||||||
|
5_input/app.cpp
|
||||||
""")
|
""")
|
||||||
|
|
||||||
shader_files = env.Glob("#assets/shaders/glsl/*.frag") \
|
shader_files = env.Glob("#assets/shaders/glsl/*.frag") \
|
||||||
|
@ -5,10 +5,9 @@
|
|||||||
|
|
||||||
#include <mijin/util/variant.hpp>
|
#include <mijin/util/variant.hpp>
|
||||||
#include <mijin/virtual_filesystem/relative.hpp>
|
#include <mijin/virtual_filesystem/relative.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
|
||||||
#include <mijin/util/winundef.hpp>
|
|
||||||
|
|
||||||
#include "./util/bitmap.hpp"
|
#include "./util/bitmap.hpp"
|
||||||
|
#include "./util/spdlog_wrapper.hpp"
|
||||||
|
|
||||||
namespace sdl_gpu_test
|
namespace sdl_gpu_test
|
||||||
{
|
{
|
||||||
@ -56,6 +55,7 @@ void Application::run(std::span<const char*> args)
|
|||||||
});
|
});
|
||||||
|
|
||||||
const clock_t::time_point startTime = clock_t::now();
|
const clock_t::time_point startTime = clock_t::now();
|
||||||
|
clock_t::time_point lastFrameTime = startTime;
|
||||||
while (mRunning)
|
while (mRunning)
|
||||||
{
|
{
|
||||||
std::optional<sdlpp::sdl_event_t> event;
|
std::optional<sdlpp::sdl_event_t> event;
|
||||||
@ -63,14 +63,20 @@ void Application::run(std::span<const char*> args)
|
|||||||
{
|
{
|
||||||
std::visit(mijin::Visitor{
|
std::visit(mijin::Visitor{
|
||||||
[&](const sdlpp::QuitEvent&) { mRunning = false; },
|
[&](const sdlpp::QuitEvent&) { mRunning = false; },
|
||||||
|
[&](const sdlpp::KeyboardEvent& event) { handleKeyboardEvent(event); },
|
||||||
|
[&](const sdlpp::MouseButtonEvent& event) { handleMouseButtonEvent(event); },
|
||||||
|
[&](const sdlpp::MouseMotionEvent& event) { handleMouseMotionEvent(event); },
|
||||||
|
[&](const sdlpp::GamepadButtonEvent& event) { handleGamepadButtonEvent(event); },
|
||||||
[](const auto&) {} // default handler
|
[](const auto&) {} // default handler
|
||||||
}, *event);
|
}, *event);
|
||||||
}
|
}
|
||||||
|
|
||||||
const clock_t::time_point frameTime = clock_t::now();
|
const clock_t::time_point frameTime = clock_t::now();
|
||||||
update({
|
update({
|
||||||
.secondsSinceStart = std::chrono::duration_cast<std::chrono::duration<float>>(frameTime - startTime).count()
|
.secondsSinceStart = std::chrono::duration_cast<std::chrono::duration<float>>(frameTime - startTime).count(),
|
||||||
|
.tickSeconds = std::chrono::duration_cast<std::chrono::duration<float>>(frameTime - lastFrameTime).count()
|
||||||
});
|
});
|
||||||
|
lastFrameTime = frameTime;
|
||||||
}
|
}
|
||||||
cleanup({});
|
cleanup({});
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ struct AppCleanupArgs
|
|||||||
struct AppUpdateArgs
|
struct AppUpdateArgs
|
||||||
{
|
{
|
||||||
float secondsSinceStart = 0.f;
|
float secondsSinceStart = 0.f;
|
||||||
|
float tickSeconds = 0.f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Application
|
class Application
|
||||||
@ -42,6 +43,10 @@ public:
|
|||||||
virtual void init(const AppInitArgs& args);
|
virtual void init(const AppInitArgs& args);
|
||||||
virtual void cleanup(const AppCleanupArgs& args);
|
virtual void cleanup(const AppCleanupArgs& args);
|
||||||
virtual void update(const AppUpdateArgs& args);
|
virtual void update(const AppUpdateArgs& args);
|
||||||
|
virtual void handleKeyboardEvent(const sdlpp::KeyboardEvent& /* event */) {}
|
||||||
|
virtual void handleMouseButtonEvent(const sdlpp::MouseButtonEvent& /* event */) {}
|
||||||
|
virtual void handleMouseMotionEvent(const sdlpp::MouseMotionEvent& /* event */) {}
|
||||||
|
virtual void handleGamepadButtonEvent(const sdlpp::GamepadButtonEvent& /* event */) {}
|
||||||
|
|
||||||
void run(std::span<const char*> args);
|
void run(std::span<const char*> args);
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "./2_triangle_with_texcoords/app.hpp"
|
#include "./2_triangle_with_texcoords/app.hpp"
|
||||||
#include "./3_textured_quad/app.hpp"
|
#include "./3_textured_quad/app.hpp"
|
||||||
#include "./4_textured_cube/app.hpp"
|
#include "./4_textured_cube/app.hpp"
|
||||||
|
#include "./5_input/app.hpp"
|
||||||
#include "./util/spdlog_wrapper.hpp"
|
#include "./util/spdlog_wrapper.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -34,7 +35,8 @@ const std::array APPS = {
|
|||||||
makeAppHelper<sdl_gpu_test::GreenTriangleApp>("green_triangle"),
|
makeAppHelper<sdl_gpu_test::GreenTriangleApp>("green_triangle"),
|
||||||
makeAppHelper<sdl_gpu_test::TriangleWithTexcoordsApp>("triangle_with_texcoords"),
|
makeAppHelper<sdl_gpu_test::TriangleWithTexcoordsApp>("triangle_with_texcoords"),
|
||||||
makeAppHelper<sdl_gpu_test::TexturedQuadApp>("textured_quad"),
|
makeAppHelper<sdl_gpu_test::TexturedQuadApp>("textured_quad"),
|
||||||
makeAppHelper<sdl_gpu_test::TexturedCubeApp>("textured_cube")
|
makeAppHelper<sdl_gpu_test::TexturedCubeApp>("textured_cube"),
|
||||||
|
makeAppHelper<sdl_gpu_test::InputApp>("input")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +47,7 @@ int main(int argc, char* argv[])
|
|||||||
return APP_ERROR;
|
return APP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_Init(0) != SDL_TRUE)
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD) != SDL_TRUE)
|
||||||
{
|
{
|
||||||
spdlog::error("Error initializing SDL.");
|
spdlog::error("Error initializing SDL.");
|
||||||
return APP_ERROR;
|
return APP_ERROR;
|
||||||
|
@ -26,8 +26,10 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
Base() noexcept = default;
|
Base() noexcept = default;
|
||||||
explicit Base(THandle* handle) noexcept : mHandle(handle) {}
|
explicit Base(THandle* handle) noexcept : mHandle(handle) {}
|
||||||
|
Base(const Base&) noexcept = default;
|
||||||
Base(Base&& other) noexcept : mHandle(std::exchange(other.mHandle, nullptr)) {}
|
Base(Base&& other) noexcept : mHandle(std::exchange(other.mHandle, nullptr)) {}
|
||||||
|
|
||||||
|
Base& operator=(const Base&) noexcept = default;
|
||||||
Base& operator=(Base&& other) noexcept
|
Base& operator=(Base&& other) noexcept
|
||||||
{
|
{
|
||||||
if (this != &other)
|
if (this != &other)
|
||||||
@ -38,15 +40,22 @@ protected:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Base(const Base&) = delete;
|
|
||||||
~Base() noexcept
|
~Base() noexcept
|
||||||
{
|
{
|
||||||
static_cast<TConcrete&>(*this).destroy();
|
static_cast<TConcrete&>(*this).destroy();
|
||||||
}
|
}
|
||||||
Base& operator=(const Base&) = delete;
|
|
||||||
auto operator<=>(const Base& other) const noexcept = default;
|
auto operator<=>(const Base& other) const noexcept = default;
|
||||||
|
|
||||||
operator THandle*() const noexcept { return mHandle; }
|
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>
|
template<typename THandle, typename TConcrete>
|
||||||
|
@ -11,6 +11,26 @@
|
|||||||
|
|
||||||
namespace sdlpp
|
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
|
struct Event
|
||||||
{
|
{
|
||||||
Uint64 timestamp;
|
Uint64 timestamp;
|
||||||
@ -18,17 +38,77 @@ struct Event
|
|||||||
template<typename TBase>
|
template<typename TBase>
|
||||||
explicit Event(const TBase& base) noexcept : timestamp(base.timestamp) {}
|
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;
|
||||||
|
SDL_bool down;
|
||||||
|
|
||||||
|
GamepadButtonEvent(const SDL_GamepadButtonEvent& base) noexcept : Event(base), which(base.which), button(base.button),
|
||||||
|
down(base.down)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct QuitEvent : Event
|
struct QuitEvent : Event
|
||||||
{
|
{
|
||||||
explicit QuitEvent(const SDL_QuitEvent& base) noexcept : Event(base) {}
|
explicit QuitEvent(const SDL_QuitEvent& base) noexcept : Event(base) {}
|
||||||
};
|
};
|
||||||
struct WindowEvent : Event
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
using sdl_event_t = std::variant<
|
using sdl_event_t = std::variant<
|
||||||
WindowEvent,
|
KeyboardEvent,
|
||||||
|
MouseButtonEvent,
|
||||||
|
MouseMotionEvent,
|
||||||
|
GamepadButtonEvent,
|
||||||
QuitEvent
|
QuitEvent
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@ -40,6 +120,17 @@ inline std::optional<sdl_event_t> pollEvent() noexcept
|
|||||||
{
|
{
|
||||||
switch (event.type)
|
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:
|
case SDL_EVENT_QUIT:
|
||||||
return QuitEvent(event.quit);
|
return QuitEvent(event.quit);
|
||||||
default:
|
default:
|
||||||
|
68
private/sdl_gpu_test/sdlpp/gamepad.hpp
Normal file
68
private/sdl_gpu_test/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)
|
20
private/sdl_gpu_test/sdlpp/keyboard.hpp
Normal file
20
private/sdl_gpu_test/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 SDL_bool> getKeyboardState() noexcept
|
||||||
|
{
|
||||||
|
int numkeys = 0;
|
||||||
|
const SDL_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)
|
Loading…
x
Reference in New Issue
Block a user