Allocate rooms in zones started
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
[layouts]
|
||||
|
||||
entries=[ {
|
||||
"children": [ 3, 4 ],
|
||||
"children": [ 4, 5 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"floor_index": 0,
|
||||
"index": 0,
|
||||
@@ -9,7 +9,7 @@ entries=[ {
|
||||
"order": 0,
|
||||
"type": "layout"
|
||||
}, {
|
||||
"children": [ 5, 6, 7 ],
|
||||
"children": [ 6, 7, 8 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"floor_index": 0,
|
||||
"index": 1,
|
||||
@@ -17,7 +17,7 @@ entries=[ {
|
||||
"order": 0,
|
||||
"type": "layout"
|
||||
}, {
|
||||
"children": [ 8, 9, 10, 11, 12 ],
|
||||
"children": [ 9, 10, 11, 12, 13 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"floor_index": 0,
|
||||
"index": 2,
|
||||
@@ -25,136 +25,126 @@ entries=[ {
|
||||
"order": 0,
|
||||
"type": "layout"
|
||||
}, {
|
||||
"children": [ 13, 14 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"children": [ 14, 15, 16, 17 ],
|
||||
"commands": [ ],
|
||||
"floor_index": 0,
|
||||
"index": 3,
|
||||
"name": "v4",
|
||||
"order": 4,
|
||||
"type": "layout"
|
||||
}, {
|
||||
"children": [ 18, 19 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 4,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 15, 16, 17 ],
|
||||
"children": [ 20, 21, 22 ],
|
||||
"commands": [ [ 4, [ ] ] ],
|
||||
"index": 4,
|
||||
"name": "zone_1",
|
||||
"order": 1,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 18, 19, 20, 21 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 5,
|
||||
"name": "zone_1",
|
||||
"order": 1,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 23, 24, 25, 26 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 6,
|
||||
"name": "zone_1",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 22, 23, 24 ],
|
||||
"children": [ 27, 28, 29 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 6,
|
||||
"index": 7,
|
||||
"name": "zone_0",
|
||||
"order": 1,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 25, 26 ],
|
||||
"children": [ 30, 31 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 7,
|
||||
"index": 8,
|
||||
"name": "unit_0",
|
||||
"order": 3,
|
||||
"type": "unit"
|
||||
}, {
|
||||
"children": [ 27, 28 ],
|
||||
"children": [ 32, 33 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 8,
|
||||
"index": 9,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 29, 30 ],
|
||||
"children": [ 34, 35 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 9,
|
||||
"index": 10,
|
||||
"name": "unit_0",
|
||||
"order": 0,
|
||||
"type": "unit"
|
||||
}, {
|
||||
"children": [ 31, 32 ],
|
||||
"children": [ 36, 37 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 10,
|
||||
"index": 11,
|
||||
"name": "unit_1",
|
||||
"order": 0,
|
||||
"type": "unit"
|
||||
}, {
|
||||
"children": [ 33, 34 ],
|
||||
"children": [ 38, 39 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 11,
|
||||
"index": 12,
|
||||
"name": "unit_2",
|
||||
"order": 0,
|
||||
"type": "unit"
|
||||
}, {
|
||||
"children": [ 35, 36 ],
|
||||
"children": [ 40, 41 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 12,
|
||||
"index": 13,
|
||||
"name": "unit_3",
|
||||
"order": 0,
|
||||
"type": "unit"
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 13,
|
||||
"name": "living_room_0",
|
||||
"order": 1,
|
||||
"room_area": 144.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"children": [ 42, 43 ],
|
||||
"commands": [ ],
|
||||
"index": 14,
|
||||
"name": "kitchen_0",
|
||||
"order": 2,
|
||||
"room_area": 16.0,
|
||||
"room_type": 302,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 15,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ], [ 3, [ ] ] ],
|
||||
"index": 16,
|
||||
"name": "bathroom_0",
|
||||
"name": "zone_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 17,
|
||||
"name": "bedroom_0",
|
||||
"children": [ 44, 45 ],
|
||||
"commands": [ ],
|
||||
"index": 15,
|
||||
"name": "zone_1",
|
||||
"order": 2,
|
||||
"room_area": 64.0,
|
||||
"room_type": 202,
|
||||
"type": "room",
|
||||
"window": true
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 46, 47, 48 ],
|
||||
"commands": [ ],
|
||||
"index": 16,
|
||||
"name": "zone_2",
|
||||
"order": 3,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 49, 50, 51, 52 ],
|
||||
"commands": [ ],
|
||||
"index": 17,
|
||||
"name": "zone_3",
|
||||
"order": 4,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 18,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"order": 1,
|
||||
"room_area": 144.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
@@ -164,6 +154,56 @@ entries=[ {
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 19,
|
||||
"name": "kitchen_0",
|
||||
"order": 2,
|
||||
"room_area": 16.0,
|
||||
"room_type": 302,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 20,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ], [ 3, [ ] ] ],
|
||||
"index": 21,
|
||||
"name": "bathroom_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 22,
|
||||
"name": "bedroom_0",
|
||||
"order": 2,
|
||||
"room_area": 64.0,
|
||||
"room_type": 202,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 23,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"room_area": 144.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 24,
|
||||
"name": "kitchen_0",
|
||||
"order": 1,
|
||||
"room_area": 64.0,
|
||||
"room_type": 302,
|
||||
@@ -172,7 +212,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 20,
|
||||
"index": 25,
|
||||
"name": "storage_room_0",
|
||||
"order": 2,
|
||||
"room_area": 16.0,
|
||||
@@ -182,7 +222,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 21,
|
||||
"index": 26,
|
||||
"name": "enterance_0",
|
||||
"order": 3,
|
||||
"room_area": 16.0,
|
||||
@@ -192,7 +232,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 22,
|
||||
"index": 27,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
@@ -202,7 +242,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 23,
|
||||
"index": 28,
|
||||
"name": "bathroom_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
@@ -212,7 +252,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 24,
|
||||
"index": 29,
|
||||
"name": "bedroom_0",
|
||||
"order": 2,
|
||||
"room_area": 64.0,
|
||||
@@ -220,17 +260,17 @@ entries=[ {
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 37, 38, 39 ],
|
||||
"children": [ 53, 54, 55 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 25,
|
||||
"index": 30,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 40, 41 ],
|
||||
"children": [ 56, 57 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 26,
|
||||
"index": 31,
|
||||
"name": "zone_1",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
@@ -238,7 +278,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 27,
|
||||
"index": 32,
|
||||
"name": "enterance_0",
|
||||
"order": 0,
|
||||
"room_area": 64.0,
|
||||
@@ -246,9 +286,9 @@ entries=[ {
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 42 ],
|
||||
"children": [ 58 ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 28,
|
||||
"index": 33,
|
||||
"name": "stair_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
@@ -256,83 +296,73 @@ entries=[ {
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 43, 44, 45 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 29,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 46, 47 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 30,
|
||||
"name": "zone_1",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 48 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 31,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 49, 50 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 32,
|
||||
"name": "zone_1",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 51 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 33,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 52 ],
|
||||
"children": [ 59, 60, 61 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 34,
|
||||
"name": "zone_1",
|
||||
"order": 1,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 53 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 35,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 54 ],
|
||||
"children": [ 62, 63 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 35,
|
||||
"name": "zone_1",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 64 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 36,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 65, 66 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 37,
|
||||
"name": "zone_1",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 67 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 38,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 68 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 39,
|
||||
"name": "zone_1",
|
||||
"order": 1,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 69 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 40,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 70 ],
|
||||
"commands": [ [ 3, [ ] ], [ 4, [ ] ] ],
|
||||
"index": 41,
|
||||
"name": "zone_1",
|
||||
"order": 1,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 37,
|
||||
"name": "bathroom_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 38,
|
||||
"commands": [ ],
|
||||
"index": 42,
|
||||
"name": "wc_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
@@ -341,65 +371,27 @@ entries=[ {
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 39,
|
||||
"commands": [ ],
|
||||
"index": 43,
|
||||
"name": "bedroom_0",
|
||||
"order": 2,
|
||||
"room_area": 36.0,
|
||||
"room_area": 64.0,
|
||||
"room_type": 202,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 40,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"room_area": 36.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 41,
|
||||
"name": "kitchen_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 302,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 55, 56 ],
|
||||
"commands": [ ],
|
||||
"floor_index": 1,
|
||||
"index": 42,
|
||||
"name": "floor_0",
|
||||
"order": 0,
|
||||
"type": "floor"
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 43,
|
||||
"index": 44,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 44,
|
||||
"name": "bathroom_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"commands": [ ],
|
||||
"index": 45,
|
||||
"name": "bedroom_0",
|
||||
"order": 2,
|
||||
@@ -409,18 +401,38 @@ entries=[ {
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"commands": [ ],
|
||||
"index": 46,
|
||||
"name": "kitchen_0",
|
||||
"order": 0,
|
||||
"name": "wc_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 302,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": true
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"commands": [ ],
|
||||
"index": 47,
|
||||
"name": "bathroom_0",
|
||||
"order": 2,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ ],
|
||||
"index": 48,
|
||||
"name": "bathroom_1",
|
||||
"order": 3,
|
||||
"room_area": 144.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ ],
|
||||
"index": 49,
|
||||
"name": "living_room_0",
|
||||
"order": 1,
|
||||
"room_area": 144.0,
|
||||
@@ -429,52 +441,32 @@ entries=[ {
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 48,
|
||||
"name": "bathroom_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 49,
|
||||
"commands": [ ],
|
||||
"index": 50,
|
||||
"name": "kitchen_0",
|
||||
"order": 0,
|
||||
"order": 2,
|
||||
"room_area": 64.0,
|
||||
"room_type": 302,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 50,
|
||||
"name": "living_room_0",
|
||||
"order": 1,
|
||||
"room_area": 64.0,
|
||||
"room_type": 300,
|
||||
"commands": [ ],
|
||||
"index": 51,
|
||||
"name": "dining_room_0",
|
||||
"order": 3,
|
||||
"room_area": 144.0,
|
||||
"room_type": 303,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 51,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"commands": [ ],
|
||||
"index": 52,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"room_area": 64.0,
|
||||
"room_type": 300,
|
||||
"name": "enterance_0",
|
||||
"order": 4,
|
||||
"room_area": 16.0,
|
||||
"room_type": 304,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
@@ -491,6 +483,144 @@ entries=[ {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 54,
|
||||
"name": "wc_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 55,
|
||||
"name": "bedroom_0",
|
||||
"order": 2,
|
||||
"room_area": 36.0,
|
||||
"room_type": 202,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 56,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"room_area": 36.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 57,
|
||||
"name": "kitchen_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 302,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 71, 72 ],
|
||||
"commands": [ ],
|
||||
"floor_index": 1,
|
||||
"index": 58,
|
||||
"name": "floor_0",
|
||||
"order": 0,
|
||||
"type": "floor"
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 59,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 60,
|
||||
"name": "bathroom_0",
|
||||
"order": 1,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 61,
|
||||
"name": "bedroom_0",
|
||||
"order": 2,
|
||||
"room_area": 64.0,
|
||||
"room_type": 202,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 62,
|
||||
"name": "kitchen_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 302,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 63,
|
||||
"name": "living_room_0",
|
||||
"order": 1,
|
||||
"room_area": 144.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 64,
|
||||
"name": "bathroom_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 65,
|
||||
"name": "kitchen_0",
|
||||
"order": 0,
|
||||
"room_area": 64.0,
|
||||
"room_type": 302,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 66,
|
||||
"name": "living_room_0",
|
||||
"order": 1,
|
||||
"room_area": 64.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 67,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 200,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 68,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"room_area": 64.0,
|
||||
@@ -498,24 +628,44 @@ entries=[ {
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 57 ],
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 69,
|
||||
"name": "bathroom_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
"room_type": 201,
|
||||
"type": "room",
|
||||
"window": false
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ [ 5, [ ] ] ],
|
||||
"index": 70,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"room_area": 64.0,
|
||||
"room_type": 300,
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 73 ],
|
||||
"commands": [ ],
|
||||
"index": 55,
|
||||
"index": 71,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 1
|
||||
}, {
|
||||
"children": [ 58, 59 ],
|
||||
"children": [ 74, 75 ],
|
||||
"commands": [ ],
|
||||
"index": 56,
|
||||
"index": 72,
|
||||
"name": "unit_0",
|
||||
"order": 0,
|
||||
"type": "unit"
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ ],
|
||||
"index": 57,
|
||||
"index": 73,
|
||||
"name": "storage_room_0",
|
||||
"order": 0,
|
||||
"room_area": 64.0,
|
||||
@@ -523,17 +673,17 @@ entries=[ {
|
||||
"type": "room",
|
||||
"window": true
|
||||
}, {
|
||||
"children": [ 60 ],
|
||||
"children": [ 76 ],
|
||||
"commands": [ ],
|
||||
"index": 58,
|
||||
"index": 74,
|
||||
"name": "zone_0",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
"zone_type": 0
|
||||
}, {
|
||||
"children": [ 61 ],
|
||||
"children": [ 77 ],
|
||||
"commands": [ ],
|
||||
"index": 59,
|
||||
"index": 75,
|
||||
"name": "zone_1",
|
||||
"order": 0,
|
||||
"type": "zone",
|
||||
@@ -541,7 +691,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ ],
|
||||
"index": 60,
|
||||
"index": 76,
|
||||
"name": "wc_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
@@ -551,7 +701,7 @@ entries=[ {
|
||||
}, {
|
||||
"children": [ ],
|
||||
"commands": [ ],
|
||||
"index": 61,
|
||||
"index": 77,
|
||||
"name": "living_room_0",
|
||||
"order": 0,
|
||||
"room_area": 16.0,
|
||||
|
||||
@@ -57,10 +57,17 @@ public:
|
||||
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 create_floor_components(
|
||||
flecs::entity floor_e, flecs::entity base_floor_e,
|
||||
const WorldEditor::components::buildings_layout_grid_size
|
||||
&size);
|
||||
void create_region(flecs::entity floor_e, flecs::entity seed_e,
|
||||
flecs::entity region_e,
|
||||
const Vector2i &position, float area);
|
||||
bool check_region(flecs::entity floor_e, int index,
|
||||
const Rect2i &rect);
|
||||
graph_module(flecs::world &ecs);
|
||||
};
|
||||
};
|
||||
@@ -868,7 +868,48 @@ void BuildingLayoutGraphUI::draw_2d_grid_view(Control *draw)
|
||||
Math::randf(),
|
||||
1);
|
||||
draw->draw_rect(Rect2(dx, dy, dsize, dsize),
|
||||
colors[cell.type]);
|
||||
colors[cell.type], true);
|
||||
draw->draw_rect(Rect2(dx, dy, dsize, dsize),
|
||||
Color(0.1f, 0.1f, 0.1f, 1.0f),
|
||||
false);
|
||||
if (fc.has<WorldEditor::components::
|
||||
outside_wall>())
|
||||
draw->draw_circle(
|
||||
Vector2(dx + 0.5f * dsize,
|
||||
dy + 0.5f * dsize),
|
||||
dsize * 0.4f,
|
||||
Color(0, 0, 1, 1));
|
||||
if (fc.has<WorldEditor::components::border>())
|
||||
draw->draw_circle(
|
||||
Vector2(dx + 0.5f * dsize,
|
||||
dy + 0.5f * dsize),
|
||||
dsize * 0.2f,
|
||||
Color(1, 0.3, 1, 1));
|
||||
int mcount = 0;
|
||||
fc.each<WorldEditor::components::
|
||||
belongs_room>([dx, dy, dsize,
|
||||
&mcount, &draw,
|
||||
&colors](
|
||||
flecs::entity
|
||||
re) {
|
||||
assert(mcount == 0);
|
||||
if (!colors.has(String(re.path()))) {
|
||||
colors[String(re.path())] =
|
||||
Color(Math::randf(),
|
||||
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);
|
||||
}
|
||||
mcount++;
|
||||
});
|
||||
print_line(
|
||||
"draw cell: (" + itos(x) + ", " +
|
||||
itos(y) + ") (" + String::num(dx) +
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "world_editor.h"
|
||||
#include "editor_event.h"
|
||||
#include "building_layout_graph.h"
|
||||
#include "graph_module.h"
|
||||
|
||||
#define MIN_ROOM_SIZE 16 /* 4 * 4 tiles */
|
||||
|
||||
@@ -265,584 +266,73 @@ void BuildingLayoutGraph::graph_module::queue_grow_cell(flecs::entity seed_e,
|
||||
WorldEditor::components::buildings_layout_grid_queue>();
|
||||
}
|
||||
}
|
||||
|
||||
void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
|
||||
const String &module_name)
|
||||
{
|
||||
struct growth_regions {
|
||||
struct region {
|
||||
Rect2i rect;
|
||||
bool can_grow_square;
|
||||
};
|
||||
HashMap<flecs::entity_t, struct region> regions;
|
||||
};
|
||||
ecs.component<growth_regions>();
|
||||
flecs::entity GraphFilter = ecs.entity("GraphFilter")
|
||||
.add(flecs::Phase)
|
||||
.depends_on(flecs::OnUpdate);
|
||||
GraphFilter.disable();
|
||||
|
||||
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_calc {
|
||||
int grid_size;
|
||||
int index2x(int index)
|
||||
{
|
||||
return index % grid_size;
|
||||
}
|
||||
int index2y(int index)
|
||||
{
|
||||
return index / grid_size;
|
||||
}
|
||||
void get_cadidates(int index, int *candidates)
|
||||
{
|
||||
int i, j, idx = 0;
|
||||
int x = index2x(index);
|
||||
int y = index2y(index);
|
||||
|
||||
for (i = -1; i < 2; i++) {
|
||||
for (j = -1; j < 2; j++)
|
||||
if (i != 0 || j != 0) {
|
||||
int cx = x + i, cy = y + j;
|
||||
if (cx >= 0 && cx < grid_size &&
|
||||
cy >= 0 && cy < grid_size) {
|
||||
int id = cx +
|
||||
grid_size * cy;
|
||||
candidates[idx++] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
grid_calc(flecs::entity layout_e)
|
||||
: grid_size(
|
||||
layout_e.get<WorldEditor::components::
|
||||
buildings_layout_grid_size>()
|
||||
->grid_size)
|
||||
{
|
||||
assert(layout_e.is_valid());
|
||||
}
|
||||
grid_calc(int grid_size)
|
||||
: grid_size(grid_size)
|
||||
{
|
||||
assert(grid_size > 0);
|
||||
}
|
||||
};
|
||||
struct grid_misc {
|
||||
LocalVector<Pair<flecs::entity_t, Vector2i> > positions;
|
||||
LocalVector<Vector2i> accepted;
|
||||
struct make_random r;
|
||||
grid_misc()
|
||||
: r(100)
|
||||
{
|
||||
}
|
||||
void get_dim_candidates(const Vector2i &base, int dim,
|
||||
Vector2i *candidates)
|
||||
{
|
||||
int i;
|
||||
std::vector<Vector2i> candidates_data = {
|
||||
/* clang-format off */
|
||||
{ base.x + dim, base.y },
|
||||
{ base.x + dim, base.y + dim },
|
||||
{ base.x, base.y + dim },
|
||||
{ base.x - dim, base.y + dim },
|
||||
{ base.x - dim, base.y },
|
||||
{ base.x - dim, base.y - dim },
|
||||
{ base.x, base.y - dim },
|
||||
{ base.x + dim, base.y - dim },
|
||||
/* clang-format on */
|
||||
};
|
||||
for (i = 0; i < (int)candidates_data.size(); i++)
|
||||
candidates[i] = candidates_data[i];
|
||||
}
|
||||
void setup_floor(
|
||||
flecs::entity grid_e, flecs::entity_t base_et,
|
||||
const WorldEditor::components::buildings_layout_grid_size
|
||||
&size,
|
||||
BuildingLayoutGraph::graph_module *obj)
|
||||
{
|
||||
int i, j;
|
||||
flecs::entity base_floor_e =
|
||||
grid_e.world().entity(base_et);
|
||||
flecs::log::warn("base_floor: %s",
|
||||
base_floor_e.path().c_str());
|
||||
int floor_index =
|
||||
base_floor_e
|
||||
.get<WorldEditor::components::
|
||||
buildings_layout_floor_index>()
|
||||
->index;
|
||||
String floor_name = "floor_" + itos(floor_index);
|
||||
flecs::entity floor_e =
|
||||
grid_e.lookup(floor_name.ascii().ptr());
|
||||
print_line("grid: " + String(grid_e.path()));
|
||||
print_line("floor: " + floor_name);
|
||||
assert(floor_e.is_valid());
|
||||
assert(grid_e.is_valid());
|
||||
obj->create_floor_components(floor_e, base_floor_e,
|
||||
size);
|
||||
flecs::log::warn("grid floor: %s",
|
||||
floor_e.path().c_str());
|
||||
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");
|
||||
assert(positions[i].second !=
|
||||
positions[j].second);
|
||||
}
|
||||
for (i = 0; i < (int)positions.size(); i++) {
|
||||
int cell_id =
|
||||
positions[i].second.x +
|
||||
size.grid_size * positions[i].second.y;
|
||||
flecs::entity region_e = grid_e.world().entity(
|
||||
positions[i].first);
|
||||
assert(region_e.is_valid());
|
||||
assert(floor_e.is_valid());
|
||||
flecs::entity cell_e = obj->create_cell(
|
||||
floor_e, region_e, cell_id);
|
||||
assert(cell_e.is_valid());
|
||||
flecs::log::warn("grid cell: %s",
|
||||
cell_e.path().c_str());
|
||||
}
|
||||
}
|
||||
float get_entity_area(flecs::entity e) const
|
||||
{
|
||||
return e.get<WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
->area;
|
||||
}
|
||||
float get_entity_area(flecs::world &&ecs,
|
||||
flecs::entity_t et) const
|
||||
{
|
||||
flecs::entity e = ecs.entity(et);
|
||||
return e.get<WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
->area;
|
||||
}
|
||||
float get_entity_area(flecs::world &ecs,
|
||||
flecs::entity_t et) const
|
||||
{
|
||||
flecs::entity e = ecs.entity(et);
|
||||
return e.get<WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
->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.5f) / 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.5f) / 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;
|
||||
}
|
||||
void filter_candidates(
|
||||
flecs::entity ce, float area,
|
||||
const WorldEditor::components::buildings_layout_grid_size
|
||||
&size)
|
||||
{
|
||||
int which = which_position();
|
||||
if (positions.empty()) {
|
||||
/* starting at grid center */
|
||||
Vector2i start_pos(size.grid_size / 2,
|
||||
size.grid_size / 2);
|
||||
positions.push_back(
|
||||
Pair<flecs::entity_t, Vector2i>(
|
||||
ce.id(), start_pos));
|
||||
return;
|
||||
}
|
||||
while (1) {
|
||||
int j, k;
|
||||
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.5f) /
|
||||
2.0f) /
|
||||
4; /* grid conversion */
|
||||
local_radius = MAX(1, local_radius);
|
||||
int dim = base_radius + local_radius;
|
||||
dim = MAX(1, dim);
|
||||
/* grid coordinates */
|
||||
Vector2i candidates[8];
|
||||
get_dim_candidates(base, dim, &candidates[0]);
|
||||
for (j = 0; j < (int)(sizeof(candidates) /
|
||||
sizeof(candidates[0]));
|
||||
j++) {
|
||||
print_line("candidate: " +
|
||||
itos(candidates[j].x) +
|
||||
", " +
|
||||
itos(candidates[j].y));
|
||||
if (candidates[j].x < 0 ||
|
||||
candidates[j].x >= size.grid_size)
|
||||
continue;
|
||||
if (candidates[j].y < 0 ||
|
||||
candidates[j].y >= size.grid_size)
|
||||
continue;
|
||||
if (!check_candidates_tolerance(
|
||||
candidates[j]))
|
||||
continue;
|
||||
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,
|
||||
candidates[j]) <
|
||||
radius_sq)
|
||||
continue;
|
||||
assert(check_candidates_tolerance(
|
||||
candidates[j]));
|
||||
accepted.push_back(
|
||||
candidates[j]);
|
||||
}
|
||||
}
|
||||
if (accepted.size() == 0) {
|
||||
which = which_position();
|
||||
print_line(
|
||||
"reset choice: " + itos(which) +
|
||||
" " + itos(positions.size()));
|
||||
continue;
|
||||
}
|
||||
assert(accepted.size() > 0);
|
||||
const Vector2i &selected =
|
||||
accepted[which_selected()];
|
||||
assert(check_candidates_tolerance(selected));
|
||||
Pair<flecs::entity_t, Vector2i> m(ce.id(),
|
||||
selected);
|
||||
positions.push_back(m);
|
||||
flecs::log::warn("add position: %d, %d",
|
||||
selected.x, selected.y);
|
||||
accepted.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
ecs.system<const WorldEditor::components::buildings_layout_grid_size>(
|
||||
"CreateGrid")
|
||||
.kind(GraphSolve)
|
||||
.write<WorldEditor::components::buildings_layout_grid>()
|
||||
.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<Pair<int, flecs::entity_t> >::Element *me =
|
||||
size.floors.front();
|
||||
while (me) {
|
||||
flecs::query<const WorldEditor::components::
|
||||
buildings_layout_area>
|
||||
q = graph_e.world()
|
||||
.query_builder<
|
||||
const WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
.with(flecs::ChildOf,
|
||||
me->get().second)
|
||||
.scope_open()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_zone>()
|
||||
.or_()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_unit>()
|
||||
.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);
|
||||
});
|
||||
grid.setup_floor(grid_e, me->get().second, size,
|
||||
this);
|
||||
|
||||
me = me->next();
|
||||
}
|
||||
graph_e.world().defer_resume();
|
||||
});
|
||||
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);
|
||||
});
|
||||
|
||||
ecs.system<WorldEditor::components::buildings_layout_grid_floor>(
|
||||
"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<const WorldEditor::components::
|
||||
buildings_layout_grid_cell>
|
||||
q = floor_e.world()
|
||||
.query_builder<
|
||||
const WorldEditor::components::
|
||||
buildings_layout_grid_cell>()
|
||||
.with(flecs::ChildOf, floor_e)
|
||||
.without<WorldEditor::components::
|
||||
final_cell>()
|
||||
.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<int> 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<WorldEditor::components::
|
||||
final_cell>();
|
||||
print_line("size: " + itos(grid.grid_size) +
|
||||
" index: " + itos(index));
|
||||
});
|
||||
});
|
||||
ecs.system<const WorldEditor::components::buildings_layout_grid_cell>(
|
||||
"GrowRegions")
|
||||
.kind(0)
|
||||
.without<WorldEditor::components::final_cell>()
|
||||
.read<WorldEditor::components::buildings_layout_grid_size>()
|
||||
.write<WorldEditor::components::buildings_layout_grid_cell>()
|
||||
.write<WorldEditor::components::buildings_layout_grid_floor>()
|
||||
.write<WorldEditor::components::buildings_layout_grid_queue>()
|
||||
.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<int> 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]);
|
||||
#if 0
|
||||
String c_name = "cell_" + itos(candidates[i]);
|
||||
flecs::entity c_e =
|
||||
e.parent().lookup(c_name.ascii().ptr());
|
||||
#endif
|
||||
extended++;
|
||||
}
|
||||
if (extended == 0)
|
||||
e.add<WorldEditor::components::final_cell>();
|
||||
print_line("size: " + itos(grid.grid_size) +
|
||||
" index: " + itos(index));
|
||||
e.world().defer_resume();
|
||||
});
|
||||
ecs.system<WorldEditor::components::buildings_layout_grid_floor,
|
||||
WorldEditor::components::buildings_layout_grid_queue>(
|
||||
"GrowCommitQueue")
|
||||
.kind(0)
|
||||
.each([this](flecs::entity e,
|
||||
WorldEditor::components::buildings_layout_grid_floor
|
||||
&fl,
|
||||
WorldEditor::components::buildings_layout_grid_queue
|
||||
&queue) {
|
||||
List<Pair<flecs::entity_t, int> >::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<WorldEditor::components::
|
||||
buildings_layout_grid_queue>();
|
||||
});
|
||||
ecs.system("RunGrow").kind(GraphFilter).run([module_name](flecs::iter &it) {
|
||||
int i;
|
||||
it.world().defer_suspend();
|
||||
print_line("Running grow...");
|
||||
for (i = 0; i < 10; i++) {
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
(module_name + "::GrowFloorRegions")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
(module_name + "::GrowCommitQueue")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
}
|
||||
it.world().defer_resume();
|
||||
flecs::query<const WorldEditor::components::
|
||||
buildings_layout_grid_floor>
|
||||
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) {
|
||||
it.world()
|
||||
.lookup((module_name + "::GraphFilter")
|
||||
.ascii()
|
||||
.ptr())
|
||||
.disable();
|
||||
print_line("Grow done");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void BuildingLayoutGraph::graph_module::create_floor_components(
|
||||
flecs::entity floor_e, flecs::entity base_floor_e,
|
||||
const WorldEditor::components::buildings_layout_grid_size &size)
|
||||
{
|
||||
floor_e.set<WorldEditor::components::buildings_layout_grid_floor>(
|
||||
{ Set<int>(), size.grid_size, size.growth_size });
|
||||
floor_e.set<growth_regions>(
|
||||
{ Vector<struct growth_regions::region>() });
|
||||
floor_e.add<WorldEditor::components::belongs>(base_floor_e);
|
||||
}
|
||||
|
||||
void BuildingLayoutGraph::graph_module::create_region(flecs::entity floor_e,
|
||||
flecs::entity seed_e,
|
||||
flecs::entity region_e,
|
||||
const Vector2i &position,
|
||||
float area)
|
||||
{
|
||||
int i;
|
||||
struct growth_regions::region r;
|
||||
r.seed_et = seed_e.id();
|
||||
r.region_et = region_e.id();
|
||||
r.rect.position = position;
|
||||
r.rect.size = Vector2i(1, 1);
|
||||
r.remains_area = MAX((int)(area * 2.0f) / 16 + 1, 16);
|
||||
r.can_grow_square = true;
|
||||
bool ok = true;
|
||||
assert(check_region(floor_e, -1, r.rect));
|
||||
const struct growth_regions *reg = floor_e.get<growth_regions>();
|
||||
for (i = 0; i < reg->regions.size(); i++) {
|
||||
if (reg->regions[i].region_et == r.region_et) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
if (reg->regions[i].rect.position == r.rect.position) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
r.remains_area -= 1;
|
||||
assert(ok);
|
||||
if (ok) {
|
||||
floor_e.get_mut<growth_regions>()->regions.push_back(r);
|
||||
floor_e.modified<growth_regions>();
|
||||
flecs::log::warn("region created for %s",
|
||||
region_e.path().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
bool BuildingLayoutGraph::graph_module::check_region(flecs::entity floor_e,
|
||||
int index,
|
||||
const Rect2i &rect)
|
||||
{
|
||||
const Vector<growth_regions::region> ®ions =
|
||||
floor_e.get<growth_regions>()->regions;
|
||||
int i;
|
||||
bool ret = true;
|
||||
for (i = 0; i < regions.size(); i++) {
|
||||
if (i == index)
|
||||
continue;
|
||||
if (rect.intersects(regions[i].rect)) {
|
||||
ret = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
{
|
||||
ecs.module<BuildingLayoutGraph::graph_module>();
|
||||
@@ -893,6 +383,11 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
GraphSolve = ecs.entity("GraphSolve")
|
||||
.add(flecs::Phase)
|
||||
.depends_on(GraphSolveFloors);
|
||||
flecs::entity GraphAssembleSkeleton =
|
||||
ecs.entity("GraphAssembleSkeleton")
|
||||
.add(flecs::Phase)
|
||||
.depends_on(GraphSolve);
|
||||
GraphAssembleSkeleton.disable();
|
||||
flecs::entity GraphPostSolve = ecs.entity("GraphPostSolve")
|
||||
.add(flecs::Phase)
|
||||
.depends_on(flecs::PostUpdate);
|
||||
@@ -1060,9 +555,36 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
buildings_layout_area &area) {
|
||||
if (area.area < MIN_ROOM_SIZE) {
|
||||
badness++;
|
||||
assert(false);
|
||||
}
|
||||
});
|
||||
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();
|
||||
}
|
||||
|
||||
print_line("Zones processing done...");
|
||||
});
|
||||
ecs.system("UnitsStart")
|
||||
@@ -1279,10 +801,19 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
buildings_layout_area &area) {
|
||||
if (area.area < MIN_ROOM_SIZE) {
|
||||
badness++;
|
||||
assert(false);
|
||||
}
|
||||
});
|
||||
print_line("Floor processing done...");
|
||||
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<const WorldEditor::components::buildings_layout_graph,
|
||||
@@ -1325,14 +856,14 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
});
|
||||
#endif
|
||||
ecs.system("AssembleSkeletonStart")
|
||||
.kind(GraphSolve)
|
||||
.kind(GraphAssembleSkeleton)
|
||||
.run([module_name](flecs::iter &it) {
|
||||
print_line("Assembling skeleton...");
|
||||
});
|
||||
|
||||
ecs.system<const WorldEditor::components::buildings_layout_graph>(
|
||||
"AssembleSkeleton")
|
||||
.kind(GraphSolve)
|
||||
.kind(GraphAssembleSkeleton)
|
||||
.read<WorldEditor::components::buildings_layout_order>()
|
||||
.read<WorldEditor::components::buildings_layout_area>()
|
||||
.read<WorldEditor::components::buildings_layout_commands>()
|
||||
@@ -1486,7 +1017,7 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
&area) {
|
||||
int grid_size = (int)(Math::sqrt(area.area) * 1.5) + 1;
|
||||
int growth_size =
|
||||
(int)Math::ceil(area.area * 2.0f / 4.0f) + 1;
|
||||
(int)Math::ceil(area.area * 1.3f / 16.0f) + 1;
|
||||
flecs::entity graph_e = it.entity(count);
|
||||
List<flecs::entity> queue;
|
||||
queue.push_back(graph_e);
|
||||
@@ -1608,6 +1139,7 @@ BuildingLayoutGraph::graph_module::graph_module(flecs::world &ecs)
|
||||
it.world().defer_resume();
|
||||
});
|
||||
growth_module(ecs, module_name);
|
||||
room_growth_module(ecs, module_name);
|
||||
#if 0
|
||||
ecs.system<WorldEditor::components::buildings_layout_grid_floor>(
|
||||
"AssignGridSizeToFloor")
|
||||
|
||||
28
src/modules/stream/ui/graph_module.h
Normal file
28
src/modules/stream/ui/graph_module.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef GRAPH_MODULE_H_
|
||||
#define GRAPH_MODULE_H_
|
||||
struct growth_regions {
|
||||
struct region {
|
||||
flecs::entity_t seed_et;
|
||||
flecs::entity_t region_et;
|
||||
Rect2i rect;
|
||||
int remains_area;
|
||||
bool can_grow_square;
|
||||
};
|
||||
Vector<struct region> 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;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
790
src/modules/stream/ui/graph_module_growth.cpp
Normal file
790
src/modules/stream/ui/graph_module_growth.cpp
Normal file
@@ -0,0 +1,790 @@
|
||||
#include "base_data.h"
|
||||
#include "editor_event.h"
|
||||
#include "world_editor.h"
|
||||
#include "building_layout_graph.h"
|
||||
#include "graph_module.h"
|
||||
|
||||
void BuildingLayoutGraph::graph_module::growth_module(flecs::world &ecs,
|
||||
const String &module_name)
|
||||
{
|
||||
ecs.component<growth_regions>();
|
||||
flecs::entity GraphFilter = ecs.entity("GraphFilter")
|
||||
.add(flecs::Phase)
|
||||
.depends_on(flecs::OnUpdate);
|
||||
GraphFilter.disable();
|
||||
|
||||
struct grid_calc {
|
||||
int grid_size;
|
||||
int index2x(int index)
|
||||
{
|
||||
return index % grid_size;
|
||||
}
|
||||
int index2y(int index)
|
||||
{
|
||||
return index / grid_size;
|
||||
}
|
||||
void get_cadidates(int index, int *candidates)
|
||||
{
|
||||
int i, j, idx = 0;
|
||||
int x = index2x(index);
|
||||
int y = index2y(index);
|
||||
|
||||
for (i = -1; i < 2; i++) {
|
||||
for (j = -1; j < 2; j++)
|
||||
if (i != 0 || j != 0) {
|
||||
int cx = x + i, cy = y + j;
|
||||
if (cx >= 0 && cx < grid_size &&
|
||||
cy >= 0 && cy < grid_size) {
|
||||
int id = cx +
|
||||
grid_size * cy;
|
||||
candidates[idx++] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
grid_calc(flecs::entity layout_e)
|
||||
: grid_size(
|
||||
layout_e.get<WorldEditor::components::
|
||||
buildings_layout_grid_size>()
|
||||
->grid_size)
|
||||
{
|
||||
assert(layout_e.is_valid());
|
||||
}
|
||||
grid_calc(int grid_size)
|
||||
: grid_size(grid_size)
|
||||
{
|
||||
assert(grid_size > 0);
|
||||
}
|
||||
};
|
||||
struct grid_misc {
|
||||
LocalVector<Pair<flecs::entity_t, Vector2i> > positions;
|
||||
LocalVector<Vector2i> accepted;
|
||||
struct make_random r;
|
||||
grid_misc()
|
||||
: r(100)
|
||||
{
|
||||
}
|
||||
void get_dim_candidates(const Vector2i &base, int dim,
|
||||
Vector2i *candidates)
|
||||
{
|
||||
int i;
|
||||
std::vector<Vector2i> 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];
|
||||
}
|
||||
void setup_floor(
|
||||
flecs::entity grid_e, flecs::entity_t base_et,
|
||||
const WorldEditor::components::buildings_layout_grid_size
|
||||
&size,
|
||||
BuildingLayoutGraph::graph_module *obj)
|
||||
{
|
||||
int i, j;
|
||||
flecs::entity base_floor_e =
|
||||
grid_e.world().entity(base_et);
|
||||
flecs::log::warn("base_floor: %s",
|
||||
base_floor_e.path().c_str());
|
||||
int floor_index =
|
||||
base_floor_e
|
||||
.get<WorldEditor::components::
|
||||
buildings_layout_floor_index>()
|
||||
->index;
|
||||
String floor_name = "floor_" + itos(floor_index);
|
||||
flecs::entity floor_e =
|
||||
grid_e.lookup(floor_name.ascii().ptr());
|
||||
print_line("grid: " + String(grid_e.path()));
|
||||
print_line("floor: " + floor_name);
|
||||
assert(floor_e.is_valid());
|
||||
assert(grid_e.is_valid());
|
||||
obj->create_floor_components(floor_e, base_floor_e,
|
||||
size);
|
||||
flecs::log::warn("grid floor: %s",
|
||||
floor_e.path().c_str());
|
||||
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");
|
||||
assert(positions[i].second !=
|
||||
positions[j].second);
|
||||
}
|
||||
for (i = 0; i < (int)positions.size(); i++) {
|
||||
int cell_id =
|
||||
positions[i].second.x +
|
||||
size.grid_size * positions[i].second.y;
|
||||
flecs::entity region_e = grid_e.world().entity(
|
||||
positions[i].first);
|
||||
float area =
|
||||
region_e.get<WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
->area;
|
||||
assert(region_e.is_valid());
|
||||
assert(floor_e.is_valid());
|
||||
Rect2i check;
|
||||
check.position = positions[i].second;
|
||||
check.size = Vector2i(1, 1);
|
||||
assert(obj->check_region(floor_e, -1, check));
|
||||
flecs::entity cell_e = obj->create_cell(
|
||||
floor_e, region_e, cell_id);
|
||||
assert(cell_e.is_valid());
|
||||
obj->create_region(floor_e, cell_e, region_e,
|
||||
positions[i].second, area);
|
||||
flecs::log::warn("grid cell: %s",
|
||||
cell_e.path().c_str());
|
||||
}
|
||||
}
|
||||
float get_entity_area(flecs::entity e) const
|
||||
{
|
||||
return e.get<WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
->area;
|
||||
}
|
||||
float get_entity_area(flecs::world &&ecs,
|
||||
flecs::entity_t et) const
|
||||
{
|
||||
flecs::entity e = ecs.entity(et);
|
||||
return e.get<WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
->area;
|
||||
}
|
||||
float get_entity_area(flecs::world &ecs,
|
||||
flecs::entity_t et) const
|
||||
{
|
||||
flecs::entity e = ecs.entity(et);
|
||||
return e.get<WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
->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++) {
|
||||
Rect2i check1, check2;
|
||||
check1.position = positions[m].second;
|
||||
check1.size = Vector2i(1, 1);
|
||||
check2.position = candidate;
|
||||
check2.size = Vector2i(1, 1);
|
||||
if (check1.intersects(check2)) {
|
||||
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)
|
||||
continue;
|
||||
assert(check_candidates_tolerance(candidate));
|
||||
accepted.push_back(candidate);
|
||||
ok = true;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
bool process_candidates(
|
||||
flecs::entity ce, const Vector2i &base, float area,
|
||||
const WorldEditor::components::buildings_layout_grid_size
|
||||
&size,
|
||||
flecs::entity_t base_et, int dim)
|
||||
{
|
||||
int j;
|
||||
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);
|
||||
int md = 1;
|
||||
if (size.grid_size > 30)
|
||||
md = 8;
|
||||
else if (size.grid_size > 20)
|
||||
md = 6;
|
||||
else if (size.grid_size > 15)
|
||||
md = 4;
|
||||
else if (size.grid_size > 10)
|
||||
md = 2;
|
||||
Rect2i clip(md, md, size.grid_size - md * 2,
|
||||
size.grid_size - md * 2);
|
||||
Vector2i candidates[8];
|
||||
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 (!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));
|
||||
accept_candidate(ce, candidates[j], area);
|
||||
}
|
||||
if (accepted.size() > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void filter_candidates(
|
||||
flecs::entity ce, float area,
|
||||
const WorldEditor::components::buildings_layout_grid_size
|
||||
&size)
|
||||
{
|
||||
if (positions.empty()) {
|
||||
/* starting at grid center */
|
||||
Vector2i start_pos(size.grid_size / 2,
|
||||
size.grid_size / 2);
|
||||
positions.push_back(
|
||||
Pair<flecs::entity_t, Vector2i>(
|
||||
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);
|
||||
int dim = base_radius + local_radius;
|
||||
dim = MAX(1, dim);
|
||||
process_candidates(ce, base, area, size,
|
||||
base_et, dim);
|
||||
if (accepted.size() == 0) {
|
||||
assert(positions.size() > 0);
|
||||
continue;
|
||||
}
|
||||
assert(accepted.size() > 0);
|
||||
const Vector2i &selected =
|
||||
accepted[which_selected()];
|
||||
assert(check_candidates_tolerance(selected));
|
||||
Pair<flecs::entity_t, Vector2i> m(ce.id(),
|
||||
selected);
|
||||
check_candidate(selected);
|
||||
positions.push_back(m);
|
||||
flecs::log::warn("add position: %d, %d",
|
||||
selected.x, selected.y);
|
||||
accepted.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
int which_position()
|
||||
{
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
ecs.system<const WorldEditor::components::buildings_layout_grid_size>(
|
||||
"CreateGrid")
|
||||
.kind(GraphSolve)
|
||||
.write<WorldEditor::components::buildings_layout_grid>()
|
||||
.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<Pair<int, flecs::entity_t> >::Element *me =
|
||||
size.floors.front();
|
||||
while (me) {
|
||||
flecs::query<const WorldEditor::components::
|
||||
buildings_layout_area>
|
||||
q = graph_e.world()
|
||||
.query_builder<
|
||||
const WorldEditor::components::
|
||||
buildings_layout_area>()
|
||||
.with(flecs::ChildOf,
|
||||
me->get().second)
|
||||
.scope_open()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_zone>()
|
||||
.or_()
|
||||
.with<WorldEditor::components::
|
||||
buildings_layout_unit>()
|
||||
.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);
|
||||
});
|
||||
grid.setup_floor(grid_e, me->get().second, size,
|
||||
this);
|
||||
|
||||
me = me->next();
|
||||
}
|
||||
graph_e.world().defer_resume();
|
||||
});
|
||||
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);
|
||||
});
|
||||
|
||||
ecs.system<WorldEditor::components::buildings_layout_grid_floor,
|
||||
growth_regions>("GrowFloorRectRegions")
|
||||
.kind(0)
|
||||
.each([this](flecs::entity floor_e,
|
||||
WorldEditor::components::buildings_layout_grid_floor
|
||||
&fl,
|
||||
growth_regions &g) {
|
||||
int i;
|
||||
bool grown = true;
|
||||
int state = 0;
|
||||
while (1) {
|
||||
while (grown) {
|
||||
grown = false;
|
||||
for (i = 0; i < g.regions.size(); i++) {
|
||||
Rect2i mrect =
|
||||
g.regions[i].rect;
|
||||
if (state == 0) {
|
||||
if (!g.regions[i]
|
||||
.can_grow_square)
|
||||
continue;
|
||||
if (g.regions[i]
|
||||
.remains_area <=
|
||||
0) {
|
||||
g.regions
|
||||
.write[i]
|
||||
.can_grow_square =
|
||||
false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mrect = g.regions[i].rect;
|
||||
int old_area = mrect.get_area();
|
||||
if (state == 0) {
|
||||
mrect = g.regions[i]
|
||||
.rect;
|
||||
|
||||
assert(check_region(
|
||||
floor_e, i,
|
||||
mrect));
|
||||
mrect = mrect.grow(1);
|
||||
Rect2i clip(
|
||||
0, 0,
|
||||
fl.grid_size,
|
||||
fl.grid_size);
|
||||
if (!clip.encloses(
|
||||
mrect))
|
||||
continue;
|
||||
bool ok = check_region(
|
||||
floor_e, i,
|
||||
mrect);
|
||||
if (!ok)
|
||||
continue;
|
||||
int new_area =
|
||||
mrect.get_area();
|
||||
int area_diff =
|
||||
new_area -
|
||||
old_area;
|
||||
if (area_diff > 0) {
|
||||
g.regions
|
||||
.write[i]
|
||||
.rect =
|
||||
mrect;
|
||||
g.regions
|
||||
.write[i]
|
||||
.remains_area -=
|
||||
area_diff;
|
||||
grown = true;
|
||||
}
|
||||
} else if (state == 1) {
|
||||
int d;
|
||||
mrect = g.regions[i]
|
||||
.rect;
|
||||
if (g.regions[i]
|
||||
.remains_area <=
|
||||
0)
|
||||
break;
|
||||
bool ok = true;
|
||||
for (d = 0; d < 4;
|
||||
d++) {
|
||||
mrect = g.regions[i]
|
||||
.rect;
|
||||
assert(check_region(
|
||||
floor_e,
|
||||
i,
|
||||
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;
|
||||
}
|
||||
Rect2i clip(
|
||||
0, 0,
|
||||
fl.grid_size,
|
||||
fl.grid_size);
|
||||
if (!clip.encloses(
|
||||
mrect)) {
|
||||
ok = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
ok = check_region(
|
||||
floor_e,
|
||||
i,
|
||||
mrect);
|
||||
if (ok) {
|
||||
int new_area =
|
||||
mrect.get_area();
|
||||
int area_diff =
|
||||
new_area -
|
||||
old_area;
|
||||
if (area_diff >
|
||||
0) {
|
||||
g.regions
|
||||
.write[i]
|
||||
.rect =
|
||||
mrect;
|
||||
g.regions
|
||||
.write[i]
|
||||
.remains_area -=
|
||||
area_diff;
|
||||
grown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
state++;
|
||||
grown = true;
|
||||
if (state == 2)
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < g.regions.size(); i++) {
|
||||
int x, y;
|
||||
Rect2i 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 =
|
||||
floor_e.world().entity(
|
||||
g.regions[i]
|
||||
.seed_et);
|
||||
assert(seed_e.is_valid());
|
||||
queue_grow_cell(seed_e,
|
||||
id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ecs.system<WorldEditor::components::buildings_layout_grid_floor>(
|
||||
"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<const WorldEditor::components::
|
||||
buildings_layout_grid_cell>
|
||||
q = floor_e.world()
|
||||
.query_builder<
|
||||
const WorldEditor::components::
|
||||
buildings_layout_grid_cell>()
|
||||
.with(flecs::ChildOf, floor_e)
|
||||
.without<WorldEditor::components::
|
||||
final_cell>()
|
||||
.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<int> 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<WorldEditor::components::
|
||||
final_cell>();
|
||||
print_line("size: " + itos(grid.grid_size) +
|
||||
" index: " + itos(index));
|
||||
});
|
||||
});
|
||||
ecs.system<const WorldEditor::components::buildings_layout_grid_cell>(
|
||||
"GrowRegions")
|
||||
.kind(0)
|
||||
.without<WorldEditor::components::final_cell>()
|
||||
.read<WorldEditor::components::buildings_layout_grid_size>()
|
||||
.write<WorldEditor::components::buildings_layout_grid_cell>()
|
||||
.write<WorldEditor::components::buildings_layout_grid_floor>()
|
||||
.write<WorldEditor::components::buildings_layout_grid_queue>()
|
||||
.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<int> 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]);
|
||||
#if 0
|
||||
String c_name = "cell_" + itos(candidates[i]);
|
||||
flecs::entity c_e =
|
||||
e.parent().lookup(c_name.ascii().ptr());
|
||||
#endif
|
||||
extended++;
|
||||
}
|
||||
if (extended == 0)
|
||||
e.add<WorldEditor::components::final_cell>();
|
||||
print_line("size: " + itos(grid.grid_size) +
|
||||
" index: " + itos(index));
|
||||
e.world().defer_resume();
|
||||
});
|
||||
ecs.system<WorldEditor::components::buildings_layout_grid_floor,
|
||||
WorldEditor::components::buildings_layout_grid_queue>(
|
||||
"GrowCommitQueue")
|
||||
.kind(0)
|
||||
.each([this](flecs::entity e,
|
||||
WorldEditor::components::buildings_layout_grid_floor
|
||||
&fl,
|
||||
WorldEditor::components::buildings_layout_grid_queue
|
||||
&queue) {
|
||||
List<Pair<flecs::entity_t, int> >::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<WorldEditor::components::
|
||||
buildings_layout_grid_queue>();
|
||||
});
|
||||
ecs.system("RunGrow")
|
||||
.kind(GraphFilter)
|
||||
.run([module_name](flecs::iter &it) {
|
||||
int i;
|
||||
it.world().defer_suspend();
|
||||
print_line("Running grow...");
|
||||
for (i = 0; i < 100; i++) {
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
(module_name +
|
||||
"::GrowFloorRectRegions")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
(module_name +
|
||||
"::GrowCommitQueue")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
}
|
||||
#if 0
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
(module_name + "::GrowFloorRegions")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
it.world()
|
||||
.system(it.world().lookup(
|
||||
(module_name + "::GrowCommitQueue")
|
||||
.ascii()
|
||||
.ptr()))
|
||||
.run();
|
||||
#endif
|
||||
it.world().defer_resume();
|
||||
});
|
||||
}
|
||||
380
src/modules/stream/ui/graph_module_rooms.cpp
Normal file
380
src/modules/stream/ui/graph_module_rooms.cpp
Normal file
@@ -0,0 +1,380 @@
|
||||
#include "base_data.h"
|
||||
#include "world_editor.h"
|
||||
#include "building_layout_graph.h"
|
||||
#include "graph_module.h"
|
||||
|
||||
void BuildingLayoutGraph::graph_module::room_growth_module(
|
||||
flecs::world &ecs, const String &module_name)
|
||||
{
|
||||
flecs::entity GraphFilter = ecs.entity("GraphFilter");
|
||||
assert(GraphFilter.is_valid());
|
||||
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("CheckGrow").kind(GraphFilter).run([module_name](flecs::iter &it) {
|
||||
flecs::query<const WorldEditor::components::
|
||||
buildings_layout_grid_floor>
|
||||
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) {
|
||||
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...");
|
||||
}
|
||||
});
|
||||
ecs.system<const WorldEditor::components::buildings_layout_grid_cell>(
|
||||
"MarkExternalWall")
|
||||
.kind(GraphMarkData)
|
||||
.without<WorldEditor::components::outside_wall>()
|
||||
.read<WorldEditor::components::buildings_layout_grid_floor>()
|
||||
.write<WorldEditor::components::outside_wall>()
|
||||
.write<WorldEditor::components::final_cell>()
|
||||
.each([](flecs::entity e,
|
||||
const WorldEditor::components::buildings_layout_grid_cell
|
||||
&cell) {
|
||||
int grid_size =
|
||||
e.parent()
|
||||
.get<WorldEditor::components::
|
||||
buildings_layout_grid_floor>()
|
||||
->grid_size;
|
||||
int i;
|
||||
Vector2i position(cell.index % grid_size,
|
||||
cell.index / grid_size);
|
||||
Vector2 west(position.x - 1, position.y);
|
||||
Vector2 north(position.x, position.y - 1);
|
||||
Vector2 east(position.x + 1, position.y);
|
||||
Vector2 south(position.x, position.y + 1);
|
||||
int west_id = west.x + grid_size * west.y;
|
||||
int north_id = north.x + grid_size * north.y;
|
||||
int east_id = east.x + grid_size * east.y;
|
||||
int south_id = south.x + grid_size * south.y;
|
||||
std::vector<int> neighbors = { west_id, north_id,
|
||||
east_id, south_id };
|
||||
bool outside = false;
|
||||
bool border = false;
|
||||
for (i = 0; i < (int)neighbors.size(); i++) {
|
||||
int id = neighbors[i];
|
||||
print_line("id=" + itos(id));
|
||||
if (!e.parent()
|
||||
.get<WorldEditor::components::
|
||||
buildings_layout_grid_floor>()
|
||||
->cells.has(id)) {
|
||||
outside = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (int)neighbors.size(); i++) {
|
||||
int id = neighbors[i];
|
||||
print_line("id=" + itos(id));
|
||||
String neighbor_name = "cell_" + itos(id);
|
||||
flecs::entity neighbor_e = e.parent().lookup(
|
||||
neighbor_name.ascii().ptr());
|
||||
if (!neighbor_e.is_valid())
|
||||
continue;
|
||||
const WorldEditor::components::buildings_layout_grid_cell
|
||||
*neighbor_cell = neighbor_e.get<
|
||||
WorldEditor::components::
|
||||
buildings_layout_grid_cell>();
|
||||
if (cell.type != neighbor_cell->type) {
|
||||
border = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (outside)
|
||||
e.add<WorldEditor::components::outside_wall>();
|
||||
else
|
||||
e.add<WorldEditor::components::final_cell>();
|
||||
if (border)
|
||||
e.add<WorldEditor::components::border>();
|
||||
print_line("outside: " + itos(outside));
|
||||
print_line("position: " + (position.operator String()));
|
||||
print_line("grid size: " + itos(grid_size));
|
||||
print_line("tile index: " + itos(cell.index));
|
||||
});
|
||||
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<WorldEditor::components::
|
||||
outside_wall>())
|
||||
wall_count++;
|
||||
if (e.has<WorldEditor::components::
|
||||
final_cell>())
|
||||
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<int, flecs::entity> entities;
|
||||
Set<int> tile_selection[4];
|
||||
Vector<int> 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<int>::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<WorldEditor::components::
|
||||
buildings_layout_grid_floor>()
|
||||
->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<const WorldEditor::components::buildings_layout_zone,
|
||||
const WorldEditor::components::buildings_layout_floor_index>(
|
||||
"ProcessFloor0Rooms")
|
||||
.kind(GraphProcessRooms)
|
||||
.read<WorldEditor::components::belongs>()
|
||||
.read<WorldEditor::components::outside_wall>()
|
||||
.read<WorldEditor::components::border>()
|
||||
.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<WorldEditor::components::belongs>(e)
|
||||
.without<WorldEditor::components::outside_wall>()
|
||||
.without<WorldEditor::components::border>()
|
||||
.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<WorldEditor::components::belongs>(e)
|
||||
.without<WorldEditor::components::outside_wall>()
|
||||
.with<WorldEditor::components::border>()
|
||||
.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<WorldEditor::components::belongs>(e)
|
||||
.with<WorldEditor::components::outside_wall>()
|
||||
.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<const WorldEditor::components::
|
||||
buildings_layout_room>()
|
||||
.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);
|
||||
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);
|
||||
});
|
||||
}
|
||||
@@ -120,6 +120,9 @@ public:
|
||||
int growth_size;
|
||||
};
|
||||
struct belongs {};
|
||||
struct border {};
|
||||
struct belongs_room {};
|
||||
struct outside_wall {};
|
||||
struct buildings_layout_grid_floor {
|
||||
Set<int> cells;
|
||||
int grid_size;
|
||||
|
||||
Reference in New Issue
Block a user