mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
623 Commits
improve-un
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8602c8e15f | ||
![]() |
017d9930aa | ||
![]() |
b9aef05f8a | ||
![]() |
e95d208e7d | ||
![]() |
162a70316a | ||
![]() |
10e8094375 | ||
![]() |
82af8dd7f3 | ||
![]() |
8cf739aa78 | ||
![]() |
f3f3d24706 | ||
![]() |
83f80b2350 | ||
![]() |
1172326ae0 | ||
![]() |
aed09d86b3 | ||
![]() |
c2d03050b8 | ||
![]() |
2e941c5afc | ||
![]() |
a3f80f2607 | ||
![]() |
3497eb2945 | ||
![]() |
b9a1f50d13 | ||
![]() |
52d239b60c | ||
![]() |
c549e277a7 | ||
![]() |
afed5d57f7 | ||
![]() |
a3f7176c42 | ||
![]() |
223268554b | ||
![]() |
43ef037a07 | ||
![]() |
20d2e06fc6 | ||
![]() |
9f795c405a | ||
![]() |
0155344ec3 | ||
![]() |
71d6d6a165 | ||
![]() |
edd14b5f8b | ||
![]() |
77d60b699b | ||
![]() |
5bc80537b7 | ||
![]() |
f93b850382 | ||
![]() |
da7cae08a1 | ||
![]() |
0ae68877b7 | ||
![]() |
32c4e040e0 | ||
![]() |
74034a0ac1 | ||
![]() |
1b41225822 | ||
![]() |
c620ed75b3 | ||
![]() |
edc577067b | ||
![]() |
e00a85909d | ||
![]() |
70e6fc7f7f | ||
![]() |
b9a899f82e | ||
![]() |
c38d14ca83 | ||
![]() |
e6b6406a95 | ||
![]() |
ff7c6de660 | ||
![]() |
8d78ec6070 | ||
![]() |
3c2876e08d | ||
![]() |
a68bac6667 | ||
![]() |
53eafe098c | ||
![]() |
ab519d41a1 | ||
![]() |
5ea03b83f0 | ||
![]() |
f2d4778459 | ||
![]() |
56662fb9b5 | ||
![]() |
0788de3d87 | ||
![]() |
6b7bc361a7 | ||
![]() |
32a6e188e7 | ||
![]() |
00f67ca7c7 | ||
![]() |
bb5291ac6f | ||
![]() |
a2ea751007 | ||
![]() |
1a4270195b | ||
![]() |
3df42cce3e | ||
![]() |
b8de302f7e | ||
![]() |
6a2bc6109c | ||
![]() |
0383f8a7e1 | ||
![]() |
bde7e1896d | ||
![]() |
32d855992e | ||
![]() |
d54c1e2f38 | ||
![]() |
f09a1dd5b2 | ||
![]() |
f4e3f2449a | ||
![]() |
a6b2cba281 | ||
![]() |
54237114d9 | ||
![]() |
3c5bcf2762 | ||
![]() |
d66ea06a4c | ||
![]() |
228479c81b | ||
![]() |
1e55c359d8 | ||
![]() |
451d525b36 | ||
![]() |
c755946d42 | ||
![]() |
7a6b6fbf7f | ||
![]() |
730c8283e5 | ||
![]() |
7ea250706c | ||
![]() |
db7a108354 | ||
![]() |
2e15d68bce | ||
![]() |
f6c9e1408c | ||
![]() |
0b3d4d048a | ||
![]() |
5d625dd497 | ||
![]() |
079eca829a | ||
![]() |
35b5f92c59 | ||
![]() |
70eb95b132 | ||
![]() |
7c7ee8b7fc | ||
![]() |
3556dd2e3c | ||
![]() |
f74f77f66a | ||
![]() |
712eb4b647 | ||
![]() |
c4474c766d | ||
![]() |
ad17a21973 | ||
![]() |
5001411ccb | ||
![]() |
05939f5c3e | ||
![]() |
91978d4c6e | ||
![]() |
d6433d89f0 | ||
![]() |
e652ab9f5a | ||
![]() |
e7decc7b92 | ||
![]() |
33dcc04112 | ||
![]() |
58ba2668c2 | ||
![]() |
b34e802dcb | ||
![]() |
31dac9cc93 | ||
![]() |
ab97258832 | ||
![]() |
2ece223737 | ||
![]() |
8342873b6e | ||
![]() |
0a85fd3814 | ||
![]() |
fe15b6d30b | ||
![]() |
f3c3559518 | ||
![]() |
a403b1343b | ||
![]() |
83dba6c21e | ||
![]() |
7a4aea6557 | ||
![]() |
82a6abacb4 | ||
![]() |
f60613cc64 | ||
![]() |
274aedb3d9 | ||
![]() |
efb31c3caf | ||
![]() |
6781c0fd6e | ||
![]() |
e9781133e1 | ||
![]() |
8972e0e3a6 | ||
![]() |
4c76a5979b | ||
![]() |
484a0daec4 | ||
![]() |
de432c1bf2 | ||
![]() |
8c7dcc1c23 | ||
![]() |
39648af248 | ||
![]() |
5c7bbf5293 | ||
![]() |
9d97b9d0eb | ||
![]() |
b39b12864f | ||
![]() |
2c3dbbbbde | ||
![]() |
72cc60bae9 | ||
![]() |
c03e94849b | ||
![]() |
80daaf5e5b | ||
![]() |
cb457cfd04 | ||
![]() |
0a55aa631b | ||
![]() |
8e104f9ae4 | ||
![]() |
a90b9a27e9 | ||
![]() |
6321e82f63 | ||
![]() |
05fc63ab1b | ||
![]() |
85a6a21934 | ||
![]() |
a9741e7b42 | ||
![]() |
23afe7b71c | ||
![]() |
85757e6d98 | ||
![]() |
524ca4dbb3 | ||
![]() |
55cf710ef5 | ||
![]() |
eee7e7f04c | ||
![]() |
ecd984e08b | ||
![]() |
d0a7fbbd02 | ||
![]() |
2a2c930b74 | ||
![]() |
f6cb203029 | ||
![]() |
fe743bbe57 | ||
![]() |
78c31408d4 | ||
![]() |
75a038344a | ||
![]() |
f0567b674c | ||
![]() |
9b85f35856 | ||
![]() |
f4568febf2 | ||
![]() |
de7f60b693 | ||
![]() |
3a595b200e | ||
![]() |
431b5929e8 | ||
![]() |
ec2e82cee5 | ||
![]() |
76517f1a2a | ||
![]() |
43f5bd1c0e | ||
![]() |
7198a22ae2 | ||
![]() |
46c52905f6 | ||
![]() |
40954bf497 | ||
![]() |
02c06ac6e7 | ||
![]() |
1fa3f59a77 | ||
![]() |
cc371273ce | ||
![]() |
364ec2ecfb | ||
![]() |
0d36a27b87 | ||
![]() |
6d597a430b | ||
![]() |
27b71b08e5 | ||
![]() |
82158f7073 | ||
![]() |
8ba352d4ba | ||
![]() |
6cda5d08be | ||
![]() |
1a3a27b73b | ||
![]() |
96d912a6f2 | ||
![]() |
ed3acd5f0d | ||
![]() |
3f269206d1 | ||
![]() |
76b5aefdbc | ||
![]() |
9ef7af803c | ||
![]() |
c77f9b9e0c | ||
![]() |
035ddb8a7a | ||
![]() |
e7dac1bafc | ||
![]() |
54f00e7c57 | ||
![]() |
0bf9dae2b0 | ||
![]() |
428aac8ab0 | ||
![]() |
9391fc2841 | ||
![]() |
cea34337c6 | ||
![]() |
dc45f3dae5 | ||
![]() |
0ca26a865e | ||
![]() |
1bce13f326 | ||
![]() |
34f8f5750a | ||
![]() |
3b9a612094 | ||
![]() |
3a84ed7c89 | ||
![]() |
ef604fd442 | ||
![]() |
d88dc4772f | ||
![]() |
02d40a1d52 | ||
![]() |
35082825d4 | ||
![]() |
6a7c3daa8e | ||
![]() |
95af02bada | ||
![]() |
30516a903e | ||
![]() |
762f7ca19c | ||
![]() |
852bf78c81 | ||
![]() |
b0da0cee34 | ||
![]() |
73771f938b | ||
![]() |
b9dbe6dbb5 | ||
![]() |
0c2341c6e5 | ||
![]() |
e9b4de2ca9 | ||
![]() |
75a4114ce8 | ||
![]() |
20abb9b45a | ||
![]() |
56436fd44a | ||
![]() |
0dd5fc55c9 | ||
![]() |
93db4cb508 | ||
![]() |
f7888abf45 | ||
![]() |
c8144da704 | ||
![]() |
832e8cd593 | ||
![]() |
ef66a9f1a4 | ||
![]() |
5efbaa8c58 | ||
![]() |
ecbf38ccda | ||
![]() |
b3fcfc3f55 | ||
![]() |
a515836add | ||
![]() |
a7c81b47b2 | ||
![]() |
0f22e462ad | ||
![]() |
e6e4d9048f | ||
![]() |
12f5f95d0c | ||
![]() |
c52168a967 | ||
![]() |
1e33a13cc5 | ||
![]() |
505debd60c | ||
![]() |
e3b7109154 | ||
![]() |
9e25899d3e | ||
![]() |
87cb8f0d47 | ||
![]() |
481c6da992 | ||
![]() |
7cbebbb82f | ||
![]() |
fcf668788b | ||
![]() |
0cc844a77f | ||
![]() |
a234d9bd35 | ||
![]() |
465a6ce2ab | ||
![]() |
7e2e19eb33 | ||
![]() |
95101763f7 | ||
![]() |
d4bd5fc671 | ||
![]() |
c7fcf48ba5 | ||
![]() |
8926d4406f | ||
![]() |
9ed2173038 | ||
![]() |
2fc3bc337f | ||
![]() |
0b7cac79ef | ||
![]() |
8721c0099e | ||
![]() |
4453eee3b9 | ||
![]() |
0215ab7dbb | ||
![]() |
87f6d5b99f | ||
![]() |
a440b16f84 | ||
![]() |
f3822ba0df | ||
![]() |
6c5813affd | ||
![]() |
be4fe62bb6 | ||
![]() |
0a29999894 | ||
![]() |
e8ac41f37e | ||
![]() |
70657ae334 | ||
![]() |
39ae2d4852 | ||
![]() |
39815bfe6c | ||
![]() |
9ff8db25dd | ||
![]() |
1da887f656 | ||
![]() |
e88ae0a7a9 | ||
![]() |
7ae74990b2 | ||
![]() |
22ea1ce42c | ||
![]() |
a54367e360 | ||
![]() |
011abaf808 | ||
![]() |
a606a6567a | ||
![]() |
c9a6b88422 | ||
![]() |
e7f7fb1583 | ||
![]() |
3cbb6644d4 | ||
![]() |
d34db53e09 | ||
![]() |
9c62a5e0f1 | ||
![]() |
4b04101638 | ||
![]() |
ad31a7843a | ||
![]() |
57371c3759 | ||
![]() |
6e7fc75e75 | ||
![]() |
65653c92d6 | ||
![]() |
a4106b7f79 | ||
![]() |
3e9f2f3f3a | ||
![]() |
45f25df292 | ||
![]() |
55eddb4972 | ||
![]() |
75566c9f38 | ||
![]() |
8db8cbe3c2 | ||
![]() |
dd8c5dce2e | ||
![]() |
2810056626 | ||
![]() |
d082d4f5a4 | ||
![]() |
eaa0f4077f | ||
![]() |
7d73f58bc4 | ||
![]() |
9171b40429 | ||
![]() |
242fc49342 | ||
![]() |
7081fd570c | ||
![]() |
34ecdce7fa | ||
![]() |
3a0903a19f | ||
![]() |
e1a4f88ba6 | ||
![]() |
ed59498835 | ||
![]() |
4b70653a0b | ||
![]() |
48dd91043a | ||
![]() |
30e7ef5865 | ||
![]() |
289c555fe4 | ||
![]() |
803a55869c | ||
![]() |
282f4c184f | ||
![]() |
875237cc8b | ||
![]() |
7aeb44d05e | ||
![]() |
e445ff710e | ||
![]() |
e016babf71 | ||
![]() |
6a34e3c1db | ||
![]() |
82e819c033 | ||
![]() |
72e5deeef3 | ||
![]() |
a91cc4557f | ||
![]() |
b2c953a31d | ||
![]() |
b29fbaa1f8 | ||
![]() |
e8faa17e12 | ||
![]() |
2585ad5dca | ||
![]() |
a9108fa87b | ||
![]() |
cd3186d2d8 | ||
![]() |
6a737f7d51 | ||
![]() |
9211aa7a3b | ||
![]() |
864ba181e9 | ||
![]() |
10fa3296a9 | ||
![]() |
2fb39b9dbe | ||
![]() |
6f43e896d6 | ||
![]() |
122df05f99 | ||
![]() |
b7a5122b07 | ||
![]() |
eb9d680d95 | ||
![]() |
354da42a9e | ||
![]() |
aca37fdade | ||
![]() |
bb6eb01153 | ||
![]() |
9fb086dcdf | ||
![]() |
7e60a0246e | ||
![]() |
3cb2da3de5 | ||
![]() |
ef23470a00 | ||
![]() |
196ea5e480 | ||
![]() |
e732f1952c | ||
![]() |
f5f024cc42 | ||
![]() |
6a3df62598 | ||
![]() |
75f049d911 | ||
![]() |
4d0ac6f355 | ||
![]() |
00a5c93b35 | ||
![]() |
a90cc83967 | ||
![]() |
87a5934df3 | ||
![]() |
d0245b8f1a | ||
![]() |
45d73df6fb | ||
![]() |
7ac600e92d | ||
![]() |
7ba8d0133e | ||
![]() |
e9adaa94c5 | ||
![]() |
35da31c5c5 | ||
![]() |
e65492e1a1 | ||
![]() |
44827ea372 | ||
![]() |
ab3ffe6785 | ||
![]() |
d83d049ac9 | ||
![]() |
67a7bd7af2 | ||
![]() |
6db5267878 | ||
![]() |
a51c223c9c | ||
![]() |
0a4e5a1012 | ||
![]() |
acce714736 | ||
![]() |
3c34a8806b | ||
![]() |
1d4cb7bef0 | ||
![]() |
7badacd24a | ||
![]() |
11ab92fc0e | ||
![]() |
ddb1e335bc | ||
![]() |
8d035a774d | ||
![]() |
5b1e3565d3 | ||
![]() |
8c88038bfb | ||
![]() |
f62811974d | ||
![]() |
b516037d2b | ||
![]() |
98befc8000 | ||
![]() |
377231fb37 | ||
![]() |
22ae8ac489 | ||
![]() |
40674fd3b9 | ||
![]() |
0792e59b24 | ||
![]() |
8ba6ad7b43 | ||
![]() |
84b07bc84d | ||
![]() |
c46d39cbed | ||
![]() |
b96132964c | ||
![]() |
130cd1e3a7 | ||
![]() |
fbbcf25bf5 | ||
![]() |
ffaae4d3d4 | ||
![]() |
75d79a7758 | ||
![]() |
d91fb78848 | ||
![]() |
e0a2ed1654 | ||
![]() |
d5f2be1c19 | ||
![]() |
7abcfe8af2 | ||
![]() |
b86dd9efce | ||
![]() |
15f6b62c5b | ||
![]() |
eb995ec7c7 | ||
![]() |
a076571120 | ||
![]() |
ec9cb790e7 | ||
![]() |
4a283add00 | ||
![]() |
6b3faa42bb | ||
![]() |
555ee61e63 | ||
![]() |
b838c8549b | ||
![]() |
33db6ee359 | ||
![]() |
f361d3e1fa | ||
![]() |
441401f34c | ||
![]() |
558daa2075 | ||
![]() |
cd475316df | ||
![]() |
8b21e72c85 | ||
![]() |
a9d6f18c11 | ||
![]() |
f58e1113b6 | ||
![]() |
f82b5fc66d | ||
![]() |
2f19a9bb33 | ||
![]() |
8f739d85c2 | ||
![]() |
f23847617d | ||
![]() |
876332a782 | ||
![]() |
93c74c9fd6 | ||
![]() |
e92d8496ac | ||
![]() |
35e67a6d26 | ||
![]() |
740c7ae8bc | ||
![]() |
432a91c47b | ||
![]() |
799bc762aa | ||
![]() |
147a0eed53 | ||
![]() |
920e1d423f | ||
![]() |
c013f319ee | ||
![]() |
db53e84c6f | ||
![]() |
4b85f710a9 | ||
![]() |
07a350dadd | ||
![]() |
7ccbf91973 | ||
![]() |
410fecf715 | ||
![]() |
967bf5cbe3 | ||
![]() |
0020f72850 | ||
![]() |
0eb7b85e77 | ||
![]() |
063bf51783 | ||
![]() |
482fb3b85e | ||
![]() |
9a4a84d2af | ||
![]() |
9a705b98e2 | ||
![]() |
da940abdc2 | ||
![]() |
528b8f4e6c | ||
![]() |
7212d56a1b | ||
![]() |
5cba43335c | ||
![]() |
324698e269 | ||
![]() |
d219bf05d3 | ||
![]() |
9cbc421d74 | ||
![]() |
f63d9d1b5c | ||
![]() |
dd5d0669b1 | ||
![]() |
e681632e60 | ||
![]() |
0bcb219e00 | ||
![]() |
6d5e9c1676 | ||
![]() |
5ded5648bf | ||
![]() |
687f926bc5 | ||
![]() |
4a2d573956 | ||
![]() |
ce77414f85 | ||
![]() |
298ff6311d | ||
![]() |
ca0a000ae1 | ||
![]() |
dc87f138a6 | ||
![]() |
28af860aff | ||
![]() |
4dbc607314 | ||
![]() |
bfefe9baf4 | ||
![]() |
2332359c19 | ||
![]() |
68b6c443c3 | ||
![]() |
37e113baaa | ||
![]() |
a8a8c142a3 | ||
![]() |
012e625a47 | ||
![]() |
c0e6d98e4c | ||
![]() |
ab63e02862 | ||
![]() |
1b13127a2f | ||
![]() |
3de0861172 | ||
![]() |
795417c915 | ||
![]() |
e8540dd720 | ||
![]() |
3c5fee0535 | ||
![]() |
7f2806bd89 | ||
![]() |
886fdb464e | ||
![]() |
6aaeda6c49 | ||
![]() |
830e35b368 | ||
![]() |
fa4a621888 | ||
![]() |
8756932c12 | ||
![]() |
0b5f929773 | ||
![]() |
183fba4720 | ||
![]() |
9d608a0e93 | ||
![]() |
5bbfd81d89 | ||
![]() |
a441bb04ef | ||
![]() |
ccf5e390d6 | ||
![]() |
e633aa77c2 | ||
![]() |
12275d0814 | ||
![]() |
4ed1889856 | ||
![]() |
ae6ac2068b | ||
![]() |
a31c5cfac3 | ||
![]() |
1917d5aedd | ||
![]() |
d0c85cd3bc | ||
![]() |
afed90ccef | ||
![]() |
ff9c6e5cf3 | ||
![]() |
199d315e29 | ||
![]() |
ddf426c2fd | ||
![]() |
43648b0a18 | ||
![]() |
96e5d6966a | ||
![]() |
eb256b3412 | ||
![]() |
d89bfd27f8 | ||
![]() |
7cef3b3a41 | ||
![]() |
f3a87a2159 | ||
![]() |
4df91f3e77 | ||
![]() |
8ca82ef457 | ||
![]() |
0c3719ff0c | ||
![]() |
a76ba988b2 | ||
![]() |
8f002541ef | ||
![]() |
6fd82376a8 | ||
![]() |
db2d6f90a3 | ||
![]() |
f32180d923 | ||
![]() |
4886cf4fd3 | ||
![]() |
0fd25c381a | ||
![]() |
916e642465 | ||
![]() |
eaebc16f49 | ||
![]() |
231d92a2fa | ||
![]() |
e3cc01e902 | ||
![]() |
fe68286eaf | ||
![]() |
7d95e44b51 | ||
![]() |
9b448f1ddf | ||
![]() |
8f34a100e5 | ||
![]() |
cc3a9af8ce | ||
![]() |
75bfa5cb45 | ||
![]() |
5ac8f411fe | ||
![]() |
870247a3df | ||
![]() |
80b68d3bb5 | ||
![]() |
6e8a8d6868 | ||
![]() |
2310f2a618 | ||
![]() |
f8bd3fca00 | ||
![]() |
92b9203ce8 | ||
![]() |
4ca859c8b9 | ||
![]() |
701b5a3250 | ||
![]() |
1e87b74d48 | ||
![]() |
b7a4bab53c | ||
![]() |
2223b6516b | ||
![]() |
7d89208e7b | ||
![]() |
70508292e4 | ||
![]() |
c899db1dba | ||
![]() |
2fb27f430e | ||
![]() |
6cd2400848 | ||
![]() |
fadccba757 | ||
![]() |
29a43514ce | ||
![]() |
e64ab94f76 | ||
![]() |
ed969d2909 | ||
![]() |
77bf67fdf0 | ||
![]() |
580c7a370c | ||
![]() |
266f0f2b6e | ||
![]() |
58af6aacb4 | ||
![]() |
1c4ee1c928 | ||
![]() |
0275476bec | ||
![]() |
3f0194acf0 | ||
![]() |
017d8b28c2 | ||
![]() |
4b518ba0fc | ||
![]() |
e4938b25b5 | ||
![]() |
c56ad2d277 | ||
![]() |
f069f9d942 | ||
![]() |
9f7c60a69e | ||
![]() |
774bf0db61 | ||
![]() |
ccd9c5c0ff | ||
![]() |
5b130a34e3 | ||
![]() |
3e6d147660 | ||
![]() |
433d85db94 | ||
![]() |
b75f707b30 | ||
![]() |
67799eb3eb | ||
![]() |
1173210386 | ||
![]() |
007cc48291 | ||
![]() |
12813c9ad9 | ||
![]() |
e503e34059 | ||
![]() |
4bf576a889 | ||
![]() |
eff1c1bcb6 | ||
![]() |
abce34f2b1 | ||
![]() |
07276d5e16 | ||
![]() |
1fdd8cc792 | ||
![]() |
79e40605d5 | ||
![]() |
fcc91e3fea | ||
![]() |
5c66623631 | ||
![]() |
5637642e1b | ||
![]() |
7e8b44af2e | ||
![]() |
0dd4650aae | ||
![]() |
c7cac31830 | ||
![]() |
56cb8581c4 | ||
![]() |
1993040b70 | ||
![]() |
883991081a | ||
![]() |
7d8afef1ad | ||
![]() |
8178595546 | ||
![]() |
a478068c64 | ||
![]() |
368da1b610 | ||
![]() |
4ee43202e9 | ||
![]() |
602fdf4bfd | ||
![]() |
6110acafcc | ||
![]() |
a3696ca9d1 | ||
![]() |
1bb473b0b0 | ||
![]() |
4376b4f36e | ||
![]() |
6ecbae9c35 | ||
![]() |
93e9fc6aed | ||
![]() |
7c0a7a4152 | ||
![]() |
d4cdb3ff83 | ||
![]() |
a7cac91e45 | ||
![]() |
6a6d72cd9a | ||
![]() |
11d74b3ea5 | ||
![]() |
5b65cf84eb | ||
![]() |
6b7af0474f | ||
![]() |
99f7e55044 | ||
![]() |
6b522b1c31 | ||
![]() |
0f35e48690 | ||
![]() |
53d19dd628 | ||
![]() |
155dc1bec8 | ||
![]() |
be26e39eae | ||
![]() |
90fa5ea8e8 | ||
![]() |
4845251f78 | ||
![]() |
31ef3fec58 | ||
![]() |
292b23ea17 | ||
![]() |
9c5a5db7a8 | ||
![]() |
d73ae4c56e | ||
![]() |
339929e021 | ||
![]() |
cea1cf20f1 | ||
![]() |
4ec2705f75 | ||
![]() |
408f6f8134 | ||
![]() |
c64bac0010 | ||
![]() |
f8d5c89ebf | ||
![]() |
ca3bb40e96 | ||
![]() |
713d437b70 | ||
![]() |
09381c3836 | ||
![]() |
ea4c2e0827 | ||
![]() |
a5d1149c21 | ||
![]() |
119b0fadce | ||
![]() |
7111859768 | ||
![]() |
08dfb4d36b | ||
![]() |
cacd482af9 | ||
![]() |
3568a58019 | ||
![]() |
a32d5fcd7e | ||
![]() |
1a999fd2dd | ||
![]() |
76648764bb | ||
![]() |
c25803c122 | ||
![]() |
ba8d7f4e38 | ||
![]() |
e1c22f6994 | ||
![]() |
7b70f9172f | ||
![]() |
a871e0f2ec | ||
![]() |
f6499e1163 | ||
![]() |
d03e58636d |
@@ -11,13 +11,24 @@
|
||||
version: 2.1
|
||||
orbs:
|
||||
aws-cli: circleci/aws-cli@2.0.6
|
||||
macos: circleci/macos@2.5.1 # For Rosetta (see below)
|
||||
node: circleci/node@5.2.0 # For a recent npm version (see below)
|
||||
jobs:
|
||||
# Build the **entire** app for macOS.
|
||||
build-macos:
|
||||
macos:
|
||||
xcode: 14.2.0
|
||||
resource_class: macos.m1.large.gen1
|
||||
steps:
|
||||
- checkout
|
||||
# Install Rosetta for AWS CLI and disable TSO to speed up S3 uploads (https://support.circleci.com/hc/en-us/articles/19334402064027-Troubleshooting-slow-uploads-to-S3-for-jobs-using-an-m1-macOS-resource-class)
|
||||
- macos/install-rosetta
|
||||
- run: sudo sysctl net.inet.tcp.tso=0
|
||||
|
||||
# Install a recent version of npm to workaround a notarization issue because of a symlink made by npm: https://github.com/electron-userland/electron-builder/issues/7755
|
||||
# Node.js v20.14.0 comes with npm v10.7.0.
|
||||
- node/install:
|
||||
node-version: "20.14.0"
|
||||
|
||||
# System dependencies (for Emscripten and upload)
|
||||
- run:
|
||||
@@ -30,7 +41,7 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Install Emscripten (for GDevelop.js)
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.66 && ./emsdk activate 3.1.66 && cd ..
|
||||
|
||||
# GDevelop.js dependencies
|
||||
- restore_cache:
|
||||
@@ -107,7 +118,7 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Install Emscripten (for GDevelop.js)
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.66 && ./emsdk activate 3.1.66 && cd ..
|
||||
|
||||
- run:
|
||||
name: Install system dependencies for Electron builder
|
||||
@@ -165,6 +176,7 @@ jobs:
|
||||
|
||||
# Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use).
|
||||
build-gdevelop_js-wasm-only:
|
||||
resource_class: medium+ # Compilation time decrease linearly with the number of CPUs, but not linking (so "large" does not speedup total build time).
|
||||
docker:
|
||||
- image: cimg/node:16.13
|
||||
|
||||
@@ -185,7 +197,7 @@ jobs:
|
||||
|
||||
- run:
|
||||
name: Install Emscripten (for GDevelop.js)
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.66 && ./emsdk activate 3.1.66 && cd ..
|
||||
|
||||
# GDevelop.js dependencies
|
||||
- restore_cache:
|
||||
@@ -221,10 +233,83 @@ jobs:
|
||||
name: Deploy to S3 (latest)
|
||||
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/latest/
|
||||
|
||||
# Build the WebAssembly library with clang-tidy and memory sanitizers.
|
||||
build-gdevelop_js-debug-sanitizers-and-extra-checks:
|
||||
resource_class: xlarge # Total time decrease linearly with the number of CPUs.
|
||||
docker:
|
||||
- image: cimg/node:16.13
|
||||
|
||||
working_directory: ~/GDevelop
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
- aws-cli/setup
|
||||
|
||||
# System dependencies (for Emscripten)
|
||||
- run:
|
||||
name: Install dependencies for Emscripten
|
||||
command: sudo apt-get update && sudo apt install cmake
|
||||
|
||||
- run:
|
||||
name: Install dependencies for clang-tidy v19
|
||||
command: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 19 && sudo apt install clang-tidy-19
|
||||
|
||||
- run:
|
||||
name: Install Python3 dependencies for Emscripten
|
||||
command: sudo apt install python-is-python3 python3-distutils -y
|
||||
|
||||
- run:
|
||||
name: Install Emscripten (for GDevelop.js)
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
||||
|
||||
# GDevelop.js dependencies
|
||||
- restore_cache:
|
||||
keys:
|
||||
- gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
|
||||
# fallback to using the latest cache if no exact match is found
|
||||
- gdevelop.js-linux-nodejs-dependencies-
|
||||
|
||||
- run:
|
||||
name: Install GDevelop.js dependencies and build it
|
||||
command: cd GDevelop.js && npm install && cd ..
|
||||
|
||||
# Build GDevelop.js
|
||||
- run:
|
||||
name: Build GDevelop.js ('debug-sanitizers' variant)
|
||||
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build -- --variant=debug-sanitizers
|
||||
|
||||
- run:
|
||||
name: Run clang-tidy
|
||||
command: cd GDevelop.js && npm run lint
|
||||
|
||||
- run:
|
||||
name: Run tests
|
||||
command: cd GDevelop.js && npm run test -- --maxWorkers=4
|
||||
|
||||
# Upload artifacts (CircleCI)
|
||||
- store_artifacts:
|
||||
path: Binaries/embuild/GDevelop.js
|
||||
|
||||
# Upload artifacts (AWS)
|
||||
- run:
|
||||
name: Deploy to S3 (specific commit)
|
||||
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/variant/debug-sanitizers/commit/$(git rev-parse HEAD)/
|
||||
|
||||
workflows:
|
||||
builds:
|
||||
gdevelop_js-wasm:
|
||||
jobs:
|
||||
- build-gdevelop_js-wasm-only
|
||||
gdevelop_js-wasm-extra-checks:
|
||||
jobs:
|
||||
- build-gdevelop_js-debug-sanitizers-and-extra-checks:
|
||||
# Extra checks are resource intensive so don't all run them.
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /experimental-build.*/
|
||||
builds:
|
||||
jobs:
|
||||
- build-macos:
|
||||
filters:
|
||||
branches:
|
||||
|
4
.clang-tidy
Normal file
4
.clang-tidy
Normal file
@@ -0,0 +1,4 @@
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,-cppcoreguidelines-explicit-virtual-functions,-cppcoreguidelines-avoid-const-or-ref-data-members,-cppcoreguidelines-special-member-functions,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-non-private-member-variables-in-classes,-cppcoreguidelines-owning-memory,-cppcoreguidelines-virtual-class-destructor,-clang-analyzer-optin.performance.Padding,-cppcoreguidelines-narrowing-conversions'
|
||||
WarningsAsErrors: 'cppcoreguidelines-pro-type-member-init, clang-analyzer-optin.cplusplus.UninitializedObject'
|
||||
HeaderFilterRegex: '.*'
|
||||
FormatStyle: none
|
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -1,12 +1,11 @@
|
||||
Core/GDCore/Serialization/rapidjson/rapidjson.h/* linguist-vendored
|
||||
Core/GDCore/TinyXml/* linguist-vendored
|
||||
Extensions/ParticleSystem/SPARK/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/Box2D/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/box2djs/* linguist-vendored
|
||||
Extensions/Physics2Behavior/box2d.js linguist-vendored
|
||||
Extensions/BBText/pixi-multistyle-text/* linguist-vendored
|
||||
Extensions/P2P/A_peer.js linguist-vendored
|
||||
Extensions/Multiplayer/peer.js linguist-vendored
|
||||
Extensions/Shopify/shopify-buy.umd.polyfilled.min.js linguist-vendored
|
||||
Extensions/TileMap/pako/* linguist-vendored
|
||||
Extensions/TileMap/pixi-tilemap/* linguist-vendored
|
||||
Extensions/TweenBehavior/shifty.js linguist-vendored
|
||||
|
22
.github/workflows/gdcore-tools-hook.yml
vendored
Normal file
22
.github/workflows/gdcore-tools-hook.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# This worflow notifies arthuro555's gdcore-tools repository when a new release is published.
|
||||
#
|
||||
# This is used to allow gdcore-tools, a library to use GDCore outside of GDevelop,
|
||||
# to attempt to automatically build, test, and publish a release for the new
|
||||
# GDevelop version.
|
||||
name: Trigger gdcore-tools pipeline
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
dispatch-event:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Repository Dispatch
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.GDCORE_TOOLS_PAT }}
|
||||
repository: arthuro555/gdcore-tools
|
||||
event-type: gdevelop-release
|
||||
client-payload: '{"release": ${{ toJson(github.event.release) }}}'
|
@@ -1,6 +1,6 @@
|
||||
# This is a configuration file allowing to quickly set up a development environment
|
||||
# on GitPod (https://www.gitpod.io/).
|
||||
# Also check GitHub codespaces if you're interested in working
|
||||
# Also check GitHub codespaces if you're interested in working
|
||||
# on a remote development server.
|
||||
|
||||
# This works well for:
|
||||
@@ -12,9 +12,9 @@
|
||||
tasks:
|
||||
- name: Install dependencies for Emscripten and build GDevelop.js
|
||||
init: |
|
||||
sudo apt-get update
|
||||
sudo apt-get update
|
||||
sudo apt install cmake python-is-python3 python3-distutils -y
|
||||
git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
||||
git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.66 && ./emsdk activate 3.1.66 && cd ..
|
||||
cd GDevelop.js
|
||||
npm install
|
||||
source ../emsdk/emsdk_env.sh && npm run build -- --dev
|
||||
|
@@ -56,6 +56,7 @@ blocks:
|
||||
- name: GDJS typing and documentation generation
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
|
||||
- cd GDJS
|
||||
|
45
.travis.yml
45
.travis.yml
@@ -6,6 +6,7 @@
|
||||
|
||||
language: cpp
|
||||
sudo: false
|
||||
dist: jammy
|
||||
compiler:
|
||||
- clang
|
||||
|
||||
@@ -16,60 +17,54 @@ cache:
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# Build dependencies:
|
||||
- cmake
|
||||
- p7zip-full
|
||||
|
||||
before_install:
|
||||
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
|
||||
- wget -q -O libstdc++6 http://security.ubuntu.com/ubuntu/pool/main/g/gcc-5/libstdc++6_5.4.0-6ubuntu1~16.04.12_amd64.deb
|
||||
- sudo dpkg --force-all -i libstdc++6
|
||||
# Build dependencies:
|
||||
- cmake
|
||||
- p7zip-full
|
||||
|
||||
install:
|
||||
# Ensure we use a recent version of Node.js (and npm).
|
||||
- nvm install v16 && nvm use v16
|
||||
#Compile the tests only for GDCore
|
||||
# Ensure we use a recent version of Node.js (and npm).
|
||||
- nvm install v18 && nvm use v18
|
||||
#Compile the tests only for GDCore
|
||||
- mkdir .build-tests
|
||||
- cd .build-tests
|
||||
- cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) ..
|
||||
- make -j 4
|
||||
- cd ..
|
||||
# Install Emscripten (for GDevelop.js)
|
||||
- git clone https://github.com/juj/emsdk.git
|
||||
- cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
|
||||
# Install GDevelop.js dependencies
|
||||
# Install Emscripten (for GDevelop.js)
|
||||
# Specify the tag for the core repository to avois breaking changes.
|
||||
- git clone --depth 1 --branch 3.1.66 https://github.com/juj/emsdk.git
|
||||
- cd emsdk && ./emsdk install 3.1.66 && ./emsdk activate 3.1.66 && cd ..
|
||||
# Install GDevelop.js dependencies
|
||||
- cd GDevelop.js && npm install && cd ..
|
||||
# Build GDevelop.js
|
||||
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build)
|
||||
# Build GDevelop.js
|
||||
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build)
|
||||
- (set -e; cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && cd ..)
|
||||
# Install newIDE tests dependencies
|
||||
# Install newIDE tests dependencies
|
||||
- npm -v
|
||||
- cd newIDE/app && npm install
|
||||
- cd ../..
|
||||
# Install GDJS tests dependencies
|
||||
# Install GDJS tests dependencies
|
||||
- cd GDJS && npm install && cd tests && npm install
|
||||
- cd ../..
|
||||
|
||||
script:
|
||||
# GDCore tests:
|
||||
# GDCore tests:
|
||||
- cd .build-tests
|
||||
- Core/GDCore_tests
|
||||
- cd ..
|
||||
# GDevelop.js tests
|
||||
# GDevelop.js tests
|
||||
- cd GDevelop.js
|
||||
- npm test
|
||||
- cd ..
|
||||
# newIDE tests:
|
||||
# newIDE tests:
|
||||
- cd newIDE/app
|
||||
- npm test
|
||||
- npm run flow
|
||||
- npm run check-format
|
||||
- npm run check-script-types
|
||||
- cd ../..
|
||||
# GDJS tests:
|
||||
# GDJS tests:
|
||||
- cd GDJS
|
||||
- npm run check-format
|
||||
- cd ..
|
||||
|
2
.vscode/GDevelopExtensions.code-snippets
vendored
2
.vscode/GDevelopExtensions.code-snippets
vendored
@@ -107,7 +107,7 @@
|
||||
"description": "Define a parameter in a GDevelop extension definition.",
|
||||
"prefix": "gdparam",
|
||||
"body": [
|
||||
".addParameter('${1|string,expression,object,behavior,yesorno,stringWithSelector,scenevar,globalvar,objectvar,objectList,objectListWithoutPicking,color,key,sceneName,file,layer,relationalOperator,operator,trueorfalse,musicfile,soundfile,police,mouse,passwordjoyaxis,camera,objectPtr,forceMultiplier|}', '${2:Parameter description}', '${3:Optional parameter data}', /*parameterIsOptional=*/${4|false,true|})"
|
||||
".addParameter('${1|string,expression,object,behavior,yesorno,stringWithSelector,scenevar,globalvar,objectvar,objectList,objectListWithoutPicking,color,key,sceneName,file,layer,relationalOperator,operator,trueorfalse,musicfile,soundfile,mouse,passwordjoyaxis,camera,objectPtr,forceMultiplier|}', '${2:Parameter description}', '${3:Optional parameter data}', /*parameterIsOptional=*/${4|false,true|})"
|
||||
]
|
||||
},
|
||||
"Add code only parameter": {
|
||||
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -114,7 +114,8 @@
|
||||
"__bits": "cpp",
|
||||
"__verbose_abort": "cpp",
|
||||
"variant": "cpp",
|
||||
"charconv": "cpp"
|
||||
"charconv": "cpp",
|
||||
"execution": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"Binaries/*build*": true,
|
||||
|
1
.vscode/tasks.json
vendored
1
.vscode/tasks.json
vendored
@@ -8,6 +8,7 @@
|
||||
"group": "build",
|
||||
"label": "Start development server",
|
||||
"detail": "Starts the GDevelop development server.",
|
||||
"options": { "env": { "NODE_OPTIONS": "--max-old-space-size=8192" } },
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "cra",
|
||||
|
@@ -60,7 +60,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_
|
||||
endif()
|
||||
|
||||
#Activate C++11
|
||||
set(CMAKE_CXX_STANDARD 11) # Upgrading to C++17 would need to remove usage of bind2nd (should be easy).
|
||||
set(CMAKE_CXX_STANDARD 11) # Upgrading to C++17 should be tried.
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Mark some warnings as errors
|
||||
@@ -69,12 +69,18 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
# uninitialized variables or other hard to debug bugs.
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wuninitialized
|
||||
-Wconditional-uninitialized
|
||||
-Wno-unknown-warning-option
|
||||
-Wno-reorder-ctor
|
||||
-Wno-reorder
|
||||
-Wno-unused-parameter
|
||||
-Wno-pessimizing-move
|
||||
-Wno-unused-variable
|
||||
-Wno-unused-variable # Not a good style, but not a risk
|
||||
-Wno-unused-private-field
|
||||
-Wno-ignored-qualifiers # Not a risk
|
||||
-Wno-sign-compare # Not a big risk
|
||||
|
||||
# Make as much warnings considered as errors as possible (only one for now).
|
||||
-Werror=return-stack-address
|
||||
|
@@ -11,6 +11,11 @@ set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
|
||||
set(GDCORE_include_dir ${GD_base_dir}/Core PARENT_SCOPE)
|
||||
set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME} PARENT_SCOPE)
|
||||
|
||||
# Create VersionPriv.h - only useful for testing.
|
||||
if (NOT EMSCRIPTEN)
|
||||
file(WRITE "${GD_base_dir}/Core/GDCore/Tools/VersionPriv.h" "#define GD_VERSION_STRING \"0.0.0-0\"")
|
||||
endif()
|
||||
|
||||
# Dependencies on external libraries:
|
||||
#
|
||||
|
||||
@@ -73,7 +78,7 @@ else()
|
||||
add_library(GDCore SHARED ${source_files})
|
||||
endif()
|
||||
if(EMSCRIPTEN)
|
||||
set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
|
||||
# set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
|
||||
elseif(WIN32)
|
||||
set_target_properties(GDCore PROPERTIES PREFIX "")
|
||||
else()
|
||||
|
@@ -58,99 +58,7 @@
|
||||
* Common functions and tools for programming.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup TinyXml Integrated TinyXml library
|
||||
*
|
||||
* See the full documentation of TinyXml [here](http://www.grinninglizard.com/tinyxmldocs/index.html).
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup SpriteObjectExtension Standard Sprite Object extension
|
||||
* \ingroup BuiltinExtensions
|
||||
*/
|
||||
|
||||
/**
|
||||
* \class TiXmlAttribute
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlAttributeSet
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlBase
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlComment
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlCursor
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlDeclaration
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlDocument
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlElement
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlHandle
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlNode
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlOutStream
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlParsingData
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlPrinter
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlString
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlText
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlUnknown
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
/**
|
||||
* \class TiXmlVisitor
|
||||
* \brief Part of the tinyxml library
|
||||
* \ingroup TinyXml
|
||||
*/
|
||||
*/
|
@@ -49,7 +49,8 @@ vector<pair<gd::Expression*, gd::ParameterMetadata> >
|
||||
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() {
|
||||
vector<pair<gd::Expression*, gd::ParameterMetadata> >
|
||||
allExpressionsWithMetadata;
|
||||
auto metadata = gd::ParameterMetadata().SetType("scenevar");
|
||||
auto metadata = gd::ParameterMetadata().SetType("variable");
|
||||
metadata.SetExtraInfo("AllowUndeclaredVariable");
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&iterableVariableName, metadata));
|
||||
allExpressionsWithMetadata.push_back(
|
||||
@@ -63,7 +64,8 @@ vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
|
||||
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() const {
|
||||
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
|
||||
allExpressionsWithMetadata;
|
||||
auto metadata = gd::ParameterMetadata().SetType("scenevar");
|
||||
auto metadata = gd::ParameterMetadata().SetType("variable");
|
||||
metadata.SetExtraInfo("AllowUndeclaredVariable");
|
||||
allExpressionsWithMetadata.push_back(
|
||||
std::make_pair(&iterableVariableName, metadata));
|
||||
allExpressionsWithMetadata.push_back(
|
||||
|
@@ -8,7 +8,6 @@
|
||||
#include "GDCore/Events/Serialization.h"
|
||||
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
|
||||
#include "GDCore/Events/Serialization.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@@ -4,8 +4,8 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_REPEATEVENT_H
|
||||
#define GDCORE_REPEATEVENT_H
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
namespace gd {
|
||||
@@ -36,10 +36,10 @@ class GD_CORE_API RepeatEvent : public gd::BaseEvent {
|
||||
const gd::InstructionsList& GetActions() const { return actions; };
|
||||
gd::InstructionsList& GetActions() { return actions; };
|
||||
|
||||
const gd::String& GetRepeatExpression() const {
|
||||
return repeatNumberExpression.GetPlainString();
|
||||
const gd::Expression& GetRepeatExpression() const {
|
||||
return repeatNumberExpression;
|
||||
};
|
||||
void SetRepeatExpression(gd::String repeatNumberExpression_) {
|
||||
void SetRepeatExpressionPlainString(gd::String repeatNumberExpression_) {
|
||||
repeatNumberExpression = gd::Expression(repeatNumberExpression_);
|
||||
};
|
||||
|
||||
@@ -68,5 +68,3 @@ class GD_CORE_API RepeatEvent : public gd::BaseEvent {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_REPEATEVENT_H
|
||||
|
@@ -15,7 +15,8 @@ using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
StandardEvent::StandardEvent() : BaseEvent() {}
|
||||
StandardEvent::StandardEvent()
|
||||
: BaseEvent(), variables(gd::VariablesContainer::SourceType::Local) {}
|
||||
|
||||
StandardEvent::~StandardEvent(){};
|
||||
|
||||
@@ -57,6 +58,9 @@ void StandardEvent::SerializeTo(SerializerElement& element) const {
|
||||
if (!events.IsEmpty())
|
||||
gd::EventsListSerialization::SerializeEventsTo(events,
|
||||
element.AddChild("events"));
|
||||
if (HasVariables()) {
|
||||
variables.SerializeTo(element.AddChild("variables"));
|
||||
}
|
||||
}
|
||||
|
||||
void StandardEvent::UnserializeFrom(gd::Project& project,
|
||||
@@ -71,6 +75,11 @@ void StandardEvent::UnserializeFrom(gd::Project& project,
|
||||
gd::EventsListSerialization::UnserializeEventsFrom(
|
||||
project, events, element.GetChild("events", 0, "Events"));
|
||||
}
|
||||
|
||||
variables.Clear();
|
||||
if (element.HasChild("variables")) {
|
||||
variables.UnserializeFrom(element.GetChild("variables"));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -4,13 +4,13 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#ifndef GDCORE_STANDARDEVENT_H
|
||||
#define GDCORE_STANDARDEVENT_H
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Events/InstructionsList.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
namespace gd {
|
||||
class Instruction;
|
||||
class Project;
|
||||
@@ -33,6 +33,10 @@ class GD_CORE_API StandardEvent : public gd::BaseEvent {
|
||||
virtual const gd::EventsList& GetSubEvents() const { return events; };
|
||||
virtual gd::EventsList& GetSubEvents() { return events; };
|
||||
|
||||
virtual bool CanHaveVariables() const { return true; }
|
||||
virtual const gd::VariablesContainer& GetVariables() const { return variables; };
|
||||
virtual gd::VariablesContainer& GetVariables() { return variables; };
|
||||
|
||||
const gd::InstructionsList& GetConditions() const { return conditions; };
|
||||
gd::InstructionsList& GetConditions() { return conditions; };
|
||||
|
||||
@@ -53,9 +57,7 @@ class GD_CORE_API StandardEvent : public gd::BaseEvent {
|
||||
gd::InstructionsList conditions;
|
||||
gd::InstructionsList actions;
|
||||
EventsList events;
|
||||
VariablesContainer variables;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_STANDARDEVENT_H
|
||||
#endif
|
||||
|
@@ -72,8 +72,6 @@ class GD_CORE_API WhileEvent : public gd::BaseEvent {
|
||||
///< de/activate infinite loop warning when the
|
||||
///< user create the event
|
||||
|
||||
mutable unsigned int whileConditionsHeight;
|
||||
|
||||
int GetConditionsHeight() const;
|
||||
int GetActionsHeight() const;
|
||||
int GetWhileConditionsHeight() const;
|
||||
|
129
Core/GDCore/Events/CodeGeneration/DiagnosticReport.h
Normal file
129
Core/GDCore/Events/CodeGeneration/DiagnosticReport.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*/
|
||||
class GD_CORE_API ProjectDiagnostic {
|
||||
public:
|
||||
enum ErrorType {
|
||||
UndeclaredVariable,
|
||||
MissingBehavior,
|
||||
UnknownObject,
|
||||
MismatchedObjectType,
|
||||
};
|
||||
|
||||
ProjectDiagnostic(ErrorType type_,
|
||||
const gd::String &message_,
|
||||
const gd::String &actualValue_,
|
||||
const gd::String &expectedValue_,
|
||||
const gd::String &objectName_ = "")
|
||||
: type(type_),
|
||||
message(message_),
|
||||
actualValue(actualValue_),
|
||||
expectedValue(expectedValue_),
|
||||
objectName(objectName_) {};
|
||||
virtual ~ProjectDiagnostic() {};
|
||||
|
||||
ErrorType GetType() const { return type; };
|
||||
const gd::String &GetMessage() const { return message; }
|
||||
const gd::String &GetObjectName() const { return objectName; }
|
||||
const gd::String &GetActualValue() const { return actualValue; }
|
||||
const gd::String &GetExpectedValue() const { return expectedValue; }
|
||||
|
||||
private:
|
||||
ErrorType type;
|
||||
gd::String message;
|
||||
gd::String objectName;
|
||||
gd::String actualValue;
|
||||
gd::String expectedValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*/
|
||||
class GD_CORE_API DiagnosticReport {
|
||||
public:
|
||||
DiagnosticReport() {};
|
||||
virtual ~DiagnosticReport() {};
|
||||
|
||||
void Add(const gd::ProjectDiagnostic &projectDiagnostic) {
|
||||
projectDiagnostics.push_back(
|
||||
gd::make_unique<gd::ProjectDiagnostic>(projectDiagnostic));
|
||||
};
|
||||
|
||||
const ProjectDiagnostic &Get(std::size_t index) const {
|
||||
return *projectDiagnostics[index].get();
|
||||
};
|
||||
|
||||
std::size_t Count() const { return projectDiagnostics.size(); };
|
||||
|
||||
const gd::String &GetSceneName() const { return sceneName; }
|
||||
|
||||
void SetSceneName(const gd::String &sceneName_) { sceneName = sceneName_; }
|
||||
|
||||
void LogAllDiagnostics() {
|
||||
for (auto &diagnostic : projectDiagnostics) {
|
||||
std::cout << diagnostic->GetMessage()
|
||||
<< "(object: " << diagnostic->GetObjectName()
|
||||
<< ", actual value: " << diagnostic->GetActualValue()
|
||||
<< ", expected value: " << diagnostic->GetExpectedValue() << ")"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<gd::ProjectDiagnostic>> projectDiagnostics;
|
||||
gd::String sceneName;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief
|
||||
*/
|
||||
class GD_CORE_API WholeProjectDiagnosticReport {
|
||||
public:
|
||||
WholeProjectDiagnosticReport() {};
|
||||
virtual ~WholeProjectDiagnosticReport() {};
|
||||
|
||||
const DiagnosticReport &Get(std::size_t index) const {
|
||||
return *diagnosticReports[index].get();
|
||||
};
|
||||
|
||||
void Clear() { diagnosticReports.clear(); };
|
||||
|
||||
DiagnosticReport &AddNewDiagnosticReportForScene(
|
||||
const gd::String &sceneName) {
|
||||
auto diagnosticReport = gd::make_unique<gd::DiagnosticReport>();
|
||||
diagnosticReport->SetSceneName(sceneName);
|
||||
diagnosticReports.push_back(std::move(diagnosticReport));
|
||||
return *diagnosticReports[diagnosticReports.size() - 1].get();
|
||||
};
|
||||
|
||||
std::size_t Count() const { return diagnosticReports.size(); };
|
||||
|
||||
bool HasAnyIssue() {
|
||||
for (auto &diagnosticReport : diagnosticReports) {
|
||||
if (diagnosticReport->Count() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<gd::DiagnosticReport>> diagnosticReports;
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -15,6 +15,7 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/IDE/ProjectBrowserHelper.h"
|
||||
|
||||
namespace gd {
|
||||
@@ -47,6 +48,9 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
|
||||
|
||||
// TODO Merge with UsedExtensionsFinder.
|
||||
|
||||
// TODO Factorize with the iteration on all effects for resource exposure.
|
||||
// TODO Implement an ArbitraryEffectWorker and add a method in ProjectBrowserHelper
|
||||
|
||||
// See also gd::Project::ExposeResources for a method that traverse the whole
|
||||
// project (this time for resources) and
|
||||
// WholeProjectRefactorer::ExposeProjectEvents.
|
||||
@@ -68,6 +72,27 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
|
||||
|
||||
// Add objects effects
|
||||
gd::ProjectBrowserHelper::ExposeProjectObjects(project, effectsCodeGenerator);
|
||||
|
||||
// Add event-based objects layouts effects
|
||||
for (std::size_t s = 0; s < project.GetEventsFunctionsExtensionsCount();
|
||||
s++) {
|
||||
auto &eventsFunctionExtension = project.GetEventsFunctionsExtension(s);
|
||||
|
||||
auto &eventsBasedObjects = eventsFunctionExtension.GetEventsBasedObjects();
|
||||
for (std::size_t objectIndex = 0;
|
||||
objectIndex < eventsBasedObjects.GetCount(); ++objectIndex) {
|
||||
auto &eventsBasedObject = eventsBasedObjects.Get(objectIndex);
|
||||
|
||||
auto &layers = eventsBasedObject.GetLayers();
|
||||
for (std::size_t l = 0; l < layers.GetLayersCount(); ++l) {
|
||||
auto &effects = layers.GetLayer(l).GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
|
||||
auto &effect = effects.GetEffect(e);
|
||||
effectsCodeGenerator.AddEffectIncludeFiles(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -3,8 +3,8 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef EVENTSCODEGENERATIONCONTEXT_H
|
||||
#define EVENTSCODEGENERATIONCONTEXT_H
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@@ -325,4 +325,3 @@ class GD_CORE_API EventsCodeGenerationContext {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // EVENTSCODEGENERATIONCONTEXT_H
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableNameFinder.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
@@ -41,14 +42,15 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
|
||||
const vector<gd::String>& arguments,
|
||||
const gd::String& callStartString,
|
||||
std::size_t startFromArgument) {
|
||||
std::size_t relationalOperatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
std::size_t relationalOperatorIndex = instrInfos.parameters.GetParametersCount();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].GetType() == "relationalOperator")
|
||||
if (instrInfos.parameters.GetParameter(i).GetType() == "relationalOperator") {
|
||||
relationalOperatorIndex = i;
|
||||
}
|
||||
}
|
||||
// Ensure that there is at least one parameter after the relational operator
|
||||
if (relationalOperatorIndex + 1 >= instrInfos.parameters.size()) {
|
||||
if (relationalOperatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
|
||||
ReportError();
|
||||
return "";
|
||||
}
|
||||
@@ -75,11 +77,11 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
|
||||
|
||||
/**
|
||||
* @brief Generate a relational operation
|
||||
*
|
||||
*
|
||||
* @param relationalOperator the operator
|
||||
* @param lhs the left hand operand
|
||||
* @param rhs the right hand operand
|
||||
* @return gd::String
|
||||
* @return gd::String
|
||||
*/
|
||||
gd::String EventsCodeGenerator::GenerateRelationalOperation(
|
||||
const gd::String& relationalOperator,
|
||||
@@ -121,14 +123,16 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
|
||||
const gd::String& callStartString,
|
||||
const gd::String& getterStartString,
|
||||
std::size_t startFromArgument) {
|
||||
std::size_t operatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
|
||||
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
||||
operatorIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there is at least one parameter after the operator
|
||||
if (operatorIndex + 1 >= instrInfos.parameters.size()) {
|
||||
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
|
||||
ReportError();
|
||||
return "";
|
||||
}
|
||||
@@ -190,14 +194,16 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
|
||||
const vector<gd::String>& arguments,
|
||||
const gd::String& callStartString,
|
||||
std::size_t startFromArgument) {
|
||||
std::size_t operatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
|
||||
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
||||
operatorIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there is at least one parameter after the operator
|
||||
if (operatorIndex + 1 >= instrInfos.parameters.size()) {
|
||||
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
|
||||
ReportError();
|
||||
return "";
|
||||
}
|
||||
@@ -241,25 +247,27 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
|
||||
const vector<gd::String>& arguments,
|
||||
const gd::String& callStartString,
|
||||
std::size_t startFromArgument) {
|
||||
std::size_t operatorIndex = instrInfos.parameters.size();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
|
||||
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount();
|
||||
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
|
||||
++i) {
|
||||
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
|
||||
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
|
||||
operatorIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that there is at least one parameter after the operator
|
||||
if (operatorIndex + 1 >= instrInfos.parameters.size()) {
|
||||
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
|
||||
ReportError();
|
||||
return "";
|
||||
}
|
||||
|
||||
gd::String operatorStr = arguments[operatorIndex];
|
||||
if (operatorStr.size() > 2)
|
||||
if (operatorStr.size() > 2 && operatorStr[0] == '\"') {
|
||||
operatorStr = operatorStr.substr(
|
||||
1,
|
||||
operatorStr.length() - 1 -
|
||||
1); // Operator contains quote which must be removed.
|
||||
|
||||
}
|
||||
auto mutators = instrInfos.codeExtraInformation.optionalMutators;
|
||||
auto mutator = mutators.find(operatorStr);
|
||||
if (mutator == mutators.end()) {
|
||||
@@ -279,6 +287,9 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
|
||||
argumentsStr += arguments[i];
|
||||
}
|
||||
}
|
||||
if (instrInfos.GetManipulatedType() == "boolean") {
|
||||
return callStartString + "(" + argumentsStr + ")." + mutator->second;
|
||||
}
|
||||
|
||||
return callStartString + "(" + argumentsStr + ")." + mutator->second + "(" +
|
||||
rhs + ")";
|
||||
@@ -312,23 +323,36 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
}
|
||||
|
||||
// Insert code only parameters and be sure there is no lack of parameter.
|
||||
while (condition.GetParameters().size() < instrInfos.parameters.size()) {
|
||||
while (condition.GetParameters().size() < instrInfos.parameters.GetParametersCount()) {
|
||||
vector<gd::Expression> parameters = condition.GetParameters();
|
||||
parameters.push_back(gd::Expression(""));
|
||||
condition.SetParameters(parameters);
|
||||
}
|
||||
|
||||
gd::EventsCodeGenerator::CheckBehaviorParameters(condition, instrInfos);
|
||||
// Verify that there are no mismatches between object type in parameters.
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
gd::String objectInParameter =
|
||||
condition.GetParameter(pNb).GetPlainString();
|
||||
|
||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(objectInParameter)) {
|
||||
const auto &expectedObjectType =
|
||||
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
|
||||
const auto &actualObjectType =
|
||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
|
||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
|
||||
objectInParameter)) {
|
||||
gd::ProjectDiagnostic projectDiagnostic(
|
||||
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
|
||||
objectInParameter, "");
|
||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
|
||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter) !=
|
||||
instrInfos.parameters[pNb].GetExtraInfo()) {
|
||||
} else if (!expectedObjectType.empty() &&
|
||||
actualObjectType != expectedObjectType) {
|
||||
gd::ProjectDiagnostic projectDiagnostic(
|
||||
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "",
|
||||
actualObjectType, expectedObjectType, objectInParameter);
|
||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
@@ -336,7 +360,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
|
||||
if (instrInfos.IsObjectInstruction()) {
|
||||
gd::String objectName = condition.GetParameter(0).GetPlainString();
|
||||
if (!objectName.empty() && !instrInfos.parameters.empty()) {
|
||||
if (!objectName.empty() && instrInfos.parameters.GetParametersCount() > 0) {
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
@@ -364,15 +388,22 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
}
|
||||
}
|
||||
} else if (instrInfos.IsBehaviorInstruction()) {
|
||||
gd::String objectName = condition.GetParameter(0).GetPlainString();
|
||||
gd::String behaviorType = GetObjectsContainersList().GetTypeOfBehavior(condition.GetParameter(1).GetPlainString());
|
||||
if (instrInfos.parameters.size() >= 2) {
|
||||
if (instrInfos.parameters.GetParametersCount() >= 2) {
|
||||
const gd::String &objectName = condition.GetParameter(0).GetPlainString();
|
||||
const gd::String &behaviorName =
|
||||
condition.GetParameter(1).GetPlainString();
|
||||
const gd::String &actualBehaviorType =
|
||||
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
|
||||
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
GetObjectsContainersList().ExpandObjectName(
|
||||
objectName, context.GetCurrentObject());
|
||||
|
||||
const BehaviorMetadata &autoInfo =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
|
||||
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Setup context
|
||||
const BehaviorMetadata& autoInfo =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
|
||||
AddIncludeFiles(autoInfo.includeFiles);
|
||||
context.SetCurrentObject(realObjects[i]);
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
@@ -382,7 +413,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
condition.GetParameters(), instrInfos.parameters, context);
|
||||
conditionCode += GenerateBehaviorCondition(
|
||||
realObjects[i],
|
||||
condition.GetParameter(1).GetPlainString(),
|
||||
behaviorName,
|
||||
autoInfo,
|
||||
arguments,
|
||||
instrInfos,
|
||||
@@ -457,6 +488,33 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
|
||||
return outputCode;
|
||||
}
|
||||
|
||||
void EventsCodeGenerator::CheckBehaviorParameters(
|
||||
const gd::Instruction &instruction,
|
||||
const gd::InstructionMetadata &instrInfos) {
|
||||
gd::ParameterMetadataTools::IterateOverParameters(
|
||||
instruction.GetParameters(), instrInfos.parameters,
|
||||
[this](const gd::ParameterMetadata ¶meterMetadata,
|
||||
const gd::Expression ¶meterValue,
|
||||
const gd::String &lastObjectName) {
|
||||
if (ParameterMetadata::IsBehavior(parameterMetadata.GetType())) {
|
||||
const gd::String &behaviorName = parameterValue.GetPlainString();
|
||||
const gd::String &actualBehaviorType =
|
||||
GetObjectsContainersList().GetTypeOfBehaviorInObjectOrGroup(
|
||||
lastObjectName, behaviorName);
|
||||
const gd::String &expectedBehaviorType =
|
||||
parameterMetadata.GetExtraInfo();
|
||||
|
||||
if (!expectedBehaviorType.empty() &&
|
||||
actualBehaviorType != expectedBehaviorType) {
|
||||
gd::ProjectDiagnostic projectDiagnostic(
|
||||
gd::ProjectDiagnostic::ErrorType::MissingBehavior, "",
|
||||
actualBehaviorType, expectedBehaviorType, lastObjectName);
|
||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate code for an action.
|
||||
*/
|
||||
@@ -488,21 +546,35 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
: instrInfos.codeExtraInformation.functionCallName;
|
||||
|
||||
// Be sure there is no lack of parameter.
|
||||
while (action.GetParameters().size() < instrInfos.parameters.size()) {
|
||||
while (action.GetParameters().size() < instrInfos.parameters.GetParametersCount()) {
|
||||
vector<gd::Expression> parameters = action.GetParameters();
|
||||
parameters.push_back(gd::Expression(""));
|
||||
action.SetParameters(parameters);
|
||||
}
|
||||
|
||||
gd::EventsCodeGenerator::CheckBehaviorParameters(action, instrInfos);
|
||||
// Verify that there are no mismatches between object type in parameters.
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
|
||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(objectInParameter)) {
|
||||
|
||||
const auto &expectedObjectType =
|
||||
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
|
||||
const auto &actualObjectType =
|
||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
|
||||
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
|
||||
objectInParameter)) {
|
||||
gd::ProjectDiagnostic projectDiagnostic(
|
||||
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
|
||||
objectInParameter, "");
|
||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
|
||||
GetObjectsContainersList().GetTypeOfObject(objectInParameter) !=
|
||||
instrInfos.parameters[pNb].GetExtraInfo()) {
|
||||
} else if (!expectedObjectType.empty() &&
|
||||
actualObjectType != expectedObjectType) {
|
||||
gd::ProjectDiagnostic projectDiagnostic(
|
||||
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "",
|
||||
actualObjectType, expectedObjectType, objectInParameter);
|
||||
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
@@ -512,7 +584,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
if (instrInfos.IsObjectInstruction()) {
|
||||
gd::String objectName = action.GetParameter(0).GetPlainString();
|
||||
|
||||
if (!instrInfos.parameters.empty()) {
|
||||
if (instrInfos.parameters.GetParametersCount() > 0) {
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
@@ -540,17 +612,22 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
}
|
||||
}
|
||||
} else if (instrInfos.IsBehaviorInstruction()) {
|
||||
gd::String objectName = action.GetParameter(0).GetPlainString();
|
||||
gd::String behaviorType = GetObjectsContainersList().GetTypeOfBehavior(action.GetParameter(1).GetPlainString());
|
||||
if (instrInfos.parameters.GetParametersCount() >= 2) {
|
||||
const gd::String &objectName = action.GetParameter(0).GetPlainString();
|
||||
const gd::String &behaviorName = action.GetParameter(1).GetPlainString();
|
||||
const gd::String &actualBehaviorType =
|
||||
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
|
||||
|
||||
if (instrInfos.parameters.size() >= 2) {
|
||||
std::vector<gd::String> realObjects =
|
||||
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
|
||||
GetObjectsContainersList().ExpandObjectName(
|
||||
objectName, context.GetCurrentObject());
|
||||
|
||||
const BehaviorMetadata &autoInfo =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
|
||||
|
||||
AddIncludeFiles(autoInfo.includeFiles);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Setup context
|
||||
const BehaviorMetadata& autoInfo =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
|
||||
AddIncludeFiles(autoInfo.includeFiles);
|
||||
context.SetCurrentObject(realObjects[i]);
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
|
||||
@@ -559,7 +636,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
action.GetParameters(), instrInfos.parameters, context);
|
||||
actionCode +=
|
||||
GenerateBehaviorAction(realObjects[i],
|
||||
action.GetParameter(1).GetPlainString(),
|
||||
behaviorName,
|
||||
autoInfo,
|
||||
functionCallName,
|
||||
arguments,
|
||||
@@ -583,6 +660,29 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
return actionCode;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateLocalVariablesStackAccessor() {
|
||||
return (HasProjectAndLayout() ? GetCodeNamespace()
|
||||
: "eventsFunctionContext") +
|
||||
".localVariables";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateAnyOrSceneVariableGetter(
|
||||
const gd::Expression &variableExpression,
|
||||
EventsCodeGenerationContext &context) {
|
||||
const auto variableName = gd::ExpressionVariableNameFinder::GetVariableName(
|
||||
*variableExpression.GetRootNode());
|
||||
|
||||
gd::String variableParameterType =
|
||||
GetProjectScopedContainers().GetVariablesContainersList().Has(
|
||||
variableName)
|
||||
? "variable"
|
||||
: "scenevar";
|
||||
|
||||
return gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, variableParameterType,
|
||||
variableExpression.GetPlainString(), "", "AllowUndeclaredVariable");
|
||||
}
|
||||
|
||||
const EventsCodeGenerator::CallbackDescriptor
|
||||
EventsCodeGenerator::GenerateCallback(
|
||||
const gd::String& callbackID,
|
||||
@@ -607,14 +707,23 @@ EventsCodeGenerator::GenerateCallback(
|
||||
actionsCode += "} //End of subevents\n";
|
||||
}
|
||||
|
||||
gd::String restoreLocalVariablesCode;
|
||||
restoreLocalVariablesCode +=
|
||||
"asyncObjectsList.restoreLocalVariablesContainers(" +
|
||||
GenerateLocalVariablesStackAccessor() + ");\n";
|
||||
|
||||
// Compose the callback function and add outside main
|
||||
const gd::String actionsDeclarationsCode =
|
||||
GenerateObjectsDeclarationCode(callbackContext);
|
||||
|
||||
const gd::String clearLocalVariablesCode =
|
||||
GenerateLocalVariablesStackAccessor() + ".length = 0;\n";
|
||||
|
||||
const gd::String callbackCode = callbackFunctionName + " = function (" +
|
||||
GenerateEventsParameters(callbackContext) +
|
||||
") {\n" + actionsDeclarationsCode +
|
||||
actionsCode + "}\n";
|
||||
") {\n" + restoreLocalVariablesCode +
|
||||
actionsDeclarationsCode + actionsCode +
|
||||
clearLocalVariablesCode + "}\n";
|
||||
|
||||
AddCustomCodeOutsideMain(callbackCode);
|
||||
|
||||
@@ -677,13 +786,13 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
|
||||
if (ParameterMetadata::IsExpression("number", metadata.GetType())) {
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, "number", parameter, lastObjectName);
|
||||
*this, context, "number", parameter, lastObjectName, metadata.GetExtraInfo());
|
||||
} else if (ParameterMetadata::IsExpression("string", metadata.GetType())) {
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, "string", parameter, lastObjectName);
|
||||
*this, context, "string", parameter, lastObjectName, metadata.GetExtraInfo());
|
||||
} else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) {
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, metadata.GetType(), parameter, lastObjectName);
|
||||
*this, context, metadata.GetType(), parameter, lastObjectName, metadata.GetExtraInfo());
|
||||
} else if (ParameterMetadata::IsObject(metadata.GetType())) {
|
||||
// It would be possible to run a gd::ExpressionCodeGenerator if later
|
||||
// objects can have nested objects, or function returning objects.
|
||||
@@ -695,7 +804,8 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
} else if (metadata.GetType() == "operator") {
|
||||
argOutput += parameter.GetPlainString();
|
||||
if (argOutput != "=" && argOutput != "+" && argOutput != "-" &&
|
||||
argOutput != "/" && argOutput != "*") {
|
||||
argOutput != "/" && argOutput != "*" && argOutput != "True" &&
|
||||
argOutput != "False" && argOutput != "Toggle") {
|
||||
cout << "Warning: Bad operator: Set to = by default." << endl;
|
||||
argOutput = "=";
|
||||
}
|
||||
@@ -718,7 +828,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
metadata.GetType() == "spineResource" ||
|
||||
// Deprecated, old parameter names:
|
||||
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
|
||||
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
|
||||
metadata.GetType() == "soundfile") {
|
||||
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
||||
} else if (metadata.GetType() == "mouse") {
|
||||
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
|
||||
@@ -760,7 +870,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
|
||||
vector<gd::String> EventsCodeGenerator::GenerateParametersCodes(
|
||||
const vector<gd::Expression>& parameters,
|
||||
const vector<gd::ParameterMetadata>& parametersInfo,
|
||||
const ParameterMetadataContainer& parametersInfo,
|
||||
EventsCodeGenerationContext& context,
|
||||
std::vector<std::pair<gd::String, gd::String> >*
|
||||
supplementaryParametersTypes) {
|
||||
@@ -865,6 +975,11 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
|
||||
gd::EventsList& events, EventsCodeGenerationContext& parentContext) {
|
||||
gd::String output;
|
||||
for (std::size_t eId = 0; eId < events.size(); ++eId) {
|
||||
auto& event = events[eId];
|
||||
if (event.HasVariables()) {
|
||||
GetProjectScopedContainers().GetVariablesContainersList().Push(event.GetVariables());
|
||||
}
|
||||
|
||||
// Each event has its own context : Objects picked in an event are totally
|
||||
// different than the one picked in another.
|
||||
gd::EventsCodeGenerationContext newContext;
|
||||
@@ -885,13 +1000,17 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
|
||||
|
||||
auto& context = reuseParentContext ? reusedContext : newContext;
|
||||
|
||||
gd::String eventCoreCode = events[eId].GenerateEventCode(*this, context);
|
||||
gd::String eventCoreCode = event.GenerateEventCode(*this, context);
|
||||
gd::String scopeBegin = GenerateScopeBegin(context);
|
||||
gd::String scopeEnd = GenerateScopeEnd(context);
|
||||
gd::String declarationsCode = GenerateObjectsDeclarationCode(context);
|
||||
|
||||
output += "\n" + scopeBegin + "\n" + declarationsCode + "\n" +
|
||||
eventCoreCode + "\n" + scopeEnd + "\n";
|
||||
|
||||
if (event.HasVariables()) {
|
||||
GetProjectScopedContainers().GetVariablesContainersList().Pop();
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
@@ -988,10 +1107,10 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
|
||||
|
||||
// Add logical not if needed
|
||||
bool conditionAlreadyTakeCareOfInversion = false;
|
||||
for (std::size_t i = 0; i < instrInfos.parameters.size();
|
||||
for (std::size_t i = 0; i < instrInfos.parameters.GetParametersCount();
|
||||
++i) // Some conditions already have a "conditionInverted" parameter
|
||||
{
|
||||
if (instrInfos.parameters[i].GetType() == "conditionInverted")
|
||||
if (instrInfos.parameters.GetParameter(i).GetType() == "conditionInverted")
|
||||
conditionAlreadyTakeCareOfInversion = true;
|
||||
}
|
||||
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
|
||||
@@ -1012,7 +1131,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
|
||||
// Prepare call
|
||||
// Add a static_cast if necessary
|
||||
gd::String objectFunctionCallNamePart =
|
||||
(!instrInfos.parameters[0].GetExtraInfo().empty())
|
||||
(!instrInfos.parameters.GetParameter(0).GetExtraInfo().empty())
|
||||
? "static_cast<" + objInfo.className + "*>(" +
|
||||
GetObjectListName(objectName, context) + "[i])->" +
|
||||
instrInfos.codeExtraInformation.functionCallName
|
||||
@@ -1067,7 +1186,13 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
|
||||
// Generate call
|
||||
gd::String call;
|
||||
if (instrInfos.codeExtraInformation.type == "number" ||
|
||||
instrInfos.codeExtraInformation.type == "string") {
|
||||
instrInfos.codeExtraInformation.type == "string" ||
|
||||
// Boolean actions declared with addExpressionAndConditionAndAction uses
|
||||
// MutatorAndOrAccessor even though they don't declare an operator parameter.
|
||||
// Boolean operators are only used with SetMutators or SetCustomCodeGenerator.
|
||||
(instrInfos.codeExtraInformation.type == "boolean" &&
|
||||
instrInfos.codeExtraInformation.accessType ==
|
||||
gd::InstructionMetadata::ExtraInformation::AccessType::Mutators)) {
|
||||
if (instrInfos.codeExtraInformation.accessType ==
|
||||
gd::InstructionMetadata::ExtraInformation::MutatorAndOrAccessor)
|
||||
call = GenerateOperatorCall(
|
||||
@@ -1251,7 +1376,8 @@ EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
|
||||
compilationForRuntime(false),
|
||||
maxCustomConditionsDepth(0),
|
||||
maxConditionsListsSize(0),
|
||||
eventsListNextUniqueId(0){};
|
||||
eventsListNextUniqueId(0),
|
||||
diagnosticReport(nullptr){};
|
||||
|
||||
EventsCodeGenerator::EventsCodeGenerator(
|
||||
const gd::Platform& platform_,
|
||||
@@ -1265,6 +1391,7 @@ EventsCodeGenerator::EventsCodeGenerator(
|
||||
compilationForRuntime(false),
|
||||
maxCustomConditionsDepth(0),
|
||||
maxConditionsListsSize(0),
|
||||
eventsListNextUniqueId(0){};
|
||||
eventsListNextUniqueId(0),
|
||||
diagnosticReport(nullptr){};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -3,8 +3,7 @@
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EVENTSCODEGENERATOR_H
|
||||
#define GDCORE_EVENTSCODEGENERATOR_H
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <utility>
|
||||
@@ -12,8 +11,10 @@
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Events/CodeGeneration/DiagnosticReport.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class EventsList;
|
||||
class Expression;
|
||||
@@ -127,7 +128,7 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
*/
|
||||
std::vector<gd::String> GenerateParametersCodes(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersInfo,
|
||||
const ParameterMetadataContainer& parametersInfo,
|
||||
EventsCodeGenerationContext& context,
|
||||
std::vector<std::pair<gd::String, gd::String> >*
|
||||
supplementaryParametersTypes = 0);
|
||||
@@ -336,6 +337,16 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
return projectScopedContainers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Give access to the project scoped containers as code generation might
|
||||
* push and pop variable containers (for local variables).
|
||||
* This could be passed as a parameter recursively in code generation, but this requires
|
||||
* heavy refactoring. Instead, we use this single instance.
|
||||
*/
|
||||
gd::ProjectScopedContainers& GetProjectScopedContainers() {
|
||||
return projectScopedContainers;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the code generation is done for a given project and
|
||||
* layout. If not, this means that the code is generated for a function.
|
||||
@@ -372,6 +383,14 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
*/
|
||||
size_t GetMaxConditionsListsSize() const { return maxConditionsListsSize; }
|
||||
|
||||
void SetDiagnosticReport(gd::DiagnosticReport* diagnosticReport_) {
|
||||
diagnosticReport = diagnosticReport_;
|
||||
}
|
||||
|
||||
gd::DiagnosticReport* GetDiagnosticReport() {
|
||||
return diagnosticReport;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generate the full name for accessing to a boolean variable used for
|
||||
* conditions.
|
||||
@@ -448,7 +467,7 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
*/
|
||||
virtual gd::String GetCodeNamespace() { return ""; };
|
||||
|
||||
enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE };
|
||||
enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE, ANY_VARIABLE };
|
||||
|
||||
/**
|
||||
* Generate a single unique number for the specified instruction.
|
||||
@@ -478,7 +497,20 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
const gd::String& lhs,
|
||||
const gd::String& rhs);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Generate the code to access the local variables stack.
|
||||
*/
|
||||
virtual gd::String GenerateLocalVariablesStackAccessor();
|
||||
|
||||
/**
|
||||
* \brief Generate an any variable getter that fallbacks on scene variable for
|
||||
* compatibility reason.
|
||||
*/
|
||||
gd::String
|
||||
GenerateAnyOrSceneVariableGetter(const gd::Expression &variableExpression,
|
||||
EventsCodeGenerationContext &context);
|
||||
|
||||
protected:
|
||||
virtual const gd::String GenerateRelationalOperatorCodes(
|
||||
const gd::String& operatorString);
|
||||
|
||||
@@ -496,7 +528,7 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
parameter -> string
|
||||
* - operator : Used to update a value using a setter and a getter -> string
|
||||
* - key, mouse, objectvar, scenevar, globalvar, password, musicfile,
|
||||
soundfile, police -> string
|
||||
soundfile -> string
|
||||
* - trueorfalse, yesorno -> boolean ( See GenerateTrue/GenerateFalse ).
|
||||
*
|
||||
* <br><br>
|
||||
@@ -534,11 +566,15 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
const VariableScope& scope,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& objectName) {
|
||||
// This code is only used as a mock.
|
||||
// See the real implementation in GDJS.
|
||||
if (scope == LAYOUT_VARIABLE) {
|
||||
return "getLayoutVariable(" + variableName + ")";
|
||||
|
||||
} else if (scope == PROJECT_VARIABLE) {
|
||||
return "getProjectVariable(" + variableName + ")";
|
||||
} else if (scope == ANY_VARIABLE) {
|
||||
return "getAnyVariable(" + variableName + ")";
|
||||
}
|
||||
|
||||
return "getVariableForObject(" + objectName + ", " + variableName + ")";
|
||||
@@ -779,6 +815,10 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
virtual gd::String GenerateGetBehaviorNameCode(
|
||||
const gd::String& behaviorName);
|
||||
|
||||
void CheckBehaviorParameters(
|
||||
const gd::Instruction &instruction,
|
||||
const gd::InstructionMetadata &instrInfos);
|
||||
|
||||
const gd::Platform& platform; ///< The platform being used.
|
||||
|
||||
gd::ProjectScopedContainers projectScopedContainers;
|
||||
@@ -809,8 +849,9 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
instructionUniqueIds; ///< The unique ids generated for instructions.
|
||||
size_t eventsListNextUniqueId; ///< The next identifier to use for an events
|
||||
///< list function name.
|
||||
|
||||
gd::DiagnosticReport* diagnosticReport;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EVENTSCODEGENERATOR_H
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
|
||||
#include "GDCore/Events/CodeGeneration/DiagnosticReport.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -39,7 +40,8 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
EventsCodeGenerationContext& context,
|
||||
const gd::String& rootType,
|
||||
const gd::Expression& expression,
|
||||
const gd::String& rootObjectName) {
|
||||
const gd::String& rootObjectName,
|
||||
const gd::String& extraInfo) {
|
||||
ExpressionCodeGenerator generator(rootType, rootObjectName, codeGenerator, context);
|
||||
|
||||
auto node = expression.GetRootNode();
|
||||
@@ -52,13 +54,34 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
|
||||
gd::ExpressionValidator validator(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetProjectScopedContainers(),
|
||||
rootType);
|
||||
rootType,
|
||||
extraInfo);
|
||||
node->Visit(validator);
|
||||
if (!validator.GetFatalErrors().empty()) {
|
||||
std::cout << "Error: \"" << validator.GetFatalErrors()[0]->GetMessage()
|
||||
<< "\" in: \"" << expression.GetPlainString() << "\" ("
|
||||
<< rootType << ")" << std::endl;
|
||||
|
||||
auto *diagnosticReport = codeGenerator.GetDiagnosticReport();
|
||||
if (diagnosticReport) {
|
||||
for (auto *error : validator.GetFatalErrors()) {
|
||||
if (error->GetType() ==
|
||||
gd::ExpressionParserError::ErrorType::UndeclaredVariable ||
|
||||
error->GetType() ==
|
||||
gd::ExpressionParserError::ErrorType::UnknownIdentifier) {
|
||||
|
||||
const auto& variableName = error->GetActualValue();
|
||||
if (!variableName.empty()) {
|
||||
gd::ProjectDiagnostic projectDiagnostic(
|
||||
gd::ProjectDiagnostic::ErrorType::UndeclaredVariable,
|
||||
error->GetMessage(), error->GetActualValue(),
|
||||
"", error->GetObjectName());
|
||||
diagnosticReport->Add(projectDiagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return generator.GenerateDefaultValue(rootType);
|
||||
}
|
||||
|
||||
@@ -110,11 +133,13 @@ void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
|
||||
if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
// The node is a variable inside an expression waiting for a *variable* to be returned, not its value.
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
type == "globalvar"
|
||||
type == "variable"
|
||||
? gd::EventsCodeGenerator::ANY_VARIABLE
|
||||
: type == "globalvar"
|
||||
? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: ((type == "scenevar")
|
||||
: type == "scenevar"
|
||||
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
|
||||
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
@@ -137,19 +162,8 @@ void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
|
||||
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
if (!codeGenerator.HasProjectAndLayout()) {
|
||||
gd::LogWarning("Tried to generate access to a variable without a project/scene - the code generator only works for global and scene variables for now.");
|
||||
output += GenerateDefaultValue(type);
|
||||
return;
|
||||
}
|
||||
|
||||
// This could be adapted in the future if more scopes are supported.
|
||||
EventsCodeGenerator::VariableScope scope = gd::EventsCodeGenerator::PROJECT_VARIABLE;
|
||||
if (codeGenerator.GetProjectScopedContainers().GetVariablesContainersList().GetBottomMostVariablesContainer()->Has(node.name)) {
|
||||
scope = gd::EventsCodeGenerator::LAYOUT_VARIABLE;
|
||||
}
|
||||
|
||||
output += codeGenerator.GenerateGetVariable(node.name, scope, context, "");
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.name, gd::EventsCodeGenerator::ANY_VARIABLE, context, "");
|
||||
if (node.child) node.child->Visit(*this);
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
@@ -209,11 +223,13 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
codeGenerator.GenerateObject(node.identifierName, type, context);
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
type == "globalvar"
|
||||
type == "variable"
|
||||
? gd::EventsCodeGenerator::ANY_VARIABLE
|
||||
: type == "globalvar"
|
||||
? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: ((type == "scenevar")
|
||||
: type == "scenevar"
|
||||
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
|
||||
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetObjectsContainersList(),
|
||||
@@ -236,19 +252,9 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
node.childIdentifierName, gd::EventsCodeGenerator::OBJECT_VARIABLE, context, node.identifierName);
|
||||
output += codeGenerator.GenerateVariableValueAs(type);
|
||||
}, [&]() {
|
||||
if (!codeGenerator.HasProjectAndLayout()) {
|
||||
gd::LogWarning("Tried to generate access to a variable without a project/scene - the code generator only works for global and scene variables for now.");
|
||||
output += GenerateDefaultValue(type);
|
||||
return;
|
||||
}
|
||||
|
||||
// This could be adapted in the future if more scopes are supported at runtime.
|
||||
EventsCodeGenerator::VariableScope scope = gd::EventsCodeGenerator::PROJECT_VARIABLE;
|
||||
if (variablesContainersList.GetBottomMostVariablesContainer()->Has(node.identifierName)) {
|
||||
scope = gd::EventsCodeGenerator::LAYOUT_VARIABLE;
|
||||
}
|
||||
|
||||
output += codeGenerator.GenerateGetVariable(node.identifierName, scope, context, "");
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.identifierName, gd::EventsCodeGenerator::ANY_VARIABLE, context,
|
||||
"");
|
||||
if (!node.childIdentifierName.empty()) {
|
||||
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
|
||||
}
|
||||
@@ -424,11 +430,11 @@ gd::String ExpressionCodeGenerator::GenerateParametersCodes(
|
||||
size_t nonCodeOnlyParameterIndex = 0;
|
||||
gd::String parametersCode;
|
||||
for (std::size_t i = initialParameterIndex;
|
||||
i < expressionMetadata.parameters.size();
|
||||
i < expressionMetadata.GetParameters().GetParametersCount();
|
||||
++i) {
|
||||
if (i != initialParameterIndex) parametersCode += ", ";
|
||||
|
||||
auto& parameterMetadata = expressionMetadata.parameters[i];
|
||||
auto& parameterMetadata = expressionMetadata.GetParameters().GetParameter(i);
|
||||
if (!parameterMetadata.IsCodeOnly()) {
|
||||
if (nonCodeOnlyParameterIndex < parameters.size()) {
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
|
||||
|
@@ -59,7 +59,8 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
|
||||
EventsCodeGenerationContext& context,
|
||||
const gd::String& type,
|
||||
const gd::Expression& expression,
|
||||
const gd::String& objectName = "");
|
||||
const gd::String& objectName = "",
|
||||
const gd::String& extraInfo = "");
|
||||
|
||||
const gd::String& GetOutput() { return output; };
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
namespace gd {
|
||||
|
||||
EventsList BaseEvent::badSubEvents;
|
||||
VariablesContainer BaseEvent::badLocalVariables;
|
||||
std::vector<gd::String> BaseEvent::emptyDependencies;
|
||||
gd::String BaseEvent::emptySourceFile;
|
||||
|
||||
@@ -28,6 +29,8 @@ BaseEvent::BaseEvent()
|
||||
|
||||
bool BaseEvent::HasSubEvents() const { return !GetSubEvents().IsEmpty(); }
|
||||
|
||||
bool BaseEvent::HasVariables() const { return GetVariables().Count() > 0; }
|
||||
|
||||
gd::String BaseEvent::GenerateEventCode(
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
|
@@ -3,9 +3,7 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#ifndef GDCORE_EVENT_H
|
||||
#define GDCORE_EVENT_H
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
@@ -26,6 +24,7 @@ class SerializerElement;
|
||||
class Instruction;
|
||||
class EventVisitor;
|
||||
class ReadOnlyEventVisitor;
|
||||
class VariablesContainer;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -92,6 +91,32 @@ class GD_CORE_API BaseEvent {
|
||||
*/
|
||||
bool HasSubEvents() const;
|
||||
|
||||
/**
|
||||
* Derived class have to redefine this function, so as to return true, if they
|
||||
* can have local variables.
|
||||
*/
|
||||
virtual bool CanHaveVariables() const { return false; }
|
||||
|
||||
/**
|
||||
* Return the local variables, if applicable.
|
||||
*/
|
||||
virtual const gd::VariablesContainer& GetVariables() const {
|
||||
return badLocalVariables;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the local variables, if applicable.
|
||||
*/
|
||||
virtual gd::VariablesContainer& GetVariables() {
|
||||
return badLocalVariables;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Return true if the events has local variables.
|
||||
* \warning This is only applicable when CanHaveVariables() return true.
|
||||
*/
|
||||
bool HasVariables() const;
|
||||
|
||||
/**
|
||||
* \brief Return a list of all conditions of the event.
|
||||
* \note Used to preprocess or search in the conditions.
|
||||
@@ -301,6 +326,7 @@ class GD_CORE_API BaseEvent {
|
||||
///< Used for saving the event for instance.
|
||||
|
||||
static gd::EventsList badSubEvents;
|
||||
static gd::VariablesContainer badLocalVariables;
|
||||
static std::vector<gd::String> emptyDependencies;
|
||||
static gd::String emptySourceFile;
|
||||
};
|
||||
@@ -325,6 +351,3 @@ class EmptyEvent : public BaseEvent {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EVENT_H
|
||||
#endif
|
||||
|
@@ -18,7 +18,6 @@ class BaseEvent;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
class TiXmlElement;
|
||||
|
||||
#undef CreateEvent
|
||||
|
||||
|
@@ -38,7 +38,7 @@ using namespace gd::GrammarTerminals;
|
||||
* parser by refactoring out the dependency on gd::MetadataProvider (injecting
|
||||
* instead functions to be called to query supported functions).
|
||||
*
|
||||
* \see gd::ExpressionParserDiagnostic
|
||||
* \see gd::ExpressionParserError
|
||||
* \see gd::ExpressionNode
|
||||
*/
|
||||
class GD_CORE_API ExpressionParser2 {
|
||||
@@ -547,28 +547,28 @@ class GD_CORE_API ExpressionParser2 {
|
||||
}
|
||||
///@}
|
||||
|
||||
std::unique_ptr<ExpressionParserDiagnostic> ValidateOperator(
|
||||
std::unique_ptr<ExpressionParserError> ValidateOperator(
|
||||
gd::String::value_type operatorChar) {
|
||||
if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' ||
|
||||
operatorChar == '*') {
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
return std::unique_ptr<ExpressionParserError>(nullptr);
|
||||
}
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
gd::ExpressionParserError::ErrorType::InvalidOperator,
|
||||
_("You've used an operator that is not supported. Operator should be "
|
||||
"either +, -, / or *."),
|
||||
GetCurrentPosition());
|
||||
}
|
||||
|
||||
std::unique_ptr<ExpressionParserDiagnostic> ValidateUnaryOperator(
|
||||
std::unique_ptr<ExpressionParserError> ValidateUnaryOperator(
|
||||
gd::String::value_type operatorChar,
|
||||
size_t position) {
|
||||
if (operatorChar == '+' || operatorChar == '-') {
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
return std::unique_ptr<ExpressionParserError>(nullptr);
|
||||
}
|
||||
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
gd::ExpressionParserError::ErrorType::InvalidOperator,
|
||||
_("You've used an \"unary\" operator that is not supported. Operator "
|
||||
"should be "
|
||||
"either + or -."),
|
||||
@@ -719,13 +719,15 @@ class GD_CORE_API ExpressionParser2 {
|
||||
std::unique_ptr<ExpressionParserError> RaiseSyntaxError(
|
||||
const gd::String &message) {
|
||||
return std::move(gd::make_unique<ExpressionParserError>(
|
||||
"syntax_error", message, GetCurrentPosition()));
|
||||
gd::ExpressionParserError::ErrorType::SyntaxError, message,
|
||||
GetCurrentPosition()));
|
||||
}
|
||||
|
||||
std::unique_ptr<ExpressionParserError> RaiseTypeError(
|
||||
const gd::String &message, size_t beginningPosition) {
|
||||
return std::move(gd::make_unique<ExpressionParserError>(
|
||||
"type_error", message, beginningPosition, GetCurrentPosition()));
|
||||
gd::ExpressionParserError::ErrorType::MismatchedType, message,
|
||||
beginningPosition, GetCurrentPosition()));
|
||||
}
|
||||
///@}
|
||||
|
||||
|
@@ -6,5 +6,5 @@
|
||||
#include "ExpressionParser2Node.h"
|
||||
|
||||
namespace gd {
|
||||
gd::String ExpressionParserDiagnostic::noMessage = "";
|
||||
|
||||
}
|
@@ -3,14 +3,14 @@
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EXPRESSIONPARSER2NODES_H
|
||||
#define GDCORE_EXPRESSIONPARSER2NODES_H
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
@@ -36,54 +36,61 @@ struct GD_CORE_API ExpressionParserLocation {
|
||||
|
||||
private:
|
||||
bool isValid;
|
||||
size_t startPosition;
|
||||
size_t endPosition;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A diagnostic that can be attached to a gd::ExpressionNode.
|
||||
*/
|
||||
struct GD_CORE_API ExpressionParserDiagnostic {
|
||||
virtual ~ExpressionParserDiagnostic() = default;
|
||||
virtual bool IsError() { return false; }
|
||||
virtual const gd::String &GetMessage() { return noMessage; }
|
||||
virtual size_t GetStartPosition() { return 0; }
|
||||
virtual size_t GetEndPosition() { return 0; }
|
||||
|
||||
private:
|
||||
static gd::String noMessage;
|
||||
size_t startPosition = 0;
|
||||
size_t endPosition = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief An error that can be attached to a gd::ExpressionNode.
|
||||
*/
|
||||
struct GD_CORE_API ExpressionParserError : public ExpressionParserDiagnostic {
|
||||
ExpressionParserError(const gd::String &type_,
|
||||
struct GD_CORE_API ExpressionParserError {
|
||||
enum ErrorType {
|
||||
SyntaxError,
|
||||
InvalidOperator,
|
||||
MismatchedType,
|
||||
UndeclaredVariable,
|
||||
UnknownIdentifier,
|
||||
BracketsNotAllowedForObjects,
|
||||
TooFewParameters,
|
||||
TooManyParameters,
|
||||
InvalidFunctionName,
|
||||
MalformedVariableParameter,
|
||||
MalformedObjectParameter,
|
||||
UnknownParameterType,
|
||||
MissingBehavior,
|
||||
VariableNameCollision,
|
||||
};
|
||||
|
||||
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
|
||||
const gd::String &message_,
|
||||
const ExpressionParserLocation &location_)
|
||||
: type(type_), message(message_), location(location_){};
|
||||
ExpressionParserError(const gd::String &type_,
|
||||
const gd::String &message_,
|
||||
size_t position_)
|
||||
const ExpressionParserLocation &location_,
|
||||
const gd::String &actualValue_ = "",
|
||||
const gd::String &objectName_ = "")
|
||||
: type(type_), message(message_), location(location_),
|
||||
actualValue(actualValue_), objectName(objectName_){};
|
||||
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
|
||||
const gd::String &message_, size_t position_)
|
||||
: type(type_), message(message_), location(position_){};
|
||||
ExpressionParserError(const gd::String &type_,
|
||||
const gd::String &message_,
|
||||
size_t startPosition_,
|
||||
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
|
||||
const gd::String &message_, size_t startPosition_,
|
||||
size_t endPosition_)
|
||||
: type(type_),
|
||||
message(message_),
|
||||
: type(type_), message(message_),
|
||||
location(startPosition_, endPosition_){};
|
||||
virtual ~ExpressionParserError(){};
|
||||
|
||||
bool IsError() override { return true; }
|
||||
const gd::String &GetMessage() override { return message; }
|
||||
size_t GetStartPosition() override { return location.GetStartPosition(); }
|
||||
size_t GetEndPosition() override { return location.GetEndPosition(); }
|
||||
gd::ExpressionParserError::ErrorType GetType() { return type; }
|
||||
const gd::String &GetMessage() { return message; }
|
||||
const gd::String &GetObjectName() { return objectName; }
|
||||
const gd::String &GetActualValue() { return actualValue; }
|
||||
size_t GetStartPosition() { return location.GetStartPosition(); }
|
||||
size_t GetEndPosition() { return location.GetEndPosition(); }
|
||||
|
||||
private:
|
||||
gd::String type;
|
||||
private:
|
||||
gd::ExpressionParserError::ErrorType type;
|
||||
gd::String message;
|
||||
ExpressionParserLocation location;
|
||||
gd::String objectName;
|
||||
gd::String actualValue;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -95,7 +102,7 @@ struct GD_CORE_API ExpressionNode {
|
||||
virtual ~ExpressionNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker){};
|
||||
|
||||
std::unique_ptr<ExpressionParserDiagnostic> diagnostic;
|
||||
std::unique_ptr<ExpressionParserError> diagnostic;
|
||||
ExpressionParserLocation location; ///< The location of the entire node. Some
|
||||
/// nodes might have other locations
|
||||
/// stored inside them. For example, a
|
||||
@@ -425,5 +432,3 @@ struct GD_CORE_API EmptyNode : public FunctionCallOrObjectFunctionNameOrEmptyNod
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
||||
|
@@ -182,10 +182,10 @@ void EventsListSerialization::UpdateInstructionsFromGD2x(
|
||||
// Common updates for some parameters
|
||||
const std::vector<gd::Expression>& parameters = instr.GetParameters();
|
||||
for (std::size_t j = 0;
|
||||
j < parameters.size() && j < metadata.parameters.size();
|
||||
j < parameters.size() && j < metadata.parameters.GetParametersCount();
|
||||
++j) {
|
||||
if (metadata.parameters[j].GetType() == "relationalOperator" ||
|
||||
metadata.parameters[j].GetType() == "operator") {
|
||||
if (metadata.parameters.GetParameter(j).GetType() == "relationalOperator" ||
|
||||
metadata.parameters.GetParameter(j).GetType() == "operator") {
|
||||
if (j == parameters.size() - 1) {
|
||||
std::cout << "ERROR: No more parameters after a [relational]operator "
|
||||
"when trying to update an instruction from GD2.x";
|
||||
|
@@ -66,6 +66,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddAction("CopyArgumentToVariable",
|
||||
_("Copy function parameter to variable"),
|
||||
@@ -78,9 +79,25 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "variable")
|
||||
.AddParameter("scenevar", _("Scene variable"))
|
||||
.SetHidden()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("CopyArgumentToVariable2",
|
||||
_("Copy function parameter to variable"),
|
||||
_("Copy a function parameter (also called \"argument\") to a variable. "
|
||||
"The parameter type must be a variable."),
|
||||
_("Copy the parameter _PARAM0_ into the variable _PARAM1_"),
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "variable")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddAction("CopyVariableToArgument",
|
||||
_("Copy variable to function parameter"),
|
||||
@@ -93,6 +110,21 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "variable")
|
||||
.AddParameter("scenevar", _("Scene variable"))
|
||||
.SetHidden()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("CopyVariableToArgument2",
|
||||
_("Copy variable to function parameter"),
|
||||
_("Copy a variable to function parameter (also called \"argument\"). "
|
||||
"The parameter type must be a variable."),
|
||||
_("Copy the variable _PARAM1_ into the parameter _PARAM0_"),
|
||||
"",
|
||||
"res/function32.png",
|
||||
"res/function32.png")
|
||||
.SetHelpPath("/events/functions/return")
|
||||
.AddParameter("functionParameterName", _("Parameter name"), "variable")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
|
@@ -417,6 +417,93 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetDefaultValue("\"\"")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("SetNumberObjectVariable",
|
||||
_("Change variable value"),
|
||||
_("Modify the number value of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction("SetStringObjectVariable",
|
||||
_("Change text variable"),
|
||||
_("Modify the text of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardOperatorParameters("string",
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction("SetBooleanObjectVariable",
|
||||
_("Change boolean variable"),
|
||||
_("Modify the boolean value of an object variable."),
|
||||
_("Change the variable _PARAM1_ of _PARAM0_: _PARAM2_"),
|
||||
_("Variables"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.AddParameter("operator", _("Value"), "boolean")
|
||||
// This parameter allows to keep the operand expression
|
||||
// when the editor switch between variable instructions.
|
||||
.AddCodeOnlyParameter("yesorno", _("Value"))
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddCondition("NumberObjectVariable",
|
||||
_("Variable value"),
|
||||
_("Compare the number value of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddCondition("StringObjectVariable",
|
||||
_("Text variable"),
|
||||
_("Compare the text of an object variable."),
|
||||
_("the variable _PARAM1_"),
|
||||
_("Variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddCondition("BooleanObjectVariable",
|
||||
_("Boolean variable"),
|
||||
_("Compare the boolean value of an object variable."),
|
||||
_("The variable _PARAM1_ of _PARAM0_ is _PARAM2_"),
|
||||
_("Variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("Check if the value is"))
|
||||
.SetDefaultValue("true")
|
||||
// This parameter allows to keep the operand expression
|
||||
// when the editor switch between variable instructions.
|
||||
.AddCodeOnlyParameter("yesorno", _("Value"))
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction("ModVarObjet",
|
||||
_("Change number variable"),
|
||||
_("Modify the number value of an object variable."),
|
||||
@@ -428,7 +515,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddAction("ModVarObjetTxt",
|
||||
_("Change text variable"),
|
||||
@@ -441,7 +529,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardOperatorParameters("string",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddAction("SetObjectVariableAsBoolean",
|
||||
_("Change boolean variable"),
|
||||
@@ -454,7 +543,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("New Value:"));
|
||||
.AddParameter("trueorfalse", _("New Value:"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddAction(
|
||||
"ToggleObjectVariableAsBoolean",
|
||||
@@ -469,7 +559,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"res/actions/var.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"));
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddCondition("ObjectVariableChildExists",
|
||||
_("Child existence"),
|
||||
@@ -657,7 +748,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions());
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddCondition("VarObjetTxt",
|
||||
_("Text variable"),
|
||||
@@ -670,7 +762,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", ParameterOptions::MakeNewOptions());
|
||||
"string", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddCondition("ObjectVariableAsBoolean",
|
||||
_("Boolean variable"),
|
||||
@@ -683,7 +776,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("Check if the value is"))
|
||||
.SetDefaultValue("true");
|
||||
.SetDefaultValue("true")
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddCondition("VarObjetDef",
|
||||
"Variable defined",
|
||||
@@ -697,6 +791,48 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("string", _("Variable"))
|
||||
.SetHidden(); // Deprecated.
|
||||
|
||||
obj.AddAction(
|
||||
"PushStringToObjectVariable",
|
||||
_("Add text variable"),
|
||||
_("Adds a text (string) to the end of an object array variable."),
|
||||
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
|
||||
_("Variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("string", _("Text to add"))
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction("PushNumberToObjectVariable",
|
||||
_("Add variable array value"),
|
||||
_("Adds a number to the end of an object array variable."),
|
||||
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
|
||||
_("Variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("expression", _("Number to add"))
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
obj.AddAction(
|
||||
"PushBooleanToObjectVariable",
|
||||
_("Add boolean variable"),
|
||||
_("Adds a boolean to the end of an object array variable."),
|
||||
_("Add value _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
|
||||
_("Variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("trueorfalse", _("Boolean to add"))
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForLayoutEventsOnly();
|
||||
|
||||
// Deprecated
|
||||
obj.AddAction(
|
||||
"ObjectVariablePush",
|
||||
_("Add existing variable"),
|
||||
@@ -708,6 +844,23 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("scenevar", _("Scene variable with the content to add"))
|
||||
.SetParameterLongDescription(_("The content of the object variable will "
|
||||
"*be copied* and added at the "
|
||||
"end of the array."))
|
||||
.MarkAsAdvanced()
|
||||
.SetHidden();
|
||||
|
||||
obj.AddAction(
|
||||
"ObjectVariablePush2",
|
||||
_("Add existing variable"),
|
||||
_("Adds an existing variable to the end of an object array variable."),
|
||||
_("Add variable _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
|
||||
_("Variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("variable", _("Scene variable with the content to add"))
|
||||
.SetParameterLongDescription(_("The content of the object variable will "
|
||||
"*be copied* and added at the "
|
||||
"end of the array."))
|
||||
@@ -724,7 +877,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("string", _("Text to add"))
|
||||
.MarkAsAdvanced();
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddAction("ObjectVariablePushNumber",
|
||||
_("Add number variable"),
|
||||
@@ -736,7 +890,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("expression", _("Number to add"))
|
||||
.MarkAsAdvanced();
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddAction(
|
||||
"ObjectVariablePushBool",
|
||||
@@ -749,7 +904,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Array variable"))
|
||||
.AddParameter("trueorfalse", _("Boolean to add"))
|
||||
.MarkAsAdvanced();
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddAction(
|
||||
"ObjectVariableRemoveAt",
|
||||
@@ -1203,7 +1359,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Variables"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"));
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddExpression(
|
||||
"VariableChildCount",
|
||||
@@ -1220,7 +1377,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Variables"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectvar", _("Variable"));
|
||||
.AddParameter("objectvar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
obj.AddExpression("ObjectTimerElapsedTime",
|
||||
_("Object timer value"),
|
||||
@@ -1610,6 +1768,22 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("expression",
|
||||
_("Angle of tolerance, in degrees (0: minimum tolerance)"))
|
||||
.AddCodeOnlyParameter("conditionInverted", "")
|
||||
.SetHidden()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddCondition("IsTurnedTowardObject",
|
||||
_("An object is turned toward another"),
|
||||
_("Check if an object is turned toward another"),
|
||||
_("_PARAM0_ is turned toward _PARAM1_ ± _PARAM2_°"),
|
||||
_("Angle"),
|
||||
"res/conditions/estTourne24.png",
|
||||
"res/conditions/estTourne.png")
|
||||
.AddParameter("objectList", _("Name of the object"))
|
||||
.AddParameter("objectList", _("Name of the second object"))
|
||||
.AddParameter("expression",
|
||||
_("Angle of tolerance, in degrees (0: minimum tolerance)"))
|
||||
.AddCodeOnlyParameter("conditionInverted", "")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
|
@@ -327,6 +327,25 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
|
||||
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
|
||||
.SetDefaultValue("0");
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"CameraZoom",
|
||||
_("Camera zoom"),
|
||||
_("Compare the zoom of a camera of a layer."),
|
||||
_("Zoom of camera _PARAM2_ of layer _PARAM1_"),
|
||||
"",
|
||||
"res/conditions/camera24.png",
|
||||
"res/conditions/camera.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("layer", _("Layer"), "", true)
|
||||
.SetDefaultValue("\"\"")
|
||||
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
|
||||
.SetDefaultValue("0")
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
|
||||
_("Zoom")))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"FixCamera",
|
||||
|
@@ -68,19 +68,22 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
||||
|
||||
extension
|
||||
.AddStrExpression("ToJSON",
|
||||
_("Convert scene variable to JSON"),
|
||||
_("Convert a scene variable to JSON"),
|
||||
_("Convert variable to JSON"),
|
||||
_("Convert a variable to JSON"),
|
||||
_("JSON"),
|
||||
"res/conditions/toujours24_black.png")
|
||||
.AddParameter("scenevar", _("Scene variable to be stringified"));
|
||||
.AddParameter("variable", _("The variable to be stringified"),
|
||||
"AllowUndeclaredVariable");
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddStrExpression("GlobalVarToJSON",
|
||||
_("Convert global variable to JSON"),
|
||||
_("Convert a global variable to JSON"),
|
||||
_("JSON"),
|
||||
"res/conditions/toujours24_black.png")
|
||||
.AddParameter("globalvar", _("The global variable to be stringified"));
|
||||
.AddParameter("globalvar", _("The global variable to be stringified"))
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddStrExpression("ObjectVarToJSON",
|
||||
@@ -91,6 +94,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
||||
.AddParameter("objectPtr", _("The object with the variable"))
|
||||
.AddParameter("objectvar", _("The object variable to be stringified"));
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddAction(
|
||||
"JSONToVariableStructure",
|
||||
@@ -102,8 +106,10 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
||||
"res/actions/net.png")
|
||||
.AddParameter("string", _("JSON string"))
|
||||
.AddParameter("scenevar", _("Variable where store the JSON object"))
|
||||
.MarkAsAdvanced();
|
||||
.MarkAsAdvanced()
|
||||
.SetHidden();
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddAction("JSONToGlobalVariableStructure",
|
||||
_("Convert JSON to global variable"),
|
||||
@@ -116,6 +122,20 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
|
||||
.AddParameter("string", _("JSON string"))
|
||||
.AddParameter("globalvar",
|
||||
_("Global variable where store the JSON object"))
|
||||
.MarkAsAdvanced()
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"JSONToVariableStructure2",
|
||||
_("Convert JSON to a variable"),
|
||||
_("Parse a JSON object and store it into a variable"),
|
||||
_("Convert JSON string _PARAM0_ and store it into variable _PARAM1_"),
|
||||
"",
|
||||
"res/actions/net24.png",
|
||||
"res/actions/net.png")
|
||||
.AddParameter("string", _("JSON string"))
|
||||
.AddParameter("variable", _("Variable where to store the JSON object"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
|
@@ -98,6 +98,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddParameter("string", _("Text"));
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddAction(
|
||||
"LireFichierExp",
|
||||
@@ -114,8 +115,27 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("scenevar", _("Scene variables"));
|
||||
.AddParameter("scenevar", _("Scene variable"))
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"ReadNumberFromStorage",
|
||||
_("Load a value"),
|
||||
_("Load the value saved in the specified element and store it in a "
|
||||
"variable.\nSpecify the structure leading to the element using / "
|
||||
"(example : Root/Level/Current)\nSpaces are forbidden in element "
|
||||
"names."),
|
||||
_("Load _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
|
||||
"",
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("variable", _("Variable"));
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddAction(
|
||||
"LireFichierTxt",
|
||||
@@ -133,7 +153,26 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("scenevar", _("Scene variables"));
|
||||
.AddParameter("scenevar", _("Scene variable"))
|
||||
.SetHidden();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"ReadStringFromStorage",
|
||||
_("Load a text"),
|
||||
_("Load the text saved in the specified element and store it in a "
|
||||
"variable.\nSpecify the structure leading to the element using / "
|
||||
"(example : Root/Level/Current)\nSpaces are forbidden in element "
|
||||
"names."),
|
||||
_("Load _PARAM1_ from storage _PARAM0_ and store as text in "
|
||||
"_PARAM3_"),
|
||||
"",
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("variable", _("Variable"));
|
||||
|
||||
extension
|
||||
.AddAction("DeleteGroupFichier",
|
||||
|
@@ -338,6 +338,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
||||
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
|
||||
.SetDefaultValue("0");
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddCondition(
|
||||
"PopStartedTouch",
|
||||
@@ -354,6 +355,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.SetHidden();
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddCondition(
|
||||
"PopEndedTouch",
|
||||
@@ -370,6 +372,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.SetHidden();
|
||||
|
||||
// Deprecated
|
||||
extension
|
||||
.AddCondition(
|
||||
"HasAnyTouchStarted",
|
||||
|
@@ -6,8 +6,6 @@
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
#include <vector>
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
@@ -4,13 +4,11 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_ANIMATION_H
|
||||
#define GDCORE_ANIMATION_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Direction;
|
||||
}
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -93,4 +91,3 @@ class GD_CORE_API Animation {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // GDCORE_ANIMATION_H
|
||||
|
@@ -3,12 +3,12 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_DIRECTION_H
|
||||
#define GDCORE_DIRECTION_H
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
namespace gd {
|
||||
class Sprite;
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
@@ -142,4 +142,3 @@ class GD_CORE_API Direction {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // GDCORE_DIRECTION_H
|
||||
|
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteAnimationList.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
Animation SpriteAnimationList::badAnimation;
|
||||
|
||||
SpriteAnimationList::SpriteAnimationList()
|
||||
: adaptCollisionMaskAutomatically(true) {}
|
||||
|
||||
SpriteAnimationList::~SpriteAnimationList(){};
|
||||
|
||||
void SpriteAnimationList::UnserializeFrom(const gd::SerializerElement& element) {
|
||||
adaptCollisionMaskAutomatically =
|
||||
element.GetBoolAttribute("adaptCollisionMaskAutomatically", false);
|
||||
|
||||
RemoveAllAnimations();
|
||||
const gd::SerializerElement& animationsElement =
|
||||
element.GetChild("animations", 0, "Animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation", "Animation");
|
||||
for (std::size_t i = 0; i < animationsElement.GetChildrenCount(); ++i) {
|
||||
const gd::SerializerElement& animationElement =
|
||||
animationsElement.GetChild(i);
|
||||
Animation newAnimation;
|
||||
|
||||
newAnimation.useMultipleDirections = animationElement.GetBoolAttribute(
|
||||
"useMultipleDirections", false, "typeNormal");
|
||||
newAnimation.SetName(animationElement.GetStringAttribute("name", ""));
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (animationElement.HasChild("Direction")) {
|
||||
for (std::size_t j = 0;
|
||||
j < animationElement.GetChildrenCount("Direction");
|
||||
++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(animationElement.GetChild("Direction", j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
// End of compatibility code
|
||||
else {
|
||||
const gd::SerializerElement& directionsElement =
|
||||
animationElement.GetChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t j = 0; j < directionsElement.GetChildrenCount(); ++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(directionsElement.GetChild(j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
AddAnimation(newAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteAnimationList::SerializeTo(gd::SerializerElement& element) const {
|
||||
element.SetAttribute("adaptCollisionMaskAutomatically",
|
||||
adaptCollisionMaskAutomatically);
|
||||
|
||||
// Animations
|
||||
gd::SerializerElement& animationsElement = element.AddChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
for (std::size_t k = 0; k < GetAnimationsCount(); k++) {
|
||||
gd::SerializerElement& animationElement =
|
||||
animationsElement.AddChild("animation");
|
||||
|
||||
animationElement.SetAttribute("useMultipleDirections",
|
||||
GetAnimation(k).useMultipleDirections);
|
||||
animationElement.SetAttribute("name", GetAnimation(k).GetName());
|
||||
|
||||
gd::SerializerElement& directionsElement =
|
||||
animationElement.AddChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t l = 0; l < GetAnimation(k).GetDirectionsCount(); l++) {
|
||||
GetAnimation(k).GetDirection(l).SerializeTo(
|
||||
directionsElement.AddChild("direction"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteAnimationList::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
for (std::size_t j = 0; j < GetAnimationsCount(); j++) {
|
||||
for (std::size_t k = 0; k < GetAnimation(j).GetDirectionsCount(); k++) {
|
||||
for (std::size_t l = 0;
|
||||
l < GetAnimation(j).GetDirection(k).GetSpritesCount();
|
||||
l++) {
|
||||
worker.ExposeImage(
|
||||
GetAnimation(j).GetDirection(k).GetSprite(l).GetImageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SpriteAnimationList::HasAnimationNamed(const gd::String &name) const {
|
||||
return !name.empty() && (find_if(animations.begin(), animations.end(),
|
||||
[&name](const Animation &animation) {
|
||||
return animation.GetName() == name;
|
||||
}) != animations.end());
|
||||
}
|
||||
|
||||
const Animation& SpriteAnimationList::GetAnimation(std::size_t nb) const {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
}
|
||||
|
||||
Animation& SpriteAnimationList::GetAnimation(std::size_t nb) {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
}
|
||||
|
||||
void SpriteAnimationList::AddAnimation(const Animation& animation) {
|
||||
animations.push_back(animation);
|
||||
}
|
||||
|
||||
bool SpriteAnimationList::RemoveAnimation(std::size_t nb) {
|
||||
if (nb >= GetAnimationsCount()) return false;
|
||||
|
||||
animations.erase(animations.begin() + nb);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteAnimationList::SwapAnimations(std::size_t firstIndex,
|
||||
std::size_t secondIndex) {
|
||||
if (firstIndex < animations.size() && secondIndex < animations.size() &&
|
||||
firstIndex != secondIndex)
|
||||
std::swap(animations[firstIndex], animations[secondIndex]);
|
||||
}
|
||||
|
||||
void SpriteAnimationList::MoveAnimation(std::size_t oldIndex, std::size_t newIndex) {
|
||||
if (oldIndex >= animations.size() || newIndex >= animations.size()) return;
|
||||
|
||||
auto animation = animations[oldIndex];
|
||||
animations.erase(animations.begin() + oldIndex);
|
||||
animations.insert(animations.begin() + newIndex, animation);
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
|
||||
namespace gd {
|
||||
class InitialInstance;
|
||||
class SerializerElement;
|
||||
class PropertyDescriptor;
|
||||
class ArbitraryResourceWorker;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A list of animations, containing directions with images and collision mask.
|
||||
*
|
||||
* It's used in the configuration of object that implements image-based animations.
|
||||
*
|
||||
* \see Animation
|
||||
* \see Direction
|
||||
* \see Sprite
|
||||
* \ingroup SpriteObjectExtension
|
||||
*/
|
||||
class GD_CORE_API SpriteAnimationList {
|
||||
public:
|
||||
SpriteAnimationList();
|
||||
virtual ~SpriteAnimationList();
|
||||
|
||||
void ExposeResources(gd::ArbitraryResourceWorker& worker);
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
*/
|
||||
const Animation& GetAnimation(std::size_t nb) const;
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
*/
|
||||
Animation& GetAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Return the number of animations this object has.
|
||||
*/
|
||||
std::size_t GetAnimationsCount() const { return animations.size(); };
|
||||
|
||||
/**
|
||||
* \brief Return true if an animation exists for a given name.
|
||||
*/
|
||||
bool HasAnimationNamed(const gd::String &name) const;
|
||||
|
||||
/**
|
||||
* \brief Add an animation at the end of the existing ones.
|
||||
*/
|
||||
void AddAnimation(const Animation& animation);
|
||||
|
||||
/**
|
||||
* \brief Remove an animation.
|
||||
*/
|
||||
bool RemoveAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Remove all animations.
|
||||
*/
|
||||
void RemoveAllAnimations() { animations.clear(); }
|
||||
|
||||
/**
|
||||
* \brief Return true if the object hasn't any animation.
|
||||
*/
|
||||
bool HasNoAnimations() const { return animations.empty(); }
|
||||
|
||||
/**
|
||||
* \brief Swap the position of two animations
|
||||
*/
|
||||
void SwapAnimations(std::size_t firstIndex, std::size_t secondIndex);
|
||||
|
||||
/**
|
||||
* \brief Change the position of the specified animation
|
||||
*/
|
||||
void MoveAnimation(std::size_t oldIndex, std::size_t newIndex);
|
||||
|
||||
/**
|
||||
* \brief Return a read-only reference to the vector containing all the
|
||||
* animation of the object.
|
||||
*/
|
||||
const std::vector<Animation>& GetAllAnimations() const { return animations; }
|
||||
|
||||
/**
|
||||
* @brief Check if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
bool AdaptCollisionMaskAutomatically() const {
|
||||
return adaptCollisionMaskAutomatically;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
void SetAdaptCollisionMaskAutomatically(bool enable) {
|
||||
adaptCollisionMaskAutomatically = enable;
|
||||
}
|
||||
|
||||
void UnserializeFrom(const gd::SerializerElement& element);
|
||||
void SerializeTo(gd::SerializerElement& element) const;
|
||||
|
||||
private:
|
||||
|
||||
mutable std::vector<Animation> animations;
|
||||
|
||||
static Animation badAnimation; //< Bad animation when an out of bound
|
||||
// animation is requested.
|
||||
bool adaptCollisionMaskAutomatically; ///< If set to true, the collision
|
||||
///< mask will be automatically
|
||||
///< adapted to the animation of the
|
||||
///< object.
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -33,6 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"most elements of a game."),
|
||||
"CppPlatform/Extensions/spriteicon.png")
|
||||
.SetCategoryFullName(_("General"))
|
||||
.SetOpenFullEditorLabel(_("Edit animations"))
|
||||
.AddDefaultBehavior("EffectCapability::EffectBehavior")
|
||||
.AddDefaultBehavior("ResizableCapability::ResizableBehavior")
|
||||
.AddDefaultBehavior("ScalableCapability::ScalableBehavior")
|
||||
|
@@ -23,127 +23,45 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
Animation SpriteObject::badAnimation;
|
||||
|
||||
SpriteObject::SpriteObject()
|
||||
: updateIfNotVisible(false), adaptCollisionMaskAutomatically(true) {}
|
||||
: updateIfNotVisible(false),
|
||||
preScale(1) {}
|
||||
|
||||
SpriteObject::~SpriteObject(){};
|
||||
|
||||
void SpriteObject::DoUnserializeFrom(gd::Project& project,
|
||||
const gd::SerializerElement& element) {
|
||||
updateIfNotVisible = element.GetBoolAttribute("updateIfNotVisible", true);
|
||||
adaptCollisionMaskAutomatically =
|
||||
element.GetBoolAttribute("adaptCollisionMaskAutomatically", false);
|
||||
|
||||
RemoveAllAnimations();
|
||||
const gd::SerializerElement& animationsElement =
|
||||
element.GetChild("animations", 0, "Animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation", "Animation");
|
||||
for (std::size_t i = 0; i < animationsElement.GetChildrenCount(); ++i) {
|
||||
const gd::SerializerElement& animationElement =
|
||||
animationsElement.GetChild(i);
|
||||
Animation newAnimation;
|
||||
|
||||
newAnimation.useMultipleDirections = animationElement.GetBoolAttribute(
|
||||
"useMultipleDirections", false, "typeNormal");
|
||||
newAnimation.SetName(animationElement.GetStringAttribute("name", ""));
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (animationElement.HasChild("Direction")) {
|
||||
for (std::size_t j = 0;
|
||||
j < animationElement.GetChildrenCount("Direction");
|
||||
++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(animationElement.GetChild("Direction", j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
// End of compatibility code
|
||||
else {
|
||||
const gd::SerializerElement& directionsElement =
|
||||
animationElement.GetChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t j = 0; j < directionsElement.GetChildrenCount(); ++j) {
|
||||
Direction direction;
|
||||
direction.UnserializeFrom(directionsElement.GetChild(j));
|
||||
|
||||
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
|
||||
newAnimation.SetDirection(direction,
|
||||
newAnimation.GetDirectionsCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
AddAnimation(newAnimation);
|
||||
}
|
||||
preScale = element.GetDoubleAttribute("preScale", 1);
|
||||
animations.UnserializeFrom(element);
|
||||
}
|
||||
|
||||
void SpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
|
||||
element.SetAttribute("updateIfNotVisible", updateIfNotVisible);
|
||||
element.SetAttribute("adaptCollisionMaskAutomatically",
|
||||
adaptCollisionMaskAutomatically);
|
||||
|
||||
// Animations
|
||||
gd::SerializerElement& animationsElement = element.AddChild("animations");
|
||||
animationsElement.ConsiderAsArrayOf("animation");
|
||||
for (std::size_t k = 0; k < GetAnimationsCount(); k++) {
|
||||
gd::SerializerElement& animationElement =
|
||||
animationsElement.AddChild("animation");
|
||||
|
||||
animationElement.SetAttribute("useMultipleDirections",
|
||||
GetAnimation(k).useMultipleDirections);
|
||||
animationElement.SetAttribute("name", GetAnimation(k).GetName());
|
||||
|
||||
gd::SerializerElement& directionsElement =
|
||||
animationElement.AddChild("directions");
|
||||
directionsElement.ConsiderAsArrayOf("direction");
|
||||
for (std::size_t l = 0; l < GetAnimation(k).GetDirectionsCount(); l++) {
|
||||
GetAnimation(k).GetDirection(l).SerializeTo(
|
||||
directionsElement.AddChild("direction"));
|
||||
}
|
||||
if (preScale != 1) {
|
||||
element.SetAttribute("preScale", preScale);
|
||||
}
|
||||
animations.SerializeTo(element);
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> SpriteObject::GetProperties()
|
||||
const {
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
properties[_("Animate even if hidden or far from the screen")]
|
||||
.SetValue(updateIfNotVisible ? "true" : "false")
|
||||
.SetType("Boolean");
|
||||
properties["PLEASE_ALSO_SHOW_EDIT_BUTTON_THANKS"].SetValue("");
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool SpriteObject::UpdateProperty(const gd::String& name,
|
||||
const gd::String& value) {
|
||||
if (name == _("Animate even if hidden or far from the screen"))
|
||||
updateIfNotVisible = value == "1";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {
|
||||
for (std::size_t j = 0; j < GetAnimationsCount(); j++) {
|
||||
for (std::size_t k = 0; k < GetAnimation(j).GetDirectionsCount(); k++) {
|
||||
for (std::size_t l = 0;
|
||||
l < GetAnimation(j).GetDirection(k).GetSpritesCount();
|
||||
l++) {
|
||||
worker.ExposeImage(
|
||||
GetAnimation(j).GetDirection(k).GetSprite(l).GetImageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
animations.ExposeResources(worker);
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
SpriteObject::GetInitialInstanceProperties(
|
||||
const gd::InitialInstance& initialInstance,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) {
|
||||
const gd::InitialInstance& initialInstance) {
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
properties["animation"] =
|
||||
gd::PropertyDescriptor(
|
||||
@@ -157,9 +75,7 @@ SpriteObject::GetInitialInstanceProperties(
|
||||
bool SpriteObject::UpdateInitialInstanceProperty(
|
||||
gd::InitialInstance& initialInstance,
|
||||
const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) {
|
||||
const gd::String& value) {
|
||||
if (name == "animation") {
|
||||
initialInstance.SetRawDoubleProperty(
|
||||
"animation", std::max(0, value.empty() ? 0 : value.To<int>()));
|
||||
@@ -168,42 +84,25 @@ bool SpriteObject::UpdateInitialInstanceProperty(
|
||||
return true;
|
||||
}
|
||||
|
||||
const Animation& SpriteObject::GetAnimation(std::size_t nb) const {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
size_t SpriteObject::GetAnimationsCount() const {
|
||||
return animations.GetAnimationsCount();
|
||||
}
|
||||
|
||||
Animation& SpriteObject::GetAnimation(std::size_t nb) {
|
||||
if (nb >= animations.size()) return badAnimation;
|
||||
|
||||
return animations[nb];
|
||||
const gd::String &SpriteObject::GetAnimationName(size_t index) const {
|
||||
return animations.GetAnimation(index).GetName();
|
||||
}
|
||||
|
||||
void SpriteObject::AddAnimation(const Animation& animation) {
|
||||
animations.push_back(animation);
|
||||
bool SpriteObject::HasAnimationNamed(
|
||||
const gd::String &name) const {
|
||||
return animations.HasAnimationNamed(name);
|
||||
}
|
||||
|
||||
bool SpriteObject::RemoveAnimation(std::size_t nb) {
|
||||
if (nb >= GetAnimationsCount()) return false;
|
||||
|
||||
animations.erase(animations.begin() + nb);
|
||||
return true;
|
||||
const SpriteAnimationList& SpriteObject::GetAnimations() const {
|
||||
return animations;
|
||||
}
|
||||
|
||||
void SpriteObject::SwapAnimations(std::size_t firstIndex,
|
||||
std::size_t secondIndex) {
|
||||
if (firstIndex < animations.size() && secondIndex < animations.size() &&
|
||||
firstIndex != secondIndex)
|
||||
std::swap(animations[firstIndex], animations[secondIndex]);
|
||||
}
|
||||
|
||||
void SpriteObject::MoveAnimation(std::size_t oldIndex, std::size_t newIndex) {
|
||||
if (oldIndex >= animations.size() || newIndex >= animations.size()) return;
|
||||
|
||||
auto animation = animations[oldIndex];
|
||||
animations.erase(animations.begin() + oldIndex);
|
||||
animations.insert(animations.begin() + newIndex, animation);
|
||||
SpriteAnimationList& SpriteObject::GetAnimations() {
|
||||
return animations;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -4,18 +4,15 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_SPRITEOBJECT_H
|
||||
#define GDCORE_SPRITEOBJECT_H
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteAnimationList.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
|
||||
namespace gd {
|
||||
class InitialInstance;
|
||||
class Object;
|
||||
class Layout;
|
||||
class Sprite;
|
||||
class Animation;
|
||||
class SerializerElement;
|
||||
class PropertyDescriptor;
|
||||
} // namespace gd
|
||||
@@ -50,85 +47,26 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
|
||||
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor> GetInitialInstanceProperties(
|
||||
const gd::InitialInstance& position,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) override;
|
||||
const gd::InitialInstance& position) override;
|
||||
bool UpdateInitialInstanceProperty(gd::InitialInstance& position,
|
||||
const gd::String& name,
|
||||
const gd::String& value,
|
||||
gd::Project& project,
|
||||
gd::Layout& scene) override;
|
||||
const gd::String& value) override;
|
||||
|
||||
/** \name Animations
|
||||
* Methods related to animations management
|
||||
*/
|
||||
///@{
|
||||
size_t GetAnimationsCount() const override;
|
||||
|
||||
const gd::String &GetAnimationName(size_t index) const override;
|
||||
|
||||
bool HasAnimationNamed(const gd::String &animationName) const override;
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
* \brief Return the animation configuration.
|
||||
*/
|
||||
const Animation& GetAnimation(std::size_t nb) const;
|
||||
const SpriteAnimationList& GetAnimations() const;
|
||||
|
||||
/**
|
||||
* \brief Return the animation at the specified index.
|
||||
* If the index is out of bound, a "bad animation" object is returned.
|
||||
* @brief Return the animation configuration.
|
||||
*/
|
||||
Animation& GetAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Return the number of animations this object has.
|
||||
*/
|
||||
std::size_t GetAnimationsCount() const { return animations.size(); };
|
||||
|
||||
/**
|
||||
* \brief Add an animation at the end of the existing ones.
|
||||
*/
|
||||
void AddAnimation(const Animation& animation);
|
||||
|
||||
/**
|
||||
* \brief Remove an animation.
|
||||
*/
|
||||
bool RemoveAnimation(std::size_t nb);
|
||||
|
||||
/**
|
||||
* \brief Remove all animations.
|
||||
*/
|
||||
void RemoveAllAnimations() { animations.clear(); }
|
||||
|
||||
/**
|
||||
* \brief Return true if the object hasn't any animation.
|
||||
*/
|
||||
bool HasNoAnimations() const { return animations.empty(); }
|
||||
|
||||
/**
|
||||
* \brief Swap the position of two animations
|
||||
*/
|
||||
void SwapAnimations(std::size_t firstIndex, std::size_t secondIndex);
|
||||
|
||||
/**
|
||||
* \brief Change the position of the specified animation
|
||||
*/
|
||||
void MoveAnimation(std::size_t oldIndex, std::size_t newIndex);
|
||||
|
||||
/**
|
||||
* \brief Return a read-only reference to the vector containing all the
|
||||
* animation of the object.
|
||||
*/
|
||||
const std::vector<Animation>& GetAllAnimations() const { return animations; }
|
||||
|
||||
/**
|
||||
* @brief Check if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
bool AdaptCollisionMaskAutomatically() const {
|
||||
return adaptCollisionMaskAutomatically;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set if the collision mask adapts automatically to the animation.
|
||||
*/
|
||||
void SetAdaptCollisionMaskAutomatically(bool enable) {
|
||||
adaptCollisionMaskAutomatically = enable;
|
||||
}
|
||||
SpriteAnimationList& GetAnimations();
|
||||
|
||||
/**
|
||||
* \brief Set if the object animation should be played even if the object is
|
||||
@@ -143,25 +81,35 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
|
||||
* is hidden or far from the camera (false by default).
|
||||
*/
|
||||
bool GetUpdateIfNotVisible() const { return updateIfNotVisible; }
|
||||
///@}
|
||||
|
||||
/**
|
||||
* \brief Return the scale applied to object to evaluate the default dimensions.
|
||||
*/
|
||||
double GetPreScale() { return preScale; }
|
||||
|
||||
/**
|
||||
* \brief Set the scale applied to object to evaluate the default dimensions.
|
||||
*
|
||||
* Its value must be strictly positive.
|
||||
*/
|
||||
void SetPreScale(double preScale_) {
|
||||
if (preScale_ <= 0) {
|
||||
return;
|
||||
}
|
||||
preScale = preScale_;
|
||||
}
|
||||
|
||||
private:
|
||||
void DoUnserializeFrom(gd::Project& project,
|
||||
const gd::SerializerElement& element) override;
|
||||
void DoSerializeTo(gd::SerializerElement& element) const override;
|
||||
|
||||
mutable std::vector<Animation> animations;
|
||||
SpriteAnimationList animations;
|
||||
|
||||
bool updateIfNotVisible; ///< If set to true, ask the game engine to play
|
||||
///< object animation even if hidden or far from
|
||||
///< the screen.
|
||||
|
||||
static Animation badAnimation; //< Bad animation when an out of bound
|
||||
// animation is requested.
|
||||
bool adaptCollisionMaskAutomatically; ///< If set to true, the collision
|
||||
///< mask will be automatically
|
||||
///< adapted to the animation of the
|
||||
///< object.
|
||||
double preScale;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // GDCORE_SPRITEOBJECT_H
|
||||
|
@@ -25,29 +25,271 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
extension.AddInstructionOrExpressionGroupMetadata(_("Variables"))
|
||||
.SetIcon("res/conditions/var24.png");
|
||||
|
||||
extension
|
||||
.AddCondition("NumberVariable",
|
||||
_("Variable value"),
|
||||
_("Compare the number value of a variable."),
|
||||
_("The variable _PARAM0_"),
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions());
|
||||
|
||||
extension
|
||||
.AddCondition("StringVariable",
|
||||
_("Variable value"),
|
||||
_("Compare the text (string) of a variable."),
|
||||
_("The variable _PARAM0_"),
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", ParameterOptions::MakeNewOptions());
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"BooleanVariable",
|
||||
_("Variable value"),
|
||||
_("Compare the boolean value of a variable."),
|
||||
_("The variable _PARAM0_ is _PARAM1_"),
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("Check if the value is"))
|
||||
.SetDefaultValue("true")
|
||||
// This parameter allows to keep the operand expression
|
||||
// when the editor switch between variable instructions.
|
||||
.AddCodeOnlyParameter("trueorfalse", "");
|
||||
|
||||
extension
|
||||
.AddAction("SetNumberVariable",
|
||||
_("Change variable value"),
|
||||
_("Modify the number value of a variable."),
|
||||
_("the variable _PARAM0_"),
|
||||
"",
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
|
||||
extension
|
||||
.AddAction("SetStringVariable",
|
||||
_("Change text variable"),
|
||||
_("Modify the text (string) of a variable."),
|
||||
_("the variable _PARAM0_"),
|
||||
"",
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.UseStandardOperatorParameters("string",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"SetBooleanVariable",
|
||||
_("Change boolean variable"),
|
||||
_("Modify the boolean value of a variable."),
|
||||
_("Change the variable _PARAM0_: _PARAM1_"),
|
||||
"",
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("operator", _("Value"), "boolean")
|
||||
// This parameter allows to keep the operand expression
|
||||
// when the editor switch between variable instructions.
|
||||
.AddCodeOnlyParameter("trueorfalse", "");
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
"VariableChildCount",
|
||||
_("Number of children"),
|
||||
_("Compare the number of children in an array variable."),
|
||||
_("The number of children in the array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddCondition("VariableChildExists2",
|
||||
_("Child existence"),
|
||||
_("Check if the specified child of the structure "
|
||||
"variable exists."),
|
||||
_("Child _PARAM1_ of variable _PARAM0_ exists"),
|
||||
_("Arrays and structures"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("variable", _("Variable"))
|
||||
.AddParameter("string", _("Name of the child"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"RemoveVariableChild",
|
||||
_("Remove a child"),
|
||||
_("Remove a child from a structure variable."),
|
||||
_("Remove child _PARAM1_ from structure variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Structure variable"))
|
||||
.AddParameter("string", _("Child's name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("ClearVariableChildren",
|
||||
_("Clear children"),
|
||||
_("Remove all the children from the structure or array "
|
||||
"variable."),
|
||||
_("Clear children from variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Structure or array variable"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("PushVariable",
|
||||
_("Add existing variable"),
|
||||
_("Adds an existing variable at the end of an array "
|
||||
"variable."),
|
||||
_("Add variable _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.AddParameter("variable", _("Variable with the content to add"))
|
||||
.SetParameterLongDescription(
|
||||
_("The content of the variable will *be copied* and added at the "
|
||||
"end of the array."))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"PushString",
|
||||
_("Add text variable"),
|
||||
_("Adds a text (string) at the end of a array variable."),
|
||||
_("Add the value _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.AddParameter("string", _("Text to add"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("PushNumber",
|
||||
_("Add variable array value"),
|
||||
_("Adds a number at the end of an array variable."),
|
||||
_("Add the value _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.AddParameter("expression", _("Number to add"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("PushBoolean",
|
||||
_("Add boolean variable"),
|
||||
_("Adds a boolean at the end of an array variable."),
|
||||
_("Add the value _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.AddParameter("trueorfalse", _("Boolean to add"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("RemoveVariableAt",
|
||||
_("Remove variable by index"),
|
||||
_("Removes a variable at the specified index of an array "
|
||||
"variable."),
|
||||
_("Remove variable at index _PARAM1_ from array "
|
||||
"variable _PARAM0_"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"))
|
||||
.AddParameter("expression", _("Index to remove"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddStrExpression(
|
||||
"VariableFirstString",
|
||||
_("First text child"),
|
||||
_("Get the value of the first element of an array variable, if "
|
||||
"it is a text (string)."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
"VariableFirstNumber",
|
||||
_("First number child"),
|
||||
_("Get the value of the first element of an array variable, if "
|
||||
"it is a number."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
extension
|
||||
.AddStrExpression(
|
||||
"VariableLastString",
|
||||
_("Last text child"),
|
||||
_("Get the value of the last element of an array variable, if "
|
||||
"it is a text (string)."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
"VariableLastNumber",
|
||||
_("Last number child"),
|
||||
_("Get the value of the last element of an array variable, if "
|
||||
"it is a number."),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("variable", _("Array variable"));
|
||||
|
||||
// Legacy instructions
|
||||
|
||||
extension
|
||||
.AddCondition("VarScene",
|
||||
_("Number variable"),
|
||||
_("Compare the number value of a scene variable."),
|
||||
_("The number of scene variable _PARAM0_"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions());
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddCondition("VarSceneTxt",
|
||||
_("Text variable"),
|
||||
_("Compare the text (string) of a scene variable."),
|
||||
_("The text of scene variable _PARAM0_"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", ParameterOptions::MakeNewOptions());
|
||||
"string", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddCondition(
|
||||
@@ -55,12 +297,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Boolean variable"),
|
||||
_("Compare the boolean value of a scene variable."),
|
||||
_("The boolean value of scene variable _PARAM0_ is _PARAM1_"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("Check if the value is"))
|
||||
.SetDefaultValue("true");
|
||||
.SetDefaultValue("true")
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddCondition("VariableChildExists",
|
||||
@@ -68,11 +311,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Check if the specified child of the scene structure "
|
||||
"variable exists."),
|
||||
_("Child _PARAM1_ of scene variable _PARAM0_ exists"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.AddParameter("string", _("Name of the child"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -81,11 +325,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Check if the specified child of the global structure "
|
||||
"variable exists."),
|
||||
_("Child _PARAM1_ of global variable _PARAM0_ exists"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.AddParameter("string", _("Name of the child"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -93,7 +338,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"Variable defined",
|
||||
"Test if the scene variable exists.",
|
||||
"Scene variable _PARAM0_ is defined",
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
@@ -105,12 +350,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Number variable"),
|
||||
_("Compare the number value of a global variable."),
|
||||
_("the global variable _PARAM0_"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -118,12 +364,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Text variable"),
|
||||
_("Compare the text (string) of a global variable."),
|
||||
_("the text of the global variable _PARAM0_"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"string", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -132,19 +379,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Boolean variable"),
|
||||
_("Compare the boolean value of a global variable."),
|
||||
_("The boolean value of global variable _PARAM0_ is _PARAM1_"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("Check if the value is"))
|
||||
.SetDefaultValue("true");
|
||||
.SetDefaultValue("true")
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddCondition("VarGlobalDef",
|
||||
"Variable defined",
|
||||
"Test if a global variable exists.",
|
||||
"Global variable _PARAM0_ is defined",
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
@@ -157,24 +405,26 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Change number variable"),
|
||||
_("Modify the number value of a scene variable."),
|
||||
_("the scene variable _PARAM0_"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction("ModVarSceneTxt",
|
||||
_("Change text variable"),
|
||||
_("Modify the text (string) of a scene variable."),
|
||||
_("the text of scene variable _PARAM0_"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.UseStandardOperatorParameters("string",
|
||||
ParameterOptions::MakeNewOptions());
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -182,11 +432,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Change boolean variable"),
|
||||
_("Modify the boolean value of a scene variable."),
|
||||
_("Set the boolean value of scene variable _PARAM0_ to _PARAM1_"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("New Value:"));
|
||||
.AddParameter("trueorfalse", _("New Value:"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction("ToggleSceneVariableAsBoolean",
|
||||
@@ -195,22 +446,24 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("If it was true, it will become false, and if it was "
|
||||
"false it will become true."),
|
||||
_("Toggle the boolean value of scene variable _PARAM0_"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"));
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction("ModVarGlobal",
|
||||
_("Change number variable"),
|
||||
_("Modify the number value of a global variable."),
|
||||
_("the global variable _PARAM0_"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.UseStandardOperatorParameters("number",
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -218,12 +471,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Change text variable"),
|
||||
_("Modify the text (string) of a global variable."),
|
||||
_("the text of global variable _PARAM0_"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.UseStandardOperatorParameters("string",
|
||||
ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -232,11 +486,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Change boolean variable"),
|
||||
_("Modify the boolean value of a global variable."),
|
||||
_("Set the boolean value of global variable _PARAM0_ to _PARAM1_"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.AddParameter("trueorfalse", _("New Value:"));
|
||||
.AddParameter("trueorfalse", _("New Value:"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction("ToggleGlobalVariableAsBoolean",
|
||||
@@ -245,10 +500,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("If it was true, it will become false, and if it was "
|
||||
"false it will become true."),
|
||||
_("Toggle the boolean value of global variable _PARAM0_"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"));
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -256,12 +512,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Remove a child"),
|
||||
_("Remove a child from a scene structure variable."),
|
||||
_("Remove child _PARAM1_ from scene structure variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Structure variable"))
|
||||
.AddParameter("string", _("Child's name"))
|
||||
.MarkAsAdvanced();
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -269,12 +526,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Remove a child"),
|
||||
_("Remove a child from a global structure variable."),
|
||||
_("Remove child _PARAM1_ from global structure variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Structure variable"))
|
||||
.AddParameter("string", _("Child's name"))
|
||||
.MarkAsAdvanced();
|
||||
.MarkAsAdvanced()
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction("VariableClearChildren",
|
||||
@@ -282,10 +540,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Remove all the children from the scene structure or array "
|
||||
"variable."),
|
||||
_("Clear children from scene variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Structure or array variable"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -294,10 +553,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Remove all the children from the global structure or array "
|
||||
"variable."),
|
||||
_("Clear children from global variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Structure or array variable"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -306,7 +566,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Adds an existing variable at the end of a scene array "
|
||||
"variable."),
|
||||
_("Add variable _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
@@ -314,6 +574,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
.SetParameterLongDescription(
|
||||
_("The content of the variable will *be copied* and added at the "
|
||||
"end of the array."))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -322,11 +583,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Add text variable"),
|
||||
_("Adds a text (string) at the end of a scene array variable."),
|
||||
_("Add text _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.AddParameter("string", _("Text to add"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -334,11 +596,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Add number variable"),
|
||||
_("Adds a number at the end of a scene array variable."),
|
||||
_("Add number _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.AddParameter("expression", _("Number to add"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -346,11 +609,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Add boolean variable"),
|
||||
_("Adds a boolean at the end of a scene array variable."),
|
||||
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.AddParameter("trueorfalse", _("Boolean to add"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -360,11 +624,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"variable."),
|
||||
_("Remove variable at index _PARAM1_ from scene array "
|
||||
"variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.AddParameter("expression", _("Index to remove"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -373,12 +638,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Number of children"),
|
||||
_("Compare the number of children in a scene array variable."),
|
||||
_("The number of children in the array variable _PARAM0_"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -387,9 +653,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("First text child"),
|
||||
_("Get the value of the first element of a scene array variable, if "
|
||||
"it is a text (string)."),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"));
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -397,9 +664,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("First number child"),
|
||||
_("Get the value of the first element of a scene array variable, if "
|
||||
"it is a number."),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"));
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddStrExpression(
|
||||
@@ -407,9 +675,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Last text child"),
|
||||
_("Get the value of the last element of a scene array variable, if "
|
||||
"it is a text (string)."),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"));
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -417,9 +686,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Last number child"),
|
||||
_("Get the value of the last element of a scene array variable, if "
|
||||
"it is a number."),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("External variables/Scene variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array variable"));
|
||||
.AddParameter("scenevar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
@@ -427,7 +697,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Add existing variable"),
|
||||
_("Adds an existing variable at the end of a global array variable."),
|
||||
_("Add variable _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
@@ -435,6 +705,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
.SetParameterLongDescription(
|
||||
_("The content of the variable will *be copied* and added at the "
|
||||
"end of the array."))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -444,11 +715,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"array variable."),
|
||||
_("Remove variable at index _PARAM1_ from global array "
|
||||
"variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.AddParameter("expression", _("Index to remove"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -457,11 +729,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Add text variable"),
|
||||
_("Adds a text (string) at the end of a global array variable."),
|
||||
_("Add text _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.AddParameter("string", _("Text to add"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -469,11 +742,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Add number variable"),
|
||||
_("Adds a number at the end of a global array variable."),
|
||||
_("Add number _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.AddParameter("expression", _("Number to add"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -481,11 +755,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Add boolean variable"),
|
||||
_("Adds a boolean at the end of a global array variable."),
|
||||
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.AddParameter("trueorfalse", _("Boolean to add"))
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -494,12 +769,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Number of children"),
|
||||
_("Compare the number of children in a global array variable."),
|
||||
_("The number of children of the array variable _PARAM0_"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.UseStandardRelationalOperatorParameters(
|
||||
"number", ParameterOptions::MakeNewOptions())
|
||||
.SetRelevantForFunctionEventsOnly()
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
@@ -507,18 +783,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("First text child"),
|
||||
_("Value of the first element of a global array "
|
||||
"variable, if it is a text (string) variable."),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"));
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddExpression("GlobalVariableFirstNumber",
|
||||
_("First number child"),
|
||||
_("Value of the first element of a global array "
|
||||
"variable, if it is a number variable"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"));
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddStrExpression(
|
||||
@@ -526,9 +804,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Last text child"),
|
||||
_("Value of the last element of a global array variable, if "
|
||||
"it is a text (string) variable."),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"));
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
@@ -536,59 +815,65 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
_("Last number child"),
|
||||
_("Value of the last element of a global array variable, if "
|
||||
"it is a number variable"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array variable"));
|
||||
.AddParameter("globalvar", _("Array variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddExpression("GlobalVariableChildCount",
|
||||
_("Number of children"),
|
||||
_("Number of children in a global array or "
|
||||
"structure variable"),
|
||||
_("Global variables/Arrays and structures"),
|
||||
_("External variables/Global variables/Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Array or structure variable"));
|
||||
.AddParameter("globalvar", _("Array or structure variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddExpression("VariableChildCount",
|
||||
_("Number of children"),
|
||||
_("Number of children in a scene array or "
|
||||
"structure variable"),
|
||||
_("Scene variables/Arrays and structures"),
|
||||
_("Arrays and structures"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Array or structure variable"));
|
||||
.AddParameter("variable", _("Array or structure variable"), "AllowUndeclaredVariable");
|
||||
|
||||
extension
|
||||
.AddExpression("Variable",
|
||||
_("Number variable"),
|
||||
_("Number value of a scene variable"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"));
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddStrExpression("VariableString",
|
||||
_("Text variable"),
|
||||
_("Text of a scene variable"),
|
||||
_("Scene variables"),
|
||||
_("External variables/Scene variables"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("scenevar", _("Variable"));
|
||||
.AddParameter("scenevar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddExpression("GlobalVariable",
|
||||
_("Number variable"),
|
||||
_("Number value of a global variable"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Name of the global variable"));
|
||||
.AddParameter("globalvar", _("Name of the global variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
|
||||
extension
|
||||
.AddStrExpression("GlobalVariableString",
|
||||
_("Text variable"),
|
||||
_("Text of a global variable"),
|
||||
_("Global variables"),
|
||||
_("External variables/Global variables"),
|
||||
"res/actions/var.png")
|
||||
.AddParameter("globalvar", _("Variable"));
|
||||
.AddParameter("globalvar", _("Variable"))
|
||||
.SetRelevantForFunctionEventsOnly();
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -114,6 +114,8 @@ public:
|
||||
|
||||
/**
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
virtual AbstractFunctionMetadata &
|
||||
SetIncludeFile(const gd::String &includeFile) = 0;
|
||||
|
@@ -424,7 +424,7 @@ std::map<gd::String, gd::PropertyDescriptor> BehaviorMetadata::GetProperties() c
|
||||
return instance->GetProperties();
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* BehaviorMetadata::GetSharedDataInstance() const {
|
||||
gd::BehaviorsSharedData* BehaviorMetadata::GetSharedDataInstance() const {
|
||||
return sharedDatasInstance.get();
|
||||
}
|
||||
|
||||
@@ -440,12 +440,18 @@ std::map<gd::String, gd::PropertyDescriptor> BehaviorMetadata::GetSharedProperti
|
||||
|
||||
const std::vector<gd::String>& BehaviorMetadata::GetRequiredBehaviorTypes() const {
|
||||
requiredBehaviors.clear();
|
||||
for (auto& property : Get().GetProperties()) {
|
||||
if (!instance) {
|
||||
return requiredBehaviors;
|
||||
}
|
||||
for (auto& property : instance->GetProperties()) {
|
||||
const String& propertyName = property.first;
|
||||
const gd::PropertyDescriptor& propertyDescriptor = property.second;
|
||||
|
||||
if (propertyDescriptor.GetType() == "Behavior") {
|
||||
requiredBehaviors.push_back(propertyDescriptor.GetExtraInfo()[0]);
|
||||
const auto& extraInfos = propertyDescriptor.GetExtraInfo();
|
||||
if (extraInfos.size() > 0) {
|
||||
requiredBehaviors.push_back(extraInfos[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return requiredBehaviors;
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Project/QuickCustomization.h"
|
||||
namespace gd {
|
||||
class Behavior;
|
||||
class BehaviorsSharedData;
|
||||
@@ -41,10 +42,10 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
const gd::String& className_,
|
||||
std::shared_ptr<gd::Behavior> instance,
|
||||
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Construct a behavior metadata, without "blueprint" behavior.
|
||||
*
|
||||
*
|
||||
* \note This is used by events based behaviors.
|
||||
*/
|
||||
BehaviorMetadata(
|
||||
@@ -205,6 +206,8 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
* \note The requirement may vary depending on the platform: Most of the time,
|
||||
* the include file contains the declaration of the behavior.
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
BehaviorMetadata& SetIncludeFile(const gd::String& includeFile) override;
|
||||
|
||||
@@ -295,9 +298,27 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
return *this;
|
||||
}
|
||||
|
||||
QuickCustomization::Visibility GetQuickCustomizationVisibility() const {
|
||||
return quickCustomizationVisibility;
|
||||
}
|
||||
|
||||
BehaviorMetadata &SetQuickCustomizationVisibility(QuickCustomization::Visibility visibility) {
|
||||
quickCustomizationVisibility = visibility;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BehaviorMetadata &SetOpenFullEditorLabel(const gd::String& label) {
|
||||
openFullEditorLabel = label;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const gd::String& GetOpenFullEditorLabel() const {
|
||||
return openFullEditorLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the associated gd::Behavior, handling behavior contents.
|
||||
*
|
||||
*
|
||||
* \note Returns a dumb Behavior for events based behaviors as CustomBehavior
|
||||
* are using EventBasedBehavior.
|
||||
*/
|
||||
@@ -315,7 +336,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
/**
|
||||
* \brief Return the associated gd::BehaviorsSharedData, handling behavior
|
||||
* shared data, if any (nullptr if none).
|
||||
*
|
||||
*
|
||||
* \note Returns nullptr for events based behaviors as they don't declare
|
||||
* shared data yet.
|
||||
*/
|
||||
@@ -372,6 +393,8 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
|
||||
mutable std::vector<gd::String> requiredBehaviors;
|
||||
bool isPrivate = false;
|
||||
bool isHidden = false;
|
||||
gd::String openFullEditorLabel;
|
||||
QuickCustomization::Visibility quickCustomizationVisibility = QuickCustomization::Visibility::Default;
|
||||
|
||||
// TODO: Nitpicking: convert these to std::unique_ptr to clarify ownership.
|
||||
std::shared_ptr<gd::Behavior> instance;
|
||||
|
@@ -65,6 +65,8 @@ class GD_CORE_API EffectMetadata {
|
||||
|
||||
/**
|
||||
* \brief Clear any existing include file and add the specified include file.
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
EffectMetadata& SetIncludeFile(const gd::String& includeFile);
|
||||
|
||||
@@ -183,10 +185,10 @@ class GD_CORE_API EffectMetadata {
|
||||
gd::String fullname;
|
||||
gd::String description;
|
||||
std::vector<gd::String> includeFiles;
|
||||
bool isMarkedAsNotWorkingForObjects;
|
||||
bool isMarkedAsOnlyWorkingFor2D;
|
||||
bool isMarkedAsOnlyWorkingFor3D;
|
||||
bool isMarkedAsUnique;
|
||||
bool isMarkedAsNotWorkingForObjects = false;
|
||||
bool isMarkedAsOnlyWorkingFor2D = false;
|
||||
bool isMarkedAsOnlyWorkingFor3D = false;
|
||||
bool isMarkedAsUnique = false;
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
};
|
||||
|
||||
|
@@ -19,7 +19,8 @@ EventMetadata::EventMetadata(const gd::String &name_,
|
||||
: fullname(fullname_),
|
||||
description(description_),
|
||||
group(group_),
|
||||
instance(instance_) {
|
||||
instance(instance_),
|
||||
hasCustomCodeGenerator(false) {
|
||||
ClearCodeGenerationAndPreprocessing();
|
||||
if (instance) instance->SetType(name_);
|
||||
}
|
||||
|
@@ -83,7 +83,7 @@ class GD_CORE_API EventMetadata {
|
||||
gd::String group;
|
||||
|
||||
std::shared_ptr<gd::BaseEvent> instance;
|
||||
bool hasCustomCodeGenerator;
|
||||
bool hasCustomCodeGenerator = false;
|
||||
std::function<gd::String(gd::BaseEvent& event,
|
||||
gd::EventsCodeGenerator& codeGenerator,
|
||||
gd::EventsCodeGenerationContext& context)>
|
||||
|
@@ -38,12 +38,12 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
|
||||
const gd::String& description,
|
||||
const gd::String& supplementaryInformation,
|
||||
bool parameterIsOptional) {
|
||||
gd::ParameterMetadata info;
|
||||
info.SetType(type);
|
||||
info.description = description;
|
||||
info.codeOnly = false;
|
||||
info.SetOptional(parameterIsOptional);
|
||||
info.SetExtraInfo(
|
||||
parameters.AddNewParameter("")
|
||||
.SetType(type)
|
||||
.SetDescription(description)
|
||||
.SetCodeOnly(false)
|
||||
.SetOptional(parameterIsOptional)
|
||||
.SetExtraInfo(
|
||||
// For objects/behavior, the supplementary information
|
||||
// parameter is an object/behavior type...
|
||||
((gd::ParameterMetadata::IsObject(type) ||
|
||||
@@ -59,22 +59,16 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
|
||||
// TODO: Assert against supplementaryInformation === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
|
||||
parameters.push_back(info);
|
||||
return *this;
|
||||
}
|
||||
|
||||
gd::ExpressionMetadata& ExpressionMetadata::AddCodeOnlyParameter(
|
||||
const gd::String& type, const gd::String& supplementaryInformation) {
|
||||
gd::ParameterMetadata info;
|
||||
info.SetType(type);
|
||||
info.codeOnly = true;
|
||||
info.SetExtraInfo(supplementaryInformation);
|
||||
|
||||
parameters.push_back(info);
|
||||
gd::ExpressionMetadata &ExpressionMetadata::AddCodeOnlyParameter(
|
||||
const gd::String &type, const gd::String &supplementaryInformation) {
|
||||
parameters.AddNewParameter("").SetType(type).SetCodeOnly().SetExtraInfo(
|
||||
supplementaryInformation);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
gd::ExpressionMetadata& ExpressionMetadata::SetRequiresBaseObjectCapability(
|
||||
const gd::String& capability) {
|
||||
requiredBaseObjectCapability = capability;
|
||||
|
@@ -193,8 +193,9 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
|
||||
* \see AddParameter
|
||||
*/
|
||||
ExpressionMetadata &SetDefaultValue(const gd::String &defaultValue) override {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetDefaultValue(defaultValue);
|
||||
if (parameters.GetParametersCount() > 0) {
|
||||
parameters.GetInternalVector().back()->SetDefaultValue(defaultValue);
|
||||
}
|
||||
return *this;
|
||||
};
|
||||
|
||||
@@ -206,8 +207,9 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*/
|
||||
ExpressionMetadata &
|
||||
SetParameterLongDescription(const gd::String &longDescription) override {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetLongDescription(longDescription);
|
||||
if (parameters.GetParametersCount() > 0) {
|
||||
parameters.GetInternalVector().back()->SetLongDescription(longDescription);
|
||||
}
|
||||
return *this;
|
||||
};
|
||||
|
||||
@@ -220,7 +222,9 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*/
|
||||
ExpressionMetadata &SetParameterExtraInfo(
|
||||
const gd::String &extraInfo) override {
|
||||
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
|
||||
if (parameters.GetParametersCount() > 0) {
|
||||
parameters.GetInternalVector().back()->SetExtraInfo(extraInfo);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -248,19 +252,16 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
|
||||
const gd::String& GetGroup() const { return group; }
|
||||
const gd::String& GetSmallIconFilename() const { return smallIconFilename; }
|
||||
const gd::ParameterMetadata& GetParameter(std::size_t id) const {
|
||||
return parameters[id];
|
||||
return parameters.GetParameter(id);
|
||||
};
|
||||
gd::ParameterMetadata& GetParameter(std::size_t id) {
|
||||
return parameters[id];
|
||||
return parameters.GetParameter(id);
|
||||
};
|
||||
std::size_t GetParametersCount() const { return parameters.size(); };
|
||||
const std::vector<gd::ParameterMetadata>& GetParameters() const {
|
||||
std::size_t GetParametersCount() const { return parameters.GetParametersCount(); };
|
||||
const gd::ParameterMetadataContainer& GetParameters() const {
|
||||
return parameters;
|
||||
};
|
||||
|
||||
std::vector<gd::ParameterMetadata> parameters;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Set the function name which will be used when generating the code.
|
||||
* \param functionName the name of the function to call
|
||||
@@ -288,6 +289,8 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
|
||||
|
||||
/**
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
ExpressionMetadata& SetIncludeFile(
|
||||
const gd::String& includeFile) override {
|
||||
@@ -366,6 +369,8 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
|
||||
bool isPrivate;
|
||||
gd::String requiredBaseObjectCapability;
|
||||
gd::String relevantContext;
|
||||
|
||||
gd::ParameterMetadataContainer parameters;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/ParameterMetadataContainer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
@@ -77,7 +78,7 @@ InstructionMetadata& InstructionMetadata::AddParameter(
|
||||
// TODO: Assert against supplementaryInformation === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
|
||||
parameters.push_back(info);
|
||||
parameters.AddParameter(info);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -88,7 +89,7 @@ InstructionMetadata& InstructionMetadata::AddCodeOnlyParameter(
|
||||
info.codeOnly = true;
|
||||
info.SetExtraInfo(supplementaryInformation);
|
||||
|
||||
parameters.push_back(info);
|
||||
parameters.AddParameter(info);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
|
||||
AddParameter(
|
||||
"yesorno",
|
||||
options.description.empty() ? _("New value") : options.description);
|
||||
size_t valueParamIndex = parameters.size() - 1;
|
||||
size_t valueParamIndex = parameters.GetParametersCount() - 1;
|
||||
|
||||
if (isObjectInstruction || isBehaviorInstruction) {
|
||||
gd::String templateSentence = _("Set _PARAM0_ as <subject>: <value>");
|
||||
@@ -127,8 +128,8 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
|
||||
options.description.empty() ? _("Value") : options.description,
|
||||
options.typeExtraInfo);
|
||||
|
||||
size_t operatorParamIndex = parameters.size() - 2;
|
||||
size_t valueParamIndex = parameters.size() - 1;
|
||||
size_t operatorParamIndex = parameters.GetParametersCount() - 2;
|
||||
size_t valueParamIndex = parameters.GetParametersCount() - 1;
|
||||
|
||||
if (isObjectInstruction || isBehaviorInstruction) {
|
||||
gd::String templateSentence = _("Change <subject> of _PARAM0_: <operator> <value>");
|
||||
@@ -181,8 +182,8 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
|
||||
AddParameter(type,
|
||||
options.description.empty() ? _("Value to compare") : options.description,
|
||||
options.typeExtraInfo);
|
||||
size_t operatorParamIndex = parameters.size() - 2;
|
||||
size_t valueParamIndex = parameters.size() - 1;
|
||||
size_t operatorParamIndex = parameters.GetParametersCount() - 2;
|
||||
size_t valueParamIndex = parameters.GetParametersCount() - 1;
|
||||
|
||||
if (isObjectInstruction || isBehaviorInstruction) {
|
||||
gd::String templateSentence = _("<subject> of _PARAM0_ <operator> <value>");
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Project/ParameterMetadataContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "ParameterMetadata.h"
|
||||
#include "ParameterOptions.h"
|
||||
@@ -61,12 +62,12 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
const gd::String &GetDescription() const { return description; }
|
||||
const gd::String &GetSentence() const { return sentence; }
|
||||
const gd::String &GetGroup() const { return group; }
|
||||
ParameterMetadata &GetParameter(size_t i) { return parameters[i]; }
|
||||
ParameterMetadata &GetParameter(size_t i) { return parameters.GetParameter(i); }
|
||||
const ParameterMetadata &GetParameter(size_t i) const {
|
||||
return parameters[i];
|
||||
return parameters.GetParameter(i);
|
||||
}
|
||||
size_t GetParametersCount() const { return parameters.size(); }
|
||||
const std::vector<ParameterMetadata> &GetParameters() const {
|
||||
size_t GetParametersCount() const { return parameters.GetParametersCount(); }
|
||||
const ParameterMetadataContainer &GetParameters() const {
|
||||
return parameters;
|
||||
}
|
||||
const gd::String &GetIconFilename() const { return iconFilename; }
|
||||
@@ -256,7 +257,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) override {
|
||||
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
|
||||
if (parameters.GetParametersCount() > 0) {
|
||||
parameters.GetInternalVector().back()->SetDefaultValue(defaultValue_);
|
||||
}
|
||||
return *this;
|
||||
};
|
||||
|
||||
@@ -268,8 +271,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*/
|
||||
InstructionMetadata &SetParameterLongDescription(
|
||||
const gd::String &longDescription) override {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetLongDescription(longDescription);
|
||||
if (parameters.GetParametersCount() > 0) {
|
||||
parameters.GetInternalVector().back()->SetLongDescription(longDescription);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -281,7 +285,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) override {
|
||||
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
|
||||
if (parameters.GetParametersCount() > 0) {
|
||||
parameters.GetInternalVector().back()->SetExtraInfo(extraInfo);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -456,6 +462,15 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the type manipulated in a standard way by the instruction.
|
||||
*
|
||||
* \param type "number" or "string"
|
||||
*/
|
||||
const gd::String &GetManipulatedType() const {
|
||||
return codeExtraInformation.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* If InstructionMetadata::ExtraInformation::SetManipulatedType was called
|
||||
* with "number" or "string", this function will tell the code generator the
|
||||
@@ -494,6 +509,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
|
||||
/**
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) override {
|
||||
codeExtraInformation.includeFiles.clear();
|
||||
@@ -549,7 +566,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
|
||||
*/
|
||||
InstructionMetadata &GetCodeExtraInformation() { return *this; }
|
||||
|
||||
std::vector<ParameterMetadata> parameters;
|
||||
ParameterMetadataContainer parameters;
|
||||
|
||||
private:
|
||||
gd::String fullname;
|
||||
|
@@ -142,6 +142,8 @@ public:
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
* \note The requirement may vary depending on the platform: Most of the time,
|
||||
* the include file contains the declaration of the behavior.
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
virtual InstructionOrExpressionContainerMetadata &
|
||||
SetIncludeFile(const gd::String &includeFile) = 0;
|
||||
|
@@ -454,11 +454,12 @@ const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
|
||||
// TODO use a badMetadata instead of a nullptr?
|
||||
const gd::ParameterMetadata* parameterMetadata = nullptr;
|
||||
while (metadataParameterIndex <
|
||||
metadata.parameters.size()) {
|
||||
if (!metadata.parameters[metadataParameterIndex]
|
||||
metadata.GetParameters().GetParametersCount()) {
|
||||
if (!metadata.GetParameters().GetParameter(metadataParameterIndex)
|
||||
.IsCodeOnly()) {
|
||||
if (visibleParameterIndex == parameterIndex) {
|
||||
parameterMetadata = &metadata.parameters[metadataParameterIndex];
|
||||
parameterMetadata =
|
||||
&metadata.GetParameters().GetParameter(metadataParameterIndex);
|
||||
}
|
||||
visibleParameterIndex++;
|
||||
}
|
||||
|
@@ -288,8 +288,8 @@ class GD_CORE_API MetadataProvider {
|
||||
static EffectMetadata badEffectMetadata;
|
||||
static gd::InstructionMetadata badInstructionMetadata;
|
||||
static gd::ExpressionMetadata badExpressionMetadata;
|
||||
int useless; // Useless member to avoid emscripten "must have a positive
|
||||
// integer typeid pointer" runtime error.
|
||||
int useless = 0; // Useless member to avoid emscripten "must have a positive
|
||||
// integer typeid pointer" runtime error.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -150,6 +150,10 @@ class GD_CORE_API MultipleInstructionMetadata : public AbstractFunctionMetadata
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
MultipleInstructionMetadata &SetIncludeFile(const gd::String &includeFile) override {
|
||||
if (expression)
|
||||
expression->SetIncludeFile(includeFile);
|
||||
|
@@ -264,6 +264,8 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
* \brief Erase any existing include file and add the specified include.
|
||||
* \note The requirement may vary depending on the platform: Most of the time,
|
||||
* the include file contains the declaration of the object.
|
||||
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
|
||||
* error prone.
|
||||
*/
|
||||
ObjectMetadata& SetIncludeFile(const gd::String& includeFile) override;
|
||||
|
||||
@@ -321,6 +323,15 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
*/
|
||||
bool IsRenderedIn3D() const { return isRenderedIn3D; }
|
||||
|
||||
ObjectMetadata &SetOpenFullEditorLabel(const gd::String& label) {
|
||||
openFullEditorLabel = label;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const gd::String& GetOpenFullEditorLabel() const {
|
||||
return openFullEditorLabel;
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::InstructionMetadata> conditionsInfos;
|
||||
std::map<gd::String, gd::InstructionMetadata> actionsInfos;
|
||||
std::map<gd::String, gd::ExpressionMetadata> expressionsInfos;
|
||||
@@ -342,6 +353,7 @@ class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetada
|
||||
std::set<gd::String> defaultBehaviorTypes;
|
||||
bool hidden = false;
|
||||
bool isRenderedIn3D = false;
|
||||
gd::String openFullEditorLabel;
|
||||
|
||||
std::shared_ptr<gd::ObjectConfiguration>
|
||||
blueprintObject; ///< The "blueprint" object to be copied when a new
|
||||
|
@@ -4,8 +4,8 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef PARAMETER_METADATA_H
|
||||
#define PARAMETER_METADATA_H
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
@@ -29,6 +29,12 @@ class GD_CORE_API ParameterMetadata {
|
||||
ParameterMetadata();
|
||||
virtual ~ParameterMetadata(){};
|
||||
|
||||
/**
|
||||
* \brief Return a pointer to a new ParameterMetadata constructed from
|
||||
* this one.
|
||||
*/
|
||||
ParameterMetadata* Clone() const { return new ParameterMetadata(*this); };
|
||||
|
||||
/**
|
||||
* \brief Return the metadata of the parameter type.
|
||||
*/
|
||||
@@ -248,5 +254,3 @@ class GD_CORE_API ParameterMetadata {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // PARAMETER_METADATA_H
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/ObjectsContainersList.h"
|
||||
#include "GDCore/Project/ParameterMetadataContainer.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "InstructionMetadata.h"
|
||||
@@ -20,13 +21,13 @@ const ParameterMetadata ParameterMetadataTools::badParameterMetadata;
|
||||
|
||||
void ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
const gd::Project& project,
|
||||
const std::vector<gd::ParameterMetadata>& parameters,
|
||||
const ParameterMetadataContainer& parameters,
|
||||
gd::ObjectsContainer& outputObjectsContainer) {
|
||||
outputObjectsContainer.GetObjects().clear();
|
||||
|
||||
gd::String lastObjectName;
|
||||
for (std::size_t i = 0; i < parameters.size(); ++i) {
|
||||
const auto& parameter = parameters[i];
|
||||
for (std::size_t i = 0; i < parameters.GetParametersCount(); ++i) {
|
||||
const auto& parameter = parameters.GetParameter(i);
|
||||
if (parameter.GetName().empty()) continue;
|
||||
|
||||
if (gd::ParameterMetadata::IsObject(parameter.GetType())) {
|
||||
@@ -61,31 +62,34 @@ void ParameterMetadataTools::ParametersToObjectsContainer(
|
||||
}
|
||||
|
||||
void ParameterMetadataTools::ForEachParameterMatchingSearch(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>&
|
||||
const std::vector<const ParameterMetadataContainer*>&
|
||||
parametersVectorsList,
|
||||
const gd::String& search,
|
||||
std::function<void(const gd::ParameterMetadata&)> cb) {
|
||||
for (auto it = parametersVectorsList.rbegin();
|
||||
it != parametersVectorsList.rend();
|
||||
++it) {
|
||||
const std::vector<gd::ParameterMetadata>* parametersVector = *it;
|
||||
const ParameterMetadataContainer* parametersVector = *it;
|
||||
|
||||
for (const auto& parameterMetadata: *parametersVector) {
|
||||
if (parameterMetadata.GetName().FindCaseInsensitive(search) != gd::String::npos) cb(parameterMetadata);
|
||||
for (const auto ¶meterMetadata :
|
||||
parametersVector->GetInternalVector()) {
|
||||
if (parameterMetadata->GetName().FindCaseInsensitive(search) !=
|
||||
gd::String::npos)
|
||||
cb(*parameterMetadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ParameterMetadataTools::Has(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const std::vector<const ParameterMetadataContainer*>& parametersVectorsList,
|
||||
const gd::String& parameterName) {
|
||||
for (auto it = parametersVectorsList.rbegin();
|
||||
it != parametersVectorsList.rend();
|
||||
++it) {
|
||||
const std::vector<gd::ParameterMetadata>* parametersVector = *it;
|
||||
const ParameterMetadataContainer* parametersVector = *it;
|
||||
|
||||
for (const auto& parameterMetadata: *parametersVector) {
|
||||
if (parameterMetadata.GetName() == parameterName) return true;
|
||||
for (const auto& parameterMetadata: parametersVector->GetInternalVector()) {
|
||||
if (parameterMetadata->GetName() == parameterName) return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,16 +97,18 @@ bool ParameterMetadataTools::Has(
|
||||
}
|
||||
|
||||
const gd::ParameterMetadata& ParameterMetadataTools::Get(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>&
|
||||
const std::vector<const ParameterMetadataContainer*>&
|
||||
parametersVectorsList,
|
||||
const gd::String& parameterName) {
|
||||
for (auto it = parametersVectorsList.rbegin();
|
||||
it != parametersVectorsList.rend();
|
||||
++it) {
|
||||
const std::vector<gd::ParameterMetadata>* parametersVector = *it;
|
||||
const ParameterMetadataContainer* parametersVector = *it;
|
||||
|
||||
for (const auto& parameterMetadata: *parametersVector) {
|
||||
if (parameterMetadata.GetName() == parameterName) return parameterMetadata;
|
||||
for (const auto ¶meterMetadata :
|
||||
parametersVector->GetInternalVector()) {
|
||||
if (parameterMetadata->GetName() == parameterName)
|
||||
return *parameterMetadata;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +117,7 @@ const gd::ParameterMetadata& ParameterMetadataTools::Get(
|
||||
|
||||
void ParameterMetadataTools::IterateOverParameters(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
const ParameterMetadataContainer& parametersMetadata,
|
||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterValue,
|
||||
const gd::String& lastObjectName)> fn) {
|
||||
@@ -128,15 +134,17 @@ void ParameterMetadataTools::IterateOverParameters(
|
||||
|
||||
void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
const ParameterMetadataContainer& parametersMetadata,
|
||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName)> fn) {
|
||||
gd::String lastObjectName = "";
|
||||
for (std::size_t pNb = 0; pNb < parametersMetadata.size(); ++pNb) {
|
||||
const gd::ParameterMetadata& parameterMetadata = parametersMetadata[pNb];
|
||||
const gd::Expression& parameterValue =
|
||||
for (std::size_t pNb = 0; pNb < parametersMetadata.GetParametersCount();
|
||||
++pNb) {
|
||||
const gd::ParameterMetadata ¶meterMetadata =
|
||||
parametersMetadata.GetParameter(pNb);
|
||||
const gd::Expression ¶meterValue =
|
||||
pNb < parameters.size() ? parameters[pNb].GetPlainString() : "";
|
||||
const gd::Expression& parameterValueOrDefault =
|
||||
parameterValue.GetPlainString().empty() && parameterMetadata.IsOptional()
|
||||
@@ -179,10 +187,10 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
|
||||
size_t parameterIndex = 0;
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0);
|
||||
metadataIndex < metadata.parameters.size() &&
|
||||
metadataIndex < metadata.GetParameters().GetParametersCount() &&
|
||||
parameterIndex < node.parameters.size();
|
||||
++metadataIndex) {
|
||||
auto ¶meterMetadata = metadata.parameters[metadataIndex];
|
||||
auto ¶meterMetadata = metadata.GetParameters().GetParameter(metadataIndex);
|
||||
if (parameterMetadata.IsCodeOnly()) {
|
||||
continue;
|
||||
}
|
||||
@@ -204,16 +212,17 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
}
|
||||
|
||||
size_t ParameterMetadataTools::GetObjectParameterIndexFor(
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
const ParameterMetadataContainer& parametersMetadata,
|
||||
size_t parameterIndex) {
|
||||
// By convention, parameters that require
|
||||
// an object (mainly, "objectvar" and "behavior") should be placed after
|
||||
// the object in the list of parameters (if possible, just after).
|
||||
// Search "lastObjectName" in the codebase for other place where this
|
||||
// convention is enforced.
|
||||
for (std::size_t pNb = parameterIndex; pNb < parametersMetadata.size();
|
||||
pNb--) {
|
||||
if (gd::ParameterMetadata::IsObject(parametersMetadata[pNb].GetType())) {
|
||||
for (std::size_t pNb = parameterIndex;
|
||||
pNb < parametersMetadata.GetParametersCount(); pNb--) {
|
||||
if (gd::ParameterMetadata::IsObject(
|
||||
parametersMetadata.GetParameter(pNb).GetType())) {
|
||||
return pNb;
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ class ObjectsContainer;
|
||||
class ObjectsContainersList;
|
||||
class ParameterMetadata;
|
||||
class Expression;
|
||||
class ParameterMetadataContainer;
|
||||
struct FunctionCallNode;
|
||||
struct ExpressionNode;
|
||||
} // namespace gd
|
||||
@@ -24,20 +25,20 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
public:
|
||||
static void ParametersToObjectsContainer(
|
||||
const gd::Project& project,
|
||||
const std::vector<gd::ParameterMetadata>& parameters,
|
||||
const ParameterMetadataContainer& parameters,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
|
||||
static void ForEachParameterMatchingSearch(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const std::vector<const ParameterMetadataContainer*>& parametersVectorsList,
|
||||
const gd::String& search,
|
||||
std::function<void(const gd::ParameterMetadata&)> cb);
|
||||
|
||||
static bool Has(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const std::vector<const ParameterMetadataContainer*>& parametersVectorsList,
|
||||
const gd::String& parameterName);
|
||||
|
||||
static const gd::ParameterMetadata& Get(
|
||||
const std::vector<const std::vector<gd::ParameterMetadata>*>& parametersVectorsList,
|
||||
const std::vector<const ParameterMetadataContainer*>& parametersVectorsList,
|
||||
const gd::String& parameterName);
|
||||
|
||||
/**
|
||||
@@ -47,7 +48,7 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
*/
|
||||
static void IterateOverParameters(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
const ParameterMetadataContainer& parametersMetadata,
|
||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterValue,
|
||||
const gd::String& lastObjectName)> fn);
|
||||
@@ -59,7 +60,7 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
*/
|
||||
static void IterateOverParametersWithIndex(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
const ParameterMetadataContainer& parametersMetadata,
|
||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterValue,
|
||||
size_t parameterIndex,
|
||||
@@ -84,7 +85,7 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
* it's linked to.
|
||||
*/
|
||||
static size_t GetObjectParameterIndexFor(
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
const ParameterMetadataContainer& parametersMetadata,
|
||||
size_t parameterIndex);
|
||||
|
||||
private:
|
||||
|
@@ -53,27 +53,32 @@ const gd::String &ValueTypeMetadata::GetExpressionPrimitiveValueType(
|
||||
|
||||
const gd::String &
|
||||
ValueTypeMetadata::GetPrimitiveValueType(const gd::String ¶meterType) {
|
||||
if (parameterType == "variable" ||
|
||||
gd::ValueTypeMetadata::IsTypeExpression("variable", parameterType)) {
|
||||
return ValueTypeMetadata::variableType;
|
||||
if (parameterType == "number" ||
|
||||
gd::ValueTypeMetadata::IsTypeValue("number", parameterType)) {
|
||||
return ValueTypeMetadata::numberType;
|
||||
}
|
||||
if (parameterType == "boolean" || parameterType == "yesorno" ||
|
||||
parameterType == "trueorfalse") {
|
||||
return ValueTypeMetadata::booleanType;
|
||||
}
|
||||
// These 2 types are not strings from the code generator point of view,
|
||||
// but it is for event-based extensions.
|
||||
if (parameterType == "key" || parameterType == "mouse") {
|
||||
if (parameterType == "string" ||
|
||||
gd::ValueTypeMetadata::IsTypeValue("string", parameterType)) {
|
||||
return ValueTypeMetadata::stringType;
|
||||
}
|
||||
return GetExpressionPrimitiveValueType(parameterType);
|
||||
if (parameterType == "variable" ||
|
||||
gd::ValueTypeMetadata::IsTypeValue("variable", parameterType)) {
|
||||
return ValueTypeMetadata::variableType;
|
||||
}
|
||||
if (parameterType == "boolean" ||
|
||||
gd::ValueTypeMetadata::IsTypeValue("boolean", parameterType)) {
|
||||
return ValueTypeMetadata::booleanType;
|
||||
}
|
||||
return parameterType;
|
||||
}
|
||||
|
||||
const gd::String ValueTypeMetadata::numberValueType = "number";
|
||||
const gd::String ValueTypeMetadata::booleanValueType = "boolean";
|
||||
const gd::String ValueTypeMetadata::stringValueType = "string";
|
||||
const gd::String ValueTypeMetadata::colorValueType = "color";
|
||||
const gd::String ValueTypeMetadata::choiceValueType = "stringWithSelector";
|
||||
const gd::String ValueTypeMetadata::stringValueType = "string";
|
||||
const gd::String ValueTypeMetadata::behaviorValueType = "behavior";
|
||||
const gd::String ValueTypeMetadata::leaderboardIdValueType = "leaderboardId";
|
||||
|
||||
const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
const gd::String &propertyType) {
|
||||
@@ -85,6 +90,10 @@ const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
return colorValueType;
|
||||
} else if (propertyType == "Choice") {
|
||||
return choiceValueType;
|
||||
} else if (propertyType == "Behavior") {
|
||||
return behaviorValueType;
|
||||
} else if (propertyType == "LeaderboardId") {
|
||||
return leaderboardIdValueType;
|
||||
}
|
||||
// For "String" or default
|
||||
return stringValueType;
|
||||
|
@@ -111,21 +111,21 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
* given type.
|
||||
*/
|
||||
bool IsNumber() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("number", name);
|
||||
return gd::ValueTypeMetadata::IsTypeValue("number", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a string.
|
||||
*/
|
||||
bool IsString() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("string", name);
|
||||
return gd::ValueTypeMetadata::IsTypeValue("string", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a boolean.
|
||||
*/
|
||||
bool IsBoolean() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("boolean", name);
|
||||
return gd::ValueTypeMetadata::IsTypeValue("boolean", name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +135,7 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
*/
|
||||
bool IsVariable() const {
|
||||
return gd::ValueTypeMetadata::IsTypeExpression("variable", name);
|
||||
return gd::ValueTypeMetadata::GetPrimitiveValueType(name) == "variable";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,7 +175,9 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is an expression of the given type.
|
||||
* \brief Return true if the type is an expression of the given type from the
|
||||
* caller point of view.
|
||||
*
|
||||
* \note If you are adding a new type of parameter, also add it in the IDE (
|
||||
* see EventsFunctionParametersEditor, ParameterRenderingService
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
@@ -186,6 +188,7 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
return parameterType == "number" || parameterType == "expression" ||
|
||||
parameterType == "camera" || parameterType == "forceMultiplier";
|
||||
} else if (type == "string") {
|
||||
// "key" and "mouse" are not mapped her, see GetPrimitiveValueType.
|
||||
return parameterType == "string" || parameterType == "layer" ||
|
||||
parameterType == "color" || parameterType == "file" ||
|
||||
parameterType == "stringWithSelector" ||
|
||||
@@ -210,8 +213,8 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
parameterType == "scenevar";
|
||||
} else if (type == "resource") {
|
||||
return parameterType == "fontResource" ||
|
||||
parameterType == "soundfile" ||
|
||||
parameterType == "musicfile" ||
|
||||
parameterType == "audioResource" ||
|
||||
parameterType == "videoResource" ||
|
||||
parameterType == "bitmapFontResource" ||
|
||||
parameterType == "imageResource" ||
|
||||
parameterType == "jsonResource" ||
|
||||
@@ -219,7 +222,30 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
parameterType == "tilesetResource" ||
|
||||
parameterType == "model3DResource" ||
|
||||
parameterType == "atlasResource" ||
|
||||
parameterType == "spineResource";
|
||||
parameterType == "spineResource" ||
|
||||
// Deprecated, old parameter types:
|
||||
parameterType == "soundfile" ||
|
||||
parameterType == "musicfile";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type is a value of the given primitive type from
|
||||
* the function events point of view
|
||||
*/
|
||||
static bool IsTypeValue(const gd::String &type,
|
||||
const gd::String ¶meterType) {
|
||||
if (gd::ValueTypeMetadata::IsTypeExpression(type, parameterType)) {
|
||||
return true;
|
||||
}
|
||||
// These 2 parameter types are not strings from the outside of a function as
|
||||
// the generator add quote around a text, but from the events inside of the
|
||||
// function the parameter is a string.
|
||||
//
|
||||
// See EventsCodeGenerator::GenerateParameterCodes
|
||||
if (type == "string") {
|
||||
return parameterType == "key" || parameterType == "mouse";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -275,9 +301,11 @@ class GD_CORE_API ValueTypeMetadata {
|
||||
|
||||
static const gd::String numberValueType;
|
||||
static const gd::String booleanValueType;
|
||||
static const gd::String stringValueType;
|
||||
static const gd::String colorValueType;
|
||||
static const gd::String choiceValueType;
|
||||
static const gd::String stringValueType;
|
||||
static const gd::String behaviorValueType;
|
||||
static const gd::String leaderboardIdValueType;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -96,11 +96,11 @@ std::shared_ptr<gd::PlatformExtension> Platform::GetExtension(
|
||||
std::unique_ptr<gd::ObjectConfiguration> Platform::CreateObjectConfiguration(
|
||||
gd::String type) const {
|
||||
if (creationFunctionTable.find(type) == creationFunctionTable.end()) {
|
||||
gd::LogWarning("Tried to create an object with an unknown type: " + type
|
||||
gd::LogWarning("Tried to create an object configuration with an unknown type: " + type
|
||||
+ " for platform " + GetName() + "!");
|
||||
type = "";
|
||||
if (creationFunctionTable.find("") == creationFunctionTable.end()) {
|
||||
gd::LogError("Unable to create a Base object!");
|
||||
gd::LogFatalError("Unable to create a base object configuration!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@@ -808,6 +808,24 @@ gd::String PlatformExtension::GetObjectFullType(const gd::String &extensionName,
|
||||
return extensionName + separator + objectName;
|
||||
}
|
||||
|
||||
gd::String PlatformExtension::GetExtensionFromFullObjectType(const gd::String& type) {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
if (separatorIndex == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
return type.substr(0, separatorIndex);
|
||||
}
|
||||
|
||||
gd::String PlatformExtension::GetObjectNameFromFullObjectType(const gd::String& type) {
|
||||
const auto separatorIndex =
|
||||
type.find(PlatformExtension::GetNamespaceSeparator());
|
||||
if (separatorIndex == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
return type.substr(separatorIndex + 2);
|
||||
}
|
||||
|
||||
PlatformExtension::PlatformExtension()
|
||||
: deprecated(false), category(_("General")) {}
|
||||
|
||||
|
@@ -40,8 +40,7 @@ class Object;
|
||||
class ObjectConfiguration;
|
||||
} // namespace gd
|
||||
|
||||
typedef std::function<std::unique_ptr<gd::ObjectConfiguration>()>
|
||||
CreateFunPtr;
|
||||
typedef std::function<std::unique_ptr<gd::ObjectConfiguration>()> CreateFunPtr;
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -51,25 +50,25 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API CompilationInfo {
|
||||
public:
|
||||
CompilationInfo() : informationCompleted(false){};
|
||||
virtual ~CompilationInfo(){};
|
||||
CompilationInfo() {};
|
||||
virtual ~CompilationInfo() {};
|
||||
|
||||
bool informationCompleted;
|
||||
bool informationCompleted = false;
|
||||
|
||||
bool runtimeOnly; ///< True if the extension was compiled for a runtime use
|
||||
///< only
|
||||
bool runtimeOnly = false; ///< True if the extension was compiled for a
|
||||
///< runtime use only
|
||||
|
||||
#if defined(__GNUC__)
|
||||
int gccMajorVersion;
|
||||
int gccMinorVersion;
|
||||
int gccPatchLevel;
|
||||
int gccMajorVersion = 0;
|
||||
int gccMinorVersion = 0;
|
||||
int gccPatchLevel = 0;
|
||||
#endif
|
||||
|
||||
int sfmlMajorVersion;
|
||||
int sfmlMinorVersion;
|
||||
int sfmlMajorVersion = 0;
|
||||
int sfmlMinorVersion = 0;
|
||||
|
||||
gd::String gdCoreVersion;
|
||||
int sizeOfpInt;
|
||||
int sizeOfpInt = 0;
|
||||
};
|
||||
|
||||
struct GD_CORE_API DuplicatedInstructionOptions {
|
||||
@@ -239,11 +238,12 @@ class GD_CORE_API PlatformExtension {
|
||||
* \param instance The "blueprint" object to be copied when a new object is
|
||||
asked for.
|
||||
*/
|
||||
gd::ObjectMetadata& AddObject(const gd::String& name_,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& description_,
|
||||
const gd::String& icon_,
|
||||
std::shared_ptr<gd::ObjectConfiguration> instance);
|
||||
gd::ObjectMetadata& AddObject(
|
||||
const gd::String& name_,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& description_,
|
||||
const gd::String& icon_,
|
||||
std::shared_ptr<gd::ObjectConfiguration> instance);
|
||||
|
||||
/**
|
||||
* \brief Declare a new events based object as being part of the extension.
|
||||
@@ -253,11 +253,10 @@ class GD_CORE_API PlatformExtension {
|
||||
* \param description The user friendly description of the object
|
||||
* \param icon The icon of the object.
|
||||
*/
|
||||
gd::ObjectMetadata& AddEventsBasedObject(
|
||||
const gd::String& name_,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& description_,
|
||||
const gd::String& icon_);
|
||||
gd::ObjectMetadata& AddEventsBasedObject(const gd::String& name_,
|
||||
const gd::String& fullname_,
|
||||
const gd::String& description_,
|
||||
const gd::String& icon_);
|
||||
|
||||
/**
|
||||
* \brief Declare a new behavior as being part of the extension.
|
||||
@@ -420,8 +419,7 @@ class GD_CORE_API PlatformExtension {
|
||||
PlatformExtension& SetTags(const gd::String& csvTags) {
|
||||
tags.clear();
|
||||
tags = csvTags.Split(',');
|
||||
for (size_t i = 0; i < tags.size(); i++)
|
||||
{
|
||||
for (size_t i = 0; i < tags.size(); i++) {
|
||||
tags[i] = tags[i].Trim().LowerCase();
|
||||
}
|
||||
return *this;
|
||||
@@ -634,26 +632,30 @@ class GD_CORE_API PlatformExtension {
|
||||
*/
|
||||
static gd::String GetNamespaceSeparator() { return "::"; }
|
||||
|
||||
static gd::String GetEventsFunctionFullType(const gd::String &extensionName,
|
||||
const gd::String &functionName);
|
||||
static gd::String GetEventsFunctionFullType(const gd::String& extensionName,
|
||||
const gd::String& functionName);
|
||||
|
||||
static gd::String
|
||||
GetBehaviorEventsFunctionFullType(const gd::String &extensionName,
|
||||
const gd::String &behaviorName,
|
||||
const gd::String &functionName);
|
||||
static gd::String GetBehaviorEventsFunctionFullType(
|
||||
const gd::String& extensionName,
|
||||
const gd::String& behaviorName,
|
||||
const gd::String& functionName);
|
||||
|
||||
static gd::String GetBehaviorFullType(const gd::String &extensionName,
|
||||
const gd::String &behaviorName);
|
||||
static gd::String GetBehaviorFullType(const gd::String& extensionName,
|
||||
const gd::String& behaviorName);
|
||||
|
||||
static gd::String
|
||||
GetObjectEventsFunctionFullType(const gd::String &extensionName,
|
||||
const gd::String &objectName,
|
||||
const gd::String &functionName);
|
||||
static gd::String GetObjectEventsFunctionFullType(
|
||||
const gd::String& extensionName,
|
||||
const gd::String& objectName,
|
||||
const gd::String& functionName);
|
||||
|
||||
static gd::String GetObjectFullType(const gd::String &extensionName,
|
||||
const gd::String &objectName);
|
||||
static gd::String GetObjectFullType(const gd::String& extensionName,
|
||||
const gd::String& objectName);
|
||||
|
||||
private:
|
||||
static gd::String GetExtensionFromFullObjectType(const gd::String& type);
|
||||
|
||||
static gd::String GetObjectNameFromFullObjectType(const gd::String& type);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Set the namespace (the string all actions/conditions/expressions start
|
||||
* with).
|
||||
@@ -668,10 +670,10 @@ private:
|
||||
gd::String fullname; ///< Name displayed to users in the editor.
|
||||
gd::String informations; ///< Description displayed to users in the editor.
|
||||
gd::String category;
|
||||
gd::String author; ///< Author displayed to users in the editor.
|
||||
gd::String license; ///< License name displayed to users in the editor.
|
||||
bool deprecated; ///< true if the extension is deprecated and shouldn't be
|
||||
///< shown in IDE.
|
||||
gd::String author; ///< Author displayed to users in the editor.
|
||||
gd::String license; ///< License name displayed to users in the editor.
|
||||
bool deprecated; ///< true if the extension is deprecated and shouldn't be
|
||||
///< shown in IDE.
|
||||
gd::String helpPath; ///< The relative path to the help for this extension in
|
||||
///< the documentation.
|
||||
gd::String iconUrl; ///< The URL to the icon to be shown for this extension.
|
||||
|
@@ -5,6 +5,8 @@
|
||||
* project is released under the MIT License.
|
||||
*/
|
||||
|
||||
// NOLINTBEGIN
|
||||
|
||||
#ifndef GDCORE_PLATFORMEXTENSION_INL
|
||||
#define GDCORE_PLATFORMEXTENSION_INL
|
||||
|
||||
@@ -36,3 +38,5 @@ gd::ObjectMetadata& PlatformExtension::AddObject(const gd::String& name,
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
||||
|
||||
// NOLINTEND
|
18
Core/GDCore/IDE/CaptureOptions.cpp
Normal file
18
Core/GDCore/IDE/CaptureOptions.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/CaptureOptions.h"
|
||||
|
||||
#include "GDCore/String.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
Screenshot::Screenshot() {}
|
||||
|
||||
CaptureOptions::CaptureOptions() {}
|
||||
|
||||
} // namespace gd
|
50
Core/GDCore/IDE/CaptureOptions.h
Normal file
50
Core/GDCore/IDE/CaptureOptions.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
class GD_CORE_API Screenshot {
|
||||
public:
|
||||
Screenshot();
|
||||
virtual ~Screenshot() {};
|
||||
|
||||
void SetDelayTimeInSeconds(int delayTimeInMs_) {
|
||||
delayTimeInMs = delayTimeInMs_;
|
||||
}
|
||||
int GetDelayTimeInSeconds() const { return delayTimeInMs; }
|
||||
|
||||
void SetSignedUrl(const gd::String& signedUrl_) { signedUrl = signedUrl_; }
|
||||
const gd::String& GetSignedUrl() const { return signedUrl; }
|
||||
|
||||
void SetPublicUrl(const gd::String& publicUrl_) { publicUrl = publicUrl_; }
|
||||
const gd::String& GetPublicUrl() const { return publicUrl; }
|
||||
|
||||
private:
|
||||
int delayTimeInMs = 0;
|
||||
gd::String signedUrl;
|
||||
gd::String publicUrl;
|
||||
};
|
||||
|
||||
class GD_CORE_API CaptureOptions {
|
||||
public:
|
||||
CaptureOptions();
|
||||
virtual ~CaptureOptions() {};
|
||||
|
||||
bool IsEmpty() const { return screenshots.empty(); }
|
||||
|
||||
void AddScreenshot(const Screenshot& screenshot) {
|
||||
screenshots.push_back(screenshot);
|
||||
}
|
||||
|
||||
const std::vector<Screenshot>& GetScreenshots() const { return screenshots; }
|
||||
|
||||
void ClearScreenshots() { screenshots.clear(); }
|
||||
|
||||
private:
|
||||
std::vector<Screenshot> screenshots;
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -26,12 +26,9 @@ void EventBasedBehaviorBrowser::ExposeEvents(
|
||||
void EventBasedBehaviorBrowser::ExposeEvents(
|
||||
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) const {
|
||||
gd::ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
|
||||
project, eventsBasedBehavior, worker);
|
||||
project, eventsFunctionsExtension, eventsBasedBehavior, worker);
|
||||
}
|
||||
|
||||
void EventBasedBehaviorBrowser::ExposeObjects(
|
||||
gd::Project &project, gd::ArbitraryObjectsWorker &worker) const {}
|
||||
|
||||
void EventBasedBehaviorBrowser::ExposeFunctions(
|
||||
gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) const {
|
||||
worker.Launch(eventsBasedBehavior.GetEventsFunctions());
|
||||
@@ -43,7 +40,4 @@ void EventBasedBehaviorBrowser::ExposeEventBasedBehaviors(
|
||||
worker.Launch(eventsBasedBehavior);
|
||||
}
|
||||
|
||||
void EventBasedBehaviorBrowser::ExposeBehaviorSharedDatas(
|
||||
gd::Project &project, gd::ArbitraryBehaviorSharedDataWorker &worker) const {}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -29,8 +29,11 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API EventBasedBehaviorBrowser : public ProjectBrowser {
|
||||
public:
|
||||
EventBasedBehaviorBrowser(gd::EventsBasedBehavior &eventsBasedBehavior_)
|
||||
: eventsBasedBehavior(eventsBasedBehavior_) {}
|
||||
EventBasedBehaviorBrowser(
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension_,
|
||||
gd::EventsBasedBehavior &eventsBasedBehavior_)
|
||||
: eventsFunctionsExtension(eventsFunctionsExtension_),
|
||||
eventsBasedBehavior(eventsBasedBehavior_) {}
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all events of the event-based
|
||||
@@ -48,7 +51,7 @@ public:
|
||||
* This should be the preferred way to traverse all the events of an event-based behavior.
|
||||
*/
|
||||
void
|
||||
ExposeEvents(gd::Project &project,
|
||||
ExposeEvents(gd::Project &project,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) const override;
|
||||
|
||||
/**
|
||||
@@ -64,7 +67,7 @@ public:
|
||||
* \brief Do nothing.
|
||||
*/
|
||||
void ExposeObjects(gd::Project &project,
|
||||
gd::ArbitraryObjectsWorker &worker) const override;
|
||||
gd::ArbitraryObjectsWorker &worker) const override {};
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on the event-based behavior.
|
||||
@@ -77,9 +80,10 @@ public:
|
||||
* \brief Do nothing.
|
||||
*/
|
||||
void ExposeBehaviorSharedDatas(gd::Project &project,
|
||||
gd::ArbitraryBehaviorSharedDataWorker &worker) const override;
|
||||
gd::ArbitraryBehaviorSharedDataWorker &worker) const override {};
|
||||
|
||||
private:
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension;
|
||||
gd::EventsBasedBehavior &eventsBasedBehavior;
|
||||
};
|
||||
|
||||
|
37
Core/GDCore/IDE/EventBasedObjectBrowser.cpp
Normal file
37
Core/GDCore/IDE/EventBasedObjectBrowser.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "EventBasedObjectBrowser.h"
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryBehaviorSharedDataWorker.h"
|
||||
#include "GDCore/IDE/ProjectBrowserHelper.h"
|
||||
#include "GDCore/Project/EventsBasedObject.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
void EventBasedObjectBrowser::ExposeEvents(
|
||||
gd::Project &project, gd::ArbitraryEventsWorker &worker) const {
|
||||
gd::ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
||||
project, eventsBasedObject, worker);
|
||||
}
|
||||
|
||||
void EventBasedObjectBrowser::ExposeEvents(
|
||||
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) const {
|
||||
gd::ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
|
||||
project, eventsFunctionsExtension, eventsBasedObject, worker);
|
||||
}
|
||||
|
||||
void EventBasedObjectBrowser::ExposeFunctions(
|
||||
gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) const {
|
||||
worker.Launch(eventsBasedObject.GetEventsFunctions());
|
||||
}
|
||||
|
||||
} // namespace gd
|
90
Core/GDCore/IDE/EventBasedObjectBrowser.h
Normal file
90
Core/GDCore/IDE/EventBasedObjectBrowser.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/IDE/ProjectBrowser.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
class String;
|
||||
class EventsFunctionsExtension;
|
||||
class EventsFunction;
|
||||
class EventsBasedBehavior;
|
||||
class EventsBasedObject;
|
||||
class ArbitraryEventsWorker;
|
||||
class ArbitraryEventsWorkerWithContext;
|
||||
class ArbitraryEventsFunctionsWorker;
|
||||
class ArbitraryObjectsWorker;
|
||||
class ArbitraryEventBasedBehaviorsWorker;
|
||||
class ArbitraryBehaviorSharedDataWorker;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Expose event-based object contents to workers.
|
||||
*/
|
||||
class GD_CORE_API EventBasedObjectBrowser : public ProjectBrowser {
|
||||
public:
|
||||
EventBasedObjectBrowser(
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension_,
|
||||
gd::EventsBasedObject &eventsBasedObject_)
|
||||
: eventsFunctionsExtension(eventsFunctionsExtension_),
|
||||
eventsBasedObject(eventsBasedObject_) {}
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all events of the event-based
|
||||
* object.
|
||||
*
|
||||
* This should be the preferred way to traverse all the events of an event-based object.
|
||||
*/
|
||||
void ExposeEvents(gd::Project &project,
|
||||
gd::ArbitraryEventsWorker &worker) const override;
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all events of the event-based
|
||||
* object.
|
||||
*
|
||||
* This should be the preferred way to traverse all the events of an event-based object.
|
||||
*/
|
||||
void
|
||||
ExposeEvents(gd::Project &project,
|
||||
gd::ArbitraryEventsWorkerWithContext &worker) const override;
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all functions of the event-based object
|
||||
*
|
||||
* This should be the preferred way to traverse all the function signatures
|
||||
* of an event-based object.
|
||||
*/
|
||||
void ExposeFunctions(gd::Project &project,
|
||||
gd::ArbitraryEventsFunctionsWorker &worker) const override;
|
||||
|
||||
/**
|
||||
* \brief Do nothing.
|
||||
*/
|
||||
void ExposeObjects(gd::Project &project,
|
||||
gd::ArbitraryObjectsWorker &worker) const override {};
|
||||
|
||||
/**
|
||||
* @brief Do nothing.
|
||||
*/
|
||||
void ExposeEventBasedBehaviors(
|
||||
gd::Project &project,
|
||||
gd::ArbitraryEventBasedBehaviorsWorker &worker) const override {};
|
||||
|
||||
/**
|
||||
* \brief Do nothing.
|
||||
*/
|
||||
void ExposeBehaviorSharedDatas(gd::Project &project,
|
||||
gd::ArbitraryBehaviorSharedDataWorker &worker) const override {};
|
||||
|
||||
private:
|
||||
const gd::EventsFunctionsExtension &eventsFunctionsExtension;
|
||||
gd::EventsBasedObject &eventsBasedObject;
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -14,29 +14,27 @@
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
ArbitraryEventsWorker::~ArbitraryEventsWorker() {}
|
||||
AbstractArbitraryEventsWorker::~AbstractArbitraryEventsWorker() {}
|
||||
|
||||
void ArbitraryEventsWorker::VisitEventList(gd::EventsList& events) {
|
||||
void AbstractArbitraryEventsWorker::VisitEventList(gd::EventsList& events) {
|
||||
DoVisitEventList(events);
|
||||
|
||||
for (std::size_t i = 0; i < events.size();) {
|
||||
if (events[i].AcceptVisitor(*this))
|
||||
events.RemoveEvent(i);
|
||||
else {
|
||||
if (events[i].CanHaveSubEvents())
|
||||
VisitEventList(events[i].GetSubEvents());
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ArbitraryEventsWorker::VisitEvent(gd::BaseEvent& event) {
|
||||
bool AbstractArbitraryEventsWorker::VisitEvent(gd::BaseEvent& event) {
|
||||
bool shouldDelete = DoVisitEvent(event);
|
||||
if (shouldDelete) return true;
|
||||
|
||||
@@ -55,15 +53,17 @@ bool ArbitraryEventsWorker::VisitEvent(gd::BaseEvent& event) {
|
||||
*expressionAndMetadata.first, expressionAndMetadata.second);
|
||||
}
|
||||
|
||||
|
||||
if (!shouldDelete && event.CanHaveSubEvents()) {
|
||||
VisitEventList(event.GetSubEvents());
|
||||
}
|
||||
return shouldDelete;
|
||||
}
|
||||
|
||||
bool ArbitraryEventsWorker::VisitLinkEvent(gd::LinkEvent& linkEvent) {
|
||||
bool AbstractArbitraryEventsWorker::VisitLinkEvent(gd::LinkEvent& linkEvent) {
|
||||
return DoVisitLinkEvent(linkEvent);
|
||||
}
|
||||
|
||||
void ArbitraryEventsWorker::VisitInstructionList(
|
||||
void AbstractArbitraryEventsWorker::VisitInstructionList(
|
||||
gd::InstructionsList& instructions, bool areConditions) {
|
||||
DoVisitInstructionList(instructions, areConditions);
|
||||
|
||||
@@ -79,22 +79,19 @@ void ArbitraryEventsWorker::VisitInstructionList(
|
||||
}
|
||||
}
|
||||
|
||||
bool ArbitraryEventsWorker::VisitInstruction(gd::Instruction& instruction,
|
||||
bool AbstractArbitraryEventsWorker::VisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
return DoVisitInstruction(instruction, isCondition);
|
||||
}
|
||||
|
||||
bool ArbitraryEventsWorker::VisitEventExpression(gd::Expression& expression,
|
||||
bool AbstractArbitraryEventsWorker::VisitEventExpression(gd::Expression& expression,
|
||||
const gd::ParameterMetadata& metadata) {
|
||||
return DoVisitEventExpression(expression, metadata);
|
||||
}
|
||||
|
||||
ArbitraryEventsWorkerWithContext::~ArbitraryEventsWorkerWithContext() {}
|
||||
AbstractReadOnlyArbitraryEventsWorker::~AbstractReadOnlyArbitraryEventsWorker() {}
|
||||
|
||||
|
||||
ReadOnlyArbitraryEventsWorker::~ReadOnlyArbitraryEventsWorker() {}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events) {
|
||||
void AbstractReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events) {
|
||||
DoVisitEventList(events);
|
||||
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
@@ -109,7 +106,7 @@ void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events)
|
||||
}
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
|
||||
void AbstractReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
|
||||
DoVisitEvent(event);
|
||||
|
||||
const vector<const gd::InstructionsList*> conditionsVectors =
|
||||
@@ -130,11 +127,11 @@ void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
|
||||
}
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitLinkEvent(const gd::LinkEvent& linkEvent) {
|
||||
void AbstractReadOnlyArbitraryEventsWorker::VisitLinkEvent(const gd::LinkEvent& linkEvent) {
|
||||
DoVisitLinkEvent(linkEvent);
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
|
||||
void AbstractReadOnlyArbitraryEventsWorker::VisitInstructionList(
|
||||
const gd::InstructionsList& instructions, bool areConditions) {
|
||||
DoVisitInstructionList(instructions, areConditions);
|
||||
|
||||
@@ -150,21 +147,73 @@ void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
|
||||
}
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& instruction,
|
||||
void AbstractReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
DoVisitInstruction(instruction, isCondition);
|
||||
}
|
||||
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitEventExpression(const gd::Expression& expression,
|
||||
void AbstractReadOnlyArbitraryEventsWorker::VisitEventExpression(const gd::Expression& expression,
|
||||
const gd::ParameterMetadata& metadata) {
|
||||
DoVisitEventExpression(expression, metadata);
|
||||
}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::StopAnyEventIteration() {
|
||||
void AbstractReadOnlyArbitraryEventsWorker::StopAnyEventIteration() {
|
||||
shouldStopIteration = true;
|
||||
}
|
||||
|
||||
ArbitraryEventsWorker::~ArbitraryEventsWorker() {}
|
||||
|
||||
bool ArbitraryEventsWorker::VisitEvent(gd::BaseEvent &event) {
|
||||
return AbstractArbitraryEventsWorker::VisitEvent(event);
|
||||
}
|
||||
|
||||
ArbitraryEventsWorkerWithContext::~ArbitraryEventsWorkerWithContext() {}
|
||||
|
||||
bool ArbitraryEventsWorkerWithContext::VisitEvent(gd::BaseEvent &event) {
|
||||
if (!event.HasVariables()) {
|
||||
return AbstractArbitraryEventsWorker::VisitEvent(event);
|
||||
}
|
||||
// Push local variables
|
||||
auto newProjectScopedContainers =
|
||||
ProjectScopedContainers::MakeNewProjectScopedContainersWithLocalVariables(
|
||||
*currentProjectScopedContainers, event);
|
||||
auto *parentProjectScopedContainers = currentProjectScopedContainers;
|
||||
currentProjectScopedContainers = &newProjectScopedContainers;
|
||||
|
||||
bool shouldDelete = AbstractArbitraryEventsWorker::VisitEvent(event);
|
||||
|
||||
// Pop local variables
|
||||
currentProjectScopedContainers = parentProjectScopedContainers;
|
||||
return shouldDelete;
|
||||
}
|
||||
|
||||
ReadOnlyArbitraryEventsWorker::~ReadOnlyArbitraryEventsWorker() {}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorker::VisitEvent(
|
||||
const gd::BaseEvent &event) {
|
||||
AbstractReadOnlyArbitraryEventsWorker::VisitEvent(event);
|
||||
}
|
||||
|
||||
ReadOnlyArbitraryEventsWorkerWithContext::~ReadOnlyArbitraryEventsWorkerWithContext() {}
|
||||
|
||||
void ReadOnlyArbitraryEventsWorkerWithContext::VisitEvent(
|
||||
const gd::BaseEvent &event) {
|
||||
if (!event.HasVariables()) {
|
||||
AbstractReadOnlyArbitraryEventsWorker::VisitEvent(event);
|
||||
return;
|
||||
}
|
||||
// Push local variables
|
||||
auto newProjectScopedContainers =
|
||||
ProjectScopedContainers::MakeNewProjectScopedContainersWithLocalVariables(
|
||||
*currentProjectScopedContainers, event);
|
||||
auto *parentProjectScopedContainers = currentProjectScopedContainers;
|
||||
currentProjectScopedContainers = &newProjectScopedContainers;
|
||||
|
||||
AbstractReadOnlyArbitraryEventsWorker::VisitEvent(event);
|
||||
|
||||
// Pop local variables
|
||||
currentProjectScopedContainers = parentProjectScopedContainers;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -3,8 +3,8 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_ARBITRARYEVENTSWORKER_H
|
||||
#define GDCORE_ARBITRARYEVENTSWORKER_H
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "GDCore/Events/EventVisitor.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Instruction;
|
||||
class BaseEvent;
|
||||
@@ -25,27 +26,24 @@ class ParameterMetadata;
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief ArbitraryEventsWorker is an abstract class used to browse events (and
|
||||
* instructions) and do some work on them. Can be used to implement refactoring
|
||||
* for example.
|
||||
* \brief AbstractArbitraryEventsWorker is a base abstract class used to browse events (and
|
||||
* instructions) and do some work on them. It must not be inherited directly.
|
||||
*
|
||||
* \see gd::ArbitraryEventsWorker
|
||||
* \see gd::ArbitraryEventsWorkerWithContext
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ArbitraryEventsWorker : private EventVisitor {
|
||||
class GD_CORE_API AbstractArbitraryEventsWorker : private EventVisitor {
|
||||
public:
|
||||
ArbitraryEventsWorker(){};
|
||||
virtual ~ArbitraryEventsWorker();
|
||||
AbstractArbitraryEventsWorker(){};
|
||||
virtual ~AbstractArbitraryEventsWorker();
|
||||
|
||||
/**
|
||||
* \brief Launch the worker on the specified events list.
|
||||
*/
|
||||
void Launch(gd::EventsList& events) { VisitEventList(events); };
|
||||
protected:
|
||||
virtual bool VisitEvent(gd::BaseEvent& event) override;
|
||||
void VisitEventList(gd::EventsList& events);
|
||||
|
||||
private:
|
||||
void VisitEventList(gd::EventsList& events);
|
||||
bool VisitEvent(gd::BaseEvent& event) override;
|
||||
bool VisitLinkEvent(gd::LinkEvent& linkEvent) override;
|
||||
void VisitInstructionList(gd::InstructionsList& instructions,
|
||||
bool areConditions);
|
||||
@@ -101,6 +99,31 @@ class GD_CORE_API ArbitraryEventsWorker : private EventVisitor {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief ArbitraryEventsWorker is an abstract class used to browse events (and
|
||||
* instructions) and do some work on them. Can be used to implement refactoring
|
||||
* for example.
|
||||
*
|
||||
* \see gd::ArbitraryEventsWorkerWithContext
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ArbitraryEventsWorker : public AbstractArbitraryEventsWorker {
|
||||
public:
|
||||
ArbitraryEventsWorker(){};
|
||||
virtual ~ArbitraryEventsWorker();
|
||||
|
||||
/**
|
||||
* \brief Launch the worker on the specified events list.
|
||||
*/
|
||||
void Launch(gd::EventsList &events) {
|
||||
AbstractArbitraryEventsWorker::VisitEventList(events);
|
||||
};
|
||||
|
||||
private:
|
||||
bool VisitEvent(gd::BaseEvent &event) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief An events worker that will know about the context (the objects
|
||||
* container). Useful for workers working on expressions notably.
|
||||
@@ -110,10 +133,10 @@ class GD_CORE_API ArbitraryEventsWorker : private EventVisitor {
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ArbitraryEventsWorkerWithContext
|
||||
: public ArbitraryEventsWorker {
|
||||
: public AbstractArbitraryEventsWorker {
|
||||
public:
|
||||
ArbitraryEventsWorkerWithContext()
|
||||
: projectScopedContainers(nullptr){};
|
||||
: currentProjectScopedContainers(nullptr){};
|
||||
virtual ~ArbitraryEventsWorkerWithContext();
|
||||
|
||||
/**
|
||||
@@ -121,53 +144,50 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
|
||||
* giving the objects container on which the events are applying to.
|
||||
*/
|
||||
void Launch(gd::EventsList& events,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_) {
|
||||
projectScopedContainers = &projectScopedContainers_;
|
||||
ArbitraryEventsWorker::Launch(events);
|
||||
const gd::ProjectScopedContainers& projectScopedContainers) {
|
||||
currentProjectScopedContainers = &projectScopedContainers;
|
||||
AbstractArbitraryEventsWorker::VisitEventList(events);
|
||||
};
|
||||
|
||||
void Launch(gd::EventsList& events) = delete;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
const gd::ProjectScopedContainers& GetProjectScopedContainers() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return *projectScopedContainers;
|
||||
return *currentProjectScopedContainers;
|
||||
};
|
||||
const gd::ObjectsContainersList& GetObjectsContainersList() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return projectScopedContainers->GetObjectsContainersList();
|
||||
return currentProjectScopedContainers->GetObjectsContainersList();
|
||||
};
|
||||
|
||||
private:
|
||||
const gd::ProjectScopedContainers* projectScopedContainers;
|
||||
bool VisitEvent(gd::BaseEvent& event) override;
|
||||
|
||||
const gd::ProjectScopedContainers* currentProjectScopedContainers;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief ReadOnlyArbitraryEventsWorker is an abstract class used to browse events (and
|
||||
* instructions). It can be used to implement autocompletion for example.
|
||||
* instructions). It must not be inherited directly.
|
||||
*
|
||||
* \see gd::ReadOnlyArbitraryEventsWorker
|
||||
* \see gd::ReadOnlyArbitraryEventsWorkerWithContext
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
|
||||
class GD_CORE_API AbstractReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
|
||||
public:
|
||||
ReadOnlyArbitraryEventsWorker() : shouldStopIteration(false) {};
|
||||
virtual ~ReadOnlyArbitraryEventsWorker();
|
||||
|
||||
/**
|
||||
* \brief Launch the worker on the specified events list.
|
||||
*/
|
||||
void Launch(const gd::EventsList& events) { VisitEventList(events); };
|
||||
AbstractReadOnlyArbitraryEventsWorker() : shouldStopIteration(false) {};
|
||||
virtual ~AbstractReadOnlyArbitraryEventsWorker();
|
||||
|
||||
protected:
|
||||
void StopAnyEventIteration() override;
|
||||
virtual void VisitEvent(const gd::BaseEvent& event) override;
|
||||
|
||||
void VisitEventList(const gd::EventsList& events);
|
||||
|
||||
private:
|
||||
void VisitEventList(const gd::EventsList& events);
|
||||
void VisitEvent(const gd::BaseEvent& event) override;
|
||||
void VisitLinkEvent(const gd::LinkEvent& linkEvent) override;
|
||||
void VisitInstructionList(const gd::InstructionsList& instructions,
|
||||
bool areConditions);
|
||||
@@ -213,6 +233,31 @@ protected:
|
||||
bool shouldStopIteration;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief ReadOnlyArbitraryEventsWorker is an abstract class used to browse events (and
|
||||
* instructions). It can be used to implement autocompletion for example.
|
||||
*
|
||||
* \see gd::ReadOnlyArbitraryEventsWorkerWithContext
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ReadOnlyArbitraryEventsWorker
|
||||
: public AbstractReadOnlyArbitraryEventsWorker {
|
||||
public:
|
||||
ReadOnlyArbitraryEventsWorker(){};
|
||||
virtual ~ReadOnlyArbitraryEventsWorker();
|
||||
|
||||
/**
|
||||
* \brief Launch the worker on the specified events list.
|
||||
*/
|
||||
void Launch(const gd::EventsList &events) {
|
||||
AbstractReadOnlyArbitraryEventsWorker::VisitEventList(events);
|
||||
};
|
||||
|
||||
private:
|
||||
void VisitEvent(const gd::BaseEvent &event) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief An events worker that will know about the context (the objects
|
||||
* container). Useful for workers working on expressions notably.
|
||||
@@ -222,10 +267,10 @@ protected:
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API ReadOnlyArbitraryEventsWorkerWithContext
|
||||
: public ReadOnlyArbitraryEventsWorker {
|
||||
: public AbstractReadOnlyArbitraryEventsWorker {
|
||||
public:
|
||||
ReadOnlyArbitraryEventsWorkerWithContext()
|
||||
: projectScopedContainers(nullptr){};
|
||||
: currentProjectScopedContainers(nullptr){};
|
||||
virtual ~ReadOnlyArbitraryEventsWorkerWithContext();
|
||||
|
||||
/**
|
||||
@@ -233,24 +278,22 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorkerWithContext
|
||||
* giving the objects container on which the events are applying to.
|
||||
*/
|
||||
void Launch(const gd::EventsList& events,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_) {
|
||||
projectScopedContainers = &projectScopedContainers_;
|
||||
ReadOnlyArbitraryEventsWorker::Launch(events);
|
||||
const gd::ProjectScopedContainers& projectScopedContainers) {
|
||||
currentProjectScopedContainers = &projectScopedContainers;
|
||||
AbstractReadOnlyArbitraryEventsWorker::VisitEventList(events);
|
||||
};
|
||||
|
||||
void Launch(gd::EventsList& events) = delete;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
const gd::ProjectScopedContainers& GetProjectScopedContainers() {
|
||||
// Pointers are guaranteed to be not nullptr after
|
||||
// Launch was called.
|
||||
return *projectScopedContainers;
|
||||
return *currentProjectScopedContainers;
|
||||
};
|
||||
|
||||
private:
|
||||
const gd::ProjectScopedContainers* projectScopedContainers;
|
||||
void VisitEvent(const gd::BaseEvent& event) override;
|
||||
|
||||
const gd::ProjectScopedContainers* currentProjectScopedContainers;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_ARBITRARYEVENTSWORKER_H
|
||||
|
65
Core/GDCore/IDE/Events/BehaviorParametersFiller.cpp
Normal file
65
Core/GDCore/IDE/Events/BehaviorParametersFiller.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2024 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "BehaviorParametersFiller.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Instruction.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
bool BehaviorParametersFiller::DoVisitInstruction(gd::Instruction &instruction,
|
||||
bool isCondition) {
|
||||
const auto &metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
instruction.GetParameters(), metadata.GetParameters(),
|
||||
[&](const gd::ParameterMetadata ¶meterMetadata,
|
||||
const gd::Expression ¶meterValue, size_t parameterIndex,
|
||||
const gd::String &lastObjectName) {
|
||||
if (parameterMetadata.GetValueTypeMetadata().IsBehavior() &&
|
||||
parameterValue.GetPlainString().length() == 0) {
|
||||
|
||||
auto &expectedBehaviorTypeName =
|
||||
parameterMetadata.GetValueTypeMetadata().GetExtraInfo();
|
||||
|
||||
auto &objectsContainersList =
|
||||
projectScopedContainers.GetObjectsContainersList();
|
||||
auto behaviorNames =
|
||||
objectsContainersList.GetBehaviorsOfObject(lastObjectName, true);
|
||||
|
||||
gd::String foundBehaviorName = "";
|
||||
for (auto &behaviorName : behaviorNames) {
|
||||
auto behaviorTypeName =
|
||||
objectsContainersList.GetTypeOfBehavior(behaviorName, false);
|
||||
if (behaviorTypeName == expectedBehaviorTypeName) {
|
||||
foundBehaviorName = behaviorName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundBehaviorName.empty()) {
|
||||
instruction.SetParameter(parameterIndex,
|
||||
gd::Expression(foundBehaviorName));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BehaviorParametersFiller::~BehaviorParametersFiller() {}
|
||||
|
||||
} // namespace gd
|
45
Core/GDCore/IDE/Events/BehaviorParametersFiller.h
Normal file
45
Core/GDCore/IDE/Events/BehaviorParametersFiller.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2024 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace gd {
|
||||
class Instruction;
|
||||
class Platform;
|
||||
class ProjectScopedContainers;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Fill empty behavior parameters with any behavior that matches the
|
||||
* required behavior type.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API BehaviorParametersFiller : public ArbitraryEventsWorker {
|
||||
public:
|
||||
BehaviorParametersFiller(
|
||||
const gd::Platform &platform_,
|
||||
const gd::ProjectScopedContainers &projectScopedContainers_)
|
||||
: platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_){};
|
||||
virtual ~BehaviorParametersFiller();
|
||||
|
||||
private:
|
||||
bool DoVisitInstruction(gd::Instruction &instruction,
|
||||
bool isCondition) override;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::ProjectScopedContainers &projectScopedContainers;
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -72,12 +72,12 @@ public:
|
||||
gd::String lastObjectParameter = "";
|
||||
const gd::InstructionMetadata &instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, instruction.GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
|
||||
if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
"number", instrInfos.parameters.GetParameter(pNb).GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"string", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = instruction.GetParameter(pNb).GetRootNode();
|
||||
node->Visit(*this);
|
||||
}
|
||||
|
@@ -86,9 +86,11 @@ class GD_CORE_API IdentifierFinderExpressionNodeWorker
|
||||
}
|
||||
|
||||
size_t parameterIndex = 0;
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0); metadataIndex < metadata.parameters.size()
|
||||
&& parameterIndex < node.parameters.size(); ++metadataIndex) {
|
||||
auto& parameterMetadata = metadata.parameters[metadataIndex];
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0);
|
||||
metadataIndex < metadata.GetParameters().GetParametersCount() &&
|
||||
parameterIndex < node.parameters.size();
|
||||
++metadataIndex) {
|
||||
auto& parameterMetadata = metadata.GetParameters().GetParameter(metadataIndex);
|
||||
if (parameterMetadata.IsCodeOnly()) {
|
||||
continue;
|
||||
}
|
||||
@@ -144,10 +146,10 @@ class GD_CORE_API IdentifierFinderEventWorker
|
||||
platform, instruction.GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
// The parameter has the searched type...
|
||||
if (instrInfos.parameters[pNb].GetType() == "identifier"
|
||||
&& instrInfos.parameters[pNb].GetExtraInfo() == identifierType) {
|
||||
if (instrInfos.parameters.GetParameter(pNb).GetType() == "identifier"
|
||||
&& instrInfos.parameters.GetParameter(pNb).GetExtraInfo() == identifierType) {
|
||||
//...remember the value of the parameter.
|
||||
if (objectName.empty() || lastObjectParameter == objectName) {
|
||||
results.insert(instruction.GetParameter(pNb).GetPlainString());
|
||||
@@ -155,9 +157,9 @@ class GD_CORE_API IdentifierFinderEventWorker
|
||||
}
|
||||
// Search in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
"number", instrInfos.parameters.GetParameter(pNb).GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"string", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = instruction.GetParameter(pNb).GetRootNode();
|
||||
|
||||
IdentifierFinderExpressionNodeWorker searcher(
|
||||
@@ -170,7 +172,7 @@ class GD_CORE_API IdentifierFinderEventWorker
|
||||
}
|
||||
// Remember the value of the last "object" parameter.
|
||||
else if (gd::ParameterMetadata::IsObject(
|
||||
instrInfos.parameters[pNb].GetType())) {
|
||||
instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
lastObjectParameter =
|
||||
instruction.GetParameter(pNb).GetPlainString();
|
||||
}
|
||||
|
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/EventsLeaderboardsLister.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
bool EventsLeaderboardsLister::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
const gd::InstructionMetadata& instrInfo =
|
||||
isCondition ? MetadataProvider::GetConditionMetadata(
|
||||
project.GetCurrentPlatform(), instruction.GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
project.GetCurrentPlatform(), instruction.GetType());
|
||||
|
||||
for (int i = 0; i < instruction.GetParametersCount() &&
|
||||
i < instrInfo.GetParametersCount();
|
||||
++i)
|
||||
if (instrInfo.GetParameter(i).GetType() == "leaderboardId") {
|
||||
leaderboardIds.insert(instruction.GetParameter(i).GetPlainString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EventsLeaderboardsLister::~EventsLeaderboardsLister() {}
|
||||
|
||||
} // namespace gd
|
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef EventsLeaderboardsLister_H
|
||||
#define EventsLeaderboardsLister_H
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class Project;
|
||||
class EventsList;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief List the leaderboard ids in the instructions.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsLeaderboardsLister : public ArbitraryEventsWorker {
|
||||
public:
|
||||
EventsLeaderboardsLister(gd::Project& project_) : project(project_){};
|
||||
virtual ~EventsLeaderboardsLister();
|
||||
|
||||
/**
|
||||
* Return the values of all leaderboardIds found in the events.
|
||||
*/
|
||||
const std::set<gd::String>& GetLeaderboardIds() { return leaderboardIds; }
|
||||
|
||||
private:
|
||||
virtual bool DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition);
|
||||
|
||||
std::set<gd::String> leaderboardIds;
|
||||
gd::Project& project;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // EventsLeaderboardsLister_H
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/EventsLeaderboardsRenamer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
bool EventsLeaderboardsRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
const gd::InstructionMetadata& instrInfo =
|
||||
isCondition ? MetadataProvider::GetConditionMetadata(
|
||||
project.GetCurrentPlatform(), instruction.GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
project.GetCurrentPlatform(), instruction.GetType());
|
||||
|
||||
for (int i = 0; i < instruction.GetParametersCount() &&
|
||||
i < instrInfo.GetParametersCount();
|
||||
++i) {
|
||||
const gd::ParameterMetadata parameter = instrInfo.GetParameter(i);
|
||||
|
||||
if (parameter.GetType() == "leaderboardId") {
|
||||
const gd::String leaderboardId =
|
||||
instruction.GetParameter(i).GetPlainString();
|
||||
|
||||
if (leaderboardIdMap.find(leaderboardId) != leaderboardIdMap.end()) {
|
||||
instruction.SetParameter(i, leaderboardIdMap[leaderboardId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EventsLeaderboardsRenamer::~EventsLeaderboardsRenamer() {}
|
||||
|
||||
} // namespace gd
|
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef EventsLeaderboardsRenamer_H
|
||||
#define EventsLeaderboardsRenamer_H
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class Project;
|
||||
class EventsList;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Replace the leaderboard ids in the instructions.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsLeaderboardsRenamer : public ArbitraryEventsWorker {
|
||||
public:
|
||||
EventsLeaderboardsRenamer(
|
||||
gd::Project& project_,
|
||||
const std::map<gd::String, gd::String>& leaderboardIdMap_)
|
||||
: project(project_), leaderboardIdMap(leaderboardIdMap_){};
|
||||
virtual ~EventsLeaderboardsRenamer();
|
||||
|
||||
private:
|
||||
virtual bool DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition);
|
||||
|
||||
std::map<gd::String, gd::String> leaderboardIdMap;
|
||||
gd::Project& project;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // EventsLeaderboardsRenamer_H
|
@@ -296,7 +296,7 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
};
|
||||
|
||||
bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& actions,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -305,14 +305,14 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
for (std::size_t aId = 0; aId < actions.size(); ++aId) {
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType()) &&
|
||||
actions[aId].GetParameter(pNb).GetPlainString() == oldName)
|
||||
actions[aId].SetParameter(pNb, gd::Expression(newName));
|
||||
// Replace object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
"number", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) {
|
||||
@@ -322,7 +322,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"string", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) {
|
||||
@@ -347,7 +347,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
|
||||
bool EventsRefactorer::RenameObjectInConditions(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -357,14 +357,14 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetConditionMetadata(platform,
|
||||
conditions[cId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType()) &&
|
||||
conditions[cId].GetParameter(pNb).GetPlainString() == oldName)
|
||||
conditions[cId].SetParameter(pNb, gd::Expression(newName));
|
||||
// Replace object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
"number", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "number", *node, oldName, newName)) {
|
||||
@@ -374,7 +374,7 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"string", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(platform, projectScopedContainers, "string", *node, oldName, newName)) {
|
||||
@@ -399,7 +399,7 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
|
||||
bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::Expression& expression,
|
||||
gd::ParameterMetadata parameterMetadata,
|
||||
gd::String oldName,
|
||||
@@ -432,7 +432,7 @@ bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
}
|
||||
|
||||
void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::EventsList& events,
|
||||
gd::String oldName,
|
||||
gd::String newName) {
|
||||
@@ -475,7 +475,7 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
}
|
||||
|
||||
bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& actions,
|
||||
gd::String name) {
|
||||
bool somethingModified = false;
|
||||
@@ -485,16 +485,16 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
// Find object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType()) &&
|
||||
actions[aId].GetParameter(pNb).GetPlainString() == name) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
// Find object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
"number", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "number", *node, name)) {
|
||||
@@ -504,7 +504,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
}
|
||||
// Find object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"string", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = actions[aId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "string", *node, name)) {
|
||||
@@ -532,7 +532,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
|
||||
bool EventsRefactorer::RemoveObjectInConditions(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name) {
|
||||
bool somethingModified = false;
|
||||
@@ -543,16 +543,16 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetConditionMetadata(platform,
|
||||
conditions[cId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
// Find object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType()) &&
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType()) &&
|
||||
conditions[cId].GetParameter(pNb).GetPlainString() == name) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
// Find object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType())) {
|
||||
"number", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "number", *node, name)) {
|
||||
@@ -562,7 +562,7 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
}
|
||||
// Find object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"string", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = conditions[cId].GetParameter(pNb).GetRootNode();
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(platform, projectScopedContainers, "string", *node, name)) {
|
||||
@@ -588,31 +588,6 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
return somethingModified;
|
||||
}
|
||||
|
||||
void EventsRefactorer::RemoveObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::EventsList& events,
|
||||
gd::String name) {
|
||||
for (std::size_t i = 0; i < events.size(); ++i) {
|
||||
vector<gd::InstructionsList*> conditionsVectors =
|
||||
events[i].GetAllConditionsVectors();
|
||||
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
|
||||
bool conditionsModified = RemoveObjectInConditions(
|
||||
platform, projectScopedContainers, *conditionsVectors[j], name);
|
||||
}
|
||||
|
||||
vector<gd::InstructionsList*> actionsVectors =
|
||||
events[i].GetAllActionsVectors();
|
||||
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
|
||||
bool actionsModified = RemoveObjectInActions(
|
||||
platform, projectScopedContainers, *actionsVectors[j], name);
|
||||
}
|
||||
|
||||
if (events[i].CanHaveSubEvents())
|
||||
RemoveObjectInEvents(
|
||||
platform, projectScopedContainers, events[i].GetSubEvents(), name);
|
||||
}
|
||||
}
|
||||
|
||||
gd::String ReplaceAllOccurrencesCaseInsensitive(gd::String context,
|
||||
const gd::String& from,
|
||||
const gd::String& to) {
|
||||
|
@@ -3,8 +3,8 @@
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EVENTSREFACTORER_H
|
||||
#define GDCORE_EVENTSREFACTORER_H
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
@@ -81,19 +81,11 @@ class GD_CORE_API EventsRefactorer {
|
||||
* events ).
|
||||
*/
|
||||
static void RenameObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::EventsList& events,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
|
||||
/**
|
||||
* Remove all actions or conditions using an object
|
||||
*/
|
||||
static void RemoveObjectInEvents(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::EventsList& events,
|
||||
gd::String name);
|
||||
|
||||
/**
|
||||
* Search for a gd::String in events
|
||||
*
|
||||
@@ -136,7 +128,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RenameObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& instructions,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -148,7 +140,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RenameObjectInConditions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& instructions,
|
||||
gd::String oldName,
|
||||
gd::String newName);
|
||||
@@ -161,7 +153,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
*/
|
||||
static bool RenameObjectInEventParameters(
|
||||
const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::Expression& expression,
|
||||
gd::ParameterMetadata parameterMetadata,
|
||||
gd::String oldName,
|
||||
@@ -173,7 +165,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RemoveObjectInConditions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name);
|
||||
|
||||
@@ -183,7 +175,7 @@ class GD_CORE_API EventsRefactorer {
|
||||
* \return true if something was modified.
|
||||
*/
|
||||
static bool RemoveObjectInActions(const gd::Platform& platform,
|
||||
gd::ProjectScopedContainers& projectScopedContainers,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers,
|
||||
gd::InstructionsList& conditions,
|
||||
gd::String name);
|
||||
|
||||
@@ -250,5 +242,3 @@ class GD_CORE_API EventsRefactorer {
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EVENTSREFACTORER_H
|
||||
|
103
Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp
Normal file
103
Core/GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/EventsVariableInstructionTypeSwitcher.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableNameFinder.h"
|
||||
#include "GDCore/IDE/VariableInstructionSwitcher.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
VariablesContainer EventsVariableInstructionTypeSwitcher::nullVariablesContainer;
|
||||
|
||||
bool EventsVariableInstructionTypeSwitcher::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
instruction.GetParameters(),
|
||||
metadata.GetParameters(),
|
||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::Expression& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
const gd::String& type = parameterMetadata.GetType();
|
||||
|
||||
if (!gd::ParameterMetadata::IsExpression("variable", type) ||
|
||||
!gd::VariableInstructionSwitcher::IsSwitchableVariableInstruction(
|
||||
instruction.GetType())) {
|
||||
return;
|
||||
}
|
||||
const auto variableName =
|
||||
gd::ExpressionVariableNameFinder::GetVariableName(
|
||||
*parameterValue.GetRootNode());
|
||||
|
||||
const gd::VariablesContainer *variablesContainer = nullptr;
|
||||
if (type == "objectvar") {
|
||||
const auto &objectsContainersList =
|
||||
GetProjectScopedContainers().GetObjectsContainersList();
|
||||
if (objectsContainersList.HasObjectOrGroupWithVariableNamed(
|
||||
lastObjectName, variableName) !=
|
||||
gd::ObjectsContainersList::VariableExistence::DoesNotExist) {
|
||||
variablesContainer =
|
||||
GetProjectScopedContainers()
|
||||
.GetObjectsContainersList()
|
||||
.GetObjectOrGroupVariablesContainer(lastObjectName);
|
||||
}
|
||||
} else {
|
||||
if (GetProjectScopedContainers().GetVariablesContainersList().Has(
|
||||
variableName)) {
|
||||
variablesContainer =
|
||||
&GetProjectScopedContainers()
|
||||
.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(variableName);
|
||||
}
|
||||
}
|
||||
|
||||
// Every occurrence of the variable or its children are checked.
|
||||
// Ensuring that a child is actually the one with a type change would
|
||||
// take more time.
|
||||
if (variablesContainer == &targetVariablesContainer ||
|
||||
lastObjectName == groupName) {
|
||||
if (typeChangedVariableNames.find(variableName) !=
|
||||
typeChangedVariableNames.end()) {
|
||||
gd::VariableInstructionSwitcher::
|
||||
SwitchBetweenUnifiedInstructionIfNeeded(
|
||||
platform, GetProjectScopedContainers(), instruction);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EventsVariableInstructionTypeSwitcher::~EventsVariableInstructionTypeSwitcher() {}
|
||||
|
||||
} // namespace gd
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2024 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class VariablesContainer;
|
||||
class Platform;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
/**
|
||||
* \brief Switch the types of variable instructions for a given set of
|
||||
* variables.
|
||||
*
|
||||
* \see gd::VariableInstructionSwitcher
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsVariableInstructionTypeSwitcher
|
||||
: public ArbitraryEventsWorkerWithContext {
|
||||
public:
|
||||
EventsVariableInstructionTypeSwitcher(
|
||||
const gd::Platform &platform_,
|
||||
const std::unordered_set<gd::String> &typeChangedVariableNames_,
|
||||
const gd::VariablesContainer &targetVariablesContainer_)
|
||||
: platform(platform_),
|
||||
typeChangedVariableNames(typeChangedVariableNames_),
|
||||
targetVariablesContainer(targetVariablesContainer_), groupName(""){};
|
||||
EventsVariableInstructionTypeSwitcher(
|
||||
const gd::Platform &platform_,
|
||||
const std::unordered_set<gd::String> &typeChangedVariableNames_,
|
||||
const gd::String &groupName_)
|
||||
: platform(platform_),
|
||||
typeChangedVariableNames(typeChangedVariableNames_),
|
||||
targetVariablesContainer(nullVariablesContainer),
|
||||
groupName(groupName_){};
|
||||
virtual ~EventsVariableInstructionTypeSwitcher();
|
||||
|
||||
private:
|
||||
bool DoVisitInstruction(gd::Instruction &instruction,
|
||||
bool isCondition) override;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::VariablesContainer &targetVariablesContainer;
|
||||
/**
|
||||
* Groups don't have VariablesContainer, so `targetVariablesContainer` will be
|
||||
* pointing to `nullVariablesContainer` and the group name is use instead to
|
||||
* check which instruction to modify.
|
||||
*/
|
||||
const gd::String groupName;
|
||||
const std::unordered_set<gd::String> &typeChangedVariableNames;
|
||||
|
||||
static VariablesContainer nullVariablesContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
@@ -20,6 +20,9 @@
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableNameFinder.h"
|
||||
#include "GDCore/IDE/VariableInstructionSwitcher.h"
|
||||
#include "GDCore/IDE/WholeProjectRefactorer.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
@@ -29,6 +32,8 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
VariablesContainer EventsVariableReplacer::nullVariablesContainer;
|
||||
|
||||
/**
|
||||
* \brief Go through the nodes and rename variables,
|
||||
* or signal if the instruction must be renamed if a removed variable is used.
|
||||
@@ -41,22 +46,26 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
ExpressionVariableReplacer(
|
||||
const gd::Platform& platform_,
|
||||
const gd::ProjectScopedContainers& projectScopedContainers_,
|
||||
const VariablesRenamingChangesetNode& variablesRenamingChangesetRoot_,
|
||||
const std::unordered_set<gd::String>& removedVariableNames_,
|
||||
const gd::VariablesContainer& targetVariablesContainer_,
|
||||
const std::unordered_map<gd::String, gd::String>& oldToNewVariableNames_,
|
||||
const std::unordered_set<gd::String>& removedVariableNames_)
|
||||
const gd::String &groupName_,
|
||||
const gd::String &forcedInitialObjectName)
|
||||
: hasDoneRenaming(false),
|
||||
removedVariableUsed(false),
|
||||
platform(platform_),
|
||||
projectScopedContainers(projectScopedContainers_),
|
||||
forcedInitialVariablesContainer(nullptr),
|
||||
forcedVariablesContainer(nullptr),
|
||||
forcedObjectName(forcedInitialObjectName),
|
||||
variablesRenamingChangesetRoot(variablesRenamingChangesetRoot_),
|
||||
removedVariableNames(removedVariableNames_),
|
||||
targetVariablesContainer(targetVariablesContainer_),
|
||||
oldToNewVariableNames(oldToNewVariableNames_),
|
||||
removedVariableNames(removedVariableNames_){};
|
||||
targetGroupName(groupName_){};
|
||||
virtual ~ExpressionVariableReplacer(){};
|
||||
|
||||
void SetForcedInitialVariablesContainer(
|
||||
const gd::VariablesContainer* forcedInitialVariablesContainer_) {
|
||||
forcedInitialVariablesContainer = forcedInitialVariablesContainer_;
|
||||
forcedVariablesContainer = forcedInitialVariablesContainer_;
|
||||
}
|
||||
|
||||
bool HasDoneRenaming() const { return hasDoneRenaming; }
|
||||
@@ -79,21 +88,30 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
// The node represents a variable or an object name on which a variable
|
||||
// will be accessed.
|
||||
|
||||
if (forcedInitialVariablesContainer) {
|
||||
if (forcedVariablesContainer) {
|
||||
const gd::String oldVariableName = node.name;
|
||||
PushVariablesRenamingChangesetRoot();
|
||||
// A scope was forced. Honor it: it means this node represents a variable
|
||||
// of the forced variables container.
|
||||
if (forcedInitialVariablesContainer == &targetVariablesContainer) {
|
||||
if (forcedVariablesContainer == &targetVariablesContainer ||
|
||||
IsTargetingObjectGroup(forcedObjectName)) {
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
if (node.child) {
|
||||
bool hasBeenPushed =
|
||||
PushVariablesRenamingChangesetNodeForVariable(oldVariableName);
|
||||
node.child->Visit(*this);
|
||||
PopVariablesRenamingChangesetNode(hasBeenPushed);
|
||||
}
|
||||
PopVariablesRenamingChangesetNode(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Match the potential *new* name of the variable, because refactorings are
|
||||
// done after changes in the variables container.
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
GetPotentialNewName(node.name),
|
||||
node.name,
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
// Remember the object name.
|
||||
@@ -103,14 +121,21 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
},
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
if (&projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(node.name) ==
|
||||
&targetVariablesContainer) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
PushVariablesRenamingChangesetRoot();
|
||||
RenameVariableAndVisitChild(node.name, node.child.get());
|
||||
PopVariablesRenamingChangesetNode(true);
|
||||
} else {
|
||||
if (node.child) {
|
||||
PushVariablesRenamingChangesetNodeForIgnoredVariables();
|
||||
node.child->Visit(*this);
|
||||
PopVariablesRenamingChangesetNode(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
},
|
||||
[&]() {
|
||||
// This is a property.
|
||||
@@ -121,14 +146,7 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
if (node.child) node.child->Visit(*this);
|
||||
},
|
||||
[&]() {
|
||||
// This is something else - potentially a deleted variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
}
|
||||
|
||||
// This is something else.
|
||||
if (node.child) node.child->Visit(*this);
|
||||
});
|
||||
}
|
||||
@@ -136,25 +154,50 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
auto& objectsContainersList =
|
||||
projectScopedContainers.GetObjectsContainersList();
|
||||
if (!objectNameToUseForVariableAccessor.empty()) {
|
||||
// This is always true because MatchIdentifierWithName is used to get
|
||||
// objectNameToUseForVariableAccessor.
|
||||
if (objectsContainersList.HasObjectOrGroupVariablesContainer(
|
||||
objectNameToUseForVariableAccessor, targetVariablesContainer)) {
|
||||
objectNameToUseForVariableAccessor, targetVariablesContainer) ||
|
||||
IsTargetingObjectGroup(objectNameToUseForVariableAccessor)) {
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
// The node represents an object variable, and this object variables are
|
||||
// the target. Do the replacement or removals:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.name);
|
||||
PushVariablesRenamingChangesetRoot();
|
||||
RenameVariableAndVisitChild(node.name, node.child.get());
|
||||
PopVariablesRenamingChangesetNode(true);
|
||||
}
|
||||
} else {
|
||||
RenameVariableAndVisitChild(node.name, node.child.get());
|
||||
}
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
objectNameToUseForVariableAccessor = "";
|
||||
|
||||
// TODO Literal expressions could be checked to handle renaming in
|
||||
// `expression` and in `child`.
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
if (node.child) {
|
||||
PushVariablesRenamingChangesetNodeForIgnoredVariables();
|
||||
node.child->Visit(*this);
|
||||
PopVariablesRenamingChangesetNode(true);
|
||||
}
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
void OnVisitIdentifierNode(IdentifierNode &node) override {
|
||||
auto renameVariableAndChild = [this, &node]() {
|
||||
PushVariablesRenamingChangesetRoot();
|
||||
const gd::String oldVariableName = node.identifierName;
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.identifierName);
|
||||
if (!node.childIdentifierName.empty()) {
|
||||
bool hasBeenPushed =
|
||||
PushVariablesRenamingChangesetNodeForVariable(oldVariableName);
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
node.childIdentifierName);
|
||||
PopVariablesRenamingChangesetNode(hasBeenPushed);
|
||||
}
|
||||
PopVariablesRenamingChangesetNode(true);
|
||||
};
|
||||
|
||||
auto& objectsContainersList =
|
||||
projectScopedContainers.GetObjectsContainersList();
|
||||
|
||||
@@ -162,11 +205,12 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
// (and if it's a variable reference or a value does not have any importance
|
||||
// here).
|
||||
|
||||
if (forcedInitialVariablesContainer) {
|
||||
if (forcedVariablesContainer) {
|
||||
// A scope was forced. Honor it: it means this node represents a variable
|
||||
// of the forced variables container.
|
||||
if (forcedInitialVariablesContainer == &targetVariablesContainer) {
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(node.identifierName);
|
||||
if (forcedVariablesContainer == &targetVariablesContainer ||
|
||||
IsTargetingObjectGroup(forcedObjectName)) {
|
||||
renameVariableAndChild();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -174,25 +218,28 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
// Match the potential *new* name of the variable, because refactorings are
|
||||
// done after changes in the variables container.
|
||||
projectScopedContainers.MatchIdentifierWithName<void>(
|
||||
GetPotentialNewName(node.identifierName),
|
||||
node.identifierName,
|
||||
[&]() {
|
||||
// This represents an object.
|
||||
if (objectsContainersList.HasObjectOrGroupVariablesContainer(
|
||||
node.identifierName, targetVariablesContainer)) {
|
||||
node.identifierName, targetVariablesContainer) ||
|
||||
IsTargetingObjectGroup(node.identifierName)) {
|
||||
// The node represents an object variable, and this object variables
|
||||
// are the target. Do the replacement or removals:
|
||||
PushVariablesRenamingChangesetRoot();
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
node.childIdentifierName);
|
||||
PopVariablesRenamingChangesetNode(true);
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
if (&projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(
|
||||
node.identifierName) == &targetVariablesContainer) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
node.identifierName);
|
||||
renameVariableAndChild();
|
||||
}
|
||||
},
|
||||
[&]() {
|
||||
@@ -202,14 +249,7 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
// This is a parameter.
|
||||
},
|
||||
[&]() {
|
||||
// This is something else - potentially a deleted variable.
|
||||
if (projectScopedContainers.GetVariablesContainersList()
|
||||
.HasVariablesContainer(targetVariablesContainer)) {
|
||||
// The node represents a variable, that can come from the target
|
||||
// (because the target is in the scope), replace or remove it:
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
node.identifierName);
|
||||
}
|
||||
// This is something else.
|
||||
});
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {}
|
||||
@@ -231,31 +271,33 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
// force the "scope" at which starts the evalution of variables.
|
||||
if (parameterMetadata && parameterMetadata->GetValueTypeMetadata()
|
||||
.IsLegacyPreScopedVariable()) {
|
||||
const gd::VariablesContainer* oldForcedInitialVariablesContainer =
|
||||
forcedInitialVariablesContainer;
|
||||
const gd::VariablesContainer *oldForcedVariablesContainer =
|
||||
forcedVariablesContainer;
|
||||
const gd::String &oldForcedObjectName = forcedObjectName;
|
||||
|
||||
forcedInitialVariablesContainer = nullptr;
|
||||
forcedVariablesContainer = nullptr;
|
||||
forcedObjectName = "";
|
||||
if (parameterMetadata->GetType() == "globalvar") {
|
||||
forcedInitialVariablesContainer =
|
||||
forcedVariablesContainer =
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetTopMostVariablesContainer();
|
||||
} else if (parameterMetadata->GetType() == "scenevar") {
|
||||
forcedInitialVariablesContainer =
|
||||
forcedVariablesContainer =
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetBottomMostVariablesContainer();
|
||||
} else if (parameterMetadata->GetType() == "objectvar") {
|
||||
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(
|
||||
platform,
|
||||
projectScopedContainers.GetObjectsContainersList(),
|
||||
node.objectName,
|
||||
*node.parameters[parameterIndex].get());
|
||||
forcedInitialVariablesContainer =
|
||||
platform, projectScopedContainers.GetObjectsContainersList(),
|
||||
node.objectName, *node.parameters[parameterIndex].get());
|
||||
forcedVariablesContainer =
|
||||
projectScopedContainers.GetObjectsContainersList()
|
||||
.GetObjectOrGroupVariablesContainer(objectName);
|
||||
forcedObjectName = objectName;
|
||||
}
|
||||
|
||||
node.parameters[parameterIndex]->Visit(*this);
|
||||
forcedInitialVariablesContainer = oldForcedInitialVariablesContainer;
|
||||
forcedVariablesContainer = oldForcedVariablesContainer;
|
||||
forcedObjectName = oldForcedObjectName;
|
||||
} else {
|
||||
// For any other parameter, there is no special treatment being needed.
|
||||
node.parameters[parameterIndex]->Visit(*this);
|
||||
@@ -268,19 +310,28 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
bool hasDoneRenaming;
|
||||
bool removedVariableUsed;
|
||||
|
||||
const gd::String& GetPotentialNewName(const gd::String& oldName) {
|
||||
return oldToNewVariableNames.count(oldName) >= 1
|
||||
? oldToNewVariableNames.find(oldName)->second
|
||||
: oldName;
|
||||
bool IsTargetingObjectGroup(const gd::String &objectGroupName) {
|
||||
return !targetGroupName.empty() && objectGroupName == targetGroupName;
|
||||
}
|
||||
|
||||
bool RenameOrRemoveVariableOfTargetVariableContainer(
|
||||
gd::String& variableName) {
|
||||
const auto *currentVariablesRenamingChangesetNode =
|
||||
GetCurrentVariablesRenamingChangesetNode();
|
||||
if (!currentVariablesRenamingChangesetNode) {
|
||||
return false;
|
||||
}
|
||||
const auto &oldToNewVariableNames =
|
||||
currentVariablesRenamingChangesetNode->oldToNewVariableNames;
|
||||
if (oldToNewVariableNames.count(variableName) >= 1) {
|
||||
variableName = oldToNewVariableNames.find(variableName)->second;
|
||||
hasDoneRenaming = true;
|
||||
return true;
|
||||
} else if (removedVariableNames.count(variableName) >= 1) {
|
||||
} else if (
|
||||
// Only the root variable is checked for removing.
|
||||
currentVariablesRenamingChangesetNode ==
|
||||
&variablesRenamingChangesetRoot &&
|
||||
removedVariableNames.count(variableName) >= 1) {
|
||||
removedVariableUsed = true;
|
||||
return true;
|
||||
}
|
||||
@@ -288,24 +339,88 @@ class GD_CORE_API ExpressionVariableReplacer
|
||||
return false; // Nothing was changed or done.
|
||||
}
|
||||
|
||||
void RenameVariableAndVisitChild(gd::String &variableName,
|
||||
ExpressionNode *childNode) {
|
||||
// `variableName` is modified by
|
||||
// `RenameOrRemoveVariableOfTargetVariableContainer`.
|
||||
const gd::String oldVariableName = variableName;
|
||||
RenameOrRemoveVariableOfTargetVariableContainer(variableName);
|
||||
if (childNode) {
|
||||
bool hasBeenPushed =
|
||||
PushVariablesRenamingChangesetNodeForVariable(oldVariableName);
|
||||
childNode->Visit(*this);
|
||||
PopVariablesRenamingChangesetNode(hasBeenPushed);
|
||||
}
|
||||
}
|
||||
|
||||
void PushVariablesRenamingChangesetRoot() {
|
||||
variablesRenamingChangesetNodeStack.push_back(&variablesRenamingChangesetRoot);
|
||||
}
|
||||
|
||||
void PushVariablesRenamingChangesetNodeForIgnoredVariables() {
|
||||
variablesRenamingChangesetNodeStack.push_back(nullptr);
|
||||
}
|
||||
|
||||
const gd::VariablesRenamingChangesetNode *GetCurrentVariablesRenamingChangesetNode() {
|
||||
return variablesRenamingChangesetNodeStack.size() == 0 ?
|
||||
&variablesRenamingChangesetRoot :
|
||||
variablesRenamingChangesetNodeStack
|
||||
[variablesRenamingChangesetNodeStack.size() - 1];
|
||||
}
|
||||
|
||||
bool PushVariablesRenamingChangesetNodeForVariable(const gd::String& variableName) {
|
||||
const auto *currentVariablesRenamingChangesetNode = GetCurrentVariablesRenamingChangesetNode();
|
||||
if (!currentVariablesRenamingChangesetNode) {
|
||||
// There were already no more change on a parent.
|
||||
return false;
|
||||
}
|
||||
const auto &childVariablesRenamingChangesetNodeItr =
|
||||
currentVariablesRenamingChangesetNode->modifiedVariables.find(
|
||||
variableName);
|
||||
if (childVariablesRenamingChangesetNodeItr ==
|
||||
currentVariablesRenamingChangesetNode->modifiedVariables.end()) {
|
||||
// There is no more change on the current variable child.
|
||||
variablesRenamingChangesetNodeStack.push_back(nullptr);
|
||||
}
|
||||
else {
|
||||
variablesRenamingChangesetNodeStack.push_back(
|
||||
childVariablesRenamingChangesetNodeItr->second.get());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PopVariablesRenamingChangesetNode(bool hasBeenPushed) {
|
||||
if (hasBeenPushed) {
|
||||
variablesRenamingChangesetNodeStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
// Scope:
|
||||
const gd::Platform& platform;
|
||||
const gd::ProjectScopedContainers& projectScopedContainers;
|
||||
const gd::VariablesContainer* forcedInitialVariablesContainer;
|
||||
const gd::VariablesContainer* forcedVariablesContainer;
|
||||
gd::String forcedObjectName;
|
||||
|
||||
// Renaming or removing to do:
|
||||
const gd::VariablesContainer& targetVariablesContainer;
|
||||
const std::unordered_map<gd::String, gd::String>& oldToNewVariableNames;
|
||||
/**
|
||||
* Groups don't have VariablesContainer, so `targetVariablesContainer` will be
|
||||
* pointing to `nullVariablesContainer` and the group name is use instead to
|
||||
* check which variable accesses to modify in expressions.
|
||||
*/
|
||||
const gd::String& targetGroupName;
|
||||
const VariablesRenamingChangesetNode &variablesRenamingChangesetRoot;
|
||||
const std::unordered_set<gd::String>& removedVariableNames;
|
||||
|
||||
gd::String objectNameToUseForVariableAccessor;
|
||||
std::vector<const VariablesRenamingChangesetNode*> variablesRenamingChangesetNodeStack;
|
||||
};
|
||||
|
||||
const gd::VariablesContainer*
|
||||
EventsVariableReplacer::FindForcedVariablesContainerIfAny(
|
||||
const gd::String& type, const gd::String& lastObjectName) {
|
||||
// Handle legacy pre-scoped variable parameters: in this case, we
|
||||
// force the "scope" at which starts the evalution of variables.
|
||||
// force the "scope" at which starts the evaluation of variables.
|
||||
if (type == "objectvar") {
|
||||
return GetProjectScopedContainers()
|
||||
.GetObjectsContainersList()
|
||||
@@ -350,9 +465,11 @@ bool EventsVariableReplacer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
if (node) {
|
||||
ExpressionVariableReplacer renamer(platform,
|
||||
GetProjectScopedContainers(),
|
||||
variablesRenamingChangesetRoot,
|
||||
removedVariableNames,
|
||||
targetVariablesContainer,
|
||||
oldToNewVariableNames,
|
||||
removedVariableNames);
|
||||
targetGroupName,
|
||||
type == "objectvar" ? lastObjectName : "");
|
||||
renamer.SetForcedInitialVariablesContainer(
|
||||
FindForcedVariablesContainerIfAny(type, lastObjectName));
|
||||
node->Visit(renamer);
|
||||
@@ -382,9 +499,11 @@ bool EventsVariableReplacer::DoVisitEventExpression(
|
||||
if (node) {
|
||||
ExpressionVariableReplacer renamer(platform,
|
||||
GetProjectScopedContainers(),
|
||||
variablesRenamingChangesetRoot,
|
||||
removedVariableNames,
|
||||
targetVariablesContainer,
|
||||
oldToNewVariableNames,
|
||||
removedVariableNames);
|
||||
targetGroupName,
|
||||
"");
|
||||
renamer.SetForcedInitialVariablesContainer(
|
||||
FindForcedVariablesContainerIfAny(type, ""));
|
||||
node->Visit(renamer);
|
||||
|
@@ -4,6 +4,7 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
@@ -12,11 +13,13 @@
|
||||
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class VariablesContainer;
|
||||
class EventsList;
|
||||
class Platform;
|
||||
struct VariablesRenamingChangesetNode;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -32,13 +35,24 @@ class GD_CORE_API EventsVariableReplacer
|
||||
public:
|
||||
EventsVariableReplacer(
|
||||
const gd::Platform &platform_,
|
||||
const gd::VariablesContainer &targetVariablesContainer_,
|
||||
const std::unordered_map<gd::String, gd::String> &oldToNewVariableNames_,
|
||||
const std::unordered_set<gd::String> &removedVariableNames_)
|
||||
const VariablesRenamingChangesetNode &variablesRenamingChangesetRoot_,
|
||||
const std::unordered_set<gd::String> &removedVariableNames_,
|
||||
const gd::VariablesContainer &targetVariablesContainer_)
|
||||
: platform(platform_),
|
||||
variablesRenamingChangesetRoot(variablesRenamingChangesetRoot_),
|
||||
removedVariableNames(removedVariableNames_),
|
||||
targetVariablesContainer(targetVariablesContainer_),
|
||||
oldToNewVariableNames(oldToNewVariableNames_),
|
||||
removedVariableNames(removedVariableNames_){};
|
||||
targetGroupName("") {};
|
||||
EventsVariableReplacer(
|
||||
const gd::Platform &platform_,
|
||||
const VariablesRenamingChangesetNode &variablesRenamingChangesetRoot_,
|
||||
const std::unordered_set<gd::String> &removedVariableNames_,
|
||||
const gd::String &targetGroupName_)
|
||||
: platform(platform_),
|
||||
variablesRenamingChangesetRoot(variablesRenamingChangesetRoot_),
|
||||
removedVariableNames(removedVariableNames_),
|
||||
targetVariablesContainer(nullVariablesContainer),
|
||||
targetGroupName(targetGroupName_) {};
|
||||
virtual ~EventsVariableReplacer();
|
||||
|
||||
private:
|
||||
@@ -52,9 +66,16 @@ class GD_CORE_API EventsVariableReplacer
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::VariablesContainer &targetVariablesContainer;
|
||||
gd::String objectName;
|
||||
const std::unordered_map<gd::String, gd::String> &oldToNewVariableNames;
|
||||
/**
|
||||
* Groups don't have VariablesContainer, so `targetVariablesContainer` will be
|
||||
* pointing to `nullVariablesContainer` and the group name is use instead to
|
||||
* check which variable accesses to modify in expressions.
|
||||
*/
|
||||
const gd::String targetGroupName;
|
||||
const VariablesRenamingChangesetNode &variablesRenamingChangesetRoot;
|
||||
const std::unordered_set<gd::String> &removedVariableNames;
|
||||
|
||||
static VariablesContainer nullVariablesContainer;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -93,9 +93,11 @@ class GD_CORE_API VariableFinderExpressionNodeWorker
|
||||
}
|
||||
|
||||
size_t parameterIndex = 0;
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0); metadataIndex < metadata.parameters.size()
|
||||
&& parameterIndex < node.parameters.size(); ++metadataIndex) {
|
||||
auto& parameterMetadata = metadata.parameters[metadataIndex];
|
||||
for (size_t metadataIndex = (isObjectFunction ? 1 : 0);
|
||||
metadataIndex < metadata.GetParameters().GetParametersCount() &&
|
||||
parameterIndex < node.parameters.size();
|
||||
++metadataIndex) {
|
||||
auto& parameterMetadata = metadata.GetParameters().GetParameter(metadataIndex);
|
||||
if (parameterMetadata.IsCodeOnly()) {
|
||||
continue;
|
||||
}
|
||||
@@ -150,18 +152,18 @@ class GD_CORE_API VariableFinderEventWorker
|
||||
platform, instruction.GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
|
||||
// The parameter has the searched type...
|
||||
if (instrInfos.parameters[pNb].GetType() == parameterType) {
|
||||
if (instrInfos.parameters.GetParameter(pNb).GetType() == parameterType) {
|
||||
//...remember the value of the parameter.
|
||||
if (objectName.empty() || lastObjectParameter == objectName)
|
||||
results.insert(instruction.GetParameter(pNb).GetPlainString());
|
||||
}
|
||||
// Search in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].GetType()) ||
|
||||
"number", instrInfos.parameters.GetParameter(pNb).GetType()) ||
|
||||
ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].GetType())) {
|
||||
"string", instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
auto node = instruction.GetParameter(pNb).GetRootNode();
|
||||
|
||||
VariableFinderExpressionNodeWorker searcher(
|
||||
@@ -174,7 +176,7 @@ class GD_CORE_API VariableFinderEventWorker
|
||||
}
|
||||
// Remember the value of the last "object" parameter.
|
||||
else if (gd::ParameterMetadata::IsObject(
|
||||
instrInfos.parameters[pNb].GetType())) {
|
||||
instrInfos.parameters.GetParameter(pNb).GetType())) {
|
||||
lastObjectParameter =
|
||||
instruction.GetParameter(pNb).GetPlainString();
|
||||
}
|
||||
@@ -229,7 +231,7 @@ std::set<gd::String> EventsVariablesFinder::FindAllObjectVariables(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::Object& object) {
|
||||
const gd::String& objectName) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
@@ -238,7 +240,7 @@ std::set<gd::String> EventsVariablesFinder::FindAllObjectVariables(
|
||||
project,
|
||||
layout,
|
||||
"objectvar",
|
||||
object.GetName());
|
||||
objectName);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
@@ -63,14 +63,14 @@ class EventsVariablesFinder {
|
||||
*
|
||||
* \param project The project
|
||||
* \param layout The layout to use.
|
||||
* \param object The object to be scanned
|
||||
* \param objectName The name of the object to be scanned
|
||||
* \return A std::set containing the names of all object variables used.
|
||||
*/
|
||||
static std::set<gd::String> FindAllObjectVariables(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::Object& object);
|
||||
const gd::String& objectName);
|
||||
|
||||
private:
|
||||
|
||||
|
@@ -3,8 +3,7 @@
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EXPRESSIONAUTOCOMPLETIONPROVIDER_H
|
||||
#define GDCORE_EXPRESSIONAUTOCOMPLETIONPROVIDER_H
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
@@ -20,7 +19,7 @@
|
||||
#include "GDCore/IDE/Events/ExpressionNodeLocationFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariableParentFinder.h"
|
||||
#include "GDCore/IDE/Events/ExpressionVariablePathFinder.h"
|
||||
#include "GDCore/Project/ProjectScopedContainers.h"
|
||||
#include "GDCore/Project/Variable.h"
|
||||
|
||||
@@ -147,6 +146,19 @@ struct GD_CORE_API ExpressionCompletionDescription {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the scope of the variable, for a variable completion.
|
||||
*/
|
||||
gd::VariablesContainer::SourceType GetVariableScope() const {
|
||||
return variableScope;
|
||||
}
|
||||
|
||||
ExpressionCompletionDescription &
|
||||
SetVariableScope(gd::VariablesContainer::SourceType variableScope_) {
|
||||
variableScope = variableScope_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the prefix that must be completed.
|
||||
*/
|
||||
@@ -315,6 +327,7 @@ struct GD_CORE_API ExpressionCompletionDescription {
|
||||
size_t replacementEndPosition_)
|
||||
: completionKind(completionKind_),
|
||||
variableType(gd::Variable::Number),
|
||||
variableScope(gd::VariablesContainer::Unknown),
|
||||
replacementStartPosition(replacementStartPosition_),
|
||||
replacementEndPosition(replacementEndPosition_),
|
||||
isExact(false),
|
||||
@@ -324,18 +337,19 @@ struct GD_CORE_API ExpressionCompletionDescription {
|
||||
|
||||
private:
|
||||
CompletionKind completionKind;
|
||||
gd::Variable::Type variableType;
|
||||
gd::Variable::Type variableType = gd::Variable::Unknown;
|
||||
gd::VariablesContainer::SourceType variableScope = gd::VariablesContainer::Unknown;
|
||||
gd::String type;
|
||||
gd::String prefix;
|
||||
gd::String completion;
|
||||
size_t replacementStartPosition;
|
||||
size_t replacementEndPosition;
|
||||
size_t replacementStartPosition = 0;
|
||||
size_t replacementEndPosition = 0;
|
||||
gd::String objectName;
|
||||
gd::String behaviorName;
|
||||
bool isExact;
|
||||
bool isLastParameter;
|
||||
const gd::ParameterMetadata* parameterMetadata;
|
||||
const gd::ObjectConfiguration* objectConfiguration;
|
||||
bool isExact = false;
|
||||
bool isLastParameter = false;
|
||||
const gd::ParameterMetadata* parameterMetadata = &badParameterMetadata;
|
||||
const gd::ObjectConfiguration* objectConfiguration = &badObjectConfiguration;
|
||||
|
||||
static const gd::ParameterMetadata badParameterMetadata;
|
||||
static const gd::ObjectConfiguration badObjectConfiguration;
|
||||
@@ -449,11 +463,15 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
MetadataProvider::GetFunctionCallMetadata(
|
||||
platform, objectsContainersList, *functionCall);
|
||||
|
||||
const gd::ParameterMetadata* parameterMetadata = nullptr;
|
||||
while (metadataParameterIndex < metadata.parameters.size()) {
|
||||
if (!metadata.parameters[metadataParameterIndex].IsCodeOnly()) {
|
||||
const gd::ParameterMetadata *parameterMetadata = nullptr;
|
||||
while (metadataParameterIndex <
|
||||
metadata.GetParameters().GetParametersCount()) {
|
||||
if (!metadata.GetParameters()
|
||||
.GetParameter(metadataParameterIndex)
|
||||
.IsCodeOnly()) {
|
||||
if (visibleParameterIndex == parameterIndex) {
|
||||
parameterMetadata = &metadata.parameters[metadataParameterIndex];
|
||||
parameterMetadata =
|
||||
&metadata.GetParameters().GetParameter(metadataParameterIndex);
|
||||
}
|
||||
visibleParameterIndex++;
|
||||
}
|
||||
@@ -525,7 +543,7 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
VariableAndItsParent variableAndItsParent =
|
||||
gd::ExpressionVariableParentFinder::GetLastParentOfNode(
|
||||
gd::ExpressionVariablePathFinder::GetLastParentOfNode(
|
||||
platform, projectScopedContainers, node);
|
||||
|
||||
// If no child, we're at the end of a variable (like `GrandChild` in
|
||||
@@ -666,7 +684,7 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
[&]() {
|
||||
// This is a variable.
|
||||
VariableAndItsParent variableAndItsParent =
|
||||
gd::ExpressionVariableParentFinder::GetLastParentOfNode(
|
||||
gd::ExpressionVariablePathFinder::GetLastParentOfNode(
|
||||
platform, projectScopedContainers, node);
|
||||
|
||||
AddCompletionsForChildrenVariablesOf(
|
||||
@@ -933,6 +951,7 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
location.GetEndPosition());
|
||||
description.SetCompletion(variableName);
|
||||
description.SetVariableType(variable.GetType());
|
||||
description.SetVariableScope(variablesContainer.GetSourceType());
|
||||
completions.push_back(description);
|
||||
|
||||
if (eagerlyCompleteIfExactMatch && variableName == search) {
|
||||
@@ -958,6 +977,7 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
location.GetEndPosition());
|
||||
description.SetCompletion(variableName);
|
||||
description.SetVariableType(variable.GetType());
|
||||
description.SetVariableScope(gd::VariablesContainer::Object);
|
||||
completions.push_back(description);
|
||||
|
||||
if (eagerlyCompleteIfExactMatch && variableName == search) {
|
||||
@@ -1012,6 +1032,10 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
location.GetEndPosition());
|
||||
description.SetCompletion(variableName);
|
||||
description.SetVariableType(variable.GetType());
|
||||
description.SetVariableScope(
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(variableName)
|
||||
.GetSourceType());
|
||||
completions.push_back(description);
|
||||
|
||||
if (eagerlyCompleteIfExactMatch && variableName == search) {
|
||||
@@ -1042,8 +1066,8 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
bool eagerlyCompleteIfExactMatch = false) {
|
||||
projectScopedContainers.ForEachIdentifierMatchingSearch(
|
||||
search,
|
||||
[&](const gd::String& objectName,
|
||||
const ObjectConfiguration* objectConfiguration) {
|
||||
[&](const gd::String &objectName,
|
||||
const ObjectConfiguration *objectConfiguration) {
|
||||
ExpressionCompletionDescription description(
|
||||
ExpressionCompletionDescription::Object,
|
||||
location.GetStartPosition(),
|
||||
@@ -1053,13 +1077,17 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
description.SetType(type);
|
||||
completions.push_back(description);
|
||||
},
|
||||
[&](const gd::String& variableName, const gd::Variable& variable) {
|
||||
[&](const gd::String &variableName, const gd::Variable &variable) {
|
||||
ExpressionCompletionDescription description(
|
||||
ExpressionCompletionDescription::Variable,
|
||||
location.GetStartPosition(),
|
||||
location.GetEndPosition());
|
||||
description.SetCompletion(variableName);
|
||||
description.SetVariableType(variable.GetType());
|
||||
description.SetVariableScope(
|
||||
projectScopedContainers.GetVariablesContainersList()
|
||||
.GetVariablesContainerFromVariableName(variableName)
|
||||
.GetSourceType());
|
||||
completions.push_back(description);
|
||||
|
||||
if (eagerlyCompleteIfExactMatch && variableName == search) {
|
||||
@@ -1067,23 +1095,29 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
variable, variableName, location);
|
||||
}
|
||||
},
|
||||
[&](const gd::NamedPropertyDescriptor& property) {
|
||||
ExpressionCompletionDescription description(
|
||||
ExpressionCompletionDescription::Property,
|
||||
location.GetStartPosition(),
|
||||
location.GetEndPosition());
|
||||
description.SetCompletion(property.GetName());
|
||||
description.SetType(property.GetType());
|
||||
completions.push_back(description);
|
||||
[&](const gd::NamedPropertyDescriptor &property) {
|
||||
auto propertyType = gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
|
||||
property.GetType());
|
||||
if (gd::ValueTypeMetadata::IsTypeValue("number", propertyType) ||
|
||||
gd::ValueTypeMetadata::IsTypeValue("string", propertyType)) {
|
||||
ExpressionCompletionDescription description(
|
||||
ExpressionCompletionDescription::Property,
|
||||
location.GetStartPosition(), location.GetEndPosition());
|
||||
description.SetCompletion(property.GetName());
|
||||
description.SetType(property.GetType());
|
||||
completions.push_back(description);
|
||||
}
|
||||
},
|
||||
[&](const gd::ParameterMetadata& parameter) {
|
||||
ExpressionCompletionDescription description(
|
||||
ExpressionCompletionDescription::Parameter,
|
||||
location.GetStartPosition(),
|
||||
location.GetEndPosition());
|
||||
description.SetCompletion(parameter.GetName());
|
||||
description.SetType(parameter.GetType());
|
||||
completions.push_back(description);
|
||||
[&](const gd::ParameterMetadata ¶meter) {
|
||||
if (parameter.GetValueTypeMetadata().IsNumber() ||
|
||||
parameter.GetValueTypeMetadata().IsString()) {
|
||||
ExpressionCompletionDescription description(
|
||||
ExpressionCompletionDescription::Parameter,
|
||||
location.GetStartPosition(), location.GetEndPosition());
|
||||
description.SetCompletion(parameter.GetName());
|
||||
description.SetType(parameter.GetType());
|
||||
completions.push_back(description);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1113,5 +1147,3 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EXPRESSIONAUTOCOMPLETIONPROVIDER_H
|
||||
|
@@ -33,8 +33,10 @@ class GD_CORE_API ExpressionNodeLocationFinder
|
||||
* \brief Initialize the finder to search at the specified position.
|
||||
*/
|
||||
ExpressionNodeLocationFinder(size_t searchedPosition_)
|
||||
: searchedPosition(searchedPosition_), foundNode(nullptr){};
|
||||
virtual ~ExpressionNodeLocationFinder(){};
|
||||
: searchedPosition(searchedPosition_),
|
||||
foundNode(nullptr),
|
||||
parentNode(nullptr) {};
|
||||
virtual ~ExpressionNodeLocationFinder() {};
|
||||
|
||||
/**
|
||||
* \brief Helper function to find the deepest node at the search position, if
|
||||
|
@@ -72,7 +72,7 @@ class GD_CORE_API ExpressionTypeFinder : public ExpressionParser2NodeWorker {
|
||||
child(nullptr) {};
|
||||
|
||||
const gd::String &GetType() {
|
||||
return gd::ParameterMetadata::GetExpressionValueType(type);
|
||||
return gd::ValueTypeMetadata::GetExpressionPrimitiveValueType(type);
|
||||
};
|
||||
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user