#include "UI/Layout/SnapObject.h" #include "UI/Window/UIWindow.h" namespace { // INLINED bool Overlaps(int a, int b, int c, int d) { return (b >= c && b <= d) || (d >= a && d <= b) || (a >= c && a <= d) || (c >= a && c <= b); } } // OFFSET: 0x007E2240 // FUNCTION: fn_09695 SnapObject::SnapObject() : window(nullptr), visited(0) { } SnapObject::~SnapObject() = default; // OFFSET: 0x007E2770 // FUNCTION: fn_09703 int SnapObject::AdjacentSide(const SnapObject& other) const { const int width = this->window->geometry.width; const int height = this->window->geometry.height; const int x = this->window->geometry.x; const int y = this->window->geometry.y; const int otherWidth = other.window->geometry.width; const int otherHeight = other.window->geometry.height; const int otherX = other.window->geometry.x; const int otherY = other.window->geometry.y; if (x == otherX + otherWidth && Overlaps(y, y + height, otherY, otherY + otherHeight)) { return 0; } if (otherX == x + width && Overlaps(otherY, otherY + otherHeight, y, y + height)) { return 2; } if (y == otherY + otherHeight && Overlaps(x, x + width, otherX, otherX + otherWidth)) { return 1; } if (otherY == y + height && Overlaps(otherX, otherX + otherWidth, x, x + width)) { return 3; } return -1; } // OFFSET: 0x007E2960 // FUNCTION: fn_09704 void SnapObject::Remove(SnapObject* object) { if (!object) { return; } for (int side = 0; side < 4; ++side) { for (auto node = this->edges[side].begin(); node != this->edges[side].end(); ++node) { if (*node == object) { this->edges[side].erase(node); break; } } } } // OFFSET: 0x007E2C20 // FUNCTION: fn_09710 bool SnapObject::Contains(SnapObject* target) { if (this->visited == 1) { return false; } if (target == this) { return true; } this->visited = 1; for (int side = 0; side < 4; ++side) { for (auto node = this->edges[side].begin(); node != this->edges[side].end(); ++node) { if ((*node)->Contains(target)) { return true; } } } return false; } // OFFSET: 0x007E2C90 // FUNCTION: fn_09711 bool SnapObject::Connected(SnapObject* target) { if (this->visited == 1 || target == this) { return false; } this->visited = 1; for (int side = 0; side < 4; ++side) { if (!this->edges[side].empty()) { for (auto node = this->edges[side].begin(); node != this->edges[side].end(); ++node) { if ((*node)->Contains(target)) { return true; } } } } return false; } // OFFSET: 0x007E2B00 // FUNCTION: fn_09707 int SnapObject::GetHeight() const { return this->window->geometry.height; } // OFFSET: 0x007E2B10 // FUNCTION: fn_09708 void SnapObject::AccumulateHeight(int& height, int side) const { const SnapObject* current = this; do { height = (height + current->window->geometry.height); const SnapObject* next = nullptr; for (SnapObject* candidate : current->edges[side]) { if (candidate->window->geometry.height > 0) { next = candidate; } } current = next; } while (current); }