From 6352e8e3196f78388b6c771073f9e03eaa612673 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Tue, 20 Jun 2023 14:33:09 +1000 Subject: everything everywhere all at once --- source/frontend/StarChatBubbleSeparation.cpp | 74 ++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 source/frontend/StarChatBubbleSeparation.cpp (limited to 'source/frontend/StarChatBubbleSeparation.cpp') diff --git a/source/frontend/StarChatBubbleSeparation.cpp b/source/frontend/StarChatBubbleSeparation.cpp new file mode 100644 index 0000000..568ca37 --- /dev/null +++ b/source/frontend/StarChatBubbleSeparation.cpp @@ -0,0 +1,74 @@ +#include "StarChatBubbleSeparation.hpp" + +namespace Star { + +bool compareLeft(RectF const& a, RectF const& b) { + return a.xMin() < b.xMin(); +} + +bool compareRight(RectF const& a, RectF const& b) { + return a.xMax() > b.xMax(); +} + +bool compareOverlapLeft(RectF const& newBox, RectF const& fixedBox) { + return newBox.xMax() < fixedBox.xMin(); +} + +bool compareOverlapRight(RectF const& newBox, RectF const& fixedBox) { + return newBox.xMin() > fixedBox.xMax(); +} + +template +void appendHorizontalOverlaps(List& overlaps, + List const& boxes, + List::iterator leftBound, + Compare compare, + RectF const& box) { + auto i = leftBound; + if (i == boxes.begin()) + return; + --i; + while (!compare(box, *i)) { + overlaps.append(*i); + if (i == boxes.begin()) + return; + --i; + } +} + +RectF separateBubble(List& sortedLeftEdges, List& sortedRightEdges, RectF box) { + // We have to maintain two lists of boxes: one sorted by the left edges and + // one + // by the right edges. This is because boxes can be different sizes, and + // if we only check one edge, appendHorizontalOverlaps can miss any boxes + // whose projections onto the X axis entirely contain other boxes'. + auto leftOverlapBound = upper_bound(sortedLeftEdges.begin(), sortedLeftEdges.end(), box, compareOverlapLeft); + auto rightOverlapBound = upper_bound(sortedRightEdges.begin(), sortedRightEdges.end(), box, compareOverlapRight); + + List horizontalOverlaps; + appendHorizontalOverlaps(horizontalOverlaps, sortedLeftEdges, leftOverlapBound, compareOverlapRight, box); + appendHorizontalOverlaps(horizontalOverlaps, sortedRightEdges, rightOverlapBound, compareOverlapLeft, box); + + // horizontalOverlaps now consists of the boxes that (when projected onto the + // X axis) + // overlap with 'box'. + + while (true) { + // While box is overlapping any other boxes, raise its Y value. + List overlappingBoxes = + horizontalOverlaps.filtered([&box](RectF const& overlapper) { return box.intersects(overlapper, false); }); + if (overlappingBoxes.empty()) + break; + RectF overlapBoundBox = fold(overlappingBoxes, box, [](RectF const& a, RectF const& b) { return a.combined(b); }); + auto height = box.height(); + box.setYMin(overlapBoundBox.yMax()); + box.setYMax(box.yMin() + height); + } + + sortedLeftEdges.insertSorted(box, compareLeft); + sortedRightEdges.insertSorted(box, compareRight); + + return box; +} + +} -- cgit v1.2.3