diff --git a/src/window/detail/input_sdl.hpp b/src/window/detail/input_sdl.hpp index 6e1f055c0..5b8c5bd03 100644 --- a/src/window/detail/input_sdl.hpp +++ b/src/window/detail/input_sdl.hpp @@ -3,7 +3,7 @@ #include "window/input.hpp" #include "window/window.hpp" -struct window_sdl; +class window_sdl; class input_sdl final : public Input { public: diff --git a/src/window/detail/window_sdl.cpp b/src/window/detail/window_sdl.cpp index 93af4f514..753245a18 100644 --- a/src/window/detail/window_sdl.cpp +++ b/src/window/detail/window_sdl.cpp @@ -86,7 +86,7 @@ static void GLAPIENTRY gl_message_callback( if (severity == GL_DEBUG_SEVERITY_NOTIFICATION) { return; } - if (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { + if constexpr (!ENGINE_DEBUG_BUILD && severity != GL_DEBUG_SEVERITY_HIGH) { return; } logger.warning() << "GL:" << gl_error_name(type) << ":" @@ -216,7 +216,7 @@ window_sdl::~window_sdl() { } void window_sdl::swapBuffers() const noexcept { - if (!SDL_GL_SwapWindow(window)) [[unlikely]] { + if (!SDL_GL_SwapWindow(window)) [[unlikely]] { // C++20 needed logger.error() << "Cant swap buffer: " << SDL_GetError(); } } @@ -240,7 +240,7 @@ void window_sdl::setShouldClose(bool flag) { } void window_sdl::setCursor(CursorShape shape) { - SDL_Cursor* cursor; + SDL_Cursor *cursor = nullptr; switch (shape) { case CursorShape::ARROW: cursor = SDL_CreateSystemCursor( @@ -293,8 +293,10 @@ void window_sdl::setCursor(CursorShape shape) { SDL_SystemCursor::SDL_SYSTEM_CURSOR_NOT_ALLOWED ); break; - SDL_SetCursor(cursor); - SDL_DestroyCursor(cursor); + } + if (cursor) { + SDL_SetCursor(cursor); + SDL_DestroyCursor(cursor); } } void window_sdl::toggleFullscreen() { @@ -337,10 +339,60 @@ void window_sdl::setIcon(const ImageData *image) { } void window_sdl::pushScissor(glm::vec4 area) { + if (scissorStack.empty()) { + glEnable(GL_SCISSOR_TEST); + } + scissorStack.push(scissorArea); + + area.z += glm::ceil(area.x); + area.w += glm::ceil(area.y); + + area.x = glm::max(area.x, scissorArea.x); + area.y = glm::max(area.y, scissorArea.y); + + area.z = glm::min(area.z, scissorArea.z); + area.w = glm::min(area.w, scissorArea.w); + + if (area.z < 0.0f || area.w < 0.0f) { + glScissor(0, 0, 0, 0); + } else { + glScissor( + area.x, + size.y - area.w, + std::max(0, static_cast(glm::ceil(area.z - area.x))), + std::max(0, static_cast(glm::ceil(area.w - area.y))) + ); + } + scissorArea = area; } -void window_sdl::popScissor() { -} + void window_sdl::resetScissor() { + scissorArea = glm::vec4(0.0f, 0.0f, size.x, size.y); + scissorStack = std::stack(); + glDisable(GL_SCISSOR_TEST); +} + +void window_sdl::popScissor() { + if (scissorStack.empty()) { + logger.warning() << "extra Window::popScissor call"; + return; + } + glm::vec4 area = scissorStack.top(); + scissorStack.pop(); + if (area.z < 0.0f || area.w < 0.0f) { + glScissor(0, 0, 0, 0); + } else { + glScissor( + area.x, + size.y - area.w, + std::max(0, static_cast(area.z - area.x)), + std::max(0, static_cast(area.w - area.y)) + ); + } + if (scissorStack.empty()) { + glDisable(GL_SCISSOR_TEST); + } + scissorArea = area; } double window_sdl::time() { diff --git a/src/window/detail/window_sdl.hpp b/src/window/detail/window_sdl.hpp index 523b23929..26cd4fd62 100644 --- a/src/window/detail/window_sdl.hpp +++ b/src/window/detail/window_sdl.hpp @@ -1,7 +1,10 @@ #include + +#include + #include "window/window.hpp" -struct SDL_Window; +struct SDL_Window; class window_sdl final : public Window { public: @@ -39,7 +42,7 @@ public: std::unique_ptr takeScreenshot() override; [[nodiscard]] bool isValid() const override; - [[nodiscard]] SDL_Window* getSdlWindow() const; + [[nodiscard]] SDL_Window *getSdlWindow() const; private: bool isSuccessfull = true; bool maximized = false; @@ -50,4 +53,7 @@ private: SDL_Window *window; SDL_GLContext context; + + std::stack scissorStack; + glm::vec4 scissorArea; }; \ No newline at end of file