Reworked growing of regions into jbo system

This commit is contained in:
2024-11-19 12:33:16 +03:00
parent aff536d37f
commit 5d59a15e36
3 changed files with 729 additions and 79 deletions

View File

@@ -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, void BuildingLayoutGraph::graph_module::queue_grow_cell(flecs::entity seed_e,
int id) int id)
{ {
assert(seed_e.is_valid());
flecs::entity floor_e = seed_e.parent(); 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< assert(floor_e.has<
WorldEditor::components::buildings_layout_grid_floor>()); WorldEditor::components::buildings_layout_grid_floor>());
Pair<flecs::entity_t, int> m(seed_e.id(), id); 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, flecs::entity floor_e, flecs::entity base_floor_e,
const WorldEditor::components::buildings_layout_grid_size &size) 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>( floor_e.set<WorldEditor::components::buildings_layout_grid_floor>(
{ Set<int>(), size.grid_size, size.growth_size }); { Set<int>(), size.grid_size, size.growth_size });
floor_e.set<growth_regions>( 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, void growth_regions::create_region(flecs::entity floor_e, flecs::entity seed_e,
flecs::entity parent_e,
flecs::entity region_e, flecs::entity region_e,
const Vector2i &position, float area) const Vector2i &position, float area)
{ {
int i; int i;
struct growth_regions::region r; struct growth_regions::region r;
r.parent = parent_e.id();
r.seed_et = seed_e.id(); r.seed_et = seed_e.id();
r.region_et = region_e.id(); r.region_et = region_e.id();
r.rect.position = position; 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.remains_area = MAX((int)(area * 2.0f) / 16 + 1, 16);
r.can_grow_square = true; r.can_grow_square = true;
r.can_grow = true; r.can_grow = true;
r.complete = false;
bool ok = true; bool ok = true;
assert(check_region(-1, r.rect)); assert(check_region(-1, r.rect));
const struct growth_regions *reg = floor_e.get<growth_regions>(); 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 region_e, int id)
{ {
flecs::entity ret; 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>() if (floor_e.get<WorldEditor::components::buildings_layout_grid_floor>()
->cells.has(id)) { ->cells.has(id)) {
flecs::log::err("cell %d already exists", 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(); ->get_layout_grid_base();
flecs::entity grid_e = flecs::entity grid_e =
grid_base_e.lookup(graph_e.name()); 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()) if (grid_e.is_valid())
grid_e.destruct(); grid_e.destruct();
it.world().defer_resume(); it.world().defer_resume();

View File

@@ -2,12 +2,14 @@
#define GRAPH_MODULE_H_ #define GRAPH_MODULE_H_
struct growth_regions { struct growth_regions {
struct region { struct region {
flecs::entity_t parent;
flecs::entity_t seed_et; flecs::entity_t seed_et;
flecs::entity_t region_et; flecs::entity_t region_et;
Rect2i rect; Rect2i rect;
int remains_area; int remains_area;
bool can_grow_square; bool can_grow_square;
bool can_grow; bool can_grow;
bool complete;
bool can_grow_region() const bool can_grow_region() const
{ {
bool ret = can_grow; bool ret = can_grow;
@@ -62,8 +64,8 @@ struct growth_regions {
return ret; return ret;
} }
void create_region(flecs::entity floor_e, flecs::entity seed_e, void create_region(flecs::entity floor_e, flecs::entity seed_e,
flecs::entity region_e, const Vector2i &position, flecs::entity parent_e, flecs::entity region_e,
float area); const Vector2i &position, float area);
flecs::entity create_cell(flecs::entity floor_e, flecs::entity region_e, flecs::entity create_cell(flecs::entity floor_e, flecs::entity region_e,
int id); int id);
}; };

View File

@@ -116,6 +116,7 @@ out:
.get<WorldEditor::components:: .get<WorldEditor::components::
buildings_layout_grid_floor>() buildings_layout_grid_floor>()
->grid_size; ->grid_size;
flecs::log::dbg("###=== %s", grid_floor_e.path().c_str());
flecs::entity grid_e = grid_floor_e.parent(); flecs::entity grid_e = grid_floor_e.parent();
assert(grid_e.is_valid()); assert(grid_e.is_valid());
growth_regions *g = grid_floor_e.get_mut<growth_regions>(); growth_regions *g = grid_floor_e.get_mut<growth_regions>();
@@ -128,15 +129,23 @@ out:
Rect2i check; Rect2i check;
check.position = positions[i].second; check.position = positions[i].second;
check.size = Vector2i(1, 1); 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)); assert(g->check_region(-1, check));
flecs::entity cell_e = flecs::entity cell_e =
g->create_cell(grid_floor_e, region_e, cell_id); g->create_cell(grid_floor_e, region_e, cell_id);
float area = get_entity_area(region_e); 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); positions[i].second, area);
flecs::log::warn("grid cell: %s", flecs::log::warn("grid cell: %s",
cell_e.path().c_str()); cell_e.path().c_str());
} }
flecs::log::dbg("###=== %s done", grid_floor_e.path().c_str());
} }
float get_entity_area(flecs::entity e) const float get_entity_area(flecs::entity e) const
{ {
@@ -220,20 +229,49 @@ out:
int radius = pdim + local_radius; int radius = pdim + local_radius;
int radius_sq = radius * radius; int radius_sq = radius * radius;
if (distance_squared(positions[k].second, candidate) < 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; continue;
}
assert(check_candidates_tolerance(candidate)); assert(check_candidates_tolerance(candidate));
accepted.push_back(candidate); accepted.push_back(candidate);
ok = true; ok = true;
} }
return ok; return ok;
} }
bool process_candidates( bool accept_candidate2(flecs::entity ce, const Vector2i &candidate)
flecs::entity ce, const Vector2i &base, float area, {
const WorldEditor::components::buildings_layout_grid_size &size, int k;
flecs::entity_t base_et, int dim) 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; int j;
assert(dim > 1);
int base_radius = get_base_radius(ce.world(), base_et); int base_radius = get_base_radius(ce.world(), base_et);
base_radius = MAX(1, base_radius); base_radius = MAX(1, base_radius);
int local_radius = (int)((Math::sqrt(area) * 1.6f) / 2.0f) / int local_radius = (int)((Math::sqrt(area) * 1.6f) / 2.0f) /
@@ -241,18 +279,8 @@ out:
local_radius = MAX(1, local_radius); local_radius = MAX(1, local_radius);
// int dim = base_radius + local_radius; // int dim = base_radius + local_radius;
// dim = MAX(4, dim); // 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]; Vector2i candidates[8];
assert(clip.has_point(base));
get_dim_candidates(base, dim, &candidates[0]); get_dim_candidates(base, dim, &candidates[0]);
for (j = 0; for (j = 0;
j < (int)(sizeof(candidates) / sizeof(candidates[0])); j < (int)(sizeof(candidates) / sizeof(candidates[0]));
@@ -278,21 +306,27 @@ out:
} }
print_line("valid candidate: " + itos(candidates[j].x) + print_line("valid candidate: " + itos(candidates[j].x) +
", " + itos(candidates[j].y)); ", " + 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) if (accepted.size() > 0)
return true; return true;
else else
return false; return false;
} }
void filter_candidates( void filter_candidates(flecs::entity ce, float area,
flecs::entity ce, float area, const Rect2i &clip_rect)
const WorldEditor::components::buildings_layout_grid_size &size)
{ {
if (positions.empty()) { if (positions.empty()) {
/* starting at grid center */ /* starting at grid center */
Vector2i start_pos(size.grid_size / 2, Vector2i start_pos(
size.grid_size / 2); 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>( positions.push_back(Pair<flecs::entity_t, Vector2i>(
ce.id(), start_pos)); ce.id(), start_pos));
return; return;
@@ -307,23 +341,78 @@ out:
(int)((Math::sqrt(area) * 1.6f) / 2.0f) / (int)((Math::sqrt(area) * 1.6f) / 2.0f) /
4; /* grid conversion */ 4; /* grid conversion */
local_radius = MAX(1, local_radius); local_radius = MAX(1, local_radius);
/* minimum distance between region positions */
int dim = base_radius + local_radius; int dim = base_radius + local_radius;
dim = MAX(1, dim); dim = MAX(2, dim);
process_candidates(ce, base, area, size, base_et, dim); int md = 1;
if (accepted.size() == 0) { 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); assert(positions.size() > 0);
continue; 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() int which_position()
@@ -344,9 +433,8 @@ out:
assert(which < (int)accepted.size()); assert(which < (int)accepted.size());
return which; return which;
} }
template <class T>
void place_region_cells( void place_region_cells(
T *obj, flecs::entity grid_floor_e, flecs::entity grid_floor_e,
const WorldEditor::components::buildings_layout_grid_floor &fl, const WorldEditor::components::buildings_layout_grid_floor &fl,
growth_regions &g) growth_regions &g)
{ {
@@ -365,12 +453,46 @@ out:
g.regions[i] g.regions[i]
.seed_et); .seed_et);
assert(seed_e.is_valid()); assert(seed_e.is_valid());
obj->queue_grow_cell(seed_e, assert(seed_e.parent()
id); .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, void print_can_grow(int state, growth_regions &g, int index,
const char *what) const char *what)
{ {
@@ -458,6 +580,14 @@ out:
break; break;
} }
ok = clip.encloses(mrect); 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) if (ok)
ok = g.check_region(index, mrect); ok = g.check_region(index, mrect);
if (ok) { if (ok) {
@@ -569,8 +699,489 @@ out:
flecs::log::dbg("grow_region_rects: %s: done", flecs::log::dbg("grow_region_rects: %s: done",
floor_e.path().c_str()); 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, void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
const String &module_name) const String &module_name)
{ {
@@ -583,6 +1194,7 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
.add(flecs::Phase) .add(flecs::Phase)
.depends_on(GraphSolve); .depends_on(GraphSolve);
#if 0
ecs.system<const WorldEditor::components::buildings_layout_grid_size>( ecs.system<const WorldEditor::components::buildings_layout_grid_size>(
"CreateGrid") "CreateGrid")
.kind(GraphSolve) .kind(GraphSolve)
@@ -646,6 +1258,7 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
} }
graph_e.world().defer_resume(); graph_e.world().defer_resume();
}); });
#endif
ecs.system("AssembleSkeletonEnd") ecs.system("AssembleSkeletonEnd")
.kind(GraphSolve) .kind(GraphSolve)
.run([module_name](flecs::iter &it) { .run([module_name](flecs::iter &it) {
@@ -795,49 +1408,63 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
buildings_layout_grid_queue>(); buildings_layout_grid_queue>();
}); });
ecs.system("RunGrow") ecs.system("RunGrow")
.immediate()
.write<WorldEditor::components::buildings_layout_grid_floor>()
.write<WorldEditor::components::buildings_layout_grid_size>()
.write<growth_regions>()
.kind(GraphFilter) .kind(GraphFilter)
.run([module_name, this](flecs::iter &it) { .run([module_name, this](flecs::iter &it) {
int i; flecs::world &&ecs = it.world();
struct queries queries(ecs);
it.world().defer_suspend(); it.world().defer_suspend();
flecs::log::dbg("Running grow..."); flecs::log::dbg("Creating regions grow...");
flecs::query<WorldEditor::components:: queries.get_qp().each(
buildings_layout_grid_floor, [this, &queries,
growth_regions> module_name](flecs::iter &it2, size_t count,
q = it.world() const WorldEditor::components::
.query_builder< buildings_layout_grid_size
WorldEditor::components:: &size) {
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) {
struct grid_misc grid; struct grid_misc grid;
if (g.complete) grid.subregions_init(it2.world());
return; flecs::entity graph_e =
grid.grow_region_rects( it2.entity(count);
this, grid_floor_e, fl, g); flecs::log::warn(
grid.place_region_cells( "creating grid for: %s",
this, grid_floor_e, fl, g); 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 #if 0
q.each([this](flecs::entity grid_floor_e, assert(false);
WorldEditor::components:: flecs::log::dbg("Running grow...");
buildings_layout_grid_floor &fl, qr.each([this](flecs::entity grid_floor_e,
growth_regions &g) { WorldEditor::components::
g.complete = true; 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 #endif
it.world() it.world()
.system(it.world().lookup( .system(it.world().lookup(
@@ -845,6 +1472,11 @@ void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
.ascii() .ascii()
.ptr())) .ptr()))
.run(); .run();
it.world()
.lookup((module_name + "::GraphFilter")
.ascii()
.ptr())
.disable();
it.world().defer_resume(); it.world().defer_resume();
}); });
} }