mirror of
https://github.com/bailwillharr/engine.git
synced 2024-09-20 20:41:19 +00:00
Fix window resize in wayland
This commit is contained in:
parent
f9422346bd
commit
5b60668f71
2
dependencies/SDL
vendored
2
dependencies/SDL
vendored
@ -1 +1 @@
|
||||
Subproject commit 2f4a7bbcedaaf49c8bf87e34081120a6a49a0d26
|
||||
Subproject commit 859844eae358447be8d66e6da59b6fb3df0ed778
|
2
dependencies/VulkanMemoryAllocator
vendored
2
dependencies/VulkanMemoryAllocator
vendored
@ -1 +1 @@
|
||||
Subproject commit c351692490513cdb0e5a2c925aaf7ea4a9b672f4
|
||||
Subproject commit a6bfc237255a6bac1513f7c1ebde6d8aed6b5191
|
@ -23,7 +23,7 @@ class GFXDevice {
|
||||
void ShutdownImguiBackend();
|
||||
void CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData* draw_data);
|
||||
|
||||
gfx::DrawBuffer* BeginRender();
|
||||
gfx::DrawBuffer* BeginRender(bool window_resized);
|
||||
|
||||
/* - draw_buffer MUST be a valid pointer returned by BeginRender().
|
||||
- draw_buffer is invalid after this function has been called. */
|
||||
@ -105,4 +105,4 @@ class GFXDevice {
|
||||
std::unique_ptr<Impl> pimpl;
|
||||
};
|
||||
|
||||
} // namespace engine
|
||||
} // namespace engine
|
||||
|
@ -35,10 +35,8 @@ class Renderer : private ApplicationComponent {
|
||||
|
||||
~Renderer();
|
||||
|
||||
void PreRender(bool window_is_resized, glm::mat4 camera_transform);
|
||||
|
||||
// staticList can be nullptr to render nothing
|
||||
void Render(const RenderList* static_list, const RenderList* dynamic_list, const std::vector<Line>& debug_lines);
|
||||
void Render(bool window_is_resized, glm::mat4 camera_transform, const RenderList* static_list, const RenderList* dynamic_list, const std::vector<Line>& debug_lines);
|
||||
|
||||
// getters
|
||||
|
||||
@ -118,4 +116,4 @@ class Renderer : private ApplicationComponent {
|
||||
void DrawRenderList(gfx::DrawBuffer* draw_buffer, const RenderList& render_list);
|
||||
};
|
||||
|
||||
} // namespace engine
|
||||
} // namespace engine
|
||||
|
@ -413,8 +413,7 @@ void Application::GameLoop()
|
||||
static_list = mesh_render_system->GetStaticRenderList();
|
||||
dynamic_list = mesh_render_system->GetDynamicRenderList();
|
||||
}
|
||||
renderer_->PreRender(window()->GetWindowResized(), camera_transform);
|
||||
renderer_->Render(static_list, dynamic_list, debug_lines);
|
||||
renderer_->Render(window()->GetWindowResized(), camera_transform, static_list, dynamic_list, debug_lines);
|
||||
debug_lines.clear(); // gets remade every frame :0
|
||||
|
||||
/* poll events */
|
||||
|
@ -67,7 +67,7 @@ static void check_vk_result(VkResult code) { checkVulkanError(code, -1); }
|
||||
|
||||
namespace engine {
|
||||
|
||||
static constexpr uint32_t FRAMES_IN_FLIGHT = 2; // This improved FPS by 5x! (on Intel IGPU)
|
||||
static constexpr uint32_t FRAMES_IN_FLIGHT = 2; // This improved FPS by 5x! (on Intel IGPU)
|
||||
|
||||
static constexpr size_t PUSH_CONSTANT_MAX_SIZE = 128; // bytes
|
||||
static constexpr VkIndexType INDEX_TYPE = VK_INDEX_TYPE_UINT32;
|
||||
@ -621,7 +621,7 @@ void GFXDevice::CmdRenderImguiDrawData(gfx::DrawBuffer* draw_buffer, ImDrawData*
|
||||
ImGui_ImplVulkan_RenderDrawData(draw_data, draw_buffer->frameData.drawBuf);
|
||||
}
|
||||
|
||||
gfx::DrawBuffer* GFXDevice::BeginRender()
|
||||
gfx::DrawBuffer* GFXDevice::BeginRender(bool window_resized)
|
||||
{
|
||||
VkResult res;
|
||||
|
||||
@ -703,6 +703,12 @@ gfx::DrawBuffer* GFXDevice::BeginRender()
|
||||
|
||||
uint32_t swapchainImageIndex;
|
||||
|
||||
if (window_resized && pimpl->FRAMECOUNT != 0) { // resize flag is true on first frame
|
||||
pimpl->swapchainIsOutOfDate = true;
|
||||
LOG_TRACE("Window resized, framecount == {}", pimpl->FRAMECOUNT);
|
||||
}
|
||||
|
||||
// THIS FUNCTION BLOCKS UNTIL AN IMAGE IS AVAILABLE (it waits for vsync)
|
||||
do {
|
||||
if (pimpl->swapchainIsOutOfDate) {
|
||||
// re-create swapchain
|
||||
@ -714,7 +720,8 @@ gfx::DrawBuffer* GFXDevice::BeginRender()
|
||||
res = vkAcquireNextImageKHR(pimpl->device.device, pimpl->swapchain.swapchain, 1000000000LL, frameData.presentSemaphore, VK_NULL_HANDLE,
|
||||
&swapchainImageIndex);
|
||||
if (res != VK_SUBOPTIMAL_KHR && res != VK_ERROR_OUT_OF_DATE_KHR) VKCHECK(res);
|
||||
if (res == VK_SUCCESS) pimpl->swapchainIsOutOfDate = false;
|
||||
if (res == VK_ERROR_OUT_OF_DATE_KHR) pimpl->swapchainIsOutOfDate = true;
|
||||
if (res == VK_SUCCESS || res == VK_SUBOPTIMAL_KHR) pimpl->swapchainIsOutOfDate = false;
|
||||
} while (pimpl->swapchainIsOutOfDate);
|
||||
|
||||
/* record command buffer */
|
||||
@ -940,7 +947,7 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
|
||||
std::vector<VkSemaphore> waitSemaphores{};
|
||||
std::vector<VkPipelineStageFlags> waitDstStageMasks{};
|
||||
|
||||
waitSemaphores.push_back(drawBuffer->frameData.presentSemaphore); // wait for image from 2nd last frame to be presented so it can be rendered to again
|
||||
waitSemaphores.push_back(drawBuffer->frameData.presentSemaphore); // wait for image from 2nd last frame to be presented so it can be rendered to again
|
||||
waitDstStageMasks.push_back(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
|
||||
waitSemaphores.push_back(drawBuffer->frameData.transferSemaphore); // wait for uniform buffer copies to complete
|
||||
waitDstStageMasks.push_back(VK_PIPELINE_STAGE_VERTEX_SHADER_BIT);
|
||||
@ -970,8 +977,8 @@ void GFXDevice::FinishRender(gfx::DrawBuffer* drawBuffer)
|
||||
.pImageIndices = &swapchainImageIndex,
|
||||
.pResults = nullptr};
|
||||
res = vkQueuePresentKHR(pimpl->device.queues.presentQueue, &presentInfo);
|
||||
if (res == VK_SUBOPTIMAL_KHR || res == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
// flag to re-create the swapchain before next render
|
||||
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||
// flag to re-create the swapchain next frame
|
||||
pimpl->swapchainIsOutOfDate = true;
|
||||
}
|
||||
else if (res != VK_SUCCESS)
|
||||
@ -1351,9 +1358,9 @@ gfx::Pipeline* GFXDevice::CreatePipeline(const gfx::PipelineInfo& info)
|
||||
if (info.depth_attachment_only) {
|
||||
// use depth bias if only rendering to a depth attachment
|
||||
rasterizer.depthBiasEnable = VK_TRUE;
|
||||
rasterizer.depthBiasConstantFactor = 2.0f;//1.25f;
|
||||
rasterizer.depthBiasConstantFactor = 2.0f; // 1.25f;
|
||||
rasterizer.depthBiasClamp = 0.0f;
|
||||
rasterizer.depthBiasSlopeFactor = 3.5f;//1.75f;
|
||||
rasterizer.depthBiasSlopeFactor = 3.5f; // 1.75f;
|
||||
}
|
||||
else {
|
||||
rasterizer.depthBiasEnable = VK_FALSE;
|
||||
@ -1486,7 +1493,7 @@ gfx::DescriptorSetLayout* GFXDevice::CreateDescriptorSetLayout(const std::vector
|
||||
uint32_t i = 0;
|
||||
for (const auto& binding : bindings) {
|
||||
auto& vulkanBinding = vulkanBindings.emplace_back();
|
||||
vulkanBinding.binding = i; // This should be as low as possible to avoid wasting memory
|
||||
vulkanBinding.binding = i; // This should be as low as possible to avoid wasting memory
|
||||
vulkanBinding.descriptorType = converters::getDescriptorType(binding.descriptor_type);
|
||||
vulkanBinding.descriptorCount = 1; // if > 1, accessible as an array in the shader
|
||||
vulkanBinding.stageFlags = converters::getShaderStageFlags(binding.stage_flags);
|
||||
@ -1929,7 +1936,7 @@ gfx::Image* GFXDevice::CreateImage(uint32_t w, uint32_t h, gfx::ImageFormat inpu
|
||||
VkImageMemoryBarrier2 afterBlitBarrier{};
|
||||
afterBlitBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2;
|
||||
afterBlitBarrier.srcStageMask = VK_PIPELINE_STAGE_2_BLIT_BIT;
|
||||
afterBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; // previous mip level was just READ from in a BLIT
|
||||
afterBlitBarrier.srcAccessMask = VK_ACCESS_2_TRANSFER_READ_BIT; // previous mip level was just READ from in a BLIT
|
||||
afterBlitBarrier.dstStageMask = VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT;
|
||||
afterBlitBarrier.dstAccessMask = VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_2_SHADER_READ_BIT; // it will next be sampled in a frag shader
|
||||
afterBlitBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
|
||||
|
@ -249,8 +249,9 @@ Renderer::~Renderer()
|
||||
device_->DestroyDescriptorSetLayout(global_uniform.layout);
|
||||
}
|
||||
|
||||
void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform)
|
||||
void Renderer::Render(bool window_is_resized, glm::mat4 camera_transform, const RenderList* static_list, const RenderList* dynamic_list, const std::vector<Line>& debug_lines)
|
||||
{
|
||||
|
||||
if (window_is_resized) {
|
||||
uint32_t w, h;
|
||||
device_->GetViewportSize(&w, &h);
|
||||
@ -265,10 +266,6 @@ void Renderer::PreRender(bool window_is_resized, glm::mat4 camera_transform)
|
||||
const glm::mat4 view_matrix = glm::inverse(camera_transform);
|
||||
frame_uniform.uniform_buffer_data.data = view_matrix;
|
||||
device_->WriteUniformBuffer(frame_uniform.uniform_buffer, 0, sizeof(frame_uniform.uniform_buffer_data), &frame_uniform.uniform_buffer_data);
|
||||
}
|
||||
|
||||
void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_list, const std::vector<Line>& debug_lines)
|
||||
{
|
||||
|
||||
if (rendering_started == false) {
|
||||
// render to shadow map
|
||||
@ -292,7 +289,7 @@ void Renderer::Render(const RenderList* static_list, const RenderList* dynamic_l
|
||||
|
||||
last_bound_pipeline_ = nullptr;
|
||||
|
||||
gfx::DrawBuffer* draw_buffer = device_->BeginRender();
|
||||
gfx::DrawBuffer* draw_buffer = device_->BeginRender(window_is_resized);
|
||||
|
||||
if (static_list) {
|
||||
if (!static_list->empty()) {
|
||||
|
@ -239,7 +239,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||
}
|
||||
if (material.pbrMetallicRoughness.metallicFactor != 1.0 || material.pbrMetallicRoughness.roughnessFactor != 1.0) {
|
||||
if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) {
|
||||
LOG_WARN("Material {} contains a metallic and/or roughness multiplier which isn't supported yet.", material.name);
|
||||
LOG_WARN("Material {} contains a metallic and/or roughness multiplier which isn't supported yet.", material.name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,7 +271,8 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||
}
|
||||
|
||||
// occlusion roughness metallic
|
||||
materials.back()->SetOcclusionRoughnessMetallicTexture(scene.app()->GetResource<Texture>("builtin.white")); // default ao = 1.0, rough = 1.0, metal = 1.0
|
||||
materials.back()->SetOcclusionRoughnessMetallicTexture(
|
||||
scene.app()->GetResource<Texture>("builtin.white")); // default ao = 1.0, rough = 1.0, metal = 1.0
|
||||
if (material.pbrMetallicRoughness.metallicRoughnessTexture.index != -1) {
|
||||
if (material.pbrMetallicRoughness.metallicRoughnessTexture.texCoord == 0) {
|
||||
LOG_DEBUG("Setting occlusion roughness metallic texture!");
|
||||
@ -283,7 +284,8 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||
}
|
||||
else {
|
||||
LOG_DEBUG("Creating occlusion roughness metallic texture...");
|
||||
const std::vector<double> mr_values{1.0f /* no AO */, material.pbrMetallicRoughness.roughnessFactor, material.pbrMetallicRoughness.metallicFactor, 1.0f};
|
||||
const std::vector<double> mr_values{1.0f /* no AO */, material.pbrMetallicRoughness.roughnessFactor, material.pbrMetallicRoughness.metallicFactor,
|
||||
1.0f};
|
||||
Color mr(mr_values);
|
||||
if (metal_rough_textures.contains(mr) == false) {
|
||||
const uint8_t pixel[4] = {mr.r, mr.g, mr.b, mr.a};
|
||||
@ -302,7 +304,8 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||
if (material.occlusionTexture.index != -1) {
|
||||
if (material.occlusionTexture.texCoord == 0) {
|
||||
if (material.occlusionTexture.index != material.pbrMetallicRoughness.metallicRoughnessTexture.index) {
|
||||
throw std::runtime_error(std::string("Material ") + material.name + std::string(" has an ambient occlusion texture different to the metal-rough texture."));
|
||||
throw std::runtime_error(std::string("Material ") + material.name +
|
||||
std::string(" has an ambient occlusion texture different to the metal-rough texture."));
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -518,8 +521,8 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||
assert(num_unq_vertices >= 0);
|
||||
|
||||
// get new vertices into the vector
|
||||
vertices.resize(num_unq_vertices);
|
||||
for (size_t i = 0; i < num_unq_vertices; ++i) {
|
||||
vertices.resize(static_cast<size_t>(num_unq_vertices));
|
||||
for (size_t i = 0; i < static_cast<size_t>(num_unq_vertices); ++i) {
|
||||
vertices[i] = vertex_data_out[i];
|
||||
}
|
||||
|
||||
@ -578,6 +581,7 @@ engine::Entity LoadGLTF(Scene& scene, const std::string& path, bool isStatic)
|
||||
|
||||
// glTF uses the Y-up convention so the parent object must be rotated to Z-up
|
||||
const Entity parent = scene.CreateEntity(name, 0, glm::vec3{}, glm::quat{glm::one_over_root_two<float>(), glm::one_over_root_two<float>(), 0.0f, 0.0f});
|
||||
scene.GetTransform(parent)->is_static = isStatic;
|
||||
|
||||
std::vector<Entity> entities(model.nodes.size(), 0);
|
||||
std::function<void(Entity, const tg::Node&)> generateEntities = [&](Entity parent_entity, const tg::Node& node) -> void {
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include <cstdio> // snprintf for vma
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
|
@ -19,8 +19,6 @@ namespace engine {
|
||||
sc->device = info.device;
|
||||
sc->allocator = info.allocator;
|
||||
|
||||
LOG_DEBUG("Recreating swapchain!\n");
|
||||
|
||||
// get surface caps and features
|
||||
VkResult res;
|
||||
res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(info.physicalDevice, info.surface, &sc->surfaceCapabilities);
|
||||
@ -249,6 +247,8 @@ namespace engine {
|
||||
|
||||
}
|
||||
|
||||
LOG_INFO("Recreating swapchain! w: {} h: {}\n", sc->extent.width, sc->extent.height);
|
||||
|
||||
}
|
||||
|
||||
void destroySwapchain(const Swapchain& sc)
|
||||
|
865
src/window.cpp
865
src/window.cpp
@ -5,494 +5,387 @@
|
||||
|
||||
#include <imgui/imgui_impl_sdl2.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
static const uint64_t BILLION = 1000000000;
|
||||
|
||||
namespace engine {
|
||||
|
||||
Window::Window(const std::string& title, bool resizable, bool fullscreen)
|
||||
: title_(title), resizable_(resizable), fullscreen_(fullscreen)
|
||||
{
|
||||
|
||||
// init SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
const std::string errMsg("Unable to initialise SDL: " + std::string(SDL_GetError()));
|
||||
throw std::runtime_error(errMsg);
|
||||
}
|
||||
|
||||
counter_freq_ = SDL_GetPerformanceFrequency();
|
||||
start_time_ = GetNanos();
|
||||
last_frame_stamp_ = start_time_ - 1;
|
||||
avg_fps_start_ = start_time_;
|
||||
|
||||
Uint32 windowFlags = SDL_WINDOW_SHOWN;
|
||||
|
||||
// use Vulkan 1.3
|
||||
windowFlags |= SDL_WINDOW_VULKAN;
|
||||
|
||||
if (resizable_) {
|
||||
windowFlags |= SDL_WINDOW_RESIZABLE;
|
||||
}
|
||||
|
||||
if (fullscreen_) {
|
||||
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
// create the window
|
||||
handle_ = SDL_CreateWindow(
|
||||
title_.c_str(),
|
||||
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
|
||||
static_cast<int>(win_size_.x),
|
||||
static_cast<int>(win_size_.y),
|
||||
windowFlags);
|
||||
if (handle_ == NULL) {
|
||||
SDL_Quit();
|
||||
throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError()));
|
||||
}
|
||||
|
||||
const int WINDOWED_MIN_WIDTH = 640;
|
||||
const int WINDOWED_MIN_HEIGHT = 480;
|
||||
SDL_SetWindowMinimumSize(handle_, WINDOWED_MIN_WIDTH, WINDOWED_MIN_HEIGHT);
|
||||
|
||||
// get window size
|
||||
int winWidth, winHeight;
|
||||
SDL_GetWindowSize(handle_, &winWidth, &winHeight);
|
||||
|
||||
OnResize(winWidth, winHeight);
|
||||
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
SDL_DestroyWindow(handle_);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
// private methods
|
||||
|
||||
void Window::OnResize(Sint32 width, Sint32 height)
|
||||
{
|
||||
// get window size
|
||||
win_size_.x = static_cast<int>(width);
|
||||
win_size_.y = static_cast<int>(height);
|
||||
|
||||
just_resized_ = true;
|
||||
}
|
||||
|
||||
void Window::ResetInputDeltas()
|
||||
{
|
||||
just_resized_ = false;
|
||||
|
||||
keyboard_.deltas.fill(ButtonDelta::kSame);
|
||||
|
||||
mouse_.deltas.fill(ButtonDelta::kSame);
|
||||
mouse_.dx = 0;
|
||||
mouse_.dy = 0;
|
||||
mouse_.xscroll = 0.0f;
|
||||
mouse_.yscroll = 0.0f;
|
||||
}
|
||||
|
||||
// TODO event methods (like callbacks)
|
||||
|
||||
void Window::OnWindowEvent(SDL_WindowEvent& e)
|
||||
{
|
||||
|
||||
switch (e.event) {
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
OnResize(e.data1, e.data2);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
keyboard_focus_ = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
keyboard_focus_ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnKeyEvent(SDL_KeyboardEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.WantCaptureKeyboard) {
|
||||
keyboard_.deltas.fill(ButtonDelta::kSame);
|
||||
}
|
||||
else {
|
||||
bool keyWasDown = keyboard_.keys[e.keysym.scancode];
|
||||
bool keyIsDown = (e.state == SDL_PRESSED);
|
||||
keyboard_.keys[e.keysym.scancode] = keyIsDown;
|
||||
if (keyIsDown != keyWasDown) { // (if key was pressed or released)
|
||||
keyboard_.deltas[e.keysym.scancode] = keyIsDown ? ButtonDelta::kPressed : ButtonDelta::kReleased;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnMouseButtonEvent(SDL_MouseButtonEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.WantCaptureMouse) {
|
||||
mouse_.deltas.fill(ButtonDelta::kSame);
|
||||
}
|
||||
else {
|
||||
enum inputs::MouseButton button = inputs::MouseButton::M_INVALID;
|
||||
switch (e.button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
button = inputs::MouseButton::M_LEFT;
|
||||
break;
|
||||
case SDL_BUTTON_MIDDLE:
|
||||
button = inputs::MouseButton::M_MIDDLE;
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
button = inputs::MouseButton::M_RIGHT;
|
||||
break;
|
||||
case SDL_BUTTON_X1:
|
||||
button = inputs::MouseButton::M_X1;
|
||||
break;
|
||||
case SDL_BUTTON_X2:
|
||||
button = inputs::MouseButton::M_X2;
|
||||
break;
|
||||
}
|
||||
int buttonIndex = static_cast<int>(button);
|
||||
bool buttonWasDown = mouse_.buttons.at(buttonIndex);
|
||||
bool buttonIsDown = (e.state == SDL_PRESSED);
|
||||
mouse_.buttons.at(buttonIndex) = buttonIsDown;
|
||||
if (buttonIsDown != buttonWasDown) { // (if button was pressed or released)
|
||||
// only sets delta if it hasn't already been set this frame (to detect very fast presses)
|
||||
if (mouse_.deltas[buttonIndex] == ButtonDelta::kSame) {
|
||||
mouse_.deltas[buttonIndex] = buttonIsDown ? ButtonDelta::kPressed : ButtonDelta::kReleased;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnMouseMotionEvent(SDL_MouseMotionEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.WantCaptureMouse) {
|
||||
mouse_.dx = 0;
|
||||
mouse_.dy = 0;
|
||||
}
|
||||
else {
|
||||
mouse_.x = e.x;
|
||||
mouse_.y = e.y;
|
||||
mouse_.dx = e.xrel;
|
||||
mouse_.dy = e.yrel;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnMouseWheelEvent(SDL_MouseWheelEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (!io.WantCaptureMouse) {
|
||||
if (e.direction == SDL_MOUSEWHEEL_NORMAL) {
|
||||
mouse_.xscroll = e.preciseX;
|
||||
mouse_.yscroll = e.preciseY;
|
||||
}
|
||||
else { // flipped
|
||||
mouse_.xscroll = -e.preciseX;
|
||||
mouse_.yscroll = -e.preciseY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public methods
|
||||
|
||||
SDL_Window* Window::GetHandle() const
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
std::string Window::GetTitle() const
|
||||
{
|
||||
return title_;
|
||||
}
|
||||
|
||||
void Window::GetInputAndEvents()
|
||||
{
|
||||
|
||||
frames_++;
|
||||
uint64_t currentFrameStamp = GetNanos();
|
||||
last_frame_time_ = currentFrameStamp - last_frame_stamp_;
|
||||
last_frame_stamp_ = currentFrameStamp;
|
||||
|
||||
ResetInputDeltas();
|
||||
|
||||
// loop through all available events
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e)) {
|
||||
ImGui_ImplSDL2_ProcessEvent(&e);
|
||||
switch (e.type) {
|
||||
|
||||
case SDL_QUIT:
|
||||
SetCloseFlag();
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
OnWindowEvent(e.window);
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN: // FALL THROUGH
|
||||
case SDL_KEYUP:
|
||||
OnKeyEvent(e.key);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN: // FALL THROUGH
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
OnMouseButtonEvent(e.button);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
OnMouseMotionEvent(e.motion);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEWHEEL:
|
||||
OnMouseWheelEvent(e.wheel);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Window::SetTitle(std::string title)
|
||||
{
|
||||
SDL_SetWindowTitle(handle_, title.c_str());
|
||||
}
|
||||
|
||||
bool Window::GetWindowResized() const
|
||||
{
|
||||
return just_resized_;
|
||||
}
|
||||
|
||||
void Window::SetResizedFlag()
|
||||
{
|
||||
just_resized_ = true;
|
||||
}
|
||||
|
||||
void Window::Show()
|
||||
{
|
||||
SDL_ShowWindow(handle_);
|
||||
}
|
||||
|
||||
void Window::Hide()
|
||||
{
|
||||
SDL_HideWindow(handle_);
|
||||
}
|
||||
|
||||
void Window::Focus()
|
||||
{
|
||||
SDL_RaiseWindow(handle_);
|
||||
keyboard_focus_ = true;
|
||||
}
|
||||
|
||||
bool Window::HasFocus() const
|
||||
{
|
||||
return keyboard_focus_;
|
||||
}
|
||||
|
||||
void Window::SetCloseFlag()
|
||||
{
|
||||
should_close_ = true;
|
||||
}
|
||||
|
||||
bool Window::IsRunning() const
|
||||
{
|
||||
return !should_close_;
|
||||
}
|
||||
|
||||
void Window::SetFullscreen(bool fullscreen, bool exclusive)
|
||||
{
|
||||
|
||||
if (resizable_) {
|
||||
|
||||
SDL_DisplayMode mode;
|
||||
SDL_GetDesktopDisplayMode(SDL_GetWindowDisplayIndex(handle_), &mode);
|
||||
SDL_SetWindowDisplayMode(handle_, &mode);
|
||||
|
||||
if (SDL_SetWindowFullscreen(handle_, fullscreen ? (exclusive ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP) : 0) != 0) {
|
||||
throw std::runtime_error("Unable to set window to fullscreen/windowed");
|
||||
}
|
||||
fullscreen_ = fullscreen;
|
||||
if (fullscreen) {
|
||||
|
||||
int width, height;
|
||||
SDL_GetWindowSize(handle_, &width, &height);
|
||||
OnResize(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::ToggleFullscreen()
|
||||
{
|
||||
SetFullscreen(!fullscreen_, true);
|
||||
}
|
||||
|
||||
bool Window::IsFullscreen() const
|
||||
{
|
||||
return fullscreen_;
|
||||
}
|
||||
|
||||
bool Window::SetRelativeMouseMode(bool enabled)
|
||||
{
|
||||
mouse_.captured = enabled;
|
||||
int code = SDL_SetRelativeMouseMode(static_cast<SDL_bool>(enabled));
|
||||
if (code != 0) {
|
||||
throw std::runtime_error("Unable to set relative mouse mode");
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::MouseCaptured()
|
||||
{
|
||||
return mouse_.captured;
|
||||
}
|
||||
|
||||
// getting input
|
||||
|
||||
bool Window::GetKey(inputs::Key key) const
|
||||
{
|
||||
return keyboard_.keys[static_cast<int>(key)];
|
||||
}
|
||||
|
||||
bool Window::GetKeyPress(inputs::Key key) const
|
||||
{
|
||||
return keyboard_.deltas[static_cast<int>(key)] == ButtonDelta::kPressed;
|
||||
}
|
||||
|
||||
bool Window::GetKeyRelease(inputs::Key key) const
|
||||
{
|
||||
return keyboard_.deltas[static_cast<int>(key)] == ButtonDelta::kReleased;
|
||||
}
|
||||
|
||||
// TODO mouse input
|
||||
|
||||
bool Window::GetButton(inputs::MouseButton button) const
|
||||
{
|
||||
return mouse_.buttons[static_cast<int>(button)];
|
||||
}
|
||||
|
||||
bool Window::GetButtonPress(inputs::MouseButton button) const
|
||||
{
|
||||
return mouse_.deltas[static_cast<int>(button)] == ButtonDelta::kPressed;
|
||||
}
|
||||
|
||||
bool Window::GetButtonRelease(inputs::MouseButton button) const
|
||||
{
|
||||
return mouse_.deltas[static_cast<int>(button)] == ButtonDelta::kReleased;
|
||||
}
|
||||
|
||||
int Window::GetMouseX() const
|
||||
{
|
||||
return static_cast<int>(mouse_.x);
|
||||
}
|
||||
|
||||
int Window::GetMouseY() const
|
||||
{
|
||||
return static_cast<int>(mouse_.y);
|
||||
}
|
||||
|
||||
float Window::GetMouseNormX() const
|
||||
{
|
||||
return ((float)mouse_.x * 2.0f / (float)win_size_.x) - 1.0f;
|
||||
}
|
||||
|
||||
float Window::GetMouseNormY() const
|
||||
{
|
||||
return ((float)mouse_.y * -2.0f / (float)win_size_.y) + 1.0f;
|
||||
}
|
||||
|
||||
int Window::GetMouseDX() const
|
||||
{
|
||||
return static_cast<int>(mouse_.dx);
|
||||
}
|
||||
|
||||
int Window::GetMouseDY() const
|
||||
{
|
||||
return static_cast<int>(mouse_.dy);
|
||||
}
|
||||
|
||||
float Window::GetMouseScrollX() const
|
||||
{
|
||||
return mouse_.xscroll;
|
||||
}
|
||||
|
||||
float Window::GetMouseScrollY() const
|
||||
{
|
||||
return mouse_.yscroll;
|
||||
}
|
||||
|
||||
// TODO game pad
|
||||
|
||||
// get timer value
|
||||
uint64_t Window::GetNanos() const
|
||||
{
|
||||
uint64_t count;
|
||||
|
||||
count = SDL_GetPerformanceCounter();
|
||||
if (counter_freq_ == BILLION) {
|
||||
return count;
|
||||
}
|
||||
else {
|
||||
return count * (BILLION / counter_freq_);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Window::GetLastFrameStamp() const
|
||||
{
|
||||
return last_frame_stamp_;
|
||||
}
|
||||
|
||||
uint64_t Window::GetFrameCount() const
|
||||
{
|
||||
return frames_;
|
||||
}
|
||||
|
||||
uint64_t Window::GetStartTime() const
|
||||
{
|
||||
return start_time_;
|
||||
}
|
||||
|
||||
float Window::dt() const
|
||||
{
|
||||
return (float)last_frame_time_ / (float)BILLION;
|
||||
}
|
||||
|
||||
uint64_t Window::GetFPS() const
|
||||
{
|
||||
if (last_frame_time_ == 0) return 0;
|
||||
return BILLION / last_frame_time_;
|
||||
}
|
||||
|
||||
uint64_t Window::GetAvgFPS() const
|
||||
{
|
||||
uint64_t delta_t = GetNanos() - avg_fps_start_;
|
||||
if (delta_t == 0) return 0;
|
||||
return BILLION * (frames_ - avg_fps_start_count_) / delta_t;
|
||||
}
|
||||
|
||||
void Window::ResetAvgFPS()
|
||||
{
|
||||
avg_fps_start_ = GetNanos();
|
||||
avg_fps_start_count_ = GetFrameCount();
|
||||
}
|
||||
|
||||
bool Window::InfoBox(const std::string& title, const std::string& msg)
|
||||
{
|
||||
if (IsFullscreen() == false) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, title.c_str(), msg.c_str(), handle_);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* STATIC METHODS */
|
||||
|
||||
// Display an error message box
|
||||
void Window::ErrorBox(const std::string& message)
|
||||
{
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Game Error", message.c_str(), NULL);
|
||||
}
|
||||
|
||||
Window::Window(const std::string& title, bool resizable, bool fullscreen) : title_(title), resizable_(resizable), fullscreen_(fullscreen)
|
||||
{
|
||||
|
||||
// init SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
|
||||
const std::string errMsg("Unable to initialise SDL: " + std::string(SDL_GetError()));
|
||||
throw std::runtime_error(errMsg);
|
||||
}
|
||||
|
||||
counter_freq_ = SDL_GetPerformanceFrequency();
|
||||
start_time_ = GetNanos();
|
||||
last_frame_stamp_ = start_time_ - 1;
|
||||
avg_fps_start_ = start_time_;
|
||||
|
||||
Uint32 windowFlags = SDL_WINDOW_SHOWN;
|
||||
|
||||
// use Vulkan 1.3
|
||||
windowFlags |= SDL_WINDOW_VULKAN;
|
||||
|
||||
if (resizable_) {
|
||||
windowFlags |= SDL_WINDOW_RESIZABLE;
|
||||
}
|
||||
|
||||
if (fullscreen_) {
|
||||
windowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
||||
// create the window
|
||||
handle_ = SDL_CreateWindow(title_.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, static_cast<int>(win_size_.x), static_cast<int>(win_size_.y),
|
||||
windowFlags);
|
||||
if (handle_ == NULL) {
|
||||
SDL_Quit();
|
||||
throw std::runtime_error("Unable to create window: " + std::string(SDL_GetError()));
|
||||
}
|
||||
|
||||
const int WINDOWED_MIN_WIDTH = 640;
|
||||
const int WINDOWED_MIN_HEIGHT = 480;
|
||||
SDL_SetWindowMinimumSize(handle_, WINDOWED_MIN_WIDTH, WINDOWED_MIN_HEIGHT);
|
||||
|
||||
// get window size
|
||||
int winWidth, winHeight;
|
||||
SDL_GetWindowSize(handle_, &winWidth, &winHeight);
|
||||
|
||||
OnResize(winWidth, winHeight);
|
||||
}
|
||||
|
||||
Window::~Window()
|
||||
{
|
||||
SDL_DestroyWindow(handle_);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
// private methods
|
||||
|
||||
void Window::OnResize(Sint32 width, Sint32 height)
|
||||
{
|
||||
// get window size
|
||||
win_size_.x = static_cast<int>(width);
|
||||
win_size_.y = static_cast<int>(height);
|
||||
|
||||
just_resized_ = true;
|
||||
}
|
||||
|
||||
void Window::ResetInputDeltas()
|
||||
{
|
||||
just_resized_ = false;
|
||||
|
||||
keyboard_.deltas.fill(ButtonDelta::kSame);
|
||||
|
||||
mouse_.deltas.fill(ButtonDelta::kSame);
|
||||
mouse_.dx = 0;
|
||||
mouse_.dy = 0;
|
||||
mouse_.xscroll = 0.0f;
|
||||
mouse_.yscroll = 0.0f;
|
||||
}
|
||||
|
||||
// TODO event methods (like callbacks)
|
||||
|
||||
void Window::OnWindowEvent(SDL_WindowEvent& e)
|
||||
{
|
||||
switch (e.event) {
|
||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||
LOG_TRACE("SDL size changed event!");
|
||||
OnResize(e.data1, e.data2);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
keyboard_focus_ = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
keyboard_focus_ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnKeyEvent(SDL_KeyboardEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.WantCaptureKeyboard) {
|
||||
keyboard_.deltas.fill(ButtonDelta::kSame);
|
||||
}
|
||||
else {
|
||||
bool keyWasDown = keyboard_.keys[e.keysym.scancode];
|
||||
bool keyIsDown = (e.state == SDL_PRESSED);
|
||||
keyboard_.keys[e.keysym.scancode] = keyIsDown;
|
||||
if (keyIsDown != keyWasDown) { // (if key was pressed or released)
|
||||
keyboard_.deltas[e.keysym.scancode] = keyIsDown ? ButtonDelta::kPressed : ButtonDelta::kReleased;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnMouseButtonEvent(SDL_MouseButtonEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.WantCaptureMouse) {
|
||||
mouse_.deltas.fill(ButtonDelta::kSame);
|
||||
}
|
||||
else {
|
||||
enum inputs::MouseButton button = inputs::MouseButton::M_INVALID;
|
||||
switch (e.button) {
|
||||
case SDL_BUTTON_LEFT:
|
||||
button = inputs::MouseButton::M_LEFT;
|
||||
break;
|
||||
case SDL_BUTTON_MIDDLE:
|
||||
button = inputs::MouseButton::M_MIDDLE;
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
button = inputs::MouseButton::M_RIGHT;
|
||||
break;
|
||||
case SDL_BUTTON_X1:
|
||||
button = inputs::MouseButton::M_X1;
|
||||
break;
|
||||
case SDL_BUTTON_X2:
|
||||
button = inputs::MouseButton::M_X2;
|
||||
break;
|
||||
}
|
||||
int buttonIndex = static_cast<int>(button);
|
||||
bool buttonWasDown = mouse_.buttons.at(buttonIndex);
|
||||
bool buttonIsDown = (e.state == SDL_PRESSED);
|
||||
mouse_.buttons.at(buttonIndex) = buttonIsDown;
|
||||
if (buttonIsDown != buttonWasDown) { // (if button was pressed or released)
|
||||
// only sets delta if it hasn't already been set this frame (to detect very fast presses)
|
||||
if (mouse_.deltas[buttonIndex] == ButtonDelta::kSame) {
|
||||
mouse_.deltas[buttonIndex] = buttonIsDown ? ButtonDelta::kPressed : ButtonDelta::kReleased;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnMouseMotionEvent(SDL_MouseMotionEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.WantCaptureMouse) {
|
||||
mouse_.dx = 0;
|
||||
mouse_.dy = 0;
|
||||
}
|
||||
else {
|
||||
mouse_.x = e.x;
|
||||
mouse_.y = e.y;
|
||||
mouse_.dx = e.xrel;
|
||||
mouse_.dy = e.yrel;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::OnMouseWheelEvent(SDL_MouseWheelEvent& e)
|
||||
{
|
||||
const ImGuiIO& io = ImGui::GetIO();
|
||||
if (!io.WantCaptureMouse) {
|
||||
if (e.direction == SDL_MOUSEWHEEL_NORMAL) {
|
||||
mouse_.xscroll = e.preciseX;
|
||||
mouse_.yscroll = e.preciseY;
|
||||
}
|
||||
else { // flipped
|
||||
mouse_.xscroll = -e.preciseX;
|
||||
mouse_.yscroll = -e.preciseY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public methods
|
||||
|
||||
SDL_Window* Window::GetHandle() const { return handle_; }
|
||||
|
||||
std::string Window::GetTitle() const { return title_; }
|
||||
|
||||
void Window::GetInputAndEvents()
|
||||
{
|
||||
|
||||
frames_++;
|
||||
uint64_t currentFrameStamp = GetNanos();
|
||||
last_frame_time_ = currentFrameStamp - last_frame_stamp_;
|
||||
last_frame_stamp_ = currentFrameStamp;
|
||||
|
||||
ResetInputDeltas();
|
||||
|
||||
// loop through all available events
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e)) {
|
||||
ImGui_ImplSDL2_ProcessEvent(&e);
|
||||
switch (e.type) {
|
||||
|
||||
case SDL_QUIT:
|
||||
SetCloseFlag();
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT:
|
||||
OnWindowEvent(e.window);
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN: // FALL THROUGH
|
||||
case SDL_KEYUP:
|
||||
OnKeyEvent(e.key);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN: // FALL THROUGH
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
OnMouseButtonEvent(e.button);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEMOTION:
|
||||
OnMouseMotionEvent(e.motion);
|
||||
break;
|
||||
|
||||
case SDL_MOUSEWHEEL:
|
||||
OnMouseWheelEvent(e.wheel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Window::SetTitle(std::string title) { SDL_SetWindowTitle(handle_, title.c_str()); }
|
||||
|
||||
bool Window::GetWindowResized() const { return just_resized_; }
|
||||
|
||||
void Window::SetResizedFlag() { just_resized_ = true; }
|
||||
|
||||
void Window::Show() { SDL_ShowWindow(handle_); }
|
||||
|
||||
void Window::Hide() { SDL_HideWindow(handle_); }
|
||||
|
||||
void Window::Focus()
|
||||
{
|
||||
SDL_RaiseWindow(handle_);
|
||||
keyboard_focus_ = true;
|
||||
}
|
||||
|
||||
bool Window::HasFocus() const { return keyboard_focus_; }
|
||||
|
||||
void Window::SetCloseFlag() { should_close_ = true; }
|
||||
|
||||
bool Window::IsRunning() const { return !should_close_; }
|
||||
|
||||
void Window::SetFullscreen(bool fullscreen, bool exclusive)
|
||||
{
|
||||
|
||||
if (resizable_) {
|
||||
|
||||
SDL_DisplayMode mode;
|
||||
SDL_GetDesktopDisplayMode(SDL_GetWindowDisplayIndex(handle_), &mode);
|
||||
SDL_SetWindowDisplayMode(handle_, &mode);
|
||||
|
||||
// this will only resize the window at the end of the frame
|
||||
if (SDL_SetWindowFullscreen(handle_, fullscreen ? (exclusive ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP) : 0) != 0) {
|
||||
throw std::runtime_error("Unable to set window to fullscreen/windowed");
|
||||
}
|
||||
fullscreen_ = fullscreen;
|
||||
}
|
||||
}
|
||||
|
||||
void Window::ToggleFullscreen() { SetFullscreen(!fullscreen_, true); }
|
||||
|
||||
bool Window::IsFullscreen() const { return fullscreen_; }
|
||||
|
||||
bool Window::SetRelativeMouseMode(bool enabled)
|
||||
{
|
||||
mouse_.captured = enabled;
|
||||
int code = SDL_SetRelativeMouseMode(static_cast<SDL_bool>(enabled));
|
||||
if (code != 0) {
|
||||
throw std::runtime_error("Unable to set relative mouse mode");
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::MouseCaptured() { return mouse_.captured; }
|
||||
|
||||
// getting input
|
||||
|
||||
bool Window::GetKey(inputs::Key key) const { return keyboard_.keys[static_cast<int>(key)]; }
|
||||
|
||||
bool Window::GetKeyPress(inputs::Key key) const { return keyboard_.deltas[static_cast<int>(key)] == ButtonDelta::kPressed; }
|
||||
|
||||
bool Window::GetKeyRelease(inputs::Key key) const { return keyboard_.deltas[static_cast<int>(key)] == ButtonDelta::kReleased; }
|
||||
|
||||
// TODO mouse input
|
||||
|
||||
bool Window::GetButton(inputs::MouseButton button) const { return mouse_.buttons[static_cast<int>(button)]; }
|
||||
|
||||
bool Window::GetButtonPress(inputs::MouseButton button) const { return mouse_.deltas[static_cast<int>(button)] == ButtonDelta::kPressed; }
|
||||
|
||||
bool Window::GetButtonRelease(inputs::MouseButton button) const { return mouse_.deltas[static_cast<int>(button)] == ButtonDelta::kReleased; }
|
||||
|
||||
int Window::GetMouseX() const { return static_cast<int>(mouse_.x); }
|
||||
|
||||
int Window::GetMouseY() const { return static_cast<int>(mouse_.y); }
|
||||
|
||||
float Window::GetMouseNormX() const { return ((float)mouse_.x * 2.0f / (float)win_size_.x) - 1.0f; }
|
||||
|
||||
float Window::GetMouseNormY() const { return ((float)mouse_.y * -2.0f / (float)win_size_.y) + 1.0f; }
|
||||
|
||||
int Window::GetMouseDX() const { return static_cast<int>(mouse_.dx); }
|
||||
|
||||
int Window::GetMouseDY() const { return static_cast<int>(mouse_.dy); }
|
||||
|
||||
float Window::GetMouseScrollX() const { return mouse_.xscroll; }
|
||||
|
||||
float Window::GetMouseScrollY() const { return mouse_.yscroll; }
|
||||
|
||||
// TODO game pad
|
||||
|
||||
// get timer value
|
||||
uint64_t Window::GetNanos() const
|
||||
{
|
||||
uint64_t count;
|
||||
|
||||
count = SDL_GetPerformanceCounter();
|
||||
if (counter_freq_ == BILLION) {
|
||||
return count;
|
||||
}
|
||||
else {
|
||||
return count * (BILLION / counter_freq_);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t Window::GetLastFrameStamp() const { return last_frame_stamp_; }
|
||||
|
||||
uint64_t Window::GetFrameCount() const { return frames_; }
|
||||
|
||||
uint64_t Window::GetStartTime() const { return start_time_; }
|
||||
|
||||
float Window::dt() const { return (float)last_frame_time_ / (float)BILLION; }
|
||||
|
||||
uint64_t Window::GetFPS() const
|
||||
{
|
||||
if (last_frame_time_ == 0) return 0;
|
||||
return BILLION / last_frame_time_;
|
||||
}
|
||||
|
||||
uint64_t Window::GetAvgFPS() const
|
||||
{
|
||||
uint64_t delta_t = GetNanos() - avg_fps_start_;
|
||||
if (delta_t == 0) return 0;
|
||||
return BILLION * (frames_ - avg_fps_start_count_) / delta_t;
|
||||
}
|
||||
|
||||
void Window::ResetAvgFPS()
|
||||
{
|
||||
avg_fps_start_ = GetNanos();
|
||||
avg_fps_start_count_ = GetFrameCount();
|
||||
}
|
||||
|
||||
bool Window::InfoBox(const std::string& title, const std::string& msg)
|
||||
{
|
||||
if (IsFullscreen() == false) {
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, title.c_str(), msg.c_str(), handle_);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* STATIC METHODS */
|
||||
|
||||
// Display an error message box
|
||||
void Window::ErrorBox(const std::string& message) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Game Error", message.c_str(), NULL); }
|
||||
|
||||
} // namespace engine
|
||||
|
@ -64,7 +64,7 @@ void CameraControllerSystem::OnUpdate(float ts)
|
||||
|
||||
// jumping
|
||||
if (scene_->app()->input_manager()->GetButtonPress("jump") && (c->grounded || c->noclip)) {
|
||||
c->vel.z += CameraControllerComponent::kJumpHeight; // m/s
|
||||
c->vel.z += CameraControllerComponent::kJumpVelocity; // m/s
|
||||
}
|
||||
|
||||
// update position with velocity:
|
||||
|
@ -16,7 +16,7 @@ struct CameraControllerComponent {
|
||||
static constexpr float kSpeedForwardBack = 4.0f;
|
||||
static constexpr float kSpeedStrafe = 4.0f;
|
||||
static constexpr float kSprintMultiplier = 2.0f;
|
||||
static constexpr float kJumpHeight = /*4.4f*/ 8.8f;
|
||||
static constexpr float kJumpVelocity = 4.4f;
|
||||
|
||||
// collision
|
||||
static constexpr float kPlayerHeight = 2.0f; // 71.0f * 25.4f / 1000.0f;
|
||||
@ -25,6 +25,7 @@ struct CameraControllerComponent {
|
||||
static constexpr size_t kNumHorizontalRays = 20;
|
||||
|
||||
static constexpr float kGravAccel = -9.81f;
|
||||
// static constexpr float kGravAccel = -1.625f; // moon gravity
|
||||
static constexpr float kMaxDistanceFromOrigin = 200.0f;
|
||||
|
||||
bool noclip = false;
|
||||
@ -48,4 +49,4 @@ class CameraControllerSystem : public engine::System {
|
||||
CameraControllerComponent* c = nullptr;
|
||||
|
||||
engine::Scene* next_scene_ = nullptr;
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user