Quality of life with road lines edge data (lots, buildings, etc.)
This commit is contained in:
@@ -6320,153 +6320,67 @@
|
|||||||
"xform": "Transform( 1, 1.8011e-08, -0.000335185, 0, 1, 5.37346e-05, 0.000335185, -5.37346e-05, 1, 159.997, -1.2499, -487.052 )",
|
"xform": "Transform( 1, 1.8011e-08, -0.000335185, 0, 1, 5.37346e-05, 0.000335185, -5.37346e-05, 1, 159.997, -1.2499, -487.052 )",
|
||||||
"index": 300
|
"index": 300
|
||||||
},
|
},
|
||||||
"Transform( -0.0570498, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570498, -28.4912, 0.0199585, -87.4024 )": {
|
"road__center2_road__transit_stop__7__0__right__bus-stop": {
|
||||||
"id": "residental-house1",
|
"id": "bus-stop",
|
||||||
"pattern_id": 0,
|
"pattern_id": 0,
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"residents": [
|
"residents": [
|
||||||
872,
|
|
||||||
2275,
|
|
||||||
2507,
|
|
||||||
574,
|
|
||||||
2756
|
|
||||||
],
|
],
|
||||||
"workers": [
|
"workers": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"guests": [
|
"guests": [
|
||||||
2399,
|
|
||||||
2585,
|
|
||||||
2028,
|
|
||||||
327,
|
|
||||||
749,
|
|
||||||
2140,
|
|
||||||
2418,
|
|
||||||
394,
|
|
||||||
549,
|
|
||||||
202,
|
|
||||||
2393,
|
|
||||||
406,
|
|
||||||
801,
|
|
||||||
315,
|
|
||||||
402,
|
|
||||||
2064,
|
|
||||||
1458,
|
|
||||||
2643,
|
|
||||||
1291
|
|
||||||
],
|
],
|
||||||
"worktime": [
|
"worktime": [
|
||||||
20,
|
0,
|
||||||
23
|
23
|
||||||
],
|
],
|
||||||
"key": "Transform( -0.0570498, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570498, -28.4912, 0.0199585, -87.4024 )",
|
"key": "road__center2_road__transit_stop__7__0__right__bus-stop",
|
||||||
"xform": "Transform( -0.0570498, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570498, -28.4912, -1.2499, -87.4024 )",
|
"xform": "Transform( 0.274721, 2.87899e-07, 0.961524, -1.04797e-06, 1, -4.58082e-14, -0.961524, -1.00765e-06, 0.274721, -75.4563, 0.00010019, -138.703 )",
|
||||||
"index": 301
|
"index": 301
|
||||||
},
|
},
|
||||||
"Transform( -0.0570498, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570498, -25.9372, 0.0189819, -132.098 )": {
|
"road__center2_road__transit_stop__0__0__right__bus-stop": {
|
||||||
"id": "residental-house2",
|
"id": "bus-stop",
|
||||||
"pattern_id": 2,
|
"pattern_id": 0,
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"residents": [
|
"residents": [
|
||||||
1814,
|
|
||||||
1825,
|
|
||||||
327
|
|
||||||
],
|
],
|
||||||
"workers": [
|
"workers": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"guests": [
|
"guests": [
|
||||||
2399,
|
|
||||||
1309,
|
|
||||||
2507,
|
|
||||||
1204,
|
|
||||||
1137,
|
|
||||||
567,
|
|
||||||
1458,
|
|
||||||
384,
|
|
||||||
2585,
|
|
||||||
2357,
|
|
||||||
496,
|
|
||||||
201,
|
|
||||||
394,
|
|
||||||
613,
|
|
||||||
2496,
|
|
||||||
1028,
|
|
||||||
749,
|
|
||||||
1660,
|
|
||||||
574,
|
|
||||||
1529,
|
|
||||||
729,
|
|
||||||
679,
|
|
||||||
1693,
|
|
||||||
801,
|
|
||||||
272,
|
|
||||||
2576,
|
|
||||||
2761,
|
|
||||||
2275,
|
|
||||||
2147,
|
|
||||||
1931,
|
|
||||||
402,
|
|
||||||
695,
|
|
||||||
2594
|
|
||||||
],
|
],
|
||||||
"worktime": [
|
"worktime": [
|
||||||
14,
|
0,
|
||||||
23
|
23
|
||||||
],
|
],
|
||||||
"key": "Transform( -0.0570498, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570498, -25.9372, 0.0189819, -132.098 )",
|
"key": "road__center2_road__transit_stop__0__0__right__bus-stop",
|
||||||
"xform": "Transform( -0.0570498, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570498, -25.9372, -1.2499, -132.098 )",
|
"xform": "Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -1110, 0.0210266, -245 )",
|
||||||
"index": 302
|
"index": 302
|
||||||
},
|
},
|
||||||
"Transform( -0.0570497, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570497, -23.9474, 0.0179977, -166.92 )": {
|
"road__center2_road__lot__7__right__lot-small1": {
|
||||||
"id": "residental-house3",
|
"id": "lot-small1",
|
||||||
"pattern_id": 3,
|
"pattern_id": 0,
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"residents": [
|
"residents": [
|
||||||
679,
|
|
||||||
347,
|
|
||||||
377
|
|
||||||
],
|
],
|
||||||
"workers": [
|
"workers": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"guests": [
|
"guests": [
|
||||||
2272,
|
|
||||||
1204,
|
|
||||||
1931,
|
|
||||||
1660,
|
|
||||||
1458,
|
|
||||||
777,
|
|
||||||
2064,
|
|
||||||
1291,
|
|
||||||
2761,
|
|
||||||
1309,
|
|
||||||
2731,
|
|
||||||
801,
|
|
||||||
2140,
|
|
||||||
2094,
|
|
||||||
622,
|
|
||||||
695,
|
|
||||||
1825,
|
|
||||||
749,
|
|
||||||
856,
|
|
||||||
2393,
|
|
||||||
1240,
|
|
||||||
2513,
|
|
||||||
2275,
|
|
||||||
394,
|
|
||||||
2218,
|
|
||||||
2507,
|
|
||||||
202,
|
|
||||||
1431,
|
|
||||||
2756
|
|
||||||
],
|
],
|
||||||
"worktime": [
|
"worktime": [
|
||||||
19,
|
0,
|
||||||
23
|
23
|
||||||
],
|
],
|
||||||
"key": "Transform( -0.0570497, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570497, -23.9474, 0.0179977, -166.92 )",
|
"key": "road__center2_road__lot__7__right__lot-small1",
|
||||||
"xform": "Transform( -0.0570497, 0, -0.998371, 0, 1, 0, 0.998371, 0, -0.0570497, -23.9474, -1.2499, -166.92 )",
|
"xform": "Transform( -0.274721, 2.87899e-07, -0.961524, 1.04797e-06, 1, -4.58082e-14, 0.961524, -1.00765e-06, -0.274721, -38.3552, 0.000121149, -107.302 )",
|
||||||
"index": 303
|
"index": 303
|
||||||
},
|
},
|
||||||
"Transform( 0.0570496, 0, 0.998371, 0, 1, 0, -0.998371, 0, 0.0570496, 41.3947, 0.0140915, -83.4089 )": {
|
"Transform( 0.0570496, 0, 0.998371, 0, 1, 0, -0.998371, 0, 0.0570496, 41.3947, 0.0140915, -83.4089 )": {
|
||||||
@@ -36578,193 +36492,88 @@
|
|||||||
"xform": "Transform( -0.999568, 0, -0.0293968, 0, 1, 0, 0.0293968, 0, -0.999568, -168.6, -1.2499, -202.982 )",
|
"xform": "Transform( -0.999568, 0, -0.0293968, 0, 1, 0, 0.0293968, 0, -0.999568, -168.6, -1.2499, -202.982 )",
|
||||||
"index": 1073
|
"index": 1073
|
||||||
},
|
},
|
||||||
"Transform( -0.999568, 0, -0.0294008, 0, 1, 0, 0.0294008, 0, -0.999568, -118.67, 0.033226, -204.451 )": {
|
"road__center2_road__lot__9__left__lot-small1": {
|
||||||
"id": "residental-house6",
|
"id": "lot-small1",
|
||||||
"pattern_id": 923,
|
"pattern_id": 0,
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"residents": [
|
"residents": [
|
||||||
2761,
|
|
||||||
801,
|
|
||||||
384
|
|
||||||
],
|
],
|
||||||
"workers": [
|
"workers": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"guests": [
|
"guests": [
|
||||||
1261,
|
|
||||||
1825,
|
|
||||||
898,
|
|
||||||
968,
|
|
||||||
2594,
|
|
||||||
377,
|
|
||||||
856,
|
|
||||||
679,
|
|
||||||
1431,
|
|
||||||
1137,
|
|
||||||
2400,
|
|
||||||
1814,
|
|
||||||
777,
|
|
||||||
502,
|
|
||||||
1863,
|
|
||||||
2643,
|
|
||||||
1370,
|
|
||||||
2147,
|
|
||||||
872,
|
|
||||||
1648,
|
|
||||||
2275,
|
|
||||||
1240,
|
|
||||||
743,
|
|
||||||
216,
|
|
||||||
1309,
|
|
||||||
1763,
|
|
||||||
202,
|
|
||||||
2507,
|
|
||||||
1153,
|
|
||||||
2513,
|
|
||||||
270,
|
|
||||||
147,
|
|
||||||
2276
|
|
||||||
],
|
],
|
||||||
"worktime": [
|
"worktime": [
|
||||||
14,
|
0,
|
||||||
23
|
23
|
||||||
],
|
],
|
||||||
"key": "Transform( -0.999568, 0, -0.0294008, 0, 1, 0, 0.0294008, 0, -0.999568, -118.67, 0.033226, -204.451 )",
|
"key": "road__center2_road__lot__9__left__lot-small1",
|
||||||
"xform": "Transform( -0.999568, 0, -0.0294008, 0, 1, 0, 0.0294008, 0, -0.999568, -118.67, -1.2499, -204.451 )",
|
"xform": "Transform( 0.201653, -2.65919e-07, 0.979457, 1.3187e-06, 1, 5.76422e-14, -0.979457, 1.29161e-06, 0.201653, -118.508, 0.000127158, -208.73 )",
|
||||||
"index": 1074
|
"index": 1074
|
||||||
},
|
},
|
||||||
"Transform( 0.212429, 0, 0.977176, 0, 1, 0, -0.977177, 0, 0.212429, -109.887, 0.0385437, -159.52 )": {
|
"road__center2_road__lot__6__left__lot-small1": {
|
||||||
"id": "residental-house7",
|
"id": "lot-small1",
|
||||||
"pattern_id": 924,
|
"pattern_id": 0,
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"residents": [
|
"residents": [
|
||||||
1693,
|
|
||||||
2594,
|
|
||||||
1204
|
|
||||||
],
|
],
|
||||||
"workers": [
|
"workers": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"guests": [
|
"guests": [
|
||||||
2006,
|
|
||||||
2396,
|
|
||||||
147,
|
|
||||||
2756,
|
|
||||||
1763,
|
|
||||||
2403,
|
|
||||||
377,
|
|
||||||
1825,
|
|
||||||
2400,
|
|
||||||
679,
|
|
||||||
574,
|
|
||||||
216,
|
|
||||||
541,
|
|
||||||
1240,
|
|
||||||
801,
|
|
||||||
202,
|
|
||||||
406,
|
|
||||||
2259,
|
|
||||||
1370,
|
|
||||||
2507,
|
|
||||||
2513,
|
|
||||||
567,
|
|
||||||
327,
|
|
||||||
2643,
|
|
||||||
743,
|
|
||||||
347,
|
|
||||||
1153,
|
|
||||||
968,
|
|
||||||
872,
|
|
||||||
2275,
|
|
||||||
622,
|
|
||||||
384,
|
|
||||||
2761,
|
|
||||||
813,
|
|
||||||
1137,
|
|
||||||
777,
|
|
||||||
2496,
|
|
||||||
315,
|
|
||||||
898
|
|
||||||
],
|
],
|
||||||
"worktime": [
|
"worktime": [
|
||||||
17,
|
0,
|
||||||
23
|
23
|
||||||
],
|
],
|
||||||
"key": "Transform( 0.212429, 0, 0.977176, 0, 1, 0, -0.977177, 0, 0.212429, -109.887, 0.0385437, -159.52 )",
|
"key": "road__center2_road__lot__6__left__lot-small1",
|
||||||
"xform": "Transform( 0.212429, 0, 0.977176, 0, 1, 0, -0.977177, 0, 0.212429, -109.887, -1.2499, -159.52 )",
|
"xform": "Transform( 0.28497, 0.000424686, 0.958536, -0.00149028, 0.999999, -6.51422e-11, -0.958535, -0.00142849, 0.28497, -147.72, 0.0204212, -93.7818 )",
|
||||||
"index": 1075
|
"index": 1075
|
||||||
},
|
},
|
||||||
"Transform( 0.212429, 0, 0.977176, 0, 1, 0, -0.977177, 0, 0.212429, -120.471, 0.0385437, -110.831 )": {
|
"road__center2_road__lot__9__right__lot-small1": {
|
||||||
"id": "residental-house8",
|
"id": "lot-small1",
|
||||||
"pattern_id": 926,
|
"pattern_id": 0,
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"residents": [
|
"residents": [
|
||||||
202,
|
|
||||||
1240,
|
|
||||||
567
|
|
||||||
],
|
],
|
||||||
"workers": [
|
"workers": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"guests": [
|
"guests": [
|
||||||
1825,
|
|
||||||
327,
|
|
||||||
678,
|
|
||||||
1814,
|
|
||||||
315,
|
|
||||||
384,
|
|
||||||
1204,
|
|
||||||
2594,
|
|
||||||
872,
|
|
||||||
2643,
|
|
||||||
2357,
|
|
||||||
2513,
|
|
||||||
597
|
|
||||||
],
|
],
|
||||||
"worktime": [
|
"worktime": [
|
||||||
19,
|
0,
|
||||||
23
|
23
|
||||||
],
|
],
|
||||||
"key": "Transform( 0.212429, 0, 0.977176, 0, 1, 0, -0.977177, 0, 0.212429, -120.471, 0.0385437, -110.831 )",
|
"key": "road__center2_road__lot__9__right__lot-small1",
|
||||||
"xform": "Transform( 0.212429, 0, 0.977176, 0, 1, 0, -0.977177, 0, 0.212429, -120.471, -1.2499, -110.831 )",
|
"xform": "Transform( -0.201653, -2.6592e-07, -0.979457, -1.3187e-06, 1, 5.76422e-14, 0.979457, 1.29161e-06, -0.201653, -15.9816, 0.000144301, -200.894 )",
|
||||||
"index": 1076
|
"index": 1076
|
||||||
},
|
},
|
||||||
"Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -168.894, 0.0385437, -90 )": {
|
"road__center2_road__lot__7__left__lot-small1": {
|
||||||
"id": "residental-house9",
|
"id": "lot-small1",
|
||||||
"pattern_id": 927,
|
"pattern_id": 0,
|
||||||
"generated": true,
|
"generated": true,
|
||||||
"residents": [
|
"residents": [
|
||||||
2006,
|
|
||||||
1137,
|
|
||||||
2643
|
|
||||||
],
|
],
|
||||||
"workers": [
|
"workers": [
|
||||||
|
|
||||||
],
|
],
|
||||||
"guests": [
|
"guests": [
|
||||||
678,
|
|
||||||
597,
|
|
||||||
1397,
|
|
||||||
406,
|
|
||||||
2120,
|
|
||||||
801,
|
|
||||||
2761,
|
|
||||||
2275,
|
|
||||||
613,
|
|
||||||
2396,
|
|
||||||
327,
|
|
||||||
1105,
|
|
||||||
1431,
|
|
||||||
1240,
|
|
||||||
2422,
|
|
||||||
384
|
|
||||||
],
|
],
|
||||||
"worktime": [
|
"worktime": [
|
||||||
19,
|
0,
|
||||||
23
|
23
|
||||||
],
|
],
|
||||||
"key": "Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -168.894, 0.0385437, -90 )",
|
"key": "road__center2_road__lot__7__left__lot-small1",
|
||||||
"xform": "Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -168.894, -1.2499, -90 )",
|
"xform": "Transform( 0.274721, 2.879e-07, 0.961524, -1.04797e-06, 1, -4.58082e-14, -0.961524, -1.00765e-06, 0.274721, -137.269, 0.000130581, -126.203 )",
|
||||||
"index": 1077
|
"index": 1077
|
||||||
},
|
},
|
||||||
"Transform( -0.090538, 0, -0.995893, 0, 1, 0, 0.995893, 0, -0.090538, -423.417, 0.0248413, -107.418 )": {
|
"Transform( -0.090538, 0, -0.995893, 0, 1, 0, 0.995893, 0, -0.090538, -423.417, 0.0248413, -107.418 )": {
|
||||||
@@ -47329,5 +47138,131 @@
|
|||||||
"key": "bb21324a6e670f9e",
|
"key": "bb21324a6e670f9e",
|
||||||
"xform": "Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 50, -1.2499, 34 )",
|
"xform": "Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 50, -1.2499, 34 )",
|
||||||
"index": 1452
|
"index": 1452
|
||||||
|
},
|
||||||
|
"road__center2_road__transit_stop__0__0__left__bus-stop": {
|
||||||
|
"id": "bus-stop",
|
||||||
|
"pattern_id": 0,
|
||||||
|
"generated": true,
|
||||||
|
"residents": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"guests": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"worktime": [
|
||||||
|
0,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"key": "road__center2_road__transit_stop__0__0__left__bus-stop",
|
||||||
|
"xform": "Transform( -0.074558, -1.44516e-05, -0.997217, -0.00019383, 1, -8.47259e-12, 0.997217, 0.000193291, -0.0745581, -1107.74, 0.0113351, -194.692 )",
|
||||||
|
"index": 1453
|
||||||
|
},
|
||||||
|
"road__center2_road__lot__7__right__0__building-residental-house1": {
|
||||||
|
"id": "residental-house1",
|
||||||
|
"pattern_id": 0,
|
||||||
|
"generated": true,
|
||||||
|
"residents": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"guests": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"worktime": [
|
||||||
|
0,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"key": "road__center2_road__lot__7__right__0__building-residental-house1",
|
||||||
|
"xform": "Transform( -0.961524, 2.87899e-07, 0.274721, -9.16164e-14, 1, -1.04797e-06, -0.274721, -1.00765e-06, -0.961524, -37.119, 0.000116433, -111.629 )",
|
||||||
|
"index": 1454
|
||||||
|
},
|
||||||
|
"road__center2_road__transit_stop__7__0__left__bus-stop": {
|
||||||
|
"id": "bus-stop",
|
||||||
|
"pattern_id": 0,
|
||||||
|
"generated": true,
|
||||||
|
"residents": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"guests": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"worktime": [
|
||||||
|
0,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"key": "road__center2_road__transit_stop__7__0__left__bus-stop",
|
||||||
|
"xform": "Transform( -0.274721, 2.87899e-07, -0.961524, 1.04797e-06, 1, -4.58082e-14, 0.961524, -1.00765e-06, -0.274721, -93.3132, 0.000131629, -112.604 )",
|
||||||
|
"index": 1455
|
||||||
|
},
|
||||||
|
"road__center2_road__lot__8__left__lot-small1": {
|
||||||
|
"id": "lot-small1",
|
||||||
|
"pattern_id": 0,
|
||||||
|
"generated": true,
|
||||||
|
"residents": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"guests": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"worktime": [
|
||||||
|
0,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"key": "road__center2_road__lot__8__left__lot-small1",
|
||||||
|
"xform": "Transform( 0.20601, 8.09512e-08, 0.97855, -3.92947e-07, 1, -1.71763e-14, -0.97855, -3.84518e-07, 0.20601, -128.352, 9.81672e-05, -166.241 )",
|
||||||
|
"index": 1456
|
||||||
|
},
|
||||||
|
"road__center2_road__lot__8__right__lot-small1": {
|
||||||
|
"id": "lot-small1",
|
||||||
|
"pattern_id": 0,
|
||||||
|
"generated": true,
|
||||||
|
"residents": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"guests": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"worktime": [
|
||||||
|
0,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"key": "road__center2_road__lot__8__right__lot-small1",
|
||||||
|
"xform": "Transform( -0.20601, 8.09512e-08, -0.97855, 3.92947e-07, 1, -1.71763e-14, 0.97855, -3.84518e-07, -0.206011, -27.5772, 9.50236e-05, -153.2 )",
|
||||||
|
"index": 1457
|
||||||
|
},
|
||||||
|
"road__center2_road__lot__8__right__0__building-residental-house2": {
|
||||||
|
"id": "residental-house2",
|
||||||
|
"pattern_id": 0,
|
||||||
|
"generated": true,
|
||||||
|
"residents": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"workers": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"guests": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"worktime": [
|
||||||
|
0,
|
||||||
|
23
|
||||||
|
],
|
||||||
|
"key": "road__center2_road__lot__8__right__0__building-residental-house2",
|
||||||
|
"xform": "Transform( -0.97855, 8.09512e-08, 0.206011, -3.43525e-14, 1, -3.92947e-07, -0.206011, -3.84518e-07, -0.97855, -17.5342, 9.26659e-05, -157.217 )",
|
||||||
|
"index": 1458
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"asset":{
|
"asset":{
|
||||||
"generator":"Khronos glTF Blender I/O v3.6.27",
|
"generator":"Khronos glTF Blender I/O v3.6.28",
|
||||||
"version":"2.0"
|
"version":"2.0"
|
||||||
},
|
},
|
||||||
"extensionsUsed":[
|
"extensionsUsed":[
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
{
|
{
|
||||||
"bufferView":0,
|
"bufferView":0,
|
||||||
"componentType":5126,
|
"componentType":5126,
|
||||||
"count":430,
|
"count":407,
|
||||||
"max":[
|
"max":[
|
||||||
7.011116981506348,
|
7.011116981506348,
|
||||||
5.200000286102295,
|
5.200000286102295,
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
],
|
],
|
||||||
"min":[
|
"min":[
|
||||||
-7.011116981506348,
|
-7.011116981506348,
|
||||||
-0.005541202612221241,
|
0,
|
||||||
-0.9000000357627869
|
-0.9000000357627869
|
||||||
],
|
],
|
||||||
"type":"VEC3"
|
"type":"VEC3"
|
||||||
@@ -96,45 +96,45 @@
|
|||||||
{
|
{
|
||||||
"bufferView":1,
|
"bufferView":1,
|
||||||
"componentType":5126,
|
"componentType":5126,
|
||||||
"count":430,
|
"count":407,
|
||||||
"type":"VEC3"
|
"type":"VEC3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bufferView":2,
|
"bufferView":2,
|
||||||
"componentType":5126,
|
"componentType":5126,
|
||||||
"count":430,
|
"count":407,
|
||||||
"type":"VEC2"
|
"type":"VEC2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bufferView":3,
|
"bufferView":3,
|
||||||
"componentType":5123,
|
"componentType":5123,
|
||||||
"count":1776,
|
"count":1662,
|
||||||
"type":"SCALAR"
|
"type":"SCALAR"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bufferViews":[
|
"bufferViews":[
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":5160,
|
"byteLength":4884,
|
||||||
"byteOffset":0,
|
"byteOffset":0,
|
||||||
"target":34962
|
"target":34962
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":5160,
|
"byteLength":4884,
|
||||||
"byteOffset":5160,
|
"byteOffset":4884,
|
||||||
"target":34962
|
"target":34962
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":3440,
|
"byteLength":3256,
|
||||||
"byteOffset":10320,
|
"byteOffset":9768,
|
||||||
"target":34962
|
"target":34962
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"buffer":0,
|
"buffer":0,
|
||||||
"byteLength":3552,
|
"byteLength":3324,
|
||||||
"byteOffset":13760,
|
"byteOffset":13024,
|
||||||
"target":34963
|
"target":34963
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
],
|
],
|
||||||
"buffers":[
|
"buffers":[
|
||||||
{
|
{
|
||||||
"byteLength":17312,
|
"byteLength":16348,
|
||||||
"uri":"bus-stop.bin"
|
"uri":"bus-stop.bin"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
BIN
godot/astream/terrain/details/lot-small1.bin
Normal file
BIN
godot/astream/terrain/details/lot-small1.bin
Normal file
Binary file not shown.
153
godot/astream/terrain/details/lot-small1.gltf
Normal file
153
godot/astream/terrain/details/lot-small1.gltf
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v3.6.28",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"extensionsUsed":[
|
||||||
|
"KHR_materials_specular",
|
||||||
|
"KHR_materials_ior"
|
||||||
|
],
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"terrain-col"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"alphaCutoff":0.5,
|
||||||
|
"alphaMode":"MASK",
|
||||||
|
"extensions":{
|
||||||
|
"KHR_materials_specular":{
|
||||||
|
"specularColorFactor":[
|
||||||
|
0.474271529955476,
|
||||||
|
0.474271529955476,
|
||||||
|
0.474271529955476
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"KHR_materials_ior":{
|
||||||
|
"ior":1.4500000476837158
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name":"material_atlas_36953_1",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Plane",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"NORMAL":1,
|
||||||
|
"TEXCOORD_0":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"Atlas_36953",
|
||||||
|
"uri":"Atlas_36953.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":330,
|
||||||
|
"max":[
|
||||||
|
28.415786743164062,
|
||||||
|
0.01780128851532936,
|
||||||
|
44.232872009277344
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-28.410146713256836,
|
||||||
|
-4.802618026733398,
|
||||||
|
-39.0701789855957
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":330,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":330,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":492,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":3960,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":3960,
|
||||||
|
"byteOffset":3960,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":2640,
|
||||||
|
"byteOffset":7920,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":984,
|
||||||
|
"byteOffset":10560,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9729,
|
||||||
|
"minFilter":9987
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":11544,
|
||||||
|
"uri":"lot-small1.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1066
godot/astream/terrain/details/lot-small1.gltf.import
Normal file
1066
godot/astream/terrain/details/lot-small1.gltf.import
Normal file
File diff suppressed because it is too large
Load Diff
5
godot/astream/terrain/details/lot-small1.tscn
Normal file
5
godot/astream/terrain/details/lot-small1.tscn
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://astream/terrain/details/lot-small1.gltf" type="PackedScene" id=1]
|
||||||
|
|
||||||
|
[node name="lot-small1" instance=ExtResource( 1 )]
|
||||||
BIN
godot/astream/terrain/details/sideroad-short1.bin
Normal file
BIN
godot/astream/terrain/details/sideroad-short1.bin
Normal file
Binary file not shown.
153
godot/astream/terrain/details/sideroad-short1.gltf
Normal file
153
godot/astream/terrain/details/sideroad-short1.gltf
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
{
|
||||||
|
"asset":{
|
||||||
|
"generator":"Khronos glTF Blender I/O v3.6.28",
|
||||||
|
"version":"2.0"
|
||||||
|
},
|
||||||
|
"extensionsUsed":[
|
||||||
|
"KHR_materials_specular",
|
||||||
|
"KHR_materials_ior"
|
||||||
|
],
|
||||||
|
"scene":0,
|
||||||
|
"scenes":[
|
||||||
|
{
|
||||||
|
"name":"Scene",
|
||||||
|
"nodes":[
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nodes":[
|
||||||
|
{
|
||||||
|
"mesh":0,
|
||||||
|
"name":"terrain-col"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"materials":[
|
||||||
|
{
|
||||||
|
"alphaCutoff":0.5,
|
||||||
|
"alphaMode":"MASK",
|
||||||
|
"extensions":{
|
||||||
|
"KHR_materials_specular":{
|
||||||
|
"specularColorFactor":[
|
||||||
|
0.474271529955476,
|
||||||
|
0.474271529955476,
|
||||||
|
0.474271529955476
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"KHR_materials_ior":{
|
||||||
|
"ior":1.4500000476837158
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name":"material_atlas_36953_1",
|
||||||
|
"pbrMetallicRoughness":{
|
||||||
|
"baseColorTexture":{
|
||||||
|
"index":0
|
||||||
|
},
|
||||||
|
"metallicFactor":0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meshes":[
|
||||||
|
{
|
||||||
|
"name":"Plane",
|
||||||
|
"primitives":[
|
||||||
|
{
|
||||||
|
"attributes":{
|
||||||
|
"POSITION":0,
|
||||||
|
"NORMAL":1,
|
||||||
|
"TEXCOORD_0":2
|
||||||
|
},
|
||||||
|
"indices":3,
|
||||||
|
"material":0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"textures":[
|
||||||
|
{
|
||||||
|
"sampler":0,
|
||||||
|
"source":0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"images":[
|
||||||
|
{
|
||||||
|
"mimeType":"image/png",
|
||||||
|
"name":"Atlas_36953",
|
||||||
|
"uri":"Atlas_36953.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"accessors":[
|
||||||
|
{
|
||||||
|
"bufferView":0,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":778,
|
||||||
|
"max":[
|
||||||
|
15.457839012145996,
|
||||||
|
0.18514837324619293,
|
||||||
|
13.391965866088867
|
||||||
|
],
|
||||||
|
"min":[
|
||||||
|
-15.484124183654785,
|
||||||
|
-3.5783910751342773,
|
||||||
|
-13.159601211547852
|
||||||
|
],
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":1,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":778,
|
||||||
|
"type":"VEC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":2,
|
||||||
|
"componentType":5126,
|
||||||
|
"count":778,
|
||||||
|
"type":"VEC2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bufferView":3,
|
||||||
|
"componentType":5123,
|
||||||
|
"count":1176,
|
||||||
|
"type":"SCALAR"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bufferViews":[
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":9336,
|
||||||
|
"byteOffset":0,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":9336,
|
||||||
|
"byteOffset":9336,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":6224,
|
||||||
|
"byteOffset":18672,
|
||||||
|
"target":34962
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"buffer":0,
|
||||||
|
"byteLength":2352,
|
||||||
|
"byteOffset":24896,
|
||||||
|
"target":34963
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"samplers":[
|
||||||
|
{
|
||||||
|
"magFilter":9729,
|
||||||
|
"minFilter":9987
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buffers":[
|
||||||
|
{
|
||||||
|
"byteLength":27248,
|
||||||
|
"uri":"sideroad-short1.bin"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1066
godot/astream/terrain/details/sideroad-short1.gltf.import
Normal file
1066
godot/astream/terrain/details/sideroad-short1.gltf.import
Normal file
File diff suppressed because it is too large
Load Diff
5
godot/astream/terrain/details/sideroad-short1.tscn
Normal file
5
godot/astream/terrain/details/sideroad-short1.tscn
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[gd_scene load_steps=2 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://astream/terrain/details/sideroad-short1.gltf" type="PackedScene" id=1]
|
||||||
|
|
||||||
|
[node name="sideroad-short1" instance=ExtResource( 1 )]
|
||||||
@@ -37,6 +37,8 @@ building_data = {
|
|||||||
"foundation30": "res://astream/terrain/details/foundation30.tscn",
|
"foundation30": "res://astream/terrain/details/foundation30.tscn",
|
||||||
"foundation60": "res://astream/terrain/details/foundation60.tscn",
|
"foundation60": "res://astream/terrain/details/foundation60.tscn",
|
||||||
"bus-stop": "res://astream/terrain/details/bus-stop.tscn",
|
"bus-stop": "res://astream/terrain/details/bus-stop.tscn",
|
||||||
|
"lot-small1": "res://astream/terrain/details/lot-small1.tscn",
|
||||||
|
"sideroad-short1": "res://astream/terrain/details/sideroad-short1.tscn",
|
||||||
}
|
}
|
||||||
buildings_path = "res://astream/buildings.json"
|
buildings_path = "res://astream/buildings.json"
|
||||||
[world]
|
[world]
|
||||||
@@ -58,3 +60,11 @@ gen_prefixes = ["empty", "foundation30", "foundation60", "sideroad-start",
|
|||||||
"business-store",
|
"business-store",
|
||||||
"business-bar", "business-cafe", "empty", "bus-stop"
|
"business-bar", "business-cafe", "empty", "bus-stop"
|
||||||
]
|
]
|
||||||
|
[lines/edges/default/left]
|
||||||
|
lot_offset = 33.8
|
||||||
|
lot_y_rotation = -90.0
|
||||||
|
|
||||||
|
[lines/edges/default/right]
|
||||||
|
lot_offset = 33.8
|
||||||
|
lot_y_rotation = 90.0
|
||||||
|
|
||||||
|
|||||||
@@ -129,6 +129,11 @@ bool BuildingsData::has_building(const String &key)
|
|||||||
{
|
{
|
||||||
String ename = "base:" + key;
|
String ename = "base:" + key;
|
||||||
flecs::entity e = lookup(ename.ascii().ptr());
|
flecs::entity e = lookup(ename.ascii().ptr());
|
||||||
|
if (!e.is_valid())
|
||||||
|
print_line("no key: " + key);
|
||||||
|
else
|
||||||
|
print_line("has building with parent: " +
|
||||||
|
String(e.parent().name()));
|
||||||
return e.is_valid();
|
return e.is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,12 +142,12 @@ String BuildingsData::get_closest_building(const Transform &xform)
|
|||||||
float dst = Math_INF;
|
float dst = Math_INF;
|
||||||
String rkey;
|
String rkey;
|
||||||
// int id = -1;
|
// int id = -1;
|
||||||
ecs().each(
|
ecs().each([xform, &rkey, &dst](flecs::entity e,
|
||||||
[xform, &rkey, &dst](flecs::entity e, const CBuildingData &d) {
|
const CBuildingData &d) {
|
||||||
Vector3 o = xform.origin;
|
Vector3 o = xform.origin;
|
||||||
Vector3 m = d.building.xform.origin;
|
Vector3 m = d.building.xform.origin;
|
||||||
float mdst = o.distance_squared_to(m);
|
float mdst = o.distance_squared_to(m);
|
||||||
if (dst > mdst) {
|
if (dst > mdst && !d.building.key.begins_with("road__")) {
|
||||||
dst = mdst;
|
dst = mdst;
|
||||||
rkey = d.building.key;
|
rkey = d.building.key;
|
||||||
}
|
}
|
||||||
@@ -176,6 +181,7 @@ void BuildingsData::read_buildings_json(const String &buildings_path)
|
|||||||
while (e) {
|
while (e) {
|
||||||
struct building b;
|
struct building b;
|
||||||
String key = e->get();
|
String key = e->get();
|
||||||
|
if (!key.begins_with("road::")) {
|
||||||
Dictionary entry = json[key];
|
Dictionary entry = json[key];
|
||||||
String id = entry.get("id", "empty");
|
String id = entry.get("id", "empty");
|
||||||
if (id == "empty") {
|
if (id == "empty") {
|
||||||
@@ -189,6 +195,7 @@ void BuildingsData::read_buildings_json(const String &buildings_path)
|
|||||||
create_building(entry);
|
create_building(entry);
|
||||||
// building::from_dict(&b, json[key]);
|
// building::from_dict(&b, json[key]);
|
||||||
// buildings_.push_back(b);
|
// buildings_.push_back(b);
|
||||||
|
}
|
||||||
e = e->next();
|
e = e->next();
|
||||||
}
|
}
|
||||||
filter_generated_stuff();
|
filter_generated_stuff();
|
||||||
@@ -208,10 +215,13 @@ void BuildingsData::save_buildings_json(const String &buildings_path)
|
|||||||
int index = 0;
|
int index = 0;
|
||||||
ecs().each([&index, &json](const CBuildingData &b) {
|
ecs().each([&index, &json](const CBuildingData &b) {
|
||||||
String key = b.building.key;
|
String key = b.building.key;
|
||||||
|
/* do not save roadside generated stuff */
|
||||||
|
if (!key.begins_with("road::")) {
|
||||||
Dictionary dict = b.building.to_dict();
|
Dictionary dict = b.building.to_dict();
|
||||||
dict["index"] = index;
|
dict["index"] = index;
|
||||||
json[key] = dict;
|
json[key] = dict;
|
||||||
index++;
|
index++;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
String json_string = JSON::print(json, "\t", false);
|
String json_string = JSON::print(json, "\t", false);
|
||||||
fa = FileAccess::open(store_path, FileAccess::WRITE);
|
fa = FileAccess::open(store_path, FileAccess::WRITE);
|
||||||
@@ -452,6 +462,21 @@ bool BuildingsData::has_scene(const String &key) const
|
|||||||
void BuildingsData::remove_scene_item(const String &key, const String &bkey)
|
void BuildingsData::remove_scene_item(const String &key, const String &bkey)
|
||||||
{
|
{
|
||||||
flecs::entity e = ecs().lookup(key.ascii().ptr());
|
flecs::entity e = ecs().lookup(key.ascii().ptr());
|
||||||
|
if (!e.is_valid()) {
|
||||||
|
print_error("bad scene: " + key);
|
||||||
|
flecs::query_builder<const CBuildingInstance> qb =
|
||||||
|
ecs().query_builder<const CBuildingInstance>();
|
||||||
|
flecs::query<const CBuildingInstance> q = qb.build();
|
||||||
|
uint64_t key_hash = bkey.hash64();
|
||||||
|
flecs::entity em =
|
||||||
|
q.find([key_hash](const CBuildingInstance &bi) {
|
||||||
|
return bi.key.hash64() == key_hash;
|
||||||
|
});
|
||||||
|
if (em.is_valid())
|
||||||
|
em.destruct();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
{
|
||||||
assert(e.is_valid());
|
assert(e.is_valid());
|
||||||
CSceneData *d = e.get_mut<CSceneData>();
|
CSceneData *d = e.get_mut<CSceneData>();
|
||||||
assert(d);
|
assert(d);
|
||||||
@@ -460,13 +485,16 @@ void BuildingsData::remove_scene_item(const String &key, const String &bkey)
|
|||||||
flecs::ChildOf, e);
|
flecs::ChildOf, e);
|
||||||
flecs::query<const CBuildingInstance> q = qb.build();
|
flecs::query<const CBuildingInstance> q = qb.build();
|
||||||
uint64_t key_hash = bkey.hash64();
|
uint64_t key_hash = bkey.hash64();
|
||||||
flecs::entity em = q.find([key_hash](const CBuildingInstance &bi) {
|
flecs::entity em =
|
||||||
|
q.find([key_hash](const CBuildingInstance &bi) {
|
||||||
return bi.key.hash64() == key_hash;
|
return bi.key.hash64() == key_hash;
|
||||||
});
|
});
|
||||||
if (em.is_valid())
|
if (em.is_valid())
|
||||||
em.destruct();
|
em.destruct();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: create buildings on top of their root node
|
||||||
void BuildingsData::add_scene_item(const String &key, const String &bkey)
|
void BuildingsData::add_scene_item(const String &key, const String &bkey)
|
||||||
{
|
{
|
||||||
flecs::entity e = ecs().lookup(key.ascii().ptr());
|
flecs::entity e = ecs().lookup(key.ascii().ptr());
|
||||||
@@ -474,11 +502,11 @@ void BuildingsData::add_scene_item(const String &key, const String &bkey)
|
|||||||
CSceneData *d = e.get_mut<CSceneData>();
|
CSceneData *d = e.get_mut<CSceneData>();
|
||||||
assert(d);
|
assert(d);
|
||||||
String ename = "bi:" + bkey;
|
String ename = "bi:" + bkey;
|
||||||
|
print_line("creating entity: " + ename + " on top of: " + key);
|
||||||
flecs::entity ce = e.lookup(ename.ascii().ptr());
|
flecs::entity ce = e.lookup(ename.ascii().ptr());
|
||||||
if (ce.is_valid())
|
if (ce.is_valid())
|
||||||
ce.destruct();
|
ce.destruct();
|
||||||
ce = ecs().entity(ename.ascii().ptr());
|
ce = ecs().entity(ename.ascii().ptr()).child_of(e);
|
||||||
ce.child_of(e);
|
|
||||||
ce.set<CBuildingInstance>({ bkey, nullptr });
|
ce.set<CBuildingInstance>({ bkey, nullptr });
|
||||||
print_line("child name: " + String(ce.name()));
|
print_line("child name: " + String(ce.name()));
|
||||||
}
|
}
|
||||||
@@ -488,11 +516,13 @@ void BuildingsData::create_scene_data(const String &key, const String &bkey)
|
|||||||
if (!has_scene(key)) {
|
if (!has_scene(key)) {
|
||||||
flecs::entity e = ecs().entity(key.ascii().ptr());
|
flecs::entity e = ecs().entity(key.ascii().ptr());
|
||||||
String path = building_data[key];
|
String path = building_data[key];
|
||||||
|
assert(path.length() > 5);
|
||||||
print_line("Requesting " + (bkey) + " " + path);
|
print_line("Requesting " + (bkey) + " " + path);
|
||||||
struct scene_data sd;
|
struct scene_data sd;
|
||||||
sd.path = path;
|
sd.path = path;
|
||||||
sd.loader = ResourceLoader::load_interactive(
|
sd.loader = ResourceLoader::load_interactive(
|
||||||
path, "PackedScene", true);
|
path, "PackedScene", true);
|
||||||
|
assert(sd.loader.is_valid());
|
||||||
e.set<CSceneData>({ sd });
|
e.set<CSceneData>({ sd });
|
||||||
assert(e.get_mut<CSceneData>());
|
assert(e.get_mut<CSceneData>());
|
||||||
String ename = "bi:" + bkey;
|
String ename = "bi:" + bkey;
|
||||||
@@ -633,8 +663,9 @@ Error BuildingsData::scene_loader_poll(const String &key)
|
|||||||
assert(e.is_valid());
|
assert(e.is_valid());
|
||||||
CSceneData *d = e.get_mut<CSceneData>();
|
CSceneData *d = e.get_mut<CSceneData>();
|
||||||
assert(d);
|
assert(d);
|
||||||
|
assert(d->sd.loader.is_valid());
|
||||||
Error err = d->sd.loader->poll();
|
Error err = d->sd.loader->poll();
|
||||||
if (err == ERR_FILE_EOF) {
|
if (err == ERR_FILE_EOF || err == OK) {
|
||||||
Ref<PackedScene> sc = d->sd.loader->get_resource();
|
Ref<PackedScene> sc = d->sd.loader->get_resource();
|
||||||
d->sd.packed_scene = sc;
|
d->sd.packed_scene = sc;
|
||||||
print_line("Loaded scene: " + d->sd.path + " OK");
|
print_line("Loaded scene: " + d->sd.path + " OK");
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <core/io/config_file.h>
|
#include <core/io/config_file.h>
|
||||||
#include <core/io/json.h>
|
#include <core/io/json.h>
|
||||||
|
#include <core/io/marshalls.h>
|
||||||
#include <core/os/dir_access.h>
|
#include <core/os/dir_access.h>
|
||||||
#include <core/os/time.h>
|
#include <core/os/time.h>
|
||||||
#include <core/math/geometry.h>
|
#include <core/math/geometry.h>
|
||||||
@@ -42,6 +43,8 @@ public:
|
|||||||
{
|
{
|
||||||
String ename = "line:" + key;
|
String ename = "line:" + key;
|
||||||
flecs::entity e = get().lookup(ename.ascii().ptr());
|
flecs::entity e = get().lookup(ename.ascii().ptr());
|
||||||
|
if (!e.is_valid())
|
||||||
|
print_line("can't find: " + key);
|
||||||
assert(e.is_valid());
|
assert(e.is_valid());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -90,6 +93,9 @@ public:
|
|||||||
{
|
{
|
||||||
flecs::entity e = lookup_create(key);
|
flecs::entity e = lookup_create(key);
|
||||||
e.set<CLine>({ line });
|
e.set<CLine>({ line });
|
||||||
|
CLine *cl = e.get_mut<CLine>();
|
||||||
|
if (cl->line.edges.size() != cl->line.points.size() - 1)
|
||||||
|
cl->line.edges.resize(cl->line.points.size() - 1);
|
||||||
}
|
}
|
||||||
inline void insert_line_point(const String &key, int index,
|
inline void insert_line_point(const String &key, int index,
|
||||||
const Transform &xform)
|
const Transform &xform)
|
||||||
@@ -97,12 +103,16 @@ public:
|
|||||||
flecs::entity e = lookup(key);
|
flecs::entity e = lookup(key);
|
||||||
struct CLine *cl = e.get_mut<CLine>();
|
struct CLine *cl = e.get_mut<CLine>();
|
||||||
cl->line.points.insert(cl->line.points.begin() + index, xform);
|
cl->line.points.insert(cl->line.points.begin() + index, xform);
|
||||||
|
if (cl->line.edges.size() != cl->line.points.size() - 1)
|
||||||
|
cl->line.edges.resize(cl->line.points.size() - 1);
|
||||||
}
|
}
|
||||||
inline void erase_line_point(const String &key, int index)
|
inline void erase_line_point(const String &key, int index)
|
||||||
{
|
{
|
||||||
flecs::entity e = lookup(key);
|
flecs::entity e = lookup(key);
|
||||||
struct CLine *cl = e.get_mut<CLine>();
|
struct CLine *cl = e.get_mut<CLine>();
|
||||||
cl->line.points.erase(cl->line.points.begin() + index);
|
cl->line.points.erase(cl->line.points.begin() + index);
|
||||||
|
if (cl->line.edges.size() != cl->line.points.size() - 1)
|
||||||
|
cl->line.edges.resize(cl->line.points.size() - 1);
|
||||||
}
|
}
|
||||||
inline void set_line_point_position(const String &key, int index,
|
inline void set_line_point_position(const String &key, int index,
|
||||||
const Vector3 &position)
|
const Vector3 &position)
|
||||||
@@ -175,21 +185,6 @@ public:
|
|||||||
offset += segment.length;
|
offset += segment.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void line_add_building(const String &key, const String &bkey,
|
|
||||||
float curve_offset, float normal_offset,
|
|
||||||
float y_rotation, float y_offset)
|
|
||||||
{
|
|
||||||
flecs::entity e = lookup(key);
|
|
||||||
struct CLine *cl = e.get_mut<CLine>();
|
|
||||||
struct RoadLinesData::line_building_data lb;
|
|
||||||
lb.building_key = bkey;
|
|
||||||
lb.building_key_hash = bkey.hash64();
|
|
||||||
lb.line_offset = curve_offset;
|
|
||||||
lb.normal_offset = normal_offset;
|
|
||||||
lb.y_rotation = y_rotation;
|
|
||||||
lb.y_offset = y_offset;
|
|
||||||
cl->line.buildings.push_back(lb);
|
|
||||||
}
|
|
||||||
void set_line_metadata(const String &key, const Dictionary &metadata)
|
void set_line_metadata(const String &key, const Dictionary &metadata)
|
||||||
{
|
{
|
||||||
flecs::entity e = lookup(key);
|
flecs::entity e = lookup(key);
|
||||||
@@ -364,27 +359,26 @@ void RoadLinesData::load_data()
|
|||||||
Dictionary entry = json.get(key, Dictionary());
|
Dictionary entry = json.get(key, Dictionary());
|
||||||
Array points = entry.get("points", Array());
|
Array points = entry.get("points", Array());
|
||||||
Array indices = entry.get("indices", Array());
|
Array indices = entry.get("indices", Array());
|
||||||
|
Array edges = entry.get("edges", Array());
|
||||||
rline.metadata = entry.get("metadata", Dictionary());
|
rline.metadata = entry.get("metadata", Dictionary());
|
||||||
int lanes = entry.get("lanes", -1);
|
int lanes = entry.get("lanes", -1);
|
||||||
int pattern = entry.get("pattern", -1);
|
int pattern = entry.get("pattern", -1);
|
||||||
rline.pattern = pattern;
|
rline.pattern = pattern;
|
||||||
rline.points.resize(points.size());
|
rline.points.resize(points.size());
|
||||||
|
rline.edges.resize(edges.size());
|
||||||
rline.indices.resize(indices.size());
|
rline.indices.resize(indices.size());
|
||||||
for (i = 0; i < (int)points.size(); i++) {
|
for (i = 0; i < (int)points.size(); i++) {
|
||||||
String point_s = points[i];
|
String point_s = points[i];
|
||||||
rline.points[i] = from_string<Transform>(point_s);
|
rline.points[i] = from_string<Transform>(point_s);
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < (int)edges.size(); i++) {
|
||||||
|
const Dictionary &d = edges[i];
|
||||||
|
rline.edges[i].from_dict(rline.edges[i], d);
|
||||||
|
}
|
||||||
for (i = 0; i < (int)indices.size(); i++) {
|
for (i = 0; i < (int)indices.size(); i++) {
|
||||||
int index = indices[i];
|
int index = indices[i];
|
||||||
rline.indices[i] = index;
|
rline.indices[i] = index;
|
||||||
}
|
}
|
||||||
Array buildings = entry.get("buildings", Array());
|
|
||||||
rline.buildings.resize(buildings.size());
|
|
||||||
for (i = 0; i < (int)buildings.size(); i++) {
|
|
||||||
struct line_building_data b;
|
|
||||||
line_building_data::from_dict(&b, buildings[i]);
|
|
||||||
rline.buildings.push_back(b);
|
|
||||||
}
|
|
||||||
// TODO: wtf is flags?
|
// TODO: wtf is flags?
|
||||||
rline.lanes = lanes;
|
rline.lanes = lanes;
|
||||||
set_line(key, rline);
|
set_line(key, rline);
|
||||||
@@ -401,6 +395,7 @@ void RoadLinesData::save_data()
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
ConfigFile config;
|
ConfigFile config;
|
||||||
|
ConfigFile line_data;
|
||||||
Error result = config.load("res://config/stream.conf");
|
Error result = config.load("res://config/stream.conf");
|
||||||
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
ERR_FAIL_COND_MSG(result != OK, "Failed to load config");
|
||||||
String road_lines_path = config.get_value("road", "road_lines_path");
|
String road_lines_path = config.get_value("road", "road_lines_path");
|
||||||
@@ -412,27 +407,26 @@ void RoadLinesData::save_data()
|
|||||||
List<String>::Element *e = keys.front();
|
List<String>::Element *e = keys.front();
|
||||||
while (e) {
|
while (e) {
|
||||||
Dictionary pvalues;
|
Dictionary pvalues;
|
||||||
Array points, indices;
|
Array points, edges, indices;
|
||||||
points.resize(lines(e->get()).points.size());
|
points.resize(lines(e->get()).points.size());
|
||||||
|
edges.resize(lines(e->get()).edges.size());
|
||||||
for (i = 0; i < (int)lines(e->get()).points.size(); i++)
|
for (i = 0; i < (int)lines(e->get()).points.size(); i++)
|
||||||
points[i] = to_string(lines(e->get()).points[i]);
|
points[i] = to_string(lines(e->get()).points[i]);
|
||||||
|
for (i = 0; i < (int)lines(e->get()).edges.size(); i++)
|
||||||
|
edges[i] = lines(e->get()).edges[i].to_dict();
|
||||||
indices.resize(lines(e->get()).indices.size());
|
indices.resize(lines(e->get()).indices.size());
|
||||||
for (i = 0; i < (int)lines(e->get()).indices.size(); i++)
|
for (i = 0; i < (int)lines(e->get()).indices.size(); i++)
|
||||||
indices[i] = lines(e->get()).indices[i];
|
indices[i] = lines(e->get()).indices[i];
|
||||||
pvalues["points"] = points;
|
pvalues["points"] = points;
|
||||||
|
pvalues["edges"] = edges;
|
||||||
// pvalues["indices"] = indices;
|
// pvalues["indices"] = indices;
|
||||||
pvalues["metadata"] = lines(e->get()).metadata;
|
pvalues["metadata"] = lines(e->get()).metadata;
|
||||||
pvalues["lanes"] = lines(e->get()).lanes;
|
pvalues["lanes"] = lines(e->get()).lanes;
|
||||||
pvalues["pattern"] = ::lines[e->get()].pattern;
|
pvalues["pattern"] = ::lines[e->get()].pattern;
|
||||||
Array buildings;
|
|
||||||
for (i = 0; i < (int)::lines[e->get()].buildings.size(); i++)
|
|
||||||
buildings.push_back(
|
|
||||||
::lines[e->get()].buildings[i].to_dict());
|
|
||||||
pvalues["buildings"] = buildings;
|
|
||||||
output[e->get()] = pvalues;
|
output[e->get()] = pvalues;
|
||||||
e = e->next();
|
e = e->next();
|
||||||
}
|
}
|
||||||
print_verbose(JSON::print(output, "\t", false));
|
// print_verbose(JSON::print(output, "\t", false));
|
||||||
Error err = OK;
|
Error err = OK;
|
||||||
if (FileAccess::exists(road_lines_path)) {
|
if (FileAccess::exists(road_lines_path)) {
|
||||||
DirAccess *dir = DirAccess::open("res:///", &err);
|
DirAccess *dir = DirAccess::open("res:///", &err);
|
||||||
@@ -444,6 +438,35 @@ void RoadLinesData::save_data()
|
|||||||
Time::get_singleton()
|
Time::get_singleton()
|
||||||
->get_unix_time_from_system()));
|
->get_unix_time_from_system()));
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
String road_lines_path_conf = road_lines_path.replace(".json", ".bin");
|
||||||
|
if (FileAccess::exists(road_lines_path_conf)) {
|
||||||
|
DirAccess *dir = DirAccess::open("res:///", &err);
|
||||||
|
assert(dir && err == OK);
|
||||||
|
err = dir->copy(
|
||||||
|
road_lines_path_conf,
|
||||||
|
road_lines_path_conf + "." +
|
||||||
|
String::num(
|
||||||
|
Time::get_singleton()
|
||||||
|
->get_unix_time_from_system()));
|
||||||
|
}
|
||||||
|
FileAccess *fd =
|
||||||
|
FileAccess::open(road_lines_path_conf, FileAccess::WRITE, &err);
|
||||||
|
assert(err == OK);
|
||||||
|
int len;
|
||||||
|
err = encode_variant(output, nullptr, len, false);
|
||||||
|
assert(err == OK);
|
||||||
|
PoolVector<uint8_t> buffer;
|
||||||
|
buffer.resize(len);
|
||||||
|
PoolVector<uint8_t>::Write w = buffer.write();
|
||||||
|
err = encode_variant(output, w.ptr(), len, false);
|
||||||
|
assert(err == OK);
|
||||||
|
fd->store_32(len);
|
||||||
|
fd->store_buffer(w.ptr(), len);
|
||||||
|
fd->close();
|
||||||
|
line_data.set_value("line_data", "lines", output);
|
||||||
|
line_data.save(road_lines_path_conf);
|
||||||
|
#endif
|
||||||
FileAccess *fd =
|
FileAccess *fd =
|
||||||
FileAccess::open(road_lines_path, FileAccess::WRITE, &err);
|
FileAccess::open(road_lines_path, FileAccess::WRITE, &err);
|
||||||
if (err == OK) {
|
if (err == OK) {
|
||||||
@@ -784,138 +807,6 @@ void RoadLinesData::update_line_segments(const String &line)
|
|||||||
::lines.update_line_segments(line);
|
::lines.update_line_segments(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadLinesData::line_add_building(const String &line, const String &key,
|
|
||||||
float curve_offset, float normal_offset,
|
|
||||||
float y_rotation, float y_offset)
|
|
||||||
{
|
|
||||||
::lines.line_add_building(line, key, curve_offset, normal_offset,
|
|
||||||
y_rotation, y_offset);
|
|
||||||
// TODO: save/load
|
|
||||||
BuildingsData::get_singleton()->get_building(key).line_name = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoadLinesData::assign_close_buildings(const String &line)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
print_line("assign_close_buildings: " + line);
|
|
||||||
if (!::lines.has(line))
|
|
||||||
return;
|
|
||||||
if (!line.ends_with("_buildings"))
|
|
||||||
return;
|
|
||||||
if (::lines[line].points.size() < 2)
|
|
||||||
return;
|
|
||||||
update_line_segments(line);
|
|
||||||
if (::lines[line].segments.size() == 0)
|
|
||||||
return;
|
|
||||||
print_line("assign_close_buildings: processing: " +
|
|
||||||
itos(BuildingsData::get_singleton()->get_building_count()) +
|
|
||||||
" buildings");
|
|
||||||
List<String> bkeys;
|
|
||||||
BuildingsData::get_singleton()->get_building_keys_list(&bkeys);
|
|
||||||
List<String>::Element *e;
|
|
||||||
for (e = bkeys.front(); e; e = e->next()) {
|
|
||||||
float dst = Math_INF;
|
|
||||||
float result_offset = 0.0f;
|
|
||||||
float side = 0.0f;
|
|
||||||
float yoff = 0.0f;
|
|
||||||
String building_key;
|
|
||||||
/* FIXME: use proper function */
|
|
||||||
String bkey = e->get();
|
|
||||||
struct BuildingsData::building &data =
|
|
||||||
BuildingsData::get_singleton()->get_building(bkey);
|
|
||||||
// manually placed
|
|
||||||
if (!data.generated)
|
|
||||||
continue;
|
|
||||||
// already assigned to another line
|
|
||||||
const String &building_line = BuildingsData::get_singleton()
|
|
||||||
->get_building(bkey)
|
|
||||||
.line_name;
|
|
||||||
if (building_line != line && building_line != "")
|
|
||||||
continue;
|
|
||||||
if (line_has_building(line, data.key))
|
|
||||||
continue;
|
|
||||||
Vector3 p = data.xform.origin;
|
|
||||||
Vector3 segment_point;
|
|
||||||
int segment_index = -1;
|
|
||||||
|
|
||||||
for (j = 0; j < (int)::lines[line].segments.size(); j++) {
|
|
||||||
Vector3 seg[] = { ::lines[line].segments[j].p1,
|
|
||||||
::lines[line].segments[j].p2 };
|
|
||||||
Vector3 closest =
|
|
||||||
Geometry::get_closest_point_to_segment(p, seg);
|
|
||||||
Vector3 xp = p;
|
|
||||||
xp.y = p.y;
|
|
||||||
float tmpdst = xp.distance_squared_to(closest);
|
|
||||||
if (closest.is_equal_approx(
|
|
||||||
::lines[line].segments[j].p1) ||
|
|
||||||
closest.is_equal_approx(
|
|
||||||
::lines[line].segments[j].p2)) {
|
|
||||||
float w = closest.dot(
|
|
||||||
::lines[line].segments[j].dir);
|
|
||||||
float wt =
|
|
||||||
xp.dot(::lines[line].segments[j].dir);
|
|
||||||
if (wt - w > 0.1f || wt - w < -0.1f)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (dst > tmpdst) {
|
|
||||||
dst = tmpdst;
|
|
||||||
building_key = data.key;
|
|
||||||
segment_index = j;
|
|
||||||
segment_point = closest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (segment_index < 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const Vector3 &p1 = ::lines[line].segments[segment_index].p1;
|
|
||||||
const Vector3 &p2 = ::lines[line].segments[segment_index].p2;
|
|
||||||
const Vector3 &dir = ::lines[line].segments[segment_index].dir;
|
|
||||||
assert(segment_index >= 0);
|
|
||||||
// assert(!segment_point.is_equal_approx(p1));
|
|
||||||
// assert(!segment_point.is_equal_approx(p2));
|
|
||||||
assert((segment_point - p1).dot(dir) >= 0);
|
|
||||||
float wdst = (p - p1).dot(dir);
|
|
||||||
print_line("wdst=" + String::num(wdst));
|
|
||||||
assert(wdst >= 0);
|
|
||||||
result_offset =
|
|
||||||
::lines[line].segments[segment_index].offset + wdst;
|
|
||||||
assert(result_offset >= 0);
|
|
||||||
side = (p - p1).dot(::lines[line].segments[j].tangent);
|
|
||||||
|
|
||||||
print_line("key: " + building_key +
|
|
||||||
" dst: " + String::num(dst));
|
|
||||||
if (dst < 16 * 16) {
|
|
||||||
print_line("adding: key: " + building_key +
|
|
||||||
" dst: " + String::num(dst));
|
|
||||||
assert(result_offset >= 0);
|
|
||||||
Vector3 reference(0, 0, -1);
|
|
||||||
Vector3 rotated =
|
|
||||||
data.xform.basis.xform(reference).normalized();
|
|
||||||
float angle = reference.signed_angle_to(
|
|
||||||
rotated, Vector3(0, 1, 0));
|
|
||||||
yoff = (p - p1).dot(Vector3(0, 1, 0));
|
|
||||||
// yoff is relative to p1.y
|
|
||||||
|
|
||||||
line_add_building(line, building_key, result_offset,
|
|
||||||
side, angle, yoff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RoadLinesData::line_has_building(const String &line,
|
|
||||||
const String &building_key)
|
|
||||||
{
|
|
||||||
uint64_t key_hash = building_key.hash64();
|
|
||||||
bool ret = false;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < (int)::lines[line].buildings.size(); i++)
|
|
||||||
if (::lines[line].buildings[i].building_key_hash == key_hash) {
|
|
||||||
ret = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 RoadLinesData::get_point_by_offsets(const String &line,
|
Vector3 RoadLinesData::get_point_by_offsets(const String &line,
|
||||||
float dir_offset,
|
float dir_offset,
|
||||||
float normal_offset)
|
float normal_offset)
|
||||||
@@ -943,89 +834,3 @@ Vector3 RoadLinesData::get_point_by_offsets(const String &line,
|
|||||||
print_verbose("data: " + (ret.operator String()));
|
print_verbose("data: " + (ret.operator String()));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RoadLinesData::update_buildings_from_lines()
|
|
||||||
{
|
|
||||||
BuildingsData *bd = BuildingsData::get_singleton();
|
|
||||||
List<String> keys;
|
|
||||||
::lines.get_key_list(&keys);
|
|
||||||
List<String>::Element *e = keys.front();
|
|
||||||
while (e) {
|
|
||||||
int i;
|
|
||||||
const String &line = e->get();
|
|
||||||
for (i = 0; i < (int)::lines[line].buildings.size(); i++) {
|
|
||||||
const uint64_t &building_key_hash =
|
|
||||||
::lines[line].buildings[i].building_key_hash;
|
|
||||||
bool found = bd->has_building(
|
|
||||||
::lines[line].buildings[i].building_key);
|
|
||||||
if (found) {
|
|
||||||
struct BuildingsData::building &b =
|
|
||||||
bd->get_building(::lines[line]
|
|
||||||
.buildings[i]
|
|
||||||
.building_key);
|
|
||||||
Vector3 pt = get_point_by_offsets(
|
|
||||||
line,
|
|
||||||
::lines[line].buildings[i].line_offset,
|
|
||||||
::lines[line]
|
|
||||||
.buildings[i]
|
|
||||||
.normal_offset);
|
|
||||||
Basis basis = Basis().rotated(
|
|
||||||
Vector3(0, 1, 0),
|
|
||||||
::lines[line].buildings[i].y_rotation);
|
|
||||||
b.xform.origin = pt;
|
|
||||||
b.xform.basis = basis;
|
|
||||||
EditorEvent::get_singleton()->event.emit(
|
|
||||||
"building_updated",
|
|
||||||
varray(::lines[line]
|
|
||||||
.buildings[i]
|
|
||||||
.building_key));
|
|
||||||
} else {
|
|
||||||
Vector3 pt = get_point_by_offsets(
|
|
||||||
line,
|
|
||||||
::lines[line].buildings[i].line_offset,
|
|
||||||
::lines[line]
|
|
||||||
.buildings[i]
|
|
||||||
.normal_offset);
|
|
||||||
Basis basis = Basis().rotated(
|
|
||||||
Vector3(0, 1, 0),
|
|
||||||
::lines[line].buildings[i].y_rotation);
|
|
||||||
struct BuildingsData::building nb;
|
|
||||||
Dictionary data;
|
|
||||||
data["id"] = ::lines[line].buildings[i].id;
|
|
||||||
data["xform"] = Transform(basis, pt);
|
|
||||||
BuildingsData::building::from_dict(&nb, data);
|
|
||||||
String bkey = bd->create_building(nb);
|
|
||||||
assert(bkey.length() > 0);
|
|
||||||
EditorEvent::get_singleton()->event.emit(
|
|
||||||
"building_created", varray(bkey));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e = e->next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RoadLinesData::line_building_data::from_dict(line_building_data *b,
|
|
||||||
const Dictionary &from)
|
|
||||||
{
|
|
||||||
assert(from.has("building_key"));
|
|
||||||
assert(from.has("line_offset"));
|
|
||||||
assert(from.has("normal_offset"));
|
|
||||||
assert(from.has("y_rotation"));
|
|
||||||
b->building_key = from.get("building_key", "");
|
|
||||||
b->building_key_hash = b->building_key.hash64();
|
|
||||||
b->line_offset = from.get("line_offset", -1.0f);
|
|
||||||
b->normal_offset = from.get("normal_offset", -1.0f);
|
|
||||||
b->y_rotation = from.get("y_rotation", Math_NAN);
|
|
||||||
b->y_offset = from.get("y_offset", Math_NAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary RoadLinesData::line_building_data::to_dict() const
|
|
||||||
{
|
|
||||||
Dictionary ret;
|
|
||||||
ret["building_key"] = building_key;
|
|
||||||
ret["line_offset"] = line_offset;
|
|
||||||
ret["normal_offset"] = normal_offset;
|
|
||||||
ret["y_rotation"] = y_rotation;
|
|
||||||
ret["y_offset"] = y_offset;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#ifndef ROAD_LINES_DATA_H
|
#ifndef ROAD_LINES_DATA_H
|
||||||
#define ROAD_LINES_DATA_H
|
#define ROAD_LINES_DATA_H
|
||||||
|
#include <cassert>
|
||||||
|
#include <core/io/json.h>
|
||||||
#include "callable.h"
|
#include "callable.h"
|
||||||
class ImmediateGeometry;
|
class ImmediateGeometry;
|
||||||
class RoadLinesData {
|
class RoadLinesData {
|
||||||
@@ -14,20 +16,6 @@ protected:
|
|||||||
static RoadLinesData *singleton;
|
static RoadLinesData *singleton;
|
||||||
_Signal<void> lines_updated;
|
_Signal<void> lines_updated;
|
||||||
|
|
||||||
public:
|
|
||||||
struct line_building_data {
|
|
||||||
String id;
|
|
||||||
String building_key;
|
|
||||||
uint64_t building_key_hash;
|
|
||||||
float line_offset;
|
|
||||||
float normal_offset;
|
|
||||||
float y_rotation;
|
|
||||||
float y_offset;
|
|
||||||
static void from_dict(struct line_building_data *b,
|
|
||||||
const Dictionary &from);
|
|
||||||
Dictionary to_dict() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct line_segment {
|
struct line_segment {
|
||||||
Vector3 p1;
|
Vector3 p1;
|
||||||
@@ -39,10 +27,172 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct road_edge_side {
|
||||||
|
int transit_stop_count;
|
||||||
|
String transit_stop_type;
|
||||||
|
float transit_stop_offset;
|
||||||
|
float transit_stop_dir_offset;
|
||||||
|
float transit_stop_y_rotation;
|
||||||
|
int sideroad;
|
||||||
|
float sideroad_offset;
|
||||||
|
float sideroad_dir_offset;
|
||||||
|
float sideroad_y_offset;
|
||||||
|
float sideroad_y_rotation;
|
||||||
|
String sideroad_type;
|
||||||
|
int lot;
|
||||||
|
float lot_offset;
|
||||||
|
float lot_dir_offset;
|
||||||
|
float lot_y_offset;
|
||||||
|
float lot_y_rotation;
|
||||||
|
String lot_type;
|
||||||
|
struct buildings {
|
||||||
|
String id;
|
||||||
|
Vector3 offsets;
|
||||||
|
float y_rotation;
|
||||||
|
String to_string() const
|
||||||
|
{
|
||||||
|
String ret;
|
||||||
|
ret += id + ":";
|
||||||
|
ret += String::num(offsets.x) + ", ";
|
||||||
|
ret += String::num(offsets.y) + ", ";
|
||||||
|
ret += String::num(offsets.z) + ":";
|
||||||
|
ret += String::num(y_rotation);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static void from_string(struct buildings &buildings,
|
||||||
|
const String &data)
|
||||||
|
{
|
||||||
|
Vector<String> parts = data.split(":");
|
||||||
|
if (parts.size() < 3)
|
||||||
|
return;
|
||||||
|
assert(parts.size() == 3);
|
||||||
|
Vector<String> vecparts = parts[1].split(",");
|
||||||
|
assert(vecparts.size() == 3);
|
||||||
|
buildings.id = parts[0];
|
||||||
|
buildings.offsets.x =
|
||||||
|
vecparts[0].strip_edges().to_float();
|
||||||
|
buildings.offsets.y =
|
||||||
|
vecparts[1].strip_edges().to_float();
|
||||||
|
buildings.offsets.z =
|
||||||
|
vecparts[2].strip_edges().to_float();
|
||||||
|
buildings.y_rotation =
|
||||||
|
parts[2].strip_edges().to_float();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::vector<struct buildings> buildings;
|
||||||
|
Dictionary to_dict() const
|
||||||
|
{
|
||||||
|
Dictionary ret;
|
||||||
|
ret["transit_stop_count"] = transit_stop_count;
|
||||||
|
ret["transit_stop_type"] = transit_stop_type;
|
||||||
|
ret["transit_stop_offset"] = transit_stop_offset;
|
||||||
|
ret["transit_stop_dir_offset"] =
|
||||||
|
transit_stop_dir_offset;
|
||||||
|
ret["transit_stop_y_rotation"] =
|
||||||
|
transit_stop_y_rotation;
|
||||||
|
ret["sideroad"] = sideroad;
|
||||||
|
ret["sideroad_offset"] = sideroad_offset;
|
||||||
|
ret["sideroad_dir_offset"] = sideroad_dir_offset;
|
||||||
|
ret["sideroad_y_offset"] = sideroad_y_offset;
|
||||||
|
ret["sideroad_y_rotation"] = sideroad_y_rotation;
|
||||||
|
ret["sideroad_type"] = sideroad_type;
|
||||||
|
ret["lot"] = lot;
|
||||||
|
ret["lot_offset"] = lot_offset;
|
||||||
|
ret["lot_dir_offset"] = lot_dir_offset;
|
||||||
|
ret["lot_y_offset"] = lot_y_offset;
|
||||||
|
ret["lot_y_rotation"] = lot_y_rotation;
|
||||||
|
ret["lot_type"] = lot_type;
|
||||||
|
String lot_buildings;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (int)buildings.size(); i++) {
|
||||||
|
lot_buildings += buildings[i].to_string();
|
||||||
|
if (i < (int)buildings.size() - 1)
|
||||||
|
lot_buildings += "!";
|
||||||
|
}
|
||||||
|
ret["lot_buildings"] = lot_buildings;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
road_edge_side()
|
||||||
|
: transit_stop_count(0)
|
||||||
|
, transit_stop_type("")
|
||||||
|
, transit_stop_offset(0.0f)
|
||||||
|
, transit_stop_dir_offset(0.0f)
|
||||||
|
, transit_stop_y_rotation(0.0f)
|
||||||
|
, sideroad(0)
|
||||||
|
, sideroad_offset(0.0f)
|
||||||
|
, sideroad_dir_offset(0.0f)
|
||||||
|
, sideroad_y_offset(0.0f)
|
||||||
|
, sideroad_y_rotation(0.0f)
|
||||||
|
, sideroad_type(String(""))
|
||||||
|
, lot(0)
|
||||||
|
, lot_offset(0.0f)
|
||||||
|
, lot_dir_offset(0.0f)
|
||||||
|
, lot_y_offset(0.0f)
|
||||||
|
, lot_y_rotation(0.0f)
|
||||||
|
, lot_type(String(""))
|
||||||
|
, buildings{}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static void from_dict(struct road_edge_side &side,
|
||||||
|
const Dictionary &dict)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
side.transit_stop_count = dict["transit_stop_count"];
|
||||||
|
side.transit_stop_type = dict["transit_stop_type"];
|
||||||
|
side.transit_stop_offset = dict["transit_stop_offset"];
|
||||||
|
side.transit_stop_dir_offset =
|
||||||
|
dict["transit_stop_dir_offset"];
|
||||||
|
side.transit_stop_y_rotation =
|
||||||
|
dict["transit_stop_y_rotation"];
|
||||||
|
side.sideroad = dict["sideroad"];
|
||||||
|
side.sideroad_offset = dict["sideroad_offset"];
|
||||||
|
side.sideroad_dir_offset = dict["sideroad_dir_offset"];
|
||||||
|
side.sideroad_y_offset = dict["sideroad_y_offset"];
|
||||||
|
side.sideroad_y_rotation = dict["sideroad_y_rotation"];
|
||||||
|
side.sideroad_type = dict["sideroad_type"];
|
||||||
|
side.lot = dict["lot"];
|
||||||
|
side.lot_offset = dict["lot_offset"];
|
||||||
|
side.lot_dir_offset = dict["lot_dir_offset"];
|
||||||
|
side.lot_y_offset = dict["lot_y_offset"];
|
||||||
|
side.lot_y_rotation = dict["lot_y_rotation"];
|
||||||
|
side.lot_type = dict["lot_type"];
|
||||||
|
String lot_buildings = dict["lot_buildings"];
|
||||||
|
lot_buildings = lot_buildings.strip_edges();
|
||||||
|
Vector<String> parts;
|
||||||
|
if (lot_buildings.find("!") >= 0)
|
||||||
|
parts = lot_buildings.split("!");
|
||||||
|
else
|
||||||
|
parts.push_back(lot_buildings);
|
||||||
|
side.buildings.resize(parts.size());
|
||||||
|
for (i = 0; i < parts.size(); i++) {
|
||||||
|
buildings::from_string(side.buildings[i],
|
||||||
|
parts[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct road_edge {
|
||||||
|
struct road_edge_side left, right;
|
||||||
|
|
||||||
|
Dictionary to_dict() const
|
||||||
|
{
|
||||||
|
Dictionary ret;
|
||||||
|
ret["left"] = left.to_dict();
|
||||||
|
ret["right"] = right.to_dict();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
static void from_dict(struct road_edge &edge,
|
||||||
|
const Dictionary &dict)
|
||||||
|
{
|
||||||
|
const Dictionary &dleft = dict["left"],
|
||||||
|
&dright = dict["right"];
|
||||||
|
road_edge_side::from_dict(edge.left, dleft);
|
||||||
|
road_edge_side::from_dict(edge.right, dright);
|
||||||
|
}
|
||||||
|
};
|
||||||
struct road_line {
|
struct road_line {
|
||||||
std::vector<Transform> points;
|
std::vector<Transform> points;
|
||||||
|
std::vector<struct road_edge> edges;
|
||||||
std::vector<int> indices;
|
std::vector<int> indices;
|
||||||
std::vector<struct line_building_data> buildings;
|
|
||||||
std::vector<struct line_segment> segments;
|
std::vector<struct line_segment> segments;
|
||||||
int lanes;
|
int lanes;
|
||||||
int pattern;
|
int pattern;
|
||||||
@@ -87,14 +237,8 @@ public:
|
|||||||
void set_debug_flags(int debug_flags);
|
void set_debug_flags(int debug_flags);
|
||||||
int get_debug_flags() const;
|
int get_debug_flags() const;
|
||||||
void update_line_segments(const String &line);
|
void update_line_segments(const String &line);
|
||||||
void line_add_building(const String &line, const String &key,
|
|
||||||
float curve_offset, float normal_offset,
|
|
||||||
float y_rotation, float y_offset);
|
|
||||||
void assign_close_buildings(const String &line);
|
|
||||||
bool line_has_building(const String &line, const String &building_key);
|
|
||||||
Vector3 get_point_by_offsets(const String &line, float dir_offset,
|
Vector3 get_point_by_offsets(const String &line, float dir_offset,
|
||||||
float normal_offset);
|
float normal_offset);
|
||||||
void update_buildings_from_lines();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void create_segments_from_lines();
|
void create_segments_from_lines();
|
||||||
|
|||||||
@@ -7,6 +7,11 @@
|
|||||||
#include <scene/gui/text_edit.h>
|
#include <scene/gui/text_edit.h>
|
||||||
#include <scene/gui/spin_box.h>
|
#include <scene/gui/spin_box.h>
|
||||||
#include <scene/gui/menu_button.h>
|
#include <scene/gui/menu_button.h>
|
||||||
|
#include <scene/gui/box_container.h>
|
||||||
|
#include <scene/gui/label.h>
|
||||||
|
#include <scene/gui/panel_container.h>
|
||||||
|
#include <scene/gui/scroll_container.h>
|
||||||
|
#include <scene/gui/separator.h>
|
||||||
#include <scene/3d/immediate_geometry.h>
|
#include <scene/3d/immediate_geometry.h>
|
||||||
#include <scene/3d/camera.h>
|
#include <scene/3d/camera.h>
|
||||||
#include <core/io/config_file.h>
|
#include <core/io/config_file.h>
|
||||||
@@ -16,6 +21,7 @@
|
|||||||
#include <core/os/time.h>
|
#include <core/os/time.h>
|
||||||
#include <core/io/json.h>
|
#include <core/io/json.h>
|
||||||
#include <modules/regex/regex.h>
|
#include <modules/regex/regex.h>
|
||||||
|
#include "signal_handler.h"
|
||||||
#include "editor_event.h"
|
#include "editor_event.h"
|
||||||
#include "world_editor.h"
|
#include "world_editor.h"
|
||||||
#include "from_string.h"
|
#include "from_string.h"
|
||||||
@@ -69,104 +75,6 @@ static Ref<Material> debug_material;
|
|||||||
__evhandler(editor_event, RoadLinesEditor);
|
__evhandler(editor_event, RoadLinesEditor);
|
||||||
static __evhandler_type(editor_event, RoadLinesEditor) * gd_editor_event;
|
static __evhandler_type(editor_event, RoadLinesEditor) * gd_editor_event;
|
||||||
|
|
||||||
class HandleSelection : public Object {
|
|
||||||
GDCLASS(HandleSelection, Object)
|
|
||||||
RoadLinesEditor *editor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
HandleSelection(RoadLinesEditor *editor)
|
|
||||||
: Object()
|
|
||||||
, editor(editor)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
LineEdit *filter =
|
|
||||||
editor->get_as_node<LineEdit>("%road_lines_filter");
|
|
||||||
filter->connect("text_changed", this, "filter_handler");
|
|
||||||
filter->connect("text_entered", this, "filter_handler");
|
|
||||||
#endif
|
|
||||||
#if 0
|
|
||||||
ItemList *lines_list =
|
|
||||||
editor->get_as_node<ItemList>("%lines_list");
|
|
||||||
lines_list->connect("item_selected", this, "handler");
|
|
||||||
Button *cursor_set = editor->cursor_set;
|
|
||||||
assert(cursor_set);
|
|
||||||
cursor_set->connect("pressed", this, "set_cursor_handler");
|
|
||||||
Button *point_set = editor->cursor_set;
|
|
||||||
assert(point_set);
|
|
||||||
point_set->connect("pressed", this, "set_point_handler");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
virtual ~HandleSelection()
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
Button *cursor_set = editor->cursor_set;
|
|
||||||
assert(cursor_set);
|
|
||||||
cursor_set->disconnect("pressed", this, "set_cursor_handler");
|
|
||||||
Button *point_set = editor->cursor_set;
|
|
||||||
assert(point_set);
|
|
||||||
point_set->disconnect("pressed", this, "set_point_handler");
|
|
||||||
ItemList *lines_list =
|
|
||||||
editor->get_as_node<ItemList>("%lines_list");
|
|
||||||
lines_list->disconnect("item_selected", this, "handler");
|
|
||||||
LineEdit *filter =
|
|
||||||
editor->get_as_node<LineEdit>("%road_lines_filter");
|
|
||||||
filter->disconnect("text_entered", this, "filter_handler");
|
|
||||||
filter->disconnect("text_changed", this, "filter_handler");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void handler(int index)
|
|
||||||
{
|
|
||||||
if (index < 0)
|
|
||||||
return;
|
|
||||||
ItemList *lines_list =
|
|
||||||
editor->get_as_node<ItemList>("%lines_list");
|
|
||||||
editor->select_line(lines_list->get_item_text(index));
|
|
||||||
}
|
|
||||||
void filter_handler(const String &text)
|
|
||||||
{
|
|
||||||
editor->line_list_filter_changed(text);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
void set_cursor_handler()
|
|
||||||
{
|
|
||||||
LineEdit *cursor_x = editor->cursor_pos[0];
|
|
||||||
LineEdit *cursor_y = editor->cursor_pos[1];
|
|
||||||
LineEdit *cursor_z = editor->cursor_pos[2];
|
|
||||||
Vector3 position;
|
|
||||||
position.x = cursor_x->get_text().to_float();
|
|
||||||
position.y = cursor_y->get_text().to_float();
|
|
||||||
position.z = cursor_z->get_text().to_float();
|
|
||||||
editor->set_cursor_position(position);
|
|
||||||
}
|
|
||||||
void set_point_handler()
|
|
||||||
{
|
|
||||||
LineEdit *point_x = editor->point_pos[0];
|
|
||||||
LineEdit *point_y = editor->point_pos[1];
|
|
||||||
LineEdit *point_z = editor->point_pos[2];
|
|
||||||
Vector3 position;
|
|
||||||
position.x = point_x->get_text().to_float();
|
|
||||||
position.y = point_y->get_text().to_float();
|
|
||||||
position.z = point_z->get_text().to_float();
|
|
||||||
editor->set_point_position(position);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
static void _bind_methods()
|
|
||||||
{
|
|
||||||
ClassDB::bind_method(D_METHOD("handler", "index"),
|
|
||||||
&HandleSelection::handler);
|
|
||||||
ClassDB::bind_method(D_METHOD("filter_handler", "text"),
|
|
||||||
&HandleSelection::filter_handler);
|
|
||||||
#if 0
|
|
||||||
ClassDB::bind_method(D_METHOD("set_cursor_handler"),
|
|
||||||
&HandleSelection::set_cursor_handler);
|
|
||||||
ClassDB::bind_method(D_METHOD("set_point_handler"),
|
|
||||||
&HandleSelection::set_point_handler);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static String current_line = "";
|
static String current_line = "";
|
||||||
|
|
||||||
class HandlePointSelection : public Object {
|
class HandlePointSelection : public Object {
|
||||||
@@ -277,25 +185,6 @@ protected:
|
|||||||
String text = editor->get_current_line_metadata();
|
String text = editor->get_current_line_metadata();
|
||||||
metadata_edit->set_text(text);
|
metadata_edit->set_text(text);
|
||||||
}
|
}
|
||||||
void update_line_buildings_editor()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (current_line == "")
|
|
||||||
return;
|
|
||||||
ItemList *items =
|
|
||||||
editor->get_as_node<ItemList>("%line_buildings_list");
|
|
||||||
items->clear();
|
|
||||||
for (i = 0; i < (int)RoadLinesData::get_singleton()
|
|
||||||
->lines(current_line)
|
|
||||||
.buildings.size();
|
|
||||||
i++) {
|
|
||||||
const String &key = RoadLinesData::get_singleton()
|
|
||||||
->lines(current_line)
|
|
||||||
.buildings[i]
|
|
||||||
.building_key;
|
|
||||||
items->add_item(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void cancel_metadata_handler()
|
void cancel_metadata_handler()
|
||||||
{
|
{
|
||||||
TextEdit *metadata_text = editor->get_as_node<TextEdit>(
|
TextEdit *metadata_text = editor->get_as_node<TextEdit>(
|
||||||
@@ -345,14 +234,6 @@ protected:
|
|||||||
editor->get_as_node<Control>("%road_lines_base")->show();
|
editor->get_as_node<Control>("%road_lines_base")->show();
|
||||||
editor->get_as_node<Control>("%road_lines_buildings")->hide();
|
editor->get_as_node<Control>("%road_lines_buildings")->hide();
|
||||||
}
|
}
|
||||||
void line_buildings_assign_handler()
|
|
||||||
{
|
|
||||||
update_line_buildings_editor();
|
|
||||||
}
|
|
||||||
void line_buildings_remove_handler()
|
|
||||||
{
|
|
||||||
update_line_buildings_editor();
|
|
||||||
}
|
|
||||||
static void _bind_methods()
|
static void _bind_methods()
|
||||||
{
|
{
|
||||||
ClassDB::bind_method(
|
ClassDB::bind_method(
|
||||||
@@ -364,19 +245,9 @@ protected:
|
|||||||
ClassDB::bind_method(
|
ClassDB::bind_method(
|
||||||
D_METHOD("metadata_changed_handler"),
|
D_METHOD("metadata_changed_handler"),
|
||||||
&HandleCreateNewLine::metadata_changed_handler);
|
&HandleCreateNewLine::metadata_changed_handler);
|
||||||
ClassDB::bind_method(
|
|
||||||
D_METHOD("line_buildings_close_handler"),
|
|
||||||
&HandleCreateNewLine::line_buildings_close_handler);
|
|
||||||
ClassDB::bind_method(
|
|
||||||
D_METHOD("line_buildings_assign_handler"),
|
|
||||||
&HandleCreateNewLine::line_buildings_assign_handler);
|
|
||||||
ClassDB::bind_method(
|
|
||||||
D_METHOD("line_buildings_remove_handler"),
|
|
||||||
&HandleCreateNewLine::line_buildings_remove_handler);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static HandleSelection *selection_handler = nullptr;
|
|
||||||
static HandleCreateNewLine *new_line_handler = nullptr;
|
static HandleCreateNewLine *new_line_handler = nullptr;
|
||||||
static HandlePointSelection *point_selection_handler = nullptr;
|
static HandlePointSelection *point_selection_handler = nullptr;
|
||||||
|
|
||||||
@@ -459,27 +330,6 @@ void RoadLinesEditor::update_line_geometry()
|
|||||||
}
|
}
|
||||||
// FIXME: update line segments on load and when line is changed
|
// FIXME: update line segments on load and when line is changed
|
||||||
rld->update_line_segments(current_line);
|
rld->update_line_segments(current_line);
|
||||||
if (rld->lines(current_line).buildings.size() > 1) {
|
|
||||||
line_im->begin(Mesh::PRIMITIVE_LINES);
|
|
||||||
for (i = 0;
|
|
||||||
i < (int)rld->lines(current_line).buildings.size();
|
|
||||||
i++) {
|
|
||||||
print_line("idx: " + itos(i));
|
|
||||||
const RoadLinesData::line_building_data &b =
|
|
||||||
rld->lines(current_line).buildings[i];
|
|
||||||
Vector3 pt = rld->get_point_by_offsets(
|
|
||||||
current_line, b.line_offset,
|
|
||||||
b.normal_offset);
|
|
||||||
line_im->set_color(
|
|
||||||
Color(0.1f, 0.8f, 0.8f, 1.0f));
|
|
||||||
line_im->add_vertex(pt +
|
|
||||||
Vector3(0.0f, 5.0f, 0.0f));
|
|
||||||
line_im->add_vertex(pt +
|
|
||||||
Vector3(0.0f, 15.0f, 0.0f));
|
|
||||||
print_line("idx: " + itos(i) + " done");
|
|
||||||
}
|
|
||||||
line_im->end();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void RoadLinesEditor::update_line_index_ui()
|
void RoadLinesEditor::update_line_index_ui()
|
||||||
@@ -807,6 +657,10 @@ void RoadLinesEditor::set_ui_point_position(const Vector3 &point_position)
|
|||||||
void RoadLinesEditor::set_line_index(int index)
|
void RoadLinesEditor::set_line_index(int index)
|
||||||
{
|
{
|
||||||
RoadLinesData *rld = RoadLinesData::get_singleton();
|
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||||
|
if (!rld->has_line(current_line)) {
|
||||||
|
print_error("bad line: " + current_line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
assert(rld->has_line(current_line));
|
assert(rld->has_line(current_line));
|
||||||
assert(index < (int)rld->lines(current_line).points.size());
|
assert(index < (int)rld->lines(current_line).points.size());
|
||||||
Vector3 point_position = rld->lines(current_line).points[index].origin;
|
Vector3 point_position = rld->lines(current_line).points[index].origin;
|
||||||
@@ -849,8 +703,6 @@ void RoadLinesEditor::activate()
|
|||||||
gd_editor_event = memnew(
|
gd_editor_event = memnew(
|
||||||
__evhandler_type(editor_event, RoadLinesEditor)(this));
|
__evhandler_type(editor_event, RoadLinesEditor)(this));
|
||||||
gd_editor_event->connect(editor, "editor_event");
|
gd_editor_event->connect(editor, "editor_event");
|
||||||
if (!selection_handler)
|
|
||||||
selection_handler = memnew(HandleSelection(this));
|
|
||||||
if (!new_line_handler)
|
if (!new_line_handler)
|
||||||
new_line_handler = memnew(HandleCreateNewLine(this));
|
new_line_handler = memnew(HandleCreateNewLine(this));
|
||||||
if (!point_selection_handler)
|
if (!point_selection_handler)
|
||||||
@@ -865,11 +717,6 @@ void RoadLinesEditor::deactivate()
|
|||||||
{
|
{
|
||||||
EditorEvent::get_singleton()->event.remove_listener(
|
EditorEvent::get_singleton()->event.remove_listener(
|
||||||
this, &RoadLinesEditor::event_handler);
|
this, &RoadLinesEditor::event_handler);
|
||||||
Node *lines_list_node =
|
|
||||||
editor->get_tree()->get_current_scene()->get_node(
|
|
||||||
NodePath("%lines_list"));
|
|
||||||
ItemList *lines_list = Object::cast_to<ItemList>(lines_list_node);
|
|
||||||
lines_list->clear();
|
|
||||||
if (line_im) {
|
if (line_im) {
|
||||||
line_im->queue_delete();
|
line_im->queue_delete();
|
||||||
line_im = nullptr;
|
line_im = nullptr;
|
||||||
@@ -881,10 +728,6 @@ void RoadLinesEditor::deactivate()
|
|||||||
memdelete(new_line_handler);
|
memdelete(new_line_handler);
|
||||||
new_line_handler = nullptr;
|
new_line_handler = nullptr;
|
||||||
}
|
}
|
||||||
if (selection_handler) {
|
|
||||||
memdelete(selection_handler);
|
|
||||||
selection_handler = nullptr;
|
|
||||||
}
|
|
||||||
if (gd_editor_event) {
|
if (gd_editor_event) {
|
||||||
memdelete(gd_editor_event);
|
memdelete(gd_editor_event);
|
||||||
gd_editor_event = nullptr;
|
gd_editor_event = nullptr;
|
||||||
@@ -1135,8 +978,13 @@ void RoadLinesEditor::event_handler(const String &event,
|
|||||||
String text = args[1];
|
String text = args[1];
|
||||||
line_list_filter_changed(text);
|
line_list_filter_changed(text);
|
||||||
} else if (event == "road_lines_editor_set_line_index") {
|
} else if (event == "road_lines_editor_set_line_index") {
|
||||||
|
if (current_line.length() == 0)
|
||||||
|
return;
|
||||||
int index = (int)args[1];
|
int index = (int)args[1];
|
||||||
set_line_index(index);
|
set_line_index(index);
|
||||||
|
EditorEvent::get_singleton()->event.emit(
|
||||||
|
"road_lines_editor_set_line_index::post",
|
||||||
|
varray(index));
|
||||||
} else if (event == "road_lines_create_new_line_name:entered") {
|
} else if (event == "road_lines_create_new_line_name:entered") {
|
||||||
String new_text = args[1];
|
String new_text = args[1];
|
||||||
String text = new_text.strip_edges();
|
String text = new_text.strip_edges();
|
||||||
@@ -1161,5 +1009,346 @@ void RoadLinesEditor::event_handler(const String &event,
|
|||||||
return;
|
return;
|
||||||
} else
|
} else
|
||||||
le->remove_color_override("font_color");
|
le->remove_color_override("font_color");
|
||||||
|
} else if (event == "road_lines_create_edge_editor") {
|
||||||
|
Control *c = Object::cast_to<Control>(args[0]);
|
||||||
|
assert(c);
|
||||||
|
create_edge_editor_ui(c);
|
||||||
|
} else if (event == "road_lines_edge_editor::update") {
|
||||||
|
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||||
|
int index = args[0];
|
||||||
|
const Dictionary &data = args[1];
|
||||||
|
print_line("Update for index: " + itos(index));
|
||||||
|
print_line("Update: " + to_string(data));
|
||||||
|
RoadLinesData::road_line rl = rld->get_line(current_line);
|
||||||
|
if (index < 0 || index >= (int)rl.edges.size()) {
|
||||||
|
print_error("Invalid index: " + itos(index));
|
||||||
|
print_error("Edge count: " +
|
||||||
|
itos((int)rl.edges.size()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RoadLinesData::road_edge::from_dict(rl.edges[index], data);
|
||||||
|
rld->set_line(current_line, rl);
|
||||||
|
print_line("Update for index: " + itos(index) + " done");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class EdgeEditorHandler {
|
||||||
|
RoadLinesEditor *editor;
|
||||||
|
String event_prefix;
|
||||||
|
int index;
|
||||||
|
Dictionary data;
|
||||||
|
std::vector<LineEditEnterString *> handlers;
|
||||||
|
std::vector<PopupMenuSelectHandler *> menu_handlers;
|
||||||
|
ConfigFile stream_conf;
|
||||||
|
|
||||||
|
void side_handler(Control *top, const Dictionary &edge_data,
|
||||||
|
const String &ident)
|
||||||
|
{
|
||||||
|
List<Variant> keys;
|
||||||
|
List<Variant>::Element *el;
|
||||||
|
edge_data.get_key_list(&keys);
|
||||||
|
el = keys.front();
|
||||||
|
VBoxContainer *v = memnew(VBoxContainer);
|
||||||
|
top->call_deferred("add_child", v);
|
||||||
|
while (el) {
|
||||||
|
HBoxContainer *h = memnew(HBoxContainer);
|
||||||
|
v->call_deferred("add_child", h);
|
||||||
|
Label *l = memnew(Label);
|
||||||
|
String name = el->get();
|
||||||
|
l->set_text(name);
|
||||||
|
h->call_deferred("add_child", l);
|
||||||
|
LineEdit *le = memnew(LineEdit);
|
||||||
|
h->call_deferred("add_child", le);
|
||||||
|
le->set_meta("edit_key", name);
|
||||||
|
le->set_meta("edit_ident", ident);
|
||||||
|
Variant value = edge_data[el->get()];
|
||||||
|
le->set_meta("edit_type", value.get_type());
|
||||||
|
if (value.get_type() == Variant::INT) {
|
||||||
|
int m = value;
|
||||||
|
le->set_text(itos(m));
|
||||||
|
} else if (value.get_type() == Variant::STRING) {
|
||||||
|
String m = value;
|
||||||
|
le->set_text(m);
|
||||||
|
} else if (value.get_type() == Variant::REAL) {
|
||||||
|
float m = value;
|
||||||
|
le->set_text(String::num(m));
|
||||||
|
}
|
||||||
|
LineEditEnterString *handler = memnew(
|
||||||
|
LineEditEnterString(le,
|
||||||
|
event_prefix + "::edit"));
|
||||||
|
handlers.push_back(handler);
|
||||||
|
el = el->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template <class T>
|
||||||
|
T get_edge_conf(const String &pname, const String &side,
|
||||||
|
const String ¶m)
|
||||||
|
{
|
||||||
|
T result = stream_conf.get_value(
|
||||||
|
"lines/edges/" + pname + "/" + side, param,
|
||||||
|
stream_conf.get_value("lines/edges/default/" + side,
|
||||||
|
param, 0));
|
||||||
|
if (result == 0 && param.ends_with("dir_offset"))
|
||||||
|
result = 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void event_handler(const String &event, const Vector<Variant> &args)
|
||||||
|
{
|
||||||
|
if (event == "road_lines_edge_editor::edit") {
|
||||||
|
LineEdit *le = Object::cast_to<LineEdit>(args[0]);
|
||||||
|
assert(le);
|
||||||
|
String text = args[1];
|
||||||
|
String key = le->get_meta("edit_key");
|
||||||
|
String ident = le->get_meta("edit_ident");
|
||||||
|
int type = le->get_meta("edit_type");
|
||||||
|
if (type == Variant::INT) {
|
||||||
|
int m = text.to_int();
|
||||||
|
Dictionary side = data[ident];
|
||||||
|
side[key] = m;
|
||||||
|
data[ident] = side;
|
||||||
|
} else if (type == Variant::STRING) {
|
||||||
|
String m = text.strip_edges();
|
||||||
|
Dictionary side = data[ident];
|
||||||
|
side[key] = m;
|
||||||
|
data[ident] = side;
|
||||||
|
} else if (type == Variant::REAL) {
|
||||||
|
float m = text.strip_edges().to_float();
|
||||||
|
Dictionary side = data[ident];
|
||||||
|
side[key] = m;
|
||||||
|
data[ident] = side;
|
||||||
|
}
|
||||||
|
EditorEvent::get_singleton()->event.emit(
|
||||||
|
event_prefix + "::update", varray(index, data));
|
||||||
|
String output = to_string(data);
|
||||||
|
print_line("index: " + itos(index));
|
||||||
|
print_line("edited: " + output);
|
||||||
|
} else if (event == "road_lines_edge_editor::menu::left") {
|
||||||
|
PopupMenu *menu = Object::cast_to<PopupMenu>(args[0]);
|
||||||
|
int id = args[1];
|
||||||
|
int item_index = menu->get_item_index(id);
|
||||||
|
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||||
|
RoadLinesData::road_line rl =
|
||||||
|
rld->get_line(current_line);
|
||||||
|
String pname;
|
||||||
|
switch (id) {
|
||||||
|
case 200:
|
||||||
|
pname = "clear";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pname = menu->get_item_metadata(item_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pname.begins_with("lot-")) {
|
||||||
|
rl.edges[index].left.lot_type =
|
||||||
|
pname.replace("lot-", "");
|
||||||
|
if (rl.edges[index].left.lot == 0) {
|
||||||
|
rl.edges[index].left.lot = 1;
|
||||||
|
rl.edges[index].left.lot_offset =
|
||||||
|
get_edge_conf<float>(
|
||||||
|
pname, "left",
|
||||||
|
"lot_offset");
|
||||||
|
rl.edges[index].left.lot_y_rotation =
|
||||||
|
get_edge_conf<float>(
|
||||||
|
pname, "left",
|
||||||
|
"lot_y_rotation");
|
||||||
|
float dir_offt =
|
||||||
|
rl.points[index + 1]
|
||||||
|
.origin.distance_to(
|
||||||
|
rl.points[index]
|
||||||
|
.origin) /
|
||||||
|
2.0f;
|
||||||
|
rl.edges[index].left.lot_dir_offset =
|
||||||
|
dir_offt;
|
||||||
|
}
|
||||||
|
} else if (pname == "clear") {
|
||||||
|
rl.edges[index].left.lot_type = "";
|
||||||
|
rl.edges[index].left.lot = 0;
|
||||||
|
rl.edges[index].left.buildings.clear();
|
||||||
|
}
|
||||||
|
rld->set_line(current_line, rl);
|
||||||
|
editor->rebuild_roads();
|
||||||
|
} else if (event == "road_lines_edge_editor::menu::right") {
|
||||||
|
PopupMenu *menu = Object::cast_to<PopupMenu>(args[0]);
|
||||||
|
int id = args[1];
|
||||||
|
int item_index = menu->get_item_index(id);
|
||||||
|
String pname;
|
||||||
|
switch (id) {
|
||||||
|
case 200:
|
||||||
|
pname = "clear";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pname = menu->get_item_metadata(item_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||||
|
RoadLinesData::road_line rl =
|
||||||
|
rld->get_line(current_line);
|
||||||
|
if (pname.begins_with("lot-")) {
|
||||||
|
rl.edges[index].right.lot_type =
|
||||||
|
pname.replace("lot-", "");
|
||||||
|
if (rl.edges[index].right.lot == 0) {
|
||||||
|
rl.edges[index].right.lot = 1;
|
||||||
|
rl.edges[index].right.lot_offset =
|
||||||
|
get_edge_conf<float>(
|
||||||
|
pname, "right",
|
||||||
|
"lot_offset");
|
||||||
|
rl.edges[index].right.lot_y_rotation =
|
||||||
|
get_edge_conf<float>(
|
||||||
|
pname, "right",
|
||||||
|
"lot_y_rotation");
|
||||||
|
float dir_offt =
|
||||||
|
rl.points[index + 1]
|
||||||
|
.origin.distance_to(
|
||||||
|
rl.points[index]
|
||||||
|
.origin) /
|
||||||
|
2.0f;
|
||||||
|
rl.edges[index].right.lot_dir_offset =
|
||||||
|
dir_offt;
|
||||||
|
}
|
||||||
|
} else if (pname == "clear") {
|
||||||
|
rl.edges[index].right.lot_type = "";
|
||||||
|
rl.edges[index].right.lot = 0;
|
||||||
|
rl.edges[index].right.buildings.clear();
|
||||||
|
}
|
||||||
|
rld->set_line(current_line, rl);
|
||||||
|
editor->rebuild_roads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
EdgeEditorHandler(RoadLinesEditor *editor, Control *top, int index)
|
||||||
|
: editor(editor)
|
||||||
|
, event_prefix("road_lines_edge_editor")
|
||||||
|
, index(index)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < top->get_child_count(); i++)
|
||||||
|
top->get_child(i)->queue_delete();
|
||||||
|
print_line("line index: " + itos(index));
|
||||||
|
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||||
|
if (index < 0 ||
|
||||||
|
index >= (int)rld->lines(current_line).points.size() - 1)
|
||||||
|
return;
|
||||||
|
assert(index >= 0 &&
|
||||||
|
index < (int)rld->lines(current_line).points.size() - 1);
|
||||||
|
assert(index >= 0 &&
|
||||||
|
index < (int)rld->lines(current_line).edges.size());
|
||||||
|
data = rld->lines(current_line).edges[index].to_dict();
|
||||||
|
const Dictionary &left = data["left"], &right = data["right"];
|
||||||
|
PanelContainer *p = memnew(PanelContainer);
|
||||||
|
top->call_deferred("add_child", p);
|
||||||
|
ScrollContainer *s = memnew(ScrollContainer);
|
||||||
|
p->call_deferred("add_child", s);
|
||||||
|
s->set_custom_minimum_size(Vector2(0, 90));
|
||||||
|
VBoxContainer *v = memnew(VBoxContainer);
|
||||||
|
s->call_deferred("add_child", v);
|
||||||
|
v->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
v->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
|
||||||
|
Label *h1 = memnew(Label), *h2 = memnew(Label);
|
||||||
|
h1->set_text("left");
|
||||||
|
h2->set_text("right");
|
||||||
|
v->call_deferred("add_child", h1);
|
||||||
|
side_handler(v, left, "left");
|
||||||
|
HSeparator *sep = memnew(HSeparator);
|
||||||
|
v->call_deferred("add_child", sep);
|
||||||
|
v->call_deferred("add_child", h2);
|
||||||
|
side_handler(v, right, "right");
|
||||||
|
MenuButton *mb = memnew(MenuButton);
|
||||||
|
v->call_deferred("add_child", mb);
|
||||||
|
mb->set_text("Action...");
|
||||||
|
MenuButton *mb_left = memnew(MenuButton);
|
||||||
|
v->call_deferred("add_child", mb_left);
|
||||||
|
mb_left->set_text("Select left lot...");
|
||||||
|
MenuButton *mb_right = memnew(MenuButton);
|
||||||
|
mb_right->set_text("Select right lot...");
|
||||||
|
v->call_deferred("add_child", mb_right);
|
||||||
|
Error err = stream_conf.load("res://config/stream.conf");
|
||||||
|
assert(err == OK);
|
||||||
|
std::vector<std::pair<String, int> > menu_items = {
|
||||||
|
{ "Move lots starting from current edge to next edges",
|
||||||
|
100 },
|
||||||
|
};
|
||||||
|
std::vector<std::pair<String, int> > menu_items_leftright = {
|
||||||
|
{ "Clear current lot and building(s)", 200 },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < (int)menu_items.size(); i++)
|
||||||
|
mb->get_popup()->add_item(menu_items[i].first,
|
||||||
|
menu_items[i].second);
|
||||||
|
for (i = 0; i < (int)menu_items_leftright.size(); i++) {
|
||||||
|
mb_left->get_popup()->add_item(
|
||||||
|
menu_items_leftright[i].first,
|
||||||
|
menu_items_leftright[i].second);
|
||||||
|
mb_right->get_popup()->add_item(
|
||||||
|
menu_items_leftright[i].first,
|
||||||
|
menu_items_leftright[i].second);
|
||||||
|
}
|
||||||
|
Dictionary bdata =
|
||||||
|
stream_conf.get_value("buildings", "building_data");
|
||||||
|
int item_id = 1000;
|
||||||
|
List<Variant> building_list;
|
||||||
|
List<Variant>::Element *el;
|
||||||
|
bdata.get_key_list(&building_list);
|
||||||
|
el = building_list.front();
|
||||||
|
while (el) {
|
||||||
|
String pname = el->get();
|
||||||
|
String msg;
|
||||||
|
if (pname.begins_with("lot-"))
|
||||||
|
msg = "Create lot: " + pname;
|
||||||
|
else if (pname.begins_with("residental-"))
|
||||||
|
msg = "Add house: " + pname;
|
||||||
|
if (msg.length() > 0 && pname.begins_with("lot-")) {
|
||||||
|
std::vector<PopupMenu *> menus = {
|
||||||
|
mb_left->get_popup(),
|
||||||
|
mb_right->get_popup()
|
||||||
|
};
|
||||||
|
for (i = 0; i < (int)menus.size(); i++) {
|
||||||
|
menus[i]->add_item(msg, item_id);
|
||||||
|
int item_index =
|
||||||
|
menus[i]->get_item_index(
|
||||||
|
item_id);
|
||||||
|
menus[i]->set_item_metadata(item_index,
|
||||||
|
pname);
|
||||||
|
item_id++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
el = el->next();
|
||||||
|
}
|
||||||
|
menu_handlers.push_back(memnew(PopupMenuSelectHandler(
|
||||||
|
mb->get_popup(), event_prefix + "::menu")));
|
||||||
|
menu_handlers.push_back(memnew(PopupMenuSelectHandler(
|
||||||
|
mb_left->get_popup(), event_prefix + "::menu::left")));
|
||||||
|
menu_handlers.push_back(memnew(PopupMenuSelectHandler(
|
||||||
|
mb_right->get_popup(),
|
||||||
|
event_prefix + "::menu::right")));
|
||||||
|
EditorEvent::get_singleton()->event.add_listener(
|
||||||
|
this, &EdgeEditorHandler::event_handler);
|
||||||
|
}
|
||||||
|
virtual ~EdgeEditorHandler()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
EditorEvent::get_singleton()->event.remove_listener(
|
||||||
|
this, &EdgeEditorHandler::event_handler);
|
||||||
|
for (i = 0; i < (int)handlers.size(); i++)
|
||||||
|
memdelete(handlers[i]);
|
||||||
|
for (i = 0; i < (int)menu_handlers.size(); i++)
|
||||||
|
memdelete(menu_handlers[i]);
|
||||||
|
handlers.clear();
|
||||||
|
menu_handlers.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static EdgeEditorHandler *edge_editor = nullptr;
|
||||||
|
void RoadLinesEditor::create_edge_editor_ui(Control *top)
|
||||||
|
{
|
||||||
|
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||||
|
assert(current_line.length() > 0);
|
||||||
|
int index = get_line_index();
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
if ((int)rld->lines(current_line).edges.size() < index)
|
||||||
|
return;
|
||||||
|
print_line("created with index: " + itos(index));
|
||||||
|
if (edge_editor)
|
||||||
|
memdelete(edge_editor);
|
||||||
|
edge_editor = memnew(EdgeEditorHandler(this, top, index));
|
||||||
|
}
|
||||||
@@ -80,5 +80,6 @@ protected:
|
|||||||
void activate();
|
void activate();
|
||||||
void deactivate();
|
void deactivate();
|
||||||
void place_zebras();
|
void place_zebras();
|
||||||
|
void create_edge_editor_ui(Control *top);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "from_string.h"
|
#include "from_string.h"
|
||||||
#include "road_debug.h"
|
#include "road_debug.h"
|
||||||
#include "road_lines_data.h"
|
#include "road_lines_data.h"
|
||||||
|
#include "buildings_data.h"
|
||||||
#include "road_processing.h"
|
#include "road_processing.h"
|
||||||
|
|
||||||
struct wedge {
|
struct wedge {
|
||||||
@@ -53,6 +54,328 @@ struct RoadLinesProcessing {
|
|||||||
memcpy(nodes.data(), road_lines_nodes.data(),
|
memcpy(nodes.data(), road_lines_nodes.data(),
|
||||||
sizeof(Vector3) * road_lines_nodes.size());
|
sizeof(Vector3) * road_lines_nodes.size());
|
||||||
}
|
}
|
||||||
|
Transform get_structure_transform(Vector3 p0, Vector3 p1, Vector3 dir,
|
||||||
|
Vector3 offset_n, float offset,
|
||||||
|
float dir_offset, float y_rotation,
|
||||||
|
float y_offset)
|
||||||
|
{
|
||||||
|
Transform xform(Basis(), p0 + dir * dir_offset +
|
||||||
|
offset_n * offset +
|
||||||
|
Vector3(0, 1, 0) * y_offset);
|
||||||
|
Transform rot(Basis().rotated(Vector3(0, 1, 0),
|
||||||
|
Math::deg2rad(y_rotation)),
|
||||||
|
Vector3());
|
||||||
|
xform.set_look_at(xform.origin, xform.origin + dir * dir_offset,
|
||||||
|
Vector3(0, 1, 0));
|
||||||
|
xform = xform * rot;
|
||||||
|
return xform;
|
||||||
|
}
|
||||||
|
void create_building_structure(const BuildingsData::building &b)
|
||||||
|
{
|
||||||
|
assert(b.key.begins_with("road__"));
|
||||||
|
assert(b.id.length() > 0);
|
||||||
|
assert(b.key.length() > 0);
|
||||||
|
if (BuildingsData::get_singleton()->has_building(b.key)) {
|
||||||
|
BuildingsData::get_singleton()->remove_scene_item(
|
||||||
|
b.id, b.key);
|
||||||
|
BuildingsData::get_singleton()->destroy_building(b.key);
|
||||||
|
}
|
||||||
|
BuildingsData::get_singleton()->create_building(b);
|
||||||
|
if (!BuildingsData::get_singleton()->has_scene(b.id))
|
||||||
|
BuildingsData::get_singleton()->create_scene_data(
|
||||||
|
b.id, b.key);
|
||||||
|
else
|
||||||
|
BuildingsData::get_singleton()->add_scene_item(b.id,
|
||||||
|
b.key);
|
||||||
|
print_line("created building: " + b.key);
|
||||||
|
print_line("at: " + (b.xform.origin.operator String()));
|
||||||
|
}
|
||||||
|
int create_sideroads(const String &line_key, int edge_no,
|
||||||
|
const RoadLinesData::road_edge &edge,
|
||||||
|
const Vector3 &p0, const Vector3 &p1,
|
||||||
|
const Vector3 &dir, const Vector3 left_n,
|
||||||
|
const Vector3 &right_n)
|
||||||
|
{
|
||||||
|
int structures_generated = 0;
|
||||||
|
if (edge.left.sideroad > 0) {
|
||||||
|
Transform xform = get_structure_transform(
|
||||||
|
p0, p1, dir, left_n, edge.left.sideroad_offset,
|
||||||
|
edge.left.sideroad_dir_offset,
|
||||||
|
edge.left.sideroad_y_rotation,
|
||||||
|
edge.left.sideroad_y_offset);
|
||||||
|
BuildingsData::building b;
|
||||||
|
b.key = "road__" + line_key + "__sideroad__" +
|
||||||
|
itos(edge_no) + "__left__sideroad-" +
|
||||||
|
edge.left.sideroad_type;
|
||||||
|
b.id = "sideroad-" + edge.left.sideroad_type;
|
||||||
|
b.generated = true;
|
||||||
|
b.line_name = line_key;
|
||||||
|
b.key_hash = b.key.hash64();
|
||||||
|
b.pattern_id = 0;
|
||||||
|
b.xform = xform;
|
||||||
|
b.worktime[0] = 0;
|
||||||
|
b.worktime[1] = 23;
|
||||||
|
if (edge.left.sideroad_type.length() == 0) {
|
||||||
|
print_error("bad sideroad");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
create_building_structure(b);
|
||||||
|
structures_generated++;
|
||||||
|
out:;
|
||||||
|
}
|
||||||
|
if (edge.right.sideroad > 0) {
|
||||||
|
Transform xform = get_structure_transform(
|
||||||
|
p0, p1, dir, right_n,
|
||||||
|
edge.right.sideroad_offset,
|
||||||
|
edge.right.sideroad_dir_offset,
|
||||||
|
edge.right.sideroad_y_rotation,
|
||||||
|
edge.right.sideroad_y_offset);
|
||||||
|
BuildingsData::building b;
|
||||||
|
b.key = "road__" + line_key + "__sideroad__" +
|
||||||
|
itos(edge_no) + "__right__sideroad-" +
|
||||||
|
edge.right.sideroad_type;
|
||||||
|
b.id = "sideroad-" + edge.right.sideroad_type;
|
||||||
|
b.generated = true;
|
||||||
|
b.line_name = line_key;
|
||||||
|
b.key_hash = b.key.hash64();
|
||||||
|
b.pattern_id = 0;
|
||||||
|
b.xform = xform;
|
||||||
|
b.worktime[0] = 0;
|
||||||
|
b.worktime[1] = 23;
|
||||||
|
if (edge.right.sideroad_type.length() == 0) {
|
||||||
|
print_error("bad sideroad");
|
||||||
|
goto out2;
|
||||||
|
}
|
||||||
|
create_building_structure(b);
|
||||||
|
structures_generated++;
|
||||||
|
out2:;
|
||||||
|
}
|
||||||
|
return structures_generated;
|
||||||
|
}
|
||||||
|
int
|
||||||
|
create_line_building(const String &line_key, int edge_id,
|
||||||
|
const Transform &xform,
|
||||||
|
const struct RoadLinesData::road_edge_side &side,
|
||||||
|
const String &side_name)
|
||||||
|
{
|
||||||
|
int building_no;
|
||||||
|
int structures_generated = 0;
|
||||||
|
for (building_no = 0; building_no < (int)side.buildings.size();
|
||||||
|
building_no++) {
|
||||||
|
const struct RoadLinesData::road_edge_side::buildings
|
||||||
|
&building = side.buildings[building_no];
|
||||||
|
String id = side.buildings[building_no].id;
|
||||||
|
id = id.strip_edges();
|
||||||
|
if (id.length() == 0)
|
||||||
|
continue;
|
||||||
|
Transform rot(
|
||||||
|
Basis().rotated(
|
||||||
|
Vector3(0, 1, 0),
|
||||||
|
Math::deg2rad(building.y_rotation)),
|
||||||
|
building.offsets);
|
||||||
|
Transform building_xform = xform * rot;
|
||||||
|
BuildingsData::building bbuilding;
|
||||||
|
bbuilding.id = id;
|
||||||
|
bbuilding.key = "road__" + line_key + "__lot__" +
|
||||||
|
itos(edge_id) + "__" + side_name +
|
||||||
|
"__" + itos(building_no) +
|
||||||
|
"__building-" + building.id;
|
||||||
|
bbuilding.generated = true;
|
||||||
|
bbuilding.line_name = line_key;
|
||||||
|
bbuilding.key_hash = bbuilding.key.hash64();
|
||||||
|
bbuilding.pattern_id = 0;
|
||||||
|
bbuilding.xform = building_xform;
|
||||||
|
bbuilding.worktime[0] = 0;
|
||||||
|
bbuilding.worktime[1] = 23;
|
||||||
|
create_building_structure(bbuilding);
|
||||||
|
structures_generated++;
|
||||||
|
}
|
||||||
|
return structures_generated;
|
||||||
|
}
|
||||||
|
int create_lots(const String &line_key, int edge_no,
|
||||||
|
const RoadLinesData::road_edge &edge, const Vector3 &p0,
|
||||||
|
const Vector3 &p1, const Vector3 &dir,
|
||||||
|
const Vector3 left_n, const Vector3 &right_n)
|
||||||
|
{
|
||||||
|
int structures_generated = 0;
|
||||||
|
if (edge.left.lot > 0) {
|
||||||
|
Transform xform = get_structure_transform(
|
||||||
|
p0, p1, dir, left_n, edge.left.lot_offset,
|
||||||
|
edge.left.lot_dir_offset,
|
||||||
|
edge.left.lot_y_rotation,
|
||||||
|
edge.left.lot_y_offset);
|
||||||
|
BuildingsData::building b;
|
||||||
|
b.key = "road__" + line_key + "__lot__" +
|
||||||
|
itos(edge_no) + "__left__lot-" +
|
||||||
|
edge.left.lot_type;
|
||||||
|
b.id = "lot-" + edge.left.lot_type;
|
||||||
|
b.generated = true;
|
||||||
|
b.line_name = line_key;
|
||||||
|
b.key_hash = b.key.hash64();
|
||||||
|
b.pattern_id = 0;
|
||||||
|
b.xform = xform;
|
||||||
|
b.worktime[0] = 0;
|
||||||
|
b.worktime[1] = 23;
|
||||||
|
create_building_structure(b);
|
||||||
|
structures_generated++;
|
||||||
|
if (edge.left.buildings.size() > 0) {
|
||||||
|
structures_generated += create_line_building(
|
||||||
|
line_key, edge_no, xform, edge.left,
|
||||||
|
"left");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (edge.right.lot > 0) {
|
||||||
|
Transform xform = get_structure_transform(
|
||||||
|
p0, p1, dir, right_n, edge.right.lot_offset,
|
||||||
|
edge.right.lot_dir_offset,
|
||||||
|
edge.right.lot_y_rotation,
|
||||||
|
edge.right.lot_y_offset);
|
||||||
|
BuildingsData::building b;
|
||||||
|
b.key = "road__" + line_key + "__lot__" +
|
||||||
|
itos(edge_no) + "__right__lot-" +
|
||||||
|
edge.right.lot_type;
|
||||||
|
b.id = "lot-" + edge.right.lot_type;
|
||||||
|
b.generated = true;
|
||||||
|
b.line_name = line_key;
|
||||||
|
b.key_hash = b.key.hash64();
|
||||||
|
b.pattern_id = 0;
|
||||||
|
b.xform = xform;
|
||||||
|
b.worktime[0] = 0;
|
||||||
|
b.worktime[1] = 23;
|
||||||
|
create_building_structure(b);
|
||||||
|
structures_generated++;
|
||||||
|
if (edge.right.buildings.size() > 0) {
|
||||||
|
structures_generated += create_line_building(
|
||||||
|
line_key, edge_no, xform, edge.right,
|
||||||
|
"right");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return structures_generated;
|
||||||
|
}
|
||||||
|
int create_transit_stops(const String &line_key, int edge_no,
|
||||||
|
const RoadLinesData::road_edge &edge,
|
||||||
|
const Vector3 &p0, const Vector3 &p1,
|
||||||
|
const Vector3 &dir, const Vector3 left_n,
|
||||||
|
const Vector3 &right_n)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
int structures_generated = 0;
|
||||||
|
float l = p0.distance_to(p1);
|
||||||
|
if (edge.left.transit_stop_count > 0) {
|
||||||
|
print_line("Creating transit stops on the left");
|
||||||
|
float t = 0.0f;
|
||||||
|
float m =
|
||||||
|
l / ((float)(edge.left.transit_stop_count + 1));
|
||||||
|
for (j = 0; j < edge.left.transit_stop_count; j++) {
|
||||||
|
Transform xform = get_structure_transform(
|
||||||
|
p0, p1, dir, left_n,
|
||||||
|
edge.left.transit_stop_offset,
|
||||||
|
t + edge.left.transit_stop_dir_offset,
|
||||||
|
edge.left.transit_stop_y_rotation,
|
||||||
|
0.0f);
|
||||||
|
BuildingsData::building b;
|
||||||
|
b.key = "road__" + line_key +
|
||||||
|
"__transit_stop__" + itos(edge_no) +
|
||||||
|
"__" + itos(j) + "__left__" +
|
||||||
|
edge.left.transit_stop_type;
|
||||||
|
b.id = edge.left.transit_stop_type;
|
||||||
|
b.generated = true;
|
||||||
|
b.line_name = line_key;
|
||||||
|
b.key_hash = b.key.hash64();
|
||||||
|
b.pattern_id = 0;
|
||||||
|
b.xform = xform;
|
||||||
|
b.worktime[0] = 0;
|
||||||
|
b.worktime[1] = 23;
|
||||||
|
create_building_structure(b);
|
||||||
|
t += m;
|
||||||
|
structures_generated++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (edge.right.transit_stop_count > 0) {
|
||||||
|
print_line("Creating transit stops on the right");
|
||||||
|
float t = 0.0f;
|
||||||
|
float m = l /
|
||||||
|
((float)(edge.right.transit_stop_count + 1));
|
||||||
|
for (j = 0; j < edge.right.transit_stop_count; j++) {
|
||||||
|
Transform xform = get_structure_transform(
|
||||||
|
p0, p1, dir, right_n,
|
||||||
|
edge.right.transit_stop_offset,
|
||||||
|
t + edge.right.transit_stop_dir_offset,
|
||||||
|
edge.right.transit_stop_y_rotation,
|
||||||
|
0.0f);
|
||||||
|
BuildingsData::building b;
|
||||||
|
b.key = "road__" + line_key +
|
||||||
|
"__transit_stop__" + itos(edge_no) +
|
||||||
|
"__" + itos(j) + "__right__" +
|
||||||
|
edge.right.transit_stop_type;
|
||||||
|
b.id = edge.right.transit_stop_type;
|
||||||
|
b.generated = true;
|
||||||
|
b.line_name = line_key;
|
||||||
|
b.key_hash = b.key.hash64();
|
||||||
|
b.pattern_id = 0;
|
||||||
|
b.xform = xform;
|
||||||
|
b.worktime[0] = 0;
|
||||||
|
b.worktime[1] = 23;
|
||||||
|
create_building_structure(b);
|
||||||
|
t += m;
|
||||||
|
structures_generated++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return structures_generated;
|
||||||
|
}
|
||||||
|
void create_structures()
|
||||||
|
{
|
||||||
|
List<String> keys;
|
||||||
|
RoadLinesData *rld = RoadLinesData::get_singleton();
|
||||||
|
rld->get_road_lines_key_list(&keys);
|
||||||
|
List<String>::Element *e = keys.front();
|
||||||
|
print_line("create structures");
|
||||||
|
print_line("road_lines: " + itos(keys.size()));
|
||||||
|
int structures_generated = 0;
|
||||||
|
while (e) {
|
||||||
|
const String &key = e->get();
|
||||||
|
int i;
|
||||||
|
if (rld->lines(key).points.size() < 2) {
|
||||||
|
e = e->next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (rld->lines(key).edges.size() !=
|
||||||
|
rld->lines(key).points.size() - 1) {
|
||||||
|
e = e->next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
print_line("line: " + key + " edges count: " +
|
||||||
|
itos((int)rld->lines(key).edges.size()));
|
||||||
|
for (i = 0; i < (int)rld->lines(key).edges.size();
|
||||||
|
i++) {
|
||||||
|
const RoadLinesData::road_edge &edge =
|
||||||
|
rld->lines(key).edges[i];
|
||||||
|
const Vector3 &p0 =
|
||||||
|
rld->lines(key).points[i].origin;
|
||||||
|
const Vector3 &p1 =
|
||||||
|
rld->lines(key).points[i + 1].origin;
|
||||||
|
Vector3 dir = (p1 - p0).normalized();
|
||||||
|
Vector3 d = dir;
|
||||||
|
Vector3 left_n = Vector3(0, 1, 0).cross(d);
|
||||||
|
Vector3 right_n = -left_n;
|
||||||
|
/* lots */
|
||||||
|
structures_generated +=
|
||||||
|
create_lots(key, i, edge, p0, p1, dir,
|
||||||
|
left_n, right_n);
|
||||||
|
/* sideroads */
|
||||||
|
structures_generated +=
|
||||||
|
create_sideroads(key, i, edge, p0, p1,
|
||||||
|
dir, left_n, right_n);
|
||||||
|
/* bus stops */
|
||||||
|
structures_generated += create_transit_stops(
|
||||||
|
key, i, edge, p0, p1, dir, left_n,
|
||||||
|
right_n);
|
||||||
|
}
|
||||||
|
e = e->next();
|
||||||
|
}
|
||||||
|
print_line("structures generated: " +
|
||||||
|
itos(structures_generated));
|
||||||
|
}
|
||||||
void create_edges()
|
void create_edges()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -236,7 +559,7 @@ struct RoadLinesProcessing {
|
|||||||
if (Vector2(q.x, q.z)
|
if (Vector2(q.x, q.z)
|
||||||
.distance_squared_to(
|
.distance_squared_to(
|
||||||
Vector2(r.x, r.z)) <
|
Vector2(r.x, r.z)) <
|
||||||
0.005f)
|
0.1f)
|
||||||
pr = q.linear_interpolate(r,
|
pr = q.linear_interpolate(r,
|
||||||
0.5f);
|
0.5f);
|
||||||
else {
|
else {
|
||||||
@@ -819,6 +1142,7 @@ RoadMeshProcessing *RoadMeshProcessing::singleton;
|
|||||||
|
|
||||||
void RoadProcessing::road_setup(Node *target, int debug_flags)
|
void RoadProcessing::road_setup(Node *target, int debug_flags)
|
||||||
{
|
{
|
||||||
|
RoadLinesProcessing::get_singleton()->create_structures();
|
||||||
RoadLinesProcessing::get_singleton()->set_debug_flags(debug_flags);
|
RoadLinesProcessing::get_singleton()->set_debug_flags(debug_flags);
|
||||||
RoadLinesProcessing::get_singleton()->road_setup();
|
RoadLinesProcessing::get_singleton()->road_setup();
|
||||||
RoadMeshProcessing::get_singleton()->create_road_meshes(target);
|
RoadMeshProcessing::get_singleton()->create_road_meshes(target);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#undef NDEBUG
|
||||||
|
#include <cassert>
|
||||||
#include <core/set.h>
|
#include <core/set.h>
|
||||||
#include <core/io/json.h>
|
#include <core/io/json.h>
|
||||||
#include <scene/main/viewport.h>
|
#include <scene/main/viewport.h>
|
||||||
@@ -18,6 +20,7 @@
|
|||||||
|
|
||||||
void StreamWorld::create_tilemap()
|
void StreamWorld::create_tilemap()
|
||||||
{
|
{
|
||||||
|
tiles.clear();
|
||||||
data()->for_each_building(
|
data()->for_each_building(
|
||||||
[this](const String &key, void *hdata) {
|
[this](const String &key, void *hdata) {
|
||||||
const struct BuildingsData::building &b =
|
const struct BuildingsData::building &b =
|
||||||
@@ -174,20 +177,33 @@ void StreamWorld::unload_building(const String &key)
|
|||||||
|
|
||||||
void StreamWorld::request_item(int type, const String &bkey)
|
void StreamWorld::request_item(int type, const String &bkey)
|
||||||
{
|
{
|
||||||
String id = data()->get_building(bkey).id;
|
bool debug = false;
|
||||||
|
/* bkey can contain "::"'s so need to replae them with underscores */
|
||||||
|
String ekey = bkey;
|
||||||
|
if (bkey.begins_with("road__")) {
|
||||||
|
print_line("loading building: " + ekey);
|
||||||
|
debug = true;
|
||||||
|
}
|
||||||
|
String id = data()->get_building(ekey).id;
|
||||||
|
if (debug)
|
||||||
|
print_line("building id: " + id);
|
||||||
if (id == "empty")
|
if (id == "empty")
|
||||||
return;
|
return;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case 0:
|
||||||
|
if (debug)
|
||||||
|
print_line("add to scene id: " + id);
|
||||||
if (!data()->has_scene(id))
|
if (!data()->has_scene(id))
|
||||||
data()->create_scene_data(id, bkey);
|
data()->create_scene_data(id, ekey);
|
||||||
else
|
else
|
||||||
data()->add_scene_item(id, bkey);
|
data()->add_scene_item(id, ekey);
|
||||||
|
if (debug)
|
||||||
|
print_line("added to scene id: " + id);
|
||||||
break;
|
break;
|
||||||
case 1: {
|
case 1: {
|
||||||
print_line("Removing key:" + bkey);
|
print_line("Removing key:" + ekey);
|
||||||
if (data()->has_scene(id)) {
|
if (data()->has_scene(id)) {
|
||||||
data()->remove_scene_item(id, bkey);
|
data()->remove_scene_item(id, ekey);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@@ -354,10 +370,43 @@ void StreamWorld::run_command(const String &command,
|
|||||||
remove_generated_stuff();
|
remove_generated_stuff();
|
||||||
update_items();
|
update_items();
|
||||||
} else if (command == "rebuild_roads") {
|
} else if (command == "rebuild_roads") {
|
||||||
|
std::vector<String> erased_keys;
|
||||||
|
erased_keys.reserve(data()->get_building_count());
|
||||||
|
String prefix = "road__";
|
||||||
|
int i;
|
||||||
|
data()->for_each_building(
|
||||||
|
[&erased_keys, prefix](const String &key, void *data) {
|
||||||
|
if (key.begins_with(prefix)) {
|
||||||
|
erased_keys.push_back(key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
print_line("delete buildings: " + itos(erased_keys.size()) +
|
||||||
|
" prefix: " + prefix);
|
||||||
|
for (i = erased_keys.size() - 1; i >= 0; i--) {
|
||||||
|
unload_building(erased_keys[i]);
|
||||||
|
data()->destroy_building(erased_keys[i]);
|
||||||
|
assert(!data()->has_building(erased_keys[i]));
|
||||||
|
}
|
||||||
|
/* FIXME */
|
||||||
if (args.size() > 0)
|
if (args.size() > 0)
|
||||||
RoadProcessing::road_setup(this, args[0]);
|
RoadProcessing::road_setup(this, args[0]);
|
||||||
else
|
else
|
||||||
RoadProcessing::road_setup(this, 0);
|
RoadProcessing::road_setup(this, 0);
|
||||||
|
create_tilemap();
|
||||||
|
update_view();
|
||||||
|
data()->scene_update();
|
||||||
|
update_items();
|
||||||
|
#if 0
|
||||||
|
data()->for_each_building(
|
||||||
|
[this](const String &key, void *mdata) {
|
||||||
|
print_line("Building key: " + key);
|
||||||
|
// FIXME do not load building every time
|
||||||
|
if (key.begins_with("road__"))
|
||||||
|
load_building(key);
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
#endif
|
||||||
print_line("road_rebuild done");
|
print_line("road_rebuild done");
|
||||||
} else if (command == "remove_road_meshes") {
|
} else if (command == "remove_road_meshes") {
|
||||||
RoadProcessing::remove_road_meshes(this);
|
RoadProcessing::remove_road_meshes(this);
|
||||||
@@ -368,7 +417,9 @@ void StreamWorld::run_command(const String &command,
|
|||||||
terrain->set_generator(gen);
|
terrain->set_generator(gen);
|
||||||
update_items();
|
update_items();
|
||||||
RoadProcessing::road_setup(this, 0);
|
RoadProcessing::road_setup(this, 0);
|
||||||
|
create_tilemap();
|
||||||
update_view();
|
update_view();
|
||||||
|
update_items();
|
||||||
assert(false);
|
assert(false);
|
||||||
} else
|
} else
|
||||||
print_error("No command " + command);
|
print_error("No command " + command);
|
||||||
@@ -394,10 +445,27 @@ void StreamWorld::_notification(int which)
|
|||||||
}
|
}
|
||||||
ERR_FAIL_COND_MSG(!current_scene, "No current scene");
|
ERR_FAIL_COND_MSG(!current_scene, "No current scene");
|
||||||
RoadProcessing::road_setup(this, 0);
|
RoadProcessing::road_setup(this, 0);
|
||||||
|
#if 0
|
||||||
|
data()->for_each_building(
|
||||||
|
[this](const String &key, void *mdata) {
|
||||||
|
print_line("Building key: " + key);
|
||||||
|
// FIXME do not load building every time
|
||||||
|
if (key.begins_with("road__")) {
|
||||||
|
load_building(key);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nullptr);
|
||||||
|
assert(false);
|
||||||
|
#endif
|
||||||
|
create_tilemap();
|
||||||
set_process(true);
|
set_process(true);
|
||||||
if (Engine::get_singleton()->is_editor_hint())
|
if (Engine::get_singleton()->is_editor_hint())
|
||||||
break;
|
break;
|
||||||
update_view();
|
update_view();
|
||||||
|
data()->scene_update();
|
||||||
|
update_items();
|
||||||
|
update_view();
|
||||||
assert(terrain);
|
assert(terrain);
|
||||||
assert(viewer);
|
assert(viewer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#undef NDEBUG
|
||||||
|
#include <cassert>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <core/engine.h>
|
#include <core/engine.h>
|
||||||
@@ -173,12 +175,28 @@ void MainTabs::handle_event(const String &event, const Vector<Variant> &args)
|
|||||||
SpinBox *sp_line_index =
|
SpinBox *sp_line_index =
|
||||||
Object::cast_to<SpinBox>(ui_data["line_index"]);
|
Object::cast_to<SpinBox>(ui_data["line_index"]);
|
||||||
sp_line_index->set_value(0);
|
sp_line_index->set_value(0);
|
||||||
|
assert(ui_data.has("road_lines_edge_editor"));
|
||||||
|
assert(ui_data["road_lines_edge_editor"]);
|
||||||
|
Object *obj = ui_data["road_lines_edge_editor"];
|
||||||
|
assert(obj);
|
||||||
|
Control *top = Object::cast_to<Control>(obj);
|
||||||
|
assert(top);
|
||||||
|
create_edge_editor(obj);
|
||||||
} else if (event == "road_lines_editor_set_line_index_ui") {
|
} else if (event == "road_lines_editor_set_line_index_ui") {
|
||||||
int index = args[0];
|
int index = args[0];
|
||||||
SpinBox *sp_line_index =
|
SpinBox *sp_line_index =
|
||||||
Object::cast_to<SpinBox>(ui_data["line_index"]);
|
Object::cast_to<SpinBox>(ui_data["line_index"]);
|
||||||
sp_line_index->set_value(0);
|
sp_line_index->set_value(0);
|
||||||
sp_line_index->set_value(index);
|
sp_line_index->set_value(index);
|
||||||
|
assert(ui_data.has("road_lines_edge_editor"));
|
||||||
|
assert(ui_data["road_lines_edge_editor"]);
|
||||||
|
print_line("create_edge_editor");
|
||||||
|
create_edge_editor(ui_data["road_lines_edge_editor"]);
|
||||||
|
} else if (event == "road_lines_editor_set_line_index::post") {
|
||||||
|
assert(ui_data.has("road_lines_edge_editor"));
|
||||||
|
assert(ui_data["road_lines_edge_editor"]);
|
||||||
|
print_line("create_edge_editor");
|
||||||
|
create_edge_editor(ui_data["road_lines_edge_editor"]);
|
||||||
} else if (event == "road_lines_create_new_line_name:entered") {
|
} else if (event == "road_lines_create_new_line_name:entered") {
|
||||||
Control *dlg = Object::cast_to<Control>(
|
Control *dlg = Object::cast_to<Control>(
|
||||||
ui_data["road_lines_create_new_line_dlg"]);
|
ui_data["road_lines_create_new_line_dlg"]);
|
||||||
@@ -199,6 +217,20 @@ void MainTabs::handle_event(const String &event, const Vector<Variant> &args)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainTabs::create_edge_editor(Control *top)
|
||||||
|
{
|
||||||
|
assert(top);
|
||||||
|
EditorEvent::get_singleton()->event.emit(
|
||||||
|
"road_lines_create_edge_editor", varray(top));
|
||||||
|
}
|
||||||
|
void MainTabs::create_edge_editor(Object *top)
|
||||||
|
{
|
||||||
|
assert(top);
|
||||||
|
Control *top_ctrl = Object::cast_to<Control>(top);
|
||||||
|
assert(top_ctrl);
|
||||||
|
create_edge_editor(top_ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
void MainTabs::_notification(int which)
|
void MainTabs::_notification(int which)
|
||||||
{
|
{
|
||||||
struct StringHasher {
|
struct StringHasher {
|
||||||
@@ -483,15 +515,17 @@ void MainTabs::_notification(int which)
|
|||||||
"", "point_y",
|
"", "point_y",
|
||||||
"", "point_z",
|
"", "point_z",
|
||||||
"Set", "road_lines_set_point_position",
|
"Set", "road_lines_set_point_position",
|
||||||
|
"Edge properties",
|
||||||
|
"road_lines_edge_editor",
|
||||||
"road_lines_create_new_line_dlg",
|
"road_lines_create_new_line_dlg",
|
||||||
"", "road_lines_create_new_line_name",
|
"", "road_lines_create_new_line_name",
|
||||||
"Cancel", "road_lines_create_new_cancel"
|
"Cancel", "road_lines_create_new_cancel",
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
};
|
};
|
||||||
HashMap<String, Object *> save_data;
|
HashMap<String, Object *> save_data;
|
||||||
ui_field::ui_field_builder(
|
ui_field::ui_field_builder(
|
||||||
this, tab,
|
this, tab,
|
||||||
"v{p#!{v{lh#!{m#!m#!m#!m#!m#!}_lh{le#!$}i.#!$x#!$_lv#!{h{e#!$e#!$e#!$b#$}}_lv#!{h{e#!$e#!$e#!$b#$}}}}p#!${v{e#!$b#!$}}}",
|
"v{p#!{v{lh#!{m#!m#!m#!m#!m#!}_lh{le#!$}i.#!$x#!$_lv#!{h{e#!$e#!$e#!$b#$}}_lv#!{h{e#!$e#!$e#!$b#$}}p{v{lv#!${}}}}}p#!${v{e#!$b#!$}}}",
|
||||||
// "p{v{lh#!{m#!m#!m#!m#!m#!}_lh{le#!}i.#!x#!_lv#!{h{e#!e#!e#!b#!}}_lv#!{h{e#!e#!e#!b#!}}}}",
|
// "p{v{lh#!{m#!m#!m#!m#!m#!}_lh{le#!}i.#!x#!_lv#!{h{e#!e#!e#!b#!}}_lv#!{h{e#!e#!e#!b#!}}}}",
|
||||||
args_data.data(), args_data.size(),
|
args_data.data(), args_data.size(),
|
||||||
&save_data);
|
&save_data);
|
||||||
@@ -509,13 +543,14 @@ void MainTabs::_notification(int which)
|
|||||||
"line_index",
|
"line_index",
|
||||||
"road_lines_create_new_line_dlg",
|
"road_lines_create_new_line_dlg",
|
||||||
"road_lines_create_new_line_name",
|
"road_lines_create_new_line_name",
|
||||||
"road_lines_create_new_cancel"
|
"road_lines_create_new_cancel",
|
||||||
|
"road_lines_edge_editor"
|
||||||
};
|
};
|
||||||
int el;
|
int el;
|
||||||
for (el = 0; el < (int)elements.size(); el++) {
|
for (el = 0; el < (int)elements.size(); el++) {
|
||||||
String elname = elements[el];
|
String elname = elements[el];
|
||||||
assert(save_data.has(elname));
|
assert(save_data.has(elname));
|
||||||
ui_data[elname] = save_data[elname];
|
ui_data.set(elname, save_data[elname]);
|
||||||
Button *button =
|
Button *button =
|
||||||
Object::cast_to<Button>(
|
Object::cast_to<Button>(
|
||||||
ui_data[elname]);
|
ui_data[elname]);
|
||||||
@@ -528,16 +563,20 @@ void MainTabs::_notification(int which)
|
|||||||
ui_data[elname]);
|
ui_data[elname]);
|
||||||
memnew(LineEditString(le,
|
memnew(LineEditString(le,
|
||||||
elname));
|
elname));
|
||||||
}
|
} else if (elname == "lines_list") {
|
||||||
if (elname == "line_index") {
|
ItemList *lines_list =
|
||||||
|
Object::cast_to<ItemList>(
|
||||||
|
ui_data[elname]);
|
||||||
|
lines_list->set_allow_reselect(
|
||||||
|
true);
|
||||||
|
} else if (elname == "line_index") {
|
||||||
SpinBox *sb =
|
SpinBox *sb =
|
||||||
Object::cast_to<SpinBox>(
|
Object::cast_to<SpinBox>(
|
||||||
ui_data[elname]);
|
ui_data[elname]);
|
||||||
memnew(SpinBoxHandler(
|
memnew(SpinBoxHandler(
|
||||||
sb,
|
sb,
|
||||||
"road_lines_editor_set_line_index"));
|
"road_lines_editor_set_line_index"));
|
||||||
}
|
} else if (elname ==
|
||||||
if (elname ==
|
|
||||||
"road_lines_create_new_line_name") {
|
"road_lines_create_new_line_name") {
|
||||||
LineEdit *le = Object::cast_to<
|
LineEdit *le = Object::cast_to<
|
||||||
LineEdit>(
|
LineEdit>(
|
||||||
@@ -548,6 +587,22 @@ void MainTabs::_notification(int which)
|
|||||||
memnew(LineEditString(
|
memnew(LineEditString(
|
||||||
le,
|
le,
|
||||||
elname + ":changed"));
|
elname + ":changed"));
|
||||||
|
} else if (elname ==
|
||||||
|
"road_lines_create_new_line_dlg") {
|
||||||
|
Control *c =
|
||||||
|
Object::cast_to<Control>(
|
||||||
|
ui_data[elname]);
|
||||||
|
c->hide();
|
||||||
|
} else if (elname ==
|
||||||
|
"road_lines_edge_editor") {
|
||||||
|
Object *obj = ui_data[elname];
|
||||||
|
assert(obj);
|
||||||
|
Control *ctrl =
|
||||||
|
Object::cast_to<Control>(
|
||||||
|
obj);
|
||||||
|
assert(ctrl);
|
||||||
|
create_edge_editor(
|
||||||
|
ui_data[elname]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -8,10 +8,63 @@ class MainTabs : public TabContainer {
|
|||||||
Vector<Object *> handlers;
|
Vector<Object *> handlers;
|
||||||
WindowDialog *npc_editor;
|
WindowDialog *npc_editor;
|
||||||
WindowDialog *building_layouts_editor;
|
WindowDialog *building_layouts_editor;
|
||||||
|
struct ui_data {
|
||||||
|
private:
|
||||||
HashMap<String, Object *> ui_data;
|
HashMap<String, Object *> ui_data;
|
||||||
|
Object *get(const String &key) const
|
||||||
|
{
|
||||||
|
if (key == "road_lines_edge_editor") {
|
||||||
|
assert(ui_data.has(key));
|
||||||
|
Object *obj = ui_data[key];
|
||||||
|
assert(obj);
|
||||||
|
Control *ctrl = Object::cast_to<Control>(obj);
|
||||||
|
assert(ctrl);
|
||||||
|
return ctrl;
|
||||||
|
} else
|
||||||
|
return ui_data[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
Object *operator[](const char *key) const
|
||||||
|
{
|
||||||
|
return get(key);
|
||||||
|
}
|
||||||
|
Object *operator[](const String &key) const
|
||||||
|
{
|
||||||
|
return get(key);
|
||||||
|
}
|
||||||
|
void set(const char *key, Object *obj)
|
||||||
|
{
|
||||||
|
if (!strcmp("road_lines_edge_editor", key)) {
|
||||||
|
assert(obj);
|
||||||
|
Control *ctrl = Object::cast_to<Control>(obj);
|
||||||
|
assert(ctrl);
|
||||||
|
ui_data[key] = ctrl;
|
||||||
|
} else
|
||||||
|
ui_data[key] = obj;
|
||||||
|
}
|
||||||
|
void set(const String &key, Object *obj)
|
||||||
|
{
|
||||||
|
set(key.ascii().ptr(), obj);
|
||||||
|
}
|
||||||
|
void get_key_list(List<String> *keys)
|
||||||
|
{
|
||||||
|
ui_data.get_key_list(keys);
|
||||||
|
}
|
||||||
|
bool has(const char *key)
|
||||||
|
{
|
||||||
|
return ui_data.has(key);
|
||||||
|
}
|
||||||
|
bool has(const String &key)
|
||||||
|
{
|
||||||
|
return ui_data.has(key);
|
||||||
|
}
|
||||||
|
} ui_data;
|
||||||
template <class T>
|
template <class T>
|
||||||
inline void mode_visibility(int mode, const String &path);
|
inline void mode_visibility(int mode, const String &path);
|
||||||
void handle_event(const String &event, const Vector<Variant> &args);
|
void handle_event(const String &event, const Vector<Variant> &args);
|
||||||
|
void create_edge_editor(Control *top);
|
||||||
|
void create_edge_editor(Object *top);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void _notification(int which);
|
void _notification(int which);
|
||||||
|
|||||||
@@ -66,26 +66,6 @@ public:
|
|||||||
String text = editor->get_current_line_metadata();
|
String text = editor->get_current_line_metadata();
|
||||||
metadata_edit->set_text(text);
|
metadata_edit->set_text(text);
|
||||||
}
|
}
|
||||||
void update_line_buildings_editor()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
if (editor->get_current_line() == "")
|
|
||||||
return;
|
|
||||||
ItemList *items =
|
|
||||||
gui->get_as_node<ItemList>("%line_buildings_list");
|
|
||||||
items->clear();
|
|
||||||
for (i = 0; i < (int)RoadLinesData::get_singleton()
|
|
||||||
->lines(editor->get_current_line())
|
|
||||||
.buildings.size();
|
|
||||||
i++) {
|
|
||||||
const String &key =
|
|
||||||
RoadLinesData::get_singleton()
|
|
||||||
->lines(editor->get_current_line())
|
|
||||||
.buildings[i]
|
|
||||||
.building_key;
|
|
||||||
items->add_item(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void main_handler(int id)
|
void main_handler(int id)
|
||||||
{
|
{
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@@ -128,16 +108,11 @@ public:
|
|||||||
case 33:
|
case 33:
|
||||||
editor->remove_road_meshes();
|
editor->remove_road_meshes();
|
||||||
break;
|
break;
|
||||||
case 34: {
|
case 34:
|
||||||
RoadLinesData::get_singleton()->assign_close_buildings(
|
assert(false);
|
||||||
editor->get_current_line());
|
break;
|
||||||
editor->update_line_geometry();
|
|
||||||
} break;
|
|
||||||
case 36:
|
case 36:
|
||||||
editor->get_as_node<Control>("%road_lines_base")->hide();
|
assert(false);
|
||||||
editor->get_as_node<Control>("%road_lines_buildings")
|
|
||||||
->show();
|
|
||||||
update_line_buildings_editor();
|
|
||||||
break;
|
break;
|
||||||
case 51:
|
case 51:
|
||||||
editor->set_point_to_cursor();
|
editor->set_point_to_cursor();
|
||||||
|
|||||||
Reference in New Issue
Block a user