diff --git a/include/Helpers/SCollision.hpp b/include/Helpers/SCollision.hpp index e2ccb02..9db6f6e 100644 --- a/include/Helpers/SCollision.hpp +++ b/include/Helpers/SCollision.hpp @@ -84,6 +84,9 @@ namespace SCollision { SkRect get_sk_rect() const { return SkRect::MakeLTRB(static_cast(min.x()), static_cast(min.y()), static_cast(max.x()), static_cast(max.y())); } + SkIRect get_sk_irect() const { + return SkIRect::MakeLTRB(static_cast(min.x()), static_cast(min.y()), static_cast(max.x()), static_cast(max.y())); + } }; template class Circle { public: diff --git a/src/GUIStuff/Elements/NumberSlider.hpp b/src/GUIStuff/Elements/NumberSlider.hpp index 42c4b74..22e615a 100644 --- a/src/GUIStuff/Elements/NumberSlider.hpp +++ b/src/GUIStuff/Elements/NumberSlider.hpp @@ -53,7 +53,7 @@ template class NumberSlider : public Element { canvas->save(); canvas->translate(bb.min.x(), bb.min.y()); - float lerpTimeHover = smooth_two_way_time(dd.hoverAnimation, io.deltaTime, mouseHovering, io.theme->hoverExpandTime); + float lerpTimeHover = dd.hoverAnimation / io.theme->hoverExpandTime; static BezierEasing easeHeight(0.68, -1.55, 0.265, 2.55); diff --git a/src/GUIStuff/GUIManager.cpp b/src/GUIStuff/GUIManager.cpp index 75a643f..986e9ef 100644 --- a/src/GUIStuff/GUIManager.cpp +++ b/src/GUIStuff/GUIManager.cpp @@ -58,6 +58,34 @@ Clay_Dimensions GUIManager::clay_skia_measure_text(Clay_StringSlice str, Clay_Te return Clay_Dimensions(p->getMaxIntrinsicWidth(), p->getHeight()); } +void GUIManager::calculate_new_clip_rect(std::vector>& clipRectStack, std::optional>& clipRect, bool& clipNoDraw) { + if(clipRectStack.empty()) { + clipNoDraw = false; + clipRect = std::nullopt; + return; + } + SCollision::AABB toRet = clipRectStack.front(); + for(size_t i = 1; i < clipRectStack.size(); i++) { + if(!SCollision::collide(toRet, clipRectStack[i])) { + clipNoDraw = true; + clipRect = std::nullopt; + return; + } + toRet = toRet.get_intersection_between_aabbs(clipRectStack[i]); + } + clipNoDraw = false; + clipRect = toRet; +} + +void GUIManager::clip_rect_transform(SkCanvas* canvas, std::vector>& clipRectStack, std::optional>& clipRect, bool& clipNoDraw) { + canvas->save(); + canvas->scale(io.guiScaleMultiplier, io.guiScaleMultiplier); + canvas->translate(io.windowPos.x(), io.windowPos.y()); + calculate_new_clip_rect(clipRectStack, clipRect, clipNoDraw); + if(clipRect.has_value()) + canvas->clipIRect(clipRect.value().get_sk_irect()); +} + void GUIManager::draw(SkCanvas* c, bool skiaAA) { if(io.redrawSurface) { oldRenderCommandMap.clear(); @@ -66,19 +94,26 @@ void GUIManager::draw(SkCanvas* c, bool skiaAA) { update_invalidated_draw_area_from_layout(); if(io.redrawSurface || invalidDrawBB.has_value()) { SkCanvas* canvas = io.surface->getCanvas(); - canvas->save(); + + std::optional> clipRect; + std::vector> clipRectStack; + bool clipNoDraw = false; + if(!io.redrawSurface) - canvas->clipRect(invalidDrawBB.value().get_sk_rect()); + clipRectStack.emplace_back(invalidDrawBB.value()); + + clip_rect_transform(canvas, clipRectStack, clipRect, clipNoDraw); + canvas->clear({0.0f, 0.0f, 0.0f, 0.0f}); - canvas->scale(io.guiScaleMultiplier, io.guiScaleMultiplier); - canvas->translate(io.windowPos.x(), io.windowPos.y()); for(size_t i = 0; i < static_cast(renderCommands.length); i++) { Clay_RenderCommand* command = Clay_RenderCommandArray_Get(&renderCommands, i); Clay_BoundingBox bb = command->boundingBox; - if(!io.redrawSurface && command->commandType != CLAY_RENDER_COMMAND_TYPE_SCISSOR_START && command->commandType != CLAY_RENDER_COMMAND_TYPE_SCISSOR_END && !SCollision::collide(get_invalid_draw_bb_from_command(command), invalidDrawBB.value())) - continue; + if(command->commandType != CLAY_RENDER_COMMAND_TYPE_SCISSOR_START && command->commandType != CLAY_RENDER_COMMAND_TYPE_SCISSOR_END) { + if(clipNoDraw || (clipRect.has_value() && !SCollision::collide(get_invalid_draw_bb_from_command(command), clipRect.value()))) + continue; + } switch(command->commandType) { case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: { @@ -210,20 +245,26 @@ void GUIManager::draw(SkCanvas* c, bool skiaAA) { Clay_ClipRenderData* clip = &command->renderData.clip; if(!clip->horizontal) { bb.x = 0.0f; - bb.width = std::numeric_limits::max(); + bb.width = 30000.0f; } if(!clip->vertical) { bb.y = 0.0f; - bb.height = std::numeric_limits::max(); + bb.height = 30000.0f; } - canvas->save(); - SkRect clipRect = SkRect::MakeXYWH(bb.x - 1.0f, bb.y - 1.0f, bb.width + 1.0f, bb.height + 1.0f); - canvas->clipRect(clipRect); + bb.x -= 1; + bb.y -= 1; + bb.width += 1; + bb.height += 1; + canvas->restore(); + clipRectStack.emplace_back(clay_bounding_box_to_aabb(bb)); + clip_rect_transform(canvas, clipRectStack, clipRect, clipNoDraw); break; } case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END: { canvas->restore(); + clipRectStack.pop_back(); + clip_rect_transform(canvas, clipRectStack, clipRect, clipNoDraw); break; } case CLAY_RENDER_COMMAND_TYPE_CUSTOM: { @@ -265,9 +306,6 @@ SCollision::AABB GUIManager::get_invalid_draw_bb(SCollision::AABB bb.min.x() -= EXTRA_AREA + extraPadding.left; bb.max.x() += EXTRA_AREA + extraPadding.right; - bb.min *= io.guiScaleMultiplier; - bb.max *= io.guiScaleMultiplier; - return bb; } diff --git a/src/GUIStuff/GUIManager.hpp b/src/GUIStuff/GUIManager.hpp index 8654c1b..e7cf63e 100644 --- a/src/GUIStuff/GUIManager.hpp +++ b/src/GUIStuff/GUIManager.hpp @@ -146,6 +146,9 @@ class GUIManager { SCollision::AABB get_invalid_draw_bb_from_command(const Clay_RenderCommand* command); void update_invalidated_draw_area_from_layout(); + void calculate_new_clip_rect(std::vector>& clipRectStack, std::optional>& clipRect, bool& clipNoDraw); + void clip_rect_transform(SkCanvas* canvas, std::vector>& clipRectStack, std::optional>& clipRect, bool& clipNoDraw); + bool setToLayout; bool setToUpdateInvalidateDrawAreaFromLayout; bool cursorObstructed;