From 5d59a15e368b24c541e1ea2af759ab3aaee2bb63 Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Tue, 19 Nov 2024 12:33:16 +0300 Subject: [PATCH] Reworked growing of regions into jbo system --- src/modules/stream/ui/graph_module.cpp | 18 +- src/modules/stream/ui/graph_module.h | 6 +- src/modules/stream/ui/graph_module_growth.cpp | 784 ++++++++++++++++-- 3 files changed, 729 insertions(+), 79 deletions(-) diff --git a/src/modules/stream/ui/graph_module.cpp b/src/modules/stream/ui/graph_module.cpp index 1d28810..ef003c9 100644 --- a/src/modules/stream/ui/graph_module.cpp +++ b/src/modules/stream/ui/graph_module.cpp @@ -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()) + 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 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()); floor_e.set( { Set(), size.grid_size, size.growth_size }); floor_e.set( @@ -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(); @@ -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() ->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(); diff --git a/src/modules/stream/ui/graph_module.h b/src/modules/stream/ui/graph_module.h index b59018c..5a8aa3d 100644 --- a/src/modules/stream/ui/graph_module.h +++ b/src/modules/stream/ui/graph_module.h @@ -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); }; diff --git a/src/modules/stream/ui/graph_module_growth.cpp b/src/modules/stream/ui/graph_module_growth.cpp index a655d63..252ac26 100644 --- a/src/modules/stream/ui/graph_module_growth.cpp +++ b/src/modules/stream/ui/graph_module_growth.cpp @@ -116,6 +116,7 @@ out: .get() ->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(); @@ -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( 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 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 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 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()) + 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 m(seed_e.id(), id); + if (!floor_e.has()) { + List > queue; + queue.push_back(m); + floor_e.set( + { queue }); + } else { + floor_e.get_mut() + ->queue.push_back(m); + floor_e.modified(); + } + } 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 > all_items; + void subregions_init(flecs::world w) + { + flecs::query + qprep = w.query_builder() + .scope_open() + .with() + .or_() + .with() + .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 > *subregions) + { + flecs::query + qprep = parent.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_area>() + .with(flecs::ChildOf, parent) + .scope_open() + .with() + .or_() + .with() + .or_() + .with() + .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 + qp; + flecs::query_builder + qr; + flecs::query_builder< + const WorldEditor::components::buildings_layout_grid_cell> + mark_cells; + HashMap > > + sub_subregions; + flecs::query + get_qp() + { + return qp.build(); + } + flecs::query + get_qr() + { + return qr.build(); + } + flecs::query + get_mark_cells() + { + return mark_cells.build(); + } + queries(flecs::world &w) + : qp(w.query_builder() + .write()) + , qr(w.query_builder< + WorldEditor::components::buildings_layout_grid_floor, + growth_regions>()) + , mark_cells( + w.query_builder() + .without() + .read() + .write() + .write()) + { + } + int get_floor_index(flecs::entity e) const + { + return e.get() + ->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 > *subregions) + { + flecs::query + qprep = parent.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_area>() + .with(flecs::ChildOf, parent) + .scope_open() + .with() + .or_() + .with() + .or_() + .with() + .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 >::Element *me = + size.floors.front(); + List 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()) + 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 > 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 >::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()); + floor_e.set( + { Set(), size.grid_size, size.growth_size }); + floor_e.set( + { Vector(), false }); + floor_e.add(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 > subregions; + struct grid_misc grid; + }; + flecs::entity grid_e; + int grid_size; + struct queries &queries; + const String &module_name; + List 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 >::Element *me; + List > 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 >::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::Element *job_e = job_list.front(); + const List > &subregions = + job_e->get().subregions; + const List >::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(); + 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() + ->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 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() + ->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(); + else + e.add(); + if (border) + e.add(); + 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( "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() + .write() + .write() .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 - 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(); }); }