WE BE RENDERING BABY
This commit is contained in:
@@ -20,6 +20,8 @@ set(SRC_FILES
|
||||
|
||||
"src/Graphics/Pipelines/MeshPipeline.cpp"
|
||||
|
||||
"src/Input/InputManager.cpp"
|
||||
|
||||
|
||||
"src/FS/AssetFS.cpp"
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <destrum/Graphics/GfxDevice.h>
|
||||
#include <destrum/Graphics/Renderer.h>
|
||||
#include <destrum/Input/InputManager.h>
|
||||
|
||||
|
||||
class App {
|
||||
@@ -41,6 +42,8 @@ protected:
|
||||
|
||||
MeshCache meshCache;
|
||||
|
||||
InputManager inputManager;
|
||||
|
||||
bool isRunning{false};
|
||||
bool gamePaused{false};
|
||||
|
||||
|
||||
@@ -118,6 +118,12 @@ public:
|
||||
void SetMovementSpeed(float speed) { m_movementSpeed = speed; }
|
||||
[[nodiscard]] float GetMovementSpeed() const { return m_movementSpeed; }
|
||||
|
||||
void SetRotation(float yawRadians, float pitchRadians);
|
||||
void SetRotation(const glm::vec2& yawPitchRadians);
|
||||
|
||||
float GetYaw() const { return m_yaw; }
|
||||
float GetPitch() const { return m_pitch; }
|
||||
|
||||
private:
|
||||
float fovAngle{90.f};
|
||||
float fov{tanf(glm::radians(fovAngle) / 2.f)};
|
||||
@@ -153,6 +159,9 @@ private:
|
||||
Frustum m_frustum{};
|
||||
|
||||
float m_movementSpeed{2.0f};
|
||||
|
||||
float m_yaw = 0.0f; // radians
|
||||
float m_pitch = 0.0f; // radians
|
||||
};
|
||||
|
||||
#endif //VCAMERA_H
|
||||
|
||||
@@ -33,7 +33,11 @@ public:
|
||||
void cleanup();
|
||||
|
||||
void drawMesh(MeshID id, const glm::mat4& transform, MaterialId materialId);
|
||||
const GPUImage& getDrawImage(const GfxDevice& gfx_device) const;
|
||||
|
||||
void resize(GfxDevice& gfxDevice, const glm::ivec2& newSize) {
|
||||
createDrawImage(gfxDevice, newSize, false);
|
||||
}
|
||||
|
||||
private:
|
||||
void createDrawImage(GfxDevice& gfxDevice, const glm::ivec2& drawImageSize, bool firstCreate);
|
||||
|
||||
92
destrum/include/destrum/Input/InputManager.h
Normal file
92
destrum/include/destrum/Input/InputManager.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef INPUTMANAGER_H
|
||||
#define INPUTMANAGER_H
|
||||
|
||||
#include <SDL.h>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class InputManager {
|
||||
public:
|
||||
// Call once at startup (optional, but convenient)
|
||||
void Init();
|
||||
|
||||
// Call at the start of every frame
|
||||
void BeginFrame();
|
||||
|
||||
// Feed SDL events into this (call for each SDL_PollEvent)
|
||||
void ProcessEvent(const SDL_Event& e);
|
||||
|
||||
// Call at end of frame if you want (not required)
|
||||
void EndFrame() {}
|
||||
|
||||
// ---- Queries ----
|
||||
bool IsKeyDown(SDL_Scancode sc) const; // held
|
||||
bool WasKeyPressed(SDL_Scancode sc) const; // pressed this frame
|
||||
bool WasKeyReleased(SDL_Scancode sc) const; // released this frame
|
||||
|
||||
bool IsMouseDown(Uint8 button) const; // held (SDL_BUTTON_LEFT etc.)
|
||||
bool WasMousePressed(Uint8 button) const; // pressed this frame
|
||||
bool WasMouseReleased(Uint8 button) const; // released this frame
|
||||
|
||||
// Mouse position (window space)
|
||||
int MouseX() const { return m_mouseX; }
|
||||
int MouseY() const { return m_mouseY; }
|
||||
int MouseDeltaX() const { return m_mouseDX; }
|
||||
int MouseDeltaY() const { return m_mouseDY; }
|
||||
|
||||
// Mouse wheel (accumulated per frame)
|
||||
int WheelX() const { return m_wheelX; }
|
||||
int WheelY() const { return m_wheelY; }
|
||||
|
||||
// ---- Text input ----
|
||||
void StartTextInput();
|
||||
void StopTextInput();
|
||||
bool IsTextInputActive() const { return m_textInputActive; }
|
||||
const std::string& GetTextInput() const { return m_textInput; } // captured this frame
|
||||
|
||||
// ---- Action mapping ----
|
||||
enum class Device { Keyboard, MouseButton, MouseWheel };
|
||||
enum class ButtonState { Down, Pressed, Released };
|
||||
|
||||
struct Binding {
|
||||
Device device;
|
||||
int code; // SDL_Scancode for keyboard, Uint8 for mouse button, wheel axis sign encoding
|
||||
// For MouseWheel: code = +1/-1 for Y, +2/-2 for X (simple encoding)
|
||||
};
|
||||
|
||||
void BindAction(const std::string& action, const Binding& binding);
|
||||
bool GetAction(const std::string& action, ButtonState state) const;
|
||||
|
||||
private:
|
||||
// Key states
|
||||
std::unordered_set<SDL_Scancode> m_keysDown;
|
||||
std::unordered_set<SDL_Scancode> m_keysPressed;
|
||||
std::unordered_set<SDL_Scancode> m_keysReleased;
|
||||
|
||||
// Mouse button states
|
||||
std::unordered_set<Uint8> m_mouseDown;
|
||||
std::unordered_set<Uint8> m_mousePressed;
|
||||
std::unordered_set<Uint8> m_mouseReleased;
|
||||
|
||||
// Mouse position + delta
|
||||
int m_mouseX = 0, m_mouseY = 0;
|
||||
int m_prevMouseX = 0, m_prevMouseY = 0;
|
||||
int m_mouseDX = 0, m_mouseDY = 0;
|
||||
|
||||
// Wheel (per-frame)
|
||||
int m_wheelX = 0, m_wheelY = 0;
|
||||
|
||||
// Text input (per-frame)
|
||||
bool m_textInputActive = false;
|
||||
std::string m_textInput;
|
||||
|
||||
// Action bindings
|
||||
std::unordered_map<std::string, std::vector<Binding>> m_bindings;
|
||||
|
||||
private:
|
||||
bool QueryBinding(const Binding& b, ButtonState state) const;
|
||||
};
|
||||
|
||||
#endif //INPUTMANAGER_H
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <destrum/FS/AssetFS.h>
|
||||
|
||||
#include "glm/gtx/transform.hpp"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
App::App(): renderer{meshCache} {
|
||||
@@ -49,6 +50,11 @@ void App::init(const AppParams& params) {
|
||||
float aspectRatio = static_cast<float>(params.renderSize.x) / static_cast<float>(params.renderSize.y);
|
||||
camera.setAspectRatio(aspectRatio);
|
||||
|
||||
//Look 90 deg to the right
|
||||
camera.SetRotation(glm::radians(glm::vec2(90.f, 0.f)));
|
||||
|
||||
inputManager.Init();
|
||||
|
||||
}
|
||||
|
||||
void App::run() {
|
||||
@@ -84,6 +90,7 @@ void App::run() {
|
||||
}
|
||||
|
||||
while (accumulator >= dt) {
|
||||
inputManager.BeginFrame();
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_QUIT) {
|
||||
@@ -99,28 +106,68 @@ void App::run() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
inputManager.ProcessEvent(event);
|
||||
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_W)) {
|
||||
camera.m_position += camera.GetForward() * dt * 5.f;
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_S)) {
|
||||
camera.m_position -= camera.GetForward() * dt * 5.f;
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_A)) {
|
||||
camera.m_position -= camera.GetRight() * dt * 5.f;
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_D)) {
|
||||
camera.m_position += camera.GetRight() * dt * 5.f;
|
||||
}
|
||||
|
||||
// rotation
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_LEFT)) {
|
||||
camera.SetRotation(camera.GetYaw() - glm::radians(90.f) * dt, camera.GetPitch());
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_RIGHT)) {
|
||||
camera.SetRotation(camera.GetYaw() + glm::radians(90.f) * dt, camera.GetPitch());
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_UP)) {
|
||||
camera.SetRotation(camera.GetYaw(), camera.GetPitch() + glm::radians(90.f) * dt);
|
||||
}
|
||||
if (inputManager.IsKeyDown(SDL_SCANCODE_DOWN)) {
|
||||
camera.SetRotation(camera.GetYaw(), camera.GetPitch() - glm::radians(90.f) * dt);
|
||||
}
|
||||
|
||||
camera.Update(dt);
|
||||
|
||||
}
|
||||
|
||||
if (gfxDevice.needsSwapchainRecreate()) {
|
||||
spdlog::info("Recreating swapchain to size: {}x{}", m_params.windowSize.x, m_params.windowSize.y);
|
||||
gfxDevice.recreateSwapchain(m_params.windowSize.x, m_params.windowSize.y);
|
||||
renderer.resize(gfxDevice, { m_params.windowSize.x, m_params.windowSize.y });
|
||||
float aspectRatio = float(m_params.windowSize.x) / float(m_params.windowSize.y);
|
||||
camera.setAspectRatio(aspectRatio);
|
||||
}
|
||||
|
||||
accumulator -= dt;
|
||||
}
|
||||
|
||||
if (!gfxDevice.needsSwapchainRecreate()) {
|
||||
glm::mat4 objMatrix = glm::mat4(1.f);
|
||||
objMatrix = glm::translate(objMatrix, glm::vec3(0.f, -3.0f, 0.f));
|
||||
renderer.beginDrawing(gfxDevice);
|
||||
renderer.drawMesh(testMeshID, glm::mat4(1.f), 0);
|
||||
renderer.drawMesh(testMeshID, objMatrix, 0);
|
||||
renderer.endDrawing();
|
||||
|
||||
|
||||
auto cmd = gfxDevice.beginFrame();
|
||||
const auto& drawImage = renderer.getDrawImage(gfxDevice);
|
||||
renderer.draw(cmd, gfxDevice, camera, GameRenderer::SceneData{
|
||||
camera, glm::vec3(0.1f), 0.5f, glm::vec3(0.5f), 0.01f
|
||||
});
|
||||
gfxDevice.endFrame(cmd, GPUImage{}, {});
|
||||
gfxDevice.endFrame(cmd, drawImage, {
|
||||
.clearColor = {{0.f, 0.f, 0.5f, 1.f}},
|
||||
.drawImageBlitRect = glm::ivec4{}}
|
||||
);
|
||||
}
|
||||
if (frameLimit) {
|
||||
// Delay to not overload the CPU
|
||||
|
||||
@@ -193,3 +193,28 @@ void Camera::Target(const glm::vec3& target) {
|
||||
m_viewMatrix = glm::lookAt(m_position, m_position + m_forward, m_up);
|
||||
m_invMatrix = glm::inverse(m_viewMatrix);
|
||||
}
|
||||
|
||||
void Camera::SetRotation(float yawRadians, float pitchRadians) {
|
||||
m_yaw = yawRadians;
|
||||
m_pitch = glm::clamp(
|
||||
pitchRadians,
|
||||
-glm::half_pi<float>() + 0.001f,
|
||||
glm::half_pi<float>() - 0.001f
|
||||
);
|
||||
|
||||
// Yaw around world Y, pitch around local Z (same convention you used)
|
||||
const glm::mat4 yawMatrix = glm::rotate(glm::mat4(1.0f), -m_yaw, glm::vec3(0, 1, 0));
|
||||
const glm::mat4 pitchMatrix = glm::rotate(glm::mat4(1.0f), m_pitch, glm::vec3(0, 0, 1));
|
||||
const glm::mat4 rotation = yawMatrix * pitchMatrix;
|
||||
|
||||
// Forward is +X in your camera space
|
||||
m_forward = glm::normalize(glm::vec3(rotation * glm::vec4(1, 0, 0, 0)));
|
||||
m_right = glm::normalize(glm::cross(m_forward, glm::vec3(0, 1, 0)));
|
||||
m_up = glm::normalize(glm::cross(m_right, m_forward));
|
||||
|
||||
m_useTarget = false; // rotation overrides target mode
|
||||
}
|
||||
|
||||
void Camera::SetRotation(const glm::vec2& yawPitchRadians) {
|
||||
SetRotation(yawPitchRadians.x, yawPitchRadians.y);
|
||||
}
|
||||
|
||||
@@ -160,49 +160,49 @@ void GfxDevice::endFrame(VkCommandBuffer cmd, const GPUImage& drawImage, const E
|
||||
auto swapchainLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
{
|
||||
// clear swapchain image
|
||||
VkImageSubresourceRange clearRange =
|
||||
vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
VkImageSubresourceRange clearRange =vkinit::imageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
vkutil::transitionImage(cmd, swapchainImage, swapchainLayout, VK_IMAGE_LAYOUT_GENERAL);
|
||||
swapchainLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
|
||||
|
||||
const auto clearValue = props.clearColor;
|
||||
vkCmdClearColorImage(cmd, swapchainImage, VK_IMAGE_LAYOUT_GENERAL, &clearValue, 1, &clearRange);
|
||||
}
|
||||
|
||||
// if (props.copyImageIntoSwapchain) {
|
||||
if (true) {
|
||||
// copy from draw image into swapchain
|
||||
// vkutil::transitionImage(
|
||||
// cmd,
|
||||
// drawImage.getImage(),
|
||||
// VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
// VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
vkutil::transitionImage(
|
||||
cmd,
|
||||
drawImage.image,
|
||||
VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||
vkutil::transitionImage(
|
||||
cmd, swapchainImage, swapchainLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
swapchainLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||
|
||||
// const auto filter = props.drawImageLinearBlit ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
||||
const auto filter = VK_FILTER_LINEAR;
|
||||
// // if (props.drawImageBlitRect != glm::ivec4{}) {
|
||||
// vkutil::copyImageToImage(
|
||||
// cmd,
|
||||
// drawImage.getImage(),
|
||||
// swapchainImage,
|
||||
// drawImage.getExtent2D(),
|
||||
// props.drawImageBlitRect.x,
|
||||
// props.drawImageBlitRect.y,
|
||||
// props.drawImageBlitRect.z,
|
||||
// props.drawImageBlitRect.w,
|
||||
// filter);
|
||||
// } else {
|
||||
// // will stretch image to swapchain
|
||||
// vkutil::copyImageToImage(
|
||||
// cmd,
|
||||
// drawImage.getImage(),
|
||||
// swapchainImage,
|
||||
// drawImage.getExtent2D(),
|
||||
// getSwapchainExtent(),
|
||||
// filter);
|
||||
// }
|
||||
auto filter = false ? VK_FILTER_LINEAR : VK_FILTER_NEAREST;
|
||||
filter = VK_FILTER_NEAREST;
|
||||
if (false) {
|
||||
vkutil::copyImageToImage(
|
||||
cmd,
|
||||
drawImage.image,
|
||||
swapchainImage,
|
||||
drawImage.getExtent2D(),
|
||||
props.drawImageBlitRect.x,
|
||||
props.drawImageBlitRect.y,
|
||||
props.drawImageBlitRect.z,
|
||||
props.drawImageBlitRect.w,
|
||||
filter);
|
||||
} else {
|
||||
// will stretch image to swapchain
|
||||
vkutil::copyImageToImage(
|
||||
cmd,
|
||||
drawImage.image,
|
||||
swapchainImage,
|
||||
drawImage.getExtent2D(),
|
||||
getSwapchainExtent(),
|
||||
filter);
|
||||
}
|
||||
}
|
||||
|
||||
// prepare for present
|
||||
vkutil::transitionImage(cmd, swapchainImage, swapchainLayout, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <destrum/Graphics/Util.h>
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
GameRenderer::GameRenderer(MeshCache& meshCache): meshCache{meshCache} {
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ void GameRenderer::draw(VkCommandBuffer cmd, GfxDevice& gfxDevice, const Camera&
|
||||
.colorImageView = drawImage.imageView,
|
||||
.colorImageClearValue = glm::vec4{0.f, 0.f, 0.f, 1.f},
|
||||
.depthImageView = depthImage.imageView,
|
||||
.depthImageClearValue = 0.f,
|
||||
.depthImageClearValue = 1.f,
|
||||
});
|
||||
|
||||
vkCmdBeginRendering(cmd, &renderInfo.renderingInfo);
|
||||
@@ -99,6 +101,10 @@ void GameRenderer::drawMesh(MeshID id, const glm::mat4& transform, MaterialId ma
|
||||
});
|
||||
}
|
||||
|
||||
const GPUImage& GameRenderer::getDrawImage(const GfxDevice& gfx_device) const {
|
||||
return gfx_device.getImage(drawImageId);
|
||||
}
|
||||
|
||||
void GameRenderer::createDrawImage(GfxDevice& gfxDevice,
|
||||
const glm::ivec2& drawImageSize,
|
||||
bool firstCreate)
|
||||
@@ -144,6 +150,7 @@ void GameRenderer::createDrawImage(GfxDevice& gfxDevice,
|
||||
};
|
||||
|
||||
depthImageId = gfxDevice.createImage(createInfo, "depth image", nullptr, depthImageId);
|
||||
spdlog::info("Created depth image with id {}", depthImageId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ void Swapchain::createSwapchain(GfxDevice* gfxDevice, VkFormat format, std::uint
|
||||
|
||||
// TODO: if re-creation of swapchain is supported, don't forget to call
|
||||
// vkutil::initSwapchainViews here.
|
||||
|
||||
extent = m_swapchain.extent;
|
||||
}
|
||||
|
||||
void Swapchain::recreateSwapchain(const GfxDevice& gfxDevice, VkFormat format, std::uint32_t width, std::uint32_t height, bool vSync) {
|
||||
@@ -98,6 +100,7 @@ void Swapchain::recreateSwapchain(const GfxDevice& gfxDevice, VkFormat format, s
|
||||
imageViews = m_swapchain.get_image_views().value();
|
||||
|
||||
dirty = false;
|
||||
extent = m_swapchain.extent;
|
||||
}
|
||||
|
||||
void Swapchain::cleanup() {
|
||||
|
||||
148
destrum/src/Input/InputManager.cpp
Normal file
148
destrum/src/Input/InputManager.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#include <destrum/Input/InputManager.h>
|
||||
|
||||
void InputManager::Init() {
|
||||
// Nothing mandatory here. You can also enable relative mouse mode, etc.
|
||||
// SDL_SetRelativeMouseMode(SDL_TRUE);
|
||||
}
|
||||
|
||||
void InputManager::BeginFrame() {
|
||||
m_keysPressed.clear();
|
||||
m_keysReleased.clear();
|
||||
m_mousePressed.clear();
|
||||
m_mouseReleased.clear();
|
||||
|
||||
m_wheelX = 0;
|
||||
m_wheelY = 0;
|
||||
|
||||
m_textInput.clear();
|
||||
|
||||
// Update mouse delta based on last known position
|
||||
m_mouseDX = m_mouseX - m_prevMouseX;
|
||||
m_mouseDY = m_mouseY - m_prevMouseY;
|
||||
m_prevMouseX = m_mouseX;
|
||||
m_prevMouseY = m_mouseY;
|
||||
}
|
||||
|
||||
void InputManager::ProcessEvent(const SDL_Event& e) {
|
||||
switch (e.type) {
|
||||
case SDL_KEYDOWN: {
|
||||
if (e.key.repeat) break; // avoid repeat spam for "Pressed"
|
||||
SDL_Scancode sc = e.key.keysym.scancode;
|
||||
m_keysDown.insert(sc);
|
||||
m_keysPressed.insert(sc);
|
||||
} break;
|
||||
|
||||
case SDL_KEYUP: {
|
||||
SDL_Scancode sc = e.key.keysym.scancode;
|
||||
m_keysDown.erase(sc);
|
||||
m_keysReleased.insert(sc);
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN: {
|
||||
Uint8 b = e.button.button;
|
||||
m_mouseDown.insert(b);
|
||||
m_mousePressed.insert(b);
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP: {
|
||||
Uint8 b = e.button.button;
|
||||
m_mouseDown.erase(b);
|
||||
m_mouseReleased.insert(b);
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEMOTION: {
|
||||
m_mouseX = e.motion.x;
|
||||
m_mouseY = e.motion.y;
|
||||
} break;
|
||||
|
||||
case SDL_MOUSEWHEEL: {
|
||||
// Accumulate wheel per frame
|
||||
m_wheelX += e.wheel.x;
|
||||
m_wheelY += e.wheel.y;
|
||||
} break;
|
||||
|
||||
case SDL_TEXTINPUT: {
|
||||
// text typed this frame
|
||||
m_textInput += e.text.text;
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
bool InputManager::IsKeyDown(SDL_Scancode sc) const {
|
||||
return m_keysDown.find(sc) != m_keysDown.end();
|
||||
}
|
||||
bool InputManager::WasKeyPressed(SDL_Scancode sc) const {
|
||||
return m_keysPressed.find(sc) != m_keysPressed.end();
|
||||
}
|
||||
bool InputManager::WasKeyReleased(SDL_Scancode sc) const {
|
||||
return m_keysReleased.find(sc) != m_keysReleased.end();
|
||||
}
|
||||
|
||||
bool InputManager::IsMouseDown(Uint8 button) const {
|
||||
return m_mouseDown.find(button) != m_mouseDown.end();
|
||||
}
|
||||
bool InputManager::WasMousePressed(Uint8 button) const {
|
||||
return m_mousePressed.find(button) != m_mousePressed.end();
|
||||
}
|
||||
bool InputManager::WasMouseReleased(Uint8 button) const {
|
||||
return m_mouseReleased.find(button) != m_mouseReleased.end();
|
||||
}
|
||||
|
||||
void InputManager::StartTextInput() {
|
||||
if (!m_textInputActive) {
|
||||
SDL_StartTextInput();
|
||||
m_textInputActive = true;
|
||||
}
|
||||
}
|
||||
void InputManager::StopTextInput() {
|
||||
if (m_textInputActive) {
|
||||
SDL_StopTextInput();
|
||||
m_textInputActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
void InputManager::BindAction(const std::string& action, const Binding& binding) {
|
||||
m_bindings[action].push_back(binding);
|
||||
}
|
||||
|
||||
bool InputManager::QueryBinding(const Binding& b, ButtonState state) const {
|
||||
switch (b.device) {
|
||||
case Device::Keyboard: {
|
||||
auto sc = static_cast<SDL_Scancode>(b.code);
|
||||
if (state == ButtonState::Down) return IsKeyDown(sc);
|
||||
if (state == ButtonState::Pressed) return WasKeyPressed(sc);
|
||||
if (state == ButtonState::Released) return WasKeyReleased(sc);
|
||||
} break;
|
||||
|
||||
case Device::MouseButton: {
|
||||
auto mb = static_cast<Uint8>(b.code);
|
||||
if (state == ButtonState::Down) return IsMouseDown(mb);
|
||||
if (state == ButtonState::Pressed) return WasMousePressed(mb);
|
||||
if (state == ButtonState::Released) return WasMouseReleased(mb);
|
||||
} break;
|
||||
|
||||
case Device::MouseWheel: {
|
||||
// Encoding:
|
||||
// +1/-1 => wheel Y (up/down), +2/-2 => wheel X (right/left)
|
||||
const int c = b.code;
|
||||
if (state != ButtonState::Pressed) return false; // wheel is "impulse"
|
||||
if (c == 1) return m_wheelY > 0;
|
||||
if (c == -1) return m_wheelY < 0;
|
||||
if (c == 2) return m_wheelX > 0;
|
||||
if (c == -2) return m_wheelX < 0;
|
||||
} break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputManager::GetAction(const std::string& action, ButtonState state) const {
|
||||
auto it = m_bindings.find(action);
|
||||
if (it == m_bindings.end()) return false;
|
||||
|
||||
for (const auto& b : it->second) {
|
||||
if (QueryBinding(b, state)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
2
destrum/third_party/CMakeLists.txt
vendored
2
destrum/third_party/CMakeLists.txt
vendored
@@ -15,7 +15,7 @@ add_subdirectory(sdl)
|
||||
|
||||
add_subdirectory(vk-bootstrap)
|
||||
if (MSVC)
|
||||
target_compile_definitions(vk-bootstrap PRIVATE $<$<CONFIG:Debug>:_ITERATOR_DEBUG_LEVEL=1>)
|
||||
# target_compile_definitions(vk-bootstrap PRIVATE $<$<CONFIG:Debug>:_ITERATOR_DEBUG_LEVEL=1>)
|
||||
endif()
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set_target_properties(vk-bootstrap PROPERTIES
|
||||
|
||||
Reference in New Issue
Block a user