Files
jasper/deps/nostalgia/src/olympic/studio/modlib/include/studio/selectiontracker.hpp

137 lines
3.0 KiB
C++

#pragma once
#include <imgui.h>
#include <ox/std/math.hpp>
#include <ox/std/point.hpp>
#include <ox/std/size.hpp>
#include <ox/std/typetraits.hpp>
namespace studio {
struct Selection {
ox::Point a, b;
constexpr Selection() noexcept = default;
constexpr Selection(ox::Point const&pA, ox::Point const&pB) noexcept: a(pA), b(pB) {}
[[nodiscard]]
constexpr ox::Size size() const noexcept {
return {b.x - a.x, b.y - a.y};
}
[[nodiscard]]
constexpr bool contains(ox::Point const&pt) const noexcept {
return a.x <= pt.x && a.y <= pt.y
&& b.x >= pt.x && b.y >= pt.y;
}
};
constexpr auto iterateSelection(studio::Selection const&sel, auto const&cb) {
constexpr auto retErr = ox::is_same_v<decltype(cb(0, 0)), ox::Error>;
for (auto x = sel.a.x; x <= sel.b.x; ++x) {
for (auto y = sel.a.y; y <= sel.b.y; ++y) {
if constexpr(retErr) {
oxReturnError(cb(x, y));
} else {
cb(x, y);
}
}
}
if constexpr(retErr) {
return ox::Error{};
}
};
constexpr auto iterateSelectionRows(studio::Selection const&sel, auto const&cb) {
constexpr auto retErr = ox::is_same_v<decltype(cb(0, 0)), ox::Error>;
for (auto y = sel.a.y; y <= sel.b.y; ++y) {
for (auto x = sel.a.x; x <= sel.b.x; ++x) {
if constexpr(retErr) {
oxReturnError(cb(x, y));
} else {
cb(x, y);
}
}
}
if constexpr(retErr) {
return ox::Error{};
}
};
class SelectionTracker {
private:
bool m_selectionOngoing{};
ox::Point m_pointA;
ox::Point m_pointB;
public:
[[nodiscard]]
constexpr bool selectionOngoing() const noexcept {
return m_selectionOngoing;
}
constexpr void startSelection(ox::Point cursor) noexcept {
m_pointA = cursor;
m_pointB = cursor;
m_selectionOngoing = true;
}
/**
*
* @param cursor
* @param allowStart
* @return true if changed, false otherwise
*/
constexpr bool updateCursorPoint(ox::Point cursor, bool allowStart = true) noexcept {
auto changed = false;
if (!m_selectionOngoing && allowStart) {
m_pointA = cursor;
m_selectionOngoing = true;
}
if (m_selectionOngoing) {
m_pointB = cursor;
changed = true;
}
return changed;
}
constexpr void updateCursorPoint(ox::Vec2 cursor, bool allowStart = true) noexcept {
updateCursorPoint(
ox::Point{
static_cast<int32_t>(cursor.x),
static_cast<int32_t>(cursor.y),
},
allowStart);
}
constexpr void updateCursorPoint(ImVec2 cursor, bool allowStart = true) noexcept {
updateCursorPoint(
ox::Point{
static_cast<int32_t>(cursor.x),
static_cast<int32_t>(cursor.y),
},
allowStart);
}
constexpr void reset() noexcept {
m_selectionOngoing = {};
}
constexpr void finishSelection() noexcept {
m_selectionOngoing = {};
}
[[nodiscard]]
constexpr Selection selection() const noexcept {
return {
{
ox::min(m_pointA.x, m_pointB.x),
ox::min(m_pointA.y, m_pointB.y),
},
{
ox::max(m_pointA.x, m_pointB.x),
ox::max(m_pointA.y, m_pointB.y),
},
};
}
};
}