|
|
|
|
@@ -63,6 +63,7 @@ void region_tree::split(flecs::entity grid_floor_e,
|
|
|
|
|
count++;
|
|
|
|
|
e = e->next();
|
|
|
|
|
}
|
|
|
|
|
assert(base_rtree->check(grid_floor_e));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const region_tree *region_tree::find(flecs::entity_t which) const
|
|
|
|
|
@@ -136,6 +137,7 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
|
|
|
|
|
const struct region_tree *base_rtree = grid_floor_e.get<region_tree>();
|
|
|
|
|
assert(base_rtree);
|
|
|
|
|
make_random r(11365);
|
|
|
|
|
assert(base_rtree->check(grid_floor_e));
|
|
|
|
|
#ifdef TESTS
|
|
|
|
|
flecs::log::warn("grow");
|
|
|
|
|
#endif
|
|
|
|
|
@@ -176,6 +178,7 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
|
|
|
|
|
return hash_one_uint64((uint64_t)ptr);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
Vector2i pos = get_global_center();
|
|
|
|
|
while (1) {
|
|
|
|
|
e = special_grow_list.front();
|
|
|
|
|
int count = 0;
|
|
|
|
|
@@ -187,29 +190,64 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
|
|
|
|
|
e = e->next();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
Vector2i dir = pos - item->region.rect.position;
|
|
|
|
|
struct region backup = item->region;
|
|
|
|
|
RegionRect2i parent_rect = item->parent->region.rect;
|
|
|
|
|
switch (variant) {
|
|
|
|
|
case 0:
|
|
|
|
|
if (dir.x > 0)
|
|
|
|
|
item->region.rect.position.x =
|
|
|
|
|
parent_rect.position.x +
|
|
|
|
|
parent_rect.size.x - 1;
|
|
|
|
|
else if (dir.x < 0)
|
|
|
|
|
item->region.rect.position.x =
|
|
|
|
|
parent_rect.position.x;
|
|
|
|
|
if (dir.y > 0)
|
|
|
|
|
item->region.rect.position.y =
|
|
|
|
|
parent_rect.position.y +
|
|
|
|
|
parent_rect.size.y - 1;
|
|
|
|
|
else if (dir.y < 0)
|
|
|
|
|
item->region.rect.position.y =
|
|
|
|
|
parent_rect.position.y;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
if (dir.x > 0)
|
|
|
|
|
item->region.rect.position.x =
|
|
|
|
|
parent_rect.position.x +
|
|
|
|
|
parent_rect.size.x - 1;
|
|
|
|
|
else if (dir.x < 0)
|
|
|
|
|
item->region.rect.position.x =
|
|
|
|
|
parent_rect.position.x;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
if (dir.y > 0)
|
|
|
|
|
item->region.rect.position.y =
|
|
|
|
|
parent_rect.position.y +
|
|
|
|
|
parent_rect.size.y - 1;
|
|
|
|
|
else if (dir.y < 0)
|
|
|
|
|
item->region.rect.position.y =
|
|
|
|
|
parent_rect.position.y;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
item->region.rect.position.x =
|
|
|
|
|
parent_rect.position.x +
|
|
|
|
|
parent_rect.size.x - 1;
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
case 4:
|
|
|
|
|
item->region.rect.position.x =
|
|
|
|
|
parent_rect.position.x;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
case 5:
|
|
|
|
|
item->region.rect.position.y =
|
|
|
|
|
parent_rect.position.y +
|
|
|
|
|
parent_rect.size.y - 1;
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
case 6:
|
|
|
|
|
item->region.rect.position.y =
|
|
|
|
|
parent_rect.position.y;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (variant > 3) {
|
|
|
|
|
if (variant > 6) {
|
|
|
|
|
do {
|
|
|
|
|
item->region.rect.position.x =
|
|
|
|
|
parent_rect.position.x +
|
|
|
|
|
@@ -363,6 +401,7 @@ void region_tree::grow(flecs::entity grid_floor_e, bool limited)
|
|
|
|
|
queue.clear();
|
|
|
|
|
assert(base_rtree->check(grid_floor_e));
|
|
|
|
|
}
|
|
|
|
|
assert(base_rtree->check(grid_floor_e));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool region_tree::check(flecs::entity grid_floor_e) const
|
|
|
|
|
@@ -407,6 +446,7 @@ bool region_tree::check(flecs::entity grid_floor_e) const
|
|
|
|
|
float aspect = (float)check_regions[i].size.x /
|
|
|
|
|
(float)check_regions[i].size.y;
|
|
|
|
|
if (aspect < 0.25f || aspect > 4.0f) {
|
|
|
|
|
flecs::log::err("bad aspect ratio");
|
|
|
|
|
ok = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@@ -456,6 +496,219 @@ bool region_tree::check(flecs::entity grid_floor_e) const
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: calculate if rooms touch each other and shrink smaller one
|
|
|
|
|
void region_tree::shrink_rooms(flecs::entity grid_floor_e)
|
|
|
|
|
{
|
|
|
|
|
int i, accepted = 0;
|
|
|
|
|
assert(!parent);
|
|
|
|
|
dump(grid_floor_e);
|
|
|
|
|
List<struct region_tree *> queue, shrinkable;
|
|
|
|
|
List<struct region_tree *> left_rooms, right_rooms, forward_rooms,
|
|
|
|
|
backward_rooms, inside_rooms;
|
|
|
|
|
List<struct region_tree *>::Element *rp, *rp1, *rp2;
|
|
|
|
|
struct touching_result {
|
|
|
|
|
struct region_tree *first;
|
|
|
|
|
struct region_tree *second;
|
|
|
|
|
int how;
|
|
|
|
|
};
|
|
|
|
|
const struct region_tree *base_rtree = grid_floor_e.get<region_tree>();
|
|
|
|
|
assert(base_rtree);
|
|
|
|
|
assert(base_rtree->check(grid_floor_e));
|
|
|
|
|
List<struct touching_result> touching;
|
|
|
|
|
int grid_size = grid_floor_e
|
|
|
|
|
.get<WorldEditor::components::
|
|
|
|
|
buildings_layout_grid_floor>()
|
|
|
|
|
->grid_size;
|
|
|
|
|
queue.push_back(this);
|
|
|
|
|
while (!queue.empty()) {
|
|
|
|
|
const struct region_tree *item = queue.front()->get();
|
|
|
|
|
queue.pop_front();
|
|
|
|
|
if (item->region.can_grow)
|
|
|
|
|
return;
|
|
|
|
|
if (item->is_leaf() && item->region.can_move)
|
|
|
|
|
return;
|
|
|
|
|
for (i = 0; i < (int)item->children.size(); i++)
|
|
|
|
|
queue.push_back(item->children[i]);
|
|
|
|
|
}
|
|
|
|
|
queue.clear();
|
|
|
|
|
queue.push_back(this);
|
|
|
|
|
while (!queue.empty()) {
|
|
|
|
|
struct region_tree *item = queue.front()->get();
|
|
|
|
|
queue.pop_front();
|
|
|
|
|
int acceptable = 0;
|
|
|
|
|
if (item->is_shrinkable())
|
|
|
|
|
acceptable = 0xf;
|
|
|
|
|
flecs::log::dbg("acceptable: %d", acceptable);
|
|
|
|
|
if ((acceptable & 0xf) == 0xf) {
|
|
|
|
|
shrinkable.push_back(item);
|
|
|
|
|
accepted++;
|
|
|
|
|
int rx, px, ry, py;
|
|
|
|
|
rx = item->region.rect.position.x;
|
|
|
|
|
px = item->parent->region.rect.position.x;
|
|
|
|
|
if (rx == px) {
|
|
|
|
|
left_rooms.push_back(item);
|
|
|
|
|
acceptable |= (1 << 4);
|
|
|
|
|
}
|
|
|
|
|
rx = item->region.rect.position.x +
|
|
|
|
|
item->region.rect.size.x - 1;
|
|
|
|
|
px = item->parent->region.rect.position.x +
|
|
|
|
|
item->parent->region.rect.size.x - 1;
|
|
|
|
|
if (rx == px) {
|
|
|
|
|
right_rooms.push_back(item);
|
|
|
|
|
acceptable |= (1 << 5);
|
|
|
|
|
}
|
|
|
|
|
ry = item->region.rect.position.y;
|
|
|
|
|
py = item->parent->region.rect.position.y;
|
|
|
|
|
if (ry == py) {
|
|
|
|
|
forward_rooms.push_back(item);
|
|
|
|
|
acceptable |= (1 << 6);
|
|
|
|
|
}
|
|
|
|
|
ry = item->region.rect.position.y +
|
|
|
|
|
item->region.rect.size.y - 1;
|
|
|
|
|
py = item->parent->region.rect.position.y +
|
|
|
|
|
item->parent->region.rect.size.y - 1;
|
|
|
|
|
if (ry == py) {
|
|
|
|
|
backward_rooms.push_back(item);
|
|
|
|
|
acceptable |= (1 << 7);
|
|
|
|
|
}
|
|
|
|
|
if ((acceptable & 0xf0) == 0)
|
|
|
|
|
inside_rooms.push_back(item);
|
|
|
|
|
flecs::log::dbg("acceptable: %d", acceptable);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < (int)item->children.size(); i++)
|
|
|
|
|
queue.push_back(item->children[i]);
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
|
|
|
|
rp1 = rooms.front();
|
|
|
|
|
while (rp1) {
|
|
|
|
|
rp2 = rooms.front();
|
|
|
|
|
while (rp2) {
|
|
|
|
|
if (rp1 == rp2) {
|
|
|
|
|
rp2 = rp2->next();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
int style = rp1->get()->what_touching(rp2->get());
|
|
|
|
|
struct region_tree *item1 = rp1->get(),
|
|
|
|
|
*item2 = rp2->get();
|
|
|
|
|
if (style & TOUCH_RIGHT) {
|
|
|
|
|
if (shrinkable.find(item2)) {
|
|
|
|
|
if (!right_rooms.find(item2))
|
|
|
|
|
right_rooms.push_back(item2);
|
|
|
|
|
} else if (shrinkable.find(item1)) {
|
|
|
|
|
if (!left_rooms.find(item1))
|
|
|
|
|
left_rooms.push_back(item1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (style & TOUCH_LEFT) {
|
|
|
|
|
if (shrinkable.find(item2)) {
|
|
|
|
|
if (!left_rooms.find(item2))
|
|
|
|
|
left_rooms.push_back(item2);
|
|
|
|
|
} else if (shrinkable.find(item1)) {
|
|
|
|
|
if (!right_rooms.find(item1))
|
|
|
|
|
right_rooms.push_back(item1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (style & TOUCH_FORWARD) {
|
|
|
|
|
if (shrinkable.find(item2)) {
|
|
|
|
|
if (!forward_rooms.find(item2))
|
|
|
|
|
forward_rooms.push_back(item2);
|
|
|
|
|
} else if (shrinkable.find(item1)) {
|
|
|
|
|
if (!backward_rooms.find(item1))
|
|
|
|
|
backward_rooms.push_back(item1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (style & TOUCH_BACKWARD) {
|
|
|
|
|
if (shrinkable.find(item2)) {
|
|
|
|
|
if (!backward_rooms.find(item2))
|
|
|
|
|
backward_rooms.push_back(item2);
|
|
|
|
|
} else if (shrinkable.find(item1)) {
|
|
|
|
|
if (!forward_rooms.find(item1))
|
|
|
|
|
forward_rooms.push_back(item1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rp2 = rp2->next();
|
|
|
|
|
}
|
|
|
|
|
rp1 = rp1->next();
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
int shrunk = 0;
|
|
|
|
|
int shrink_mode = SHRINK_LEFT_ROOM;
|
|
|
|
|
while (1) {
|
|
|
|
|
switch (shrink_mode) {
|
|
|
|
|
case SHRINK_LEFT_ROOM:
|
|
|
|
|
rp = left_rooms.front();
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_RIGHT_ROOM:
|
|
|
|
|
rp = right_rooms.front();
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_FORWARD_ROOM:
|
|
|
|
|
rp = forward_rooms.front();
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_BACKWARD_ROOM:
|
|
|
|
|
rp = backward_rooms.front();
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_INSIDE_ROOM:
|
|
|
|
|
rp = inside_rooms.front();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
while (rp) {
|
|
|
|
|
struct region backup = rp->get()->region;
|
|
|
|
|
List<struct region_tree *> neighbors;
|
|
|
|
|
switch (shrink_mode) {
|
|
|
|
|
case SHRINK_LEFT_ROOM:
|
|
|
|
|
get_neighbors(grid_floor_e, RIGHT, &neighbors);
|
|
|
|
|
if (neighbors.size() > 0) {
|
|
|
|
|
rp->get()->region.rect.size.x -= 1;
|
|
|
|
|
shrunk++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_RIGHT_ROOM:
|
|
|
|
|
get_neighbors(grid_floor_e, LEFT, &neighbors);
|
|
|
|
|
if (neighbors.size() > 0) {
|
|
|
|
|
rp->get()->region.rect.position.x += 1;
|
|
|
|
|
rp->get()->region.rect.size.x -= 1;
|
|
|
|
|
shrunk++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_FORWARD_ROOM:
|
|
|
|
|
get_neighbors(grid_floor_e, BACKWARD,
|
|
|
|
|
&neighbors);
|
|
|
|
|
if (neighbors.size() > 0) {
|
|
|
|
|
rp->get()->region.rect.size.y -= 1;
|
|
|
|
|
shrunk++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_BACKWARD_ROOM:
|
|
|
|
|
get_neighbors(grid_floor_e, FORWARD,
|
|
|
|
|
&neighbors);
|
|
|
|
|
if (neighbors.size() > 0) {
|
|
|
|
|
rp->get()->region.rect.position.y += 1;
|
|
|
|
|
rp->get()->region.rect.size.y -= 1;
|
|
|
|
|
shrunk++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SHRINK_INSIDE_ROOM:
|
|
|
|
|
// TODO: check neighbors
|
|
|
|
|
rp->get()->region.rect =
|
|
|
|
|
rp->get()->region.rect.grow(-1);
|
|
|
|
|
shrunk++;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert(false);
|
|
|
|
|
}
|
|
|
|
|
if (!base_rtree->check(grid_floor_e))
|
|
|
|
|
rp->get()->region = backup;
|
|
|
|
|
assert(base_rtree->check(grid_floor_e));
|
|
|
|
|
rp = rp->next();
|
|
|
|
|
}
|
|
|
|
|
if (shrink_mode >= SHRINK_INSIDE_ROOM)
|
|
|
|
|
break;
|
|
|
|
|
shrink_mode++;
|
|
|
|
|
}
|
|
|
|
|
assert(base_rtree->check(grid_floor_e));
|
|
|
|
|
// assert(accepted == 0 || shrunk > 0);
|
|
|
|
|
grid_floor_e.modified<region_tree>();
|
|
|
|
|
}
|
|
|
|
|
void region_tree::place(flecs::entity grid_floor_e) const
|
|
|
|
|
{
|
|
|
|
|
int i, j, k;
|
|
|
|
|
@@ -568,10 +821,13 @@ void region_tree::place(flecs::entity grid_floor_e) const
|
|
|
|
|
|
|
|
|
|
void region_tree::move(flecs::entity grid_floor_e)
|
|
|
|
|
{
|
|
|
|
|
if (!parent)
|
|
|
|
|
return;
|
|
|
|
|
struct region_tree *base_rtree = grid_floor_e.get_mut<region_tree>();
|
|
|
|
|
assert(base_rtree);
|
|
|
|
|
List<struct region_tree *> queue;
|
|
|
|
|
List<struct region_tree *> movables;
|
|
|
|
|
List<struct region_tree *> movables_sorted;
|
|
|
|
|
int count = 0;
|
|
|
|
|
Vector2i center;
|
|
|
|
|
queue.push_back(base_rtree);
|
|
|
|
|
@@ -595,37 +851,97 @@ void region_tree::move(flecs::entity grid_floor_e)
|
|
|
|
|
flecs::log::dbg("center: %d %d", center.x, center.y);
|
|
|
|
|
while (!movables.empty()) {
|
|
|
|
|
struct region_tree *item = movables.front()->get();
|
|
|
|
|
Vector2i dir = item->region.rect.get_center() - center;
|
|
|
|
|
int d = dir.x * dir.x + dir.y * dir.y;
|
|
|
|
|
movables.pop_front();
|
|
|
|
|
List<struct region_tree *>::Element *e = movables.front();
|
|
|
|
|
bool ok = true;
|
|
|
|
|
while (e) {
|
|
|
|
|
struct region_tree *check = e->get();
|
|
|
|
|
Vector2i dir2 =
|
|
|
|
|
check->region.rect.get_center() - center;
|
|
|
|
|
int d2 = dir2.x * dir2.x + dir2.y * dir2.y;
|
|
|
|
|
if (d2 > d) {
|
|
|
|
|
ok = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
e = e->next();
|
|
|
|
|
}
|
|
|
|
|
if (ok)
|
|
|
|
|
movables_sorted.push_back(item);
|
|
|
|
|
else
|
|
|
|
|
movables.push_back(item);
|
|
|
|
|
}
|
|
|
|
|
flecs::log::dbg("sorting done");
|
|
|
|
|
int fail_count = 0;
|
|
|
|
|
while (!movables_sorted.empty()) {
|
|
|
|
|
struct region_tree *item = movables_sorted.front()->get();
|
|
|
|
|
if (!item->region.can_move)
|
|
|
|
|
continue;
|
|
|
|
|
Vector2i dir = item->region.rect.get_center() - center, dir1,
|
|
|
|
|
dir2;
|
|
|
|
|
if (dir.x * dir.x > dir.y * dir.y) {
|
|
|
|
|
dir1.x = CLAMP(dir.x, -1, 1);
|
|
|
|
|
dir1.y = 0;
|
|
|
|
|
} else if (dir.x * dir.x < dir.y * dir.y) {
|
|
|
|
|
dir1.x = 0;
|
|
|
|
|
dir1.y = CLAMP(dir.y, -1, 1);
|
|
|
|
|
}
|
|
|
|
|
dir2.x = CLAMP(dir.x, -1, 1);
|
|
|
|
|
dir2.y = CLAMP(dir.y, -1, 1);
|
|
|
|
|
flecs::log::dbg("direction: %d %d", dir.x, dir.y);
|
|
|
|
|
RegionRect2i backup = item->region.rect;
|
|
|
|
|
item->region.rect.position += dir1;
|
|
|
|
|
if (base_rtree->check(grid_floor_e)) {
|
|
|
|
|
queue.push_back(item);
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
item->region.rect = backup;
|
|
|
|
|
item->region.rect.position += dir2;
|
|
|
|
|
if (base_rtree->check(grid_floor_e)) {
|
|
|
|
|
queue.push_back(item);
|
|
|
|
|
continue;
|
|
|
|
|
Vector2i gcenter = item->get_global_center();
|
|
|
|
|
Vector2i dir = item->parent->region.rect.get_center() -
|
|
|
|
|
(center * 2 + gcenter * 4);
|
|
|
|
|
int flag1 = (item->region.rect.position.x +
|
|
|
|
|
item->region.rect.position.y) &
|
|
|
|
|
(1 << 1);
|
|
|
|
|
int flag2 = (item->region.rect.position.x +
|
|
|
|
|
item->region.rect.position.y) &
|
|
|
|
|
(1 << 2);
|
|
|
|
|
if (dir.x == 0 && dir.y == 0) {
|
|
|
|
|
if (flag1) {
|
|
|
|
|
dir.x = 0;
|
|
|
|
|
if (flag2)
|
|
|
|
|
dir.y = 1;
|
|
|
|
|
else
|
|
|
|
|
dir.y = -1;
|
|
|
|
|
} else {
|
|
|
|
|
item->region.rect = backup;
|
|
|
|
|
item->region.can_move = false;
|
|
|
|
|
if (flag2)
|
|
|
|
|
dir.x = 1;
|
|
|
|
|
else
|
|
|
|
|
dir.x = -1;
|
|
|
|
|
dir.y = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Vector2i mdir1, mdir2;
|
|
|
|
|
mdir1.x = CLAMP(dir.x, -1, 1);
|
|
|
|
|
mdir1.y = 0;
|
|
|
|
|
mdir2.x = 0;
|
|
|
|
|
mdir2.y = CLAMP(dir.y, -1, 1);
|
|
|
|
|
flecs::log::dbg("direction: %d %d", dir.x, dir.y);
|
|
|
|
|
flecs::log::dbg("direction1: %d %d", mdir1.x, mdir1.y);
|
|
|
|
|
flecs::log::dbg("direction2: %d %d", mdir2.x, mdir2.y);
|
|
|
|
|
flecs::log::dbg("position: %d %d", item->region.rect.position.x,
|
|
|
|
|
item->region.rect.position.y);
|
|
|
|
|
RegionRect2i backup = item->region.rect;
|
|
|
|
|
item->region.rect.position += mdir1;
|
|
|
|
|
flecs::log::dbg("updated position: %d %d",
|
|
|
|
|
item->region.rect.position.x,
|
|
|
|
|
item->region.rect.position.y);
|
|
|
|
|
bool ok1 = false, ok2 = false;
|
|
|
|
|
if (base_rtree->check(grid_floor_e)) {
|
|
|
|
|
fail_count = 0;
|
|
|
|
|
flecs::log::dbg("can still move");
|
|
|
|
|
ok1 = true;
|
|
|
|
|
} else {
|
|
|
|
|
ok1 = false;
|
|
|
|
|
item->region.rect = backup;
|
|
|
|
|
item->region.rect.position += mdir2;
|
|
|
|
|
if (base_rtree->check(grid_floor_e))
|
|
|
|
|
ok2 = true;
|
|
|
|
|
else
|
|
|
|
|
ok2 = false;
|
|
|
|
|
}
|
|
|
|
|
if (!ok1 && !ok2) {
|
|
|
|
|
fail_count++;
|
|
|
|
|
item->region.rect = backup;
|
|
|
|
|
if (fail_count > 10) {
|
|
|
|
|
item->region.can_move = false;
|
|
|
|
|
movables_sorted.pop_front();
|
|
|
|
|
flecs::log::dbg("can't move, going to next");
|
|
|
|
|
fail_count = 0;
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
grid_floor_e.modified<region_tree>();
|
|
|
|
|
}
|
|
|
|
|
@@ -702,7 +1018,156 @@ bool region_tree::is_special() const
|
|
|
|
|
{
|
|
|
|
|
return flag_special;
|
|
|
|
|
}
|
|
|
|
|
bool region_tree::is_touching(const struct region_tree *other) const
|
|
|
|
|
{
|
|
|
|
|
int flags = what_touching(other);
|
|
|
|
|
return (flags > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void region_tree::get_room_nodes(
|
|
|
|
|
List<const struct region_tree *> *node_list) const
|
|
|
|
|
{
|
|
|
|
|
List<const struct region_tree *> queue;
|
|
|
|
|
queue.push_back(this);
|
|
|
|
|
while (!queue.empty()) {
|
|
|
|
|
int i;
|
|
|
|
|
const struct region_tree *item = queue.front()->get();
|
|
|
|
|
queue.pop_front();
|
|
|
|
|
if (item->is_leaf() && item->is_a_room()) {
|
|
|
|
|
node_list->push_back(item);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < (int)item->children.size(); i++)
|
|
|
|
|
queue.push_back(item->children[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void region_tree::get_room_nodes(List<struct region_tree *> *node_list)
|
|
|
|
|
{
|
|
|
|
|
List<struct region_tree *> queue;
|
|
|
|
|
queue.push_back(this);
|
|
|
|
|
while (!queue.empty()) {
|
|
|
|
|
int i;
|
|
|
|
|
struct region_tree *item = queue.front()->get();
|
|
|
|
|
queue.pop_front();
|
|
|
|
|
if (item->is_leaf() && item->is_a_room()) {
|
|
|
|
|
node_list->push_back(item);
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < (int)item->children.size(); i++)
|
|
|
|
|
queue.push_back(item->children[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void region_tree::get_neighbors(flecs::entity grid_floor_e, int direction,
|
|
|
|
|
List<struct region_tree *> *neighbors) const
|
|
|
|
|
{
|
|
|
|
|
List<struct region_tree *> rooms;
|
|
|
|
|
List<struct region_tree *>::Element *el;
|
|
|
|
|
struct region_tree *base_rtree = grid_floor_e.get_mut<region_tree>();
|
|
|
|
|
assert(base_rtree);
|
|
|
|
|
base_rtree->get_room_nodes(&rooms);
|
|
|
|
|
RegionRect2i neighbor_rect = region.rect;
|
|
|
|
|
neighbors->clear();
|
|
|
|
|
switch (direction) {
|
|
|
|
|
case LEFT:
|
|
|
|
|
neighbor_rect.position.x -= 1;
|
|
|
|
|
neighbor_rect.size.x = 1;
|
|
|
|
|
break;
|
|
|
|
|
case RIGHT:
|
|
|
|
|
neighbor_rect.position.x += region.rect.size.x;
|
|
|
|
|
neighbor_rect.size.x = 1;
|
|
|
|
|
break;
|
|
|
|
|
case FORWARD:
|
|
|
|
|
neighbor_rect.position.y -= 1;
|
|
|
|
|
neighbor_rect.size.y = 1;
|
|
|
|
|
break;
|
|
|
|
|
case BACKWARD:
|
|
|
|
|
neighbor_rect.position.y += region.rect.size.y;
|
|
|
|
|
neighbor_rect.size.y = 1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert(false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
el = rooms.front();
|
|
|
|
|
while (el) {
|
|
|
|
|
if (el->get() == this) {
|
|
|
|
|
el = el->next();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
bool neighbor = false;
|
|
|
|
|
if (neighbor_rect == el->get()->region.rect)
|
|
|
|
|
neighbor = true;
|
|
|
|
|
if (neighbor_rect.encloses(el->get()->region.rect))
|
|
|
|
|
neighbor = true;
|
|
|
|
|
if (neighbor_rect.intersects(el->get()->region.rect))
|
|
|
|
|
neighbor = true;
|
|
|
|
|
if (el->get()->region.rect.encloses(neighbor_rect))
|
|
|
|
|
neighbor = true;
|
|
|
|
|
if (el->get()->region.rect.intersects(neighbor_rect))
|
|
|
|
|
neighbor = true;
|
|
|
|
|
if (neighbor)
|
|
|
|
|
neighbors->push_back(el->get());
|
|
|
|
|
el = el->next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int region_tree::what_touching(const region_tree *other) const
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
RegionRect2i right = region.rect, left = region.rect,
|
|
|
|
|
forward = region.rect, backward = region.rect;
|
|
|
|
|
right.position.x = region.rect.position.x + region.rect.size.x;
|
|
|
|
|
left.position.x = region.rect.position.x - region.rect.size.x;
|
|
|
|
|
forward.position.y = region.rect.position.y - region.rect.size.y;
|
|
|
|
|
backward.position.y = region.rect.position.y + region.rect.size.y;
|
|
|
|
|
int flags = 0;
|
|
|
|
|
RegionRect2i rects[] = { right, left, forward, backward };
|
|
|
|
|
for (i = 0; i < (int)sizeof(rects) / (int)sizeof(rects[0]); i++) {
|
|
|
|
|
if (other->region.rect == rects[i])
|
|
|
|
|
flags |= (1 << i);
|
|
|
|
|
if (other->region.rect.encloses(rects[i]))
|
|
|
|
|
flags |= (1 << i);
|
|
|
|
|
if (other->region.rect.intersects(rects[i]))
|
|
|
|
|
flags |= (1 << i);
|
|
|
|
|
if (rects[i].encloses(other->region.rect))
|
|
|
|
|
flags |= (1 << i);
|
|
|
|
|
}
|
|
|
|
|
return flags;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool region_tree::is_shrinkable() const
|
|
|
|
|
{
|
|
|
|
|
int acceptable = 0;
|
|
|
|
|
if (region.rect.size.x > 2)
|
|
|
|
|
acceptable |= (1 << 0);
|
|
|
|
|
if (region.rect.size.y > 2)
|
|
|
|
|
acceptable |= (1 << 1);
|
|
|
|
|
if (is_leaf())
|
|
|
|
|
acceptable |= (1 << 2);
|
|
|
|
|
if (parent)
|
|
|
|
|
acceptable |= (1 << 3);
|
|
|
|
|
return (acceptable & 0xf) == 0xf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Vector2i region_tree::get_global_center() const
|
|
|
|
|
{
|
|
|
|
|
Vector2i center;
|
|
|
|
|
int i;
|
|
|
|
|
const struct region_tree *r = this;
|
|
|
|
|
while (r->parent)
|
|
|
|
|
r = r->parent;
|
|
|
|
|
for (i = 0; i < r->children.size(); i++)
|
|
|
|
|
center += r->children[i]->region.rect.get_center();
|
|
|
|
|
return center;
|
|
|
|
|
}
|
|
|
|
|
Vector2i region_tree::get_center() const
|
|
|
|
|
{
|
|
|
|
|
return region.rect.get_center();
|
|
|
|
|
}
|
|
|
|
|
int region_tree::area() const
|
|
|
|
|
{
|
|
|
|
|
return region.rect.get_area();
|
|
|
|
|
}
|
|
|
|
|
bool region_tree::check_candidate(int i, const RegionRect2i &candidate) const
|
|
|
|
|
{
|
|
|
|
|
int j;
|
|
|
|
|
|