Compare commits
232 Commits
v5.0.0-bet
...
feature/ac
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8811ed7046 | ||
![]() |
137a23b86a | ||
![]() |
3dae2c50e6 | ||
![]() |
e288414684 | ||
![]() |
0d965fc23c | ||
![]() |
728188114e | ||
![]() |
72a61be8ec | ||
![]() |
3e822e4ef0 | ||
![]() |
29f7501dcf | ||
![]() |
2544c71f30 | ||
![]() |
6c629f6d68 | ||
![]() |
fa022747e2 | ||
![]() |
d0a2491acd | ||
![]() |
816513ad85 | ||
![]() |
b36cb17e4c | ||
![]() |
4fb27b6135 | ||
![]() |
96674f36b4 | ||
![]() |
c31de12048 | ||
![]() |
aaeaa8338b | ||
![]() |
f5827d4a48 | ||
![]() |
afe9d18b03 | ||
![]() |
175e12b25b | ||
![]() |
c4bb03d360 | ||
![]() |
acc34e8bda | ||
![]() |
edecc01e14 | ||
![]() |
808721a29f | ||
![]() |
b57316b4f4 | ||
![]() |
8d57aa5353 | ||
![]() |
2ce1c56005 | ||
![]() |
fc7c092cfb | ||
![]() |
e100b6f2c3 | ||
![]() |
ac2867f1a7 | ||
![]() |
3166daf041 | ||
![]() |
0c2d58e70b | ||
![]() |
af9ab09b3b | ||
![]() |
0c8560e60d | ||
![]() |
5a44fd8b9f | ||
![]() |
20ce83ccfe | ||
![]() |
0cc4543948 | ||
![]() |
5ff045d74a | ||
![]() |
0fdf123f8d | ||
![]() |
ec0b934557 | ||
![]() |
7fa1e50c17 | ||
![]() |
9a7c5ead3a | ||
![]() |
72282d4e6d | ||
![]() |
be950a7779 | ||
![]() |
d37ef30041 | ||
![]() |
53360bc189 | ||
![]() |
bfd6712a93 | ||
![]() |
6902f1495d | ||
![]() |
156fd3bc19 | ||
![]() |
b1303b4ad6 | ||
![]() |
2fa3bb7b1b | ||
![]() |
fca6f7627a | ||
![]() |
e7bca87063 | ||
![]() |
a7afaa1241 | ||
![]() |
e98f25255c | ||
![]() |
b4bd225f78 | ||
![]() |
2c0253fafa | ||
![]() |
c8201949df | ||
![]() |
0426bcb2a6 | ||
![]() |
9025d055a0 | ||
![]() |
bef6f04f89 | ||
![]() |
800d4f7098 | ||
![]() |
e8d9d4fa4b | ||
![]() |
c9e2d3f4e0 | ||
![]() |
43230003b8 | ||
![]() |
725069026c | ||
![]() |
7729137a72 | ||
![]() |
3c81b3decb | ||
![]() |
460946e8f4 | ||
![]() |
6908ab9b3f | ||
![]() |
0286f97145 | ||
![]() |
a40ba2551d | ||
![]() |
02c65bcf66 | ||
![]() |
ecf5401626 | ||
![]() |
8866719ef0 | ||
![]() |
6a02f1b3c5 | ||
![]() |
02d7c84e17 | ||
![]() |
0a9fb45841 | ||
![]() |
6ddace1ec4 | ||
![]() |
fc4107107b | ||
![]() |
30da9e6556 | ||
![]() |
939de1e928 | ||
![]() |
c8b3572cd8 | ||
![]() |
d350243b2e | ||
![]() |
ea68c31c07 | ||
![]() |
0dd837d127 | ||
![]() |
b5c019ae6b | ||
![]() |
b4337d3746 | ||
![]() |
afc0a86903 | ||
![]() |
2e6821d231 | ||
![]() |
ea8a827937 | ||
![]() |
bc352424e1 | ||
![]() |
8e83f1581e | ||
![]() |
ba593b46dd | ||
![]() |
d8cfead994 | ||
![]() |
cf7db809ac | ||
![]() |
26dd33854f | ||
![]() |
1ed530d946 | ||
![]() |
b85008c269 | ||
![]() |
08ddb6e519 | ||
![]() |
d37c55e86f | ||
![]() |
e2c7e1a145 | ||
![]() |
6ebf40647e | ||
![]() |
ed42f1c54a | ||
![]() |
c94097acfb | ||
![]() |
9c6c8564fa | ||
![]() |
4b33373296 | ||
![]() |
7ce11c5252 | ||
![]() |
0d864ce6a7 | ||
![]() |
a6360152cd | ||
![]() |
827fdbf05a | ||
![]() |
a4c372d945 | ||
![]() |
93708cb2f3 | ||
![]() |
3035bc9386 | ||
![]() |
4c789967c3 | ||
![]() |
75797f2c41 | ||
![]() |
571686f180 | ||
![]() |
df68978adc | ||
![]() |
7a87fd9924 | ||
![]() |
8d1502cb20 | ||
![]() |
34b5038bd5 | ||
![]() |
a9e1120f00 | ||
![]() |
b14238c692 | ||
![]() |
dfe4a75fbd | ||
![]() |
4fd88072e9 | ||
![]() |
f2e6f19c34 | ||
![]() |
66029c62ed | ||
![]() |
43d78a74bd | ||
![]() |
0ec6ebad07 | ||
![]() |
8743672038 | ||
![]() |
3fd032d898 | ||
![]() |
2b40f57189 | ||
![]() |
fc3f8a945b | ||
![]() |
ed24871130 | ||
![]() |
e416fb0586 | ||
![]() |
5778131deb | ||
![]() |
8e81f78596 | ||
![]() |
1abdcaf0c0 | ||
![]() |
4af867ba3a | ||
![]() |
f75c2297d7 | ||
![]() |
72c4f88936 | ||
![]() |
34bcfdfee7 | ||
![]() |
7e78d4de5a | ||
![]() |
971b7a2322 | ||
![]() |
9a95aabc87 | ||
![]() |
53dcfa1cbf | ||
![]() |
0ed7ccfb72 | ||
![]() |
0fcd5cbbb9 | ||
![]() |
fb6b959636 | ||
![]() |
1d7f0f9f94 | ||
![]() |
4be527c18a | ||
![]() |
5e770d460d | ||
![]() |
73daf0e940 | ||
![]() |
58d88835c5 | ||
![]() |
0aa66837d4 | ||
![]() |
11349086c7 | ||
![]() |
d3d636744e | ||
![]() |
5baf2d9735 | ||
![]() |
d0daf0b5a8 | ||
![]() |
21841e0bce | ||
![]() |
417ab2ff3d | ||
![]() |
caee5fdcc7 | ||
![]() |
1fbd58fa75 | ||
![]() |
389deadac5 | ||
![]() |
7d52165a82 | ||
![]() |
5e3e7e25fc | ||
![]() |
56afb11e2c | ||
![]() |
b6a0cfef32 | ||
![]() |
37c3a6d38a | ||
![]() |
30f830589c | ||
![]() |
5f8546c3b9 | ||
![]() |
4c2997b2d9 | ||
![]() |
2338b5bfd6 | ||
![]() |
8a07e9b6c5 | ||
![]() |
61303c7cf9 | ||
![]() |
43eaf30750 | ||
![]() |
db278485fc | ||
![]() |
3f5b42dc90 | ||
![]() |
cd285b5676 | ||
![]() |
509ac8966e | ||
![]() |
bda2a10b5f | ||
![]() |
841e1a66b6 | ||
![]() |
3fc588b6e3 | ||
![]() |
50ebf6e5a2 | ||
![]() |
cbe33d2bd1 | ||
![]() |
8c8c297adb | ||
![]() |
a8d927994b | ||
![]() |
1fb3231f98 | ||
![]() |
70a58f1bd4 | ||
![]() |
302bcb718f | ||
![]() |
857c706f48 | ||
![]() |
5b5f91c1f9 | ||
![]() |
0652e19190 | ||
![]() |
5feb4caa31 | ||
![]() |
1cd5519b93 | ||
![]() |
96761c461d | ||
![]() |
1a82663968 | ||
![]() |
9111b56eb3 | ||
![]() |
d7f22bcf26 | ||
![]() |
b9b0ed812d | ||
![]() |
6734644df4 | ||
![]() |
ddeff6bfae | ||
![]() |
8f10eac512 | ||
![]() |
162524f779 | ||
![]() |
1da347b08b | ||
![]() |
01b7f81507 | ||
![]() |
5a3d2cc2b9 | ||
![]() |
cb659eee6d | ||
![]() |
0f24410a2e | ||
![]() |
a31ea1475d | ||
![]() |
0cecf685ca | ||
![]() |
f39af51fda | ||
![]() |
704eaacc7e | ||
![]() |
1f7bec0ff1 | ||
![]() |
69ffa45ea9 | ||
![]() |
2558052a61 | ||
![]() |
abf40200cb | ||
![]() |
2fd4459364 | ||
![]() |
2ed9088b58 | ||
![]() |
f69b9132ad | ||
![]() |
fb7d3d589d | ||
![]() |
87acba5105 | ||
![]() |
2d314ff51b | ||
![]() |
5054678193 | ||
![]() |
aaf9d318a9 | ||
![]() |
cc92445d4c | ||
![]() |
1649591442 | ||
![]() |
77faff3919 | ||
![]() |
873280d818 | ||
![]() |
238b6a2a09 |
1
.gitignore
vendored
@@ -9,6 +9,7 @@
|
||||
/ExtLibs/*.7z
|
||||
/scripts/Repository keys
|
||||
/scripts/logs/*.txt
|
||||
/scripts/gdcore-gdcpp-gdjs-extensions-messages.pot
|
||||
/Binaries/.build*
|
||||
/Binaries/.embuild*
|
||||
/Binaries/build*
|
||||
|
@@ -69,6 +69,7 @@ script:
|
||||
- cd newIDE/app
|
||||
- npm test
|
||||
- npm run flow
|
||||
- npm run check-format
|
||||
- cd ../..
|
||||
#GDJS game engine tests, disabled on Travis CI because ChromeHeadless can't be started.
|
||||
#See them running on Semaphore-CI instead: https://semaphoreci.com/4ian/gd
|
||||
|
5
.vscode/settings.json
vendored
@@ -77,7 +77,9 @@
|
||||
"cstdint": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"mutex": "cpp",
|
||||
"__hash": "cpp"
|
||||
"__hash": "cpp",
|
||||
"__debug": "cpp",
|
||||
"__threading_support": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"Binaries/*build*": true,
|
||||
@@ -97,6 +99,7 @@
|
||||
// Support for Flowtype:
|
||||
"javascript.validate.enable": false,
|
||||
"flow.useNPMPackagedFlow": true,
|
||||
"flow.useLSP": false, // As we are in a monorepo, see https://github.com/flowtype/flow-for-vscode/issues/301
|
||||
|
||||
// Clang format styling (duplicated in scripts/CMakeClangUtils.txt)
|
||||
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}"
|
||||
|
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 722 B |
After Width: | Height: | Size: 935 B |
@@ -0,0 +1,194 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="filesystem_create_folder.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/create_folder16.png"
|
||||
inkscape:export-xdpi="45"
|
||||
inkscape:export-ydpi="45">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.919596"
|
||||
inkscape:cx="-14.99721"
|
||||
inkscape:cy="14.343353"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<path
|
||||
style="opacity:1;fill:#80bbdb;fill-opacity:1;fill-rule:nonzero;stroke:#548dad;stroke-width:0.97142506;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10.44448,1025.9309 c 0.65513,0 1.18165,0.5595 1.18165,1.2556 l 0,1.2733 16.256617,0 c 1.376723,0 2.484776,1.1774 2.484776,2.6403 l 0,13.0531 c 0,1.4629 -1.108053,2.6403 -2.484776,2.6403 l -23.7654964,0 c -1.3767228,0 -2.4847757,-1.1774 -2.4847757,-2.6403 l 0,-10.7551 0,-2.298 0,-3.9136 c 0,-0.6961 0.5265186,-1.2556 1.1816486,-1.2556 z"
|
||||
id="rect4901"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sscssssssccsss" />
|
||||
<path
|
||||
style="opacity:1;fill:#5fa1c7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 2.1084458,1031.4784 0,0.7321 0,11.4039 c 0,1.5514 1.0713447,2.7998 2.4024592,2.7998 l 22.978188,0 c 1.331114,0 2.40246,-1.2484 2.40246,-2.7998 l 0,-12.136 -27.7831072,0 z"
|
||||
id="path4919"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="opacity:1;fill:#d9db30;fill-opacity:1;fill-rule:nonzero;stroke:#bec021;stroke-width:1.38540256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4939"
|
||||
sodipodi:sides="5"
|
||||
sodipodi:cx="24.252151"
|
||||
sodipodi:cy="1028.8562"
|
||||
sodipodi:r1="7.8899426"
|
||||
sodipodi:r2="3.9449718"
|
||||
sodipodi:arg1="0.79249024"
|
||||
sodipodi:arg2="1.4208088"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 29.791477,1034.4747 -4.949845,-1.7178 -4.221206,3.1037 0.104117,-5.2384 -4.256247,-3.0555 5.014193,-1.5197 1.590701,-4.9922 2.994825,4.2992 5.239353,-0.03 -3.163289,4.1767 z"
|
||||
inkscape:transform-center-x="0.36431952"
|
||||
inkscape:transform-center-y="-0.39846334" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 545 B |
After Width: | Height: | Size: 771 B |
After Width: | Height: | Size: 944 B |
@@ -0,0 +1,206 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="filesystem_file_delete.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/filesystem_file_delete32.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="56.026486"
|
||||
inkscape:cy="-2.8092946"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px"
|
||||
inkscape:snap-grids="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<g
|
||||
id="g4225"
|
||||
transform="matrix(1.1128183,0,0,1.1128183,55.344213,-128.05315)">
|
||||
<path
|
||||
id="rect4177"
|
||||
transform="translate(-9.5367432e-7,1020.3622)"
|
||||
d="m -43.681641,13.882812 c -0.563451,0 -1.017578,0.452174 -1.017578,1.015626 l 0,22.210937 c 0,0.563451 0.454127,1.015625 1.017578,1.015625 l 16.652344,0 c 0.563451,0 1.017578,-0.452174 1.017578,-1.015625 l 0,-15.246094 -6.05664,-7.980469 -11.613282,0 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4218"
|
||||
d="m -31.837816,1034.2449 0,7.043 c 0,0.3498 0.283047,0.6328 0.632812,0.6328 l 5.19336,0 -5.826172,-7.6758 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<rect
|
||||
style="opacity:1;fill:#a6a6a6;fill-opacity:1;fill-rule:nonzero;stroke:#5a5a5a;stroke-width:0.99999934;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4158"
|
||||
width="8.9121208"
|
||||
height="8.7162371"
|
||||
x="10.293939"
|
||||
y="1038.0229" />
|
||||
<rect
|
||||
style="opacity:1;fill:#a6a6a6;fill-opacity:1;fill-rule:nonzero;stroke:#5a5a5a;stroke-width:0.99999934;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4160"
|
||||
width="8.9631233"
|
||||
height="2.6948419"
|
||||
x="-516.44586"
|
||||
y="897.6803"
|
||||
inkscape:transform-center-x="-3.1829089"
|
||||
inkscape:transform-center-y="-3.4427076"
|
||||
transform="matrix(0.86246101,-0.50612351,0.50612351,0.86246101,0,0)" />
|
||||
<rect
|
||||
y="1044.6921"
|
||||
x="8.1238213"
|
||||
height="1.985044"
|
||||
width="2.0916421"
|
||||
id="rect4162"
|
||||
style="opacity:1;fill:#a6a6a6;fill-opacity:1;fill-rule:nonzero;stroke:#5a5a5a;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 556 B |
After Width: | Height: | Size: 741 B |
After Width: | Height: | Size: 974 B |
@@ -0,0 +1,181 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="filesystem_file.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/filesystem_file16.png"
|
||||
inkscape:export-xdpi="45"
|
||||
inkscape:export-ydpi="45">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.959798"
|
||||
inkscape:cx="-51.539982"
|
||||
inkscape:cy="23.000437"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<g
|
||||
id="g4225"
|
||||
transform="matrix(1.1128183,0,0,1.1128183,55.344213,-128.05315)">
|
||||
<path
|
||||
id="rect4177"
|
||||
transform="translate(-9.5367432e-7,1020.3622)"
|
||||
d="m -43.681641,13.882812 c -0.563451,0 -1.017578,0.452174 -1.017578,1.015626 l 0,22.210937 c 0,0.563451 0.454127,1.015625 1.017578,1.015625 l 16.652344,0 c 0.563451,0 1.017578,-0.452174 1.017578,-1.015625 l 0,-15.246094 -6.05664,-7.980469 -11.613282,0 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4218"
|
||||
d="m -31.837816,1034.2449 0,7.043 c 0,0.3498 0.283047,0.6328 0.632812,0.6328 l 5.19336,0 -5.826172,-7.6758 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 376 B |
After Width: | Height: | Size: 482 B |
After Width: | Height: | Size: 612 B |
@@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="filesystem_folder.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/filesystem_folder16.png"
|
||||
inkscape:export-xdpi="45"
|
||||
inkscape:export-ydpi="45">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.919596"
|
||||
inkscape:cx="3.5385856"
|
||||
inkscape:cy="13.013876"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<path
|
||||
style="opacity:1;fill:#80bbdb;fill-opacity:1;fill-rule:nonzero;stroke:#548dad;stroke-width:0.97142506;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10.44448,1025.9309 c 0.65513,0 1.18165,0.5595 1.18165,1.2556 l 0,1.2733 16.256617,0 c 1.376723,0 2.484776,1.1774 2.484776,2.6403 l 0,13.0531 c 0,1.4629 -1.108053,2.6403 -2.484776,2.6403 l -23.7654964,0 c -1.3767228,0 -2.4847757,-1.1774 -2.4847757,-2.6403 l 0,-10.7551 0,-2.298 0,-3.9136 c 0,-0.6961 0.5265186,-1.2556 1.1816486,-1.2556 z"
|
||||
id="rect4901"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sscssssssccsss" />
|
||||
<path
|
||||
style="opacity:1;fill:#5fa1c7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 2.1084458,1031.4784 0,0.7321 0,11.4039 c 0,1.5514 1.0713447,2.7998 2.4024592,2.7998 l 22.978188,0 c 1.331114,0 2.40246,-1.2484 2.40246,-2.7998 l 0,-12.136 -27.7831072,0 z"
|
||||
id="path4919"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 356 B |
After Width: | Height: | Size: 465 B |
After Width: | Height: | Size: 488 B |
@@ -0,0 +1,203 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="filesystem_load_file.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/filesystem_load_file16.png"
|
||||
inkscape:export-xdpi="45"
|
||||
inkscape:export-ydpi="45">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="-15.256846"
|
||||
inkscape:cy="-4.5327826"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<g
|
||||
id="g4206">
|
||||
<path
|
||||
id="rect4177"
|
||||
d="m 6.7344825,1022.8736 c -0.6270186,0 -1.1323794,0.5032 -1.1323794,1.1303 l 0,24.7167 c 0,0.627 0.5053608,1.1302 1.1323794,1.1302 l 18.5310335,0 c 0.627018,0 1.132379,-0.5032 1.132379,-1.1302 l 0,-16.9661 -6.73994,-8.8809 -12.9234725,0 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.66922748;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4218"
|
||||
d="m 19.914509,1022.8735 0,7.8376 c 0,0.3892 0.31498,0.7042 0.704204,0.7042 l 5.779267,0 -6.483471,-8.5418 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.66922748;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4202"
|
||||
transform="translate(-0.22767735,0)">
|
||||
<ellipse
|
||||
style="opacity:1;fill:#d4d68c;fill-opacity:1;fill-rule:nonzero;stroke:#c8cb6c;stroke-width:0.69685775;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse4194"
|
||||
cx="16.227676"
|
||||
cy="1044.2556"
|
||||
rx="7.8167491"
|
||||
ry="1.7860432" />
|
||||
<ellipse
|
||||
ry="0.47607893"
|
||||
rx="3.9621422"
|
||||
cy="1044.1664"
|
||||
cx="16.227676"
|
||||
id="ellipse4198"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.45964342;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#368fac;fill-opacity:1;fill-rule:evenodd;stroke:#2b7188;stroke-width:0.81720334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 15.999999,1032.9608 -4.451864,5.7416 2.225932,0 0,5.1577 4.451864,0 0,-5.1577 2.225932,0 z"
|
||||
id="path4210"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 544 B |
After Width: | Height: | Size: 795 B |
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,189 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="filesystem_path_exists.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/filesystem_path_exists16.png"
|
||||
inkscape:export-xdpi="45"
|
||||
inkscape:export-ydpi="45">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="7.919596"
|
||||
inkscape:cx="3.5385856"
|
||||
inkscape:cy="13.013876"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<path
|
||||
style="opacity:1;fill:#80bbdb;fill-opacity:1;fill-rule:nonzero;stroke:#548dad;stroke-width:0.97142506;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 10.44448,1025.9309 c 0.65513,0 1.18165,0.5595 1.18165,1.2556 l 0,1.2733 16.256617,0 c 1.376723,0 2.484776,1.1774 2.484776,2.6403 l 0,13.0531 c 0,1.4629 -1.108053,2.6403 -2.484776,2.6403 l -23.7654964,0 c -1.3767228,0 -2.4847757,-1.1774 -2.4847757,-2.6403 l 0,-10.7551 0,-2.298 0,-3.9136 c 0,-0.6961 0.5265186,-1.2556 1.1816486,-1.2556 z"
|
||||
id="rect4901"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="sscssssssccsss" />
|
||||
<path
|
||||
style="opacity:1;fill:#5fa1c7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 2.1084458,1031.4784 0,0.7321 0,11.4039 c 0,1.5514 1.0713447,2.7998 2.4024592,2.7998 l 22.978188,0 c 1.331114,0 2.40246,-1.2484 2.40246,-2.7998 l 0,-12.136 -27.7831072,0 z"
|
||||
id="path4919"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:33.25431824px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#9b80db;fill-opacity:1;stroke:#6e6f5e;stroke-width:1.19503343;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="5.8434677"
|
||||
y="1048.4673"
|
||||
id="text4229"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan4231"
|
||||
x="5.8434677"
|
||||
y="1048.4673"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Arial Black';-inkscape-font-specification:'Arial Black, ';fill:#9b80db;fill-opacity:1;stroke:#6e6f5e;stroke-width:1.19503343;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">?</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 680 B |
After Width: | Height: | Size: 984 B |
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,203 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="filesystem_save_file.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/filesystem_save_file32.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.6"
|
||||
inkscape:cx="30.546725"
|
||||
inkscape:cy="-3.8184969"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-smooth-nodes="true"
|
||||
inkscape:snap-midpoints="true"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<g
|
||||
id="g4206">
|
||||
<path
|
||||
id="rect4177"
|
||||
d="m 6.7344825,1022.8736 c -0.6270186,0 -1.1323794,0.5032 -1.1323794,1.1303 l 0,24.7167 c 0,0.627 0.5053608,1.1302 1.1323794,1.1302 l 18.5310335,0 c 0.627018,0 1.132379,-0.5032 1.132379,-1.1302 l 0,-16.9661 -6.73994,-8.8809 -12.9234725,0 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.66922748;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4218"
|
||||
d="m 19.914509,1022.8735 0,7.8376 c 0,0.3892 0.31498,0.7042 0.704204,0.7042 l 5.779267,0 -6.483471,-8.5418 z"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:#6e6f5e;stroke-width:1.66922748;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4202"
|
||||
transform="translate(-0.22767735,0)">
|
||||
<ellipse
|
||||
style="opacity:1;fill:#d4d68c;fill-opacity:1;fill-rule:nonzero;stroke:#c8cb6c;stroke-width:0.69685775;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="ellipse4194"
|
||||
cx="16.227676"
|
||||
cy="1044.2556"
|
||||
rx="7.8167491"
|
||||
ry="1.7860432" />
|
||||
<ellipse
|
||||
ry="0.47607893"
|
||||
rx="3.9621422"
|
||||
cy="1044.1664"
|
||||
cx="16.227676"
|
||||
id="ellipse4198"
|
||||
style="opacity:1;fill:#fcfdf1;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.45964342;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#6aac36;fill-opacity:1;fill-rule:evenodd;stroke:#54882b;stroke-width:0.81720334;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 15.999999,1043.6019 -4.451864,-5.7416 2.225932,0 0,-5.1577 4.451864,0 0,5.1577 2.225932,0 z"
|
||||
id="path4210"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 545 B |
After Width: | Height: | Size: 788 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 835 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 644 B |
After Width: | Height: | Size: 997 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 636 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 485 B |
After Width: | Height: | Size: 752 B |
After Width: | Height: | Size: 899 B |
After Width: | Height: | Size: 629 B |
After Width: | Height: | Size: 931 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 521 B |
After Width: | Height: | Size: 814 B |
After Width: | Height: | Size: 1011 B |
After Width: | Height: | Size: 701 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 560 B |
After Width: | Height: | Size: 898 B |
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 31.999999 32.000001"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="take_screenshot.svg"
|
||||
inkscape:export-filename="/home/matthias/Programme/GD_MyFork/GDevelop/Binaries/Output/Release_Windows/JsPlatform/Extensions/take_screenshot16.png"
|
||||
inkscape:export-xdpi="45"
|
||||
inkscape:export-ydpi="45">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6933"
|
||||
is_visible="true"
|
||||
pattern="m -9.5367432e-7,1025.3622 c 0,-2.76 2.23999995367432,-5 4.99999995367432,-5 2.76,0 5,2.24 5,5 0,2.76 -2.24,5 -5,5 -2.76,0 -4.99999995367432,-2.24 -4.99999995367432,-5 z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6855"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect6842"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<inkscape:path-effect
|
||||
effect="skeletal"
|
||||
id="path-effect4583"
|
||||
is_visible="true"
|
||||
pattern="M 0,5 C 0,2.24 2.24,0 5,0 7.76,0 10,2.24 10,5 10,7.76 7.76,10 5,10 2.24,10 0,7.76 0,5 Z"
|
||||
copytype="single_stretched"
|
||||
prop_scale="1"
|
||||
scale_y_rel="false"
|
||||
spacing="0"
|
||||
normal_offset="0"
|
||||
tang_offset="0"
|
||||
prop_units="false"
|
||||
vertical_pattern="false"
|
||||
fuse_tolerance="0" />
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lend"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lend"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4234"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#617da1;fill-opacity:1;fill-rule:evenodd;stroke:#617da1;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="Arrow1Lstart"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="Arrow1Lstart"
|
||||
style="overflow:visible"
|
||||
inkscape:isstock="true">
|
||||
<path
|
||||
id="path4231"
|
||||
d="M 0,0 5,-5 -12.5,0 5,5 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1"
|
||||
transform="matrix(0.8,0,0,0.8,10,0)"
|
||||
inkscape:connector-curvature="0" />
|
||||
</marker>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="11.313709"
|
||||
inkscape:cx="0.48062283"
|
||||
inkscape:cy="15.066705"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer2"
|
||||
showgrid="true"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1026"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:snap-intersection-paths="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-nodes="true"
|
||||
units="px">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid6838" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="bg"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
style="opacity:0"
|
||||
sodipodi:insensitive="true"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.48900003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#5d3b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4136"
|
||||
width="537.14288"
|
||||
height="537.14288"
|
||||
x="108.57143"
|
||||
y="232.3622"
|
||||
ry="0" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
id="layer2"
|
||||
inkscape:label="vg"
|
||||
transform="translate(0,-1020.3622)">
|
||||
<rect
|
||||
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#535353;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
|
||||
id="rect4139"
|
||||
width="31.889814"
|
||||
height="20.333548"
|
||||
x="0.055091862"
|
||||
y="1026.1954"
|
||||
ry="2.8092401" />
|
||||
<circle
|
||||
style="opacity:1;fill:#8c8c8c;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4208"
|
||||
cx="15.999999"
|
||||
cy="1038.0809"
|
||||
r="6.34375" />
|
||||
<rect
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4210"
|
||||
width="5.0598979"
|
||||
height="5.2740483"
|
||||
x="2.8781402"
|
||||
y="1028.0603"
|
||||
ry="2.6370242" />
|
||||
<rect
|
||||
style="opacity:1;fill:#535353;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect4212"
|
||||
width="11.124999"
|
||||
height="4.3597975"
|
||||
x="19.03125"
|
||||
y="1023.6198"
|
||||
ry="1.2027028" />
|
||||
<rect
|
||||
ry="0.59375"
|
||||
y="1024.6122"
|
||||
x="20.748579"
|
||||
height="2.375"
|
||||
width="7.6903405"
|
||||
id="rect4214"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<circle
|
||||
r="4.75"
|
||||
cy="1038.0809"
|
||||
cx="15.999999"
|
||||
id="circle4216"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 500 B |
After Width: | Height: | Size: 684 B |
After Width: | Height: | Size: 909 B |
After Width: | Height: | Size: 567 B |
After Width: | Height: | Size: 840 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 696 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.5 KiB |
@@ -3,6 +3,7 @@
|
||||
#include <utility>
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
|
||||
#include "GDCore/Events/CodeGeneration/ExpressionCodeGenerator.h"
|
||||
#include "GDCore/Events/CodeGeneration/ExpressionsCodeGeneration.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser.h"
|
||||
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
|
||||
@@ -13,8 +14,8 @@
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -295,11 +296,14 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(objectInParameter)) {
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
condition.SetParameter(pNb, gd::Expression(""));
|
||||
condition.SetType("");
|
||||
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectInParameter) !=
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter) !=
|
||||
instrInfos.parameters[pNb].supplementaryInformation) {
|
||||
condition.SetParameter(pNb, gd::Expression(""));
|
||||
condition.SetType("");
|
||||
@@ -328,7 +332,8 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
gd::String objectName = condition.GetParameters().empty()
|
||||
? ""
|
||||
: condition.GetParameter(0).GetPlainString();
|
||||
gd::String objectType = gd::GetTypeOfObject(GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectName);
|
||||
gd::String objectType = gd::GetTypeOfObject(
|
||||
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectName);
|
||||
if (!objectName.empty() &&
|
||||
MetadataProvider::HasObjectCondition(
|
||||
platform, objectType, condition.GetType()) &&
|
||||
@@ -442,120 +447,41 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
|
||||
return outputCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate code for an action.
|
||||
*/
|
||||
gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
gd::Instruction& action, EventsCodeGenerationContext& context) {
|
||||
gd::String actionCode;
|
||||
|
||||
gd::InstructionMetadata instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, action.GetType());
|
||||
|
||||
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
|
||||
|
||||
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
|
||||
return instrInfos.codeExtraInformation.customCodeGenerator(
|
||||
action, *this, context);
|
||||
}
|
||||
|
||||
// TODO: Could be moved to a EventsValidator
|
||||
void EventsCodeGenerator::ValidateAction(
|
||||
gd::InstructionMetadata& instructionMetadata, gd::Instruction& action) {
|
||||
// Be sure there is no lack of parameter.
|
||||
while (action.GetParameters().size() < instrInfos.parameters.size()) {
|
||||
while (action.GetParameters().size() <
|
||||
instructionMetadata.parameters.size()) {
|
||||
vector<gd::Expression> parameters = action.GetParameters();
|
||||
parameters.push_back(gd::Expression(""));
|
||||
action.SetParameters(parameters);
|
||||
}
|
||||
|
||||
// Verify that there are not mismatch between object type in parameters
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
|
||||
for (std::size_t pNb = 0; pNb < instructionMetadata.parameters.size();
|
||||
++pNb) {
|
||||
if (ParameterMetadata::IsObject(instructionMetadata.parameters[pNb].type)) {
|
||||
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
|
||||
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
|
||||
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(objectInParameter)) {
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
action.SetParameter(pNb, gd::Expression(""));
|
||||
action.SetType("");
|
||||
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectInParameter) !=
|
||||
instrInfos.parameters[pNb].supplementaryInformation) {
|
||||
} else if (!instructionMetadata.parameters[pNb]
|
||||
.supplementaryInformation.empty() &&
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter) !=
|
||||
instructionMetadata.parameters[pNb]
|
||||
.supplementaryInformation) {
|
||||
action.SetParameter(pNb, gd::Expression(""));
|
||||
action.SetType("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call free function first if available
|
||||
if (MetadataProvider::HasAction(platform, action.GetType())) {
|
||||
vector<gd::String> arguments = GenerateParametersCodes(
|
||||
action.GetParameters(), instrInfos.parameters, context);
|
||||
actionCode += GenerateFreeAction(arguments, instrInfos, context);
|
||||
}
|
||||
|
||||
// Call object function if available
|
||||
gd::String objectName = action.GetParameters().empty()
|
||||
? ""
|
||||
: action.GetParameter(0).GetPlainString();
|
||||
gd::String objectType = gd::GetTypeOfObject(GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectName);
|
||||
if (MetadataProvider::HasObjectAction(
|
||||
platform, objectType, action.GetType()) &&
|
||||
!instrInfos.parameters.empty()) {
|
||||
std::vector<gd::String> realObjects =
|
||||
ExpandObjectsName(objectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Setup context
|
||||
const ObjectMetadata& objInfo =
|
||||
MetadataProvider::GetObjectMetadata(platform, objectType);
|
||||
AddIncludeFiles(objInfo.includeFiles);
|
||||
context.SetCurrentObject(realObjects[i]);
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
|
||||
// Prepare arguments and generate the whole action code
|
||||
vector<gd::String> arguments = GenerateParametersCodes(
|
||||
action.GetParameters(), instrInfos.parameters, context);
|
||||
actionCode += GenerateObjectAction(
|
||||
realObjects[i], objInfo, arguments, instrInfos, context);
|
||||
|
||||
context.SetNoCurrentObject();
|
||||
}
|
||||
}
|
||||
|
||||
// Assign to a behavior member function if found
|
||||
gd::String behaviorType =
|
||||
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
action.GetParameters().size() < 2
|
||||
? ""
|
||||
: action.GetParameter(1).GetPlainString());
|
||||
if (MetadataProvider::HasBehaviorAction(
|
||||
platform, behaviorType, action.GetType()) &&
|
||||
instrInfos.parameters.size() >= 2) {
|
||||
std::vector<gd::String> realObjects =
|
||||
ExpandObjectsName(objectName, context);
|
||||
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]);
|
||||
|
||||
// Prepare arguments and generate the whole action code
|
||||
vector<gd::String> arguments = GenerateParametersCodes(
|
||||
action.GetParameters(), instrInfos.parameters, context);
|
||||
actionCode +=
|
||||
GenerateBehaviorAction(realObjects[i],
|
||||
action.GetParameter(1).GetPlainString(),
|
||||
autoInfo,
|
||||
arguments,
|
||||
instrInfos,
|
||||
context);
|
||||
|
||||
context.SetNoCurrentObject();
|
||||
}
|
||||
}
|
||||
|
||||
return actionCode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -564,17 +490,169 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
gd::String EventsCodeGenerator::GenerateActionsListCode(
|
||||
gd::InstructionsList& actions, EventsCodeGenerationContext& context) {
|
||||
gd::String outputCode;
|
||||
|
||||
// Generation of actions related to a same object (or same group)
|
||||
// is batched, so that we only iterate once on the objects, and not
|
||||
// one time for every action.
|
||||
gd::String batchedObjectName;
|
||||
gd::String batchedObjectType;
|
||||
std::vector<gd::Instruction*> batchedActions;
|
||||
auto generateBatchedObjectActionsCode = [&]() {
|
||||
if (batchedActions.empty()) {
|
||||
return gd::String("");
|
||||
}
|
||||
|
||||
gd::String batchedActionsCode;
|
||||
|
||||
std::vector<gd::String> realObjects =
|
||||
ExpandObjectsName(batchedObjectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
// Setup context
|
||||
context.SetCurrentObject(realObjects[i]);
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
|
||||
gd::String actionsCode =
|
||||
batchedActions.size() > 1
|
||||
? "/*Batching for " + batchedObjectName + "*/\n"
|
||||
: "/*No batching for " + batchedObjectName + "*/\n";
|
||||
|
||||
for (auto& actionPtr : batchedActions) {
|
||||
auto& action = *actionPtr;
|
||||
gd::InstructionMetadata instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, action.GetType());
|
||||
|
||||
if (MetadataProvider::HasObjectAction(
|
||||
platform, batchedObjectType, action.GetType()) &&
|
||||
!instrInfos.parameters.empty()) {
|
||||
const ObjectMetadata& objInfo =
|
||||
MetadataProvider::GetObjectMetadata(platform, batchedObjectType);
|
||||
AddIncludeFiles(objInfo.includeFiles);
|
||||
|
||||
// Prepare arguments and generate the whole action code
|
||||
vector<gd::String> arguments = GenerateParametersCodes(
|
||||
action.GetParameters(),
|
||||
instrInfos.parameters,
|
||||
context); // TODO: FACTOR or move into Generate function?
|
||||
actionsCode += GenerateObjectAction(
|
||||
realObjects[i], objInfo, arguments, instrInfos, context);
|
||||
} else {
|
||||
gd::String behaviorType = gd::GetTypeOfBehavior(
|
||||
GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
action.GetParameters().size() < 2
|
||||
? ""
|
||||
: action.GetParameter(1).GetPlainString());
|
||||
if (MetadataProvider::HasBehaviorAction(
|
||||
platform, behaviorType, action.GetType()) &&
|
||||
instrInfos.parameters.size() >= 2) {
|
||||
// Setup context
|
||||
const BehaviorMetadata& autoInfo =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
|
||||
AddIncludeFiles(autoInfo.includeFiles);
|
||||
|
||||
// Prepare arguments and generate the whole action code
|
||||
vector<gd::String> arguments = GenerateParametersCodes(
|
||||
action.GetParameters(),
|
||||
instrInfos.parameters,
|
||||
context); // TODO: FACTOR or move into Generate function?
|
||||
actionsCode +=
|
||||
GenerateBehaviorAction(realObjects[i],
|
||||
action.GetParameter(1).GetPlainString(),
|
||||
autoInfo,
|
||||
arguments,
|
||||
instrInfos,
|
||||
context);
|
||||
}
|
||||
}
|
||||
}
|
||||
batchedActionsCode +=
|
||||
GenerateObjectLoop(realObjects[i], context, actionsCode); //TODO: use for conditions too
|
||||
context.SetNoCurrentObject();
|
||||
}
|
||||
|
||||
batchedObjectName = "";
|
||||
batchedObjectType = "";
|
||||
batchedActions.clear();
|
||||
|
||||
return batchedActionsCode;
|
||||
};
|
||||
|
||||
// Defer the generation of the object (or behavior) action.
|
||||
auto batchObjectAction = [&](const gd::String& objectName,
|
||||
const gd::String& objectType,
|
||||
gd::Instruction& action) {
|
||||
gd::String outputCode;
|
||||
if (objectName != batchedObjectName || objectType != batchedObjectType) {
|
||||
// Dump any batched action for a different object before.
|
||||
outputCode += generateBatchedObjectActionsCode();
|
||||
batchedObjectName = objectName;
|
||||
batchedObjectType = objectType;
|
||||
}
|
||||
|
||||
batchedActions.push_back(&action);
|
||||
|
||||
return outputCode;
|
||||
};
|
||||
|
||||
for (std::size_t aId = 0; aId < actions.size(); ++aId) {
|
||||
gd::Instruction& action = actions[aId];
|
||||
gd::InstructionMetadata instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
|
||||
gd::String actionCode = GenerateActionCode(actions[aId], context);
|
||||
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
|
||||
|
||||
outputCode += "{";
|
||||
if (!actions[aId].GetType().empty()) outputCode += actionCode;
|
||||
outputCode += "}";
|
||||
// Generate custom code if needed
|
||||
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
|
||||
outputCode += generateBatchedObjectActionsCode(); // Dump any batched
|
||||
// action before.
|
||||
outputCode += instrInfos.codeExtraInformation.customCodeGenerator(
|
||||
action, *this, context);
|
||||
} else {
|
||||
// No custom code
|
||||
ValidateAction(instrInfos, action);
|
||||
|
||||
// Call free function first if available
|
||||
if (MetadataProvider::HasAction(platform, action.GetType())) {
|
||||
outputCode += generateBatchedObjectActionsCode(); // Dump any batched
|
||||
// action before.
|
||||
|
||||
vector<gd::String> arguments = GenerateParametersCodes(
|
||||
action.GetParameters(),
|
||||
instrInfos.parameters,
|
||||
context); // TODO: FACTOR or move into Generate function?
|
||||
outputCode += GenerateFreeAction(arguments, instrInfos, context);
|
||||
}
|
||||
|
||||
// Call object function if available
|
||||
gd::String objectName = action.GetParameters().empty()
|
||||
? ""
|
||||
: action.GetParameter(0).GetPlainString();
|
||||
gd::String objectType = gd::GetTypeOfObject(
|
||||
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectName);
|
||||
if (MetadataProvider::HasObjectAction(
|
||||
platform, objectType, action.GetType()) &&
|
||||
!instrInfos.parameters.empty()) {
|
||||
outputCode += batchObjectAction(objectName, objectType, action);
|
||||
}
|
||||
|
||||
// Assign to a behavior member function if found
|
||||
gd::String behaviorType =
|
||||
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
action.GetParameters().size() < 2
|
||||
? ""
|
||||
: action.GetParameter(1).GetPlainString());
|
||||
if (MetadataProvider::HasBehaviorAction(
|
||||
platform, behaviorType, action.GetType()) &&
|
||||
instrInfos.parameters.size() >= 2) {
|
||||
outputCode += batchObjectAction(objectName, objectType, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dump any remaining batched actions.
|
||||
outputCode += generateBatchedObjectActionsCode();
|
||||
|
||||
return outputCode;
|
||||
}
|
||||
|
||||
@@ -582,34 +660,24 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
const gd::String& parameter,
|
||||
const gd::ParameterMetadata& metadata,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& previousParameter,
|
||||
const gd::String& lastObjectName,
|
||||
std::vector<std::pair<gd::String, gd::String> >*
|
||||
supplementaryParametersTypes) {
|
||||
gd::String argOutput;
|
||||
|
||||
if (ParameterMetadata::IsExpression("number", metadata.type)) {
|
||||
CallbacksForGeneratingExpressionCode callbacks(argOutput, *this, context);
|
||||
|
||||
gd::ExpressionParser parser(parameter);
|
||||
if (!parser.ParseMathExpression(platform, GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), callbacks)) {
|
||||
cout << "Error :" << parser.GetFirstError() << " in: " << parameter
|
||||
<< endl;
|
||||
|
||||
argOutput = "0";
|
||||
}
|
||||
|
||||
if (argOutput.empty()) argOutput = "0";
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, "number", parameter);
|
||||
} else if (ParameterMetadata::IsExpression("string", metadata.type)) {
|
||||
CallbacksForGeneratingExpressionCode callbacks(argOutput, *this, context);
|
||||
|
||||
gd::ExpressionParser parser(parameter);
|
||||
if (!parser.ParseStringExpression(platform, GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), callbacks)) {
|
||||
cout << "Error in text expression" << parser.GetFirstError() << endl;
|
||||
|
||||
argOutput = "\"\"";
|
||||
}
|
||||
|
||||
if (argOutput.empty()) argOutput = "\"\"";
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, "string", parameter);
|
||||
} else if (ParameterMetadata::IsExpression("variable", metadata.type)) {
|
||||
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
*this, context, metadata.type, parameter, lastObjectName);
|
||||
} else if (ParameterMetadata::IsObject(metadata.type)) {
|
||||
// It would be possible to run a gd::ExpressionCodeGenerator if later
|
||||
// objects can have nested objects, or function returning objects.
|
||||
argOutput = GenerateObject(parameter, metadata.type, context);
|
||||
} else if (metadata.type == "relationalOperator") {
|
||||
argOutput += parameter == "=" ? "==" : parameter;
|
||||
if (argOutput != "==" && argOutput != "<" && argOutput != ">" &&
|
||||
@@ -628,14 +696,12 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
|
||||
}
|
||||
|
||||
argOutput = "\"" + argOutput + "\"";
|
||||
} else if (metadata.type == "object" || metadata.type == "behavior") {
|
||||
} else if (metadata.type == "behavior") {
|
||||
argOutput = "\"" + ConvertToString(parameter) + "\"";
|
||||
} else if (metadata.type == "key") {
|
||||
argOutput = "\"" + ConvertToString(parameter) + "\"";
|
||||
} else if (metadata.type == "objectvar" || metadata.type == "scenevar" ||
|
||||
metadata.type == "globalvar" || metadata.type == "password" ||
|
||||
metadata.type == "musicfile" || metadata.type == "soundfile" ||
|
||||
metadata.type == "police") {
|
||||
} else if (metadata.type == "password" || metadata.type == "musicfile" ||
|
||||
metadata.type == "soundfile" || metadata.type == "police") {
|
||||
argOutput = "\"" + ConvertToString(parameter) + "\"";
|
||||
} else if (metadata.type == "mouse") {
|
||||
argOutput = "\"" + ConvertToString(parameter) + "\"";
|
||||
@@ -682,6 +748,7 @@ vector<gd::String> EventsCodeGenerator::GenerateParametersCodes(
|
||||
while (parameters.size() < parametersInfo.size())
|
||||
parameters.push_back(gd::Expression(""));
|
||||
|
||||
gd::String lastObjectName = "";
|
||||
for (std::size_t pNb = 0;
|
||||
pNb < parametersInfo.size() && pNb < parameters.size();
|
||||
++pNb) {
|
||||
@@ -689,12 +756,18 @@ vector<gd::String> EventsCodeGenerator::GenerateParametersCodes(
|
||||
parametersInfo[pNb].optional)
|
||||
parameters[pNb] = gd::Expression(parametersInfo[pNb].defaultValue);
|
||||
|
||||
gd::String argOutput = GenerateParameterCodes(
|
||||
parameters[pNb].GetPlainString(),
|
||||
parametersInfo[pNb],
|
||||
context,
|
||||
pNb == 0 ? "" : parameters[pNb - 1].GetPlainString(),
|
||||
supplementaryParametersTypes);
|
||||
gd::String argOutput =
|
||||
GenerateParameterCodes(parameters[pNb].GetPlainString(),
|
||||
parametersInfo[pNb],
|
||||
context,
|
||||
lastObjectName,
|
||||
supplementaryParametersTypes);
|
||||
|
||||
// Memorize the last object name. By convention, parameters that require
|
||||
// an object (mainly, "objectvar") should be placed after the object
|
||||
// in the list of parameters (if possible, just after).
|
||||
if (gd::ParameterMetadata::IsObject(parametersInfo[pNb].GetType()))
|
||||
lastObjectName = parameters[pNb].GetPlainString();
|
||||
|
||||
arguments.push_back(argOutput);
|
||||
}
|
||||
@@ -799,23 +872,10 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::ConvertToString(gd::String plainString) {
|
||||
for (size_t i = 0; i < plainString.length(); ++i) {
|
||||
if (plainString[i] == '\\') {
|
||||
if (i + 1 >= plainString.length() || plainString[i + 1] != '\"') {
|
||||
if (i + 1 < plainString.length())
|
||||
plainString.insert(i + 1, "\\");
|
||||
else
|
||||
plainString += ("\\");
|
||||
|
||||
++i;
|
||||
}
|
||||
} else if (plainString[i] == '"') {
|
||||
plainString.insert(i, "\\");
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
plainString = plainString.FindAndReplace("\n", "\\n");
|
||||
plainString = plainString.FindAndReplace("\\", "\\\\")
|
||||
.FindAndReplace("\r", "\\r")
|
||||
.FindAndReplace("\n", "\\n")
|
||||
.FindAndReplace("\"", "\\\"");
|
||||
|
||||
return plainString;
|
||||
}
|
||||
@@ -831,10 +891,12 @@ std::vector<gd::String> EventsCodeGenerator::ExpandObjectsName(
|
||||
// Note: this logic is duplicated in EventsContextAnalyzer::ExpandObjectsName
|
||||
std::vector<gd::String> realObjects;
|
||||
if (globalObjectsAndGroups.GetObjectGroups().Has(objectName))
|
||||
realObjects =
|
||||
globalObjectsAndGroups.GetObjectGroups().Get(objectName).GetAllObjectsNames();
|
||||
realObjects = globalObjectsAndGroups.GetObjectGroups()
|
||||
.Get(objectName)
|
||||
.GetAllObjectsNames();
|
||||
else if (objectsAndGroups.GetObjectGroups().Has(objectName))
|
||||
realObjects = objectsAndGroups.GetObjectGroups().Get(objectName).GetAllObjectsNames();
|
||||
realObjects =
|
||||
objectsAndGroups.GetObjectGroups().Get(objectName).GetAllObjectsNames();
|
||||
else
|
||||
realObjects.push_back(objectName);
|
||||
|
||||
@@ -893,7 +955,9 @@ gd::String EventsCodeGenerator::GenerateObjectFunctionCall(
|
||||
gd::String parametersStr,
|
||||
gd::String defaultOutput,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
return "TODO (GenerateObjectFunctionCall)";
|
||||
// To be used for testing only.
|
||||
return objectListName + "." + codeInfo.functionCallName + "(" +
|
||||
parametersStr + ") ?? " + defaultOutput;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateObjectBehaviorFunctionCall(
|
||||
@@ -904,7 +968,10 @@ gd::String EventsCodeGenerator::GenerateObjectBehaviorFunctionCall(
|
||||
gd::String parametersStr,
|
||||
gd::String defaultOutput,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
return "TODO (GenerateObjectBehaviorFunctionCall)";
|
||||
// To be used for testing only.
|
||||
return objectListName + "::" + behaviorName + "." +
|
||||
codeInfo.functionCallName + "(" + parametersStr + ") ?? " +
|
||||
defaultOutput;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateFreeCondition(
|
||||
@@ -1031,6 +1098,18 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
|
||||
return call + ";\n";
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateObjectLoop(
|
||||
const gd::String& objectName,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& innerLoopCode) {
|
||||
gd::String loopCode; //TODO: For GDCpp
|
||||
loopCode += "foreach("+objectName+") {\n";
|
||||
loopCode += " " + innerLoopCode + ";\n";
|
||||
loopCode += "}\n";
|
||||
|
||||
return loopCode;
|
||||
}
|
||||
|
||||
gd::String EventsCodeGenerator::GenerateObjectAction(
|
||||
const gd::String& objectName,
|
||||
const gd::ObjectMetadata& objInfo,
|
||||
@@ -1056,14 +1135,13 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
|
||||
instrInfos.codeExtraInformation.functionCallName,
|
||||
2);
|
||||
|
||||
return "For each picked object \"" + objectName + "\", call " + call +
|
||||
".\n";
|
||||
return "For object \"" + objectName + "\", call " + call + ".\n";
|
||||
} else {
|
||||
gd::String argumentsStr = GenerateArgumentsList(arguments, 1);
|
||||
|
||||
call = instrInfos.codeExtraInformation.functionCallName + "(" +
|
||||
argumentsStr + ")";
|
||||
return "For each picked object \"" + objectName + "\", call " + call + "(" +
|
||||
return "For object \"" + objectName + "\", call " + call + "(" +
|
||||
argumentsStr + ").\n";
|
||||
}
|
||||
}
|
||||
@@ -1093,14 +1171,14 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
|
||||
arguments,
|
||||
instrInfos.codeExtraInformation.functionCallName,
|
||||
2);
|
||||
return "For each picked object \"" + objectName + "\", call " + call +
|
||||
return "For object \"" + objectName + "\", call " + call +
|
||||
" for behavior \"" + behaviorName + "\".\n";
|
||||
} else {
|
||||
gd::String argumentsStr = GenerateArgumentsList(arguments, 2);
|
||||
|
||||
call = instrInfos.codeExtraInformation.functionCallName + "(" +
|
||||
argumentsStr + ")";
|
||||
return "For each picked object \"" + objectName + "\", call " + call + "(" +
|
||||
return "For object \"" + objectName + "\", call " + call + "(" +
|
||||
argumentsStr + ")" + " for behavior \"" + behaviorName + "\".\n";
|
||||
}
|
||||
}
|
||||
@@ -1135,9 +1213,10 @@ EventsCodeGenerator::EventsCodeGenerator(gd::Project& project_,
|
||||
maxCustomConditionsDepth(0),
|
||||
maxConditionsListsSize(0){};
|
||||
|
||||
EventsCodeGenerator::EventsCodeGenerator(const gd::Platform& platform_,
|
||||
gd::ObjectsContainer & globalObjectsAndGroups_,
|
||||
const gd::ObjectsContainer & objectsAndGroups_)
|
||||
EventsCodeGenerator::EventsCodeGenerator(
|
||||
const gd::Platform& platform_,
|
||||
gd::ObjectsContainer& globalObjectsAndGroups_,
|
||||
const gd::ObjectsContainer& objectsAndGroups_)
|
||||
: platform(platform_),
|
||||
globalObjectsAndGroups(globalObjectsAndGroups_),
|
||||
objectsAndGroups(objectsAndGroups_),
|
||||
|
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* 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
|
||||
|
||||
@@ -22,18 +27,19 @@ class EventsCodeGenerationContext;
|
||||
class ExpressionCodeGenerationInformation;
|
||||
class InstructionMetadata;
|
||||
class Platform;
|
||||
}
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Internal class used to generate code from events
|
||||
* \todo For now, this class generates only C++ code for GD C++ Platform.
|
||||
*
|
||||
* \see CallbacksForGeneratingExpressionCode
|
||||
*/
|
||||
class GD_CORE_API EventsCodeGenerator {
|
||||
// Compatiblity with old ExpressionParser
|
||||
friend class CallbacksForGeneratingExpressionCode;
|
||||
friend class VariableCodeGenerationCallbacks;
|
||||
// end of compatibility code
|
||||
friend class ExpressionCodeGenerator;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -53,9 +59,9 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
* \brief Construct a code generator for the specified
|
||||
* objects/groups and platform
|
||||
*/
|
||||
EventsCodeGenerator(const gd::Platform& platform,
|
||||
gd::ObjectsContainer & globalObjectsAndGroups_,
|
||||
const gd::ObjectsContainer & objectsAndGroups_);
|
||||
EventsCodeGenerator(const gd::Platform& platform,
|
||||
gd::ObjectsContainer& globalObjectsAndGroups_,
|
||||
const gd::ObjectsContainer& objectsAndGroups_);
|
||||
virtual ~EventsCodeGenerator(){};
|
||||
|
||||
/**
|
||||
@@ -141,19 +147,6 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
gd::String returnBoolean,
|
||||
EventsCodeGenerationContext& context);
|
||||
|
||||
/**
|
||||
* \brief Generate code for a single action
|
||||
*
|
||||
* The generation is really done in GenerateFreeAction/GenerateObjectAction or
|
||||
* GenerateBehaviorAction.
|
||||
*
|
||||
* \param condition instruction to be done.
|
||||
* \param context Context used for generation
|
||||
* \return Code
|
||||
*/
|
||||
gd::String GenerateActionCode(gd::Instruction& action,
|
||||
EventsCodeGenerationContext& context);
|
||||
|
||||
/**
|
||||
* \brief Generate code for declaring objects lists.
|
||||
*
|
||||
@@ -182,9 +175,9 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
virtual gd::String ConvertToString(gd::String plainString);
|
||||
|
||||
/**
|
||||
* \brief Convert a plain string ( with line feed, quotes ) to a string that
|
||||
* \brief Convert a plain string (with line feed, quotes) to a string that
|
||||
can be inserted into code.
|
||||
* The string construction must be explicit : for example, quotes must be
|
||||
* The string construction must be explicit: for example, quotes must be
|
||||
added if the target language need quotes.
|
||||
*
|
||||
* Usage example :
|
||||
@@ -278,23 +271,31 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
void ReportError();
|
||||
|
||||
/**
|
||||
* \brief Return true if an error has occurred during code generation ( in
|
||||
* this case, generated code is not usable )
|
||||
* \brief Return true if an error has occurred during code generation (in
|
||||
* this case, generated code is not usable).
|
||||
*
|
||||
* \todo TODO: This is actually not used and should be moved to a more
|
||||
* complete error reporting.
|
||||
*/
|
||||
bool ErrorOccurred() const { return errorOccurred; };
|
||||
|
||||
/**
|
||||
* \brief Get the global objects/groups used for code generation.
|
||||
*/
|
||||
gd::ObjectsContainer& GetGlobalObjectsAndGroups() const { return globalObjectsAndGroups; }
|
||||
gd::ObjectsContainer& GetGlobalObjectsAndGroups() const {
|
||||
return globalObjectsAndGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the objects/groups used for code generation.
|
||||
*/
|
||||
const gd::ObjectsContainer& GetObjectsAndGroups() const { return objectsAndGroups; }
|
||||
const gd::ObjectsContainer& GetObjectsAndGroups() const {
|
||||
return objectsAndGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the code generation is done for a given project and layout.
|
||||
* \brief Return true if the code generation is done for a given project and
|
||||
* layout.
|
||||
*/
|
||||
bool HasProjectAndLayout() const { return hasProjectAndLayout; }
|
||||
|
||||
@@ -380,27 +381,36 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
* \brief Generate the code to notify the profiler of the beginning of a
|
||||
* section.
|
||||
*/
|
||||
virtual gd::String GenerateProfilerSectionBegin(const gd::String& section) { return ""; };
|
||||
virtual gd::String GenerateProfilerSectionBegin(const gd::String& section) {
|
||||
return "";
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Generate the code to notify the profiler of the end of a section.
|
||||
*/
|
||||
virtual gd::String GenerateProfilerSectionEnd(const gd::String& section) { return ""; };
|
||||
virtual gd::String GenerateProfilerSectionEnd(const gd::String& section) {
|
||||
return "";
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Get the namespace to be used to store code generated objects/values/functions,
|
||||
* with the extra "dot" at the end to be used to access to a property/member.
|
||||
* \brief Get the namespace to be used to store code generated
|
||||
* objects/values/functions, with the extra "dot" at the end to be used to
|
||||
* access to a property/member.
|
||||
*
|
||||
* Example: "gdjs.something."
|
||||
*/
|
||||
virtual gd::String GetCodeNamespaceAccessor() { return ""; };
|
||||
|
||||
/**
|
||||
* \brief Get the namespace to be used to store code generated objects/values/functions.
|
||||
* \brief Get the namespace to be used to store code generated
|
||||
* objects/values/functions.
|
||||
*
|
||||
* Example: "gdjs.something"
|
||||
*/
|
||||
virtual gd::String GetCodeNamespace() { return ""; };
|
||||
|
||||
enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE };
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Generate the code for a single parameter.
|
||||
@@ -452,10 +462,69 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
const gd::String& parameter,
|
||||
const gd::ParameterMetadata& metadata,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& previousParameter,
|
||||
const gd::String& lastObjectName,
|
||||
std::vector<std::pair<gd::String, gd::String> >*
|
||||
supplementaryParametersTypes);
|
||||
|
||||
/**
|
||||
* \brief Generate the code to get a variable.
|
||||
*/
|
||||
virtual gd::String GenerateGetVariable(
|
||||
const gd::String& variableName,
|
||||
const VariableScope& scope,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& objectName) {
|
||||
if (scope == LAYOUT_VARIABLE) {
|
||||
return "getLayoutVariable(" + variableName + ")";
|
||||
|
||||
} else if (scope == PROJECT_VARIABLE) {
|
||||
return "getProjectVariable(" + variableName + ")";
|
||||
}
|
||||
|
||||
return "getVariableForObject(" + objectName + ", " + variableName + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generate the code to get the child of a variable.
|
||||
*/
|
||||
virtual gd::String GenerateVariableAccessor(gd::String childName) {
|
||||
return ".getChild(" + ConvertToStringExplicit(childName) + ")";
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Generate the code to get the child of a variable,
|
||||
* using generated the expression.
|
||||
*/
|
||||
virtual gd::String GenerateVariableBracketAccessor(
|
||||
gd::String expressionCode) {
|
||||
return ".getChild(" + expressionCode + ")";
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Generate the code to reference a variable which is
|
||||
* in an empty/null state.
|
||||
*/
|
||||
virtual gd::String GenerateBadVariable() { return "fakeBadVariable"; }
|
||||
|
||||
/**
|
||||
* \brief Generate the code to reference an object.
|
||||
* \param objectName the name of the object.
|
||||
* \param type what is the expected type (object, objectPtr...) in which the
|
||||
* object must be generated.
|
||||
* \param context The context for code generation
|
||||
*/
|
||||
virtual gd::String GenerateObject(const gd::String& objectName,
|
||||
const gd::String& type,
|
||||
gd::EventsCodeGenerationContext& context) {
|
||||
return "fakeObjectListOf_" + objectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Generate the code to reference an object which is
|
||||
* in an empty/null state.
|
||||
*/
|
||||
virtual gd::String GenerateBadObject() { return "fakeNullObject"; }
|
||||
|
||||
/**
|
||||
* \brief Call a function of the current object.
|
||||
* \note The current object is the object being manipulated by a condition or
|
||||
@@ -577,6 +646,11 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
const gd::InstructionMetadata& instrInfos,
|
||||
gd::EventsCodeGenerationContext& context);
|
||||
|
||||
virtual gd::String GenerateObjectLoop(
|
||||
const gd::String& objectName,
|
||||
gd::EventsCodeGenerationContext& context,
|
||||
const gd::String& innerLoopCode);
|
||||
|
||||
virtual gd::String GenerateObjectAction(
|
||||
const gd::String& objectName,
|
||||
const gd::ObjectMetadata& objInfo,
|
||||
@@ -613,31 +687,36 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
std::size_t startFromArgument = 0);
|
||||
|
||||
/**
|
||||
* \brief Must return an expression whose value is true.
|
||||
* \brief Return the "true" keyword in the target language.
|
||||
*/
|
||||
gd::String GenerateTrue() const { return "true"; };
|
||||
|
||||
/**
|
||||
* \brief Must return an expression whose value is false.
|
||||
* \brief Return the "false" keyword in the target language.
|
||||
*/
|
||||
gd::String GenerateFalse() const { return "false"; };
|
||||
|
||||
/**
|
||||
* \brief Generate the list of comma-separated arguments to be used to call a
|
||||
* function. \param arguments The code already generated for the arguments
|
||||
* function.
|
||||
*
|
||||
* \param arguments The code already generated for the arguments
|
||||
* \param startFrom Index of the first argument, the previous will be ignored.
|
||||
*/
|
||||
virtual gd::String GenerateArgumentsList(
|
||||
const std::vector<gd::String>& arguments, size_t startFrom = 0);
|
||||
|
||||
const gd::Platform& platform; ///< The platform being used.
|
||||
|
||||
gd::ObjectsContainer & globalObjectsAndGroups;
|
||||
const gd::ObjectsContainer & objectsAndGroups;
|
||||
void ValidateAction(gd::InstructionMetadata & instructionMetadata, gd::Instruction& action);
|
||||
|
||||
bool hasProjectAndLayout; ///< true only if project and layout are valid references. If false, they should not be used.
|
||||
gd::Project* project; ///< The project being used.
|
||||
const gd::Layout* scene; ///< The scene being generated.
|
||||
const gd::Platform& platform; ///< The platform being used.
|
||||
|
||||
gd::ObjectsContainer& globalObjectsAndGroups;
|
||||
const gd::ObjectsContainer& objectsAndGroups;
|
||||
|
||||
bool hasProjectAndLayout; ///< true only if project and layout are valid
|
||||
///< references. If false, they should not be used.
|
||||
gd::Project* project; ///< The project being used.
|
||||
const gd::Layout* scene; ///< The scene being generated.
|
||||
|
||||
bool errorOccurred; ///< Must be set to true if an error occured.
|
||||
bool compilationForRuntime; ///< Is set to true if the code generation is
|
||||
@@ -652,7 +731,7 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
gd::String customCodeInMain; ///< Custom code inserted before events ( in
|
||||
///< main function )
|
||||
std::set<gd::String>
|
||||
customGlobalDeclarations; ///< Custom global C++ declarations inserted
|
||||
customGlobalDeclarations; ///< Custom global C++ declarations inserted
|
||||
///< after includes
|
||||
size_t maxCustomConditionsDepth; ///< The maximum depth value for all the
|
||||
///< custom conditions created.
|
||||
|
465
Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.cpp
Normal file
@@ -0,0 +1,465 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ExpressionCodeGenerator.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
// Compatibility with old ExpressionParser
|
||||
#include "GDCore/Events/CodeGeneration/ExpressionsCodeGeneration.h"
|
||||
#include "GDCore/Events/CodeGeneration/VariableParserCallbacks.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser.h"
|
||||
#include "GDCore/Events/Parsers/VariableParser.h"
|
||||
// end of compatibility code
|
||||
|
||||
namespace gd {
|
||||
|
||||
bool ExpressionCodeGenerator::useOldExpressionParser = false;
|
||||
|
||||
gd::String ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
EventsCodeGenerator& codeGenerator,
|
||||
EventsCodeGenerationContext& context,
|
||||
const gd::String& type,
|
||||
const gd::String& expression,
|
||||
const gd::String& objectName) {
|
||||
// Compatibility with old ExpressionParser
|
||||
if (useOldExpressionParser) {
|
||||
if (type == "number") {
|
||||
gd::String code = "";
|
||||
gd::CallbacksForGeneratingExpressionCode callbacks(
|
||||
code, codeGenerator, context);
|
||||
gd::ExpressionParser parser(expression);
|
||||
if (!parser.ParseMathExpression(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
callbacks) ||
|
||||
code.empty()) {
|
||||
std::cout << "Error (old ExpressionParser): \""
|
||||
<< parser.GetFirstError() << "\" in: \"" << expression
|
||||
<< "\" (number)" << std::endl;
|
||||
code = "0";
|
||||
}
|
||||
|
||||
return code;
|
||||
} else if (type == "string") {
|
||||
gd::String code = "";
|
||||
gd::CallbacksForGeneratingExpressionCode callbacks(
|
||||
code, codeGenerator, context);
|
||||
gd::ExpressionParser parser(expression);
|
||||
if (!parser.ParseStringExpression(
|
||||
codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups(),
|
||||
callbacks) ||
|
||||
code.empty()) {
|
||||
std::cout << "Error (old ExpressionParser): \""
|
||||
<< parser.GetFirstError() << "\" in: \"" << expression
|
||||
<< "\" (string)" << std::endl;
|
||||
code = "\"\"";
|
||||
}
|
||||
|
||||
return code;
|
||||
} else if (type == "scenevar") {
|
||||
gd::String code = "";
|
||||
gd::VariableCodeGenerationCallbacks callbacks(
|
||||
code,
|
||||
codeGenerator,
|
||||
context,
|
||||
gd::EventsCodeGenerator::LAYOUT_VARIABLE);
|
||||
|
||||
gd::VariableParser parser(expression);
|
||||
if (!parser.Parse(callbacks)) {
|
||||
std::cout << "Error (old VariableParser) :" << parser.GetFirstError()
|
||||
<< " in: " << expression << std::endl;
|
||||
code = codeGenerator.GenerateBadVariable();
|
||||
}
|
||||
return code;
|
||||
} else if (type == "globalvar") {
|
||||
gd::String code = "";
|
||||
gd::VariableCodeGenerationCallbacks callbacks(
|
||||
code,
|
||||
codeGenerator,
|
||||
context,
|
||||
gd::EventsCodeGenerator::PROJECT_VARIABLE);
|
||||
|
||||
gd::VariableParser parser(expression);
|
||||
if (!parser.Parse(callbacks)) {
|
||||
std::cout << "Error (old VariableParser) :" << parser.GetFirstError()
|
||||
<< " in: " << expression << std::endl;
|
||||
code = codeGenerator.GenerateBadVariable();
|
||||
}
|
||||
return code;
|
||||
} else if (type == "objectvar") {
|
||||
gd::String code = "";
|
||||
|
||||
// Object is either the object of the previous parameter or, if it is
|
||||
// empty, the object being picked by the instruction.
|
||||
gd::String object =
|
||||
objectName.empty() ? context.GetCurrentObject() : objectName;
|
||||
|
||||
gd::VariableCodeGenerationCallbacks callbacks(
|
||||
code, codeGenerator, context, object);
|
||||
|
||||
gd::VariableParser parser(expression);
|
||||
if (!parser.Parse(callbacks)) {
|
||||
std::cout << "Error (old VariableParser) :" << parser.GetFirstError()
|
||||
<< " in: " << expression << std::endl;
|
||||
code = codeGenerator.GenerateBadVariable();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
std::cout << "Type error (old ExpressionParser): type \"" << type
|
||||
<< "\" is not supported" << std::endl;
|
||||
return "/* Error during code generation: type " + type +
|
||||
" is not supported for old ExpressionParser. */ 0";
|
||||
}
|
||||
// end of compatibility code
|
||||
|
||||
gd::ExpressionParser2 parser(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups());
|
||||
auto node = parser.ParseExpression(type, expression, objectName);
|
||||
gd::ExpressionValidator validator;
|
||||
node->Visit(validator);
|
||||
|
||||
ExpressionCodeGenerator generator(codeGenerator, context);
|
||||
if (!validator.GetErrors().empty()) {
|
||||
std::cout << "Error: \"" << validator.GetErrors()[0]->GetMessage()
|
||||
<< "\" in: \"" << expression << "\" (" << type << ")"
|
||||
<< std::endl;
|
||||
|
||||
return generator.GenerateDefaultValue(type);
|
||||
}
|
||||
|
||||
node->Visit(generator);
|
||||
return generator.GetOutput();
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitOperatorNode(OperatorNode& node) {
|
||||
node.leftHandSide->Visit(*this);
|
||||
output += " ";
|
||||
output.push_back(node.op);
|
||||
output += " ";
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitUnaryOperatorNode(
|
||||
UnaryOperatorNode& node) {
|
||||
output.push_back(node.op);
|
||||
output += "("; // Add extra parenthesis to ensure that things like --2 are
|
||||
// properly outputted as -(-2) (GDevelop don't have -- or ++
|
||||
// operators, but JavaScript and C++ have).
|
||||
node.factor->Visit(*this);
|
||||
output += ")";
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitSubExpressionNode(
|
||||
SubExpressionNode& node) {
|
||||
output += "(";
|
||||
node.expression->Visit(*this);
|
||||
output += ")";
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitNumberNode(NumberNode& node) {
|
||||
output += node.number;
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitTextNode(TextNode& node) {
|
||||
output += codeGenerator.ConvertToStringExplicit(node.text);
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
|
||||
// This "translation" from the type to an enum could be avoided
|
||||
// if all types were moved to an enum.
|
||||
EventsCodeGenerator::VariableScope scope =
|
||||
node.type == "globalvar"
|
||||
? gd::EventsCodeGenerator::PROJECT_VARIABLE
|
||||
: ((node.type == "scenevar")
|
||||
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
|
||||
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
|
||||
|
||||
output += codeGenerator.GenerateGetVariable(
|
||||
node.name, scope, context, node.objectName);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitVariableAccessorNode(
|
||||
VariableAccessorNode& node) {
|
||||
output += codeGenerator.GenerateVariableAccessor(node.name);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) {
|
||||
ExpressionCodeGenerator generator(codeGenerator, context);
|
||||
node.expression->Visit(generator);
|
||||
output +=
|
||||
codeGenerator.GenerateVariableBracketAccessor(generator.GetOutput());
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
|
||||
if (gd::ParameterMetadata::IsObject(node.type)) {
|
||||
output +=
|
||||
codeGenerator.GenerateObject(node.identifierName, node.type, context);
|
||||
} else {
|
||||
output += "/* Error during generation, unrecognized identifier type: " +
|
||||
codeGenerator.ConvertToString(node.type) + " with value " +
|
||||
codeGenerator.ConvertToString(node.identifierName) + " */ " +
|
||||
codeGenerator.ConvertToStringExplicit(node.identifierName);
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitFunctionNode(FunctionNode& node) {
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(node.expressionMetadata)) {
|
||||
output += "/* Error during generation, function not found: " +
|
||||
codeGenerator.ConvertToString(node.functionName) + " for type " +
|
||||
node.type + " */ " + GenerateDefaultValue(node.type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.objectName.empty()) {
|
||||
if (!node.behaviorName.empty()) {
|
||||
output += GenerateBehaviorFunctionCode(node.type,
|
||||
node.objectName,
|
||||
node.behaviorName,
|
||||
node.parameters,
|
||||
node.expressionMetadata);
|
||||
} else {
|
||||
output += GenerateObjectFunctionCode(
|
||||
node.type, node.objectName, node.parameters, node.expressionMetadata);
|
||||
}
|
||||
} else {
|
||||
output +=
|
||||
GenerateFreeFunctionCode(node.parameters, node.expressionMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
gd::String ExpressionCodeGenerator::GenerateFreeFunctionCode(
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata) {
|
||||
codeGenerator.AddIncludeFiles(
|
||||
expressionMetadata.codeExtraInformation.GetIncludeFiles());
|
||||
|
||||
// Launch custom code generator if needed
|
||||
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
|
||||
return expressionMetadata.codeExtraInformation.customCodeGenerator(
|
||||
PrintParameters(parameters), codeGenerator, context);
|
||||
}
|
||||
|
||||
gd::String parametersCode =
|
||||
GenerateParametersCodes(parameters, expressionMetadata, 0);
|
||||
|
||||
return expressionMetadata.codeExtraInformation.functionCallName + "(" +
|
||||
parametersCode + ")";
|
||||
}
|
||||
|
||||
gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
|
||||
const gd::String& type,
|
||||
const gd::String& objectName,
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata) {
|
||||
const gd::ObjectsContainer& globalObjectsAndGroups =
|
||||
codeGenerator.GetGlobalObjectsAndGroups();
|
||||
const gd::ObjectsContainer& objectsAndGroups =
|
||||
codeGenerator.GetObjectsAndGroups();
|
||||
|
||||
codeGenerator.AddIncludeFiles(
|
||||
expressionMetadata.codeExtraInformation.GetIncludeFiles());
|
||||
|
||||
// Launch custom code generator if needed
|
||||
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
|
||||
return expressionMetadata.codeExtraInformation.customCodeGenerator(
|
||||
PrintParameters(parameters), codeGenerator, context);
|
||||
}
|
||||
|
||||
// Prepare parameters
|
||||
gd::String parametersCode = GenerateParametersCodes(
|
||||
parameters,
|
||||
expressionMetadata,
|
||||
// By convention, the first parameter is the object
|
||||
1);
|
||||
|
||||
gd::String functionOutput = GenerateDefaultValue(type);
|
||||
|
||||
// Get object(s) concerned by function call
|
||||
std::vector<gd::String> realObjects =
|
||||
codeGenerator.ExpandObjectsName(objectName, context);
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
|
||||
gd::String objectType = gd::GetTypeOfObject(
|
||||
globalObjectsAndGroups, objectsAndGroups, realObjects[i]);
|
||||
const ObjectMetadata& objInfo = MetadataProvider::GetObjectMetadata(
|
||||
codeGenerator.GetPlatform(), objectType);
|
||||
|
||||
codeGenerator.AddIncludeFiles(objInfo.includeFiles);
|
||||
functionOutput = codeGenerator.GenerateObjectFunctionCall(
|
||||
realObjects[i],
|
||||
objInfo,
|
||||
expressionMetadata.codeExtraInformation,
|
||||
parametersCode,
|
||||
functionOutput,
|
||||
context);
|
||||
}
|
||||
|
||||
return functionOutput;
|
||||
}
|
||||
gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
|
||||
const gd::String& type,
|
||||
const gd::String& objectName,
|
||||
const gd::String& behaviorName,
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata) {
|
||||
const gd::ObjectsContainer& globalObjectsAndGroups =
|
||||
codeGenerator.GetGlobalObjectsAndGroups();
|
||||
const gd::ObjectsContainer& objectsAndGroups =
|
||||
codeGenerator.GetObjectsAndGroups();
|
||||
|
||||
codeGenerator.AddIncludeFiles(
|
||||
expressionMetadata.codeExtraInformation.GetIncludeFiles());
|
||||
|
||||
// Launch custom code generator if needed
|
||||
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
|
||||
return expressionMetadata.codeExtraInformation.customCodeGenerator(
|
||||
PrintParameters(parameters), codeGenerator, context);
|
||||
}
|
||||
|
||||
// Prepare parameters
|
||||
gd::String parametersCode = GenerateParametersCodes(
|
||||
parameters,
|
||||
expressionMetadata,
|
||||
// By convention, the first parameters are the object and behavior
|
||||
2);
|
||||
|
||||
// Get object(s) concerned by function call
|
||||
std::vector<gd::String> realObjects =
|
||||
codeGenerator.ExpandObjectsName(objectName, context);
|
||||
|
||||
gd::String functionOutput = GenerateDefaultValue(type);
|
||||
|
||||
gd::String behaviorType = gd::GetTypeOfBehavior(
|
||||
globalObjectsAndGroups, objectsAndGroups, behaviorName);
|
||||
const BehaviorMetadata& autoInfo = MetadataProvider::GetBehaviorMetadata(
|
||||
codeGenerator.GetPlatform(), behaviorType);
|
||||
|
||||
for (std::size_t i = 0; i < realObjects.size(); ++i) {
|
||||
context.ObjectsListNeeded(realObjects[i]);
|
||||
|
||||
codeGenerator.AddIncludeFiles(autoInfo.includeFiles);
|
||||
functionOutput = codeGenerator.GenerateObjectBehaviorFunctionCall(
|
||||
realObjects[i],
|
||||
behaviorName,
|
||||
autoInfo,
|
||||
expressionMetadata.codeExtraInformation,
|
||||
parametersCode,
|
||||
functionOutput,
|
||||
context);
|
||||
}
|
||||
|
||||
return functionOutput;
|
||||
}
|
||||
|
||||
gd::String ExpressionCodeGenerator::GenerateParametersCodes(
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata,
|
||||
size_t initialParameterIndex) {
|
||||
size_t nonCodeOnlyParameterIndex = 0;
|
||||
gd::String parametersCode;
|
||||
for (std::size_t i = initialParameterIndex;
|
||||
i < expressionMetadata.parameters.size();
|
||||
++i) {
|
||||
if (i != initialParameterIndex) parametersCode += ", ";
|
||||
|
||||
auto& parameterMetadata = expressionMetadata.parameters[i];
|
||||
if (!parameterMetadata.IsCodeOnly()) {
|
||||
ExpressionCodeGenerator generator(codeGenerator, context);
|
||||
if (nonCodeOnlyParameterIndex < parameters.size()) {
|
||||
parameters[nonCodeOnlyParameterIndex]->Visit(generator);
|
||||
parametersCode += generator.GetOutput();
|
||||
} else if (parameterMetadata.IsOptional()) {
|
||||
// Optional parameters default value were not parsed at the time of the
|
||||
// expression parsing. Parse them now.
|
||||
ExpressionParser2 parser(codeGenerator.GetPlatform(),
|
||||
codeGenerator.GetGlobalObjectsAndGroups(),
|
||||
codeGenerator.GetObjectsAndGroups());
|
||||
auto node = parser.ParseExpression(parameterMetadata.GetType(),
|
||||
parameterMetadata.GetDefaultValue());
|
||||
|
||||
node->Visit(generator);
|
||||
parametersCode += generator.GetOutput();
|
||||
} else {
|
||||
parametersCode +=
|
||||
"/* Error during generation, parameter not existing in the nodes "
|
||||
"*/ " +
|
||||
GenerateDefaultValue(parameterMetadata.GetType());
|
||||
}
|
||||
|
||||
nonCodeOnlyParameterIndex++;
|
||||
} else {
|
||||
parametersCode +=
|
||||
codeGenerator.GenerateParameterCodes(parameterMetadata.GetExtraInfo(),
|
||||
parameterMetadata,
|
||||
context,
|
||||
"",
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
return parametersCode;
|
||||
}
|
||||
|
||||
std::vector<gd::Expression> ExpressionCodeGenerator::PrintParameters(
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters) {
|
||||
// Printing parameters is only useful because custom code generator of
|
||||
// expression require to get the parameters of the expression as strings
|
||||
// (gd::Expression). Once the old ExpressionParser is removed, custom
|
||||
// code generator can be reworked to directly take the parsed nodes,
|
||||
// avoiding an extra and useless printing/parsing of their parameters.
|
||||
|
||||
std::vector<gd::Expression> printedParameters;
|
||||
for (auto& parameter : parameters) {
|
||||
printedParameters.push_back(
|
||||
gd::ExpressionParser2NodePrinter::PrintNode(*parameter));
|
||||
}
|
||||
|
||||
return printedParameters;
|
||||
}
|
||||
|
||||
gd::String ExpressionCodeGenerator::GenerateDefaultValue(
|
||||
const gd::String& type) {
|
||||
if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
return codeGenerator.GenerateBadVariable();
|
||||
}
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
return codeGenerator.GenerateBadObject();
|
||||
}
|
||||
|
||||
return (type == "string") ? "\"\"" : "0";
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
|
||||
output += GenerateDefaultValue(node.type);
|
||||
}
|
||||
|
||||
} // namespace gd
|
117
Core/GDCore/Events/CodeGeneration/ExpressionCodeGenerator.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#ifndef GDCORE_ExpressionCodeGenerator_H
|
||||
#define GDCORE_ExpressionCodeGenerator_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
class Platform;
|
||||
class ParameterMetadata;
|
||||
class ExpressionMetadata;
|
||||
class EventsCodeGenerationContext;
|
||||
class EventsCodeGenerator;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Generate code for a parsed expression.
|
||||
*
|
||||
* Almost all code generation is dedicated to the gd::EventsCodeGenerator,
|
||||
* so that it can be adapted to the target.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionCodeGenerator(EventsCodeGenerator& codeGenerator_,
|
||||
EventsCodeGenerationContext& context_)
|
||||
: codeGenerator(codeGenerator_), context(context_){};
|
||||
virtual ~ExpressionCodeGenerator(){};
|
||||
|
||||
/**
|
||||
* Helper to generate the code for an expression.
|
||||
* If expression is invalid, a default generated value is returned (0 for
|
||||
* number expression, empty string for strings).
|
||||
*
|
||||
* \param codeGenerator The code generator to use to output code.
|
||||
* \param context The context of the code generation.
|
||||
* \param type The type of the expression (see gd::ExpressionParser2).
|
||||
* \param expression The expression to parse and generate code for.
|
||||
* \param object The object the expression refers too (only for "objectvar"
|
||||
* type).
|
||||
*
|
||||
* \see see gd::ExpressionParser2
|
||||
*/
|
||||
static gd::String GenerateExpressionCode(EventsCodeGenerator& codeGenerator,
|
||||
EventsCodeGenerationContext& context,
|
||||
const gd::String& type,
|
||||
const gd::String& expression,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
static void UseOldExpressionParser(bool enable) {
|
||||
useOldExpressionParser = enable;
|
||||
};
|
||||
static bool IsUsingOldExpressionParser() { return useOldExpressionParser; };
|
||||
|
||||
const gd::String& GetOutput() { return output; };
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override;
|
||||
void OnVisitOperatorNode(OperatorNode& node) override;
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override;
|
||||
void OnVisitNumberNode(NumberNode& node) override;
|
||||
void OnVisitTextNode(TextNode& node) override;
|
||||
void OnVisitVariableNode(VariableNode& node) override;
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override;
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override;
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override;
|
||||
void OnVisitFunctionNode(FunctionNode& node) override;
|
||||
void OnVisitEmptyNode(EmptyNode& node) override;
|
||||
|
||||
private:
|
||||
gd::String GenerateFreeFunctionCode(
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata);
|
||||
gd::String GenerateObjectFunctionCode(
|
||||
const gd::String& type,
|
||||
const gd::String& objectName,
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata);
|
||||
gd::String GenerateBehaviorFunctionCode(
|
||||
const gd::String& type,
|
||||
const gd::String& objectName,
|
||||
const gd::String& behaviorName,
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata);
|
||||
gd::String GenerateParametersCodes(
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
|
||||
const ExpressionMetadata& expressionMetadata,
|
||||
size_t initialParameterIndex);
|
||||
gd::String GenerateDefaultValue(const gd::String& type);
|
||||
static std::vector<gd::Expression> PrintParameters(
|
||||
const std::vector<std::unique_ptr<ExpressionNode>>& parameters);
|
||||
|
||||
gd::String output;
|
||||
EventsCodeGenerator& codeGenerator;
|
||||
EventsCodeGenerationContext& context;
|
||||
|
||||
static bool useOldExpressionParser;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_ExpressionCodeGenerator_H
|
||||
#endif
|
@@ -11,28 +11,18 @@
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class ExpressionMetadata;
|
||||
}
|
||||
namespace gd {
|
||||
class Expression;
|
||||
}
|
||||
namespace gd {
|
||||
class Project;
|
||||
}
|
||||
namespace gd {
|
||||
class Layout;
|
||||
}
|
||||
namespace gd {
|
||||
class Layout;
|
||||
}
|
||||
namespace gd {
|
||||
class EventsCodeGenerationContext;
|
||||
}
|
||||
namespace gd {
|
||||
class EventsCodeGenerator;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
// TODO: Replace and remove (ExpressionCodeGenerator)
|
||||
|
||||
/**
|
||||
* \brief Used to generate code from expressions.
|
||||
*
|
||||
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* GDevelop C++ Platform
|
||||
* 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)
|
||||
#include "VariableParserCallbacks.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
|
||||
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
|
||||
#include "GDCore/Events/CodeGeneration/ExpressionCodeGenerator.h"
|
||||
#include "GDCore/Events/Parsers/VariableParser.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
VariableCodeGenerationCallbacks::VariableCodeGenerationCallbacks(
|
||||
gd::String& output_,
|
||||
gd::EventsCodeGenerator& codeGenerator_,
|
||||
gd::EventsCodeGenerationContext& context_,
|
||||
const gd::EventsCodeGenerator::VariableScope& scope_)
|
||||
: output(output_),
|
||||
codeGenerator(codeGenerator_),
|
||||
context(context_),
|
||||
scope(scope_) {
|
||||
if (scope == gd::EventsCodeGenerator::OBJECT_VARIABLE) {
|
||||
std::cout << "ERROR: Initializing VariableCodeGenerationCallbacks with "
|
||||
"OBJECT_VARIABLE without object.";
|
||||
}
|
||||
}
|
||||
|
||||
VariableCodeGenerationCallbacks::VariableCodeGenerationCallbacks(
|
||||
gd::String& output_,
|
||||
gd::EventsCodeGenerator& codeGenerator_,
|
||||
gd::EventsCodeGenerationContext& context_,
|
||||
const gd::String& object_)
|
||||
: output(output_),
|
||||
codeGenerator(codeGenerator_),
|
||||
context(context_),
|
||||
scope(gd::EventsCodeGenerator::OBJECT_VARIABLE),
|
||||
object(object_) {}
|
||||
|
||||
void VariableCodeGenerationCallbacks::OnRootVariable(gd::String variableName) {
|
||||
output += codeGenerator.GenerateGetVariable(variableName, scope, context, object);
|
||||
}
|
||||
|
||||
void VariableCodeGenerationCallbacks::OnChildVariable(gd::String variableName) {
|
||||
output += codeGenerator.GenerateVariableAccessor(variableName);
|
||||
}
|
||||
|
||||
void VariableCodeGenerationCallbacks::OnChildSubscript(
|
||||
gd::String stringExpression) {
|
||||
gd::String argumentCode = gd::ExpressionCodeGenerator::GenerateExpressionCode(
|
||||
codeGenerator, context, "string", stringExpression);
|
||||
|
||||
output += codeGenerator.GenerateVariableBracketAccessor(argumentCode);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
@@ -10,12 +10,15 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "GDCore/Events/Parsers/VariableParser.h"
|
||||
#include "GDCpp/Runtime/String.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "EventsCodeGenerator.h"
|
||||
namespace gd {
|
||||
class EventsCodeGenerator;
|
||||
class EventsCodeGenerationContext;
|
||||
} // namespace gd
|
||||
|
||||
// TODO: Replace and remove (ExpressionCodeGenerator)
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Callbacks called to generate the code for getting a variable.
|
||||
*
|
||||
@@ -36,8 +39,6 @@ class EventsCodeGenerationContext;
|
||||
*/
|
||||
class VariableCodeGenerationCallbacks : public gd::VariableParserCallbacks {
|
||||
public:
|
||||
enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE };
|
||||
|
||||
/**
|
||||
* \brief Default constructor for generating code for a layout/global
|
||||
* variable. \param output The string in which the code will be generated.
|
||||
@@ -49,7 +50,7 @@ class VariableCodeGenerationCallbacks : public gd::VariableParserCallbacks {
|
||||
VariableCodeGenerationCallbacks(gd::String& output,
|
||||
gd::EventsCodeGenerator& codeGenerator_,
|
||||
gd::EventsCodeGenerationContext& context_,
|
||||
const VariableScope& scope_);
|
||||
const gd::EventsCodeGenerator::VariableScope& scope_);
|
||||
/**
|
||||
|
||||
* \brief Default constructor for generating code for an object variable.
|
||||
@@ -86,9 +87,11 @@ class VariableCodeGenerationCallbacks : public gd::VariableParserCallbacks {
|
||||
gd::String& output;
|
||||
gd::EventsCodeGenerator& codeGenerator;
|
||||
gd::EventsCodeGenerationContext& context;
|
||||
VariableScope scope;
|
||||
gd::EventsCodeGenerator::VariableScope scope;
|
||||
const gd::String object; ///< The object name, when scope == OBJECT_VARIABLE.
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VARIABLEPARSERCALLBACKS_H
|
||||
#endif
|
@@ -717,9 +717,6 @@ bool ExpressionParser::ParseStringExpression(const gd::Platform& platform,
|
||||
firstErrorPos = functionNameEnd;
|
||||
firstErrorStr = _("Incorrect number of parameters");
|
||||
|
||||
for (std::size_t i = 0; i < parameters.size(); ++i)
|
||||
cout << "Param:" << parameters[i].GetPlainString() << endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
220
Core/GDCore/Events/Parsers/ExpressionParser2.cpp
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
gd::String ExpressionParser2::NUMBER_FIRST_CHAR = ".0123456789";
|
||||
gd::String ExpressionParser2::DOT = ".";
|
||||
gd::String ExpressionParser2::PARAMETERS_SEPARATOR = ",";
|
||||
gd::String ExpressionParser2::QUOTE = "\"";
|
||||
gd::String ExpressionParser2::BRACKETS = "()[]{}";
|
||||
gd::String ExpressionParser2::EXPRESSION_OPERATORS = "+-<>?^=\\:!";
|
||||
gd::String ExpressionParser2::TERM_OPERATORS = "/*";
|
||||
gd::String ExpressionParser2::UNARY_OPERATORS = "+-";
|
||||
gd::String ExpressionParser2::WHITESPACES = " \n\r";
|
||||
gd::String ExpressionParser2::NAMESPACE_SEPARATOR = "::";
|
||||
|
||||
ExpressionParser2::ExpressionParser2(
|
||||
const gd::Platform& platform_,
|
||||
const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_)
|
||||
: expression(""),
|
||||
currentPosition(0),
|
||||
platform(platform_),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_) {}
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Return the minimum number of parameters, starting from a given parameter
|
||||
* (by convention, 1 for object functions and 2 for behavior functions).
|
||||
*/
|
||||
size_t GetMinimumParametersNumber(
|
||||
const std::vector<gd::ParameterMetadata>& parameters,
|
||||
size_t initialParameterIndex) {
|
||||
size_t nb = 0;
|
||||
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
|
||||
if (!parameters[i].optional && !parameters[i].codeOnly) nb++;
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum number of parameters, starting from a given parameter
|
||||
* (by convention, 1 for object functions and 2 for behavior functions).
|
||||
*/
|
||||
size_t GetMaximumParametersNumber(
|
||||
const std::vector<gd::ParameterMetadata>& parameters,
|
||||
size_t initialParameterIndex) {
|
||||
size_t nb = 0;
|
||||
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
|
||||
if (!parameters[i].codeOnly) nb++;
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<ExpressionParserDiagnostic> ExpressionParser2::ValidateFunction(
|
||||
const gd::FunctionNode& function, size_t functionStartPosition) {
|
||||
if (gd::MetadataProvider::IsBadExpressionMetadata(
|
||||
function.expressionMetadata)) {
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_function_name",
|
||||
_("Cannot find an expression with this name: ") +
|
||||
function.functionName + "\n" +
|
||||
_("Double check that you've not made any typo in the name."),
|
||||
functionStartPosition,
|
||||
GetCurrentPosition());
|
||||
}
|
||||
|
||||
size_t minParametersCount = GetMinimumParametersNumber(
|
||||
function.expressionMetadata.parameters,
|
||||
WrittenParametersFirstIndex(function.objectName, function.behaviorName));
|
||||
size_t maxParametersCount = GetMaximumParametersNumber(
|
||||
function.expressionMetadata.parameters,
|
||||
WrittenParametersFirstIndex(function.objectName, function.behaviorName));
|
||||
if (function.parameters.size() < minParametersCount ||
|
||||
function.parameters.size() > maxParametersCount) {
|
||||
gd::String expectedCountMessage =
|
||||
minParametersCount == maxParametersCount
|
||||
? _("The number of parameters must be exactly ") +
|
||||
gd::String::From(minParametersCount)
|
||||
: _("The number of parameters must be: ") +
|
||||
gd::String::From(minParametersCount) + "-" +
|
||||
gd::String::From(maxParametersCount);
|
||||
|
||||
if (function.parameters.size() < minParametersCount) {
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"too_few_parameters",
|
||||
"You have not entered enough parameters for the expression. " +
|
||||
expectedCountMessage,
|
||||
functionStartPosition,
|
||||
GetCurrentPosition());
|
||||
}
|
||||
}
|
||||
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
}
|
||||
|
||||
std::unique_ptr<TextNode> ExpressionParser2::ReadText() {
|
||||
SkipWhitespace();
|
||||
if (!IsAnyChar("\"")) {
|
||||
auto text = gd::make_unique<TextNode>("");
|
||||
text->diagnostic =
|
||||
RaiseSyntaxError(_("A text must start with a double quote (\")."));
|
||||
return text;
|
||||
}
|
||||
SkipChar();
|
||||
|
||||
gd::String parsedText = "";
|
||||
bool textParsingHasEnded = false;
|
||||
bool expectEscapedCharacter = false;
|
||||
while (!IsEndReached() && !textParsingHasEnded) {
|
||||
if (GetCurrentChar() == '"') {
|
||||
if (expectEscapedCharacter) {
|
||||
parsedText += '"';
|
||||
expectEscapedCharacter = false;
|
||||
} else {
|
||||
textParsingHasEnded = true;
|
||||
}
|
||||
} else if (GetCurrentChar() == '\\') {
|
||||
if (expectEscapedCharacter) {
|
||||
parsedText += '\\';
|
||||
expectEscapedCharacter = false;
|
||||
} else {
|
||||
expectEscapedCharacter = true;
|
||||
}
|
||||
} else {
|
||||
if (expectEscapedCharacter) {
|
||||
parsedText += '\\';
|
||||
}
|
||||
|
||||
parsedText += GetCurrentChar();
|
||||
}
|
||||
|
||||
currentPosition++;
|
||||
}
|
||||
|
||||
auto text = gd::make_unique<TextNode>(parsedText);
|
||||
if (!textParsingHasEnded) {
|
||||
text->diagnostic =
|
||||
RaiseSyntaxError(_("A text must end with a double quote (\"). Add a "
|
||||
"double quote to terminate the text."));
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
std::unique_ptr<NumberNode> ExpressionParser2::ReadNumber() {
|
||||
SkipWhitespace();
|
||||
gd::String parsedNumber;
|
||||
|
||||
bool numberHasStarted = false;
|
||||
bool digitFound = false;
|
||||
bool dotFound = false;
|
||||
while (!IsEndReached()) {
|
||||
if (IsAnyChar("0")) {
|
||||
numberHasStarted = true;
|
||||
digitFound = true;
|
||||
if (!parsedNumber.empty()) { // Ignore leading 0s.
|
||||
parsedNumber += GetCurrentChar();
|
||||
}
|
||||
} else if (IsAnyChar("123456789")) {
|
||||
numberHasStarted = true;
|
||||
digitFound = true;
|
||||
parsedNumber += GetCurrentChar();
|
||||
} else if (IsAnyChar(".") && !dotFound) {
|
||||
numberHasStarted = true;
|
||||
dotFound = true;
|
||||
if (parsedNumber == "") {
|
||||
parsedNumber += "0."; //Normalize by adding a leading 0, only in this case.
|
||||
} else {
|
||||
parsedNumber += ".";
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
currentPosition++;
|
||||
}
|
||||
|
||||
// parsedNumber can be empty in the only case where we have only seen
|
||||
// 0s (one or more), so normalize it to a single 0.
|
||||
if (parsedNumber.empty()) {
|
||||
parsedNumber = "0";
|
||||
}
|
||||
|
||||
// Note that parsedNumber can finish by a dot (1., 2., 0.). This is
|
||||
// valid in most languages so we allow this.
|
||||
|
||||
auto number = gd::make_unique<NumberNode>(parsedNumber);
|
||||
if (!numberHasStarted || !digitFound) {
|
||||
number->diagnostic = RaiseSyntaxError(
|
||||
_("A number was expected. You must enter a number here."));
|
||||
}
|
||||
|
||||
return number;
|
||||
}
|
||||
|
||||
} // namespace gd
|
763
Core/GDCore/Events/Parsers/ExpressionParser2.h
Normal file
@@ -0,0 +1,763 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EXPRESSIONPARSER2_H
|
||||
#define GDCORE_EXPRESSIONPARSER2_H
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "ExpressionParser2Node.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Project/Layout.h" // For GetTypeOfObject and GetTypeOfBehavior
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
class Platform;
|
||||
class ParameterMetadata;
|
||||
class ExpressionMetadata;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/** \brief Parse an expression, returning a tree of node corresponding
|
||||
* to the parsed expression.
|
||||
*
|
||||
* This is a LL(1) parser. This could be extracted to a generic/reusable
|
||||
* parser by refactoring out the dependency on gd::MetadataProvider (injecting
|
||||
* instead functions to be called to query supported functions).
|
||||
*
|
||||
* \see gd::ExpressionParserDiagnostic
|
||||
* \see gd::ExpressionNode
|
||||
*/
|
||||
class GD_CORE_API ExpressionParser2 {
|
||||
public:
|
||||
ExpressionParser2(const gd::Platform &platform_,
|
||||
const gd::ObjectsContainer &globalObjectsContainer_,
|
||||
const gd::ObjectsContainer &objectsContainer_);
|
||||
virtual ~ExpressionParser2(){};
|
||||
|
||||
/**
|
||||
* Parse the given expression with the specified type.
|
||||
*
|
||||
* \param type Type of the expression: "string", "number",
|
||||
* type supported by gd::ParameterMetadata::IsObject, types supported by
|
||||
* gd::ParameterMetadata::IsExpression or "unknown". \param expression The
|
||||
* expression to parse \param objectName Specify the object name, only for the
|
||||
* case of "objectvar" type.
|
||||
*
|
||||
* \return The node representing the expression as a parsed tree.
|
||||
*/
|
||||
std::unique_ptr<ExpressionNode> ParseExpression(
|
||||
const gd::String &type,
|
||||
const gd::String &expression_,
|
||||
const gd::String &objectName = "") {
|
||||
expression = expression_;
|
||||
|
||||
currentPosition = 0;
|
||||
return Start(type, objectName);
|
||||
}
|
||||
|
||||
private:
|
||||
/** \name Grammar
|
||||
* Each method is a part of the grammar.
|
||||
*/
|
||||
///@{
|
||||
std::unique_ptr<ExpressionNode> Start(const gd::String &type,
|
||||
const gd::String &objectName = "") {
|
||||
auto expression = Expression(type, objectName);
|
||||
|
||||
// Check for extra characters at the end of the expression
|
||||
if (!IsEndReached()) {
|
||||
auto op = gd::make_unique<OperatorNode>();
|
||||
op->op = ' ';
|
||||
op->leftHandSide = std::move(expression);
|
||||
op->rightHandSide = ReadUntilEnd("unknown");
|
||||
|
||||
op->rightHandSide->diagnostic = RaiseSyntaxError(
|
||||
_("The expression has extra character at the end that should be "
|
||||
"removed (or completed if your expression is not finished)."));
|
||||
return std::move(op);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
std::unique_ptr<ExpressionNode> Expression(
|
||||
const gd::String &type, const gd::String &objectName = "") {
|
||||
SkipWhitespace();
|
||||
|
||||
size_t expressionStartPosition = GetCurrentPosition();
|
||||
std::unique_ptr<ExpressionNode> leftHandSide = Term(type, objectName);
|
||||
|
||||
SkipWhitespace();
|
||||
|
||||
if (IsEndReached()) return leftHandSide;
|
||||
if (IsAnyChar(",)]")) return leftHandSide;
|
||||
if (IsAnyChar(EXPRESSION_OPERATORS)) {
|
||||
auto op = gd::make_unique<OperatorNode>();
|
||||
op->op = GetCurrentChar();
|
||||
op->leftHandSide = std::move(leftHandSide);
|
||||
op->diagnostic = ValidateOperator(type, GetCurrentChar());
|
||||
SkipChar();
|
||||
op->rightHandSide = Expression(type, objectName);
|
||||
return std::move(op);
|
||||
}
|
||||
|
||||
if (type == "string") {
|
||||
leftHandSide->diagnostic = RaiseSyntaxError(
|
||||
"You must add the operator + between texts or expressions. For "
|
||||
"example: \"Your name: \" + VariableString(PlayerName).");
|
||||
} else if (type == "number") {
|
||||
leftHandSide->diagnostic = RaiseSyntaxError(
|
||||
"No operator found. Did you forget to enter an operator (like +, -, "
|
||||
"* or /) between numbers or expressions?");
|
||||
} else {
|
||||
leftHandSide->diagnostic = RaiseSyntaxError(
|
||||
"More than one term was found. Verify that your expression is "
|
||||
"properly written.");
|
||||
}
|
||||
|
||||
auto op = gd::make_unique<OperatorNode>();
|
||||
op->op = ' ';
|
||||
op->leftHandSide = std::move(leftHandSide);
|
||||
op->rightHandSide = Expression(type, objectName);
|
||||
return std::move(op);
|
||||
}
|
||||
|
||||
std::unique_ptr<ExpressionNode> Term(const gd::String &type,
|
||||
const gd::String &objectName) {
|
||||
SkipWhitespace();
|
||||
|
||||
std::unique_ptr<ExpressionNode> factor = Factor(type, objectName);
|
||||
SkipWhitespace();
|
||||
|
||||
// This while loop is used instead of a recursion (like in Expression)
|
||||
// to guarantee the proper operator precedence. (Expression could also
|
||||
// be reworked to use a while loop).
|
||||
while (IsAnyChar(TERM_OPERATORS)) {
|
||||
auto op = gd::make_unique<OperatorNode>();
|
||||
op->op = GetCurrentChar();
|
||||
op->leftHandSide = std::move(factor);
|
||||
op->diagnostic = ValidateOperator(type, GetCurrentChar());
|
||||
SkipChar();
|
||||
op->rightHandSide = Factor(type, objectName);
|
||||
SkipWhitespace();
|
||||
|
||||
factor = std::move(op);
|
||||
}
|
||||
|
||||
return factor;
|
||||
};
|
||||
|
||||
std::unique_ptr<ExpressionNode> Factor(const gd::String &type,
|
||||
const gd::String &objectName) {
|
||||
SkipWhitespace();
|
||||
|
||||
size_t expressionStartPosition = GetCurrentPosition();
|
||||
std::unique_ptr<ExpressionNode> factor;
|
||||
|
||||
if (IsAnyChar(QUOTE)) {
|
||||
factor = ReadText();
|
||||
if (type == "number")
|
||||
factor->diagnostic =
|
||||
RaiseTypeError(_("You entered a text, but a number was expected."),
|
||||
expressionStartPosition);
|
||||
else if (type != "string")
|
||||
factor->diagnostic = RaiseTypeError(
|
||||
_("You entered a text, but this type was expected:") + type,
|
||||
expressionStartPosition);
|
||||
} else if (IsAnyChar(UNARY_OPERATORS)) {
|
||||
auto unaryOperator = gd::make_unique<UnaryOperatorNode>(GetCurrentChar());
|
||||
unaryOperator->diagnostic = ValidateUnaryOperator(type, GetCurrentChar());
|
||||
SkipChar();
|
||||
unaryOperator->factor = Factor(type, objectName);
|
||||
|
||||
factor = std::move(unaryOperator);
|
||||
} else if (IsAnyChar(NUMBER_FIRST_CHAR)) {
|
||||
factor = ReadNumber();
|
||||
if (type == "string")
|
||||
factor->diagnostic = RaiseTypeError(
|
||||
_("You entered a number, but a text was expected (in quotes)."),
|
||||
expressionStartPosition);
|
||||
else if (type != "number")
|
||||
factor->diagnostic = RaiseTypeError(
|
||||
_("You entered a number, but this type was expected:") + type,
|
||||
expressionStartPosition);
|
||||
} else if (IsAnyChar("(")) {
|
||||
SkipChar();
|
||||
factor = SubExpression(type, objectName);
|
||||
|
||||
if (!IsAnyChar(")")) {
|
||||
factor->diagnostic =
|
||||
RaiseSyntaxError(_("Missing a closing parenthesis. Add a closing "
|
||||
"parenthesis for each opening parenthesis."));
|
||||
}
|
||||
SkipIfIsAnyChar(")");
|
||||
} else if (IsIdentifierAllowedChar()) {
|
||||
// This is a place where the grammar differs according to the
|
||||
// type being expected.
|
||||
if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
factor = Variable(type, objectName);
|
||||
} else {
|
||||
factor = Identifier(type);
|
||||
}
|
||||
} else {
|
||||
factor = ReadUntilWhitespace(type);
|
||||
factor->diagnostic = RaiseEmptyError(type, expressionStartPosition);
|
||||
}
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
std::unique_ptr<SubExpressionNode> SubExpression(
|
||||
const gd::String &type, const gd::String &objectName) {
|
||||
return std::move(
|
||||
gd::make_unique<SubExpressionNode>(Expression(type, objectName)));
|
||||
};
|
||||
|
||||
std::unique_ptr<IdentifierOrFunctionOrEmptyNode> Identifier(
|
||||
const gd::String &type) {
|
||||
size_t identifierStartPosition = GetCurrentPosition();
|
||||
gd::String name = ReadIdentifierName();
|
||||
|
||||
SkipWhitespace();
|
||||
|
||||
if (IsNamespaceSeparator()) {
|
||||
SkipNamespaceSeparator();
|
||||
|
||||
name += NAMESPACE_SEPARATOR;
|
||||
name += ReadIdentifierName();
|
||||
}
|
||||
|
||||
if (IsAnyChar("(")) {
|
||||
SkipChar();
|
||||
return FreeFunction(type, name, identifierStartPosition);
|
||||
} else if (IsAnyChar(DOT)) {
|
||||
SkipChar();
|
||||
return ObjectFunctionOrBehaviorFunction(
|
||||
type, name, identifierStartPosition);
|
||||
} else {
|
||||
auto identifier = gd::make_unique<IdentifierNode>(name, type);
|
||||
if (type == "string") {
|
||||
identifier->diagnostic =
|
||||
RaiseTypeError(_("You must wrap your text inside double quotes "
|
||||
"(example: \"Hello world\")."),
|
||||
identifierStartPosition);
|
||||
} else if (type == "number") {
|
||||
identifier->diagnostic = RaiseTypeError(_("You must enter a number."),
|
||||
identifierStartPosition);
|
||||
} else if (!gd::ParameterMetadata::IsObject(type)) {
|
||||
identifier->diagnostic = RaiseTypeError(
|
||||
_("You've entered a name, but this type was expected:") + type,
|
||||
identifierStartPosition);
|
||||
}
|
||||
|
||||
return std::move(identifier);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableNode> Variable(const gd::String &type,
|
||||
const gd::String &objectName) {
|
||||
size_t identifierStartPosition = GetCurrentPosition();
|
||||
|
||||
gd::String name = ReadIdentifierName();
|
||||
auto variable = gd::make_unique<VariableNode>(type, name, objectName);
|
||||
variable->child = VariableAccessorOrVariableBracketAccessor();
|
||||
|
||||
return std::move(variable);
|
||||
}
|
||||
|
||||
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
|
||||
VariableAccessorOrVariableBracketAccessor() {
|
||||
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> child;
|
||||
SkipWhitespace();
|
||||
if (IsAnyChar("[")) {
|
||||
SkipChar();
|
||||
child =
|
||||
gd::make_unique<VariableBracketAccessorNode>(Expression("string"));
|
||||
|
||||
if (!IsAnyChar("]")) {
|
||||
child->diagnostic =
|
||||
RaiseSyntaxError(_("Missing a closing bracket. Add a closing "
|
||||
"bracket for each opening bracket."));
|
||||
}
|
||||
SkipIfIsAnyChar("]");
|
||||
child->child = VariableAccessorOrVariableBracketAccessor();
|
||||
} else if (IsAnyChar(DOT)) {
|
||||
SkipChar();
|
||||
SkipWhitespace();
|
||||
|
||||
child = gd::make_unique<VariableAccessorNode>(ReadIdentifierName());
|
||||
child->child = VariableAccessorOrVariableBracketAccessor();
|
||||
}
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
std::unique_ptr<FunctionNode> FreeFunction(const gd::String &type,
|
||||
const gd::String &functionFullName,
|
||||
size_t functionStartPosition) {
|
||||
// TODO: error if trying to use function for type != "number" && != "string"
|
||||
// + Test for it
|
||||
|
||||
// This could be improved to have the type passed to a single
|
||||
// GetExpressionMetadata function.
|
||||
const gd::ExpressionMetadata &metadata =
|
||||
type == "number" ? MetadataProvider::GetExpressionMetadata(
|
||||
platform, functionFullName)
|
||||
: MetadataProvider::GetStrExpressionMetadata(
|
||||
platform, functionFullName);
|
||||
|
||||
auto parametersAndError = Parameters(metadata.parameters);
|
||||
auto function = gd::make_unique<FunctionNode>(
|
||||
type, std::move(parametersAndError.first), metadata, functionFullName);
|
||||
function->diagnostic = std::move(parametersAndError.second);
|
||||
if (!function->diagnostic)
|
||||
function->diagnostic = ValidateFunction(*function, functionStartPosition);
|
||||
|
||||
return std::move(function);
|
||||
}
|
||||
|
||||
std::unique_ptr<FunctionOrEmptyNode> ObjectFunctionOrBehaviorFunction(
|
||||
const gd::String &type,
|
||||
const gd::String &objectName,
|
||||
size_t functionStartPosition) {
|
||||
gd::String objectFunctionOrBehaviorName = ReadIdentifierName();
|
||||
|
||||
SkipWhitespace();
|
||||
|
||||
if (IsNamespaceSeparator()) {
|
||||
SkipNamespaceSeparator();
|
||||
return BehaviorFunction(type,
|
||||
objectName,
|
||||
objectFunctionOrBehaviorName,
|
||||
functionStartPosition);
|
||||
} else if (IsAnyChar("(")) {
|
||||
SkipChar();
|
||||
|
||||
gd::String objectType =
|
||||
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName);
|
||||
|
||||
// This could be improved to have the type passed to a single
|
||||
// GetExpressionMetadata function.
|
||||
const gd::ExpressionMetadata &metadata =
|
||||
type == "number"
|
||||
? MetadataProvider::GetObjectExpressionMetadata(
|
||||
platform, objectType, objectFunctionOrBehaviorName)
|
||||
: MetadataProvider::GetObjectStrExpressionMetadata(
|
||||
platform, objectType, objectFunctionOrBehaviorName);
|
||||
|
||||
auto parametersAndError = Parameters(metadata.parameters, objectName);
|
||||
auto function =
|
||||
gd::make_unique<FunctionNode>(type,
|
||||
objectName,
|
||||
std::move(parametersAndError.first),
|
||||
metadata,
|
||||
objectFunctionOrBehaviorName);
|
||||
function->diagnostic = std::move(parametersAndError.second);
|
||||
if (!function->diagnostic)
|
||||
function->diagnostic =
|
||||
ValidateFunction(*function, functionStartPosition);
|
||||
|
||||
return std::move(function);
|
||||
}
|
||||
|
||||
auto node = gd::make_unique<EmptyNode>(type);
|
||||
node->diagnostic = RaiseSyntaxError(
|
||||
_("An opening parenthesis (for an object expression), or double colon "
|
||||
"(::) was expected (for a behavior expression)."));
|
||||
|
||||
return std::move(node);
|
||||
}
|
||||
|
||||
std::unique_ptr<FunctionOrEmptyNode> BehaviorFunction(
|
||||
const gd::String &type,
|
||||
const gd::String &objectName,
|
||||
const gd::String &behaviorName,
|
||||
size_t functionStartPosition) {
|
||||
gd::String functionName = ReadIdentifierName();
|
||||
|
||||
SkipWhitespace();
|
||||
|
||||
if (IsAnyChar("(")) {
|
||||
SkipChar();
|
||||
|
||||
gd::String behaviorType = GetTypeOfBehavior(
|
||||
globalObjectsContainer, objectsContainer, behaviorName);
|
||||
|
||||
// This could be improved to have the type passed to a single
|
||||
// GetExpressionMetadata function.
|
||||
const gd::ExpressionMetadata &metadata =
|
||||
type == "number" ? MetadataProvider::GetBehaviorExpressionMetadata(
|
||||
platform, behaviorType, functionName)
|
||||
: MetadataProvider::GetBehaviorStrExpressionMetadata(
|
||||
platform, behaviorType, functionName);
|
||||
|
||||
auto parametersAndError =
|
||||
Parameters(metadata.parameters, objectName, behaviorName);
|
||||
auto function =
|
||||
gd::make_unique<FunctionNode>(type,
|
||||
objectName,
|
||||
behaviorName,
|
||||
std::move(parametersAndError.first),
|
||||
metadata,
|
||||
functionName);
|
||||
function->diagnostic = std::move(parametersAndError.second);
|
||||
if (!function->diagnostic)
|
||||
function->diagnostic =
|
||||
ValidateFunction(*function, functionStartPosition);
|
||||
|
||||
return std::move(function);
|
||||
} else {
|
||||
auto node = gd::make_unique<EmptyNode>(type);
|
||||
node->diagnostic = RaiseSyntaxError(
|
||||
_("An opening parenthesis was expected here to call a function."));
|
||||
|
||||
return std::move(node);
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<std::vector<std::unique_ptr<ExpressionNode>>,
|
||||
std::unique_ptr<gd::ExpressionParserError>>
|
||||
Parameters(std::vector<gd::ParameterMetadata> parameterMetadata,
|
||||
const gd::String &objectName = "",
|
||||
const gd::String &behaviorName = "") {
|
||||
std::vector<std::unique_ptr<ExpressionNode>> parameters;
|
||||
|
||||
// By convention, object is always the first parameter, and behavior the
|
||||
// second one.
|
||||
size_t parameterIndex =
|
||||
WrittenParametersFirstIndex(objectName, behaviorName);
|
||||
|
||||
while (!IsEndReached()) {
|
||||
SkipWhitespace();
|
||||
|
||||
if (IsAnyChar(")")) {
|
||||
SkipChar();
|
||||
return std::make_pair(std::move(parameters), nullptr);
|
||||
} else {
|
||||
if (parameterIndex < parameterMetadata.size()) {
|
||||
const gd::String &type = parameterMetadata[parameterIndex].GetType();
|
||||
if (parameterMetadata[parameterIndex].IsCodeOnly()) {
|
||||
// Do nothing, code only parameters are not written in expressions.
|
||||
} else if (gd::ParameterMetadata::IsExpression("number", type)) {
|
||||
parameters.push_back(Expression("number"));
|
||||
} else if (gd::ParameterMetadata::IsExpression("string", type)) {
|
||||
parameters.push_back(Expression("string"));
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
parameters.push_back(Expression(type, objectName));
|
||||
} else if (gd::ParameterMetadata::IsObject(type)) {
|
||||
parameters.push_back(Expression(type));
|
||||
} else {
|
||||
size_t parameterStartPosition = GetCurrentPosition();
|
||||
parameters.push_back(Expression("unknown"));
|
||||
parameters.back()->diagnostic =
|
||||
gd::make_unique<ExpressionParserError>(
|
||||
"unknown_parameter_type",
|
||||
_("This function is improperly set up. Reach out to the "
|
||||
"extension developer or a GDevelop maintainer to fix "
|
||||
"this issue"),
|
||||
parameterStartPosition,
|
||||
GetCurrentPosition());
|
||||
}
|
||||
} else {
|
||||
size_t parameterStartPosition = GetCurrentPosition();
|
||||
parameters.push_back(Expression("unknown"));
|
||||
parameters.back()
|
||||
->diagnostic = gd::make_unique<ExpressionParserError>(
|
||||
"extra_parameter",
|
||||
_("This parameter was not expected by this expression. Remove it "
|
||||
"or verify that you've entered the proper expression name."),
|
||||
parameterStartPosition,
|
||||
GetCurrentPosition());
|
||||
}
|
||||
|
||||
SkipWhitespace();
|
||||
SkipIfIsAnyChar(PARAMETERS_SEPARATOR);
|
||||
parameterIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(
|
||||
std::move(parameters),
|
||||
RaiseSyntaxError(_("The list of parameters is not terminated. Add a "
|
||||
"closing parenthesis to end the parameters.")));
|
||||
}
|
||||
///@}
|
||||
|
||||
/** \name Validators
|
||||
* Return a diagnostic if any error is found
|
||||
*/
|
||||
///@{
|
||||
std::unique_ptr<ExpressionParserDiagnostic> ValidateFunction(
|
||||
const gd::FunctionNode &function, size_t functionStartPosition);
|
||||
|
||||
std::unique_ptr<ExpressionParserDiagnostic> ValidateOperator(
|
||||
const gd::String &type, gd::String::value_type operatorChar) {
|
||||
if (type == "number") {
|
||||
if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' ||
|
||||
operatorChar == '*') {
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
}
|
||||
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("You've used an operator that is not supported. Operator should be "
|
||||
"either +, -, / or *."),
|
||||
GetCurrentPosition());
|
||||
} else if (type == "string") {
|
||||
if (operatorChar == '+') {
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
}
|
||||
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("You've used an operator that is not supported. Only + can be used "
|
||||
"to concatenate texts."),
|
||||
GetCurrentPosition());
|
||||
} else if (gd::ParameterMetadata::IsObject(type)) {
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("Operators (+, -, /, *) can't be used with an object name. Remove the operator."),
|
||||
GetCurrentPosition());
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("Operators (+, -, /, *) can't be used in variable names. Remove "
|
||||
"the operator from the variable name."),
|
||||
GetCurrentPosition());
|
||||
}
|
||||
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
}
|
||||
|
||||
std::unique_ptr<ExpressionParserDiagnostic> ValidateUnaryOperator(
|
||||
const gd::String &type, gd::String::value_type operatorChar) {
|
||||
if (type == "number") {
|
||||
if (operatorChar == '+' || operatorChar == '-') {
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
}
|
||||
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("You've used an \"unary\" operator that is not supported. Operator "
|
||||
"should be "
|
||||
"either + or -."),
|
||||
GetCurrentPosition());
|
||||
} else if (type == "string") {
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("You've used an operator that is not supported. Only + can be used "
|
||||
"to concatenate texts, and must be placed between two texts (or "
|
||||
"expressions)."),
|
||||
GetCurrentPosition());
|
||||
} else if (gd::ParameterMetadata::IsObject(type)) {
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("Operators (+, -) can't be used with an object name. Remove the operator."),
|
||||
GetCurrentPosition());
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
return gd::make_unique<ExpressionParserError>(
|
||||
"invalid_operator",
|
||||
_("Operators (+, -) can't be used in variable names. Remove "
|
||||
"the operator from the variable name."),
|
||||
GetCurrentPosition());
|
||||
}
|
||||
|
||||
return gd::make_unique<ExpressionParserDiagnostic>();
|
||||
}
|
||||
///@}
|
||||
|
||||
/** \name Parsing tokens
|
||||
* Read tokens or characters
|
||||
*/
|
||||
///@{
|
||||
void SkipChar() { currentPosition++; }
|
||||
|
||||
void SkipWhitespace() {
|
||||
while (currentPosition < expression.size() &&
|
||||
WHITESPACES.find(expression[currentPosition]) != gd::String::npos) {
|
||||
currentPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
void SkipIfIsAnyChar(const gd::String &allowedCharacters) {
|
||||
if (IsAnyChar(allowedCharacters)) {
|
||||
currentPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
void SkipNamespaceSeparator() {
|
||||
// Namespace separator is a special kind of delimiter as it is 2 characters
|
||||
// long
|
||||
if (IsNamespaceSeparator()) {
|
||||
currentPosition += NAMESPACE_SEPARATOR.size();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsAnyChar(const gd::String &allowedCharacters) {
|
||||
if (currentPosition < expression.size() &&
|
||||
allowedCharacters.find(expression[currentPosition]) !=
|
||||
gd::String::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsIdentifierAllowedChar() {
|
||||
if (currentPosition < expression.size() &&
|
||||
PARAMETERS_SEPARATOR.find(expression[currentPosition]) ==
|
||||
gd::String::npos &&
|
||||
DOT.find(expression[currentPosition]) == gd::String::npos &&
|
||||
QUOTE.find(expression[currentPosition]) == gd::String::npos &&
|
||||
BRACKETS.find(expression[currentPosition]) == gd::String::npos &&
|
||||
EXPRESSION_OPERATORS.find(expression[currentPosition]) ==
|
||||
gd::String::npos &&
|
||||
TERM_OPERATORS.find(expression[currentPosition]) == gd::String::npos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsNamespaceSeparator() {
|
||||
// Namespace separator is a special kind of delimiter as it is 2 characters
|
||||
// long
|
||||
return (currentPosition + NAMESPACE_SEPARATOR.size() <= expression.size() &&
|
||||
expression.substr(currentPosition, NAMESPACE_SEPARATOR.size()) ==
|
||||
NAMESPACE_SEPARATOR);
|
||||
}
|
||||
|
||||
bool IsEndReached() { return currentPosition >= expression.size(); }
|
||||
|
||||
gd::String ReadIdentifierName() {
|
||||
gd::String name;
|
||||
while (currentPosition < expression.size() &&
|
||||
(IsIdentifierAllowedChar()
|
||||
// Allow whitespace in identifier name for compatibility
|
||||
|| expression[currentPosition] == ' ')) {
|
||||
name += expression[currentPosition];
|
||||
currentPosition++;
|
||||
}
|
||||
|
||||
// Trim whitespace at the end (we allow them for compatibility inside
|
||||
// the name, but after the last character that is not whitespace, they
|
||||
// should be ignore again).
|
||||
size_t lastCharacterPos = name.find_last_not_of(WHITESPACES);
|
||||
if (!name.empty() && (lastCharacterPos + 1) < name.size()) {
|
||||
name.erase(lastCharacterPos + 1);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
std::unique_ptr<TextNode> ReadText();
|
||||
|
||||
std::unique_ptr<NumberNode> ReadNumber();
|
||||
|
||||
std::unique_ptr<EmptyNode> ReadUntilWhitespace(gd::String type) {
|
||||
gd::String text;
|
||||
while (currentPosition < expression.size() &&
|
||||
WHITESPACES.find(expression[currentPosition]) == gd::String::npos) {
|
||||
text += expression[currentPosition];
|
||||
currentPosition++;
|
||||
}
|
||||
|
||||
return gd::make_unique<EmptyNode>(type, text);
|
||||
}
|
||||
|
||||
std::unique_ptr<EmptyNode> ReadUntilEnd(gd::String type) {
|
||||
gd::String text;
|
||||
while (currentPosition < expression.size()) {
|
||||
text += expression[currentPosition];
|
||||
currentPosition++;
|
||||
}
|
||||
|
||||
return gd::make_unique<EmptyNode>(type, text);
|
||||
}
|
||||
|
||||
size_t GetCurrentPosition() { return currentPosition; }
|
||||
|
||||
gd::String::value_type GetCurrentChar() {
|
||||
if (currentPosition < expression.size()) {
|
||||
return expression[currentPosition];
|
||||
}
|
||||
|
||||
return '\n'; // Should not arise, unless GetCurrentChar was called when
|
||||
// IsEndReached() is true (which is a logical error).
|
||||
}
|
||||
///@}
|
||||
|
||||
/** \name Raising errors
|
||||
* Helpers to attach errors to nodes
|
||||
*/
|
||||
///@{
|
||||
std::unique_ptr<ExpressionParserError> RaiseSyntaxError(
|
||||
const gd::String &message) {
|
||||
return std::move(gd::make_unique<ExpressionParserError>(
|
||||
"syntax_error", 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()));
|
||||
}
|
||||
|
||||
std::unique_ptr<ExpressionParserError> RaiseEmptyError(
|
||||
const gd::String &type, size_t beginningPosition) {
|
||||
gd::String message;
|
||||
if (type == "number") {
|
||||
message = _("You must enter a number or a valid expression call.");
|
||||
} else if (type == "string") {
|
||||
message = _(
|
||||
"You must enter a text (between quotes) or a valid expression call.");
|
||||
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
|
||||
message = _("You must enter a variable name.");
|
||||
} else if (gd::ParameterMetadata::IsObject(type)) {
|
||||
message = _("You must enter a valid object name.");
|
||||
} else {
|
||||
message = _("You must enter a valid expression.");
|
||||
}
|
||||
|
||||
return std::move(RaiseTypeError(message, beginningPosition));
|
||||
}
|
||||
///@}
|
||||
|
||||
static size_t WrittenParametersFirstIndex(const gd::String &objectName,
|
||||
const gd::String &behaviorName) {
|
||||
// By convention, object is always the first parameter, and behavior the
|
||||
// second one.
|
||||
return !behaviorName.empty() ? 2 : (!objectName.empty() ? 1 : 0);
|
||||
}
|
||||
|
||||
gd::String expression;
|
||||
std::size_t currentPosition;
|
||||
|
||||
const gd::Platform &platform;
|
||||
const gd::ObjectsContainer &globalObjectsContainer;
|
||||
const gd::ObjectsContainer &objectsContainer;
|
||||
|
||||
static gd::String NUMBER_FIRST_CHAR;
|
||||
static gd::String DOT;
|
||||
static gd::String PARAMETERS_SEPARATOR;
|
||||
static gd::String QUOTE;
|
||||
static gd::String BRACKETS;
|
||||
static gd::String EXPRESSION_OPERATORS;
|
||||
static gd::String TERM_OPERATORS;
|
||||
static gd::String UNARY_OPERATORS;
|
||||
static gd::String WHITESPACES;
|
||||
static gd::String NAMESPACE_SEPARATOR;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EXPRESSIONPARSER2_H
|
10
Core/GDCore/Events/Parsers/ExpressionParser2Node.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ExpressionParser2Node.h"
|
||||
|
||||
namespace gd {
|
||||
gd::String ExpressionParserDiagnostic::noMessage = "";
|
||||
}
|
294
Core/GDCore/Events/Parsers/ExpressionParser2Node.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* 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
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
class Platform;
|
||||
class ParameterMetadata;
|
||||
class ExpressionMetadata;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A diagnostic that can be attached to a gd::ExpressionNode.
|
||||
*/
|
||||
struct ExpressionParserDiagnostic {
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief An error that can be attached to a gd::ExpressionNode.
|
||||
*/
|
||||
struct ExpressionParserError : public ExpressionParserDiagnostic {
|
||||
ExpressionParserError(const gd::String &type_,
|
||||
const gd::String &message_,
|
||||
size_t position_)
|
||||
: type(type_),
|
||||
message(message_),
|
||||
startPosition(position_),
|
||||
endPosition(position_){};
|
||||
ExpressionParserError(const gd::String &type_,
|
||||
const gd::String &message_,
|
||||
size_t startPosition_,
|
||||
size_t endPosition_)
|
||||
: type(type_),
|
||||
message(message_),
|
||||
startPosition(startPosition_),
|
||||
endPosition(endPosition_){};
|
||||
virtual ~ExpressionParserError(){};
|
||||
|
||||
bool IsError() override { return true; }
|
||||
const gd::String &GetMessage() override { return message; }
|
||||
size_t GetStartPosition() override { return startPosition; }
|
||||
size_t GetEndPosition() override { return endPosition; }
|
||||
|
||||
private:
|
||||
gd::String type;
|
||||
gd::String message;
|
||||
size_t startPosition;
|
||||
size_t endPosition;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief The base node, from which all nodes in the tree of
|
||||
* an expression inherits from.
|
||||
*/
|
||||
struct ExpressionNode {
|
||||
virtual ~ExpressionNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker){};
|
||||
|
||||
std::unique_ptr<ExpressionParserDiagnostic> diagnostic;
|
||||
};
|
||||
|
||||
struct SubExpressionNode : public ExpressionNode {
|
||||
SubExpressionNode(std::unique_ptr<ExpressionNode> expression_)
|
||||
: expression(std::move(expression_)){};
|
||||
virtual ~SubExpressionNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitSubExpressionNode(*this);
|
||||
};
|
||||
|
||||
std::unique_ptr<ExpressionNode> expression;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief An operator node. For example: "lhs + rhs".
|
||||
*/
|
||||
struct OperatorNode : public ExpressionNode {
|
||||
virtual ~OperatorNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitOperatorNode(*this);
|
||||
};
|
||||
|
||||
std::unique_ptr<ExpressionNode> leftHandSide;
|
||||
std::unique_ptr<ExpressionNode> rightHandSide;
|
||||
gd::String::value_type op;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A unary operator node. For example: "-2".
|
||||
*/
|
||||
struct UnaryOperatorNode : public ExpressionNode {
|
||||
UnaryOperatorNode(gd::String::value_type op_) : op(op_){};
|
||||
virtual ~UnaryOperatorNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitUnaryOperatorNode(*this);
|
||||
};
|
||||
|
||||
std::unique_ptr<ExpressionNode> factor;
|
||||
gd::String::value_type op;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A number node. For example: "123".
|
||||
*/
|
||||
struct NumberNode : public ExpressionNode {
|
||||
NumberNode(const gd::String &number_) : number(number_){};
|
||||
virtual ~NumberNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitNumberNode(*this);
|
||||
};
|
||||
|
||||
gd::String number;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A text node. For example: "Hello World".
|
||||
*/
|
||||
struct TextNode : public ExpressionNode {
|
||||
TextNode(const gd::String &text_) : text(text_){};
|
||||
virtual ~TextNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitTextNode(*this);
|
||||
};
|
||||
|
||||
gd::String text;
|
||||
};
|
||||
|
||||
struct VariableAccessorOrVariableBracketAccessorNode : public ExpressionNode {
|
||||
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> child;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A variable, potentially with accessor to its children.
|
||||
*
|
||||
* Example: MyVariable or MyVariable.MyChildren
|
||||
*
|
||||
* \see gd::VariableAccessorNode
|
||||
* \see gd::VariableBracketAccessorNode
|
||||
*/
|
||||
struct VariableNode : public ExpressionNode {
|
||||
VariableNode(const gd::String &type_,
|
||||
const gd::String &name_,
|
||||
const gd::String &objectName_)
|
||||
: type(type_), name(name_), objectName(objectName_){};
|
||||
virtual ~VariableNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitVariableNode(*this);
|
||||
};
|
||||
|
||||
gd::String type;
|
||||
gd::String name;
|
||||
gd::String objectName;
|
||||
|
||||
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
|
||||
child; // Can be nullptr if no accessor
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A bracket accessor of a variable. Example: MyChild
|
||||
* in MyVariable.MyChild
|
||||
*/
|
||||
struct VariableAccessorNode
|
||||
: public VariableAccessorOrVariableBracketAccessorNode {
|
||||
VariableAccessorNode(const gd::String &name_) : name(name_){};
|
||||
virtual ~VariableAccessorNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitVariableAccessorNode(*this);
|
||||
};
|
||||
|
||||
gd::String name;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A bracket accessor of a variable. Example: ["MyChild"]
|
||||
* (in MyVariable["MyChild"]).
|
||||
*/
|
||||
struct VariableBracketAccessorNode
|
||||
: public VariableAccessorOrVariableBracketAccessorNode {
|
||||
VariableBracketAccessorNode(std::unique_ptr<ExpressionNode> expression_)
|
||||
: expression(std::move(expression_)){};
|
||||
virtual ~VariableBracketAccessorNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitVariableBracketAccessorNode(*this);
|
||||
};
|
||||
|
||||
std::unique_ptr<ExpressionNode> expression;
|
||||
};
|
||||
|
||||
struct IdentifierOrFunctionOrEmptyNode : public ExpressionNode {};
|
||||
|
||||
/**
|
||||
* \brief An identifier node, usually representing an object.
|
||||
*/
|
||||
struct IdentifierNode : public IdentifierOrFunctionOrEmptyNode {
|
||||
IdentifierNode(const gd::String &identifierName_, const gd::String &type_)
|
||||
: identifierName(identifierName_), type(type_){};
|
||||
virtual ~IdentifierNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitIdentifierNode(*this);
|
||||
};
|
||||
|
||||
gd::String identifierName;
|
||||
gd::String type;
|
||||
};
|
||||
|
||||
struct FunctionOrEmptyNode : public IdentifierOrFunctionOrEmptyNode {
|
||||
virtual ~FunctionOrEmptyNode(){};
|
||||
void Visit(ExpressionParser2NodeWorker &worker) override{};
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief A function node. For example: "MyExtension::MyFunction(1, 2)".
|
||||
*/
|
||||
struct FunctionNode : public FunctionOrEmptyNode {
|
||||
FunctionNode(const gd::String &type_,
|
||||
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
|
||||
const ExpressionMetadata &expressionMetadata_,
|
||||
const gd::String &functionName_)
|
||||
: type(type_),
|
||||
parameters(std::move(parameters_)),
|
||||
expressionMetadata(expressionMetadata_),
|
||||
functionName(functionName_){};
|
||||
FunctionNode(const gd::String &type_,
|
||||
const gd::String &objectName_,
|
||||
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
|
||||
const ExpressionMetadata &expressionMetadata_,
|
||||
const gd::String &functionName_)
|
||||
: type(type_),
|
||||
objectName(objectName_),
|
||||
parameters(std::move(parameters_)),
|
||||
expressionMetadata(expressionMetadata_),
|
||||
functionName(functionName_){};
|
||||
FunctionNode(const gd::String &type_,
|
||||
const gd::String &objectName_,
|
||||
const gd::String &behaviorName_,
|
||||
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
|
||||
const ExpressionMetadata &expressionMetadata_,
|
||||
const gd::String &functionName_)
|
||||
: type(type_),
|
||||
objectName(objectName_),
|
||||
behaviorName(behaviorName_),
|
||||
parameters(std::move(parameters_)),
|
||||
expressionMetadata(expressionMetadata_),
|
||||
functionName(functionName_){};
|
||||
virtual ~FunctionNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitFunctionNode(*this);
|
||||
};
|
||||
|
||||
gd::String type; // This could be removed if the type ("string" or "number")
|
||||
// was stored in ExpressionMetadata.
|
||||
gd::String objectName;
|
||||
gd::String behaviorName;
|
||||
std::vector<std::unique_ptr<ExpressionNode>> parameters;
|
||||
const ExpressionMetadata &expressionMetadata;
|
||||
gd::String functionName;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief An empty node, used when parsing failed/a syntax error was
|
||||
* encountered and any other node could not make sense.
|
||||
*/
|
||||
struct EmptyNode : public FunctionOrEmptyNode {
|
||||
EmptyNode(const gd::String &type_, const gd::String &text_ = "")
|
||||
: type(type_), text(text_){};
|
||||
virtual ~EmptyNode(){};
|
||||
virtual void Visit(ExpressionParser2NodeWorker &worker) {
|
||||
worker.OnVisitEmptyNode(*this);
|
||||
};
|
||||
|
||||
gd::String type;
|
||||
gd::String text;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
124
Core/GDCore/Events/Parsers/ExpressionParser2NodePrinter.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EXPRESSIONNODEPRINTER_H
|
||||
#define GDCORE_EXPRESSIONNODEPRINTER_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
class Platform;
|
||||
class ParameterMetadata;
|
||||
class ExpressionMetadata;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Print the expression corresponding to a set of nodes
|
||||
* (i.e: this is doing the inverse operation of gd::ExpressionParser2).
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionParser2NodePrinter
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionParser2NodePrinter(){};
|
||||
virtual ~ExpressionParser2NodePrinter(){};
|
||||
|
||||
static gd::String PrintNode(gd::ExpressionNode& node) {
|
||||
gd::ExpressionParser2NodePrinter printer;
|
||||
node.Visit(printer);
|
||||
return printer.GetOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the string corresponding to the expression nodes.
|
||||
*/
|
||||
const gd::String& GetOutput() { return output; };
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
output += "(";
|
||||
node.expression->Visit(*this);
|
||||
output += ")";
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
if (node.op == ' ') {
|
||||
// There is no "space" operator. If it's there, it's because
|
||||
// an operator could not be found (that's an error). Add only
|
||||
// a whitespace between terms.
|
||||
output += " ";
|
||||
} else {
|
||||
output += " ";
|
||||
output.push_back(node.op);
|
||||
output += " ";
|
||||
}
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
output.push_back(node.op);
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override { output += node.number; }
|
||||
void OnVisitTextNode(TextNode& node) override {
|
||||
output +=
|
||||
"\"" +
|
||||
node.text.FindAndReplace("\\", "\\\\").FindAndReplace("\"", "\\\"") +
|
||||
"\"";
|
||||
}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
output += node.name;
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
output += "." + node.name;
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
output += "[";
|
||||
node.expression->Visit(*this);
|
||||
output += "]";
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
output += node.identifierName;
|
||||
}
|
||||
void OnVisitFunctionNode(FunctionNode& node) override {
|
||||
if (!node.behaviorName.empty()) {
|
||||
output +=
|
||||
node.objectName + "." + node.behaviorName + "::" + node.functionName;
|
||||
} else if (!node.objectName.empty()) {
|
||||
output += node.objectName + "." + node.functionName;
|
||||
} else {
|
||||
output += node.functionName;
|
||||
}
|
||||
|
||||
output += "(";
|
||||
|
||||
bool isFirst = true;
|
||||
for (auto& parameterNode : node.parameters) {
|
||||
if (!isFirst) output += ", ";
|
||||
parameterNode->Visit(*this);
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
output += ")";
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override { output += node.text; }
|
||||
|
||||
private:
|
||||
gd::String output;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_EXPRESSIONNODEPRINTER_H
|
10
Core/GDCore/Events/Parsers/ExpressionParser2NodeWorker.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ExpressionParser2NodeWorker.h"
|
||||
|
||||
namespace gd {
|
||||
ExpressionParser2NodeWorker::~ExpressionParser2NodeWorker(){};
|
||||
}
|
71
Core/GDCore/Events/Parsers/ExpressionParser2NodeWorker.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EXPRESSIONPARSER2NODEWORKER_H
|
||||
#define GDCORE_EXPRESSIONPARSER2NODEWORKER_H
|
||||
|
||||
namespace gd {
|
||||
class ExpressionNode;
|
||||
class SubExpressionNode;
|
||||
class OperatorNode;
|
||||
class UnaryOperatorNode;
|
||||
class NumberNode;
|
||||
class TextNode;
|
||||
class VariableNode;
|
||||
class VariableAccessorNode;
|
||||
class VariableBracketAccessorNode;
|
||||
class IdentifierOrFunctionOrEmptyNode;
|
||||
class IdentifierNode;
|
||||
class FunctionOrEmptyNode;
|
||||
class FunctionNode;
|
||||
class EmptyNode;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief The interface for any worker class ("visitor" pattern)
|
||||
* that want to interact with the nodes of a parsed expression.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
* \see gd::ExpressionNode
|
||||
*/
|
||||
class GD_CORE_API ExpressionParser2NodeWorker {
|
||||
friend class ExpressionNode;
|
||||
friend class SubExpressionNode;
|
||||
friend class OperatorNode;
|
||||
friend class UnaryOperatorNode;
|
||||
friend class NumberNode;
|
||||
friend class TextNode;
|
||||
friend class VariableNode;
|
||||
friend class VariableAccessorNode;
|
||||
friend class VariableBracketAccessorNode;
|
||||
friend class IdentifierOrFunctionOrEmptyNode;
|
||||
friend class IdentifierNode;
|
||||
friend class FunctionOrEmptyNode;
|
||||
friend class FunctionNode;
|
||||
friend class EmptyNode;
|
||||
|
||||
public:
|
||||
virtual ~ExpressionParser2NodeWorker();
|
||||
|
||||
protected:
|
||||
virtual void OnVisitSubExpressionNode(SubExpressionNode& node) = 0;
|
||||
virtual void OnVisitOperatorNode(OperatorNode& node) = 0;
|
||||
virtual void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) = 0;
|
||||
virtual void OnVisitNumberNode(NumberNode& node) = 0;
|
||||
virtual void OnVisitTextNode(TextNode& node) = 0;
|
||||
virtual void OnVisitVariableNode(VariableNode& node) = 0;
|
||||
virtual void OnVisitVariableAccessorNode(VariableAccessorNode& node) = 0;
|
||||
virtual void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) = 0;
|
||||
virtual void OnVisitIdentifierNode(IdentifierNode& node) = 0;
|
||||
virtual void OnVisitFunctionNode(FunctionNode& node) = 0;
|
||||
virtual void OnVisitEmptyNode(EmptyNode& node) = 0;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
@@ -134,7 +134,7 @@ gd::String VariableParser::SkipStringExpression() {
|
||||
++currentPositionIt;
|
||||
}
|
||||
|
||||
// End of the expression reached ( So expression is invalid by the way )
|
||||
// End of the expression reached (so expression is invalid by the way)
|
||||
return stringExpression;
|
||||
}
|
||||
|
||||
|
@@ -40,13 +40,14 @@ gd::VariableParserCallbacks VariableCodeGenerationCallbacks callbacks(output,
|
||||
gd::VariableParser parser(parameter);
|
||||
if ( !parser.Parse(callbacks) )
|
||||
cout << "Error :" << parser.GetFirstError() << " in: "<< parameter <<
|
||||
endl; \endcode
|
||||
endl;
|
||||
\endcode
|
||||
*
|
||||
* Here is the parsed grammar: <br>
|
||||
* S -> VarName X <br>
|
||||
* X -> e | . S | [StringExpression] X <br>
|
||||
*
|
||||
* where e = nothing ( end of expression ), StringExpression = A valid string
|
||||
* where e = nothing (end of expression), StringExpression = A valid string
|
||||
expression and
|
||||
* S is the start.
|
||||
*
|
||||
|
@@ -16,11 +16,75 @@
|
||||
#include "GDCore/Serialization/Serializer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
#include "GDCore/Tools/VersionWrapper.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace {
|
||||
bool AddQuotesToFunctionCall(gd::String& expressionStr,
|
||||
const gd::String& functionName) {
|
||||
bool changedSomething = false;
|
||||
size_t functionCallPos = expressionStr.find(functionName + "(");
|
||||
while (functionCallPos != gd::String::npos) {
|
||||
size_t pos = functionCallPos + functionName.size() + 1;
|
||||
|
||||
// Skip whitespace
|
||||
while (pos < expressionStr.size() && expressionStr[pos] == ' ') pos++;
|
||||
|
||||
if (pos < expressionStr.size()) {
|
||||
changedSomething = true;
|
||||
|
||||
// Insert the first quote
|
||||
expressionStr.insert(pos, "\"");
|
||||
pos++;
|
||||
|
||||
// Escape the argument
|
||||
while (pos < expressionStr.size() && expressionStr[pos] != ')') {
|
||||
if (expressionStr[pos] == '"') {
|
||||
expressionStr.insert(pos,
|
||||
"\\"); // Insert a backslash to escape the quote
|
||||
pos++;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
|
||||
// Insert the last quote
|
||||
if (pos < expressionStr.size() && expressionStr[pos] == ')') {
|
||||
expressionStr.insert(pos, "\"");
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
functionCallPos = expressionStr.find(functionName + "(", pos + 1);
|
||||
}
|
||||
|
||||
return changedSomething;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace gd {
|
||||
|
||||
void EventsListSerialization::UpdateInstructionsFromGD4097(
|
||||
gd::Project& project, gd::InstructionsList& list) {
|
||||
for (std::size_t i = 0; i < list.size(); ++i) {
|
||||
gd::Instruction& instr = list[i];
|
||||
|
||||
for (std::size_t j = 0; j < instr.GetParametersCount(); ++j) {
|
||||
gd::String expressionStr = instr.GetParameter(j).GetPlainString();
|
||||
bool changedSomething = false;
|
||||
changedSomething |= AddQuotesToFunctionCall(expressionStr, "PointX");
|
||||
changedSomething |= AddQuotesToFunctionCall(expressionStr, "PointY");
|
||||
|
||||
if (changedSomething) {
|
||||
std::cout << "(Debug) Converted \""
|
||||
<< instr.GetParameter(j).GetPlainString() << "\" to \""
|
||||
<< expressionStr << "\"" << std::endl;
|
||||
instr.SetParameter(j, gd::Expression(expressionStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventsListSerialization::UpdateInstructionsFromGD31x(
|
||||
gd::Project& project, gd::InstructionsList& list) {
|
||||
for (std::size_t i = 0; i < list.size(); ++i) {
|
||||
@@ -256,6 +320,18 @@ void gd::EventsListSerialization::UnserializeInstructionsFrom(
|
||||
if (project.GetLastSaveGDMajorVersion() < 3)
|
||||
UpdateInstructionsFromGD2x(
|
||||
project, instructions, elem.HasChild("action", "Action"));
|
||||
|
||||
// Compatibility with GD <= 4.0.97
|
||||
if (VersionWrapper::IsOlderOrEqual(project.GetLastSaveGDMajorVersion(),
|
||||
project.GetLastSaveGDMinorVersion(),
|
||||
project.GetLastSaveGDBuildVersion(),
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
97,
|
||||
0)) {
|
||||
UpdateInstructionsFromGD4097(project, instructions);
|
||||
}
|
||||
// end of compatibility code
|
||||
}
|
||||
|
||||
|
@@ -72,6 +72,16 @@ class GD_CORE_API EventsListSerialization {
|
||||
*/
|
||||
static void UpdateInstructionsFromGD31x(gd::Project& project,
|
||||
gd::InstructionsList& list);
|
||||
|
||||
/**
|
||||
* \brief Internal method called when opening events created with GD <= 4.0.97
|
||||
*
|
||||
* PointX/PointY would previously take a name of a point without quotes.
|
||||
* This is not providing any value and inconsistent with everything else.
|
||||
* Add quotes around them.
|
||||
*/
|
||||
static void UpdateInstructionsFromGD4097(gd::Project& project,
|
||||
gd::InstructionsList& list);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -176,15 +176,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("AddForceXY",
|
||||
_("Add a force"),
|
||||
_("Add a force to an object. The object will move according to "
|
||||
"all of the forces it has."),
|
||||
_("Add to _PARAM0_ _PARAM3_ force of _PARAM1_ p/s on X axis and "
|
||||
"_PARAM2_ p/s on Y axis"),
|
||||
_("Movement"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
obj.AddAction(
|
||||
"AddForceXY",
|
||||
_("Add a force"),
|
||||
_("Add a force to an object. The object will move according to "
|
||||
"all of the forces it has."),
|
||||
_("Add to _PARAM0_ _PARAM3_ force of _PARAM1_ p/s on X axis and "
|
||||
"_PARAM2_ p/s on Y axis"),
|
||||
_("Movement"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("Speed on X axis (in pixels per second)"))
|
||||
@@ -551,13 +552,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("yesorno", _("Activate?"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("AddForceVers",
|
||||
_("Add a force to move toward an object"),
|
||||
_("Add a force to an object to make it move toward another."),
|
||||
_("Move _PARAM0_ to _PARAM1_ with _PARAM3_ force of _PARAM2_ pixels"),
|
||||
_("Movement"),
|
||||
"res/actions/forceVers24.png",
|
||||
"res/actions/forceVers.png")
|
||||
obj.AddAction(
|
||||
"AddForceVers",
|
||||
_("Add a force to move toward an object"),
|
||||
_("Add a force to an object to make it move toward another."),
|
||||
_("Move _PARAM0_ to _PARAM1_ with _PARAM3_ force of _PARAM2_ pixels"),
|
||||
_("Movement"),
|
||||
"res/actions/forceVers24.png",
|
||||
"res/actions/forceVers.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectPtr", _("Target Object"))
|
||||
@@ -640,6 +642,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectList", _("Objects"))
|
||||
.AddParameter("yesorno",
|
||||
_("Ignore objects that are touching each other on their "
|
||||
"edges, but are not overlapping (default: no)"),
|
||||
"",
|
||||
true)
|
||||
.SetDefaultValue("no")
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("CollisionPoint",
|
||||
@@ -654,13 +662,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("expression", _("Y position of the point"))
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("ObjectTimer",
|
||||
_("Value of a timer"),
|
||||
_("Test the elapsed time of a timer."),
|
||||
_("The timer _PARAM1_ of _PARAM0_ is greater than _PARAM2_ seconds"),
|
||||
_("Timers"),
|
||||
"res/conditions/timer24.png",
|
||||
"res/conditions/timer.png")
|
||||
obj.AddCondition(
|
||||
"ObjectTimer",
|
||||
_("Value of a timer"),
|
||||
_("Test the elapsed time of a timer."),
|
||||
_("The timer _PARAM1_ of _PARAM0_ is greater than _PARAM2_ seconds"),
|
||||
_("Timers"),
|
||||
"res/conditions/timer24.png",
|
||||
"res/conditions/timer.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"))
|
||||
.AddParameter("expression", _("Time in seconds"));
|
||||
@@ -863,10 +872,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("objectvar", _("Variable"));
|
||||
|
||||
obj.AddExpression("ObjectTimerElapsedTime",
|
||||
_("Timer value"),
|
||||
_("Value of a timer"),
|
||||
_("Timers"),
|
||||
"res/actions/time.png")
|
||||
_("Timer value"),
|
||||
_("Value of a timer"),
|
||||
_("Timers"),
|
||||
"res/actions/time.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
|
||||
@@ -911,8 +920,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
extension
|
||||
.AddAction("AjoutObjConcern",
|
||||
_("Pick all objects"),
|
||||
_("Pick all objects with this name."),
|
||||
_("Pick all _PARAM1_"),
|
||||
_("Pick all the specified objects. When you pick all objects, "
|
||||
"the next conditions and actions of this event work on all "
|
||||
"of them."),
|
||||
_("Pick all _PARAM1_ objects"),
|
||||
_("Objects"),
|
||||
"res/actions/add24.png",
|
||||
"res/actions/add.png")
|
||||
@@ -921,13 +932,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("AjoutHasard",
|
||||
_("Pick a random object"),
|
||||
_("Pick only one object with this name, among all"),
|
||||
_("Pick a random _PARAM1_"),
|
||||
_("Objects"),
|
||||
"res/actions/ajouthasard24.png",
|
||||
"res/actions/ajouthasard.png")
|
||||
.AddAction(
|
||||
"AjoutHasard",
|
||||
_("Pick a random object"),
|
||||
_("Pick one object from all the specified objects. When an object "
|
||||
"is picked, the next conditions and actions of this event work "
|
||||
"only on that object."),
|
||||
_("Pick a random _PARAM1_"),
|
||||
_("Objects"),
|
||||
"res/actions/ajouthasard24.png",
|
||||
"res/actions/ajouthasard.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.MarkAsSimple();
|
||||
@@ -977,25 +991,31 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddCondition("AjoutObjConcern",
|
||||
_("Pick all objects"),
|
||||
_("Pick all objects with this name."),
|
||||
_("Pick all _PARAM1_"),
|
||||
_("Objects"),
|
||||
"res/conditions/add24.png",
|
||||
"res/conditions/add.png")
|
||||
.AddCondition(
|
||||
"AjoutObjConcern",
|
||||
_("Pick all objects"),
|
||||
_("Pick all the specified objects. When you pick all objects, "
|
||||
"the next conditions and actions of this event work on all "
|
||||
"of them."),
|
||||
_("Pick all _PARAM1_ objects"),
|
||||
_("Objects"),
|
||||
"res/conditions/add24.png",
|
||||
"res/conditions/add.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddCondition("AjoutHasard",
|
||||
_("Pick a random object"),
|
||||
_("Pick only one object with this name, among all"),
|
||||
_("Pick a random _PARAM1_"),
|
||||
_("Objects"),
|
||||
"res/conditions/ajouthasard24.png",
|
||||
"res/conditions/ajouthasard.png")
|
||||
.AddCondition(
|
||||
"AjoutHasard",
|
||||
_("Pick a random object"),
|
||||
_("Pick one object from all the specified objects. When an object "
|
||||
"is picked, the next conditions and actions of this event work "
|
||||
"only on that object."),
|
||||
_("Pick a random _PARAM1_"),
|
||||
_("Objects"),
|
||||
"res/conditions/ajouthasard24.png",
|
||||
"res/conditions/ajouthasard.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.MarkAsSimple();
|
||||
@@ -1004,9 +1024,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddCondition(
|
||||
"PickNearest",
|
||||
_("Pick nearest object"),
|
||||
_("Among the objects, pick the one that is nearest (or furthest if "
|
||||
"condition is inverted) from the specified position."),
|
||||
_("Pick nearest _PARAM0_ to _PARAM1_;_PARAM2_"),
|
||||
_("Pick the object of this type that is nearest to the specified "
|
||||
"position. If the condition is inverted, the object farthest from "
|
||||
"the specified position is picked instead."),
|
||||
_("Pick the _PARAM0_ that is nearest to _PARAM1_;_PARAM2_"),
|
||||
_("Objects"),
|
||||
"res/conditions/distance24.png",
|
||||
"res/conditions/distance.png")
|
||||
@@ -1017,13 +1038,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddCondition("NbObjet",
|
||||
_("Objects count"),
|
||||
_("Compare the number of picked objects"),
|
||||
_("The number of _PARAM0_ is _PARAM1__PARAM2_"),
|
||||
_("Objects"),
|
||||
"res/conditions/nbObjet24.png",
|
||||
"res/conditions/nbObjet.png")
|
||||
.AddCondition(
|
||||
"NbObjet",
|
||||
_("Number of objects"),
|
||||
_("Count how many of the specified objects are currently picked, and "
|
||||
"compare that number to a value. If previous conditions on the "
|
||||
"objects have not been used, this condition counts how many of "
|
||||
"these objects exist in the current scene."),
|
||||
_("The number of _PARAM0_ objects is _PARAM1__PARAM2_"),
|
||||
_("Objects"),
|
||||
"res/conditions/nbObjet24.png",
|
||||
"res/conditions/nbObjet.png")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.AddParameter("relationalOperator", _("Sign of the test"))
|
||||
.AddParameter("expression", _("Value to test"))
|
||||
@@ -1046,6 +1071,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.AddCodeOnlyParameter("conditionInverted", "")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("yesorno",
|
||||
_("Ignore objects that are touching each other on their "
|
||||
"edges, but are not overlapping (default: no)"),
|
||||
"",
|
||||
true)
|
||||
.SetDefaultValue("no")
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
@@ -1119,12 +1151,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddExpression(
|
||||
"Count",
|
||||
_("Number of objects"),
|
||||
_("Count the number of the specified objects currently picked"),
|
||||
_("Objects"),
|
||||
"res/conditions/nbObjet.png")
|
||||
.AddExpression("Count",
|
||||
_("Number of objects"),
|
||||
_("Count the number of the specified objects being "
|
||||
"currently picked in the event"),
|
||||
_("Objects"),
|
||||
"res/conditions/nbObjet.png")
|
||||
.AddParameter("objectList", _("Object"));
|
||||
|
||||
obj.AddStrExpression("ObjectName",
|
||||
|
@@ -13,9 +13,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
gd::PlatformExtension& extension) {
|
||||
extension
|
||||
.SetExtensionInformation("BuiltinFile",
|
||||
_("Storage and files"),
|
||||
_("Storage"),
|
||||
_("Built-in extension providing functions "
|
||||
"to store data and manipulate files."),
|
||||
"to store data."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/all-features/storage");
|
||||
@@ -26,55 +26,55 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
"GroupExists",
|
||||
_("Existence of a group"),
|
||||
_("Check if an element (example : PlayerState/CurrentLevel) exists "
|
||||
"in the file.\nSpaces are forbidden in element names."),
|
||||
_("_PARAM1_ exists in file _PARAM0_"),
|
||||
"in the stored data.\nSpaces are forbidden in element names."),
|
||||
_("_PARAM1_ exists in storage _PARAM0_"),
|
||||
_("Storage"),
|
||||
"res/conditions/fichier24.png",
|
||||
"res/conditions/fichier.png")
|
||||
.AddParameter("file", _("Filename"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"LoadFile",
|
||||
_("Load a structured file in memory"),
|
||||
_("This action loads the structured file in memory, so you can write "
|
||||
"and read it.\nYou can open and write without using this action, "
|
||||
"but it will be slower.\nIf you use this action, do not forget to "
|
||||
"unload the file from memory.\n\nFor the native platform, the file "
|
||||
"format is XML."),
|
||||
_("Load structured file _PARAM0_ in memory"),
|
||||
_("Load a storage in memory"),
|
||||
_("This action loads the specified storage in memory, so you can "
|
||||
"write and read it.\nYou can open and write without using this "
|
||||
"action, but it will be slower.\nIf you use this action, do not "
|
||||
"forget to unload the storage from memory."),
|
||||
_("Load storage _PARAM0_ in memory"),
|
||||
_("Storage"),
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("file", _("File"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("UnloadFile",
|
||||
_("Close a structured file"),
|
||||
_("This action closes the structured file previously loaded "
|
||||
_("Close a storage"),
|
||||
_("This action closes the structured data previously loaded "
|
||||
"in memory, saving all changes made."),
|
||||
_("Close structured file _PARAM0_"),
|
||||
_("Close structured data _PARAM0_"),
|
||||
_("Storage"),
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("file", _("File"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("EcrireFichierExp",
|
||||
_("Write a value"),
|
||||
_("Write the result of the expression in the file, in the "
|
||||
"specified element.\nSpecify the structure leading to the "
|
||||
"element using / (example : Root/Level/Current)\nSpaces are "
|
||||
"forbidden in element names."),
|
||||
_("Write _PARAM2_ in _PARAM1_ of file _PARAM0_"),
|
||||
_("Storage"),
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("file", _("File"))
|
||||
.AddAction(
|
||||
"EcrireFichierExp",
|
||||
_("Write a value"),
|
||||
_("Write the result of the expression in the stored data, in the "
|
||||
"specified element.\nSpecify the structure leading to the "
|
||||
"element using / (example : Root/Level/Current)\nSpaces are "
|
||||
"forbidden in element names."),
|
||||
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
|
||||
_("Storage"),
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddParameter("expression", _("Expression"));
|
||||
|
||||
@@ -82,14 +82,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
.AddAction(
|
||||
"EcrireFichierTxt",
|
||||
_("Write a text"),
|
||||
_("Write the text in the file, in the specified element.\nSpecify "
|
||||
_("Write the text in the specified storage, in the specified "
|
||||
"element.\nSpecify "
|
||||
"the structure leading to the element using / (example : "
|
||||
"Root/Level/Current)\nSpaces are forbidden in element names."),
|
||||
_("Write _PARAM2_ in _PARAM1_ of file _PARAM0_"),
|
||||
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
|
||||
_("Storage"),
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("file", _("File"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddParameter("string", _("Text"));
|
||||
|
||||
@@ -101,11 +102,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
"variable.\nSpecify the structure leading to the element using / "
|
||||
"(example : Root/Level/Current)\nSpaces are forbidden in element "
|
||||
"names."),
|
||||
_("Read _PARAM1_ from file _PARAM0_ and store value in _PARAM3_"),
|
||||
_("Read _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
|
||||
_("Storage"),
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("file", _("File"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("scenevar", _("Scene variables"));
|
||||
@@ -118,11 +119,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
"variable.\nSpecify the structure leading to the element using / "
|
||||
"(example : Root/Level/Current)\nSpaces are forbidden in element "
|
||||
"names."),
|
||||
_("Read _PARAM1_ from file _PARAM0_ and store as text in _PARAM3_"),
|
||||
_("Read _PARAM1_ from storage _PARAM0_ and store as text in "
|
||||
"_PARAM3_"),
|
||||
_("Storage"),
|
||||
"res/actions/fichier24.png",
|
||||
"res/actions/fichier.png")
|
||||
.AddParameter("file", _("File"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("scenevar", _("Scene variables"));
|
||||
@@ -131,36 +133,37 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
|
||||
.AddAction("DeleteGroupFichier",
|
||||
_("Delete an element"),
|
||||
_("This action deletes the specified element from the "
|
||||
"structured file.\nSpecify the structure leading to the "
|
||||
"specified storage.\nSpecify the structure leading to the "
|
||||
"element using / (example : Root/Level/Current)\nSpaces are "
|
||||
"forbidden in element names."),
|
||||
_("Delete _PARAM1_ from the file _PARAM0_"),
|
||||
_("Delete _PARAM1_ from storage _PARAM0_"),
|
||||
_("Storage"),
|
||||
"res/actions/delete24.png",
|
||||
"res/actions/delete.png")
|
||||
.AddParameter("file", _("Filename"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.AddParameter("string", _("Group"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("DeleteFichier",
|
||||
_("Delete a file"),
|
||||
_("Delete the file."),
|
||||
_("Delete the file _PARAM0_"),
|
||||
_("Files"),
|
||||
"res/actions/delete24.png",
|
||||
"res/actions/delete.png")
|
||||
.AddParameter("file", _("Filename"));
|
||||
.AddAction(
|
||||
"DeleteFichier",
|
||||
_("Clear a storage"),
|
||||
_("Clear the specified storage, removing all data saved in it."),
|
||||
_("Delete storage _PARAM0_"),
|
||||
_("Storage"),
|
||||
"res/actions/delete24.png",
|
||||
"res/actions/delete.png")
|
||||
.AddParameter("string", _("Storage name"));
|
||||
|
||||
extension
|
||||
.AddCondition("FileExists",
|
||||
_("A file exists"),
|
||||
_("Test if the file exists."),
|
||||
_("File _PARAM0_ exists"),
|
||||
_("Files"),
|
||||
_("A storage exists"),
|
||||
_("Test if the specified storage exists."),
|
||||
_("Storage _PARAM0_ exists"),
|
||||
_("Storage"),
|
||||
"res/conditions/fichier24.png",
|
||||
"res/conditions/fichier.png")
|
||||
.AddParameter("file", _("Filename"))
|
||||
.AddParameter("string", _("Storage name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
|
@@ -221,7 +221,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("expression", _("Touch identifier"))
|
||||
.AddParameter("relationalOperator", _("Sign of the test"))
|
||||
.AddParameter("expression", _("X position"))
|
||||
.AddParameter("expression", _("Y position"))
|
||||
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
|
||||
.SetDefaultValue("\"\"")
|
||||
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
|
||||
|
@@ -492,7 +492,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("", _("Name of the point"), "", true);
|
||||
.AddParameter("string", _("Name of the point"), "", true);
|
||||
|
||||
obj.AddExpression("Y",
|
||||
_("Y position of a point"),
|
||||
@@ -501,7 +501,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("", _("Name of the point"), "", true);
|
||||
.AddParameter("string", _("Name of the point"), "", true);
|
||||
|
||||
obj.AddExpression("PointX",
|
||||
_("X position of a point"),
|
||||
@@ -510,7 +510,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("", _("Name of the point"));
|
||||
.AddParameter("string", _("Name of the point"));
|
||||
|
||||
obj.AddExpression("PointY",
|
||||
_("Y position of a point"),
|
||||
@@ -519,7 +519,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("", _("Name of the point"));
|
||||
.AddParameter("string", _("Name of the point"));
|
||||
|
||||
obj.AddExpression("Direc",
|
||||
_("Direction"),
|
||||
|
@@ -61,14 +61,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
extension
|
||||
.AddAction("ResetTimer",
|
||||
_("Start (or reset) a scene timer"),
|
||||
_("Reset the specified scene timer, if the timer doesn't exist "
|
||||
"it's created and started."),
|
||||
_("Reset the timer _PARAM1_"),
|
||||
_("Timers and time"),
|
||||
"res/actions/timer24.png",
|
||||
"res/actions/timer.png")
|
||||
.AddAction(
|
||||
"ResetTimer",
|
||||
_("Start (or reset) a scene timer"),
|
||||
_("Reset the specified scene timer, if the timer doesn't exist "
|
||||
"it's created and started."),
|
||||
_("Reset the timer _PARAM1_"),
|
||||
_("Timers and time"),
|
||||
"res/actions/timer24.png",
|
||||
"res/actions/timer.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
|
||||
@@ -197,10 +198,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
|
||||
"res/actions/time.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter(
|
||||
"",
|
||||
_("Hour : hour\nMinutes : min\nSeconds : sec\nDay of the month : "
|
||||
"mday\nMonths since January : mon\nYear since 1900 : year\nDays "
|
||||
"since sunday :wday\nDays since January 1st : yday"));
|
||||
"stringWithSelector",
|
||||
_("Hour: hour - Minutes: min - Seconds: sec - Day of month: "
|
||||
"mday - Months since January: mon - Year since 1900: year - Days "
|
||||
"since Sunday: wday - Days since Jan 1st: yday - Timestamp (ms): "
|
||||
"timestamp\""),
|
||||
"[\"hour\", \"min\", \"sec\", \"mon\", \"year\", \"wday\", \"mday\", "
|
||||
"\"yday\", \"timestamp\"]");
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@@ -50,7 +50,20 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
|
||||
info.codeOnly = false;
|
||||
info.optional = parameterIsOptional;
|
||||
info.supplementaryInformation =
|
||||
optionalObjectType.empty() ? "" : extensionNamespace + optionalObjectType;
|
||||
// For objects/behavior, the supplementary information
|
||||
// parameter is an object/behavior type...
|
||||
(gd::ParameterMetadata::IsObject(type) ||
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
? (optionalObjectType.empty()
|
||||
? ""
|
||||
: extensionNamespace +
|
||||
optionalObjectType //... so prefix it with the extension
|
||||
// namespace.
|
||||
)
|
||||
: optionalObjectType; // Otherwise don't change anything
|
||||
|
||||
// TODO: Assert against optionalObjectType === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
|
||||
parameters.push_back(info);
|
||||
return *this;
|
||||
|
@@ -9,13 +9,17 @@
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
#include "InstructionMetadata.h"
|
||||
|
||||
namespace gd {
|
||||
InstructionMetadata::InstructionMetadata()
|
||||
: sentence(_("Unknown or unsupported instruction")),
|
||||
: sentence(
|
||||
"Unknown or unsupported instruction"), // Avoid translating this
|
||||
// string, so that it's safe
|
||||
// and *fast* to use a
|
||||
// InstructionMetadata.
|
||||
canHaveSubInstructions(false),
|
||||
hidden(true) {}
|
||||
|
||||
@@ -65,7 +69,20 @@ InstructionMetadata& InstructionMetadata::AddParameter(
|
||||
info.codeOnly = false;
|
||||
info.optional = parameterIsOptional;
|
||||
info.supplementaryInformation =
|
||||
optionalObjectType.empty() ? "" : extensionNamespace + optionalObjectType;
|
||||
// For objects/behavior, the supplementary information
|
||||
// parameter is an object/behavior type...
|
||||
(gd::ParameterMetadata::IsObject(type) ||
|
||||
gd::ParameterMetadata::IsBehavior(type))
|
||||
? (optionalObjectType.empty()
|
||||
? ""
|
||||
: extensionNamespace +
|
||||
optionalObjectType //... so prefix it with the extension
|
||||
// namespace.
|
||||
)
|
||||
: optionalObjectType; // Otherwise don't change anything
|
||||
|
||||
// TODO: Assert against optionalObjectType === "emsc" (when running with
|
||||
// Emscripten), and warn about a missing argument when calling addParameter.
|
||||
|
||||
parameters.push_back(info);
|
||||
return *this;
|
||||
@@ -94,7 +111,8 @@ void ParameterMetadata::SerializeTo(SerializerElement& element) const {
|
||||
|
||||
void ParameterMetadata::UnserializeFrom(const SerializerElement& element) {
|
||||
type = element.GetStringAttribute("type");
|
||||
supplementaryInformation = element.GetStringAttribute("supplementaryInformation");
|
||||
supplementaryInformation =
|
||||
element.GetStringAttribute("supplementaryInformation");
|
||||
optional = element.GetBoolAttribute("optional");
|
||||
description = element.GetStringAttribute("description");
|
||||
codeOnly = element.GetBoolAttribute("codeOnly");
|
||||
|
@@ -146,7 +146,9 @@ class GD_CORE_API ParameterMetadata {
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is "object", "objectPtr" or
|
||||
* "objectList". \see gd::ParameterMetadata::GetType
|
||||
* "objectList".
|
||||
*
|
||||
* \see gd::ParameterMetadata::GetType
|
||||
*/
|
||||
static bool IsObject(const gd::String ¶meterType) {
|
||||
return parameterType == "object" || parameterType == "objectPtr" ||
|
||||
@@ -155,8 +157,17 @@ class GD_CORE_API ParameterMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is "object", "objectPtr" or
|
||||
* "objectList". \see gd::ParameterMetadata::GetType
|
||||
* \brief Return true if the type of the parameter is "behavior".
|
||||
*
|
||||
* \see gd::ParameterMetadata::GetType
|
||||
*/
|
||||
static bool IsBehavior(const gd::String ¶meterType) {
|
||||
return parameterType == "behavior";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the type of the parameter is an expression of the
|
||||
* given type.
|
||||
*/
|
||||
static bool IsExpression(const gd::String &type,
|
||||
const gd::String ¶meterType) {
|
||||
@@ -166,7 +177,10 @@ class GD_CORE_API ParameterMetadata {
|
||||
} else if (type == "string") {
|
||||
return parameterType == "string" || parameterType == "layer" ||
|
||||
parameterType == "color" || parameterType == "file" ||
|
||||
parameterType == "joyaxis";
|
||||
parameterType == "joyaxis" || parameterType == "stringWithSelector";
|
||||
} else if (type == "variable") {
|
||||
return parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -19,8 +19,8 @@ class PlatformExtension;
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A container for metadata about an object/behavior/instruction/expression
|
||||
* and its associated extension.
|
||||
* \brief A container for metadata about an
|
||||
* object/behavior/instruction/expression and its associated extension.
|
||||
*/
|
||||
template <class T>
|
||||
class ExtensionAndMetadata {
|
||||
@@ -34,8 +34,7 @@ class ExtensionAndMetadata {
|
||||
* \warning Please do not use.
|
||||
* \private
|
||||
*/
|
||||
ExtensionAndMetadata()
|
||||
: extension(nullptr), metadata(nullptr){};
|
||||
ExtensionAndMetadata() : extension(nullptr), metadata(nullptr){};
|
||||
|
||||
/**
|
||||
* \brief Get the associated extension.
|
||||
@@ -296,6 +295,11 @@ class GD_CORE_API MetadataProvider {
|
||||
gd::String behaviorType,
|
||||
gd::String name);
|
||||
|
||||
static bool IsBadExpressionMetadata(const gd::ExpressionMetadata& metadata) {
|
||||
return &metadata == &badExpressionMetadata ||
|
||||
&metadata == &badStrExpressionMetadata;
|
||||
}
|
||||
|
||||
virtual ~MetadataProvider();
|
||||
|
||||
private:
|
||||
|
@@ -75,6 +75,12 @@ class GD_CORE_API Platform {
|
||||
* Member functions used to manage the extensions
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief (Re)load platform built-in extensions.
|
||||
* \note Can be useful if, for example, the user changed the language
|
||||
* of the editor.
|
||||
*/
|
||||
virtual void ReloadBuiltinExtensions(){};
|
||||
|
||||
/**
|
||||
* \brief Must return the name of the function that is used to create an
|
||||
|
@@ -19,7 +19,7 @@ class GD_CORE_API PropertyDescriptor {
|
||||
* value. \param propertyValue The value of the property.
|
||||
*/
|
||||
PropertyDescriptor(gd::String propertyValue)
|
||||
: currentValue(propertyValue), type("string") {}
|
||||
: currentValue(propertyValue), type("string"), label("") {}
|
||||
|
||||
/**
|
||||
* \brief Empty constructor creating an empty property to be displayed.
|
||||
@@ -51,6 +51,14 @@ class GD_CORE_API PropertyDescriptor {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Change the label displayed in the property grid.
|
||||
*/
|
||||
PropertyDescriptor& SetLabel(gd::String label_) {
|
||||
label = label_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add an information about the property.
|
||||
* \note The information are arbitrary and are interpreted by the class
|
||||
@@ -65,6 +73,7 @@ class GD_CORE_API PropertyDescriptor {
|
||||
|
||||
const gd::String& GetValue() const { return currentValue; }
|
||||
const gd::String& GetType() const { return type; }
|
||||
const gd::String& GetLabel() const { return label; }
|
||||
const std::vector<gd::String>& GetExtraInfo() const {
|
||||
return extraInformation;
|
||||
}
|
||||
@@ -74,6 +83,7 @@ class GD_CORE_API PropertyDescriptor {
|
||||
gd::String
|
||||
type; ///< The type of the property. This is arbitrary and interpreted by
|
||||
///< the class responsible for updating the property grid.
|
||||
gd::String label; //< The user-friendly property name
|
||||
std::vector<gd::String>
|
||||
extraInformation; ///< Can be used to store for example the available
|
||||
///< choices, if a property is a displayed as a combo
|
||||
|
@@ -9,102 +9,71 @@
|
||||
#include <vector>
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
class CallbacksForListingObjects : public gd::ParserCallbacks {
|
||||
/**
|
||||
* \brief Go through the nodes and report any object found.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionObjectsAnalyzer
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
CallbacksForListingObjects(const gd::Platform& platform_,
|
||||
const gd::ObjectsContainer& project_,
|
||||
const gd::ObjectsContainer& layout_,
|
||||
EventsContext& context_)
|
||||
: platform(platform_),
|
||||
project(project_),
|
||||
layout(layout_),
|
||||
context(context_){};
|
||||
virtual ~CallbacksForListingObjects(){};
|
||||
ExpressionObjectsAnalyzer(EventsContext& context_) : context(context_){};
|
||||
virtual ~ExpressionObjectsAnalyzer(){};
|
||||
|
||||
virtual void OnConstantToken(gd::String text){};
|
||||
|
||||
virtual void OnStaticFunction(gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
for (std::size_t i = 0;
|
||||
i < parameters.size() && i < expressionInfo.parameters.size();
|
||||
++i) {
|
||||
EventsContextAnalyzer::AnalyzeParameter(platform,
|
||||
project,
|
||||
layout,
|
||||
expressionInfo.parameters[i],
|
||||
parameters[i],
|
||||
context);
|
||||
}
|
||||
};
|
||||
|
||||
virtual void OnObjectFunction(gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
for (std::size_t i = 0;
|
||||
i < parameters.size() && i < expressionInfo.parameters.size();
|
||||
++i) {
|
||||
EventsContextAnalyzer::AnalyzeParameter(platform,
|
||||
project,
|
||||
layout,
|
||||
expressionInfo.parameters[i],
|
||||
parameters[i],
|
||||
context);
|
||||
}
|
||||
};
|
||||
|
||||
virtual void OnObjectBehaviorFunction(
|
||||
gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
for (std::size_t i = 0;
|
||||
i < parameters.size() && i < expressionInfo.parameters.size();
|
||||
++i) {
|
||||
EventsContextAnalyzer::AnalyzeParameter(platform,
|
||||
project,
|
||||
layout,
|
||||
expressionInfo.parameters[i],
|
||||
parameters[i],
|
||||
context);
|
||||
}
|
||||
};
|
||||
|
||||
virtual bool OnSubMathExpression(const gd::Platform& platform,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression) {
|
||||
CallbacksForListingObjects callbacks(platform, project, layout, context);
|
||||
|
||||
gd::ExpressionParser parser(expression.GetPlainString());
|
||||
parser.ParseMathExpression(platform, project, layout, callbacks);
|
||||
return true;
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
|
||||
virtual bool OnSubTextExpression(const gd::Platform& platform,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression) {
|
||||
CallbacksForListingObjects callbacks(platform, project, layout, context);
|
||||
|
||||
gd::ExpressionParser parser(expression.GetPlainString());
|
||||
parser.ParseStringExpression(platform, project, layout, callbacks);
|
||||
return true;
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
if (gd::ParameterMetadata::IsObject(node.type)) {
|
||||
context.AddObjectName(node.identifierName);
|
||||
}
|
||||
}
|
||||
void OnVisitFunctionNode(FunctionNode& node) override {
|
||||
if (!node.objectName.empty()) {
|
||||
context.AddObjectName(node.objectName);
|
||||
}
|
||||
|
||||
for (auto& parameter : node.parameters) {
|
||||
parameter->Visit(*this);
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {}
|
||||
|
||||
private:
|
||||
const gd::Platform& platform;
|
||||
const gd::ObjectsContainer& project;
|
||||
const gd::ObjectsContainer& layout;
|
||||
EventsContext& context;
|
||||
};
|
||||
|
||||
@@ -142,15 +111,17 @@ void EventsContextAnalyzer::AnalyzeParameter(
|
||||
if (ParameterMetadata::IsObject(type)) {
|
||||
context.AddObjectName(value);
|
||||
} else if (ParameterMetadata::IsExpression("number", type)) {
|
||||
CallbacksForListingObjects callbacks(platform, project, layout, context);
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", value);
|
||||
|
||||
gd::ExpressionParser parser(value);
|
||||
parser.ParseMathExpression(platform, project, layout, callbacks);
|
||||
ExpressionObjectsAnalyzer analyzer(context);
|
||||
node->Visit(analyzer);
|
||||
} else if (ParameterMetadata::IsExpression("string", type)) {
|
||||
CallbacksForListingObjects callbacks(platform, project, layout, context);
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", value);
|
||||
|
||||
gd::ExpressionParser parser(value);
|
||||
parser.ParseStringExpression(platform, project, layout, callbacks);
|
||||
ExpressionObjectsAnalyzer analyzer(context);
|
||||
node->Visit(analyzer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,200 +8,159 @@
|
||||
#include <memory>
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
class CallbacksForRenamingObject : public gd::ParserCallbacks {
|
||||
/**
|
||||
* \brief Go through the nodes and change the given object name to a new one.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
CallbacksForRenamingObject(gd::String& plainExpression_,
|
||||
gd::String oldName_,
|
||||
gd::String newName_)
|
||||
: plainExpression(plainExpression_),
|
||||
newName(newName_),
|
||||
oldName(oldName_){};
|
||||
virtual ~CallbacksForRenamingObject(){};
|
||||
ExpressionObjectRenamer(const gd::String& objectName_,
|
||||
const gd::String& objectNewName_)
|
||||
: hasDoneRenaming(false), objectName(objectName_), objectNewName(objectNewName_){};
|
||||
virtual ~ExpressionObjectRenamer(){};
|
||||
|
||||
virtual void OnConstantToken(gd::String text) { plainExpression += text; };
|
||||
static bool Rename(gd::ExpressionNode & node, const gd::String& objectName, const gd::String& objectNewName) {
|
||||
if (ExpressionValidator::HasNoErrors(node)) {
|
||||
ExpressionObjectRenamer renamer(objectName, objectNewName);
|
||||
node.Visit(renamer);
|
||||
|
||||
virtual void OnStaticFunction(gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
// Special case : Function without name is a litteral string.
|
||||
if (functionName.empty()) {
|
||||
if (parameters.empty()) return;
|
||||
plainExpression += "\"" + parameters[0].GetPlainString() + "\"";
|
||||
|
||||
return;
|
||||
return renamer.HasDoneRenaming();
|
||||
}
|
||||
|
||||
gd::String parametersStr;
|
||||
for (std::size_t i = 0; i < parameters.size(); ++i) {
|
||||
if (i < expressionInfo.parameters.size() &&
|
||||
expressionInfo.parameters[i].codeOnly)
|
||||
continue; // Skip code only parameter which are not included in
|
||||
// function calls.
|
||||
|
||||
if (!parametersStr.empty()) parametersStr += ",";
|
||||
parametersStr += parameters[i].GetPlainString();
|
||||
}
|
||||
plainExpression += functionName + "(" + parametersStr + ")";
|
||||
};
|
||||
|
||||
virtual void OnObjectFunction(gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
if (parameters.empty()) return;
|
||||
|
||||
gd::String parametersStr;
|
||||
for (std::size_t i = 1; i < parameters.size(); ++i) {
|
||||
if (i < expressionInfo.parameters.size() &&
|
||||
expressionInfo.parameters[i].codeOnly)
|
||||
continue; // Skip code only parameter which are not included in
|
||||
// function calls.
|
||||
|
||||
if (!parametersStr.empty()) parametersStr += ",";
|
||||
parametersStr += parameters[i].GetPlainString();
|
||||
}
|
||||
plainExpression += (parameters[0].GetPlainString() == oldName
|
||||
? newName
|
||||
: parameters[0].GetPlainString()) +
|
||||
"." + functionName + "(" + parametersStr + ")";
|
||||
};
|
||||
|
||||
virtual void OnObjectBehaviorFunction(
|
||||
gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
if (parameters.size() < 2) return;
|
||||
|
||||
gd::String parametersStr;
|
||||
for (std::size_t i = 2; i < parameters.size(); ++i) {
|
||||
if (i < expressionInfo.parameters.size() &&
|
||||
expressionInfo.parameters[i].codeOnly)
|
||||
continue; // Skip code only parameter which are not included in
|
||||
// function calls.
|
||||
|
||||
if (!parametersStr.empty()) parametersStr += ",";
|
||||
parametersStr += parameters[i].GetPlainString();
|
||||
}
|
||||
plainExpression += (parameters[0].GetPlainString() == oldName
|
||||
? newName
|
||||
: parameters[0].GetPlainString()) +
|
||||
"." + parameters[1].GetPlainString() +
|
||||
"::" + functionName + "(" + parametersStr + ")";
|
||||
};
|
||||
|
||||
virtual bool OnSubMathExpression(const gd::Platform& platform,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression) {
|
||||
// TODO: Add support for renaming in sub expressions. This is not working
|
||||
// as the parser does not handle change made to the expression.
|
||||
gd::String newExpression;
|
||||
|
||||
CallbacksForRenamingObject callbacks(newExpression, oldName, newName);
|
||||
|
||||
gd::ExpressionParser parser(expression.GetPlainString());
|
||||
if (!parser.ParseMathExpression(platform, project, layout, callbacks))
|
||||
return false;
|
||||
|
||||
expression = gd::Expression(newExpression); // This change won't be picked up by the parser
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnSubTextExpression(const gd::Platform& platform,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression) {
|
||||
// TODO: Add support for renaming in sub expressions. This is not working
|
||||
// as the parser does not handle change made to the expression.
|
||||
gd::String newExpression;
|
||||
bool HasDoneRenaming() const { return hasDoneRenaming; }
|
||||
|
||||
CallbacksForRenamingObject callbacks(newExpression, oldName, newName);
|
||||
|
||||
gd::ExpressionParser parser(expression.GetPlainString());
|
||||
if (!parser.ParseStringExpression(platform, project, layout, callbacks))
|
||||
return false;
|
||||
|
||||
expression = gd::Expression(newExpression); // This change won't be picked up by the parser
|
||||
return true;
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
if (gd::ParameterMetadata::IsObject(node.type) && node.identifierName == objectName) {
|
||||
hasDoneRenaming = true;
|
||||
node.identifierName = objectNewName;
|
||||
}
|
||||
}
|
||||
void OnVisitFunctionNode(FunctionNode& node) override {
|
||||
if (node.objectName == objectName) {
|
||||
hasDoneRenaming = true;
|
||||
node.objectName = objectNewName;
|
||||
}
|
||||
for (auto& parameter : node.parameters) {
|
||||
parameter->Visit(*this);
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {}
|
||||
|
||||
private:
|
||||
gd::String& plainExpression;
|
||||
gd::String newName;
|
||||
gd::String oldName;
|
||||
bool hasDoneRenaming;
|
||||
const gd::String& objectName;
|
||||
const gd::String& objectNewName;
|
||||
};
|
||||
|
||||
class CallbacksForRemovingObject : public gd::ParserCallbacks {
|
||||
/**
|
||||
* \brief Go through the nodes and check if the given object is being used
|
||||
* in the expression.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
CallbacksForRemovingObject(gd::String name_)
|
||||
: objectPresent(false), name(name_){};
|
||||
virtual ~CallbacksForRemovingObject(){};
|
||||
ExpressionObjectFinder(const gd::String& objectName_)
|
||||
: hasObject(false), objectName(objectName_) {};
|
||||
virtual ~ExpressionObjectFinder(){};
|
||||
|
||||
bool objectPresent; // True if the object is present in the expression
|
||||
static bool CheckIfHasObject(gd::ExpressionNode & node, const gd::String & objectName) {
|
||||
if (ExpressionValidator::HasNoErrors(node)) {
|
||||
ExpressionObjectFinder finder(objectName);
|
||||
node.Visit(finder);
|
||||
|
||||
virtual void OnConstantToken(gd::String text){};
|
||||
return finder.HasFoundObject();
|
||||
}
|
||||
|
||||
virtual void OnStaticFunction(gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo){};
|
||||
|
||||
virtual void OnObjectFunction(gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
if (parameters.empty()) return;
|
||||
|
||||
if (parameters[0].GetPlainString() == name) objectPresent = true;
|
||||
};
|
||||
|
||||
virtual void OnObjectBehaviorFunction(
|
||||
gd::String functionName,
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const gd::ExpressionMetadata& expressionInfo) {
|
||||
if (parameters.empty()) return;
|
||||
|
||||
if (parameters[0].GetPlainString() == name) objectPresent = true;
|
||||
};
|
||||
|
||||
virtual bool OnSubMathExpression(const gd::Platform& platform,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression) {
|
||||
CallbacksForRemovingObject callbacks(name);
|
||||
|
||||
gd::ExpressionParser parser(expression.GetPlainString());
|
||||
if (!parser.ParseMathExpression(platform, project, layout, callbacks))
|
||||
return false;
|
||||
|
||||
if (callbacks.objectPresent) objectPresent = true;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool OnSubTextExpression(const gd::Platform& platform,
|
||||
const gd::ObjectsContainer& project,
|
||||
const gd::ObjectsContainer& layout,
|
||||
gd::Expression& expression) {
|
||||
CallbacksForRemovingObject callbacks(name);
|
||||
bool HasFoundObject() const { return hasObject; }
|
||||
|
||||
gd::ExpressionParser parser(expression.GetPlainString());
|
||||
if (!parser.ParseStringExpression(platform, project, layout, callbacks))
|
||||
return false;
|
||||
|
||||
if (callbacks.objectPresent) objectPresent = true;
|
||||
return true;
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
if (gd::ParameterMetadata::IsObject(node.type) && node.identifierName == objectName) {
|
||||
hasObject = true;
|
||||
}
|
||||
}
|
||||
void OnVisitFunctionNode(FunctionNode& node) override {
|
||||
if (node.objectName == objectName) {
|
||||
hasObject = true;
|
||||
}
|
||||
for (auto& parameter : node.parameters) {
|
||||
parameter->Visit(*this);
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {}
|
||||
|
||||
private:
|
||||
gd::String name;
|
||||
bool hasObject;
|
||||
const gd::String& objectName;
|
||||
};
|
||||
|
||||
bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
@@ -221,34 +180,23 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
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].type)) {
|
||||
gd::String newExpression;
|
||||
gd::String oldExpression =
|
||||
actions[aId].GetParameter(pNb).GetPlainString();
|
||||
|
||||
CallbacksForRenamingObject callbacks(newExpression, oldName, newName);
|
||||
|
||||
gd::ExpressionParser parser(oldExpression);
|
||||
if (parser.ParseMathExpression(platform, project, layout, callbacks) &&
|
||||
newExpression != oldExpression) {
|
||||
somethingModified = true;
|
||||
actions[aId].SetParameter(pNb, gd::Expression(newExpression));
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
actions[aId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression("string", instrInfos.parameters[pNb].type)) {
|
||||
gd::String newExpression;
|
||||
gd::String oldExpression =
|
||||
actions[aId].GetParameter(pNb).GetPlainString();
|
||||
|
||||
CallbacksForRenamingObject callbacks(newExpression, oldName, newName);
|
||||
|
||||
gd::ExpressionParser parser(oldExpression);
|
||||
if (parser.ParseStringExpression(
|
||||
platform, project, layout, callbacks) &&
|
||||
newExpression != oldExpression) {
|
||||
somethingModified = true;
|
||||
actions[aId].SetParameter(pNb, gd::Expression(newExpression));
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
actions[aId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,31 +233,23 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
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].type)) {
|
||||
gd::String newExpression;
|
||||
gd::String oldExpression =
|
||||
conditions[cId].GetParameter(pNb).GetPlainString();
|
||||
|
||||
CallbacksForRenamingObject callbacks(newExpression, oldName, newName);
|
||||
|
||||
gd::ExpressionParser parser(oldExpression);
|
||||
if (parser.ParseMathExpression(platform, project, layout, callbacks)) {
|
||||
somethingModified = true;
|
||||
conditions[cId].SetParameter(pNb, gd::Expression(newExpression));
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
conditions[cId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression("string", instrInfos.parameters[pNb].type)) {
|
||||
gd::String newExpression;
|
||||
gd::String oldExpression =
|
||||
conditions[cId].GetParameter(pNb).GetPlainString();
|
||||
|
||||
CallbacksForRenamingObject callbacks(newExpression, oldName, newName);
|
||||
|
||||
gd::ExpressionParser parser(oldExpression);
|
||||
if (parser.ParseMathExpression(platform, project, layout, callbacks)) {
|
||||
somethingModified = true;
|
||||
conditions[cId].SetParameter(pNb, gd::Expression(newExpression));
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
conditions[cId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,33 +318,30 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
gd::InstructionMetadata instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
// Find object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
actions[aId].GetParameter(pNb).GetPlainString() == name) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
// Replace object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression("number", instrInfos.parameters[pNb].type)) {
|
||||
CallbacksForRemovingObject callbacks(name);
|
||||
|
||||
gd::ExpressionParser parser(
|
||||
actions[aId].GetParameter(pNb).GetPlainString());
|
||||
if (parser.ParseMathExpression(platform, project, layout, callbacks) &&
|
||||
callbacks.objectPresent) {
|
||||
// Find object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression("string", instrInfos.parameters[pNb].type)) {
|
||||
CallbacksForRemovingObject callbacks(name);
|
||||
|
||||
gd::ExpressionParser parser(
|
||||
actions[aId].GetParameter(pNb).GetPlainString());
|
||||
if (parser.ParseStringExpression(
|
||||
platform, project, layout, callbacks) &&
|
||||
callbacks.objectPresent) {
|
||||
// Find object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
@@ -442,33 +379,30 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
gd::InstructionMetadata instrInfos = MetadataProvider::GetConditionMetadata(
|
||||
platform, conditions[cId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
// Find object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
conditions[cId].GetParameter(pNb).GetPlainString() == name) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
// Replace object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression("number", instrInfos.parameters[pNb].type)) {
|
||||
CallbacksForRemovingObject callbacks(name);
|
||||
|
||||
gd::ExpressionParser parser(
|
||||
conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
if (parser.ParseMathExpression(platform, project, layout, callbacks) &&
|
||||
callbacks.objectPresent) {
|
||||
// Find object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression("string", instrInfos.parameters[pNb].type)) {
|
||||
CallbacksForRemovingObject callbacks(name);
|
||||
|
||||
gd::ExpressionParser parser(
|
||||
conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
if (parser.ParseStringExpression(
|
||||
platform, project, layout, callbacks) &&
|
||||
callbacks.objectPresent) {
|
||||
// Find object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
break;
|
||||
}
|
||||
|