Reworked growing of regions into jbo system
This commit is contained in:
@@ -221,7 +221,15 @@ void BuildingLayoutGraph::graph_module::grow_cell(flecs::entity seed_e, int id)
|
||||
void BuildingLayoutGraph::graph_module::queue_grow_cell(flecs::entity seed_e,
|
||||
int id)
|
||||
{
|
||||
assert(seed_e.is_valid());
|
||||
flecs::entity floor_e = seed_e.parent();
|
||||
if (!floor_e.is_valid())
|
||||
flecs::log::err("the parent of %s is not grid floor",
|
||||
seed_e.path().c_str());
|
||||
assert(floor_e.is_valid());
|
||||
if (!floor_e.has<WorldEditor::components::buildings_layout_grid_floor>())
|
||||
flecs::log::err("the parent of %s is not grid floor %s",
|
||||
seed_e.path().c_str(), floor_e.path().c_str());
|
||||
assert(floor_e.has<
|
||||
WorldEditor::components::buildings_layout_grid_floor>());
|
||||
Pair<flecs::entity_t, int> m(seed_e.id(), id);
|
||||
@@ -243,6 +251,9 @@ void BuildingLayoutGraph::graph_module::create_floor_components(
|
||||
flecs::entity floor_e, flecs::entity base_floor_e,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size)
|
||||
{
|
||||
assert(!floor_e.has<
|
||||
WorldEditor::components::buildings_layout_grid_floor>());
|
||||
assert(!floor_e.has<growth_regions>());
|
||||
floor_e.set<WorldEditor::components::buildings_layout_grid_floor>(
|
||||
{ Set<int>(), size.grid_size, size.growth_size });
|
||||
floor_e.set<growth_regions>(
|
||||
@@ -251,11 +262,13 @@ void BuildingLayoutGraph::graph_module::create_floor_components(
|
||||
}
|
||||
|
||||
void growth_regions::create_region(flecs::entity floor_e, flecs::entity seed_e,
|
||||
flecs::entity parent_e,
|
||||
flecs::entity region_e,
|
||||
const Vector2i &position, float area)
|
||||
{
|
||||
int i;
|
||||
struct growth_regions::region r;
|
||||
r.parent = parent_e.id();
|
||||
r.seed_et = seed_e.id();
|
||||
r.region_et = region_e.id();
|
||||
r.rect.position = position;
|
||||
@@ -263,6 +276,7 @@ void growth_regions::create_region(flecs::entity floor_e, flecs::entity seed_e,
|
||||
r.remains_area = MAX((int)(area * 2.0f) / 16 + 1, 16);
|
||||
r.can_grow_square = true;
|
||||
r.can_grow = true;
|
||||
r.complete = false;
|
||||
bool ok = true;
|
||||
assert(check_region(-1, r.rect));
|
||||
const struct growth_regions *reg = floor_e.get<growth_regions>();
|
||||
@@ -290,6 +304,7 @@ flecs::entity growth_regions::create_cell(flecs::entity floor_e,
|
||||
flecs::entity region_e, int id)
|
||||
{
|
||||
flecs::entity ret;
|
||||
flecs::log::dbg("create_cell: %s %d", region_e.path().c_str(), id);
|
||||
if (floor_e.get<WorldEditor::components::buildings_layout_grid_floor>()
|
||||
->cells.has(id)) {
|
||||
flecs::log::err("cell %d already exists", id);
|
||||
@@ -1057,7 +1072,8 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
->get_layout_grid_base();
|
||||
flecs::entity grid_e =
|
||||
grid_base_e.lookup(graph_e.name());
|
||||
flecs::log::warn("deleting entity %s", grid_e.path());
|
||||
flecs::log::warn("deleting entity %s",
|
||||
grid_e.path().c_str());
|
||||
if (grid_e.is_valid())
|
||||
grid_e.destruct();
|
||||
it.world().defer_resume();
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
#define GRAPH_MODULE_H_
|
||||
struct growth_regions {
|
||||
struct region {
|
||||
flecs::entity_t parent;
|
||||
flecs::entity_t seed_et;
|
||||
flecs::entity_t region_et;
|
||||
Rect2i rect;
|
||||
int remains_area;
|
||||
bool can_grow_square;
|
||||
bool can_grow;
|
||||
bool complete;
|
||||
bool can_grow_region() const
|
||||
{
|
||||
bool ret = can_grow;
|
||||
@@ -62,8 +64,8 @@ struct growth_regions {
|
||||
return ret;
|
||||
}
|
||||
void create_region(flecs::entity floor_e, flecs::entity seed_e,
|
||||
flecs::entity region_e, const Vector2i &position,
|
||||
float area);
|
||||
flecs::entity parent_e, flecs::entity region_e,
|
||||
const Vector2i &position, float area);
|
||||
flecs::entity create_cell(flecs::entity floor_e, flecs::entity region_e,
|
||||
int id);
|
||||
};
|
||||
|
||||
@@ -116,6 +116,7 @@ out:
|
||||
.get<WorldEditor::components::
|
||||
buildings_layout_grid_floor>()
|
||||
->grid_size;
|
||||
flecs::log::dbg("###=== %s", grid_floor_e.path().c_str());
|
||||
flecs::entity grid_e = grid_floor_e.parent();
|
||||
assert(grid_e.is_valid());
|
||||
growth_regions *g = grid_floor_e.get_mut<growth_regions>();
|
||||
@@ -128,15 +129,23 @@ out:
|
||||
Rect2i check;
|
||||
check.position = positions[i].second;
|
||||
check.size = Vector2i(1, 1);
|
||||
flecs::log::dbg("%s ->region: %s cell_id %d",
|
||||
grid_floor_e.path().c_str(),
|
||||
region_e.path().c_str(), cell_id);
|
||||
assert(g->check_region(-1, check));
|
||||
flecs::entity cell_e =
|
||||
g->create_cell(grid_floor_e, region_e, cell_id);
|
||||
float area = get_entity_area(region_e);
|
||||
g->create_region(grid_floor_e, cell_e, region_e,
|
||||
flecs::log::dbg("region: %s: parent: %s",
|
||||
region_e.path().c_str(),
|
||||
region_e.parent().path().c_str());
|
||||
g->create_region(grid_floor_e, cell_e,
|
||||
region_e.parent(), region_e,
|
||||
positions[i].second, area);
|
||||
flecs::log::warn("grid cell: %s",
|
||||
cell_e.path().c_str());
|
||||
}
|
||||
flecs::log::dbg("###=== %s done", grid_floor_e.path().c_str());
|
||||
}
|
||||
float get_entity_area(flecs::entity e) const
|
||||
{
|
||||
@@ -220,20 +229,49 @@ out:
|
||||
int radius = pdim + local_radius;
|
||||
int radius_sq = radius * radius;
|
||||
if (distance_squared(positions[k].second, candidate) <
|
||||
radius_sq)
|
||||
radius_sq) {
|
||||
flecs::log::dbg(
|
||||
"too close to positions %d < %d",
|
||||
distance_squared(positions[k].second,
|
||||
candidate),
|
||||
radius_sq);
|
||||
continue;
|
||||
}
|
||||
assert(check_candidates_tolerance(candidate));
|
||||
accepted.push_back(candidate);
|
||||
ok = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
bool process_candidates(
|
||||
flecs::entity ce, const Vector2i &base, float area,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size,
|
||||
flecs::entity_t base_et, int dim)
|
||||
bool accept_candidate2(flecs::entity ce, const Vector2i &candidate)
|
||||
{
|
||||
int k;
|
||||
bool ok = false;
|
||||
for (k = 0; k < (int)positions.size(); k++) {
|
||||
assert(k < (int)positions.size());
|
||||
flecs::entity_t pbase_et = positions[k].first;
|
||||
int radius_sq = 4;
|
||||
if (distance_squared(positions[k].second, candidate) <
|
||||
radius_sq) {
|
||||
flecs::log::dbg(
|
||||
"too close to positions %d < %d",
|
||||
distance_squared(positions[k].second,
|
||||
candidate),
|
||||
radius_sq);
|
||||
continue;
|
||||
}
|
||||
assert(check_candidates_tolerance(candidate));
|
||||
accepted.push_back(candidate);
|
||||
ok = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
bool process_candidates(flecs::entity ce, const Vector2i &base,
|
||||
float area, flecs::entity_t base_et, int dim,
|
||||
const Rect2i &clip, bool tight)
|
||||
{
|
||||
int j;
|
||||
assert(dim > 1);
|
||||
int base_radius = get_base_radius(ce.world(), base_et);
|
||||
base_radius = MAX(1, base_radius);
|
||||
int local_radius = (int)((Math::sqrt(area) * 1.6f) / 2.0f) /
|
||||
@@ -241,18 +279,8 @@ out:
|
||||
local_radius = MAX(1, local_radius);
|
||||
// int dim = base_radius + local_radius;
|
||||
// dim = MAX(4, dim);
|
||||
int md = 1;
|
||||
if (size.grid_size > 30)
|
||||
md = 8;
|
||||
else if (size.grid_size > 20)
|
||||
md = 6;
|
||||
else if (size.grid_size > 15)
|
||||
md = 4;
|
||||
else if (size.grid_size > 10)
|
||||
md = 2;
|
||||
Rect2i clip(md, md, size.grid_size - md * 2,
|
||||
size.grid_size - md * 2);
|
||||
Vector2i candidates[8];
|
||||
assert(clip.has_point(base));
|
||||
get_dim_candidates(base, dim, &candidates[0]);
|
||||
for (j = 0;
|
||||
j < (int)(sizeof(candidates) / sizeof(candidates[0]));
|
||||
@@ -278,21 +306,27 @@ out:
|
||||
}
|
||||
print_line("valid candidate: " + itos(candidates[j].x) +
|
||||
", " + itos(candidates[j].y));
|
||||
accept_candidate(ce, candidates[j], area);
|
||||
flecs::log::dbg(
|
||||
"accepting candidate: %s",
|
||||
(candidates[j].operator String()).ascii().ptr());
|
||||
if (!tight)
|
||||
accept_candidate(ce, candidates[j], area);
|
||||
else
|
||||
accept_candidate2(ce, candidates[j]);
|
||||
}
|
||||
if (accepted.size() > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void filter_candidates(
|
||||
flecs::entity ce, float area,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size)
|
||||
void filter_candidates(flecs::entity ce, float area,
|
||||
const Rect2i &clip_rect)
|
||||
{
|
||||
if (positions.empty()) {
|
||||
/* starting at grid center */
|
||||
Vector2i start_pos(size.grid_size / 2,
|
||||
size.grid_size / 2);
|
||||
Vector2i start_pos(
|
||||
clip_rect.position.x + clip_rect.size.x / 2,
|
||||
clip_rect.position.y + clip_rect.size.y / 2);
|
||||
positions.push_back(Pair<flecs::entity_t, Vector2i>(
|
||||
ce.id(), start_pos));
|
||||
return;
|
||||
@@ -307,23 +341,78 @@ out:
|
||||
(int)((Math::sqrt(area) * 1.6f) / 2.0f) /
|
||||
4; /* grid conversion */
|
||||
local_radius = MAX(1, local_radius);
|
||||
/* minimum distance between region positions */
|
||||
int dim = base_radius + local_radius;
|
||||
dim = MAX(1, dim);
|
||||
process_candidates(ce, base, area, size, base_et, dim);
|
||||
if (accepted.size() == 0) {
|
||||
dim = MAX(2, dim);
|
||||
int md = 1;
|
||||
int clip_size = MIN(clip_rect.size.x, clip_rect.size.y);
|
||||
assert(dim > 1);
|
||||
|
||||
if (clip_size > 30)
|
||||
md = 8;
|
||||
else if (clip_size > 20)
|
||||
md = 6;
|
||||
else if (clip_size > 15)
|
||||
md = 4;
|
||||
else if (clip_size > 10)
|
||||
md = 2;
|
||||
if (clip_size < 6)
|
||||
md = 0;
|
||||
Rect2i clip(clip_rect.position.x + md,
|
||||
clip_rect.position.y + md,
|
||||
clip_rect.size.x - md * 2,
|
||||
clip_rect.size.y - md * 2);
|
||||
#if 0
|
||||
Rect2i dim_rect_min(base.x - dim, base.y - dim, dim,
|
||||
dim),
|
||||
dim_rect_max(base.x, base.y, dim, dim);
|
||||
dim_rect_min = clip.clip(dim_rect_min);
|
||||
dim_rect_max = clip.clip(dim_rect_max);
|
||||
int dim_min =
|
||||
MAX(dim_rect_min.size.x, dim_rect_min.size.y);
|
||||
int dim_max =
|
||||
MAX(dim_rect_max.size.x, dim_rect_max.size.y);
|
||||
int avg_dim = (dim_min + dim_max) / 2;
|
||||
dim = MIN(dim, avg_dim - 1);
|
||||
#endif
|
||||
flecs::log::dbg("dim=%d", dim);
|
||||
assert(dim > 1);
|
||||
assert(clip.has_point(base));
|
||||
flecs::log::warn(
|
||||
"filter_candidates: %d %d / %s / %s",
|
||||
clip_size, dim,
|
||||
(base.operator String()).ascii().ptr(),
|
||||
(clip.operator String()).ascii().ptr());
|
||||
assert(clip.has_point(base));
|
||||
assert(clip.has_point(base + Vector2i(dim, dim)) ||
|
||||
clip.has_point(base + Vector2i(dim, 0)) ||
|
||||
clip.has_point(base + Vector2i(0, dim)) ||
|
||||
clip.has_point(base + Vector2i(-dim, -dim)) ||
|
||||
clip.has_point(base + Vector2i(-dim, 0)) ||
|
||||
clip.has_point(base + Vector2i(0, -dim)));
|
||||
if (dim < 4)
|
||||
process_candidates(ce, base, area, base_et, dim,
|
||||
clip, true);
|
||||
else
|
||||
process_candidates(ce, base, area, base_et, dim,
|
||||
clip, false);
|
||||
if (accepted.size() > 0) {
|
||||
assert(accepted.size() > 0);
|
||||
const Vector2i &selected =
|
||||
accepted[which_selected()];
|
||||
assert(check_candidates_tolerance(selected));
|
||||
Pair<flecs::entity_t, Vector2i> m(ce.id(),
|
||||
selected);
|
||||
check_candidate(selected);
|
||||
positions.push_back(m);
|
||||
flecs::log::warn("add position: %d, %d",
|
||||
selected.x, selected.y);
|
||||
accepted.clear();
|
||||
break;
|
||||
} else {
|
||||
assert(positions.size() > 0);
|
||||
continue;
|
||||
}
|
||||
assert(accepted.size() > 0);
|
||||
const Vector2i &selected = accepted[which_selected()];
|
||||
assert(check_candidates_tolerance(selected));
|
||||
Pair<flecs::entity_t, Vector2i> m(ce.id(), selected);
|
||||
check_candidate(selected);
|
||||
positions.push_back(m);
|
||||
flecs::log::warn("add position: %d, %d", selected.x,
|
||||
selected.y);
|
||||
accepted.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
int which_position()
|
||||
@@ -344,9 +433,8 @@ out:
|
||||
assert(which < (int)accepted.size());
|
||||
return which;
|
||||
}
|
||||
template <class T>
|
||||
void place_region_cells(
|
||||
T *obj, flecs::entity grid_floor_e,
|
||||
flecs::entity grid_floor_e,
|
||||
const WorldEditor::components::buildings_layout_grid_floor &fl,
|
||||
growth_regions &g)
|
||||
{
|
||||
@@ -365,12 +453,46 @@ out:
|
||||
g.regions[i]
|
||||
.seed_et);
|
||||
assert(seed_e.is_valid());
|
||||
obj->queue_grow_cell(seed_e,
|
||||
id);
|
||||
assert(seed_e.parent()
|
||||
.is_valid());
|
||||
assert(seed_e.parent().id() ==
|
||||
grid_floor_e.id());
|
||||
queue_grow_cell(seed_e, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void queue_grow_cell(flecs::entity seed_e, int id)
|
||||
{
|
||||
assert(seed_e.is_valid());
|
||||
flecs::entity floor_e = seed_e.parent();
|
||||
if (!floor_e.is_valid())
|
||||
flecs::log::err("the parent of %s is not grid floor",
|
||||
seed_e.path().c_str());
|
||||
assert(floor_e.is_valid());
|
||||
if (!floor_e.has<WorldEditor::components::
|
||||
buildings_layout_grid_floor>())
|
||||
flecs::log::err("the parent of %s is not grid floor %s",
|
||||
seed_e.path().c_str(),
|
||||
floor_e.path().c_str());
|
||||
assert(floor_e.has<
|
||||
WorldEditor::components::buildings_layout_grid_floor>());
|
||||
Pair<flecs::entity_t, int> m(seed_e.id(), id);
|
||||
if (!floor_e.has<WorldEditor::components::
|
||||
buildings_layout_grid_queue>()) {
|
||||
List<Pair<flecs::entity_t, int> > queue;
|
||||
queue.push_back(m);
|
||||
floor_e.set<WorldEditor::components::
|
||||
buildings_layout_grid_queue>(
|
||||
{ queue });
|
||||
} else {
|
||||
floor_e.get_mut<WorldEditor::components::
|
||||
buildings_layout_grid_queue>()
|
||||
->queue.push_back(m);
|
||||
floor_e.modified<WorldEditor::components::
|
||||
buildings_layout_grid_queue>();
|
||||
}
|
||||
}
|
||||
void print_can_grow(int state, growth_regions &g, int index,
|
||||
const char *what)
|
||||
{
|
||||
@@ -458,6 +580,14 @@ out:
|
||||
break;
|
||||
}
|
||||
ok = clip.encloses(mrect);
|
||||
if (ok) {
|
||||
ok = false;
|
||||
if (mrect.size.y > 0 && mrect.size.x > 0) {
|
||||
float aspect = (float)mrect.size.x /
|
||||
(float)mrect.size.y;
|
||||
ok = (aspect > 0.2f && aspect < 5.0f);
|
||||
}
|
||||
}
|
||||
if (ok)
|
||||
ok = g.check_region(index, mrect);
|
||||
if (ok) {
|
||||
@@ -569,8 +699,489 @@ out:
|
||||
flecs::log::dbg("grow_region_rects: %s: done",
|
||||
floor_e.path().c_str());
|
||||
}
|
||||
Vector<Pair<flecs::entity, flecs::entity_t> > all_items;
|
||||
void subregions_init(flecs::world w)
|
||||
{
|
||||
flecs::query<const WorldEditor::components::buildings_layout_area>
|
||||
qprep = w.query_builder<const WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
.scope_open()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_zone>()
|
||||
.or_()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_unit>()
|
||||
.scope_close()
|
||||
.build();
|
||||
qprep.each([this](flecs::entity ce,
|
||||
const WorldEditor::components::
|
||||
buildings_layout_area &area) {
|
||||
all_items.push_back({ ce, ce.parent().id() });
|
||||
});
|
||||
}
|
||||
void get_subregions(flecs::entity parent,
|
||||
List<Pair<flecs::entity, float> > *subregions)
|
||||
{
|
||||
flecs::query<const WorldEditor::components::buildings_layout_area>
|
||||
qprep = parent.world()
|
||||
.query_builder<
|
||||
const WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
.with(flecs::ChildOf, parent)
|
||||
.scope_open()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_zone>()
|
||||
.or_()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_unit>()
|
||||
.or_()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_room>()
|
||||
.scope_close()
|
||||
.build();
|
||||
qprep.each([&subregions](flecs::entity ce,
|
||||
const WorldEditor::components::
|
||||
buildings_layout_area &area) {
|
||||
subregions->push_back({ ce, area.area });
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
struct queries {
|
||||
flecs::query_builder<WorldEditor::components::buildings_layout_grid_size>
|
||||
qp;
|
||||
flecs::query_builder<WorldEditor::components::buildings_layout_grid_floor,
|
||||
growth_regions>
|
||||
qr;
|
||||
flecs::query_builder<
|
||||
const WorldEditor::components::buildings_layout_grid_cell>
|
||||
mark_cells;
|
||||
HashMap<flecs::entity_t, List<Pair<flecs::entity, float> > >
|
||||
sub_subregions;
|
||||
flecs::query<WorldEditor::components::buildings_layout_grid_size>
|
||||
get_qp()
|
||||
{
|
||||
return qp.build();
|
||||
}
|
||||
flecs::query<WorldEditor::components::buildings_layout_grid_floor,
|
||||
growth_regions>
|
||||
get_qr()
|
||||
{
|
||||
return qr.build();
|
||||
}
|
||||
flecs::query<const WorldEditor::components::buildings_layout_grid_cell>
|
||||
get_mark_cells()
|
||||
{
|
||||
return mark_cells.build();
|
||||
}
|
||||
queries(flecs::world &w)
|
||||
: qp(w.query_builder<WorldEditor::components::
|
||||
buildings_layout_grid_size>()
|
||||
.write<WorldEditor::components::
|
||||
buildings_layout_grid>())
|
||||
, qr(w.query_builder<
|
||||
WorldEditor::components::buildings_layout_grid_floor,
|
||||
growth_regions>())
|
||||
, mark_cells(
|
||||
w.query_builder<const WorldEditor::components::
|
||||
buildings_layout_grid_cell>()
|
||||
.without<WorldEditor::components::outside_wall>()
|
||||
.read<WorldEditor::components::
|
||||
buildings_layout_grid_floor>()
|
||||
.write<WorldEditor::components::outside_wall>()
|
||||
.write<WorldEditor::components::final_cell>())
|
||||
{
|
||||
}
|
||||
int get_floor_index(flecs::entity e) const
|
||||
{
|
||||
return e.get<WorldEditor::components::
|
||||
buildings_layout_floor_index>()
|
||||
->index;
|
||||
}
|
||||
flecs::entity get_grid_floor(flecs::entity grid_e,
|
||||
flecs::entity graph_floor_e)
|
||||
{
|
||||
assert(grid_e.is_valid());
|
||||
assert(graph_floor_e.is_valid());
|
||||
int floor_index = get_floor_index(graph_floor_e);
|
||||
String floor_name = "floor_" + itos(floor_index);
|
||||
flecs::log::dbg("floor: %s", floor_name.ascii().ptr());
|
||||
flecs::entity floor_e = grid_e.lookup(floor_name.ascii().ptr());
|
||||
assert(floor_e.is_valid());
|
||||
return floor_e;
|
||||
}
|
||||
void get_subregions(flecs::entity parent,
|
||||
List<Pair<flecs::entity, float> > *subregions)
|
||||
{
|
||||
flecs::query<const WorldEditor::components::buildings_layout_area>
|
||||
qprep = parent.world()
|
||||
.query_builder<
|
||||
const WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
.with(flecs::ChildOf, parent)
|
||||
.scope_open()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_zone>()
|
||||
.or_()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_unit>()
|
||||
.or_()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_room>()
|
||||
.scope_close()
|
||||
.build();
|
||||
qprep.each([&subregions](flecs::entity ce,
|
||||
const WorldEditor::components::
|
||||
buildings_layout_area &area) {
|
||||
subregions->push_back({ ce, area.area });
|
||||
});
|
||||
}
|
||||
void build_subregions(
|
||||
flecs::entity grid_e, struct grid_misc &grid,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size)
|
||||
{
|
||||
const List<Pair<int, flecs::entity_t> >::Element *me =
|
||||
size.floors.front();
|
||||
List<flecs::entity_t> subregions_queue;
|
||||
while (me) {
|
||||
subregions_queue.push_back(me->get().second);
|
||||
flecs::entity_t base_floor_et = me->get().second;
|
||||
flecs::entity base_floor_e =
|
||||
grid_e.world().entity(base_floor_et);
|
||||
flecs::log::dbg("job_queue: base_floor: %s",
|
||||
base_floor_e.path().c_str());
|
||||
flecs::entity grid_floor_e =
|
||||
get_grid_floor(grid_e, base_floor_e);
|
||||
flecs::log::dbg("job_queue: grid_floor: %s",
|
||||
grid_floor_e.path().c_str());
|
||||
if (!grid_floor_e
|
||||
.has<WorldEditor::components::
|
||||
buildings_layout_grid_floor>())
|
||||
create_floor_components(grid_floor_e,
|
||||
base_floor_e, size);
|
||||
me = me->next();
|
||||
}
|
||||
while (!subregions_queue.empty()) {
|
||||
// eid is graph entity
|
||||
flecs::entity_t eid = subregions_queue.front()->get();
|
||||
subregions_queue.pop_front();
|
||||
List<Pair<flecs::entity, float> > subregions;
|
||||
flecs::entity item_e = grid_e.world().entity(eid);
|
||||
get_subregions(grid_e.world().entity(eid), &subregions);
|
||||
if (subregions.empty())
|
||||
flecs::log::dbg("!no subregions for: %s",
|
||||
item_e.path().c_str());
|
||||
sub_subregions[eid] = subregions;
|
||||
List<Pair<flecs::entity, float> >::Element *fe =
|
||||
subregions.front();
|
||||
while (fe) {
|
||||
subregions_queue.push_back(
|
||||
fe->get().first.id());
|
||||
fe = fe->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
void create_floor_components(
|
||||
flecs::entity floor_e, flecs::entity base_floor_e,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size)
|
||||
const
|
||||
{
|
||||
assert(!floor_e.has<
|
||||
WorldEditor::components::buildings_layout_grid_floor>());
|
||||
assert(!floor_e.has<growth_regions>());
|
||||
floor_e.set<WorldEditor::components::buildings_layout_grid_floor>(
|
||||
{ Set<int>(), size.grid_size, size.growth_size });
|
||||
floor_e.set<growth_regions>(
|
||||
{ Vector<struct growth_regions::region>(), false });
|
||||
floor_e.add<WorldEditor::components::belongs>(base_floor_e);
|
||||
}
|
||||
};
|
||||
struct grow_job_queue {
|
||||
struct grow_job {
|
||||
enum { INITIAL, COMMON };
|
||||
int job_type;
|
||||
flecs::entity_t parent_id;
|
||||
flecs::entity_t base_floor_id;
|
||||
flecs::entity_t grid_floor_id;
|
||||
List<Pair<flecs::entity, float> > subregions;
|
||||
struct grid_misc grid;
|
||||
};
|
||||
flecs::entity grid_e;
|
||||
int grid_size;
|
||||
struct queries &queries;
|
||||
const String &module_name;
|
||||
List<struct grow_job> job_list;
|
||||
grow_job_queue(
|
||||
flecs::entity grid_e, struct grid_misc &grid,
|
||||
struct queries &queries,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size,
|
||||
const String &module_name);
|
||||
void iterate();
|
||||
};
|
||||
grow_job_queue::grow_job_queue(
|
||||
flecs::entity grid_e, struct grid_misc &grid, struct queries &queries,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size,
|
||||
const String &module_name)
|
||||
: grid_e(grid_e)
|
||||
, grid_size(size.grid_size)
|
||||
, queries(queries)
|
||||
, module_name(module_name)
|
||||
{
|
||||
const List<Pair<int, flecs::entity_t> >::Element *me;
|
||||
List<Pair<flecs::entity_t, flecs::entity_t> > job_create_queue;
|
||||
me = size.floors.front();
|
||||
while (me) {
|
||||
// graph entity
|
||||
job_create_queue.push_back(
|
||||
{ me->get().second, me->get().second });
|
||||
me = me->next();
|
||||
}
|
||||
while (!job_create_queue.empty()) {
|
||||
// graph entity
|
||||
flecs::entity_t et = job_create_queue.front()->get().first;
|
||||
// parent graph entity
|
||||
flecs::entity_t base_floor_et =
|
||||
job_create_queue.front()->get().second;
|
||||
job_create_queue.pop_front();
|
||||
flecs::entity base_floor_e =
|
||||
grid_e.world().entity(base_floor_et);
|
||||
flecs::log::dbg("job_queue: base_floor: %s",
|
||||
base_floor_e.path().c_str());
|
||||
flecs::entity grid_floor_e =
|
||||
grid.get_grid_floor(grid_e, base_floor_e);
|
||||
flecs::log::dbg("job_queue: grid_floor: %s",
|
||||
grid_floor_e.path().c_str());
|
||||
if (queries.sub_subregions.has(et) &&
|
||||
!queries.sub_subregions[et].empty()) {
|
||||
flecs::log::dbg(
|
||||
"subregions for: %s",
|
||||
grid_e.world().entity(et).path().c_str());
|
||||
struct grow_job job;
|
||||
if (job_list.size() == 0)
|
||||
job.job_type = grow_job::INITIAL;
|
||||
else
|
||||
job.job_type = grow_job::COMMON;
|
||||
job.parent_id = et;
|
||||
job.base_floor_id = base_floor_et;
|
||||
job.grid_floor_id = grid_floor_e.id();
|
||||
job.subregions = queries.sub_subregions[job.parent_id];
|
||||
job_list.push_back(job);
|
||||
List<Pair<flecs::entity, float> >::Element *se =
|
||||
job.subregions.front();
|
||||
while (se) {
|
||||
job_create_queue.push_back(
|
||||
{ se->get().first.id(),
|
||||
base_floor_et });
|
||||
se = se->next();
|
||||
}
|
||||
} else
|
||||
flecs::log::dbg(
|
||||
"no subregions for: %s",
|
||||
grid_e.world().entity(et).path().c_str());
|
||||
}
|
||||
flecs::log::dbg("created jobs: %d", job_list.size());
|
||||
}
|
||||
void grow_job_queue::iterate()
|
||||
{
|
||||
while (!job_list.empty()) {
|
||||
List<struct grow_job>::Element *job_e = job_list.front();
|
||||
const List<Pair<flecs::entity, float> > &subregions =
|
||||
job_e->get().subregions;
|
||||
const List<Pair<flecs::entity, float> >::Element *fe =
|
||||
subregions.front();
|
||||
flecs::entity base_floor_e =
|
||||
grid_e.world().entity(job_e->get().base_floor_id);
|
||||
flecs::entity grid_floor_e =
|
||||
grid_e.world().entity(job_e->get().grid_floor_id);
|
||||
flecs::log::dbg("create: base_floor: %s",
|
||||
base_floor_e.path().c_str());
|
||||
flecs::log::dbg("create: grid_floor: %s",
|
||||
grid_floor_e.path().c_str());
|
||||
growth_regions *g = grid_floor_e.get_mut<growth_regions>();
|
||||
switch (job_e->get().job_type) {
|
||||
case grow_job::INITIAL: {
|
||||
int i;
|
||||
Rect2i clip_rect(0, 0, grid_size, grid_size);
|
||||
bool restart = false, found = false;
|
||||
for (i = 0; i < (int)g->regions.size(); i++) {
|
||||
flecs::log::dbg(
|
||||
"region %d: %s", i,
|
||||
grid_e.world()
|
||||
.entity(g->regions[i].region_et)
|
||||
.path()
|
||||
.c_str());
|
||||
if (g->regions[i].region_et ==
|
||||
job_e->get().parent_id) {
|
||||
flecs::log::err(
|
||||
"parent is in regions %d", i);
|
||||
if (!g->regions[i].complete) {
|
||||
job_list.push_back(
|
||||
job_e->get());
|
||||
job_list.pop_front();
|
||||
restart = true;
|
||||
flecs::log::err(
|
||||
"parent is in regions %d incomplete",
|
||||
i);
|
||||
flecs::log::warn(
|
||||
"delay job fo %s (%d jobs)",
|
||||
grid_e.world()
|
||||
.entity(job_e->get()
|
||||
.parent_id)
|
||||
.path()
|
||||
.c_str(),
|
||||
job_list.size());
|
||||
break;
|
||||
} else {
|
||||
clip_rect = g->regions[i].rect;
|
||||
g->regions.remove(i);
|
||||
break;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found && g->regions.size() > 0) {
|
||||
flecs::entity parent_e = grid_e.world().entity(
|
||||
job_e->get().parent_id);
|
||||
if (base_floor_e != parent_e.parent()) {
|
||||
// no parent region yet
|
||||
flecs::log::warn(
|
||||
"%s != %s",
|
||||
base_floor_e.path().c_str(),
|
||||
parent_e.parent()
|
||||
.path()
|
||||
.c_str());
|
||||
job_list.push_back(job_e->get());
|
||||
job_list.pop_front();
|
||||
flecs::log::warn(
|
||||
"delay job fo %s (%d jobs)",
|
||||
parent_e.path().c_str(),
|
||||
job_list.size());
|
||||
restart = true;
|
||||
}
|
||||
}
|
||||
if (restart)
|
||||
continue;
|
||||
|
||||
while (fe) {
|
||||
flecs::entity ce = fe->get().first;
|
||||
float area = fe->get().second;
|
||||
flecs::log::warn("generating positions for: %s",
|
||||
ce.path().c_str());
|
||||
job_e->get().grid.filter_candidates(ce, area,
|
||||
clip_rect);
|
||||
fe = fe->next();
|
||||
}
|
||||
job_e->get().grid.place_regions(grid_floor_e);
|
||||
|
||||
flecs::log::dbg("Running grow...");
|
||||
queries.get_qr().each(
|
||||
[this](flecs::entity grid_floor_e,
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_floor &fl,
|
||||
growth_regions &g) {
|
||||
struct grid_misc grd;
|
||||
if (g.complete)
|
||||
return;
|
||||
grd.grow_region_rects(
|
||||
this, grid_floor_e, fl, g);
|
||||
grd.place_region_cells(grid_floor_e, fl,
|
||||
g);
|
||||
});
|
||||
queries.get_qr().each(
|
||||
[](flecs::entity grid_floor_e,
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_floor &fl,
|
||||
growth_regions &g) {
|
||||
int i;
|
||||
for (i = 0; i < (int)g.regions.size();
|
||||
i++)
|
||||
g.regions.write[i].complete =
|
||||
true;
|
||||
g.complete = true;
|
||||
});
|
||||
grid_e.world()
|
||||
.system(grid_e.world().lookup(
|
||||
(module_name + "::GrowCommitQueue")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
queries.get_mark_cells().each([](flecs::entity e,
|
||||
const WorldEditor::
|
||||
components::buildings_layout_grid_cell
|
||||
&cell) {
|
||||
int grid_size =
|
||||
e.parent()
|
||||
.get<WorldEditor::components::
|
||||
buildings_layout_grid_floor>()
|
||||
->grid_size;
|
||||
int i;
|
||||
Vector2i position(cell.index % grid_size,
|
||||
cell.index / grid_size);
|
||||
Vector2 west(position.x - 1, position.y);
|
||||
Vector2 north(position.x, position.y - 1);
|
||||
Vector2 east(position.x + 1, position.y);
|
||||
Vector2 south(position.x, position.y + 1);
|
||||
int west_id = west.x + grid_size * west.y;
|
||||
int north_id = north.x + grid_size * north.y;
|
||||
int east_id = east.x + grid_size * east.y;
|
||||
int south_id = south.x + grid_size * south.y;
|
||||
std::vector<int> neighbors = {
|
||||
west_id, north_id, east_id, south_id
|
||||
};
|
||||
bool outside = false;
|
||||
bool border = false;
|
||||
for (i = 0; i < (int)neighbors.size(); i++) {
|
||||
int id = neighbors[i];
|
||||
print_line("id=" + itos(id));
|
||||
if (!e.parent()
|
||||
.get<WorldEditor::components::
|
||||
buildings_layout_grid_floor>()
|
||||
->cells.has(id)) {
|
||||
outside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (int)neighbors.size(); i++) {
|
||||
int id = neighbors[i];
|
||||
print_line("id=" + itos(id));
|
||||
String neighbor_name =
|
||||
"cell_" + itos(id);
|
||||
flecs::entity neighbor_e =
|
||||
e.parent().lookup(
|
||||
neighbor_name.ascii()
|
||||
.ptr());
|
||||
if (!neighbor_e.is_valid())
|
||||
continue;
|
||||
const WorldEditor::components::buildings_layout_grid_cell
|
||||
*neighbor_cell = neighbor_e.get<
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_cell>();
|
||||
if (cell.type != neighbor_cell->type) {
|
||||
border = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (outside)
|
||||
e.add<WorldEditor::components::
|
||||
outside_wall>();
|
||||
else
|
||||
e.add<WorldEditor::components::
|
||||
final_cell>();
|
||||
if (border)
|
||||
e.add<WorldEditor::components::border>();
|
||||
print_line("outside: " + itos(outside));
|
||||
print_line("position: " +
|
||||
(position.operator String()));
|
||||
print_line("grid size: " + itos(grid_size));
|
||||
print_line("tile index: " + itos(cell.index));
|
||||
});
|
||||
} break;
|
||||
}
|
||||
job_list.pop_front();
|
||||
}
|
||||
flecs::log::dbg("processed jobs (created region initial positions): %d",
|
||||
job_list.size());
|
||||
}
|
||||
void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
|
||||
const String &module_name)
|
||||
{
|
||||
@@ -583,6 +1194,7 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
|
||||
.add(flecs::Phase)
|
||||
.depends_on(GraphSolve);
|
||||
|
||||
#if 0
|
||||
ecs.system<const WorldEditor::components::buildings_layout_grid_size>(
|
||||
"CreateGrid")
|
||||
.kind(GraphSolve)
|
||||
@@ -646,6 +1258,7 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
|
||||
}
|
||||
graph_e.world().defer_resume();
|
||||
});
|
||||
#endif
|
||||
ecs.system("AssembleSkeletonEnd")
|
||||
.kind(GraphSolve)
|
||||
.run([module_name](flecs::iter &it) {
|
||||
@@ -795,49 +1408,63 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
|
||||
buildings_layout_grid_queue>();
|
||||
});
|
||||
ecs.system("RunGrow")
|
||||
.immediate()
|
||||
.write<WorldEditor::components::buildings_layout_grid_floor>()
|
||||
.write<WorldEditor::components::buildings_layout_grid_size>()
|
||||
.write<growth_regions>()
|
||||
.kind(GraphFilter)
|
||||
.run([module_name, this](flecs::iter &it) {
|
||||
int i;
|
||||
flecs::world &&ecs = it.world();
|
||||
struct queries queries(ecs);
|
||||
it.world().defer_suspend();
|
||||
flecs::log::dbg("Running grow...");
|
||||
flecs::query<WorldEditor::components::
|
||||
buildings_layout_grid_floor,
|
||||
growth_regions>
|
||||
q = it.world()
|
||||
.query_builder<
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_floor,
|
||||
growth_regions>()
|
||||
.build();
|
||||
for (i = 0; i < 100; i++)
|
||||
q.each([this](flecs::entity grid_floor_e,
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_floor
|
||||
&fl,
|
||||
growth_regions &g) {
|
||||
flecs::log::dbg("Creating regions grow...");
|
||||
queries.get_qp().each(
|
||||
[this, &queries,
|
||||
module_name](flecs::iter &it2, size_t count,
|
||||
const WorldEditor::components::
|
||||
buildings_layout_grid_size
|
||||
&size) {
|
||||
struct grid_misc grid;
|
||||
if (g.complete)
|
||||
return;
|
||||
grid.grow_region_rects(
|
||||
this, grid_floor_e, fl, g);
|
||||
grid.place_region_cells(
|
||||
this, grid_floor_e, fl, g);
|
||||
grid.subregions_init(it2.world());
|
||||
flecs::entity graph_e =
|
||||
it2.entity(count);
|
||||
flecs::log::warn(
|
||||
"creating grid for: %s",
|
||||
graph_e.path().c_str());
|
||||
flecs::entity grid_base_e =
|
||||
get_layout_grid_base();
|
||||
flecs::entity grid_e =
|
||||
grid_base_e.lookup(
|
||||
graph_e.name());
|
||||
assert(grid_e.is_valid());
|
||||
flecs::log::warn(
|
||||
"creating grid for: %s: %s",
|
||||
graph_e.path().c_str(),
|
||||
grid_e.path().c_str());
|
||||
/* starting at grid center */
|
||||
queries.build_subregions(grid_e, grid,
|
||||
size);
|
||||
struct grow_job_queue job_queue(
|
||||
grid_e, grid, queries, size,
|
||||
module_name);
|
||||
job_queue.iterate();
|
||||
// assert(false);
|
||||
});
|
||||
#if 0
|
||||
q.each([this](flecs::entity grid_floor_e,
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_floor &fl,
|
||||
growth_regions &g) {
|
||||
g.complete = true;
|
||||
assert(false);
|
||||
flecs::log::dbg("Running grow...");
|
||||
qr.each([this](flecs::entity grid_floor_e,
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_floor &fl,
|
||||
growth_regions &g) {
|
||||
struct grid_misc grd;
|
||||
if (g.complete)
|
||||
return;
|
||||
grd.grow_region_rects(this, grid_floor_e, fl,
|
||||
g);
|
||||
grd.place_region_cells(this, grid_floor_e, fl,
|
||||
g);
|
||||
});
|
||||
#endif
|
||||
#if 0
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
(module_name + "::GrowFloorRectRegions")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
#endif
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
@@ -845,6 +1472,11 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
it.world()
|
||||
.lookup((module_name + "::GraphFilter")
|
||||
.ascii()
|
||||
.ptr())
|
||||
.disable();
|
||||
it.world().defer_resume();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user