diff --git a/godot/astream/building_layout_data.conf b/godot/astream/building_layout_data.conf index ae1773c..f1cd86f 100644 --- a/godot/astream/building_layout_data.conf +++ b/godot/astream/building_layout_data.conf @@ -33,7 +33,7 @@ entries=[ { "order": 4, "type": "layout" }, { -"children": [ 18, 19 ], +"children": [ 18, 19, 20 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 4, "name": "zone_0", @@ -41,7 +41,7 @@ entries=[ { "type": "zone", "zone_type": 1 }, { -"children": [ 20, 21, 22 ], +"children": [ 21, 22, 23 ], "commands": [ [ 4, [ ] ] ], "index": 5, "name": "zone_1", @@ -49,7 +49,7 @@ entries=[ { "type": "zone", "zone_type": 0 }, { -"children": [ 23, 24, 25, 26 ], +"children": [ 24, 25, 26, 27 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 6, "name": "zone_1", @@ -57,7 +57,7 @@ entries=[ { "type": "zone", "zone_type": 1 }, { -"children": [ 27, 28, 29 ], +"children": [ 28, 29, 30 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 7, "name": "zone_0", @@ -65,14 +65,14 @@ entries=[ { "type": "zone", "zone_type": 0 }, { -"children": [ 30, 31 ], +"children": [ 31, 32 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 8, "name": "unit_0", "order": 3, "type": "unit" }, { -"children": [ 32, 33 ], +"children": [ 33, 34 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 9, "name": "zone_0", @@ -80,35 +80,35 @@ entries=[ { "type": "zone", "zone_type": 1 }, { -"children": [ 34, 35 ], +"children": [ 35, 36 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 10, "name": "unit_0", "order": 0, "type": "unit" }, { -"children": [ 36, 37 ], +"children": [ 37, 38 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 11, "name": "unit_1", "order": 0, "type": "unit" }, { -"children": [ 38, 39 ], +"children": [ 39, 40 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 12, "name": "unit_2", "order": 0, "type": "unit" }, { -"children": [ 40, 41 ], +"children": [ 41, 42 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 13, "name": "unit_3", "order": 0, "type": "unit" }, { -"children": [ 42, 43 ], +"children": [ 43, 44 ], "commands": [ ], "index": 14, "name": "zone_0", @@ -116,7 +116,7 @@ entries=[ { "type": "zone", "zone_type": 0 }, { -"children": [ 44, 45 ], +"children": [ 45, 46 ], "commands": [ ], "index": 15, "name": "zone_1", @@ -124,7 +124,7 @@ entries=[ { "type": "zone", "zone_type": 0 }, { -"children": [ 46, 47, 48 ], +"children": [ 47, 48, 49 ], "commands": [ ], "index": 16, "name": "zone_2", @@ -132,7 +132,7 @@ entries=[ { "type": "zone", "zone_type": 0 }, { -"children": [ 49, 50, 51, 52, 53 ], +"children": [ 50, 51, 52, 53, 54 ], "commands": [ ], "index": 17, "name": "zone_3", @@ -161,8 +161,18 @@ entries=[ { "window": true }, { "children": [ ], -"commands": [ [ 5, [ ] ] ], +"commands": [ ], "index": 20, +"name": "office_0", +"order": 3, +"room_area": 16.0, +"room_type": 309, +"type": "room", +"window": true +}, { +"children": [ ], +"commands": [ [ 5, [ ] ] ], +"index": 21, "name": "wc_0", "order": 0, "room_area": 16.0, @@ -172,7 +182,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ], [ 3, [ ] ] ], -"index": 21, +"index": 22, "name": "bathroom_0", "order": 1, "room_area": 16.0, @@ -182,7 +192,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 22, +"index": 23, "name": "bedroom_0", "order": 2, "room_area": 64.0, @@ -192,7 +202,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 23, +"index": 24, "name": "living_room_0", "order": 0, "room_area": 144.0, @@ -202,7 +212,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 24, +"index": 25, "name": "kitchen_0", "order": 1, "room_area": 64.0, @@ -212,7 +222,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 25, +"index": 26, "name": "storage_room_0", "order": 2, "room_area": 16.0, @@ -222,7 +232,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ], [ 4, [ ] ] ], -"index": 26, +"index": 27, "name": "enterance_0", "order": 3, "room_area": 16.0, @@ -232,7 +242,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 27, +"index": 28, "name": "wc_0", "order": 0, "room_area": 16.0, @@ -242,7 +252,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 28, +"index": 29, "name": "bathroom_0", "order": 1, "room_area": 16.0, @@ -252,7 +262,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 29, +"index": 30, "name": "bedroom_0", "order": 2, "room_area": 64.0, @@ -260,17 +270,17 @@ entries=[ { "type": "room", "window": true }, { -"children": [ 54, 55, 56 ], +"children": [ 55, 56, 57 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], -"index": 30, +"index": 31, "name": "zone_0", "order": 0, "type": "zone", "zone_type": 0 }, { -"children": [ 57, 58 ], +"children": [ 58, 59 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], -"index": 31, +"index": 32, "name": "zone_1", "order": 0, "type": "zone", @@ -278,7 +288,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 32, +"index": 33, "name": "enterance_0", "order": 0, "room_area": 64.0, @@ -286,9 +296,9 @@ entries=[ { "type": "room", "window": true }, { -"children": [ 59 ], +"children": [ 60 ], "commands": [ [ 5, [ ] ] ], -"index": 33, +"index": 34, "name": "stair_0", "order": 0, "room_area": 16.0, @@ -296,65 +306,65 @@ entries=[ { "type": "room", "window": true }, { -"children": [ 60, 61, 62 ], -"commands": [ [ 3, [ ] ], [ 4, [ ] ] ], -"index": 34, -"name": "zone_0", -"order": 0, -"type": "zone", -"zone_type": 0 -}, { -"children": [ 63, 64 ], +"children": [ 61, 62, 63 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 35, -"name": "zone_1", +"name": "zone_0", "order": 0, "type": "zone", -"zone_type": 1 +"zone_type": 0 }, { -"children": [ 65 ], +"children": [ 64, 65 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 36, -"name": "zone_0", -"order": 0, -"type": "zone", -"zone_type": 0 -}, { -"children": [ 66, 67 ], -"commands": [ [ 3, [ ] ], [ 4, [ ] ] ], -"index": 37, "name": "zone_1", "order": 0, "type": "zone", "zone_type": 1 }, { -"children": [ 68 ], +"children": [ 66 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], -"index": 38, +"index": 37, "name": "zone_0", "order": 0, "type": "zone", "zone_type": 0 }, { +"children": [ 67, 68 ], +"commands": [ [ 3, [ ] ], [ 4, [ ] ] ], +"index": 38, +"name": "zone_1", +"order": 0, +"type": "zone", +"zone_type": 1 +}, { "children": [ 69 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 39, -"name": "zone_1", -"order": 1, -"type": "zone", -"zone_type": 1 -}, { -"children": [ 70 ], -"commands": [ [ 3, [ ] ], [ 4, [ ] ] ], -"index": 40, "name": "zone_0", "order": 0, "type": "zone", "zone_type": 0 }, { +"children": [ 70 ], +"commands": [ [ 3, [ ] ], [ 4, [ ] ] ], +"index": 40, +"name": "zone_1", +"order": 1, +"type": "zone", +"zone_type": 1 +}, { "children": [ 71 ], "commands": [ [ 3, [ ] ], [ 4, [ ] ] ], "index": 41, +"name": "zone_0", +"order": 0, +"type": "zone", +"zone_type": 0 +}, { +"children": [ 72 ], +"commands": [ [ 3, [ ] ], [ 4, [ ] ] ], +"index": 42, "name": "zone_1", "order": 1, "type": "zone", @@ -362,7 +372,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 42, +"index": 43, "name": "wc_0", "order": 1, "room_area": 16.0, @@ -372,27 +382,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 43, -"name": "bedroom_0", -"order": 2, -"room_area": 64.0, -"room_type": 202, -"type": "room", -"window": true -}, { -"children": [ ], -"commands": [ ], "index": 44, -"name": "wc_0", -"order": 1, -"room_area": 16.0, -"room_type": 200, -"type": "room", -"window": false -}, { -"children": [ ], -"commands": [ ], -"index": 45, "name": "bedroom_0", "order": 2, "room_area": 64.0, @@ -402,7 +392,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 46, +"index": 45, "name": "wc_0", "order": 1, "room_area": 16.0, @@ -412,7 +402,27 @@ entries=[ { }, { "children": [ ], "commands": [ ], +"index": 46, +"name": "bedroom_0", +"order": 2, +"room_area": 64.0, +"room_type": 202, +"type": "room", +"window": true +}, { +"children": [ ], +"commands": [ ], "index": 47, +"name": "wc_0", +"order": 1, +"room_area": 16.0, +"room_type": 200, +"type": "room", +"window": false +}, { +"children": [ ], +"commands": [ ], +"index": 48, "name": "bathroom_0", "order": 2, "room_area": 16.0, @@ -422,7 +432,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 48, +"index": 49, "name": "bathroom_1", "order": 3, "room_area": 144.0, @@ -432,7 +442,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 49, +"index": 50, "name": "living_room_0", "order": 1, "room_area": 144.0, @@ -442,7 +452,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 50, +"index": 51, "name": "kitchen_0", "order": 2, "room_area": 64.0, @@ -452,7 +462,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 51, +"index": 52, "name": "dining_room_0", "order": 3, "room_area": 144.0, @@ -462,7 +472,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 52, +"index": 53, "name": "enterance_0", "order": 4, "room_area": 16.0, @@ -472,7 +482,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 53, +"index": 54, "name": "enterance_1", "order": 5, "room_area": 16.0, @@ -482,7 +492,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 54, +"index": 55, "name": "bathroom_0", "order": 0, "room_area": 16.0, @@ -492,7 +502,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 55, +"index": 56, "name": "wc_0", "order": 1, "room_area": 16.0, @@ -502,7 +512,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 56, +"index": 57, "name": "bedroom_0", "order": 2, "room_area": 36.0, @@ -512,7 +522,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 57, +"index": 58, "name": "living_room_0", "order": 0, "room_area": 36.0, @@ -522,7 +532,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 58, +"index": 59, "name": "kitchen_0", "order": 1, "room_area": 16.0, @@ -530,17 +540,17 @@ entries=[ { "type": "room", "window": true }, { -"children": [ 72, 73 ], +"children": [ 73, 74 ], "commands": [ ], "floor_index": 1, -"index": 59, +"index": 60, "name": "floor_0", "order": 0, "type": "floor" }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 60, +"index": 61, "name": "wc_0", "order": 0, "room_area": 16.0, @@ -550,7 +560,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 61, +"index": 62, "name": "bathroom_0", "order": 1, "room_area": 16.0, @@ -560,7 +570,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 62, +"index": 63, "name": "bedroom_0", "order": 2, "room_area": 64.0, @@ -570,7 +580,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 63, +"index": 64, "name": "kitchen_0", "order": 0, "room_area": 16.0, @@ -580,7 +590,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 64, +"index": 65, "name": "living_room_0", "order": 1, "room_area": 144.0, @@ -590,7 +600,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 65, +"index": 66, "name": "bathroom_0", "order": 0, "room_area": 16.0, @@ -600,7 +610,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 66, +"index": 67, "name": "kitchen_0", "order": 0, "room_area": 64.0, @@ -610,7 +620,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 67, +"index": 68, "name": "living_room_0", "order": 1, "room_area": 64.0, @@ -620,7 +630,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 68, +"index": 69, "name": "wc_0", "order": 0, "room_area": 16.0, @@ -630,7 +640,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 69, +"index": 70, "name": "living_room_0", "order": 0, "room_area": 64.0, @@ -640,7 +650,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 70, +"index": 71, "name": "bathroom_0", "order": 0, "room_area": 16.0, @@ -650,7 +660,7 @@ entries=[ { }, { "children": [ ], "commands": [ [ 5, [ ] ] ], -"index": 71, +"index": 72, "name": "living_room_0", "order": 0, "room_area": 64.0, @@ -658,24 +668,24 @@ entries=[ { "type": "room", "window": true }, { -"children": [ 74 ], +"children": [ 75 ], "commands": [ ], -"index": 72, +"index": 73, "name": "zone_0", "order": 0, "type": "zone", "zone_type": 1 }, { -"children": [ 75, 76 ], +"children": [ 76, 77 ], "commands": [ ], -"index": 73, +"index": 74, "name": "unit_0", "order": 0, "type": "unit" }, { "children": [ ], "commands": [ ], -"index": 74, +"index": 75, "name": "storage_room_0", "order": 0, "room_area": 64.0, @@ -683,17 +693,17 @@ entries=[ { "type": "room", "window": true }, { -"children": [ 77 ], +"children": [ 78 ], "commands": [ ], -"index": 75, +"index": 76, "name": "zone_0", "order": 0, "type": "zone", "zone_type": 0 }, { -"children": [ 78 ], +"children": [ 79 ], "commands": [ ], -"index": 76, +"index": 77, "name": "zone_1", "order": 0, "type": "zone", @@ -701,7 +711,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 77, +"index": 78, "name": "wc_0", "order": 0, "room_area": 16.0, @@ -711,7 +721,7 @@ entries=[ { }, { "children": [ ], "commands": [ ], -"index": 78, +"index": 79, "name": "living_room_0", "order": 0, "room_area": 16.0, diff --git a/src/flecs b/src/flecs index e3219d7..3ae6926 160000 --- a/src/flecs +++ b/src/flecs @@ -1 +1 @@ -Subproject commit e3219d774d4b52b3cf4e97faaba9b88806498bdc +Subproject commit 3ae6926f7820cd0fb45a5108f241a3ea3468e119 diff --git a/src/godot b/src/godot index f75abbb..36a0185 160000 --- a/src/godot +++ b/src/godot @@ -1 +1 @@ -Subproject commit f75abbb3ec4a7a9046159f78431f234542400d7a +Subproject commit 36a01852a7c55823d05cb9591d23af46c123f658 diff --git a/src/meshoptimizer b/src/meshoptimizer index bab6997..20787cc 160000 --- a/src/meshoptimizer +++ b/src/meshoptimizer @@ -1 +1 @@ -Subproject commit bab69978d8f035ff32d6b5e7efb64196e284508c +Subproject commit 20787cc054fa0e46584c2791139c1878aa899d78 diff --git a/src/modules/stream/ui/building_layout_graph.cpp b/src/modules/stream/ui/building_layout_graph.cpp index a4bcbd5..6eeff89 100644 --- a/src/modules/stream/ui/building_layout_graph.cpp +++ b/src/modules/stream/ui/building_layout_graph.cpp @@ -2,6 +2,8 @@ #include "base_data.h" #include "world_editor.h" #include "editor_event.h" +#include "graph_module.h" +#include "growth_module.h" #include "building_layout_graph.h" // TODO: allocate zones in completed units and grow them. @@ -17,7 +19,8 @@ BuildingLayoutGraph::BuildingLayoutGraph() flecs::log::set_level(255); get_layout_grid_base(); get_layout_grid_base(); - ecs.import (); + ecs.import (); + ecs.import (); Error err = config.load("res://astream/building_layout.conf"); assert(err == OK); public_rooms = config.get_value("rooms", "public", Array()); diff --git a/src/modules/stream/ui/building_layout_graph.h b/src/modules/stream/ui/building_layout_graph.h index 8fc49b2..e572b72 100644 --- a/src/modules/stream/ui/building_layout_graph.h +++ b/src/modules/stream/ui/building_layout_graph.h @@ -45,26 +45,4 @@ public: void create_interior_tilemap(const String &layout_name); int get_layout_count() const; int get_children_count(flecs::entity base_e) const; - struct graph_module { - flecs::entity GraphSolve; - - flecs::entity get_layout_grid_base(); - flecs::entity get_layout_base(); - bool have_cell(flecs::entity floor_e, int id); - void grow_cell(flecs::entity seed_e, int id); - void queue_grow_cell(flecs::entity seed_e, int id); - void growth_module(flecs::world &ecs, - const String &module_name); - void room_growth_module(flecs::world &ecs, - const String &module_name); - void zones_graph_module(flecs::world &ecs, - const String &module_name); - void create_floor_components( - flecs::entity floor_e, flecs::entity base_floor_e, - const WorldEditor::components::buildings_layout_grid_size - &size); - bool check_region(flecs::entity floor_e, int index, - const Rect2i &rect) const; - graph_module(flecs::world &ecs); - }; }; \ No newline at end of file diff --git a/src/modules/stream/ui/building_layout_graph_ui.cpp b/src/modules/stream/ui/building_layout_graph_ui.cpp index 97ac397..4be354d 100644 --- a/src/modules/stream/ui/building_layout_graph_ui.cpp +++ b/src/modules/stream/ui/building_layout_graph_ui.cpp @@ -899,15 +899,14 @@ void BuildingLayoutGraphUI::draw_2d_grid_view(Control *draw) Math::randf(), Math::randf(), 1.0f); - draw->draw_rect( - Rect2(dx + 0.1f * dsize, - dy + 0.1f * dsize, - 0.8f * dsize, - 0.8f * dsize), - colors[String( - re.path())], - true); } + draw->draw_rect( + Rect2(dx + 0.3f * dsize, + dy + 0.3f * dsize, + 0.6f * dsize, + 0.6f * dsize), + colors[String(re.path())], + true); mcount++; }); print_line( @@ -916,6 +915,8 @@ void BuildingLayoutGraphUI::draw_2d_grid_view(Control *draw) ", " + String::num(dy) + ") " + String::num(dsize) + " " + (colors[cell.type].operator String())); + if (mcount) + print_line("draw_cell: is a room"); }); } pos++; diff --git a/src/modules/stream/ui/graph_module.cpp b/src/modules/stream/ui/graph_module.cpp index 7aa7622..0b6df5d 100644 --- a/src/modules/stream/ui/graph_module.cpp +++ b/src/modules/stream/ui/graph_module.cpp @@ -6,9 +6,10 @@ #include "grid_misc.h" #include "grow_job.h" #include "growth_regions.h" +#include "queries.h" #include "graph_module.h" -#define MIN_ROOM_SIZE 16 /* 4 * 4 tiles */ +#define MIN_ROOM_SIZE 16 /* 4 * 4 m tiles */ struct state { Rect2i bounds; @@ -140,47 +141,7 @@ struct state { } }; -flecs::entity BuildingLayoutGraph::graph_module::get_layout_grid_base() -{ - const String &layout_grid_name = "buildings_layout_grid_v2"; - flecs::world ecs = BaseData::get_singleton()->get(); - flecs::entity layout_base_e = - ecs.lookup(layout_grid_name.ascii().ptr()); - if (layout_base_e.is_valid()) { - assert(layout_base_e.has< - WorldEditor::components::buildings_layout_grid_base>()); - return layout_base_e; - } else { - layout_base_e = ecs.entity(layout_grid_name.ascii().ptr()); - assert(layout_base_e.is_valid()); - layout_base_e.add< - WorldEditor::components::buildings_layout_grid_base>(); - assert(layout_base_e.has< - WorldEditor::components::buildings_layout_grid_base>()); - return layout_base_e; - } -} - -flecs::entity BuildingLayoutGraph::graph_module::get_layout_base() -{ - const String &layout_base_name = "buildings_layout_graph"; - flecs::world ecs = BaseData::get_singleton()->get(); - flecs::entity layout_base_e = - ecs.lookup(layout_base_name.ascii().ptr()); - if (layout_base_e.is_valid()) { - assert(layout_base_e.has< - WorldEditor::components::buildings_layout_base>()); - return layout_base_e; - } else { - layout_base_e = ecs.entity(layout_base_name.ascii().ptr()); - assert(layout_base_e.is_valid()); - layout_base_e - .add(); - return layout_base_e; - } -} - -bool BuildingLayoutGraph::graph_module::have_cell(flecs::entity floor_e, int id) +bool graph_module::have_cell(flecs::entity floor_e, int id) { if (floor_e.get() ->cells.has(id)) @@ -190,47 +151,7 @@ bool BuildingLayoutGraph::graph_module::have_cell(flecs::entity floor_e, int id) return cell_e.is_valid(); } -void BuildingLayoutGraph::graph_module::grow_cell(flecs::entity seed_e, int id) -{ - flecs::entity floor_e = seed_e.parent(); - String c_name = "cell_" + itos(id); - flecs::entity c_e = floor_e.lookup(c_name.ascii().ptr()); - if (!c_e.is_valid()) { - c_e = seed_e.world() - .entity(c_name.ascii().ptr()) - .child_of(floor_e); - assert(c_e.is_valid()); - String type = seed_e.get() - ->type; - c_e.set( - { type, id }); - seed_e.each( - [&c_e](flecs::entity second) { - c_e.add( - second); - }); - int mcount = 0; - seed_e.each( - [&c_e, &mcount](flecs::entity second) { - assert(mcount == 0); - c_e.add( - second); - mcount++; - }); - floor_e.get_mut() - ->size_left--; - floor_e.get_mut() - ->cells.insert(id); - floor_e.modified< - WorldEditor::components::buildings_layout_grid_floor>(); - } -} - -void BuildingLayoutGraph::graph_module::queue_grow_cell(flecs::entity seed_e, - int id) +void graph_module::queue_grow_cell(flecs::entity seed_e, int id) { assert(seed_e.is_valid()); flecs::entity floor_e = seed_e.parent(); @@ -258,7 +179,7 @@ void BuildingLayoutGraph::graph_module::queue_grow_cell(flecs::entity seed_e, WorldEditor::components::buildings_layout_grid_queue>(); } } -void BuildingLayoutGraph::graph_module::create_floor_components( +void graph_module::create_floor_components( flecs::entity floor_e, flecs::entity base_floor_e, const WorldEditor::components::buildings_layout_grid_size &size) { @@ -520,30 +441,66 @@ void growth_regions::split_region( } } #endif -void BuildingLayoutGraph::graph_module::zones_graph_module( - flecs::world &ecs, const String &module_name) +void graph_module::zones_graph_module(flecs::world &ecs, + const String &module_name) { + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component() + .member("index"); + ecs.component(); + ecs.component(); + ecs.component(); + ecs.component() + .member("grid_size"); + ecs.component() + .member("area"); + ecs.component() + .member("index"); + ecs.component(); + ecs.component(); + ecs.component(); + // get_layout_grid_base(); + // BuildingLayoutGraph::get_singleton()->get_layout_grid_base(); + flecs::entity GraphPostSolve = ecs.entity("GraphPostSolve") + .add(flecs::Phase) + .depends_on(flecs::PostUpdate); + GraphPostSolve.disable(); + flecs::entity GraphSolveZones = ecs.entity("GraphSolveZones") .add(flecs::Phase) .depends_on(flecs::OnUpdate); GraphSolveZones.disable(); - ecs.system("ZonesStart") - .kind(GraphSolveZones) - .run([module_name](flecs::iter &it) { - print_line("Processing zones..."); - }); - ecs.system( - "FloorIndex") - .kind(GraphSolveZones) - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_floor_index - &index, - const WorldEditor::components::buildings_layout_floor - &f) { - flecs::entity e = it.entity(count); + ecs.system("ZonesStart").immediate().kind(GraphSolveZones).run([module_name, this](flecs::iter &it) { + it.world().defer_suspend(); + flecs::log::dbg("Processing zones..."); + /* Add floor index to all floor children nodes stopping at floors */ + flecs::query< + WorldEditor::components::buildings_layout_floor_index, + const WorldEditor::components::buildings_layout_floor> + floor_index_query = + it.world() + .query_builder< + WorldEditor::components:: + buildings_layout_floor_index, + const WorldEditor::components:: + buildings_layout_floor>() + .write() + .build(); + floor_index_query.each([](flecs::iter &it_, size_t count, + WorldEditor::components:: + buildings_layout_floor_index + &index, + const WorldEditor::components:: + buildings_layout_floor &f) { + flecs::entity e = it_.entity(count); List queue; e.children([&queue](flecs::entity ec) { if (!ec.has("RoomArea") - .kind(GraphSolveZones) - .without() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_room &f) { - flecs::entity room_e = it.entity(count); + /* add size to all rooms where size is not set */ + flecs::query rooms = + it.world() + .query_builder() + .without() + .write() + .build(); + rooms.each([](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_room &f) { + flecs::entity room_e = it_.entity(count); room_e.set< WorldEditor::components::buildings_layout_area>( { MIN_ROOM_SIZE }); }); - ecs.system("RoomArea2") - .kind(GraphSolveZones) - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_room &f, - WorldEditor::components::buildings_layout_area &area) { - // flecs::entity room_e = it.entity(count); - if (area.area < MIN_ROOM_SIZE) - area.area = MIN_ROOM_SIZE; - }); - ecs.system("ZoneArea") - .kind(GraphSolveZones) - .without() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_zone &f) { - flecs::entity zone_e = it.entity(count); + flecs::query + rooms2 = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_room, + WorldEditor::components:: + buildings_layout_area>() + .without() + .write() + .build(); + rooms2.each( + [](flecs::iter &it_, size_t count, + const WorldEditor::components::buildings_layout_room + &f, + WorldEditor::components::buildings_layout_area &area) { + // flecs::entity room_e = it.entity(count); + if (area.area < MIN_ROOM_SIZE) + area.area = MIN_ROOM_SIZE; + }); + flecs::query zones = + it.world() + .query_builder() + .without() + .write() + .build(); + zones.each([](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_zone &f) { + flecs::entity zone_e = it_.entity(count); zone_e.set< WorldEditor::components::buildings_layout_area>( { 0.0f }); }); - ecs.system( - "ZoneAreaSum") - .kind(GraphSolveZones) - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_zone &f, - WorldEditor::components::buildings_layout_area &area, - WorldEditor::components::buildings_layout_floor_index - &index) { - flecs::entity zone_e = it.entity(count); + flecs::query< + WorldEditor::components::buildings_layout_zone, + WorldEditor::components::buildings_layout_area, + WorldEditor::components::buildings_layout_floor_index> + zone_sum = + it.world() + .query_builder< + WorldEditor::components:: + buildings_layout_zone, + WorldEditor::components:: + buildings_layout_area, + WorldEditor::components:: + buildings_layout_floor_index>() + .write() + .build(); + zone_sum.each([](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_zone + &f, + WorldEditor::components::buildings_layout_area + &area, + WorldEditor::components:: + buildings_layout_floor_index &index) { + flecs::entity zone_e = it_.entity(count); flecs::query< WorldEditor::components::buildings_layout_room, const WorldEditor::components:: @@ -650,170 +641,125 @@ void BuildingLayoutGraph::graph_module::zones_graph_module( WorldEditor::components::buildings_layout_area>( { sum }); }); - ecs.system( - "ZoneAreaDisplay") - .kind(GraphSolveZones) - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_zone &f, - WorldEditor::components::buildings_layout_area &area, - WorldEditor::components::buildings_layout_floor_index - &index) { - flecs::entity zone_e = it.entity(count); - float sum = area.area; - print_line("area: " + itos(count) + " " + - itos(it.field_count()) + " " + - String(zone_e.path()) + ": " + - String::num(sum)); - if (count + 1 == (size_t)it.count()) - print_line("end"); - }); - ecs.system("ZonesCheckpoint") - .kind(GraphSolveZones) - .run([module_name](flecs::iter &it) { - flecs::query - q = it.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_zone, - const WorldEditor::components:: - buildings_layout_area>() - .build(); - int badness = 0; - q.each([&badness](flecs::entity e, - const WorldEditor::components:: - buildings_layout_zone &zone, - const WorldEditor::components:: - buildings_layout_area &area) { + flecs::query< + WorldEditor::components::buildings_layout_zone, + WorldEditor::components::buildings_layout_area, + WorldEditor::components::buildings_layout_floor_index> + zones_area_display = + it.world() + .query_builder< + WorldEditor::components:: + buildings_layout_zone, + WorldEditor::components:: + buildings_layout_area, + WorldEditor::components:: + buildings_layout_floor_index>() + .build(); + zones_area_display.each( + [](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_zone &f, + WorldEditor::components::buildings_layout_area &area, + WorldEditor::components::buildings_layout_floor_index + &index) { + flecs::entity zone_e = it_.entity(count); + float sum = area.area; + print_line("area: " + itos(count) + " " + + itos(it_.field_count()) + " " + + String(zone_e.path()) + ": " + + String::num(sum)); + if (count + 1 == (size_t)it_.count()) + print_line("end"); + }); + flecs::query< + const WorldEditor::components::buildings_layout_zone, + const WorldEditor::components::buildings_layout_area> + check_zones = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_zone, + const WorldEditor::components:: + buildings_layout_area>() + .build(); + int badness = 0; + check_zones.each( + [&badness](flecs::entity e, + const WorldEditor::components:: + buildings_layout_zone &zone, + const WorldEditor::components:: + buildings_layout_area &area) { if (area.area < MIN_ROOM_SIZE) { badness++; } }); - if (badness == 0) { + assert(badness == 0); + if (badness == 0) { + it.world() + .lookup((module_name + "::GraphSolveUnits") + .ascii() + .ptr()) + .enable(); + it.world() + .lookup((module_name + "::GraphSolveFloors") + .ascii() + .ptr()) + .enable(); + } else { + it.world() + .lookup((module_name + "::GraphSolveUnits") + .ascii() + .ptr()) + .disable(); + it.world() + .lookup((module_name + "::GraphSolveFloors") + .ascii() + .ptr()) + .disable(); + } + flecs::query + unit_area = it.world() - .lookup((module_name + - "::GraphSolveUnits") - .ascii() - .ptr()) - .enable(); - it.world() - .lookup((module_name + - "::GraphSolveFloors") - .ascii() - .ptr()) - .enable(); - } else { - it.world() - .lookup((module_name + - "::GraphSolveUnits") - .ascii() - .ptr()) - .disable(); - it.world() - .lookup((module_name + - "::GraphSolveFloors") - .ascii() - .ptr()) - .disable(); - } - - print_line("Zones processing done..."); - }); - ecs.system("UnitsStart") - .kind(GraphSolveZones) - .run([module_name](flecs::iter &it) { - print_line("Processing units..."); - }); -} - -BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) -{ - const String &module_name = "::BuildingLayoutGraph::graph_module"; - ecs.module(); - ecs.import (); - ecs.set({}); - ecs.component(); - ecs.component(); - ecs.component(); - ecs.component(); - ecs.component(); - ecs.component(); - ecs.component(); - ecs.component() - .member("index"); - ecs.component(); - ecs.component(); - ecs.component(); - ecs.component() - .member("grid_size"); - ecs.component() - .member("area"); - ecs.component() - .member("index"); - ecs.component(); - ecs.component(); -#if 0 - ecs.component< - WorldEditor::components::buildings_layout_commands::command>() - .member("command") - .member >("args"); - ecs.component() - .member("commands"); -#endif - ecs.component(); - // get_layout_grid_base(); - // BuildingLayoutGraph::get_singleton()->get_layout_grid_base(); - flecs::entity GraphPostSolve = ecs.entity("GraphPostSolve") - .add(flecs::Phase) - .depends_on(flecs::PostUpdate); - GraphPostSolve.disable(); - - zones_graph_module(ecs, module_name); - flecs::entity GraphSolveZones = - ecs.lookup((module_name + "::GraphSolveZones").ascii().ptr()); - assert(GraphSolveZones.is_valid()); - flecs::entity GraphSolveUnits = ecs.entity("GraphSolveUnits") - .add(flecs::Phase) - .depends_on(GraphSolveZones); - flecs::entity GraphSolveFloors = ecs.entity("GraphSolveFloors") - .add(flecs::Phase) - .depends_on(GraphSolveUnits); - GraphSolve = ecs.entity("GraphSolve") - .add(flecs::Phase) - .depends_on(GraphSolveFloors); - flecs::entity GraphAssembleSkeleton = - ecs.entity("GraphAssembleSkeleton") - .add(flecs::Phase) - .depends_on(GraphSolve); - GraphAssembleSkeleton.disable(); - ecs.system("UnitArea") - .kind(GraphSolveUnits) - .without() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_unit &f) { - flecs::entity floor_e = it.entity(count); + .query_builder< + WorldEditor::components:: + buildings_layout_unit>() + .without() + .write() + .build(); + unit_area.each([](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_unit + &f) { + flecs::entity floor_e = it_.entity(count); floor_e.set< WorldEditor::components::buildings_layout_area>( { 0.0f }); }); - ecs.system( - "UnitAreaSum") - .kind(GraphSolveUnits) - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_unit &f, - WorldEditor::components::buildings_layout_area &area, - WorldEditor::components::buildings_layout_floor_index - &index) { - flecs::entity unit_e = it.entity(count); + flecs::query< + const WorldEditor::components::buildings_layout_unit, + WorldEditor::components::buildings_layout_area, + WorldEditor::components::buildings_layout_floor_index> + unit_area_sum = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_unit, + WorldEditor::components:: + buildings_layout_area, + WorldEditor::components:: + buildings_layout_floor_index>() + .write() + .build(); + unit_area_sum.each([](flecs::iter &it_, size_t count, + const WorldEditor::components:: + buildings_layout_unit &f, + WorldEditor::components:: + buildings_layout_area &area, + WorldEditor::components:: + buildings_layout_floor_index + &index) { + flecs::entity unit_e = it_.entity(count); flecs::query< WorldEditor::components::buildings_layout_zone, const WorldEditor::components:: @@ -849,108 +795,128 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) print_line("area: " + String(unit_e.path()) + ": " + String::num(sum)); }); - ecs.system( - "UnitAreaDisplay") - .kind(GraphSolveUnits) - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_unit &f, - WorldEditor::components::buildings_layout_area &area, - WorldEditor::components::buildings_layout_floor_index - &index) { - flecs::entity zone_e = it.entity(count); - float sum = area.area; - print_line("area: " + itos(count) + " " + - itos(it.field_count()) + " " + - String(zone_e.path()) + ": " + - String::num(sum)); - if (count + 1 == (size_t)it.count()) - print_line("end"); - }); - ecs.system("UnitCheckpoint") - .kind(GraphSolveUnits) - .run([module_name](flecs::iter &it) { - flecs::query - q = it.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_unit, - const WorldEditor::components:: - buildings_layout_area>() - .build(); - int badness = 0; - q.each([&badness](flecs::entity e, - const WorldEditor::components:: - buildings_layout_unit &zone, - const WorldEditor::components:: - buildings_layout_area &area) { - if (area.area < MIN_ROOM_SIZE) { - badness++; - assert(false); - } - }); - }); - ecs.system("FloorsStart") - .kind(GraphSolveFloors) - .run([module_name](flecs::iter &it) { - print_line("Processing floors..."); - }); - ecs.system("FloorArea") - .kind(GraphSolveFloors) - .without() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_floor &f) { - flecs::entity floor_e = it.entity(count); - floor_e.set< - WorldEditor::components::buildings_layout_area>( - { 0.0f }); + print_line("Zones processing done..."); + flecs::query< + WorldEditor::components::buildings_layout_unit, + WorldEditor::components::buildings_layout_area, + WorldEditor::components::buildings_layout_floor_index> + unit_area_display = + it.world() + .query_builder< + WorldEditor::components:: + buildings_layout_unit, + WorldEditor::components:: + buildings_layout_area, + WorldEditor::components:: + buildings_layout_floor_index>() + .build(); + unit_area_display.each( + [](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_unit &f, + WorldEditor::components::buildings_layout_area &area, + WorldEditor::components::buildings_layout_floor_index + &index) { + flecs::entity zone_e = it_.entity(count); + float sum = area.area; + print_line("area: " + itos(count) + " " + + itos(it_.field_count()) + " " + + String(zone_e.path()) + ": " + + String::num(sum)); + if (count + 1 == (size_t)it_.count()) + print_line("end"); + }); + flecs::query< + const WorldEditor::components::buildings_layout_unit, + const WorldEditor::components::buildings_layout_area> + q = it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_unit, + const WorldEditor::components:: + buildings_layout_area>() + .build(); + badness = 0; + q.each([&badness](flecs::entity e, + const WorldEditor::components:: + buildings_layout_unit &zone, + const WorldEditor::components:: + buildings_layout_area &area) { + if (area.area < MIN_ROOM_SIZE) { + badness++; + assert(false); + } }); - ecs.system( - "FloorAreaSum") - .kind(GraphSolveFloors) - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_floor - &f, - WorldEditor::components::buildings_layout_area &area, - WorldEditor::components::buildings_layout_floor_index - &index) { - flecs::entity floor_e = it.entity(count); + print_line("Processing floors..."); + flecs::query + floors_area = + it.world() + .query_builder< + WorldEditor::components:: + buildings_layout_floor>() + .without() + .write() + .build(); + floors_area.each( + [](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_floor &f) { + flecs::entity floor_e = it_.entity(count); + floor_e.set( + { 0.0f }); + }); + flecs::query< + const WorldEditor::components::buildings_layout_floor, + WorldEditor::components::buildings_layout_area, + WorldEditor::components::buildings_layout_floor_index> + floor_area_sum = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_floor, + WorldEditor::components:: + buildings_layout_area, + WorldEditor::components:: + buildings_layout_floor_index>() + .build(); + floor_area_sum.each([](flecs::iter &it_, size_t count, + const WorldEditor::components:: + buildings_layout_floor &f, + WorldEditor::components:: + buildings_layout_area &area, + WorldEditor::components:: + buildings_layout_floor_index + &index) { + flecs::entity floor_e = it_.entity(count); flecs::query - q = floor_e.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_area, - const WorldEditor::components:: - buildings_layout_floor_index>() - .scope_open() - .with() - .or_() - .with() - .scope_close() - .with(flecs::ChildOf, floor_e) - .build(); + qsum = floor_e.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_area, + const WorldEditor::components:: + buildings_layout_floor_index>() + .scope_open() + .with() + .or_() + .with() + .scope_close() + .with(flecs::ChildOf, floor_e) + .build(); float sum = 0.0f; - q.each([&sum, - index](flecs::entity e, - const WorldEditor::components:: - buildings_layout_area &rarea, - const WorldEditor::components:: - buildings_layout_floor_index - &rindex) { + qsum.each([&sum, + index](flecs::entity e, + const WorldEditor::components:: + buildings_layout_area &rarea, + const WorldEditor::components:: + buildings_layout_floor_index + &rindex) { if (index.index == rindex.index) sum += rarea.area; }); @@ -958,124 +924,99 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) WorldEditor::components::buildings_layout_area>( { sum }); }); - ecs.system( - "FloorAreaDisplay") - .kind(GraphSolveFloors) - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_floor &f, - WorldEditor::components::buildings_layout_area &area, - WorldEditor::components::buildings_layout_floor_index - &index) { - flecs::entity zone_e = it.entity(count); - float sum = area.area; - print_line("area: " + itos(count) + " " + - itos(it.field_count()) + " " + - String(zone_e.path()) + ": " + - String::num(sum)); - if (count + 1 == (size_t)it.count()) - print_line("end"); - }); - ecs.system("FloorCheckpoint") - .kind(GraphSolveFloors) - .run([module_name](flecs::iter &it) { - flecs::query - q = it.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_floor, - const WorldEditor::components:: - buildings_layout_area>() - .build(); - int badness = 0; - q.each([&badness](flecs::entity e, - const WorldEditor::components:: - buildings_layout_floor &fl, - const WorldEditor::components:: - buildings_layout_area &area) { - if (area.area < MIN_ROOM_SIZE) { - badness++; - } - }); - if (badness == 0) { - flecs::world w = it.world(); - // create indices - w.lookup((module_name + - "::GraphAssembleSkeleton") - .ascii() - .ptr()) - .enable(); - print_line("Floor processing done..."); - } else - print_line("Still processing..."); - }); -#if 0 - ecs.system( - "CreateFloorData") - .kind(0) - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_graph - &p, - const WorldEditor::components:: - buildings_layout_floor_index &idx, - const WorldEditor::components::buildings_layout_area - &area) { - flecs::entity e = it.entity(count); - flecs::query q = - e.world() + flecs::query< + WorldEditor::components::buildings_layout_floor, + WorldEditor::components::buildings_layout_area, + WorldEditor::components::buildings_layout_floor_index> + floor_area_display = + it.world() .query_builder< WorldEditor::components:: - buildings_layout_area>() - .with() - .with(flecs::ChildOf, e) + buildings_layout_floor, + WorldEditor::components:: + buildings_layout_area, + WorldEditor::components:: + buildings_layout_floor_index>() .build(); - float max_area = area.area; - q.each([&max_area](flecs::entity ec, - WorldEditor::components:: - buildings_layout_area &r) { - if (max_area < r.area) - max_area = r.area; + floor_area_display.each( + [](flecs::iter &it_, size_t count, + WorldEditor::components::buildings_layout_floor &f, + WorldEditor::components::buildings_layout_area &area, + WorldEditor::components::buildings_layout_floor_index + &index) { + flecs::entity zone_e = it_.entity(count); + float sum = area.area; + print_line("area: " + itos(count) + " " + + itos(it_.field_count()) + " " + + String(zone_e.path()) + ": " + + String::num(sum)); + if (count + 1 == (size_t)it_.count()) + print_line("end"); }); - float grid_size = Math::ceil( - Math::ceil(Math::sqrt(max_area)) / 4.0f); - e.set( - { (int)Math::ceil(grid_size) }); - print_line("grid size: " + - itos((int)Math::ceil(grid_size))); - }); -#endif - ecs.system("AssembleSkeletonStart") - .kind(GraphAssembleSkeleton) - .run([module_name](flecs::iter &it) { - print_line("Assembling skeleton..."); - }); - - ecs.system( - "AssembleSkeleton") - .kind(GraphAssembleSkeleton) - .read() - .read() - .read() - .read() - .read() - .write() - .each([module_name](flecs::iter &it, size_t count, - const WorldEditor::components:: - buildings_layout_graph &f) { - flecs::entity graph_e = it.entity(count); + flecs::query< + const WorldEditor::components::buildings_layout_floor, + const WorldEditor::components::buildings_layout_area> + floor_area_checkpoint = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_floor, + const WorldEditor::components:: + buildings_layout_area>() + .build(); + badness = 0; + floor_area_checkpoint.each( + [&badness](flecs::entity e, + const WorldEditor::components:: + buildings_layout_floor &fl, + const WorldEditor::components:: + buildings_layout_area &area) { + if (area.area < MIN_ROOM_SIZE) { + badness++; + assert(false); + } + }); + if (badness == 0) { + flecs::world w = it.world(); + // create indices + w.lookup((module_name + "::GraphAssembleSkeleton") + .ascii() + .ptr()) + .enable(); + print_line("Floor processing done..."); + } else + print_line("Still processing..."); + print_line("Assembling skeleton..."); + flecs::query< + const WorldEditor::components::buildings_layout_graph> + assemble_skeleton = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_graph>() + .read() + .read() + .read() + .read() + .read() + .write() + .build(); + badness = 0; + assemble_skeleton.each([module_name, &badness]( + flecs::iter &it_, size_t count, + const WorldEditor::components:: + buildings_layout_graph + &f) { + flecs::entity graph_e = it_.entity(count); List queue; queue.push_back(graph_e); struct state state(Vector2i(0, 0)); - int badness = 0; while (!queue.empty()) { flecs::entity e = queue.front()->get(); queue.pop_front(); @@ -1085,45 +1026,45 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) buildings_layout_area, const WorldEditor::components:: buildings_layout_commands> - q = e.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_order, - const WorldEditor::components:: - buildings_layout_area, - const WorldEditor::components:: - buildings_layout_commands>() - .with(flecs::ChildOf, e) - .order_by< - WorldEditor::components:: - buildings_layout_order>( - [](flecs::entity_t - e1, - const WorldEditor:: - components::buildings_layout_order - *d1, - flecs::entity_t - e2, - const WorldEditor:: - components::buildings_layout_order - *d2) { - return (d1->index > - d2->index) - - (d1->index < - d2->index); - }) - .build(); - q.each([&state, &queue, &badness]( - flecs::entity ec, - const WorldEditor::components:: - buildings_layout_order - &order, - const WorldEditor::components:: - buildings_layout_area - &area, - const WorldEditor::components:: - buildings_layout_commands - &cmd) { + qm = e.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_order, + const WorldEditor::components:: + buildings_layout_area, + const WorldEditor::components:: + buildings_layout_commands>() + .with(flecs::ChildOf, e) + .order_by< + WorldEditor::components:: + buildings_layout_order>( + [](flecs::entity_t + e1, + const WorldEditor:: + components::buildings_layout_order + *d1, + flecs::entity_t + e2, + const WorldEditor:: + components::buildings_layout_order + *d2) { + return (d1->index > + d2->index) - + (d1->index < + d2->index); + }) + .build(); + qm.each([&state, &queue, &badness]( + flecs::entity ec, + const WorldEditor::components:: + buildings_layout_order + &order, + const WorldEditor::components:: + buildings_layout_area + &area, + const WorldEditor::components:: + buildings_layout_commands + &cmd) { int m; for (m = 0; m < cmd.commands.size(); m++) { @@ -1181,42 +1122,31 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) state.dump(); if (badness > 0) print_line("BAD!"); + assert(badness == 0); }); -#if 0 - ecs.system( - "MakeBuildingGrid") - .kind(GraphSolve) - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_skeleton - &skel) { - flecs::entity graph_e = it.entity(count); - flecs::entity base_e = - BuildingLayoutGraph::get_singleton() - ->get_layout_base(); - String pname(graph_e.name()); - String ename = "grid_" + pname; -#if 0 - flecs::entity grid_e = graph_e.lookup("grid"); - if (!grid_e.is_valid()) - grid_e = - graph_e.world().entity("grid").child_of( - graph_e); -#endif - }); -#endif - ecs.system( - "SetGridSize") - .kind(GraphSolve) - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_graph, - const WorldEditor::components::buildings_layout_area - &area) { + flecs::query< + const WorldEditor::components::buildings_layout_graph, + const WorldEditor::components::buildings_layout_area> + set_grid_size = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_graph, + const WorldEditor::components:: + buildings_layout_area>() + .write() + .build(); + + set_grid_size.each([](flecs::iter &it_, size_t count, + const WorldEditor::components:: + buildings_layout_graph, + const WorldEditor::components:: + buildings_layout_area &area) { int grid_size = (int)(Math::sqrt(area.area) * 1.5) + 1; int growth_size = - (int)Math::ceil(area.area * 1.3f / 16.0f) + 1; - flecs::entity graph_e = it.entity(count); + (int)Math::ceil(area.area * 1.2f / 16.0f) + 1; + flecs::entity graph_e = it_.entity(count); List queue; queue.push_back(graph_e); @@ -1244,18 +1174,24 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) buildings_layout_grid_size>( { grid_size, floors, growth_size }); }); - ecs.system( - "ResetGrid") - .kind(GraphSolve) - .immediate() - .read() - .read() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_grid_size - &size) { - flecs::entity graph_e = it.entity(count); - it.world().defer_suspend(); + flecs::query< + const WorldEditor::components::buildings_layout_grid_size> + reset_grid = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_grid_size>() + .read() + .read() + .write() + .build(); + reset_grid.each([](flecs::iter &it_, size_t count, + const WorldEditor::components:: + buildings_layout_grid_size &size) { + flecs::entity graph_e = it_.entity(count); flecs::entity grid_base_e = BuildingLayoutGraph::get_singleton() ->get_layout_grid_base(); @@ -1266,48 +1202,64 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) grid_e.path().c_str()); grid_e.destruct(); } - it.world().defer_resume(); }); - ecs.system( - "CreateGridEntity") - .kind(GraphSolve) - .immediate() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_grid_size - &size) { - flecs::entity graph_e = it.entity(count); - flecs::entity grid_base_e = - BuildingLayoutGraph::get_singleton() - ->get_layout_grid_base(); - flecs::entity grid_e = - grid_base_e.lookup(graph_e.name()); - assert(!grid_e.is_valid()); - grid_e = graph_e.world() - .entity(graph_e.name()) - .child_of(grid_base_e); - grid_e.add< - WorldEditor::components::buildings_layout_grid>(); - }); - ecs.system( - "SetupGrid") - .kind(GraphSolve) - .write() - .write() - .read() - .each([this](flecs::iter &it, size_t count, - const WorldEditor::components:: - buildings_layout_grid_size &size, - const WorldEditor::components::buildings_layout_area - &area) { + flecs::query< + const WorldEditor::components::buildings_layout_grid_size> + create_grid_entity = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_grid_size>() + .build(); + create_grid_entity.each( + [](flecs::iter &it_, size_t count, + const WorldEditor::components:: + buildings_layout_grid_size &size) { + flecs::entity graph_e = it_.entity(count); + flecs::entity grid_base_e = + BuildingLayoutGraph::get_singleton() + ->get_layout_grid_base(); + flecs::entity grid_e = + grid_base_e.lookup(graph_e.name()); + assert(!grid_e.is_valid()); + grid_e = graph_e.world() + .entity(graph_e.name()) + .child_of(grid_base_e); + grid_e.add(); + }); + flecs::query< + const WorldEditor::components::buildings_layout_grid_size, + const WorldEditor::components::buildings_layout_area> + setup_grid = + it.world() + .query_builder< + const WorldEditor::components:: + buildings_layout_grid_size, + const WorldEditor::components:: + buildings_layout_area>() + .write() + .write() + .read() + .build(); + setup_grid.each([this](flecs::iter &it_, size_t count, + const WorldEditor::components:: + buildings_layout_grid_size &size, + const WorldEditor::components:: + buildings_layout_area &area) { /* TODO: use it or delete it flecs::entity graph_e = it.entity(count); graph_e.add< WorldEditor::components::buildings_layout_grid>(); */ - flecs::entity graph_e = it.entity(count); - it.world().defer_suspend(); - flecs::entity grid_base_e = get_layout_grid_base(); + flecs::world &&w = it_.world(); + struct queries queries(w); + flecs::entity graph_e = it_.entity(count); + flecs::entity grid_base_e = + queries.get_layout_grid_base(); flecs::entity grid_e = grid_base_e.lookup(graph_e.name()); assert(grid_e.is_valid()); @@ -1336,633 +1288,23 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) floor_name.ascii().ptr()); me = me->next(); } - it.world().defer_resume(); }); - growth_module(ecs, module_name); - room_growth_module(ecs, module_name); -#if 0 - ecs.system( - "AssignGridSizeToFloor") - .kind(GraphSolve) - .read() - .each([](flecs::entity e, - WorldEditor::components::buildings_layout_grid_floor - &fl) {}); -#endif - ecs.system( - "FloorCompleteArea") - .kind(0) - .each([module_name]( - flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_floor - &f) { - flecs::entity floor_e = it.entity(count); - flecs::world w = floor_e.world(); - std::vector systems = { - "RoomArea", "ZoneArea", - "UnitArea", "FloorArea", - "ZoneAreaSum", "UnitAreaSum", - "FloorAreaSum", "CreateFloorData", - }; - int i; - for (i = 0; i < (int)systems.size(); i++) { - w.system(w.lookup((module_name + - "::" + systems[i]) - .ascii() - .ptr())) - .run(); - } - print_line("floor complete"); - }); -#if 0 - ecs.system("FloorArea") - .kind(flecs::OnUpdate) - .without() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_floor &f) { - flecs::entity floor_e = it.entity(count); - floor_e.set< - WorldEditor::components::buildings_layout_area>( - { 0.0f }); - }); - ecs.system("UnitArea") - .kind(flecs::OnUpdate) - .without() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_unit &f) { - flecs::entity floor_e = it.entity(count); - floor_e.set< - WorldEditor::components::buildings_layout_area>( - { 0.0f }); - }); - ecs.system("ZoneArea") - .kind(flecs::OnUpdate) - .without() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_zone &f) { - flecs::entity floor_e = it.entity(count); - floor_e.set< - WorldEditor::components::buildings_layout_area>( - { 0.0f }); - }); - ecs.system( - "MakeZoneAreas") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_area &area, - const WorldEditor::components::buildings_layout_zone &f, - const WorldEditor::components:: - buildings_layout_floor_index &idx) { - flecs::entity zone_e = it.entity(count); - int index = idx.index; - float parea = 0.0f; - zone_e.children([index, &parea](flecs::entity ec) { - if (ec.has() && - ec.has() && - ec.has()) { - if (ec.get() - ->index == index) - parea += - ec.get() - ->area; - } - }); - area.area = parea; - print_line(String(zone_e.path()) + - " area: " + String::num(area.area)); - }); - ecs.system( - "MakeUnitAreas") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_area &area, - const WorldEditor::components::buildings_layout_unit &f, - const WorldEditor::components:: - buildings_layout_floor_index &idx) { - flecs::entity zone_e = it.entity(count); - int index = idx.index; - float parea = 0.0f; - zone_e.children([index, &parea](flecs::entity ec) { - if (ec.has() && - ec.has() && - ec.has()) { - if (ec.get() - ->index == index) - parea += - ec.get() - ->area; - } - }); - area.area = parea; - print_line(String(zone_e.path()) + - " area: " + String::num(area.area)); - }); - ecs.system( - "MakeFloorAreas") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_area &area, - const WorldEditor::components::buildings_layout_floor - &f, - const WorldEditor::components:: - buildings_layout_floor_index &idx) { - flecs::entity floor_e = it.entity(count); - int index = idx.index; - float parea = 0.0f; - floor_e.children([index, &parea](flecs::entity ec) { - if (ec.has() && - ec.has() && - ec.has()) { - if (ec.get() - ->index == index) - parea += - ec.get() - ->area; - } - if (ec.has() && - ec.has() && - ec.has()) { - if (ec.get() - ->index == index) - parea += - ec.get() - ->area; - } - }); - area.area = parea; - print_line(String(floor_e.path()) + - " area: " + String::num(area.area)); - }); -#if 0 - ecs.system( - "MakeAreas") - .kind(flecs::OnUpdate) - // .read() - .with() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_area &area, - const WorldEditor::components::buildings_layout_floor - &f, - const WorldEditor::components:: - buildings_layout_floor_index &idx) { - flecs::entity floor_e = it.entity(count); - flecs::world ecs_ = floor_e.world(); - ecs_.system(ecs_.lookup("MakeZoneAreas")).run(); - ecs_.system(ecs_.lookup("MakeUnitAreas")).run(); - ecs_.system(ecs_.lookup("MakeFloorAreas")).run(); - }); -#endif - ecs.system( - "MakeGridEntities") - .kind(flecs::OnUpdate) - // .read() - .with() - .each([](flecs::iter &it, size_t count, - WorldEditor::components::buildings_layout_area &area, - const WorldEditor::components::buildings_layout_floor - &f, - const WorldEditor::components:: - buildings_layout_floor_index &idx) { -#if 0 - flecs::entity floor_e = it.entity(count); - List queue; - assert(false); - floor_e.children([&queue](flecs::entity ec) { - if (!ec.has()) - queue.push_back(ec); - }); - while (!queue.empty()) { - flecs::entity e = queue.front()->get(); - queue.pop_front(); - } -#endif - }); -#if 0 - ecs.system( - "CreateZoneData") - .kind(flecs::OnUpdate) - .without() - .write() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_zone - &p) { - flecs::entity e = it.entity(count); - e.set( - { 0.0f, false }); - e.add(); - String path(it.entity(count).path()); - print_line("Create zone data: entity: " + path); - }); - ecs.system( - "CreateUnitData") - .kind(flecs::OnUpdate) - .without() - .write() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_unit - &p) { - flecs::entity e = it.entity(count); - e.set( - { 0.0f }); - e.add(); - String path(it.entity(count).path()); - print_line("Create unit data: entity: " + path); - }); -#if 0 - ecs.system("CreateFloorIndex") - .kind(flecs::OnUpdate) - .without() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_floor - &p) { - flecs::entity e = it.entity(count); - e.set( - { 0.0f }); - }); -#endif - ecs.system( - "UpdateUnitData") - .kind(flecs::OnUpdate) - .with() - .with() - .write() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_unit - &p) { - flecs::entity e = it.entity(count); - float area = 0.0f; - e.children([&area](flecs::entity ec) { - if (ec.has()) - area += ec.get() - ->area; - }); - WorldEditor::components::buildings_layout_unit_data - *udata = e.get_mut< - WorldEditor::components:: - buildings_layout_unit_data>(); - udata->area = area; - String path(it.entity(count).path()); - print_line("Update unit data: entity: " + path + - " area: " + String::num(area)); - e.remove(); - BuildingLayoutGraph::get_singleton() - ->get_layout_base() - .add(); - }); - ecs.system( - "UpdateZoneData") - .kind(flecs::OnUpdate) - .with() - .with() - .write() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_zone - &p) { - flecs::entity e = it.entity(count); - float area = 0.0f; - bool window = false; - e.children([&area, &window](flecs::entity ec) { - if (ec.has()) - area += ec.get() - ->area; - if (ec.has()) { - bool w = - ec.get() - ->window; - if (w) - window = true; - } - }); - WorldEditor::components::buildings_layout_zone_data - *zdata = e.get_mut< - WorldEditor::components:: - buildings_layout_zone_data>(); - zdata->area = area; - zdata->align_wall = window; - String path(it.entity(count).path()); - print_line("Update zone data: entity: " + path + - " area: " + String::num(area)); - e.remove(); - flecs::entity parent_e = e.parent(); - if (parent_e.has()) - parent_e.add(); - BuildingLayoutGraph::get_singleton() - ->get_layout_base() - .add(); - }); - ecs.system( - "PropogateFloorIndex") - .kind(flecs::OnUpdate) - .with() - .write() - .write() - .write() - .immediate() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_floor - &r) { - flecs::entity e = it.entity(count); - print_line("propogate: " + String(e.path()) + " " + - itos(r.index)); - List queue; - float area = 0.0f; - /* e is a floor so skip it and add children instead*/ - e.children([&area](flecs::entity ec) { - if (ec.has()) - area += ec.get() - ->area; - if (ec.has()) - area += ec.get() - ->area; - }); - float size = Math::ceil(Math::sqrt(area) * 2.0f); - int grid_size = (int)Math::ceil(size / 2.0f); - e.set( - { area, grid_size }); - e.children([&queue](flecs::entity ec) { - /* do not add children floors to the queue */ - if (!ec.has()) - queue.push_back(ec); - }); - while (!queue.empty()) { - flecs::entity qe = queue.front()->get(); - queue.pop_front(); - if (!qe.has()) { - /* do not add children under another floor either */ - qe.set( - { r.index }); - qe.children([&queue](flecs::entity ec) { - queue.push_back(ec); - }); - } - } - BuildingLayoutGraph::get_singleton() - ->get_layout_base() - .add(); - e.remove(); - }); -#if 0 - ecs.system( - "CollectFloors") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_graph - &p) { - flecs::entity e = it.entity(count); - List queue; - queue.push_back(e); - while (!queue.empty()) { - flecs::entity em = queue.front()->get(); - if (em.has(); - }); - - ecs.system( - "DestroyGrid") - .kind(flecs::OnUpdate) - .with() - .write() - .immediate() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_base - &p) { - flecs::entity e = it.entity(count); - flecs::entity grid_base_e = - BuildingLayoutGraph::get_singleton() - ->get_layout_grid_base(); - grid_base_e.children([](flecs::entity ce) { - print_line("delete: " + String(ce.path())); - ce.destruct(); - }); - }); - ecs.system("CreateGrid") - .kind(flecs::OnUpdate) - .with() - .write() - .immediate() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_base - &p) { - flecs::entity e = it.entity(count); - flecs::entity grid_base_e = - BuildingLayoutGraph::get_singleton() - ->get_layout_grid_base(); - e.children([&grid_base_e](flecs::entity ec) { - if (ec.has()) { - print_line(String(grid_base_e.path())); - flecs::entity gc = - ec.world() - .entity(ec.name()) - .child_of(grid_base_e); - gc.add(); - gc.add(); - print_line("create: " + - String(gc.path())); - } - }); - }); -#endif -#if 0 - ecs.system( - "PopulateGrid") - .kind(flecs::OnUpdate) - .with() - .write() - .immediate() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_grid - &p) { - flecs::entity e = it.entity(count); - flecs::entity grid_layout_e = - BuildingLayoutGraph::get_singleton() - ->get_layout_base(); - flecs::entity layout_e - - }); -#endif - ecs.system( - "UpdateGraph") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_base - &p) { - flecs::entity e = it.entity(count); - EditorEvent::get_singleton()->event.emit( - "update_layout_view", varray()); - e.remove(); - }); -#endif -#if 0 - ecs.observer() - .event(flecs::OnSet) - .each([](flecs::entity e, - WorldEditor::components::buildings_layout_room &r) { - e.add(); - print_line("room set " + String(e.path())); - }); - ecs.observer() - .event(flecs::OnSet) - .each([](flecs::entity e, - WorldEditor::components::buildings_layout_zone &r) { - e.add(); - print_line("zone set " + String(e.path())); - }); - ecs.observer() - .event(flecs::OnSet) - .each([](flecs::entity e, - WorldEditor::components::buildings_layout_unit &r) { - e.add(); - print_line("unit set " + String(e.path())); - }); -#endif - ecs.system( - "CreateFloorData") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_floor - &p, - const WorldEditor::components:: - buildings_layout_floor_index &idx, - const WorldEditor::components::buildings_layout_area - &area) { - flecs::entity e = it.entity(count); - float grid_size = Math::ceil( - Math::ceil(Math::sqrt(area.area)) / 4.0f); - e.set( - { (int)Math::ceil(grid_size) }); - print_line("grid size: " + - itos((int)Math::ceil(grid_size))); - assert(false); - }); - ecs.system( - "CreateGridEntity") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_floor - &p, - const WorldEditor::components:: - buildings_layout_floor_index &idx, - const WorldEditor::components::buildings_layout_area - &area) { - flecs::entity e = it.entity(count); - flecs::entity grid_e = e.lookup("grid"); - if (!grid_e.is_valid()) - grid_e = e.world().entity("grid").child_of(e); - grid_e.add< - WorldEditor::components::buildings_layout_grid>(); - /* create grid here */ - }); - ecs.system( - "FinishGraphUpdate") - .kind(flecs::OnUpdate) - .with() - .write() - .each([](flecs::iter &it, size_t count, - const WorldEditor::components::buildings_layout_floor - &p, - const WorldEditor::components:: - buildings_layout_floor_index &idx, - const WorldEditor::components::buildings_layout_area - &area) { - flecs::entity e = it.entity(count); - EditorEvent::get_singleton()->event.emit( - "update_layout_view", varray()); - e.remove(); - }); -#endif + it.world().defer_resume(); + }); + flecs::entity GraphSolveUnits = ecs.entity("GraphSolveUnits") + .add(flecs::Phase) + .depends_on(GraphSolveZones); + flecs::entity GraphSolveFloors = ecs.entity("GraphSolveFloors") + .add(flecs::Phase) + .depends_on(GraphSolveUnits); + GraphSolve = ecs.entity("GraphSolve") + .add(flecs::Phase) + .depends_on(GraphSolveFloors); + flecs::entity GraphAssembleSkeleton = + ecs.entity("GraphAssembleSkeleton") + .add(flecs::Phase) + .depends_on(GraphSolve); + GraphAssembleSkeleton.disable(); ecs.observer() .event(flecs::OnSet) @@ -1984,38 +1326,6 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) .ascii() .ptr()) .enable(); -#if 0 - /* if set for room make zone dirty */ - flecs::entity parent_e = e.parent(); - while (parent_e.is_valid()) { - print_line(String(parent_e.path())); - if (parent_e.has< - WorldEditor::components:: - buildings_layout_floor>()) { - parent_e.add< - WorldEditor::components:: - buildings_layout_dirty>(); - break; - } - parent_e = parent_e.parent(); - } -#endif -#if 0 - if (parent_e.has()) - parent_e.add< - WorldEditor::components:: - buildings_layout_dirty>(); - parent_e.set( - { 0.0f }); -#endif -#if 0 - flecs::world ecs_ = e.world(); - ecs_.system(ecs_.lookup("MakeZoneAreas")).run(); - ecs_.system(ecs_.lookup("MakeUnitAreas")).run(); - ecs_.system(ecs_.lookup("MakeFloorAreas")).run(); -#endif print_line(String(e.path()) + ": set area"); }); /* Propagate floor index to children which are not floor */ @@ -2038,27 +1348,18 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs) .ptr()) .enable(); print_line(String(e.path()) + ": set floor"); -#if 0 - List queue; - queue.push_back(e); - while (!queue.empty()) { - flecs::entity qe = queue.front()->get(); - queue.pop_front(); - if (!qe.has()) { - qe.set( - { r.index }); - } - } - BuildingLayoutGraph::get_singleton() - ->get_layout_base() - .add(); -#endif }); } +graph_module::graph_module(flecs::world &ecs) +{ + const String &module_name = "::graph_module"; + ecs.module(); + ecs.import (); + ecs.set({}); + zones_graph_module(ecs, module_name); +} + /* These functions are used from GUI */ flecs::entity diff --git a/src/modules/stream/ui/graph_module.h b/src/modules/stream/ui/graph_module.h index ee6fa25..4164f77 100644 --- a/src/modules/stream/ui/graph_module.h +++ b/src/modules/stream/ui/graph_module.h @@ -1,235 +1,19 @@ #ifndef GRAPH_MODULE_H_ #define GRAPH_MODULE_H_ -#include #include "grid_misc.h" #include "grow_job.h" -struct RegionRect2i { - Point2i position; - Size2i size; +struct graph_module { + flecs::entity GraphSolve; - const Point2i &get_position() const - { - return position; - } - void set_position(const Point2i &p_position) - { - position = p_position; - } - const Size2i &get_size() const - { - return size; - } - void set_size(const Size2i &p_size) - { - size = p_size; - } - - int get_area() const - { - return size.width * size.height; - } - - _FORCE_INLINE_ Vector2i get_center() const - { - return position + (size / 2); - } - - inline bool intersects(const RegionRect2i &p_rect) const - { - if (position.x > (p_rect.position.x + p_rect.size.width - 1)) { - return false; - } - if ((position.x + size.width - 1) < p_rect.position.x) { - return false; - } - if (position.y > (p_rect.position.y + p_rect.size.height - 1)) { - return false; - } - if ((position.y + size.height - 1) < p_rect.position.y) { - return false; - } - - return true; - } - - inline bool encloses(const RegionRect2i &p_rect) const - { - return (p_rect.position.x >= position.x) && - (p_rect.position.y >= position.y) && - ((p_rect.position.x + p_rect.size.x) <= - (position.x + size.x)) && - ((p_rect.position.y + p_rect.size.y) <= - (position.y + size.y)); - } - - _FORCE_INLINE_ bool has_no_area() const - { - return (size.x <= 0 || size.y <= 0); - } - inline RegionRect2i clip(const RegionRect2i &p_rect) const - { /// return a clipped rect - - RegionRect2i new_rect = p_rect; - - if (!intersects(new_rect)) { - return RegionRect2i(); - } - - new_rect.position.x = MAX(p_rect.position.x, position.x); - new_rect.position.y = MAX(p_rect.position.y, position.y); - - Point2 p_rect_end = p_rect.position + p_rect.size; - Point2 end = position + size; - - new_rect.size.x = - (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x); - new_rect.size.y = - (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y); - - return new_rect; - } - - inline RegionRect2i merge(const RegionRect2i &p_rect) const - { ///< return a merged rect - - RegionRect2i new_rect; - - new_rect.position.x = MIN(p_rect.position.x, position.x); - new_rect.position.y = MIN(p_rect.position.y, position.y); - - new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, - position.x + size.x); - new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, - position.y + size.y); - - new_rect.size = - new_rect.size - new_rect.position; //make relative again - - return new_rect; - }; - bool has_point(const Point2 &p_point) const - { - if (p_point.x < position.x) { - return false; - } - if (p_point.y < position.y) { - return false; - } - - if (p_point.x >= (position.x + size.x)) { - return false; - } - if (p_point.y >= (position.y + size.y)) { - return false; - } - - return true; - } - - bool operator==(const RegionRect2i &p_rect) const - { - return position == p_rect.position && size == p_rect.size; - } - bool operator!=(const RegionRect2i &p_rect) const - { - return position != p_rect.position || size != p_rect.size; - } - - RegionRect2i grow(int p_by) const - { - RegionRect2i g = *this; - g.position.x -= p_by; - g.position.y -= p_by; - g.size.width += p_by * 2; - g.size.height += p_by * 2; - return g; - } - - inline RegionRect2i grow_margin(Margin p_margin, int p_amount) const - { - RegionRect2i g = *this; - g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, - (MARGIN_TOP == p_margin) ? p_amount : 0, - (MARGIN_RIGHT == p_margin) ? p_amount : 0, - (MARGIN_BOTTOM == p_margin) ? p_amount : - 0); - return g; - } - - inline RegionRect2i grow_individual(int p_left, int p_top, int p_right, - int p_bottom) const - { - RegionRect2i g = *this; - g.position.x -= p_left; - g.position.y -= p_top; - g.size.width += p_left + p_right; - g.size.height += p_top + p_bottom; - - return g; - } - - _FORCE_INLINE_ RegionRect2i expand(const Vector2i &p_vector) const - { - RegionRect2i r = *this; - r.expand_to(p_vector); - return r; - } - - inline void expand_to(const Point2i &p_vector) - { - Point2i begin = position; - Point2i end = position + size; - - if (p_vector.x < begin.x) { - begin.x = p_vector.x; - } - if (p_vector.y < begin.y) { - begin.y = p_vector.y; - } - - if (p_vector.x > end.x) { - end.x = p_vector.x; - } - if (p_vector.y > end.y) { - end.y = p_vector.y; - } - - position = begin; - size = end - begin; - } - - operator String() const - { - return String(position) + ", " + String(size); - } - - operator Rect2() const - { - return Rect2(position, size); - } - RegionRect2i(const Rect2 &p_r2) - : position(p_r2.position) - , size(p_r2.size) - { - } - RegionRect2i(const Rect2i &p_r2) - : position(p_r2.position) - , size(p_r2.size) - { - } - RegionRect2i() - { - } - RegionRect2i(int p_x, int p_y, int p_width, int p_height) - : position(Point2(p_x, p_y)) - , size(Size2(p_width, p_height)) - { - } - RegionRect2i(const Point2 &p_pos, const Size2 &p_size) - : position(p_pos) - , size(p_size) - { - } + bool have_cell(flecs::entity floor_e, int id); + void queue_grow_cell(flecs::entity seed_e, int id); + void zones_graph_module(flecs::world &ecs, const String &module_name); + void create_floor_components( + flecs::entity floor_e, flecs::entity base_floor_e, + const WorldEditor::components::buildings_layout_grid_size &size); + bool check_region(flecs::entity floor_e, int index, + const Rect2i &rect) const; + graph_module(flecs::world &ecs); }; #endif \ No newline at end of file diff --git a/src/modules/stream/ui/graph_module_growth.cpp b/src/modules/stream/ui/graph_module_growth.cpp index 097fdef..34fca38 100644 --- a/src/modules/stream/ui/graph_module_growth.cpp +++ b/src/modules/stream/ui/graph_module_growth.cpp @@ -48,303 +48,4 @@ struct grid_calc { { assert(grid_size > 0); } -}; -void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs, - const String &module_name) -{ - ecs.component(); - ecs.component(); - flecs::entity GraphFilter = ecs.entity("GraphFilter") - .add(flecs::Phase) - .depends_on(flecs::OnUpdate); - GraphFilter.disable(); - flecs::entity GraphGridPrepare = ecs.entity("GraphGridPrepare") - .add(flecs::Phase) - .depends_on(GraphSolve); - -#if 0 - ecs.system( - "CreateGrid") - .kind(GraphSolve) - .write() - .each([this](flecs::iter &it, size_t count, - const WorldEditor::components:: - buildings_layout_grid_size &size) { - struct grid_misc grid; - flecs::entity graph_e = it.entity(count); - graph_e.world().defer_suspend(); - 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 */ - const List >::Element *me = - size.floors.front(); - while (me) { - flecs::query - q = graph_e.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_area>() - .with(flecs::ChildOf, - me->get().second) - .scope_open() - .with() - .or_() - .with() - .scope_close() - .build(); - q.each([size, - &grid](flecs::entity ce, - const WorldEditor::components:: - buildings_layout_area - &area) { - flecs::log::warn( - "generating positions for: %s", - ce.path().c_str()); - grid.filter_candidates(ce, area.area, - size); - }); - flecs::entity base_floor_e = - grid_e.world().entity(me->get().second); - flecs::entity grid_floor_e = - grid.get_grid_floor(grid_e, - base_floor_e); - create_floor_components(grid_floor_e, - base_floor_e, size); - grid.place_regions(grid_floor_e); - - me = me->next(); - } - graph_e.world().defer_resume(); - }); -#endif - ecs.system("AssembleSkeletonEnd") - .kind(GraphSolve) - .run([module_name](flecs::iter &it) { - print_line("Assembling skeleton done..."); - it.world() - .lookup((module_name + "::GraphSolveZones") - .ascii() - .ptr()) - .disable(); - it.world() - .lookup((module_name + "::GraphFilter") - .ascii() - .ptr()) - .enable(); - EditorEvent::get_singleton()->event.emit( - "update_layout_view", varray()); - // assert(false); - }); -#if 0 - - ecs.system("GrowFloorRectRegions") - .kind(0) - .each([this](flecs::entity floor_e, - WorldEditor::components::buildings_layout_grid_floor - &fl, - growth_regions &g) { - struct grid_misc grid; - grid.grow_region_rects(this, floor_e, fl, g); - grid.place_region_cells(this, floor_e, fl, g); - }); -#endif -#if 0 - ecs.system( - "GrowFloorRegions") - .kind(0) - .each([this](flecs::entity floor_e, - WorldEditor::components::buildings_layout_grid_floor - &fl) { - /* TODO: limit growth per region too */ - struct grid_calc grid(fl.grid_size); - if (fl.size_left <= 0) - return; - flecs::query - q = floor_e.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_grid_cell>() - .with(flecs::ChildOf, floor_e) - .without() - .build(); - q.each([this, &floor_e, &fl, - &grid](flecs::entity et, - const WorldEditor::components:: - buildings_layout_grid_cell &cell) { - int index = cell.index; - assert(et.is_valid()); - int i; - LocalVector candidates; - candidates.resize(8); - grid.get_cadidates(cell.index, - candidates.ptr()); - int extended = 0; - for (i = 0; i < (int)candidates.size(); i++) { - if (have_cell(floor_e, candidates[i])) - continue; - queue_grow_cell(et, candidates[i]); - extended++; - } - if (extended == 0) - et.add(); - print_line("size: " + itos(grid.grid_size) + - " index: " + itos(index)); - }); - }); -#endif -#if 0 - ecs.system( - "GrowRegions") - .kind(0) - .without() - .read() - .write() - .write() - .write() - .each([this](flecs::entity e, - const WorldEditor::components:: - buildings_layout_grid_cell &cell) { - e.world().defer_suspend(); - int index = cell.index; - assert(e.is_valid()); - flecs::entity floor_e = e.parent(); - assert(floor_e.is_valid()); - - flecs::entity grid_e = floor_e.parent(); - assert(grid_e.is_valid()); - String layout_name(grid_e.name()); - flecs::entity base_e = get_layout_base(); - flecs::entity layout_e = - base_e.lookup(layout_name.ascii().ptr()); - assert(layout_e.is_valid()); - struct grid_calc grid(layout_e); - int i; - LocalVector candidates; - candidates.resize(8); - grid.get_cadidates(cell.index, candidates.ptr()); - int extended = 0; - for (i = 0; i < (int)candidates.size(); i++) { - if (have_cell(floor_e, candidates[i])) - continue; - queue_grow_cell(e, candidates[i]); - extended++; - } - if (extended == 0) - e.add(); - print_line("size: " + itos(grid.grid_size) + - " index: " + itos(index)); - e.world().defer_resume(); - }); -#endif - ecs.system( - "GrowCommitQueue") - .kind(0) - .each([this](flecs::entity e, - WorldEditor::components::buildings_layout_grid_floor - &fl, - WorldEditor::components::buildings_layout_grid_queue - &queue) { - List >::Element *me = - queue.queue.front(); - while (me) { - flecs::entity seed_e = - e.world().entity(me->get().first); - int id = me->get().second; - if (!fl.cells.has(id)) { - grow_cell(seed_e, id); - fl.cells.insert(id); - } - me = me->next(); - } - queue.queue.clear(); - e.remove(); - }); - ecs.system("RunGrow") - .immediate() - .write() - .write() - .write() - .kind(GraphFilter) - .run([module_name, this](flecs::iter &it) { - flecs::world &&ecs = it.world(); - it.world().defer_suspend(); - struct queries queries(ecs); - 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; - // 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, queries, size, - module_name); - job_queue.iterate(); - // assert(false); - }); -#if 0 - 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 - it.world() - .system(it.world().lookup( - (module_name + "::GrowCommitQueue") - .ascii() - .ptr())) - .run(); - it.world() - .lookup((module_name + "::GraphFilter") - .ascii() - .ptr()) - .disable(); - it.world().defer_resume(); - }); -} +}; \ No newline at end of file diff --git a/src/modules/stream/ui/graph_module_rooms.cpp b/src/modules/stream/ui/graph_module_rooms.cpp deleted file mode 100644 index 837061c..0000000 --- a/src/modules/stream/ui/graph_module_rooms.cpp +++ /dev/null @@ -1,456 +0,0 @@ -#include "base_data.h" -#include "world_editor.h" -#include "building_layout_graph.h" -#include "grid_misc.h" -#include "graph_module.h" - -void BuildingLayoutGraph::graph_module::room_growth_module( - flecs::world &ecs, const String &module_name) -{ - flecs::entity GraphFilter = - ecs.lookup((module_name + "::GraphFilter").ascii().ptr()); - assert(GraphFilter.is_valid()); - flecs::entity GraphGrowUnitAreas = ecs.entity("GraphGrowUnitAreas") - .add(flecs::Phase) - .depends_on(flecs::OnUpdate); - GraphGrowUnitAreas.disable(); - flecs::entity GraphMarkData = ecs.entity("GraphMarkData") - .add(flecs::Phase) - .depends_on(flecs::OnUpdate); - GraphMarkData.disable(); - flecs::entity GraphProcessRooms = ecs.entity("GraphProcessRooms") - .add(flecs::Phase) - .depends_on(flecs::OnUpdate); - GraphProcessRooms.disable(); - ecs.system( - "AllocateUnitGrow") - .kind(GraphGrowUnitAreas) - .each([](flecs::entity ec, - const WorldEditor::components::buildings_layout_unit - &unit) { - ec.world() - .query_builder() - .build() - .each([](flecs::entity e, - const WorldEditor::components:: - buildings_layout_zone &zone) { - // assert(false); - }); - }); - - ecs.system("CheckGrow").kind(GraphFilter).run([module_name](flecs::iter &it) { - int failed_zones = 0, total_zones = 0; - it.world() - .query_builder() - .build() - .each([&failed_zones, &total_zones]( - flecs::entity ec, - const WorldEditor::components:: - buildings_layout_zone &zone) { - int count = 0; - ec.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_grid_cell>() - .with( - ec) - .build() - .each([&count]( - flecs::entity e, - const WorldEditor::components:: - buildings_layout_grid_cell - &cell) { - count++; - }); - if (count == 0) - failed_zones++; - total_zones++; - }); - if (failed_zones > 0) - flecs::log::err("failed to allocate zones: %d/%d", - failed_zones, total_zones); - flecs::query - q = it.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_grid_floor>() - .build(); - int count_left = 0; - int count_run = 0; - q.each([&count_left, - &count_run](flecs::entity e, - const WorldEditor::components:: - buildings_layout_grid_floor &fl) { - count_run++; - count_left += MAX(0, fl.size_left); - }); - // assert(false); - if (count_run > 0 && count_left <= 0 && failed_zones == 0) { - it.world() - .lookup((module_name + "::GraphFilter") - .ascii() - .ptr()) - .disable(); - print_line("Grow done"); - it.world() - .lookup((module_name + "::GraphMarkData") - .ascii() - .ptr()) - .enable(); - print_line("Mark started..."); - } else if (count_run > 0 && count_left <= 0 && - failed_zones > 0) { - it.world() - .lookup((module_name + "::GraphFilter") - .ascii() - .ptr()) - .disable(); - print_line("Grow done"); - it.world() - .lookup((module_name + "::GraphGrowUnitAreas") - .ascii() - .ptr()) - .enable(); - print_line("Grow unit started..."); - } - }); - ecs.system( - "MarkExternalWall") - .kind(GraphMarkData) - .without() - .read() - .write() - .write() - .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)); - }); - ecs.system("CheckMark") - .kind(GraphMarkData) - .run([module_name](flecs::iter &it) { - int tile_count = 0, inside_count = 0, wall_count = 0; - it.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_grid_cell>() - .build() - .each([&tile_count, &inside_count, &wall_count]( - flecs::entity e, - const WorldEditor::components:: - buildings_layout_grid_cell - &cell) { - tile_count++; - if (e.has()) - wall_count++; - if (e.has()) - inside_count++; - }); - if (tile_count > 0 && wall_count > 0 && - inside_count > 0 && - tile_count == wall_count + inside_count) { - it.world() - .lookup((module_name + - "::GraphMarkData") - .ascii() - .ptr()) - .disable(); - it.world() - .lookup((module_name + - "::GraphProcessRooms") - .ascii() - .ptr()) - .enable(); - } - }); - struct prio_queue { - HashMap entities; - Set tile_selection[4]; - Vector tile_selection_array[4]; - struct make_random r; - bool dirty; - prio_queue() - : r(make_random(100)) - , dirty(true) - { - } - void add_tile(int prio, int id, flecs::entity ec) - { - if (!tile_selection[prio].has(id)) - tile_selection[prio].insert(id); - if (!entities.has(id)) - entities[id] = ec; - dirty = true; - } - void update() - { - int i, j; - for (i = 0; i < 4; i++) { - tile_selection_array[i].resize( - tile_selection[i].size()); - j = 0; - Set::Element *m = - tile_selection[i].front(); - while (m) { - tile_selection_array[i].write[j++] = - m->get(); - m = m->next(); - } - } - } - void dump() - { - if (dirty) { - update(); - dirty = false; - } - print_line("0: " + - itos(tile_selection_array[0].size())); - print_line("1: " + - itos(tile_selection_array[1].size())); - print_line("2: " + - itos(tile_selection_array[2].size())); - } - int get_random_tile(int prio) - { - assert(tile_selection[prio].size() > 0); - int sel = r.get() % tile_selection[prio].size(); - int id = tile_selection_array[prio][sel]; - assert(entities.has(id)); - tile_selection_array[prio].erase(id); - tile_selection[prio].erase(id); - return id; - } - void delete_neighbors(int id) - { - int i, j; - flecs::entity selected_e = entities[id]; - int grid_size = - selected_e.parent() - .get() - ->grid_size; - Vector2i base(id % grid_size, id / grid_size); - for (i = -1; i < 2; i++) - for (j = -1; j < 2; j++) { - if (i == 0 && j == 0) - continue; - Vector2i neighbor = - base + Vector2i(i, j); - int neighbor_id = - neighbor.x + - grid_size * neighbor.y; - tile_selection_array[0].erase( - neighbor_id); - tile_selection[0].erase(neighbor_id); - if (!tile_selection[3].has( - neighbor_id)) { - tile_selection_array[3] - .push_back(neighbor_id); - tile_selection[3].insert( - neighbor_id); - } - } - } - int take_tile() - { - if (dirty) { - update(); - dirty = false; - } - if (tile_selection[0].size() > 0) { - int id = get_random_tile(0); - delete_neighbors(id); - return id; - } else { - int prio; - flecs::log::warn( - "out of normal tiles, using outside wall and zone borders"); - for (prio = 1; prio < 4; prio++) { - if (tile_selection[prio].size() > 0) { - int id = get_random_tile(prio); - return id; - } - } - } - flecs::log::err("failed to allocate room initial tile"); - return -1; - } - flecs::entity get_entity(int id) - { - assert(entities.has(id)); - return entities[id]; - } - int get_total_size() - { - int ret = 0, i; - for (i = 0; i < 4; i++) - ret += tile_selection[i].size(); - return ret; - } - }; - ecs.system( - "ProcessFloor0Rooms") - .kind(GraphProcessRooms) - .read() - .read() - .read() - .each([](flecs::entity e, - const WorldEditor::components::buildings_layout_zone - &zone, - const WorldEditor::components:: - buildings_layout_floor_index &idx) { - if (idx.index != 0) - return; - // make_random r(1001); - struct prio_queue prio; - e.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_grid_cell>() - .with(e) - .without() - .without() - .build() - .each([&prio](flecs::entity ec, - const WorldEditor::components:: - buildings_layout_grid_cell - &cell) { - prio.add_tile(0, cell.index, ec); - }); - e.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_grid_cell>() - .with(e) - .without() - .with() - .build() - .each([&prio](flecs::entity ec, - const WorldEditor::components:: - buildings_layout_grid_cell - &cell) { - prio.add_tile(1, cell.index, ec); - }); - e.world() - .query_builder< - const WorldEditor::components:: - buildings_layout_grid_cell>() - .with(e) - .with() - .build() - .each([&prio](flecs::entity ec, - const WorldEditor::components:: - buildings_layout_grid_cell - &cell) { - prio.add_tile(2, cell.index, ec); - }); - prio.update(); - prio.dump(); - if (prio.get_total_size() == 0) { - flecs::log::err( - "no tiles allocated for zone: %s", - e.path().c_str()); - return; - } - int count = 0, assigned_count = 0; - e.world() - .query_builder() - .with(flecs::ChildOf, e) - .build() - .each([&prio, &count, &assigned_count]( - flecs::entity ec, - const WorldEditor::components:: - buildings_layout_room - &room) { - int id = prio.take_tile(); - if (id >= 0) { - flecs::entity selected_e = - prio.get_entity(id); - int mcount = 0; - selected_e.each< - WorldEditor::components:: - belongs_room>( - [&mcount](flecs::entity - e) { - mcount++; - }); - assert(mcount == 0); - selected_e.add< - WorldEditor::components:: - belongs_room>( - ec); - assigned_count++; - } - count++; - }); - if (assigned_count < count) - flecs::log::err( - "not all rooms were assigned: %d < %d", - assigned_count, count); - }); -} diff --git a/src/modules/stream/ui/grid_misc.cpp b/src/modules/stream/ui/grid_misc.cpp new file mode 100644 index 0000000..8dc11b7 --- /dev/null +++ b/src/modules/stream/ui/grid_misc.cpp @@ -0,0 +1,713 @@ +#include +#include +#include +#include "world_editor.h" +#include "graph_module.h" +#include "growth_regions.h" +#include "grid_misc.h" + +void grid_misc::get_dim_candidates(const Vector2i &base, int dim, + Vector2i *candidates) +{ + int i; + std::vector candidates_data = { + /* clang-format off */ + { base.x + dim, base.y }, + { base.x, base.y + dim }, + { base.x - dim, base.y }, + { base.x, base.y - dim }, + { base.x + dim, base.y }, + { base.x, base.y + dim }, + { base.x - dim, base.y }, + { base.x, base.y - dim }, + /* clang-format on */ + }; + for (i = 0; i < (int)candidates_data.size(); i++) + candidates[i] = candidates_data[i]; +} + +int grid_misc::get_floor_index(flecs::entity e) const +{ + return e.get() + ->index; +} + +flecs::entity grid_misc::get_grid_floor(flecs::entity grid_e, + flecs::entity graph_floor_e) const +{ + 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; +} + +bool grid_misc::check_duplicates() const +{ + int i, j; + bool result = true; + for (i = 0; i < (int)positions.size(); i++) + for (j = 0; j < (int)positions.size(); j++) { + if (i == j) + continue; + if (positions[i].second == positions[j].second) { + flecs::log::err("duplicate positions"); + result = false; + goto out; + } + } +out: + return result; +} + +#if 0 +void grid_misc::place_regions(flecs::entity grid_floor_e) +{ + int i; + int grid_size = grid_floor_e + .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::region parent_reg; + parent_reg.can_grow = false; + parent_reg.complete = true; + parent_reg.rect.position = Vector2i(); + parent_reg.rect.size = Vector2i(grid_size, grid_size); + parent_reg.can_grow_square = false; + growth_regions *g = grid_floor_e.get_mut(); + int parent_index = g->parent_regions.size(); + g->parent_regions.push_back(parent_reg); + for (i = 0; i < (int)positions.size(); i++) { + int cell_id = positions[i].second.x + + grid_size * positions[i].second.y; + flecs::entity region_e = + grid_e.world().entity(positions[i].first); + assert(region_e.is_valid()); + 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); + assert(cell_e.is_valid()); + flecs::log::warn("grid cell: %s", cell_e.path().c_str()); + float area = get_entity_area(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, + parent_index); + flecs::log::warn("grid cell: %s", cell_e.path().c_str()); + } + // flecs::log::dbg("###=== %s done", grid_floor_e.path().c_str()); +} +#endif + +#if 0 + +void grid_misc::place_regions_common(flecs::entity parent_e, + flecs::entity grid_floor_e, + int parent_index) +{ + int i; + int grid_size = grid_floor_e + .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(); + for (i = 0; i < (int)positions.size(); i++) { + assert(g->parent_regions[parent_index].rect.has_point( + positions[i].second)); + int cell_id = positions[i].second.x + + grid_size * positions[i].second.y; + flecs::entity region_e = + grid_e.world().entity(positions[i].first); + assert(region_e.is_valid()); + RegionRect2i 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->update_cell(grid_floor_e, parent_e, + region_e, cell_id); + if (cell_e.is_valid()) { + float area = get_entity_area(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, parent_e, + region_e, positions[i].second, area, + parent_index); + // flecs::log::warn("grid cell: %s", + // cell_e.path().c_str()); + } else { + flecs::log::err("unable to create region"); + assert(false); + } + } + // flecs::log::dbg("###=== %s done", grid_floor_e.path().c_str()); +} +#endif + +bool grid_misc::process_candidates(flecs::entity ce, const Vector2i &base, + float area, flecs::entity_t base_et, int dim, + const RegionRect2i &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) / + 4; /* grid conversion */ + local_radius = MAX(1, local_radius); + // int dim = base_radius + local_radius; + // dim = MAX(4, dim); + 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])); + j++) { + print_line("base: " + itos(base.x) + ", " + itos(base.y)); + print_line("possible candidate: " + itos(candidates[j].x) + + ", " + itos(candidates[j].y)); + if (!clip.has_point(candidates[j])) { + print_line("clipped by grid field"); + print_line(clip.operator String()); + continue; + } + if (!clip.has_point(candidates[j])) { + flecs::log::dbg("clipped by clip rect"); + continue; + } + if (!check_candidates_tolerance(candidates[j])) { + print_line("too close to existing positions"); + continue; + } + if (!check_candidate(candidates[j])) { + // print_line( + // "too close to existing positions (rect)"); + continue; + } + // print_line("valid candidate: " + itos(candidates[j].x) + + // ", " + itos(candidates[j].y)); + // 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) { + Vector2i current = base; + Set generated; + int candidate_count = 0; + int max_count = 1000; + for (j = 0; j < positions.size(); j++) { + assert(clip.has_point(positions[j].second)); + generated.insert(positions[j].second); + } + for (j = 0; + j < (int)(sizeof(candidates) / sizeof(candidates[0])); + j++) { + do { + candidates[j] = clip.position + + Vector2i(r.get() % clip.size.x, + r.get() % clip.size.y); + max_count--; + if (max_count < 0) + break; + } while (generated.has(candidates[j]) || + !clip.has_point(candidates[j])); + if (max_count >= 0) { + assert(!generated.has(candidates[j])); + generated.insert(candidates[j]); + flecs::log::dbg( + "candidate: %d: %s -> %s", j, + (clip.operator String()).ascii().ptr(), + (candidates[j].operator String()) + .ascii() + .ptr()); + candidate_count++; + } + } + for (j = 0; j < candidate_count; j++) { + print_line("!!base: " + itos(base.x) + ", " + + itos(base.y)); + print_line("!!possible candidate: " + + itos(candidates[j].x) + ", " + + itos(candidates[j].y)); + if (!clip.has_point(candidates[j])) { + print_line("!!clipped by grid field"); + print_line(clip.operator String()); + continue; + } + if (!clip.has_point(candidates[j])) { + flecs::log::dbg("!!clipped by clip rect"); + continue; + } + /* + if (!check_candidate(candidates[j])) { + print_line( + "!!too close to existing positions (rect)"); + continue; + } + */ + // print_line("valid candidate: " + itos(candidates[j].x) + + // ", " + itos(candidates[j].y)); + // 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]); + assert(clip.has_point(candidates[j])); + } + if (accepted.size() == 0) + flecs::log::err("all candidates were rejected"); + } + if (accepted.size() > 0) + return true; + else + return false; +} + +void grid_misc::filter_candidates(flecs::entity ce, float area, + const RegionRect2i &clip_rect) +{ + if (positions.empty()) { + /* starting at grid center */ + 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; + } + while (1) { + int which = which_position(); + const Vector2i &base = positions[which].second; + flecs::entity_t base_et = positions[which].first; + 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) / + 4; /* grid conversion */ + local_radius = MAX(1, local_radius); + /* minimum distance between region positions */ + int dim = base_radius + local_radius; + 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()); + // flecs::log::warn("clip: %s base: %s dim: %d", + // (clip.operator String()).ascii().ptr(), + // (base.operator String()).ascii().ptr(), + // dim); + if (!(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)))) + dim = MIN(2, dim); + 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); + assert(clip_rect.encloses( + Rect2i(m.second, Vector2i(1, 1)))); + positions.push_back(m); + flecs::log::warn("add position: %d, %d", selected.x, + selected.y); + accepted.clear(); + break; + } else { + assert(positions.size() > 0); + continue; + } + } +} + +#if 0 + +void grid_misc::place_region_cells( + flecs::entity grid_floor_e, + const WorldEditor::components::buildings_layout_grid_floor &fl, + growth_regions &g) +{ + int i; + for (i = 0; i < g.regions.size(); i++) { + int x, y; + RegionRect2i rect = g.regions[i].rect; + for (x = rect.position.x; x <= rect.position.x + rect.size.x; + x++) + for (y = rect.position.y; + y <= rect.position.y + rect.size.y; y++) { + int id = x + fl.grid_size * y; + if (!fl.cells.has(id)) { + flecs::entity seed_e = + grid_floor_e.world().entity( + g.regions[i].seed_et); + assert(seed_e.is_valid()); + assert(seed_e.parent().is_valid()); + assert(seed_e.parent().id() == + grid_floor_e.id()); + queue_grow_cell(seed_e, id); + } + } + } +} +#endif + +void grid_misc::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< + WorldEditor::components::buildings_layout_grid_queue>()) { + List > queue; + queue.push_back(m); + floor_e.set( + { queue }); + } else { + floor_e.get_mut() + ->queue.push_back(m); + floor_e.modified< + WorldEditor::components::buildings_layout_grid_queue>(); + } +} + +#if 0 +void grid_misc::print_can_grow(int state, growth_regions &g, int index, + const char *what) +{ + const growth_regions::region ®ion = g.regions[index]; + bool can = false; + if (!strcmp(what, "square")) + can = region.can_grow_square; + else if (!strcmp(what, "rect")) + can = region.can_grow; + + if (can) + flecs::log::dbg( + "state: %d: index %d: region can still grow %s %d", + state, index, what, region.remains_area); + else + flecs::log::dbg("state: %d: index %d: region can't grow %s %d", + state, index, what, region.remains_area); + if (region.can_grow_region()) + flecs::log::dbg("state %d: index %d: region can still continue", + state, index); +} + +bool grid_misc::grow_state0(growth_regions &g, int index, + const RegionRect2i &clip) +{ + bool ok = true, ret = false; + RegionRect2i mrect; + growth_regions::region ®ion = g.regions.write[index]; + mrect = region.rect; + assert(g.check_region(index, mrect)); + + mrect = mrect.grow(1); + ok = clip.encloses(mrect); + // if (!ok) + // flecs::log::dbg("state: %d: index %d: out of clip area", + // 0, index); + if (ok) { + ok = g.check_region(index, mrect); + // if (!ok) + // flecs::log::dbg( + // "state: %d: index %d: check_region failed", + // 0, index); + } + if (ok) { + ret = region.update_region_size(mrect); + // if (!ret) + // flecs::log::dbg( + // "state: %d: index %d: update_region_size failed", + // 0, index); + } + print_can_grow(0, g, index, "square"); + // if (!ret) + // flecs::log::dbg("state %d could not grow region %d: %d", + // 0, index, region.remains_area); + // else + // flecs::log::dbg("state %d could grow region %d: %d", 0, + // index, region.remains_area); + return ret; +} + +#if 0 +bool grid_misc::grow_state1(growth_regions &g, int index, + const RegionRect2i &clip) +{ + int d; + bool ret = false; + RegionRect2i mrect; + growth_regions::region ®ion = g.regions.write[index]; + int count = 0; + for (d = 0; d < 4; d++) { + bool ok; + mrect = region.rect; + assert(g.check_region(index, mrect)); + switch (d) { + case 0: + mrect.position.y -= 1; + mrect.size.y += 1; + break; + case 1: + mrect.size.y += 1; + break; + case 2: + mrect.position.x -= 1; + mrect.size.x += 1; + break; + case 3: + mrect.size.x += 1; + break; + } + ok = g.parent_regions[region.parent_region].rect.encloses( + mrect); + if (ok) + 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) { + bool result = region.update_region_size(mrect); + if (result) + count++; + } + } + if (count > 0) { + ret = true; + // flecs::log::dbg( + // "state %d could grow region %d: %d - %d out of %d times", + // 0, index, region.remains_area, count, 4); + } + print_can_grow(1, g, index, "rect"); + // if (!ret) + // flecs::log::dbg( + // "state %d could not grow region rect %d: %d", 0, + // index, region.remains_area); + return ret; +} +#endif +#endif + +#if 0 +void grid_misc::grow_region_rects( + flecs::entity floor_e, + WorldEditor::components::buildings_layout_grid_floor &fl, + growth_regions &g) +{ + int i; + bool grown = true; + int state = 0; + if (g.complete) + return; + Rect2i clip(0, 0, fl.grid_size, fl.grid_size); + state = 0; + // flecs::log::dbg("growing square"); + while (grown) { + grown = false; + int count = 0; + for (i = 0; i < g.regions.size(); i++) { + growth_regions::region ®ion = g.regions.write[i]; + RegionRect2i mrect = region.rect; + // flecs::log::dbg("grow_region_rects: region %d", + // i); + if (!region.can_grow_region()) { + // flecs::log::dbg( + // "grow_region_rects: skip %d", + // i); + continue; + } + mrect = region.rect; + bool result = false; + result = grow_state0(g, i, clip); + if (result) + count++; + } + if (count > 0) { + grown = true; + // flecs::log::dbg("grown squares %d times of %d", + // count, g.regions.size()); + } + // if (!grown) + // flecs::log::dbg( + // "grow_region_rects: could not grow more squares"); + } + state = 1; + grown = true; + // flecs::log::dbg("growing rect"); + while (grown) { + grown = false; + int count = 0; + for (i = 0; i < g.regions.size(); i++) { + growth_regions::region ®ion = g.regions.write[i]; + RegionRect2i mrect = region.rect; + // flecs::log::dbg("grow_region_rects: region %d", + // i); + if (!region.can_grow_region()) { + // flecs::log::dbg( + // "grow_region_rects: skip %d", + // i); + continue; + } + mrect = region.rect; + bool result = false; + result = grow_state1(g, i, clip); + if (result) + count++; + // if (!result) + // flecs::log::dbg( + // "state %d could not grow region %d", + // state, i); + // else + // flecs::log::dbg( + // "state %d could grow region %d: %d", + // state, i, region.remains_area); + } + if (count > 0) { + grown = true; + // flecs::log::dbg("grown rects %d times of %d", + // count, g.regions.size()); + } + // if (!grown) + // flecs::log::dbg( + // "grow_region_rects: could not grow any more rects"); + } + flecs::log::dbg("grow_region_rects: complete"); + g.complete = true; + flecs::log::dbg("grow_region_rects: %s: done", floor_e.path().c_str()); +} + +void grid_misc::subregions_init(flecs::world w) +{ + flecs::query qprep = + w.query_builder< + const WorldEditor::components::buildings_layout_area>() + .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 grid_misc::get_subregions(flecs::entity parent, + List > *subregions) +{ + flecs::query qprep = + parent.world() + .query_builder() + .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 }); + }); +} +#endif diff --git a/src/modules/stream/ui/grid_misc.h b/src/modules/stream/ui/grid_misc.h new file mode 100644 index 0000000..42b8829 --- /dev/null +++ b/src/modules/stream/ui/grid_misc.h @@ -0,0 +1,196 @@ +#ifndef GRID_MISC_H +#define GRID_MISC_H +#include +#include +#include "world_editor.h" +struct RegionRect2i; +struct growth_regions; +struct make_random { + int seed; + int next; + make_random(int seed) + : seed(seed) + , next(seed) + { + } + int get() + { + next = next * 1103515245 + 12345; + return (int)((unsigned)next >> 16) % 32768; + } +}; +struct grid_misc { + Vector > positions; + Vector accepted; + struct make_random r; + grid_misc() + : r(100) + { + } + void get_dim_candidates(const Vector2i &base, int dim, + Vector2i *candidates); + int get_floor_index(flecs::entity e) const; + flecs::entity get_grid_floor(flecs::entity grid_e, + flecs::entity graph_floor_e) const; + bool check_duplicates() const; + void place_regions(flecs::entity grid_floor_e); + void place_regions_common(flecs::entity parent_e, + flecs::entity grid_floor_e, int parent_index); + float get_entity_area(flecs::entity e) const + { + return e.get() + ->area; + } + float get_entity_area(flecs::world &&ecs, flecs::entity_t et) const + { + flecs::entity e = ecs.entity(et); + return e.get() + ->area; + } + float get_entity_area(flecs::world &ecs, flecs::entity_t et) const + { + flecs::entity e = ecs.entity(et); + return e.get() + ->area; + } + int get_base_radius(flecs::world &&ecs, flecs::entity_t et) const + { + float base_area = get_entity_area(ecs, et); + int base_radius = (int)((Math::sqrt(base_area) * 1.6f) / 2.0f) / + 4; /* grid conversion */ + return base_radius; + } + int get_base_radius(flecs::world &ecs, flecs::entity_t et) const + { + float base_area = get_entity_area(ecs, et); + int base_radius = (int)((Math::sqrt(base_area) * 1.6f) / 2.0f) / + 4; /* grid conversion */ + return base_radius; + } + int distance_squared(const Vector2i &p1, const Vector2i &p2) const + { + int lx = p2.x - p1.x; + int ly = p2.y - p1.y; + return lx * lx + ly * ly; + } + bool check_candidates_tolerance(const Vector2i check) + { + int i; + bool ret = true; + for (i = 0; i < (int)positions.size(); i++) + if (distance_squared(check, positions[i].second) < 1) { + ret = false; + break; + } + return ret; + } + bool check_candidate(const Vector2i &candidate) + { + int m; + bool bad = false; + for (m = 0; m < (int)positions.size(); m++) + if (positions[m].second == candidate) { + bad = true; + break; + } + return !bad; + } + bool accept_candidate(flecs::entity ce, const Vector2i &candidate, + float area) + { + int k; + int local_radius = (int)((Math::sqrt(area) * 1.6f) / 2.0f) / + 4; /* grid conversion */ + local_radius = MAX(1, local_radius); + bool ok = false; + for (k = 0; k < (int)positions.size(); k++) { + assert(k < (int)positions.size()); + flecs::entity_t pbase_et = positions[k].first; + float parea = get_entity_area(ce.world(), pbase_et); + int pdim = (int)((Math::sqrt(parea) * 1.5f) / 2.0f) / + 4; /* radius converted to grid 4x4*/ + int radius = pdim + local_radius; + int radius_sq = radius * radius; + 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 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 RegionRect2i &clip, bool tight); + void filter_candidates(flecs::entity ce, float area, + const RegionRect2i &clip_rect); + int which_position() + { + int which; + if (positions.size() == 0) + return -1; + which = r.get() % positions.size(); + assert(which < (int)positions.size()); + return which; + } + int which_selected() + { + int which; + if (accepted.size() == 0) + return -1; + which = r.get() % accepted.size(); + assert(which < (int)accepted.size()); + return which; + } + void place_region_cells( + flecs::entity grid_floor_e, + const WorldEditor::components::buildings_layout_grid_floor &fl, + growth_regions &g); + void queue_grow_cell(flecs::entity seed_e, int id); + void print_can_grow(int state, growth_regions &g, int index, + const char *what); + bool grow_state0(growth_regions &g, int index, + const RegionRect2i &clip); + bool grow_state1(growth_regions &g, int index, + const RegionRect2i &clip); + void grow_region_rects( + flecs::entity floor_e, + WorldEditor::components::buildings_layout_grid_floor &fl, + growth_regions &g); + Vector > all_items; + void subregions_init(flecs::world w); + void get_subregions(flecs::entity parent, + List > *subregions); +}; + +#endif diff --git a/src/modules/stream/ui/grow_job.cpp b/src/modules/stream/ui/grow_job.cpp new file mode 100644 index 0000000..643b13a --- /dev/null +++ b/src/modules/stream/ui/grow_job.cpp @@ -0,0 +1,735 @@ +#include "base_data.h" +#include "world_editor.h" +#include "grid_misc.h" +#include "graph_module.h" +#include "queries.h" +#include "region_tree.h" +#include "grow_job.h" + +static inline int get_floor_index(flecs::entity e) +{ + return e.get() + ->index; +} + +static inline 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; +} + +grow_job_queue::grow_job_queue( + flecs::entity grid_e, struct subregions &subregions, + const WorldEditor::components::buildings_layout_grid_size &size, + const String &module_name) + : grid_e(grid_e) + , grid_size(size.grid_size) + , subregions(subregions) + , 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 }); + flecs::entity_t base_floor_et = + job_create_queue.front()->get().second; + flecs::entity base_floor_e = + grid_e.world().entity(base_floor_et); + flecs::entity grid_floor_e = + get_grid_floor(grid_e, base_floor_e); + grid_floor_e.get_mut()->job_list = + List(); + 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 = + get_grid_floor(grid_e, base_floor_e); + flecs::log::dbg("job_queue: grid_floor: %s", + grid_floor_e.path().c_str()); + assert(!subregions.sub_subregions.empty()); + if (subregions.sub_subregions.has(et) && + !subregions.sub_subregions[et].empty()) { + flecs::log::dbg( + "subregions for: %s", + grid_e.world().entity(et).path().c_str()); + struct grow_job job; + if (grid_floor_e.get()->job_list.empty()) + 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 = + subregions.sub_subregions[job.parent_id]; + grid_floor_e.get_mut() + ->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(); + } + grid_floor_e.modified(); + } else + flecs::log::dbg( + "no subregions for: %s", + grid_e.world().entity(et).path().c_str()); + } +} +void grow_job_queue::job_initial(struct grow_job *job) +{ + int i, j; + flecs::entity base_floor_e = grid_e.world().entity(job->base_floor_id); + flecs::entity grid_floor_e = grid_e.world().entity(job->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(); + RegionRect2i clip_rect(1, 1, grid_size - 2, grid_size - 2); + const List > &subregions = job->subregions; + List initial_regions; +#if 0 + assert(g->regions.size() == 0); +#endif + if (subregions.size() == 0) { + flecs::log::err("nothing to do"); + return; + } + grid_floor_e.set( + { { job->base_floor_id, job->base_floor_id, job->base_floor_id, + clip_rect.grow(-1), grid_size * grid_size, false, false, + true }, + Vector(), + nullptr }); + struct region_tree *rtree = grid_floor_e.get_mut(); + create_region_list(rtree, subregions, initial_regions); + grid_floor_e.modified(); + grid_floor_e.get_mut()->split(grid_floor_e, + initial_regions); + assert(rtree->check(grid_floor_e)); + grid_floor_e.modified(); + grid_floor_e.get()->dump(grid_floor_e); + grid_floor_e.get_mut()->grow(grid_floor_e); + grid_floor_e.modified(); + grid_floor_e.get()->dump(grid_floor_e); + // grid_floor_e.get()->place(grid_floor_e); + List rects; + List::Element *e, *e1; + grid_floor_e.get()->get_rects(&rects); + e = rects.front(); + bool ok = true; + while (e) { + e1 = rects.front(); + while (e1) { + if (e->get() == e1->get()) { + e1 = e1->next(); + continue; + } + if (e->get().intersects(e1->get())) + ok = false; + if (e->get().encloses(e1->get())) + ok = false; + if (e1->get().intersects(e->get())) + ok = false; + if (e1->get().encloses(e->get())) + ok = false; + if (!ok) + break; + e1 = e1->next(); + } + e = e->next(); + } + +#if 0 + 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->grid.filter_candidates(ce, area, clip_rect); + fe = fe->next(); + } +#endif +#if 0 + job->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(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)); + }); + flecs::log::dbg("initial: region count: %d", g->regions.size()); + assert(g->regions.size() > 0); +#endif + assert(rtree->check(grid_floor_e)); +} +void grow_job_queue::job_common(struct grow_job *job) +{ + int i, j; + make_random r(172); + flecs::entity base_floor_e = grid_e.world().entity(job->base_floor_id); + flecs::entity grid_floor_e = grid_e.world().entity(job->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()); + flecs::entity parent_e = grid_e.world().entity(job->parent_id); + growth_regions *g = grid_floor_e.get_mut(); + const List > &subregions = job->subregions; + const List >::Element *fe = + subregions.front(); + + struct region_tree *base_rtree = grid_floor_e.get_mut(), + *rtree; + List region_list; + base_rtree->dump(grid_floor_e); + flecs::log::warn("search for: %s %lx", parent_e.path().c_str(), + job->parent_id); + rtree = base_rtree->find(job->parent_id); + if (!rtree) { + g->job_list.push_back(*job); + flecs::log::warn("delay job fo %s (%d jobs)", + parent_e.path().c_str(), g->job_list.size()); + return; + } + create_region_list(rtree, subregions, region_list); + assert(base_rtree->check(grid_floor_e)); + rtree->split(grid_floor_e, region_list); + assert(base_rtree->check(grid_floor_e)); + grid_floor_e.modified(); + rtree->dump(grid_floor_e); + assert(base_rtree->check(grid_floor_e)); + rtree->grow(grid_floor_e); + assert(base_rtree->check(grid_floor_e)); + rtree->dump(grid_floor_e); + grid_floor_e.modified(); + +#if 0 + flecs::log::dbg("common: region count: %d", g->regions.size()); + assert(g->regions.size() > 0); + bool restart = false, found = false; + RegionRect2i clip_rect(0, 0, grid_size, grid_size); + 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()); + } + int region_index = -1; + for (i = 0; i < (int)g->regions.size(); i++) { + if (g->regions[i].region_et == job->parent_id) { + flecs::log::warn("parent is in regions %d", i); + region_index = i; + if (!g->regions[i].complete) { + g->job_list.push_back(*job); + 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->parent_id) + .path() + .c_str(), + g->job_list.size()); + } + found = true; + break; + } + } + if (!found) { + // no parent region yet + g->job_list.push_back(*job); + flecs::log::warn("delay job fo %s (%d jobs)", + parent_e.path().c_str(), g->job_list.size()); + restart = true; + } + if (restart) + return; +#endif +#if 0 + for (i = 0; i < g->regions.size(); i++) + flecs::log::warn( + "before: region %d: %s", i, + (g->regions[i].rect.operator String()).ascii().ptr()); + // growth_regions::region parent_region = g->regions[region_index]; + // const List >::Element *fe = + // subregions.front(); + List > region_list = subregions; + g->split_region(grid_floor_e, region_index, region_list); +#endif + // g->regions.remove(region_index); + // clip_rect = parent_region.rect; + // int parent_region_index = g->parent_regions.size(); + // g->parent_regions.push_back(parent_region); + /* + 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->grid.filter_candidates(ce, area, clip_rect); + fe = fe->next(); + } + job->grid.place_regions_common(parent_e, grid_floor_e, + parent_region_index); +*/ +#if 0 + for (i = 0; i < g->regions.size(); i++) + flecs::log::warn( + "after: region %d: %s", i, + (g->regions[i].rect.operator String()).ascii().ptr()); + flecs::log::dbg("Running grow..."); + g->grow_regions(grid_floor_e); +#endif +#if 0 + // FIXME: fix this + queries.get_qr().each( + [this, parent_e]( + flecs::entity grid_floor_e, + WorldEditor::components::buildings_layout_grid_floor &fl, + growth_regions &g) { + if (g.complete) + return; + g.grow_regions(grid_floor_e); + }); +#endif +#if 0 + for (i = 0; i < g->regions.size(); i++) + flecs::log::warn( + "after2: region %d: %s", i, + (g->regions[i].rect.operator String()).ascii().ptr()); +#endif +#if 0 + queries.get_qr().each( + [this, parent_e]( + 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(grid_floor_e, fl, g); + grd.update_region_cells(grid_floor_e, parent_e, fl, g); + assert(false); + }); +#endif +#if 0 + update_region_cells(grid_floor_e); + for (i = 0; i < (int)g->regions.size(); i++) + g->regions.write[i].complete = true; + g->complete = true; +#endif + commit_common_queue(); + // assert(false); +} +void grow_job_queue::commit_common_queue() +{ + grid_e.world() + .query_builder< + WorldEditor::components::buildings_layout_grid_floor, + WorldEditor::components::buildings_layout_grid_queue>() + .each([this](flecs::entity e, + WorldEditor::components::buildings_layout_grid_floor + &fl, + WorldEditor::components::buildings_layout_grid_queue + &queue) { + List >::Element *me = + queue.queue.front(); + while (me) { + flecs::entity seed_e = + e.world().entity(me->get().first); + int id = me->get().second; + if (!fl.cells.has(id)) { + flecs::log::err("bad cell %d", id); + assert(false); + } + // fl.cells.insert(id); + flecs::entity floor_e = seed_e.parent(); + String c_name = "cell_" + itos(id); + flecs::entity c_e = + floor_e.lookup(c_name.ascii().ptr()); + if (c_e.is_valid() && + c_e.has()) { + // flecs::log::dbg("cell: %s: %s", + // e.path().c_str(), + // c_e.path().c_str()); + String type = + seed_e.get() + ->type; + c_e.set( + { type, id }); + seed_e.each< + WorldEditor::components::belongs>( + [&c_e](flecs::entity second) { + c_e.add( + second); + }); + seed_e.each( + [&c_e](flecs::entity second) { + c_e.add( + second); + }); + floor_e.modified< + WorldEditor::components:: + buildings_layout_grid_floor>(); + } else { + flecs::log::err("bad cell %s", + c_name.ascii().ptr()); + assert(false); + } + me = me->next(); + } + queue.queue.clear(); + e.remove(); + }); +} +void grow_job_queue::create_region_list( + region_tree *rtree, const List > &subregions, + List ®ion_list) +{ + int i, j; + const List >::Element *fe = + subregions.front(); + bool restart = false, found = false; + make_random r(172); + RegionRect2i clip_rect = rtree->region.rect; + Vector2i current_position = clip_rect.get_center(); + Vector2i velocity; + + Vector regions; + LocalVector positions; + Vector distances; + LocalVector areas; + // Drunk walk implementation + int speed = MAX(1, grid_size * grid_size / 2 / subregions.size()); + int bad_count = 0; + while (fe) { + Vector position_candidates; + if (positions.empty()) { + int target_distance = + (int)(Math::sqrt(fe->get().second) * 0.7f) + 1; + positions.push_back(current_position); + distances.push_back(target_distance); + regions.push_back(fe->get().first); + areas.push_back(fe->get().second); + fe = fe->next(); + if (!fe) + break; + } + for (i = 0; i < (int)positions.size(); i++) { + int which = r.get() % 12; + switch (which) { + case 1: + velocity = { 0, 1 }; + break; + case 3: + velocity = { 1, 0 }; + break; + case 5: + velocity = { 0, -1 }; + break; + case 7: + velocity = { -1, 0 }; + break; + } + if (clip_rect.has_point(current_position + velocity)) { + position_candidates.push_back(current_position + + velocity); + current_position += velocity; + } + } + int target_distance = + (int)(Math::sqrt(fe->get().second) * 0.7f) + 1; + assert(fe); + if (bad_count > 100) + target_distance = 1; + bool any_match = false; + for (i = 0; i < position_candidates.size(); i++) { + bool bad = false; + assert(fe); + for (j = 0; j < (int)positions.size(); j++) { + Vector2i l = + position_candidates[i] - positions[j]; + int distance = + l.x * l.x + l.y * l.y - distances[j]; + if (distance < target_distance) { + bad = true; + break; + } + } + assert(fe); + if (!bad) { + assert(fe); + positions.push_back(position_candidates[i]); + distances.push_back(target_distance); + regions.push_back(fe->get().first); + areas.push_back(fe->get().second); + any_match = true; + bad_count = 0; + if (fe) { + fe = fe->next(); + if (fe) + target_distance = + (int)(Math::sqrt( + fe->get() + .second) * + 0.7f) + + 1; + } + } + if (!fe) + break; + } + if (!any_match) { + flecs::log::err( + "No match found: %s: %s", + (clip_rect.operator String()).ascii().ptr(), + (current_position.operator String()) + .ascii() + .ptr()); + bad_count++; + } + if (bad_count >= 100) { + position_candidates.clear(); + int x, y; + for (x = clip_rect.position.x; + x < clip_rect.position.x + clip_rect.size.x; x++) + for (y = clip_rect.position.y; + y < + clip_rect.position.y + clip_rect.size.y; + y++) { + position_candidates.push_back( + Vector2i(x, y)); + } + bad_count = 0; + for (i = 0; i < position_candidates.size(); i++) { + bool bad = false; + assert(fe); + for (j = 0; j < (int)positions.size(); j++) { + Vector2i l = position_candidates[i] - + positions[j]; + int distance = l.x * l.x + l.y * l.y - + distances[j]; + if (distance > 0) { + bad = true; + break; + } + } + assert(fe); + if (!bad) { + assert(fe); + positions.push_back( + position_candidates[i]); + distances.push_back(target_distance); + regions.push_back(fe->get().first); + areas.push_back(fe->get().second); + any_match = true; + bad_count = 0; + if (fe) + fe = fe->next(); + } + if (!fe) + break; + } + } + assert(bad_count < 2000); + } + flecs::log::dbg("grid_size %d", grid_size); + for (i = 0; i < (int)positions.size(); i++) { + struct region region; + flecs::log::dbg("region: %s", regions[i].path().c_str()); + flecs::log::dbg("position: %d, %d", positions[i].x, + positions[i].y); + region.complete = false; + region.can_grow = true; + region.can_grow_square = true; + region.parent = rtree->region.region_et; + region.rect = RegionRect2i(positions[i], Vector2i(1, 1)); + region.region_et = regions[i].id(); + region.remains_area = MAX(1, (areas[i] / 16)); + /* setting seed uninitialized */ + region_list.push_back(region); + } +} +void grow_job_queue::iterate() +{ + assert(grid_e.is_valid()); + assert(this); + flecs::query q = + grid_e.world().query_builder().build(); + q.each([this](flecs::entity e, growth_regions &g) { + flecs::log::warn("pre floor: %s", e.path().c_str()); + }); + q.each([this](flecs::entity e, growth_regions &g) { + flecs::log::warn("floor: %s", e.path().c_str()); + flecs::log::warn("job count: %d", g.job_list.size()); + while (!g.job_list.empty()) { + List::Element *job_e = + g.job_list.front(); + assert(job_e); + flecs::entity base_floor_e = grid_e.world().entity( + job_e->get().base_floor_id); + assert(base_floor_e.is_valid()); + flecs::entity grid_floor_e = grid_e.world().entity( + job_e->get().grid_floor_id); + assert(grid_floor_e.is_valid()); + flecs::log::dbg("inerate: create: base_floor: %s", + base_floor_e.path().c_str()); + flecs::log::dbg("iterate: create: grid_floor: %s", + grid_floor_e.path().c_str()); + switch (job_e->get().job_type) { + case grow_job::INITIAL: + flecs::log::dbg("initial"); + job_initial(&job_e->get()); + { + const region_tree *rtree = + e.get(); + assert(!rtree || + (rtree && + rtree->check(grid_floor_e))); + } + break; + case grow_job::COMMON: + flecs::log::dbg("common"); + job_common(&job_e->get()); + { + const region_tree *rtree = + e.get(); + assert(!rtree || + (rtree && + rtree->check(grid_floor_e))); + } + break; + default: + assert(false); + break; + } + g.job_list.pop_front(); + // if (common_count > 0) + // break; + } + g.job_list.clear(); + flecs::query qm = + grid_e.world().query_builder().build(); + qm.each([this](flecs::entity em, region_tree &rt) { + assert(rt.check(em)); + }); + qm.each([this](flecs::entity em, region_tree &rt) { + rt.place(em); + }); + flecs::log::dbg( + "processed jobs (created region initial positions): %d", + g.job_list.size()); + }); +} \ No newline at end of file diff --git a/src/modules/stream/ui/grow_job.h b/src/modules/stream/ui/grow_job.h new file mode 100644 index 0000000..a0f3ccb --- /dev/null +++ b/src/modules/stream/ui/grow_job.h @@ -0,0 +1,31 @@ +#ifndef GROW_JOB_H +#define GROW_JOB_H +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; +}; + +struct grow_job_queue { + flecs::entity grid_e; + int grid_size; + struct subregions &subregions; + const String &module_name; + grow_job_queue( + flecs::entity grid_e, struct subregions &subregions, + const WorldEditor::components::buildings_layout_grid_size &size, + const String &module_name); + void iterate(); + void job_initial(struct grow_job *job); + void job_common(struct grow_job *job); + void commit_common_queue(); + void + create_region_list(struct region_tree *rtree, + const List > &subregions, + List ®ion_list); +}; +#endif diff --git a/src/modules/stream/ui/growth_module.cpp b/src/modules/stream/ui/growth_module.cpp new file mode 100644 index 0000000..1342b97 --- /dev/null +++ b/src/modules/stream/ui/growth_module.cpp @@ -0,0 +1,242 @@ +#include "growth_regions.h" +#include "region_tree.h" +#include "editor_event.h" +#include "queries.h" +#include "growth_module.h" + +growth_module::growth_module(flecs::world &ecs) +{ + ecs.module(); + ecs.component(); + ecs.component(); + const String &module_name = "::growth_module"; + flecs::entity GraphFilter = ecs.entity("GraphFilter") + .add(flecs::Phase) + .depends_on(flecs::OnUpdate); + flecs::entity GraphSolve = ecs.lookup("::graph_module::GraphSolve"); + assert(GraphSolve.is_valid()); + GraphFilter.disable(); +#if 0 + flecs::entity GraphGridPrepare = ecs.entity("GraphGridPrepare") + .add(flecs::Phase) + .depends_on(GraphSolve); +#endif + + ecs.system("RunGrow") + .immediate() + .write() + .write() + .write() + .kind(GraphSolve) + .run([module_name, this, GraphFilter](flecs::iter &it) { + flecs::world &&ecs_ = it.world(); + it.world().defer_suspend(); + flecs::log::dbg("Assembling skeleton done..."); + flecs::entity GraphSolveZones = it.world().lookup( + "::graph_module::GraphSolveZones"); + assert(GraphSolveZones.is_valid()); + GraphSolveZones.disable(); + assert(GraphFilter.is_valid()); + GraphFilter.enable(); + EditorEvent::get_singleton()->event.emit( + "update_layout_view", varray()); + // assert(false); + struct subregions subregions(ecs_); + struct queries queries(ecs_); + flecs::log::dbg("Creating regions grow..."); + queries.get_qp().each( + [this, &subregions, &queries, + module_name](flecs::iter &it2, size_t count, + const WorldEditor::components:: + buildings_layout_grid_size + &size) { + struct grid_misc grid; + // 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 = + queries.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 */ + subregions.build_subregions(grid_e, + grid, size); + struct grow_job_queue job_queue( + grid_e, subregions, size, + module_name); + job_queue.iterate(); + }); + commit_growth_queue(it.world()); + 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; +#if 0 + bool border = false; +#endif + for (i = 0; i < (int)neighbors.size(); i++) { + int id = neighbors[i]; + print_line("id=" + itos(id)); + String neighbor_cell = + "cell_" + itos(id); + flecs::entity neighbor_e = + e.parent().lookup( + neighbor_cell.ascii() + .ptr()); + if (!neighbor_e.is_valid()) { + outside = true; + break; + } + if (!e.parent() + .get() + ->cells.has(id)) { + outside = true; + break; + } + } + flecs::log::dbg("outside: %d", outside); +#if 0 + 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; + } + } +#endif + if (outside) { + e.add(); + flecs::log::dbg("outside wall cell %s", + e.path().c_str()); + } else + e.add(); +#if 0 + if (border) + e.add(); +#endif + 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)); + }); + it.world() + .lookup("::growth_module::GraphFilter") + .disable(); + it.world().defer_resume(); + }); +} + +void growth_module::grow_cell(flecs::entity seed_e, int id) +{ + flecs::entity floor_e = seed_e.parent(); + String c_name = "cell_" + itos(id); + flecs::entity c_e = floor_e.lookup(c_name.ascii().ptr()); + if (!c_e.is_valid()) { + c_e = seed_e.world() + .entity(c_name.ascii().ptr()) + .child_of(floor_e); + assert(c_e.is_valid()); + String type = seed_e.get() + ->type; + c_e.set( + { type, id }); + seed_e.each( + [&c_e](flecs::entity second) { + c_e.add( + second); + }); + int mcount = 0; + seed_e.each( + [&c_e, &mcount](flecs::entity second) { + assert(mcount == 0); + c_e.add( + second); + mcount++; + }); + floor_e.get_mut() + ->size_left--; + floor_e.get_mut() + ->cells.insert(id); + floor_e.modified< + WorldEditor::components::buildings_layout_grid_floor>(); + } +} + +void growth_module::commit_growth_queue(flecs::world &&ecs) +{ + flecs::query + grow_commit_queue = + ecs.query_builder() + .build(); + grow_commit_queue.each( + [this](flecs::entity e, + WorldEditor::components::buildings_layout_grid_floor &fl, + WorldEditor::components::buildings_layout_grid_queue + &queue) { + List >::Element *me = + queue.queue.front(); + while (me) { + flecs::entity seed_e = + e.world().entity(me->get().first); + int id = me->get().second; + if (!fl.cells.has(id)) { + grow_cell(seed_e, id); + fl.cells.insert(id); + } + me = me->next(); + } + queue.queue.clear(); + e.remove(); + }); +} diff --git a/src/modules/stream/ui/growth_module.h b/src/modules/stream/ui/growth_module.h new file mode 100644 index 0000000..813bdb7 --- /dev/null +++ b/src/modules/stream/ui/growth_module.h @@ -0,0 +1,12 @@ +/* ~/godot-projects/streaming_world/src/modules/stream/ui/growth_module.h */ +#ifndef GROWTH_MODULE_H_ +#define GROWTH_MODULE_H_ +#include "base_data.h" + +struct growth_module { + void grow_cell(flecs::entity seed_e, int id); + void commit_growth_queue(flecs::world &&world); + growth_module(flecs::world &ecs); +}; + +#endif // GROWTH_MODULE_H_ \ No newline at end of file diff --git a/src/modules/stream/ui/growth_regions.cpp b/src/modules/stream/ui/growth_regions.cpp new file mode 100644 index 0000000..8d24811 --- /dev/null +++ b/src/modules/stream/ui/growth_regions.cpp @@ -0,0 +1,213 @@ +#include "growth_regions.h" + +#if 0 + +static void print_can_grow(int state, growth_regions &g, int index, + const char *what) +{ + const growth_regions::region ®ion = g.regions[index]; + bool can = false; + if (!strcmp(what, "square")) + can = region.can_grow_square; + else if (!strcmp(what, "rect")) + can = region.can_grow; + + if (can) + flecs::log::dbg( + "state: %d: index %d: region can still grow %s %d", + state, index, what, region.remains_area); + else + flecs::log::dbg("state: %d: index %d: region can't grow %s %d", + state, index, what, region.remains_area); + if (region.can_grow_region()) + flecs::log::dbg("state %d: index %d: region can still continue", + state, index); +} + +bool growth_regions::grow_state0(int index, const RegionRect2i &clip) +{ + bool ok = true, ret = false; + RegionRect2i mrect; + growth_regions::region ®ion = regions.write[index]; + mrect = region.rect; + assert(check_region(index, mrect)); + + mrect = mrect.grow(1); + ok = clip.encloses(mrect); + // if (!ok) + // flecs::log::dbg("state: %d: index %d: out of clip area", + // 0, index); + if (ok) { + ok = check_region(index, mrect); + // if (!ok) + // flecs::log::dbg( + // "state: %d: index %d: check_region failed", + // 0, index); + } + if (ok) { + ret = region.update_region_size(mrect); + // if (!ret) + // flecs::log::dbg( + // "state: %d: index %d: update_region_size failed", + // 0, index); + } + print_can_grow(0, *this, index, "square"); + // if (!ret) + // flecs::log::dbg("state %d could not grow region %d: %d", + // 0, index, region.remains_area); + // else + // flecs::log::dbg("state %d could grow region %d: %d", 0, + // index, region.remains_area); + return ret; +} +bool growth_regions::grow_state1(int index, const RegionRect2i &clip) +{ + int d; + bool ret = false; + RegionRect2i mrect; + growth_regions::region ®ion = regions.write[index]; + int count = 0; + for (d = 0; d < 4; d++) { + bool ok; + mrect = region.rect; + assert(check_region(index, mrect)); + switch (d) { + case 0: + mrect.position.y -= 1; + mrect.size.y += 1; + break; + case 1: + mrect.size.y += 1; + break; + case 2: + mrect.position.x -= 1; + mrect.size.x += 1; + break; + case 3: + mrect.size.x += 1; + break; + } + ok = parent_regions[region.parent_region].rect.encloses(mrect); + if (ok) + 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 = check_region(index, mrect); + if (ok) { + bool result = region.update_region_size(mrect); + if (result) + count++; + } + } + if (count > 0) { + ret = true; + // flecs::log::dbg( + // "state %d could grow region %d: %d - %d out of %d times", + // 0, index, region.remains_area, count, 4); + } + print_can_grow(1, *this, index, "rect"); + // if (!ret) + // flecs::log::dbg( + // "state %d could not grow region rect %d: %d", 0, + // index, region.remains_area); + return ret; +} +#endif +#if 0 +void growth_regions::grow_regions(flecs::entity grid_floor_e) +{ + int i; + bool grown = true; + int state = 0; + if (complete) + return; +#if 0 + int grid_size = grid_floor_e + .get() + ->grid_size; +#endif + state = 0; + flecs::log::dbg("growing square"); + while (grown) { + grown = false; + int count = 0; + for (i = 0; i < regions.size(); i++) { + growth_regions::region ®ion = regions.write[i]; + const RegionRect2i &clip = + parent_regions[region.parent_region].rect; + RegionRect2i mrect = region.rect; + flecs::log::dbg("grow_region_rects: region %d", i); + if (!region.can_grow_region()) { + flecs::log::dbg("grow_region_rects: skip %d", + i); + continue; + } + mrect = region.rect; + bool result = false; + result = grow_state0(i, clip); + if (result) + count++; + } + if (count > 0) { + grown = true; + flecs::log::dbg("grown squares %d times of %d", count, + regions.size()); + } + if (!grown) + flecs::log::dbg( + "grow_region_rects: could not grow more squares"); + } + state = 1; + grown = true; + flecs::log::dbg("growing rect"); + while (grown) { + grown = false; + int count = 0; + for (i = 0; i < regions.size(); i++) { + growth_regions::region ®ion = regions.write[i]; + const RegionRect2i &clip = + parent_regions[region.parent_region].rect; + RegionRect2i mrect = region.rect; + flecs::log::dbg("grow_region_rects: region %d", i); + if (!region.can_grow_region()) { + flecs::log::dbg("grow_region_rects: skip %d", + i); + continue; + } + mrect = region.rect; + bool result = false; + result = grow_state1(i, clip); + if (result) + count++; + if (!result) + flecs::log::dbg( + "state %d could not grow region %d", + state, i); + else + flecs::log::dbg( + "state %d could grow region %d: %d", + state, i, region.remains_area); + } + if (count > 0) { + grown = true; + flecs::log::dbg("grown rects %d times of %d", count, + regions.size()); + } + if (!grown) + flecs::log::dbg( + "grow_region_rects: could not grow any more rects"); + } + flecs::log::dbg("grow_region_rects: complete"); + complete = true; + flecs::log::dbg("grow_region_rects: %s: done", + grid_floor_e.path().c_str()); +} +#endif \ No newline at end of file diff --git a/src/modules/stream/ui/growth_regions.h b/src/modules/stream/ui/growth_regions.h new file mode 100644 index 0000000..14780a1 --- /dev/null +++ b/src/modules/stream/ui/growth_regions.h @@ -0,0 +1,99 @@ +#ifndef GROWTH_REGIONS_H +#define GROWTH_REGIONS_H +#include +#include +#include +#include +#include "base_data.h" +#include "region_rect2.h" +#include "graph_module.h" +struct region { + flecs::entity_t parent; + flecs::entity_t seed_et; + flecs::entity_t region_et; + RegionRect2i rect; + int remains_area; + bool can_grow_square; + bool can_grow; + bool complete; + bool can_grow_region() const + { + bool ret = can_grow; + if (remains_area <= 0) + ret = false; + return ret; + } + bool update_region_size(RegionRect2i &mrect) + { + bool ret = false; + int old_area = rect.get_area(); + int new_area = mrect.get_area(); + int area_diff = new_area - old_area; + if (area_diff > 0) { + rect = mrect; + remains_area -= area_diff; + ret = true; + } + if (remains_area <= 0) { + can_grow_square = false; + can_grow = false; + } + flecs::log::dbg("update_region_size %d -> %d", area_diff, ret); + return ret; + } +}; +struct growth_regions { + List job_list; + bool complete; + bool check_region(int index, const RegionRect2i &rect) const; +#if 0 + bool check_region(int index, const RegionRect2i &rect) const + { + int i; + bool ret = true; + for (i = 0; i < regions.size(); i++) { + if (i == index) + continue; + if (rect.intersects(regions[i].rect)) { + ret = false; + flecs::log::dbg( + "%d: %s intersects %s", i, + (rect.operator String()).ascii().ptr(), + (regions[i].rect.operator String()) + .ascii() + .ptr()); + break; + } + } + flecs::log::dbg("check_region: %d -> %d", index, ret); + return ret; + } +#endif + bool update_region_size(int index, RegionRect2i &mrect); +#if 0 + bool update_region_size(int index, RegionRect2i &mrect) + { + bool ret = false; + bool ok = check_region(index, mrect); + if (ok) + ret = regions.write[index].update_region_size(mrect); + flecs::log::dbg("update_region_size %d -> %d", index, ret); + return ret; + } +#endif + void create_region(flecs::entity floor_e, flecs::entity seed_e, + flecs::entity parent_e, flecs::entity region_e, + const Vector2i &position, float area, + int parent_index); + flecs::entity create_cell(flecs::entity floor_e, flecs::entity region_e, + int id); + flecs::entity update_cell(flecs::entity floor_e, flecs::entity parent_e, + flecs::entity region_e, int id); + void split_region(flecs::entity grid_floor_e, int region_index, + const List > ®ion_list); + void grow_regions(flecs::entity grid_floor_e); + bool grow_state0(int index, const RegionRect2i &clip); + bool grow_state1(int index, const RegionRect2i &clip); +}; + +#endif \ No newline at end of file diff --git a/src/modules/stream/ui/queries.h b/src/modules/stream/ui/queries.h new file mode 100644 index 0000000..24864ce --- /dev/null +++ b/src/modules/stream/ui/queries.h @@ -0,0 +1,204 @@ +#ifndef QUERIES_H +#define QUERIES_H +#include "base_data.h" +#include "world_editor.h" +#include "growth_regions.h" +#include "graph_module.h" +struct queries { + flecs::query_builder + qp; + flecs::query_builder + qr; + flecs::query_builder< + const WorldEditor::components::buildings_layout_grid_cell> + mark_cells; + 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 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({ List(), false }); + floor_e.add(base_floor_e); + } + flecs::entity get_layout_grid_base() + { + const String &layout_grid_name = "buildings_layout_grid_v2"; + flecs::world ecs = BaseData::get_singleton()->get(); + flecs::entity layout_base_e = + ecs.lookup(layout_grid_name.ascii().ptr()); + if (layout_base_e.is_valid()) { + assert(layout_base_e.has< + WorldEditor::components:: + buildings_layout_grid_base>()); + return layout_base_e; + } else { + layout_base_e = + ecs.entity(layout_grid_name.ascii().ptr()); + assert(layout_base_e.is_valid()); + layout_base_e.add(); + assert(layout_base_e.has< + WorldEditor::components:: + buildings_layout_grid_base>()); + return layout_base_e; + } + } + flecs::entity get_layout_base() + { + const String &layout_base_name = "buildings_layout_graph"; + flecs::world ecs = BaseData::get_singleton()->get(); + flecs::entity layout_base_e = + ecs.lookup(layout_base_name.ascii().ptr()); + if (layout_base_e.is_valid()) { + assert(layout_base_e.has< + WorldEditor::components::buildings_layout_base>()); + return layout_base_e; + } else { + layout_base_e = + ecs.entity(layout_base_name.ascii().ptr()); + assert(layout_base_e.is_valid()); + layout_base_e.add< + WorldEditor::components::buildings_layout_base>(); + return layout_base_e; + } + } +}; +struct subregions { + HashMap > > + sub_subregions; + struct queries queries; + subregions(flecs::world &ecs) + : queries(ecs) + { + } + 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 = + queries.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()) + queries.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(); + } + } + } +}; +#endif \ No newline at end of file diff --git a/src/modules/stream/ui/region_rect2.h b/src/modules/stream/ui/region_rect2.h new file mode 100644 index 0000000..66aa46c --- /dev/null +++ b/src/modules/stream/ui/region_rect2.h @@ -0,0 +1,235 @@ +/* ~/godot-projects/streaming_world/src/modules/stream/ui/region_rect2.h */ +#ifndef REGION_RECT2_H_ +#define REGION_RECT2_H_ +#include +#include +struct RegionRect2i { + Point2i position; + Size2i size; + + const Point2i &get_position() const + { + return position; + } + void set_position(const Point2i &p_position) + { + position = p_position; + } + const Size2i &get_size() const + { + return size; + } + void set_size(const Size2i &p_size) + { + size = p_size; + } + + int get_area() const + { + return size.width * size.height; + } + + _FORCE_INLINE_ Vector2i get_center() const + { + return position + (size / 2); + } + + inline bool intersects(const RegionRect2i &p_rect) const + { + if (position.x > (p_rect.position.x + p_rect.size.width - 1)) { + return false; + } + if ((position.x + size.width - 1) < p_rect.position.x) { + return false; + } + if (position.y > (p_rect.position.y + p_rect.size.height - 1)) { + return false; + } + if ((position.y + size.height - 1) < p_rect.position.y) { + return false; + } + + return true; + } + + inline bool encloses(const RegionRect2i &p_rect) const + { + return (p_rect.position.x >= position.x) && + (p_rect.position.y >= position.y) && + ((p_rect.position.x + p_rect.size.x) <= + (position.x + size.x)) && + ((p_rect.position.y + p_rect.size.y) <= + (position.y + size.y)); + } + + _FORCE_INLINE_ bool has_no_area() const + { + return (size.x <= 0 || size.y <= 0); + } + inline RegionRect2i clip(const RegionRect2i &p_rect) const + { /// return a clipped rect + + RegionRect2i new_rect = p_rect; + + if (!intersects(new_rect)) { + return RegionRect2i(); + } + + new_rect.position.x = MAX(p_rect.position.x, position.x); + new_rect.position.y = MAX(p_rect.position.y, position.y); + + Point2 p_rect_end = p_rect.position + p_rect.size; + Point2 end = position + size; + + new_rect.size.x = + (int)(MIN(p_rect_end.x, end.x) - new_rect.position.x); + new_rect.size.y = + (int)(MIN(p_rect_end.y, end.y) - new_rect.position.y); + + return new_rect; + } + + inline RegionRect2i merge(const RegionRect2i &p_rect) const + { ///< return a merged rect + + RegionRect2i new_rect; + + new_rect.position.x = MIN(p_rect.position.x, position.x); + new_rect.position.y = MIN(p_rect.position.y, position.y); + + new_rect.size.x = MAX(p_rect.position.x + p_rect.size.x, + position.x + size.x); + new_rect.size.y = MAX(p_rect.position.y + p_rect.size.y, + position.y + size.y); + + new_rect.size = + new_rect.size - new_rect.position; //make relative again + + return new_rect; + }; + bool has_point(const Point2 &p_point) const + { + if (p_point.x < position.x) { + return false; + } + if (p_point.y < position.y) { + return false; + } + + if (p_point.x >= (position.x + size.x)) { + return false; + } + if (p_point.y >= (position.y + size.y)) { + return false; + } + + return true; + } + + bool operator==(const RegionRect2i &p_rect) const + { + return position == p_rect.position && size == p_rect.size; + } + bool operator!=(const RegionRect2i &p_rect) const + { + return position != p_rect.position || size != p_rect.size; + } + + RegionRect2i grow(int p_by) const + { + RegionRect2i g = *this; + g.position.x -= p_by; + g.position.y -= p_by; + g.size.width += p_by * 2; + g.size.height += p_by * 2; + return g; + } + + inline RegionRect2i grow_margin(Margin p_margin, int p_amount) const + { + RegionRect2i g = *this; + g = g.grow_individual((MARGIN_LEFT == p_margin) ? p_amount : 0, + (MARGIN_TOP == p_margin) ? p_amount : 0, + (MARGIN_RIGHT == p_margin) ? p_amount : 0, + (MARGIN_BOTTOM == p_margin) ? p_amount : + 0); + return g; + } + + inline RegionRect2i grow_individual(int p_left, int p_top, int p_right, + int p_bottom) const + { + RegionRect2i g = *this; + g.position.x -= p_left; + g.position.y -= p_top; + g.size.width += p_left + p_right; + g.size.height += p_top + p_bottom; + + return g; + } + + _FORCE_INLINE_ RegionRect2i expand(const Vector2i &p_vector) const + { + RegionRect2i r = *this; + r.expand_to(p_vector); + return r; + } + + inline void expand_to(const Point2i &p_vector) + { + Point2i begin = position; + Point2i end = position + size; + + if (p_vector.x < begin.x) { + begin.x = p_vector.x; + } + if (p_vector.y < begin.y) { + begin.y = p_vector.y; + } + + if (p_vector.x > end.x) { + end.x = p_vector.x; + } + if (p_vector.y > end.y) { + end.y = p_vector.y; + } + + position = begin; + size = end - begin; + } + + operator String() const + { + return String(position) + ", " + String(size); + } + + operator Rect2() const + { + return Rect2(position, size); + } + RegionRect2i(const Rect2 &p_r2) + : position(p_r2.position) + , size(p_r2.size) + { + } + RegionRect2i(const Rect2i &p_r2) + : position(p_r2.position) + , size(p_r2.size) + { + } + RegionRect2i() + { + } + RegionRect2i(int p_x, int p_y, int p_width, int p_height) + : position(Point2(p_x, p_y)) + , size(Size2(p_width, p_height)) + { + } + RegionRect2i(const Point2 &p_pos, const Size2 &p_size) + : position(p_pos) + , size(p_size) + { + } +}; + +#endif // REGION_RECT2_H_ \ No newline at end of file diff --git a/src/modules/stream/ui/region_tree.cpp b/src/modules/stream/ui/region_tree.cpp index 674cd40..5d85406 100644 --- a/src/modules/stream/ui/region_tree.cpp +++ b/src/modules/stream/ui/region_tree.cpp @@ -2,17 +2,40 @@ #include #include #include +#include +#include #include "region_tree.h" -void region_tree::split(const List ®ions) +void region_tree::split(flecs::entity grid_floor_e, + const List ®ions) { assert(children.size() == 0); + const region_tree *base_rtree = grid_floor_e.get(); const List::Element *e = regions.front(); + int count = 0; + assert(base_rtree->check(grid_floor_e)); while (e) { + flecs::log::warn( + "%lx: %s -> %s", region.region_et, + (region.rect.operator String()).ascii().ptr(), + (e->get().rect.operator String()).ascii().ptr()); + assert(region.rect.encloses(e->get().rect)); struct region_tree *child = memnew(struct region_tree); child->parent = this; child->region = e->get(); children.push_back(child); + base_rtree->dump(grid_floor_e); + flecs::log::dbg( + "added region: %d: %s", count, + (child->region.rect.operator String()).ascii().ptr()); + if (!base_rtree->check(grid_floor_e)) + flecs::log::err( + "bad region %d: %s: %s", count, + (region.rect.operator String()).ascii().ptr(), + (e->get().rect.operator String()).ascii().ptr()); + base_rtree->dump(grid_floor_e); + assert(base_rtree->check(grid_floor_e)); + count++; e = e->next(); } } @@ -40,6 +63,8 @@ region_tree *region_tree::find(flecs::entity_t which) queue.push_back(this); while (!queue.empty()) { struct region_tree *item = queue.front()->get(); + flecs::log::dbg("check %lx == %lx", item->region.region_et, + which); if (item->region.region_et == which) return item; queue.pop_front(); @@ -62,11 +87,12 @@ void region_tree::dump(flecs::entity grid_floor_e) const int i; for (i = 0; i < tabs; i++) stabs += "\t"; - flecs::log::warn("%sregion: %s", stabs.ascii().ptr(), + flecs::log::warn("%sregion: %s: %lx", stabs.ascii().ptr(), grid_floor_e.world() .entity(item->region.region_et) .path() - .c_str()); + .c_str(), + item->region.region_et); flecs::log::warn( "%srect: %s", stabs.ascii().ptr(), (item->region.rect.operator String()).ascii().ptr()); @@ -76,13 +102,20 @@ void region_tree::dump(flecs::entity grid_floor_e) const } } -void region_tree::grow() +void region_tree::grow(flecs::entity grid_floor_e) { List grow_list; List queue; List::Element *e, *e1; + const struct region_tree *base_rtree = grid_floor_e.get(); + assert(base_rtree); +#ifdef TESTS + flecs::log::warn("grow"); +#endif if (region.complete) queue.push_back(this); + else + flecs::log::warn("incomplete"); while (!queue.empty()) { int i; struct region_tree *item = queue.front()->get(); @@ -95,216 +128,229 @@ void region_tree::grow() queue.push_back(item->children[i]); } } + assert(base_rtree->check(grid_floor_e)); flecs::log::warn("grow list: %d", grow_list.size()); - e = grow_list.front(); - int amount = 0; - while (e) { - struct region_tree *item = e->get(); - flecs::log::warn( - "item: %s", - (item->region.rect.operator String()).ascii().ptr()); - if (!item->region.can_grow) { - e = e->next(); - flecs::log::err("can't grow"); - continue; + int grow_count = 0; + queue.clear(); + struct pointer_hasher { + static _FORCE_INLINE_ uint32_t hash(void *ptr) + { + return hash_one_uint64((uint64_t)ptr); } - RegionRect2i candidate = item->region.rect.grow(1); - e1 = grow_list.front(); - bool ok = true; - while (e1) { - struct region_tree *check_item = e1->get(); - if (item != check_item) { - flecs::log::warn("check item: %s candidate: %s", - (check_item->region.rect - .operator String()) - .ascii() - .ptr(), - (candidate.operator String()) - .ascii() - .ptr()); - if (!check_item->check_candidate(candidate)) { - ok = false; - flecs::log::err("check failed"); - break; - } + }; + HashMap state; + while (1) { + e = grow_list.front(); + while (e) { + struct region_tree *item = e->get(); + flecs::log::warn("item: %s", + (item->region.rect.operator String()) + .ascii() + .ptr()); + if (!item->region.can_grow) { + e = e->next(); + flecs::log::err("can't grow"); + continue; } - e1 = e1->next(); - } - if (ok) { - item->update_candidate(candidate); - amount++; - } else { - flecs::log::err("can't update candidate"); - } - e = e->next(); - } -#if 0 - assert(false); - if (region.complete) - queue.push_back(this); - while (!queue.empty()) { - struct region_tree *item = queue.front()->get(); - queue.pop_front(); - if (item->region.can_grow || item->region.can_grow_square) - continue; - int i, j; - int amount = 0; - amount = 0; - for (i = 0; i < (int)item->children.size(); i++) { - if (item->children[i]->region.can_grow_square) { - RegionRect2i candidate = - item->children[i]->region.rect.grow(1); - if (!item->region.rect.encloses(candidate)) { - item->children.write[i] - ->region.can_grow_square = - false; - continue; - } - bool ok = item->check_candidate(i, candidate); - if (ok) { - item->children.write[i] - ->update_candidate(candidate); - amount++; - } else - item->children.write[i] - ->region.can_grow_square = - false; + if (!state.has(item)) + state[item] = 0; + RegionRect2i candidate = item->region.rect; + switch (state[item]) { + case 0: + candidate = item->region.rect.grow(1); + break; + case 1: + candidate = item->region.rect; + candidate.size.x += 1; + break; + case 2: + candidate = item->region.rect; + candidate.size.y += 1; + break; + case 3: + candidate = item->region.rect; + candidate.position.x -= 1; + candidate.size.x += 1; + break; + case 4: + candidate = item->region.rect; + candidate.position.y -= 1; + candidate.size.y += 1; + break; + default: + state[item]++; } - } - if (amount > 0) /* try again later */ - queue.push_back(item); -#if 0 - for (i = 0; i < (int)item->children.size(); i++) { - if (!can_grow_square) - item->children.write[i] - ->region.can_grow_square = - false; + e1 = grow_list.front(); + bool ok = true; + while (e1) { + struct region_tree *check_item = e1->get(); + if (item != check_item) { + flecs::log::warn( + "check item: %s candidate: %s", + (check_item->region.rect + .operator String()) + .ascii() + .ptr(), + (candidate.operator String()) + .ascii() + .ptr()); + if (!check_item->check_candidate( + candidate)) { + ok = false; + flecs::log::err("check failed"); + break; + } + } + e1 = e1->next(); } - while (can_grow) { - amount = 0; - for (i = 0; i < (int)item->children.size(); - i++) { - if (!item->children[i]->region.can_grow) - continue; - int orig_area = - item->children[i] - ->region.rect.get_area(); - RegionRect2i candidate = - item->children[i]->region.rect; - candidate.size.x += 1; - if (!item->region.rect.encloses( - candidate)) - continue; - bool ok = item->check_candidate( - i, candidate); - if (ok) { - item->children.write[i] - ->update_candidate( - candidate); - amount++; - } - } - for (i = 0; i < (int)item->children.size(); - i++) { - if (!item->children[i]->region.can_grow) - continue; - int orig_area = - item->children[i] - ->region.rect.get_area(); - RegionRect2i candidate = - item->children[i]->region.rect; - candidate.size.x += 1; - candidate.position.x -= 1; - if (!item->region.rect.encloses( - candidate)) - continue; - bool ok = item->check_candidate( - i, candidate); - if (ok) { - item->children.write[i] - ->update_candidate( - candidate); - amount++; - } - } - for (i = 0; i < (int)item->children.size(); - i++) { - if (!item->children[i]->region.can_grow) - continue; - int orig_area = - item->children[i] - ->region.rect.get_area(); - RegionRect2i candidate = - item->children[i]->region.rect; - candidate.size.y += 1; - if (!item->region.rect.encloses( - candidate)) - continue; - bool ok = item->check_candidate( - i, candidate); - if (ok) { - item->children.write[i] - ->update_candidate( - candidate); - amount++; - } - } - for (i = 0; i < (int)item->children.size(); - i++) { - if (!item->children[i]->region.can_grow) - continue; - int orig_area = - item->children[i] - ->region.rect.get_area(); - RegionRect2i candidate = - item->children[i]->region.rect; - candidate.size.y += 1; - candidate.position.y -= 1; - if (!item->region.rect.encloses( - candidate)) - continue; - bool ok = item->check_candidate( - i, candidate); - if (ok) { - item->children.write[i] - ->update_candidate( - candidate); - amount++; - } - } - for (i = 0; i < (int)item->children.size(); - i++) { - if (item->children[i] - ->region.remains_area < - -100) { - item->children[i] - ->region.can_grow = + if (ok) { + struct region backup = item->region; + item->update_candidate(candidate); + if (!base_rtree->check(grid_floor_e)) { + item->region = backup; + flecs::log::err( + "can't update candidate (after checking all rects)"); + if (state[item] == 0) + item->region.can_grow_square = false; - item->children[i] - ->region.complete = - true; - } + state[item]++; } - if (amount == 0) - can_grow = false; + assert(base_rtree->check(grid_floor_e)); + } else { + flecs::log::err("can't update candidate"); + if (state[item] == 0) + item->region.can_grow_square = false; + state[item]++; } -#endif + if (item->region.remains_area < -2) { + item->region.can_grow = false; + item->region.can_grow_square = false; + item->region.complete = true; + } + grow_count++; + if (item->region.can_grow && state[item] < 5) + queue.push_back(item); + else { + item->region.can_grow = false; + item->region.complete = true; + } + e = e->next(); + assert(base_rtree->check(grid_floor_e)); + } + if (queue.empty()) + break; + while (!queue.empty()) { + grow_list.push_back(queue.front()->get()); + queue.pop_front(); + } + queue.clear(); + assert(base_rtree->check(grid_floor_e)); + } +} + +bool region_tree::check(flecs::entity grid_floor_e) const +{ + List queue; + assert(!parent); + Vector check_regions; + Vector root_regions; + int i, j; + if (children.size() == 0) + return true; + int grid_size = grid_floor_e + .get() + ->grid_size; + for (i = 0; i < children.size(); i++) + root_regions.push_back(children[i]->region.rect); + flecs::log::dbg("root regions count: %d", root_regions.size()); + queue.push_back(this); + while (!queue.empty()) { + const struct region_tree *item = queue.front()->get(); + queue.pop_front(); + if (item->is_leaf()) { + const RegionRect2i &rect = item->region.rect; + check_regions.push_back(rect); + } for (i = 0; i < (int)item->children.size(); i++) { queue.push_back(item->children[i]); } - break; } -#endif + flecs::log::dbg("regions to check: %d", check_regions.size()); + for (i = 0; i < (int)root_regions.size(); i++) + flecs::log::dbg( + "root region: %d %s", i, + (root_regions[i].operator String()).ascii().ptr()); + for (i = 0; i < (int)check_regions.size(); i++) + flecs::log::dbg( + "check region: %d %s", i, + (check_regions[i].operator String()).ascii().ptr()); + int ok = true; + for (i = 0; i < (int)check_regions.size(); i++) { + if (!region.rect.encloses(check_regions[i])) { + flecs::log::err("region is not inside parent"); + ok = false; + break; + } + } + if (root_regions.size() > 0) { + for (i = 0; i < (int)check_regions.size(); i++) { + int count = 0; + if (root_regions.find(check_regions[i]) >= 0) + continue; + for (j = 0; j < (int)root_regions.size(); j++) + if (root_regions[j].encloses(check_regions[i])) + count++; + if (count == 0) { + flecs::log::err( + "region is out of root regions"); + ok = false; + break; + } + } + } + if (!ok) + return ok; + for (i = 0; i < (int)check_regions.size(); i++) { + for (j = 0; j < (int)check_regions.size(); j++) { + if (i == j) + continue; + if (check_regions[i].intersects(check_regions[j])) + ok = false; + if (check_regions[i].encloses(check_regions[j])) + ok = false; + if (check_regions[j].encloses(check_regions[i])) + ok = false; + if (!ok) + break; + } + if (!ok) + break; + } + if (!ok) + flecs::log::err( + "some leaf regions intersect other leaf regions"); + return ok; } void region_tree::place(flecs::entity grid_floor_e) const { - int i, j; + int i, j, k; + assert(!parent); List queue; int grid_size = grid_floor_e .get() ->grid_size; + LocalVector delete_cells; + grid_floor_e.children([&delete_cells](flecs::entity e) { + if (e.has()) + delete_cells.push_back(e); + }); + for (i = 0; i < (int)delete_cells.size(); i++) + delete_cells[i].destruct(); + delete_cells.clear(); +#if 0 for (i = region.rect.position.x; i < region.rect.position.x + region.rect.size.x; i++) for (j = region.rect.position.y; @@ -316,6 +362,39 @@ void region_tree::place(flecs::entity grid_floor_e) const if (cell_e.is_valid()) cell_e.destruct(); } +#endif + queue.push_back(this); + bool result = true; + while (!queue.empty()) { + const struct region_tree *item = queue.front()->get(); + queue.pop_front(); + if (item->is_leaf()) { + const RegionRect2i &rect = item->region.rect; + for (i = rect.position.x; + i < rect.position.x + rect.size.x; i++) { + for (j = rect.position.y; + j < rect.position.y + rect.size.y; j++) { + int cell_id = i + grid_size * j; + result = check_cell( + grid_floor_e, + item->region.parent, + item->region.region_et, + cell_id); + if (!result) + break; + } + if (!result) + break; + } + } + if (!result) + break; + for (i = 0; i < (int)item->children.size(); i++) { + queue.push_back(item->children[i]); + } + } + assert(result); + queue.clear(); queue.push_back(this); while (!queue.empty()) { const struct region_tree *item = queue.front()->get(); @@ -324,8 +403,8 @@ void region_tree::place(flecs::entity grid_floor_e) const const RegionRect2i &rect = item->region.rect; for (i = rect.position.x; i < rect.position.x + rect.size.x; i++) - for (j = rect.position.x; - j < rect.position.x + rect.size.x; j++) { + for (j = rect.position.y; + j < rect.position.y + rect.size.y; j++) { int cell_id = i + grid_size * j; update_cell(grid_floor_e, item->region.parent, @@ -337,6 +416,31 @@ void region_tree::place(flecs::entity grid_floor_e) const queue.push_back(item->children[i]); } } + for (i = 0; i < children.size(); i++) { + for (j = children[i]->region.rect.position.x; + j < children[i]->region.rect.position.x + + children[i]->region.rect.size.x; + j++) + for (k = children[i]->region.rect.position.y; + k < children[i]->region.rect.position.y + + children[i]->region.rect.size.y; + k++) { + int id = j + grid_size * k; + String cname("cell_" + itos(id)); + flecs::entity cell_e = grid_floor_e.lookup( + cname.ascii().ptr()); + if (cell_e.is_valid()) + continue; +#if 0 + update_cell(grid_floor_e, + grid_floor_e.parent().id(), + grid_floor_e.id(), id); +#endif + create_corridoor_cell( + grid_floor_e, + grid_floor_e.parent().id(), id); + } + } } void region_tree::get_rects(List *rect_list) const @@ -451,6 +555,63 @@ flecs::entity region_tree::update_cell(flecs::entity grid_floor_e, return cell_e; } +flecs::entity region_tree::create_corridoor_cell(flecs::entity grid_floor_e, + flecs::entity_t parent_et, + int id) const +{ + // flecs::entity region_e = grid_floor_e.world().entity(region_et); + flecs::entity parent_e = grid_floor_e.world().entity(parent_et); + String pname("cell_" + itos(id)); + flecs::entity cell_e = grid_floor_e.lookup(pname.ascii().ptr()); + if (!cell_e.is_valid()) { + flecs::log::warn("creating new cell %s", pname.ascii().ptr()); + cell_e = grid_floor_e.world() + .entity(pname.ascii().ptr()) + .child_of(grid_floor_e); + assert(cell_e.is_valid()); + } + // assert(cell_e.has(parent_e)); + /* already there */ + grid_floor_e + .get_mut() + ->cells.insert(id); + grid_floor_e.modified< + WorldEditor::components::buildings_layout_grid_floor>(); + cell_e.set( + { "corridoor", id }); + cell_e.add(); + return cell_e; +} + +bool region_tree::check_cell(flecs::entity grid_floor_e, + flecs::entity_t parent_et, + flecs::entity_t region_et, int id) const +{ + flecs::entity region_e = grid_floor_e.world().entity(region_et); + flecs::entity parent_e = grid_floor_e.world().entity(parent_et); + flecs::log::dbg("check_cell: %s %d", region_e.path().c_str(), id); + String pname("cell_" + itos(id)); + flecs::entity cell_e = grid_floor_e.lookup(pname.ascii().ptr()); + if (!cell_e.is_valid()) + return true; + int mcount = 0; + if (region_e.has()) { + cell_e.each( + [&mcount, region_e, cell_e](flecs::entity e) { + flecs::log::err( + "while adding region %s to cell %s", + region_e.path().c_str(), + cell_e.path().c_str()); + flecs::log::err("already belongs to %s", + e.path().c_str()); + mcount++; + }); + } + if (mcount == 0) + return true; + return false; +} + void region_tree::update_candidate(const RegionRect2i &candidate) { int orig_area = region.rect.get_area(); diff --git a/src/modules/stream/ui/region_tree.h b/src/modules/stream/ui/region_tree.h index 8a692bc..69e6398 100644 --- a/src/modules/stream/ui/region_tree.h +++ b/src/modules/stream/ui/region_tree.h @@ -6,7 +6,8 @@ struct region_tree { struct region region; Vector children; struct region_tree *parent; - void split(const List ®ions); + void split(flecs::entity grid_floor_e, + const List ®ions); const struct region_tree *find(flecs::entity_t which) const; struct region_tree *find(flecs::entity_t which); bool is_leaf() const @@ -14,7 +15,8 @@ struct region_tree { return children.size() == 0; } void dump(flecs::entity grid_floor_e) const; - void grow(); + void grow(flecs::entity grid_floor_e); + bool check(flecs::entity grid_floor_e) const; void place(flecs::entity grid_floor_e) const; void get_rects(List *rect_list) const; @@ -24,6 +26,11 @@ private: flecs::entity update_cell(flecs::entity grid_floor_e, flecs::entity_t parent_et, flecs::entity_t region_et, int id) const; + flecs::entity create_corridoor_cell(flecs::entity grid_floor_e, + flecs::entity_t parent_et, + int id) const; + bool check_cell(flecs::entity grid_floor_e, flecs::entity_t parent_et, + flecs::entity_t region_et, int id) const; void update_candidate(const RegionRect2i &candidate); }; #endif // REGION_TREE_H_ \ No newline at end of file diff --git a/src/modules/stream/world_editor.h b/src/modules/stream/world_editor.h index a222338..6b9a918 100644 --- a/src/modules/stream/world_editor.h +++ b/src/modules/stream/world_editor.h @@ -123,6 +123,7 @@ public: struct border {}; struct belongs_room {}; struct outside_wall {}; + struct corridoor {}; struct buildings_layout_grid_floor { Set cells; int grid_size; diff --git a/tests/Makefile b/tests/Makefile index d45a9e7..3d1deb7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,9 +1,12 @@ all: graph_test entity_test rect2i regions LIBS= +SDL_LIBS=$(shell pkg-config sdl2 --libs) +SDL_CFLAGS=$(shell pkg-config sdl2 --cflags) +IMGUI_OBJS= ./imgui/imgui.o ./imgui/imgui_draw.o ./imgui/imgui_tables.o ./imgui/imgui_widgets.o ./imgui/imgui_impl_sdlrenderer2.o ./imgui/imgui_impl_sdl2.o # LIBS= ./godot_mockery/libgodot-mockery.a -CFLAGS = -I../src/flecs/distr -g -CXXFLAGS = -I../src/flecs/distr -I../src/modules/stream/ui -I./godot_mockery -I../src/godot -I../src/godot/platform/x11 -I. -I../src/modules/stream -g +CFLAGS = -I../src/flecs/distr $(SDL_CFLAGS) -I./cglm/include -I./flecs-game/include -g +CXXFLAGS = -I../src/flecs/distr -I../src/modules/stream/ui -I./godot_mockery -I../src/godot -I../src/godot/platform/x11 -I. -I../src/modules/stream -I./imgui $(SDL_CFLAGS) -g #CXXFLAGS = -I../src/flecs/distr -I../src/modules/stream/ui -I../src/godot -I../src/godot/platform/x11 -I. -I../src/modules/stream -g graph_test: graph_module.o flecs.o $(LIBS) @@ -20,8 +23,14 @@ rect2i: rect2i.o $(LIBS) region_tree.o: ../src/modules/stream/ui/region_tree.cpp $(CC) $(CFLAGS) $(CXXFLAGS) -DTESTS -o $@ -c $< -regions: regions.o flecs.o region_tree.o godot_mockery/core/os/memory.o godot_mockery/core/ustring.o $(LIBS) - $(CXX) -o $@ regions.o flecs.o region_tree.o godot_mockery/core/os/memory.o godot_mockery/core/ustring.o $(LIBS) +#graph_module_growth.o: ../src/modules/stream/ui/graph_module_growth.cpp +# $(CC) $(CFLAGS) $(CXXFLAGS) -DTESTS -o $@ -c $< +# +#graph_module_core.o: ../src/modules/stream/ui/graph_module.cpp +# $(CC) $(CFLAGS) $(CXXFLAGS) -DTESTS -o $@ -c $< + +regions: regions.o flecs.o region_tree.o godot_mockery/core/os/memory.o godot_mockery/core/ustring.o $(SDL_LIBS) $(IMGUI_OBJS) $(LIBS) + $(CXX) -o $@ regions.o flecs.o region_tree.o godot_mockery/core/os/memory.o godot_mockery/core/ustring.o $(IMGUI_OBJS) $(LIBS) $(SDL_LIBS) MOCK_OBJS=godot_mockery/core/os/memory.o godot_mockery/core/error_macros.o \ godot_mockery/core/ustring.o godot_mockery/core/array.o \ @@ -58,7 +67,7 @@ godot_mockery/core/math/%.o: ../src/godot/core/math/%.cpp $(CC) $(CFLAGS) $(CXXFLAGS) -DTESTS -o $@ -c $< clean: - rm -f godot_mockery/core/*.o godot_mockery/core/os/*.o *.o graph_test entity_test rect2i regions + rm -f godot_mockery/core/*.o godot_mockery/core/os/*.o *.o graph_test entity_test rect2i regions $(FLECS_OBJS) .PHONY: all clean diff --git a/tests/flecs-systems-sokol b/tests/flecs-systems-sokol deleted file mode 160000 index 29f521a..0000000 --- a/tests/flecs-systems-sokol +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 29f521a7d42fbfc3cb3c527d59c526c70cb9d6a1 diff --git a/tests/godot_mockery/core/ustring.cpp b/tests/godot_mockery/core/ustring.cpp index c66771a..b4c2608 100644 --- a/tests/godot_mockery/core/ustring.cpp +++ b/tests/godot_mockery/core/ustring.cpp @@ -460,4 +460,72 @@ String String::num_int64(int64_t p_num, int base, bool capitalize_hex) { return s; } +uint32_t String::hash(const char *p_cstr) { + uint32_t hashv = 5381; + uint32_t c; + + while ((c = *p_cstr++)) { + hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } + + return hashv; +} + +uint32_t String::hash(const char *p_cstr, int p_len) { + uint32_t hashv = 5381; + for (int i = 0; i < p_len; i++) { + hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */ + } + + return hashv; +} + +uint32_t String::hash(const CharType *p_cstr, int p_len) { + uint32_t hashv = 5381; + for (int i = 0; i < p_len; i++) { + hashv = ((hashv << 5) + hashv) + p_cstr[i]; /* hash * 33 + c */ + } + + return hashv; +} + +uint32_t String::hash(const CharType *p_cstr) { + uint32_t hashv = 5381; + uint32_t c; + + while ((c = *p_cstr++)) { + hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } + + return hashv; +} + +uint32_t String::hash() const { + /* simple djb2 hashing */ + + const CharType *chr = c_str(); + uint32_t hashv = 5381; + uint32_t c; + + while ((c = *chr++)) { + hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } + + return hashv; +} + +uint64_t String::hash64() const { + /* simple djb2 hashing */ + + const CharType *chr = c_str(); + uint64_t hashv = 5381; + uint64_t c; + + while ((c = *chr++)) { + hashv = ((hashv << 5) + hashv) + c; /* hash * 33 + c */ + } + + return hashv; +} + diff --git a/tests/regions.cpp b/tests/regions.cpp index 1689a64..decf816 100644 --- a/tests/regions.cpp +++ b/tests/regions.cpp @@ -1,18 +1,45 @@ #include "../src/modules/stream/ui/region_tree.h" +#include "../src/modules/stream/ui/grid_misc.h" +#include "../src/modules/stream/world_editor.h" +#include "../src/modules/stream/ui/queries.h" +#include "../src/modules/stream/ui/building_layout_graph.h" +#include "imgui.h" +#include "imgui_impl_sdl2.h" +#include "imgui_impl_sdlrenderer2.h" +#include +#include + +using graph_module = BuildingLayoutGraph::graph_module; int main() { int i; + SDL_Window *window = NULL; + SDL_Surface *screenSurface = NULL; + SDL_Renderer *renderer; + SDL_WindowFlags window_flags; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + HashMap colors; + make_random r(172); + flecs::world ecs; + ecs.component(); + ecs.component(); + flecs::log::set_level(1); flecs::entity graph_base_e = ecs.entity("graph"); flecs::entity graph_e = ecs.entity("v1").child_of(graph_base_e); flecs::entity grid_base_e = ecs.entity("grid"); flecs::entity grid_e = ecs.entity("v1").child_of(grid_base_e); flecs::entity grid_floor_e = ecs.entity("floor_0").child_of(grid_e); + int grid_size = 27; + grid_floor_e.set({.grid_size = grid_size, .size_left = grid_size * grid_size}); List region_list; struct region region; region.region_et = graph_e.id(); - region.rect = RegionRect2i(0, 0, 25, 25); + region.rect = RegionRect2i(1, 1, grid_size - 2, grid_size - 2); + region.complete = true; + region.can_grow = false; + region.can_grow_square = false; struct region_tree regions; regions.region = region; regions.dump(grid_floor_e); @@ -20,9 +47,32 @@ int main() zone2_e = ecs.entity("zone2").child_of(graph_e), zone3_e = ecs.entity("zone3").child_of(graph_e); struct region region_data[] = { - {.region_et = zone1_e.id(), .rect = {0, 0, 1, 1}}, - {.region_et = zone2_e.id(), .rect = {2, 2, 1, 1}}, - {.region_et = zone3_e.id(), .rect = {4, 4, 1 ,1}} + { + .parent = graph_e.id(), + .region_et = zone1_e.id(), + .rect = {4, 4, 1, 1}, + .remains_area = 140, + .can_grow_square = true, + .can_grow = true, + .complete = false + }, + { + .parent = graph_e.id(), + .region_et = zone2_e.id(), + .rect = {4, 9, 1, 1}, + .remains_area = 80, + .can_grow_square = true, + .can_grow = true, + .complete = false}, + { + .parent = graph_e.id(), + .region_et = zone3_e.id(), + .rect = {20, 15, 1 ,1}, + .remains_area = 50, + .can_grow_square = true, + .can_grow = true, + .complete = false + } }; for (i = 0; i < sizeof(region_data) / sizeof(region_data[0]); i++) region_list.push_back(region_data[i]); @@ -30,6 +80,109 @@ int main() regions.dump(grid_floor_e); regions.grow(); regions.dump(grid_floor_e); + regions.place(grid_floor_e); + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) < 0) + goto out; + +#ifdef SDL_HINT_IME_SHOW_UI + SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); +#endif + window_flags = (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); + + window = SDL_CreateWindow("RegionTest", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 1024, window_flags); + if (window == NULL) + goto out; + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + if (!renderer) + goto out; + // screenSurface = SDL_GetWindowSurface(window); + // if (!screenSurface) + // goto out; + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + { + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + } + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup Platform/Renderer backends + ImGui_ImplSDL2_InitForSDLRenderer(window, renderer); + ImGui_ImplSDLRenderer2_Init(renderer); + // SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xFF, 0xFF, 0xFF)); + // SDL_UpdateWindowSurface(window); + SDL_Event event; + while(1) { + SDL_PollEvent(&event); + ImGui_ImplSDL2_ProcessEvent(&event); + switch(event.type) { + case SDL_QUIT: + goto shutdown; + break; + case SDL_WINDOWEVENT: + if (event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window)) + goto shutdown; + break; + default: + break; + + } + ecs.progress(); + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) { + SDL_Delay(10); + continue; + } + ImGui_ImplSDLRenderer2_NewFrame(); + ImGui_ImplSDL2_NewFrame(); + ImGui::NewFrame(); + { + ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it. + ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too) + ImGui::End(); + } + ImGui::Render(); + { + ImGuiIO& io = ImGui::GetIO(); (void)io; + SDL_RenderSetScale(renderer, io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); + } + SDL_SetRenderDrawColor(renderer, (Uint8)(clear_color.x * 255), (Uint8)(clear_color.y * 255), (Uint8)(clear_color.z * 255), (Uint8)(clear_color.w * 255)); + SDL_RenderClear(renderer); + ecs.query_builder() + .build().each([grid_size, renderer, &colors, &r](flecs::entity e, const WorldEditor::components::buildings_layout_grid_cell &cell) + { +// flecs::log::warn("cell: %s: %s: %d", e.path().c_str(), cell.type.ascii().ptr(), cell.index); + int x = cell.index % grid_size; + int y = cell.index / grid_size; + int px = 1280 * x / grid_size; + int py = 1024 * y / grid_size; + int w = 1280 / grid_size; + int h = 1024 / grid_size; +// flecs::log::warn("position: %d %d", x, y); + if (!colors.has(cell.type)) + colors[cell.type] = Color((float)(r.get() % 256) / 256.0f, (float)(r.get() % 256) / 256.0f, (float)(r.get() % 256) / 256.0f, 1.0f); + const Color &c = colors[cell.type]; + SDL_SetRenderDrawColor(renderer, (uint8_t)(c.r * 255), (uint8_t)(c.g * 255), (uint8_t)(c.b * 255), 255); + SDL_Rect rect = {px, py, w, h}; + SDL_RenderFillRect(renderer, &rect); + SDL_SetRenderDrawColor(renderer, 255, 15, 15, 255); + SDL_RenderDrawRect(renderer, &rect); + }); + ImGui_ImplSDLRenderer2_RenderDrawData(ImGui::GetDrawData(), renderer); + SDL_RenderPresent(renderer); + } +shutdown: + ImGui_ImplSDLRenderer2_Shutdown(); + ImGui_ImplSDL2_Shutdown(); + ImGui::DestroyContext(); + + SDL_DestroyRenderer(renderer); + SDL_DestroyWindow(window); + SDL_Quit(); +out: return 0; }