Compare commits

...

258 Commits

Author SHA1 Message Date
Davy Hélard
3a113ea419 Generate ObjectsLists names without mangled namespace 2023-04-04 14:15:03 +02:00
D8H
e52faae332 Test the create action picking (#5178)
* Useful for dev only
2023-03-31 13:27:34 +02:00
Clément Pasteau
31809fdf61 Add missing types (#5184)
Do not show in changelog
2023-03-31 12:32:50 +02:00
AlexandreS
17504c1713 Add possibility to revert cloud project to last sane version (#5180) 2023-03-31 11:25:15 +02:00
github-actions[bot]
e29b79fdc9 Update translations [skip ci] (#5172)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-31 11:23:40 +02:00
Clément Pasteau
b0009cc999 Fix too many aliases for analytics (#5177)
Do not show in changelog
2023-03-31 11:12:57 +02:00
Clément Pasteau
384eb2b8ee Add sounds packs category on the asset store (#5179) 2023-03-30 14:39:20 +02:00
AlexandreS
5fa0627218 Randomize private asset packs in asset home (#5176)
Don't show in changelog
2023-03-30 11:11:15 +02:00
D8H
e66660d2df Fix the creation of a new frame with the image editor when the animation doesn't have a name (#5175)
* Don't show in changelog
2023-03-29 12:32:25 +02:00
Clément Pasteau
df6320c39f Display lessons on Learn section on mobile (#5174)
Do not show in changelog
2023-03-29 10:44:25 +02:00
D8H
ca667c02be [Tilemap] Fix collision name between tilemap object and collision mask object (#5173)
* Projects that use actions and conditions of the wrong object should still work. To fix the red underling of object names, actions for the right object can now be selected.
2023-03-29 10:00:18 +02:00
AlexandreS
62d0754b33 Update properties panel after paste or duplication of instances (#5171) 2023-03-28 15:36:17 +02:00
Clément Pasteau
4c4ca0d202 Try to fix providers crashing the app if services return an unexpected response (#5170)
Do not show in changelog
2023-03-28 13:08:37 +02:00
github-actions[bot]
5c68d117c6 Update translations [skip ci] (#5168)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-28 11:51:21 +02:00
AlexandreS
21b9ae47ab Update icons bis (#5169)
Don't show in changelog
2023-03-28 11:33:07 +02:00
D8H
e8687119c9 Fix errors not being displayed in expressions when an object or a behavior doesn't exist (#5146)
* GDevelop will now warn when an object (or group of objects) written in an expression is misspelled or does not exist in the scene.
2023-03-27 13:55:23 +02:00
D8H
9c09e26aaa Fix the Not condition to handle its last sub condition correctly (#5074) 2023-03-27 13:29:27 +02:00
Tristan Rhodes
c223abad60 Add property a property to particle to "Jump the emitter forward in time" when it's created (#5039)
* This works like the action of the same name, and allow newly created particle emitters to act as if they were emitting since a bit of time - useful when starting a scene for example to avoid seeing the initial particles being emitted.
2023-03-27 13:27:03 +02:00
github-actions[bot]
769de55317 Update translations [skip ci] (#5166)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-03-27 13:22:37 +02:00
Clément Pasteau
0dfe765ae1 Increase allowed time to load the game in memory on Android before failing (#5110)
* This should help old or constrained devices to better run large games.
2023-03-27 13:21:50 +02:00
D8H
b94ce2b20d When renaming or removing an object, only refactor associated external events (#5155)
* The editor used to refactor every events that were used in the object layout even if they were associated to another layout which could result to errors.
2023-03-27 12:55:00 +02:00
Infokub
89eb61b4a6 Add a new expression to get the maximum of an inventory item (#5126) 2023-03-26 13:28:05 +02:00
Florian Rival
32ba55e726 Delete .devcontainer
Outdated and not working well

Don't show in changelog
2023-03-26 13:16:40 +02:00
Infokub
844ac23666 Add a warning about installing an extension from the store if it replaces an extension manually created (#5111) 2023-03-26 12:38:46 +02:00
github-actions[bot]
657036384d Update translations [skip ci] (#5161)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-03-24 19:21:52 +01:00
Florian Rival
b13ce5b17c Fix shape painter anti-aliasing select labels
Don't show in changelog
2023-03-24 18:30:12 +01:00
Clément Pasteau
8f0f5a5bc5 Fix the behavior fields crashing the app when edited inline in the Events Sheet (#5162) 2023-03-24 18:23:49 +01:00
AlexandreS
d23a064ca2 Update icons everywhere possible (#5160)
Don't show in changelog
2023-03-24 17:25:52 +01:00
github-actions[bot]
3b0dc66046 Update translations [skip ci] (#5159)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-24 17:00:00 +01:00
Clément Pasteau
356bde650b Improve selection of a Scene in an instruction with a drop-down list (#5154) 2023-03-24 16:27:38 +01:00
github-actions[bot]
6d25496f89 Update translations [skip ci] (#5157)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-24 16:19:39 +01:00
Oxey405
dfeeb864a5 Allow setting anti-aliasing on shape drawer (#4509)
* defaulted to "none", it allows 3 anti-aliasing options, from "low" to "high" increasing quality of the drawings.
2023-03-24 16:19:07 +01:00
Clément Pasteau
25c36d26db Fix drag preview causing a request without Origin (#5158)
* This request can be cached by Chrome and causing CORS issues for following requests.
2023-03-24 16:02:05 +01:00
Arthur Pacaud
36721c63e0 Improve various aspects of the Firebase extension (#5125)
* Update Firebase SDK to v8.10.0
* Fix small firebase usability issues
* Fix tracer stopping
* Fix a crash when using tracers
* Add password reset action to authentication
2023-03-24 15:32:10 +01:00
github-actions[bot]
69cd89ddb8 Update translations [skip ci] (#5153)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-23 18:27:22 +01:00
AlexandreS
2db4b54986 Add Algolia search results from the wiki to the command palette (#5148) 2023-03-23 16:31:58 +01:00
D8H
303a4d20ed Fix the default image name suggested to Piskel when the animation name is empty (#5152)
* The resource name was given with the extension which resulted to a file names with twice the extension.
2023-03-23 15:38:42 +01:00
Clément Pasteau
a09bfafd26 Improve guided lessons so they can be done on mobile (#5143) 2023-03-23 15:02:13 +01:00
github-actions[bot]
822329af63 Update translations [skip ci] (#5149)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-23 11:58:44 +01:00
Florian Rival
0b90e17307 Adapt the rendering of reference document to Markdown for the new wiki (#5112)
Don't show in changelog
2023-03-23 11:43:57 +01:00
github-actions[bot]
00817b4393 Update translations [skip ci] (#5140)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-22 11:26:46 +01:00
Clément Pasteau
2a5bbcb8d4 Add new guided lesson: Timer (#5144) 2023-03-22 11:05:41 +01:00
github-actions[bot]
7f03579855 Update translations [skip ci] (#5136)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-21 12:12:30 +01:00
Clément Pasteau
c7e42d1e88 Improve the selection of a layer in an instruction (#5119)
* The layer selection is now done via a dropdown by default, with the possibility to switch to an expression
2023-03-21 12:11:45 +01:00
AlexandreS
e3fd91681c Fix: Upgrade shifty to 2.20.4 to prevent tweens to be applied when a scene is resumed (#5139) 2023-03-21 11:07:24 +01:00
Clément Pasteau
c8392332c7 Block auto-translate tools to avoid unfixable crashes with React (#5138) 2023-03-21 10:12:41 +01:00
Clément Pasteau
14d7dafb79 Fix wrong props (#5137)
Do not show in changelog
2023-03-21 09:26:05 +01:00
Clément Pasteau
373d5e14b8 New guided lesson: Joystick (#5135) 2023-03-20 17:56:32 +01:00
github-actions[bot]
8b89896082 Update translations [skip ci] (#5133)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-20 17:50:01 +01:00
D8H
e7d213534e Revert: Report errors in expressions when an object or a behavior doesn't exist (#5118) (#5134)
Do not show in changelog
2023-03-20 15:08:40 +01:00
D8H
859b1d0a1c Refactor events when project elements are renamed (#5031)
* Project elements are: scenes, external layouts, external events, layers, layer effects, object effects, sprite animations and sprite points.
2023-03-20 12:02:36 +01:00
Clément Pasteau
2b6a14c612 Bump version to 5.1.159 (#5121) 2023-03-20 10:56:22 +01:00
github-actions[bot]
07051017b9 Update translations [skip ci] (#5131)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-20 10:51:29 +01:00
Clément Pasteau
0d5f238c75 Increase drag preview on touch screens (#5132)
Do not show in changelog
2023-03-20 10:43:45 +01:00
D8H
936c75b4ed Round dragged points and collision masks vertices of sprites (#5124) 2023-03-20 10:20:59 +01:00
AlexandreS
8d1bdfed25 Add possibility to scroll editor tabs horizontally with the mouse wheel (#5130) 2023-03-20 10:05:26 +01:00
github-actions[bot]
440205531f Update translations [skip ci] (#5123)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-03-20 09:28:04 +01:00
D8H
8f45642a25 Fix the "pick all" and "pick a random" conditions when they are used in functions (#5128) 2023-03-19 13:24:24 +01:00
D8H
1e6ca8c403 Fix a regression on extension loading (#5127)
* Don't show in changelog
2023-03-19 13:23:42 +01:00
D8H
113e329d7a Fix a collision mask compatibility issue with a breaking change of Tiled 1.10 (#5122)
* Handle the "type" attribute as an alias of "class".
2023-03-17 19:22:03 +01:00
D8H
48ae688873 Report errors in expressions when an object or a behavior doesn't exist (#5118) 2023-03-17 15:24:24 +01:00
Clément Pasteau
fe77180748 Improve preview of dragged items (#5076)
* This is valid for Groups & Objects, and allows seeing the item while dragging on the canvas
* This also allows having a preview visible on touchscreens while dragging an item with your finger
2023-03-17 12:07:12 +01:00
D8H
48b88b9d92 Add tests on loop events and boolean operator conditions (#5117)
* Show in developer logs only
2023-03-16 18:12:32 +01:00
D8H
f57a8bc6cd Fix behaviors that were staying in the list after switching of project with an extension tab opened (#5102) 2023-03-16 18:10:36 +01:00
Clément Pasteau
1b827eb67b Always scroll to the newly created items across the app (#5114)
* This allows always seeing the element that was just added
* Works for Object/Group/Behavior/Effect/Animation/Function
2023-03-16 15:24:13 +01:00
github-actions[bot]
c3521db5ba Update translations [skip ci] (#5108)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-16 15:11:23 +01:00
Clément Pasteau
b51e47233e Remove some unnecessary dismissable info messages (#5115)
Do not show in changelog
2023-03-16 14:58:54 +01:00
github-actions[bot]
1bf9d3c432 Update translations [skip ci] (#5106)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-14 18:30:48 +01:00
Clément Pasteau
1c47d12033 Allow opening any guided lesson from the URL (#5107)
Do not show in changelog
2023-03-14 18:30:14 +01:00
Clément Pasteau
1250060848 Rework sprites list to make button sticky and improve mobile view (#5096) 2023-03-14 18:03:25 +01:00
AlexandreS
4712c3d9ef Add new guided lesson about how to add a health bar prefab (#5095) 2023-03-14 17:02:21 +01:00
Clément Pasteau
56cf1cf18f Allow opening instance properties from instance right click on canvas (#5105) 2023-03-14 16:09:22 +01:00
github-actions[bot]
0427766b9d Update translations [skip ci] (#5094)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-03-14 15:18:18 +01:00
D8H
8cf20cdef2 [Tilemap] Fix the tile map resource property of the collision mask object to accept tilemap resources in addition to json ones (#5101) 2023-03-13 15:55:53 +01:00
D8H
b3f74a3e9b Keep example templates list order (#5103)
* Don't show in changelog
2023-03-13 15:04:44 +01:00
Clément Pasteau
38f15503e9 Improve Scene canvas interactions (#5072)
* Increase canvas FPS to 60 when interacting
* Reduce FPS to 10 when not using the canvas
* This should make the editor feel smoother when used, as well as save battery life when not using it!
* Also detect pinch zoom for trackpads
2023-03-10 18:09:51 +01:00
AlexandreS
47f15f6881 Keep scroll when navigating from page to page in the asset store (#5092) 2023-03-10 17:39:48 +01:00
Clément Pasteau
b0c8bf9625 Fix audio pack url download (#5093)
Do not show in changelog
2023-03-10 17:09:26 +01:00
github-actions[bot]
089c774ad6 Update translations [skip ci] (#5086)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-10 14:10:37 +01:00
Clément Pasteau
a2ca532749 Add new guided lesson: Camera Parallax (#5090) 2023-03-10 14:01:14 +01:00
AlexandreS
a6e7dd6160 Add possibility to close preview window with Cmd/Ctrl + W (#5088) 2023-03-10 11:33:55 +01:00
D8H
7b6f3c029d [Platformer] Fix horizontal speed losses when characters land or jump from a slope (#5077)
* It fixes a regression that was introduced in the 5.0.139 release.
2023-03-10 11:24:30 +01:00
D8H
6c31056be4 Fix the touch end condition to detect a touch that ends because the device can't handle more touches (#5079) 2023-03-09 17:39:29 +01:00
D8H
2f8287b017 Fix a white flash when opening a project with a tile map (#5084)
* Also allow atlas images to be bigger than expected as some artists extend them to add their names. The error was aiming to help to understand that rescaled atlas will not work without changing the tiles size, but artifacts can actually help figuring this out.
2023-03-09 16:31:55 +01:00
github-actions[bot]
0ef4012b03 Update translations [skip ci] (#5067)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-09 14:38:35 +01:00
Clément Pasteau
438d70e8ba Fix identifying correctly non auth users (#5085)
Do not show in changelog
2023-03-09 14:34:08 +01:00
AlexandreS
04214abc85 Update layers list when scene editor becomes active again (#5083)
Don't show in changelog
2023-03-09 12:21:29 +01:00
AlexandreS
32fa646e47 Better synchronize object groups between layout and external layout
- Also, in the project resources tab, refresh image preview when checking or unchecking the smooth image option.
2023-03-09 11:46:48 +01:00
AlexandreS
78952816b9 Fix: Change selected layer when it's removed (#5082) 2023-03-09 11:37:39 +01:00
Clément Pasteau
6057496ff8 Fix search results crashing if auto-translate is activated (#5081)
Do not show in changelog
2023-03-09 11:19:06 +01:00
AlexandreS
76f1832b4e Remove hard-coded color (#5075)
Don't show in changelog
2023-03-08 16:27:36 +01:00
Tristan Rhodes
d8e1c1ee8a Update wording for the "Create package for Android" button so that it is clearer (#5069) 2023-03-08 09:15:17 +01:00
D8H
3de8ec0759 Fix the unsupported instructions when a function is renamed (#5062)
* Extension creators no longer need to switch tabs to refresh the extension.
2023-03-07 16:28:05 +01:00
Arthur Pacaud
de3d5e6583 Update P2P hints/explanations shown in the editor (#5004)
* Add a mention to THNK as a multiplayer framework to try.
2023-03-07 16:06:17 +01:00
github-actions[bot]
a772c7baa9 Update translations [skip ci] (#5066)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-03-07 15:54:26 +01:00
Clément Pasteau
5730fcb611 Send additional info to analytics (#5061)
Do not show in changelog
2023-03-07 15:47:06 +01:00
Clément Pasteau
b601e94791 Add first mini guided lesson, Plinko Multiplier (#5051)
* This is the first lesson of many, with the goal of covering multiple game creation concepts
* The lessons are available in the Learn or Get Started sections of the homepage
* This lesson can be finished in just a few minutes, directly inside the app
* In this first lesson, we go through improving the score of a game, through variables
2023-03-07 14:51:50 +01:00
github-actions[bot]
b7bf4ea62b Update translations [skip ci] (#5064)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-07 12:52:47 +01:00
AlexandreS
46466d5c11 Warn user when adding an instance to a layer that is not visible (#5063) 2023-03-07 11:56:25 +01:00
github-actions[bot]
1892dc09c3 Update translations [skip ci] (#5057)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-03-06 10:03:52 +01:00
AlexandreS
e5a710d7d5 Fix offset between image and container for small images (#5056)
Don't show in changelog
2023-03-03 15:24:51 +01:00
D8H
561e18a044 Fix extension renaming (#5054)
* Behaviors of the extension with the old name no longer stay in the list.
2023-03-03 15:23:41 +01:00
github-actions[bot]
fb9c29af52 Update translations [skip ci] (#5048)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-02 18:04:44 +01:00
AlexandreS
dade3483be Fix points preview to give priority to selected point when dragging a point (#5049)
Co-authored-by: D8H <Davy.Helard@gmail.com>
2023-03-02 16:54:38 +01:00
AlexandreS
05e6c41ed3 Add possibility to select layer on which instances will be added by default (#5046) 2023-03-02 16:04:13 +01:00
Florian Rival
cd6a400fcb Fix filters panel always opening on small screens (#5047)
* Also fix a confusing warning message when opening link in a markdown text (like in the changelog or in the tutorials) on mobile with unsaved changes in the project.
2023-03-02 15:33:14 +01:00
AlexandreS
b648ecba45 Add color to example difficulty tag (#5045) 2023-03-02 15:31:55 +01:00
github-actions[bot]
681636a74a Update translations [skip ci] (#5041)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-02 09:25:51 +01:00
AlexandreS
d4e8a7a314 Display asset packs from the same creator when viewing a premium asset pack (#5044) 2023-03-01 17:25:52 +01:00
AlexandreS
56ed187eba Bump newIDE version (#5040) 2023-03-01 13:16:47 +01:00
AlexandreS
6c26d69a7b Prevent in app tutorial tooltip from overflowing (#5043)
Don't show in changelog
2023-03-01 13:13:52 +01:00
D8H
b2d13077a8 Fix the position of pasted object instances to always appear on screen (#5020) 2023-03-01 11:52:49 +01:00
D8H
399d9c2c14 Add an action to include or exclude a child from its parent collision mask (#5000)
* This is useful for custom objects.
2023-03-01 11:51:25 +01:00
D8H
1d5bb98233 Allow extensions to define measurement units (#5010) 2023-03-01 11:23:31 +01:00
Florian Rival
e6c0c23789 Move the filter button and panel in the assets store (#5038)
Don't show in changelog
2023-03-01 11:18:19 +01:00
github-actions[bot]
33ce33215b Update translations [skip ci] (#5034)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-01 10:11:41 +01:00
AlexandreS
8f547c63b2 Add support for premium asset pack that contains audio only (#5036)
- Also supports asset pack that contains sprites and audio and gives possibility to download the audio of the pack
2023-03-01 09:49:33 +01:00
Florian Rival
4ac404ccfc Fix homepage layout shifts at loading (#5035)
* This makes the opening of GDevelop less "jumpy".
2023-02-28 18:08:34 +01:00
Florian Rival
f04ebc0e19 Allow usage of toolbar buttons to add an event or a sub-event when an action or a condition is selected (#5032) 2023-02-28 12:22:35 +01:00
Clément Pasteau
ebabcd0ddc Fix font for lists and menu padding (#5033)
Do not show in changelog
2023-02-28 11:13:12 +01:00
github-actions[bot]
afc279dd8a Update translations [skip ci] (#5021)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-02-28 10:23:27 +01:00
D8H
5bd8da0b75 Pass a context to the top-down movement hook methods (#5023)
* Don't show in changelog
2023-02-28 10:17:13 +01:00
Tristan Rhodes
3195813a0b Update nightly build links in documentation to 5.1 (#5030) 2023-02-27 17:39:54 +01:00
Florian Rival
de28cebb67 Fix warnings
Don't show in changelog
2023-02-27 15:10:26 +01:00
Florian Rival
d0038ce536 Highlight the icons of the opened editors in the toolbars (#5027) 2023-02-27 14:16:40 +01:00
D8H
60c0a0c1a8 Adapt the events of a behavior when it is copied from one extension to another (#4812) 2023-02-27 12:42:49 +01:00
Clément Pasteau
1df03601f8 Update extension icons (#5029)
Do not show in changelog
2023-02-27 11:29:40 +01:00
AlexandreS
474b6b6d9d Image preview fixes (#5028)
Don't show in changelog
2023-02-27 11:12:10 +01:00
Florian Rival
c1fad4c123 Fix variables sometimes overflowing out of the screen on small screens 2023-02-25 23:48:05 +01:00
D8H
9690f1f195 Fix instance selection box buttons margin (#5022) 2023-02-25 11:02:37 +01:00
D8H
0eabd5aed3 Fix the instance duplication to occur only when they are dragged (#5018) 2023-02-24 20:30:32 +01:00
Florian Rival
e0e7037dd8 Improve colors and design of the panels in the editors 2023-02-24 19:15:20 +01:00
AlexandreS
412dc0b4ea Improve zoom on the points and collision masks editors 2023-02-24 18:53:12 +01:00
github-actions[bot]
111c6eb014 Update translations [skip ci] (#5012)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-02-24 18:15:43 +01:00
Florian Rival
1f0f62099b Fix parameters of an extension function overflowing on small screens 2023-02-24 18:14:41 +01:00
D8H
ea10467062 Fix Control and Shift handling in the instances editor (#5016) 2023-02-24 17:53:17 +01:00
Florian Rival
a6dac96db1 Adapt title sizes for small screens or small windows (#5017) 2023-02-24 17:00:53 +01:00
D8H
b8de8d4f15 Add missing group icons on the conditions and actions list (#5014) 2023-02-24 14:34:05 +01:00
Daniel R
d25cad5aaf Add shortcut (Ctrl+D or Cmd+D) to duplicate selected instance(s) on the scene editor (#5011) 2023-02-24 13:04:09 +01:00
D8H
f0583df184 Fix the note of the generated extension reference pages (#5013)
* Don't show in changelog
2023-02-24 12:47:27 +01:00
Arthur Pacaud
8d25904462 Allow to wait for Filesystem actions to finish before continuing the actions/sub-events following it (#5001)
* This means the Filesystem actions can optionally be set as being "waited for", like the "Wait X seconds" action.
2023-02-24 11:47:42 +01:00
github-actions[bot]
9e9db1fc4c Update translations [skip ci] (#5007)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-24 09:50:35 +01:00
Clément Pasteau
9047b5a4ec Improve objects panel design (#4997)
* Add button is more accessible, as well as search bar
* Slightly improve font-size and margins to fit more objects
* Also improve all listings in the app (Groups, Resources, Extensions objects)
2023-02-24 09:25:22 +01:00
Tristan Rhodes
4dbe90b9a2 Added new action "Jump emitter forward in time" (#4985)
* This is particularly useful to let emitters create lot of particles first then continue at a slower rate
2023-02-24 09:07:54 +01:00
Clément Pasteau
73b88b7d5e Activate gdevelop logo by default, with Watermark (#5009)
Do not show in changelog
2023-02-23 15:47:15 +01:00
D8H
e8bc3b7ee8 Allow JavaScript extensions to customize the top-down movement behavior (#4999)
* Only for developers
2023-02-23 14:34:20 +01:00
Clément Pasteau
baa3cad99a Remove yarn lock to avoid maintaining 2 lock files (#5008)
Do not show in changelog
2023-02-23 11:38:35 +01:00
Clément Pasteau
f477af7c6b Improve object dialog to display a warning if canceling after any change (#4989) 2023-02-23 11:22:52 +01:00
AlexandreS
f8cedfd357 Performance: Slightly reduce number of requests to server at app opening (#4990) 2023-02-23 10:45:30 +01:00
github-actions[bot]
1021447b02 Update translations [skip ci] (#5006)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-23 09:40:28 +01:00
Clément Pasteau
7567584ecd Fix yml indentation (#5005)
Do not show in changelog
2023-02-23 09:29:34 +01:00
Clément Pasteau
90f75fba42 Use Node16 for translations update to avoid package lock conflict (#5003)
Do not show in changelog
2023-02-22 17:33:38 +01:00
Florian Rival
fcc35f4e3c Fix outdated package-lock.json
Don't show in changelog
2023-02-22 14:28:29 +01:00
Florian Rival
01a7c48864 Don't show the Get Started page if the screen is too small when launching the app (#5002) 2023-02-22 14:21:27 +01:00
github-actions[bot]
be6a7753cf Update translations [skip ci] (#4966)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-21 18:23:37 +01:00
D8H
3b1e0a5750 Show function-related actions, conditions and expressions only when editing a function (#4992) 2023-02-21 18:23:01 +01:00
Clément Pasteau
4d2fd4752f Force node version 16 for storybook (#4996)
Do not show in changelog
2023-02-21 18:20:26 +01:00
Clément Pasteau
8e00e9615e Fix tutorial tooltip being translated and causing a crash on web (#4995) 2023-02-21 17:04:55 +01:00
D8H
68253017ee Add autocompletion for repeat events (#4993) 2023-02-21 16:01:51 +01:00
Florian Rival
35c91f6f99 Fix crash when closing a project after unsaved changes (#4994) 2023-02-21 14:55:11 +01:00
AlexandreS
803559fad8 Upgrade storybook (#4991)
Don't show in changelog
2023-02-21 12:14:29 +01:00
AlexandreS
e85229d38e Drag project manager items using icon and not label (#4988) 2023-02-20 16:51:54 +01:00
Clément Pasteau
e7381a7229 Simplify slug management so that is reads the cache value (#4973)
Do not show in changelog
2023-02-20 15:20:04 +01:00
D8H
257ba78486 Allow event-based objects to define a rotation center point (#4910)
* It will allow sliders to work vertically.
2023-02-20 11:55:53 +01:00
Aurélien Vivet
fb3d821368 Add a value range (#4877)
Don't show in changelog
2023-02-20 11:45:15 +01:00
Aurélien Vivet
a5068d8fcf Add a line about Silver plan unlocking the watermark & GD logo when the game loads. (#4979) 2023-02-20 10:58:22 +01:00
Florian Rival
d20b3228cf Fix Debugger crashing when GDevelop logo was enabled (#4980) 2023-02-19 19:29:06 +01:00
D8H
aae54ef331 Link the extension installation page on every extension page (#4974) 2023-02-18 16:07:20 +01:00
AlexandreS
caa5105651 Improve some things on mobile (#4971)
Don't show in changelog
2023-02-17 12:50:07 +01:00
Florian Rival
5eccdde332 Allow authentication to player accounts using an iframe in some exceptional cases (#4968)
Don't show in changelog
2023-02-17 11:49:23 +01:00
AlexandreS
c34d758ccf Fix display of Social network share buttons on mobile (#4969)
Don't show in changelog
2023-02-16 18:29:59 +01:00
AlexandreS
4e57d6aee9 Do not display importing resources dialog full screen (#4967)
Don't show in changelog
2023-02-16 16:52:00 +01:00
AlexandreS
74d208f736 Allow export dialog to only have the online web export (#4965)
Don't show in changelog
2023-02-16 16:19:10 +01:00
github-actions[bot]
d88b76becf Update translations [skip ci] (#4938)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-02-16 15:49:51 +01:00
D8H
4a0e2481e6 Fix author chips wrapping on small screens (#4943) 2023-02-16 12:59:25 +01:00
D8H
612b041da4 Add tags for the code size and difficulty level of examples (#4958) 2023-02-16 11:16:56 +01:00
AlexandreS
3df7cd8e80 Add check on project file content existence at opening (#4961)
Don't show in changelog
2023-02-16 11:01:32 +01:00
AlexandreS
7ba96ed0ab Use safe area only on portrait (#4962)
Don't show in changelog
2023-02-15 19:17:18 +01:00
AlexandreS
689cd14947 Use device orientation to define default scene editor layout (#4960) 2023-02-15 17:55:10 +01:00
AlexandreS
de50dc7967 Use safe area to correctly display a few elements (#4959)
Don't show in changelog
2023-02-15 15:39:58 +01:00
Florian Rival
1aa2afaf85 Fix "Insert new..." menu option not doing anything if objects list was closed 2023-02-15 11:58:28 +01:00
Clément Pasteau
9120a52a08 Rename Liluo.io to gd.games (#4954) 2023-02-14 17:42:46 +01:00
AlexandreS
b0ffaebe91 Fix subscription diamond svg not displaying on Safari and Firefox (#4948)
Don't show in changelog
2023-02-14 16:09:34 +01:00
D8H
64a4a0b3a1 Add a tool to count the number of instructions of examples (#4952)
* Only show in "Internal changes" changelog
2023-02-14 15:52:53 +01:00
AlexandreS
cdfd7a7ab1 Autotranslate improvements (#4951)
Don't show in changelog
2023-02-14 14:08:57 +01:00
Florian Rival
a944ac43db Update README
Don't show in changelog
2023-02-14 12:40:59 +01:00
Clément Pasteau
b7a1a96e7b Update storybook urls (#4949)
Do not show in changelog
2023-02-14 09:54:02 +01:00
Clément Pasteau
29d71796cc Remove unused ravenjs (sentry) (#4940)
Do not show in changelog
2023-02-13 16:41:28 +01:00
AlexandreS
78a1361897 Use form in account related actions to simplify mobile experience (#4917)
Don't show in changelog
2023-02-13 14:27:05 +01:00
AlexandreS
e340784ad6 Prevent google translate issue (#4937)
Don't show in changelog
2023-02-13 14:22:08 +01:00
github-actions[bot]
511466f0b8 Update translations [skip ci] (#4909)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-02-13 10:39:08 +01:00
Florian Rival
3f4e372acb Fix check of subscriptions
Don't show in changelog
2023-02-10 17:01:18 +01:00
D8H
a73a92d748 Fix tile map loading for collision mask objects (#4916) 2023-02-10 15:52:06 +01:00
AlexandreS
6e131d8a17 Display asset pack categories in asset store homepage (#4905) 2023-02-10 14:57:24 +01:00
D8H
9ac4c021e0 Fix the number parameter color in the events (#4915) 2023-02-10 11:37:38 +01:00
AlexandreS
a1fbf91ac7 Add Eye icon to switch password visibility (#4914) 2023-02-09 17:16:13 +01:00
Clément Pasteau
3f8d01e25e Improve subscription messages when a redeem code has been used (#4912) 2023-02-09 16:56:54 +01:00
AlexandreS
03b4170d74 Fix resource store display for extension icon (#4913)
Don't show in changelog
2023-02-09 15:34:13 +01:00
AlexandreS
0146ad9c38 Add error boundary at the app level (#4911)
Don't show in changelog
2023-02-09 12:19:26 +01:00
Clément Pasteau
fbb23f86cd Rename and add more actions, conditions and expressions to manipulate array variables (#4904) 2023-02-08 16:53:57 +01:00
github-actions[bot]
1fdaeea4f8 Update translations [skip ci] (#4893)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-08 11:21:06 +01:00
Clément Pasteau
32b97f2c40 Improve search accuracy in the app (instructions, examples, objects, tags) (#4906)
* Use tokenized search to improve search with multiple words looking into multiple keys (ex: name & description)
2023-02-08 09:41:27 +01:00
AlexandreS
d61f8336a8 Fix firebase extension tests (#4907)
Don't show in changelog
2023-02-07 17:11:16 +01:00
Clément Pasteau
3448cd57fe Allow showing an alertMessage without an icon (#4903) 2023-02-06 16:41:55 +01:00
Clément Pasteau
b7333612aa Prompt for email verification when logging in or signing up (#4898) 2023-02-06 11:45:32 +01:00
Aurélien Vivet
de82182b37 fix typo (#4899)
Do not show in changelog
2023-02-06 08:47:53 +01:00
Clément Pasteau
a8177b0e6f Upgrade electron-builder (#4892)
* This should fix the auto-updater uninstalling GDevelop without re-installing it on Windows, if installed "for all users"
2023-02-03 13:48:43 +01:00
AlexandreS
9716ff14ed Fix: Use correct default values for effects with color parameters (#4891) 2023-02-03 12:06:26 +01:00
Clément Pasteau
f0e1d7a6d9 Bump to 5.1.157 (#4886)
Do not show in changelog
2023-02-02 15:48:45 +01:00
github-actions[bot]
dd89562405 Update translations [skip ci] (#4887)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-02 15:48:29 +01:00
Clément Pasteau
f0e56c4513 Update tutorials for offline use (#4888)
Do not show in changelog
2023-02-02 15:47:59 +01:00
Clément Pasteau
ad2ea0abb8 Improve search accuracy for conditions and actions (#4885) 2023-02-02 15:38:42 +01:00
D8H
7ff71ea11f Make the button to open condition/action extensions easier to see (#4884) 2023-02-02 15:35:01 +01:00
github-actions[bot]
cd1d82f7ee Update translations [skip ci] (#4839)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-02 15:34:09 +01:00
Clément Pasteau
0724b7d113 Move save to toolbar (#4883)
Do not show in changelog
2023-02-02 15:26:26 +01:00
Clément Pasteau
c58ea73631 Upgrade AdMob extension (#4881)
* Updated internal Google Ads SDK version
* Added "App open" ads
* Added "Rewarded Interstitial" ads
2023-02-02 13:03:41 +01:00
Arthur Pacaud
b1039c6146 Add support for asynchronous actions in extensions in the editor (#4819)
* By marking an action as asynchronous, the actions and sub-events following it will wait for it to end. This is similar to the "Wait X seconds" action.
* Don't forget to use the action *"End asynchronous function"* in the events to mark the end of the action. Otherwise, the action will never end.
2023-02-02 12:30:17 +01:00
D8H
1b5acc9fa9 Fix the instruction group of event functions with operator (#4882) 2023-02-02 11:38:16 +01:00
Clément Pasteau
54cf91f180 Display new objects in the New Object Dialog (#4871)
* Buttons
* Toggles, Switches and Sliders
* Multitouch Joysticks
* Health and loading bars
* (Those objects were previously available through the asset store and are now visible when creating an object from scratch)
2023-02-02 11:27:49 +01:00
D8H
a434e4d9a9 Add a button to jump to behavior events (#4878)
---------

Co-authored-by: Florian Rival <Florian.Rival@gmail.com>
2023-02-02 10:45:36 +01:00
Florian Rival
2f339dd170 Add a save icon button to the top left next to the app main menu 2023-02-01 22:33:07 +01:00
Florian Rival
e843ca67ad Update comment [skip ci]
Don't show in changelog
2023-02-01 15:32:30 +01:00
Florian Rival
e4286b2021 Show expiration date and clearer explanations when using a redemption code (#4879) 2023-02-01 09:37:45 +01:00
Florian Rival
4579568866 Fix formatting and improve namings
Don't show in changelog
2023-02-01 09:35:14 +01:00
Florian Rival
4543a03530 Render the grid of the scene in realtime when a change is made to the grid setup (#4880) 2023-02-01 09:26:33 +01:00
Florian Rival
5aed25a02f Hide labels from buttons to add objects (or other items) when a list is too narrow
Don't show in changelog
2023-01-31 22:16:09 +01:00
Florian Rival
6fd9cfe4c3 Fix Events Sheet crashes and inconsistent order or location of pasting (#4876)
* Fix extracting events to a function or to a group crashing sometimes the app
* Also ensure events are copied/pasted or moved in their order of selection
* Events or actions/conditions are now only pasted at a single location
  * We previously allowed pasted events/actions/conditions to be inserted multiple times for each selected event, but this was more confusing than useful.
  * Now, the pasted elements are only pasted on the last selected event/action/condition (usually the one you just right clicked)
2023-01-31 17:56:35 +01:00
D8H
091324d93b Add a condition to check if the player has just closed the leaderboard view (#4875) 2023-01-31 15:16:28 +01:00
D8H
d802bd14b9 Add an action to hide the player login banner (#4874) 2023-01-31 12:55:12 +01:00
D8H
f46a6dc421 Optimize the z-order action (#4868)
- Scenes should be faster to load
- Games that y-sort a lot of moving objects should run much faster.
2023-01-30 13:29:50 +01:00
Florian Rival
b09e783b06 Remove help buttons for each accordion in the editor of a custom object
Don't show in changelog
2023-01-30 12:43:27 +01:00
Florian Rival
e2a050b717 Reduce size of text alignment icons 2023-01-30 12:41:32 +01:00
Florian Rival
ae22d1b876 Fix warning
Don't show in changelog
2023-01-28 17:26:34 +01:00
Florian Rival
9e6e7166ef Allow to retry uploading a file that failed to be uploaded
Don't show in changelog
2023-01-28 16:56:29 +01:00
Florian Rival
22c71a8aef Fix regression in font loading
Don't show in changelog
2023-01-27 19:32:08 +01:00
Florian Rival
4908c84494 Adapt loading of resources to allow a token instead of a cookie (#4870)
Don't show in changelog
2023-01-27 18:11:39 +01:00
AlexandreS
e4f44f7899 Add possibility to display GDevelop watermark that opens Liluo creator page on click/touch (#4811) 2023-01-24 18:26:39 +01:00
AlexandreS
c441610123 Improve in app tutorial element highlighting (#4865)
Don't show in changelog
2023-01-24 17:48:55 +01:00
D8H
d724712aa4 Fix direction actions on Sprites after an animation change with custom origin (#4860)
* Impacted actions are "Turn toward a position" and "Add a force toward a position".
2023-01-24 15:04:36 +01:00
Florian Rival
08fc7d3e9f Fix typos in description of StartedTouchOrMouseId and StartedTouchOrMouseCount 2023-01-22 20:49:29 +01:00
Florian Rival
ba30665811 Open the file chooser when adding a sprite or choosing a resource with less clicks for Cloud projects (#4859)
*Choosing a file from the device/computer is also the default choice when adding any resource, like for local projects.
2023-01-22 19:17:27 +01:00
Florian Rival
c72658e2d6 Fix some missing extensions accepted for files for Cloud projects (#4858) 2023-01-22 18:35:19 +01:00
AlexandreS
a3fc7585b4 Show the number of instances on a layer in the dialog confirming its deletion (#4854) 2023-01-21 18:33:46 +01:00
Florian Rival
244bc7e274 Fix error when trying to save in Piskel immediately after saving a project in the cloud for the first time (#4857) 2023-01-21 17:06:35 +01:00
Florian Rival
5a5bf60aac Add a selector in external editors to choose if new files must be created, or existing files be edited (#4855) 2023-01-21 14:26:07 +01:00
Florian Rival
33a69849d9 Temporarily revert game with login template to use gdevelop-app.com to prevent CORS issue
Don't show in changelog
2023-01-20 16:56:07 +01:00
Florian Rival
131ee1534a Fix performance issue when pinching to zoom on the scene editor (#4852) 2023-01-20 16:54:40 +01:00
AlexandreS
614c324a63 Change SortableVirtualizedItemList ItemRow to use text field with same fontsize as when not editing (#4851)
Don't show in changelog
2023-01-20 15:12:31 +01:00
AlexandreS
ca4ff1fa6d Decrease line height in comments (#4850)
Don't show in changelog
2023-01-20 14:53:05 +01:00
AlexandreS
0e9ed86b4d Improved comment and group events display (#4846)
* Fix bug that added a new line when one typed Enter key to edit a comment event
* Focus comment or group event after adding it (so that one doesn't have to click on it after adding it)
* Keep the same style when editing a group or comment event
* Submit modifications of group or comment event with Ctrl/Cmd + Enter
2023-01-20 13:53:26 +01:00
Florian Rival
3961c2af4a Remove useless analytics event
Don't show in changelog
2023-01-20 10:33:22 +01:00
Daniel R
cc4d78b08a Don't snap to grid when resizing an instance if Alt key is pressed (#4847)
* This is similar to pressing Alt key when moving an object - it won't snap to the grid.
2023-01-20 09:12:46 +01:00
AlexandreS
8d13285c97 Fix GDJS tests (#4845)
Don't show in changelog
2023-01-19 09:36:21 +01:00
Florian Rival
7b7e13817c Hide the old, deprecated Text Entry object when creating a new object from scratch
* Instead, use the Text Input object to display a field to let the player write something.
2023-01-18 14:44:13 +01:00
Florian Rival
129ebeb4e4 Fix previews not automatically opened on iOS and Safari for the web-app (#4843) 2023-01-18 13:58:14 +01:00
Florian Rival
808f2bc802 Fix new images made with Piskel wrongly smoothed when the project is configured for pixel-art (#4844) 2023-01-18 13:35:43 +01:00
AlexandreS
c5935232f7 Add legacy flag on former plans (#4842)
Don't show in changelog
2023-01-18 12:37:06 +01:00
AlexandreS
35a8341964 Display former subscriptions (indie and pro) in user profile (#4841) 2023-01-18 11:02:24 +01:00
1085 changed files with 48428 additions and 34833 deletions

View File

@@ -1,6 +0,0 @@
# This is the Dockerfile to create a "devcontainer".
# This is a way to quickly create a development environment,
# that can be used with GitHub workspaces.
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/codespaces-linux/.devcontainer/base.Dockerfile
FROM mcr.microsoft.com/vscode/devcontainers/universal:1-focal

View File

@@ -1,16 +0,0 @@
# Devcontainer (development environment in the cloud) for GDevelop (beta)
A devcontainer is the configuration to run a cloud development environment, available remotely.
This is notably used to run a **[GitHub Codespace](https://docs.github.com/en/github/developing-online-with-codespaces/about-codespaces)**. The advantage is that you can quickly experiment and do changes without installing anything on your computer.
> ⚠️ This development environment is in beta, and not everything is supported. This is useful for playing a bit with GDevelop codebase or to make quick changes. **In particular, it's not possible to test your changes on GDJS** because only the web-app can be launched.
It's recommended that you follow the usual [README](../newIDE/README.md) to get started, with development tools installed on your computer.
## Start a GitHub workspace to work on GDevelop (beta)
- Subscribe to the [beta edition of GitHub workspace](https://docs.github.com/en/github/developing-online-with-codespaces/about-codespaces#joining-the-beta).
- In the repository GitHub page, click **Code** and then choose **Open with Codespaces**.
- Wait for the Codespace to load and Visual Studio Code to open.
- When it's ready, open a terminal in Visual Studio Code.
- Follow the usual [README in `newIDE`](../newIDE/README.md) to get started, like you would do on your own computer.

View File

@@ -1,51 +0,0 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/codespaces-linux
{
"name": "GitHub Codespaces for GDevelop",
"build": {
"dockerfile": "Dockerfile"
},
"settings": {
"terminal.integrated.shell.linux": "/bin/zsh",
"go.toolsManagement.checkForUpdates": "off",
"go.useLanguageServer": true,
"go.gopath": "/go",
"go.goroot": "/usr/local/go",
"python.pythonPath": "/opt/python/latest/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
"lldb.executable": "/usr/bin/lldb",
"files.watcherExclude": {
"**/target/**": true
}
},
"remoteUser": "codespace",
"overrideCommand": false,
"workspaceMount": "source=${localWorkspaceFolder},target=/home/codespace/workspace,type=bind,consistency=cached",
"workspaceFolder": "/home/codespace/workspace",
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--privileged", "--init" ],
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"GitHub.vscode-pull-request-github",
"esbenp.prettier-vscode",
"ms-vscode.cpptools",
"xaver.clang-format",
"flowtype.flow-for-vscode"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// "oryx build" will automatically install your dependencies and attempt to build your project
"postCreateCommand": "oryx build -p virtualenv_name=.venv || echo 'Could not auto-build. Skipping.'"
}

View File

@@ -17,6 +17,10 @@ jobs:
build-storybook:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
@@ -57,8 +61,8 @@ jobs:
- name: Log urls to the Storybook
run: |
echo "Find the latest Storybook for this branch on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html"
echo "Find the Storybook for this commit on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html"
echo "Find the latest Storybook for this branch on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html"
echo "Find the Storybook for this commit on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html"
# Publish on Chromatic, only when manually launched (too costly to run on every commit).
- name: Publish Storybook to Chromatic

View File

@@ -11,6 +11,9 @@ jobs:
extract-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: actions/checkout@v2
# Cache npm dependencies to speed up the workflow
@@ -38,7 +41,7 @@ jobs:
- name: Install Crowdin CLI
if: github.ref == 'refs/heads/master'
run: npm i -g @crowdin/cli
- name: Upload translations to Crowdin
run: crowdin upload sources
if: github.ref == 'refs/heads/master'

View File

@@ -14,6 +14,9 @@ jobs:
update-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: actions/checkout@v2
# Cache npm dependencies to speed up the workflow
@@ -44,7 +47,7 @@ jobs:
# (Build and) download the most recent translations (PO files) from Crowdin.
- name: Install Crowdin CLI
run: npm i -g @crowdin/cli
- name: Download new translations from Crowdin
run: crowdin download
env:
@@ -66,8 +69,8 @@ jobs:
commit-message: Update translations [skip ci]
branch: chore/update-translations
delete-branch: true
title: '[Auto PR] Update translations'
title: "[Auto PR] Update translations"
body: |
This updates the translations by downloading them from Crowdin and compiling them for usage by the app.
Please double check the values in `newIDE/app/src/locales/LocalesMetadata.js` to ensure the changes are sensible.

View File

@@ -13,6 +13,7 @@
namespace gd {
class Instruction;
class Project;
class EventVisitor;
}
class EventsCodeGenerationContext;

View File

@@ -16,6 +16,7 @@
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Events/EventVisitor.h"
using namespace std;
@@ -156,4 +157,14 @@ void LinkEvent::UnserializeFrom(gd::Project& project,
}
}
bool LinkEvent::AcceptVisitor(gd::EventVisitor &eventVisitor) {
return BaseEvent::AcceptVisitor(eventVisitor) |
eventVisitor.VisitLinkEvent(*this);
}
void LinkEvent::AcceptVisitor(gd::ReadOnlyEventVisitor &eventVisitor) const {
BaseEvent::AcceptVisitor(eventVisitor);
eventVisitor.VisitLinkEvent(*this);
}
} // namespace gd

View File

@@ -30,7 +30,7 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
includeEnd(gd::String::npos),
linkWasInvalid(false){};
virtual ~LinkEvent();
virtual gd::LinkEvent* Clone() const { return new LinkEvent(*this); }
virtual gd::LinkEvent* Clone() const override { return new LinkEvent(*this); }
/**
* Get the link target (i.e. the scene or external events the link refers to).
@@ -86,7 +86,7 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
/**
* The link event must always be preprocessed.
*/
virtual bool MustBePreprocessed() { return true; }
virtual bool MustBePreprocessed() override { return true; }
/**
* \brief Get a pointer to the list of events that are targeted by the link.
@@ -107,11 +107,14 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
EventsList& eventList,
std::size_t indexOfTheEventInThisList);
virtual bool IsExecutable() const { return true; };
virtual bool IsExecutable() const override { return true; };
virtual void SerializeTo(SerializerElement& element) const;
virtual void SerializeTo(SerializerElement& element) const override;
virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element);
const SerializerElement& element) override;
bool AcceptVisitor(gd::EventVisitor& eventVisitor) override;
void AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const override;
private:
gd::String

View File

@@ -273,8 +273,6 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
context.EnterCustomCondition();
conditionCode += GenerateReferenceToUpperScopeBoolean(
"conditionTrue", returnBoolean, context);
conditionCode += instrInfos.codeExtraInformation.customCodeGenerator(
condition, *this, context);
maxCustomConditionsDepth =
@@ -1258,6 +1256,11 @@ size_t EventsCodeGenerator::GenerateSingleUsageUniqueIdFor(
gd::String EventsCodeGenerator::GetObjectListName(
const gd::String& name, const gd::EventsCodeGenerationContext& context) {
return GetObjectListNameWithoutNamespace(name, context);
}
gd::String EventsCodeGenerator::GetObjectListNameWithoutNamespace(
const gd::String& name, const gd::EventsCodeGenerationContext& context) {
return ManObjListName(name);
}

View File

@@ -404,6 +404,18 @@ class GD_CORE_API EventsCodeGenerator {
return boolName;
}
/**
* \brief Generate the full name for accessing to a boolean variable used for
* conditions.
*
* Default implementation just returns the boolean name passed as argument.
*/
virtual gd::String GenerateUpperScopeBooleanFullName(
const gd::String& boolName,
const gd::EventsCodeGenerationContext& context) {
return boolName;
}
/**
* \brief Must create a boolean. Its value must be false.
*
@@ -423,6 +435,15 @@ class GD_CORE_API EventsCodeGenerator {
*/
virtual gd::String GetObjectListName(
const gd::String& name, const gd::EventsCodeGenerationContext& context);
/**
* \brief Get the list of objects full name without the namespace.
*
* Default implementation simply returns the name mangled using
* gd::EventsCodeNameMangler.
*/
virtual gd::String GetObjectListNameWithoutNamespace(
const gd::String& name, const gd::EventsCodeGenerationContext& context);
/**
* \brief Generate the code to notify the profiler of the beginning of a
@@ -493,7 +514,7 @@ class GD_CORE_API EventsCodeGenerator {
* - object : Object name -> string
* - expression : Mathematical expression -> number (double)
* - string : %Text expression -> string
* - layer, color, file, joyaxis : Same as string
* - layer, color, file, stringWithSelector : Same as string
* - relationalOperator : Used to make a comparison between the function
resturn value and value of the parameter preceding the relationOperator
parameter -> string
@@ -665,19 +686,6 @@ class GD_CORE_API EventsCodeGenerator {
return "!(" + predicat + ")";
};
/**
* \brief Must create a boolean which is a reference to a boolean declared in
* the parent scope.
*
* The default implementation generates C-style code.
*/
virtual gd::String GenerateReferenceToUpperScopeBoolean(
const gd::String& referenceName,
const gd::String& referencedBoolean,
gd::EventsCodeGenerationContext& context) {
return "bool & " + referenceName + " = " + referencedBoolean + ";\n";
}
virtual gd::String GenerateFreeCondition(
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,

View File

@@ -51,8 +51,8 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode(
codeGenerator.GetObjectsAndGroups(),
rootType);
node->Visit(validator);
if (!validator.GetErrors().empty()) {
std::cout << "Error: \"" << validator.GetErrors()[0]->GetMessage()
if (!validator.GetFatalErrors().empty()) {
std::cout << "Error: \"" << validator.GetFatalErrors()[0]->GetMessage()
<< "\" in: \"" << expression.GetPlainString() << "\" ("
<< rootType << ")" << std::endl;

View File

@@ -9,6 +9,7 @@
#include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/EventVisitor.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
@@ -140,6 +141,14 @@ void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator,
}
}
bool BaseEvent::AcceptVisitor(gd::EventVisitor& eventVisitor) {
return eventVisitor.VisitEvent(*this);
}
void BaseEvent::AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const {
eventVisitor.VisitEvent(*this);
}
BaseEventSPtr GD_CORE_API CloneRememberingOriginalEvent(BaseEventSPtr event) {
gd::BaseEventSPtr copy(event->Clone());
// Original event is either the original event of the copied event, or the

View File

@@ -24,6 +24,8 @@ class EventsCodeGenerationContext;
class Platform;
class SerializerElement;
class Instruction;
class EventVisitor;
class ReadOnlyEventVisitor;
} // namespace gd
namespace gd {
@@ -238,6 +240,9 @@ class GD_CORE_API BaseEvent {
*/
virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element){};
virtual bool AcceptVisitor(gd::EventVisitor& eventVisitor);
virtual void AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const;
///@}
/** \name Common properties

View File

@@ -0,0 +1,71 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <iostream>
#include <memory>
#include <vector>
#include "GDCore/String.h"
namespace gd {
class BaseEvent;
class LinkEvent;
} // namespace gd
namespace gd {
/**
* \brief Visitor of any kind of event.
*
* \ingroup Events
*/
class GD_CORE_API EventVisitor {
public:
virtual ~EventVisitor(){};
/**
* Called to do some work on an event.
*
* \return true if the event must be deleted from the events list, false
* otherwise.
*/
virtual bool VisitEvent(gd::BaseEvent& linkEvent) = 0;
/**
* Called to do some work on a link event.
*
* Note that VisitEvent is also called with this event.
*
* \return true if the event must be deleted from the events list, false
* otherwise.
*/
virtual bool VisitLinkEvent(gd::LinkEvent& linkEvent) = 0;
};
/**
* \brief Visitor of any kind of event.
*
* \ingroup Events
*/
class GD_CORE_API ReadOnlyEventVisitor {
public:
virtual ~ReadOnlyEventVisitor(){};
/**
* Called to do some work on an event.
*/
virtual void VisitEvent(const gd::BaseEvent& linkEvent) = 0;
/**
* Called to do some work on a link event.
*
* Note that VisitEvent is also called with this event.
*/
virtual void VisitLinkEvent(const gd::LinkEvent& linkEvent) = 0;
};
}

View File

@@ -34,6 +34,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("expression", "The number to be returned")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
@@ -48,6 +49,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("string", "The text to be returned")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
@@ -61,6 +63,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("trueorfalse", "Should the condition be true or false?")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
@@ -75,6 +78,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png",
"res/function32.png")
.AddParameter("functionParameterName", "Parameter name")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
@@ -84,7 +88,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Get function parameter (also called \"argument\") value."),
"",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name");
.AddParameter("functionParameterName", "Parameter name")
.SetRelevantForFunctionEventsOnly();
extension
.AddStrExpression(
@@ -93,7 +98,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Get function parameter (also called \"argument\") text."),
"",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name");
.AddParameter("functionParameterName", "Parameter name")
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition(
@@ -106,7 +112,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
"number", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition(
@@ -119,7 +126,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions());
"string", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
}
} // namespace gd

View File

@@ -15,11 +15,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
extension
.SetExtensionInformation(
"BuiltinAsync",
_("Async functions"),
_("Asynchronous functions"),
_("Functions that defer the execution of the events after it."),
"Arthur Pacaud (arthuro555)",
"Open source (MIT License)")
.SetCategory("Advanced");
extension.AddInstructionOrExpressionGroupMetadata(_("Asynchronous functions"))
.SetIcon("res/function32.png");
extension.AddEvent("Async",
_("Async event"),
@@ -27,6 +29,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
"",
"res/eventaddicon.png",
std::make_shared<gd::AsyncEvent>());
extension
.AddAction(
"ResolveAsyncEventsFunction",
_("End asynchronous function"),
_("Mark an asynchronous function as finished. This will allow the "
"actions and subevents following it to be run."),
"Mark asynchronous function as ended",
"",
"res/actions/quit24.png",
"res/actions/quit.png")
.AddCodeOnlyParameter("eventsFunctionContext", "")
.SetRelevantForAsynchronousFunctionEventsOnly();
}
} // namespace gd

View File

@@ -27,6 +27,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.SetIcon("res/actions/create24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Movement using forces"))
.SetIcon("res/actions/force24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Variables"))
.SetIcon("res/conditions/var24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Position"))
.SetIcon("res/actions/position24_black.png");
gd::ObjectMetadata& obj = extension.AddObject<gd::ObjectConfiguration>(
"", _("Base object"), _("Base object"), "res/objeticon24.png");
@@ -406,8 +410,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddAction("ModVarObjet",
_("Value of an object variable"),
_("Change the value of an object variable."),
_("Change number variable"),
_("Modify the number value of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
"res/actions/var24.png",
@@ -419,8 +423,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
ParameterOptions::MakeNewOptions());
obj.AddAction("ModVarObjetTxt",
_("Text of an object variable"),
_("Change the text of an object variable."),
_("Change text variable"),
_("Modify the text of an object variable."),
_("the text of variable _PARAM1_"),
_("Variables"),
"res/actions/var24.png",
@@ -432,8 +436,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
ParameterOptions::MakeNewOptions());
obj.AddAction("SetObjectVariableAsBoolean",
_("Boolean value of an object variable"),
_("Change the boolean value of an object variable."),
_("Change boolean variable"),
_("Modify the boolean value of an object variable."),
_("Set the boolean value of variable _PARAM1_ of "
"_PARAM0_ to _PARAM2_"),
_("Variables"),
@@ -446,7 +450,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddAction(
"ToggleObjectVariableAsBoolean",
_("Toggle the boolean value of an object variable"),
_("Toggle boolean variable"),
_("Toggles the boolean value of an object variable.") + "\n" +
_("If it was true, it will become false, and if it was false "
"it will become true."),
@@ -461,37 +465,39 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddCondition("ObjectVariableChildExists",
_("Child existence"),
_("Check if the specified child of the variable exists."),
_("Check if the specified child of the object "
"structure variable exists."),
_("Child _PARAM2_ of variable _PARAM1_ of _PARAM0_ exists"),
_("Variables/Collections/Structures"),
_("Variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Name of the child"))
.MarkAsAdvanced();
obj.AddAction("ObjectVariableRemoveChild",
_("Remove a child"),
_("Remove a child from an object variable."),
_("Remove a child from an object structure variable."),
_("Remove child _PARAM2_ from variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.MarkAsAdvanced();
obj.AddAction("ObjectVariableClearChildren",
_("Clear variable"),
_("Remove all the children from the object variable."),
_("Clear children"),
_("Remove all the children from the object array or structure "
"variable."),
_("Clear children from variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Array or structure variable"))
.MarkAsAdvanced();
obj.AddAction("Cache",
@@ -619,8 +625,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddCondition("VarObjet",
_("Value of an object variable"),
_("Compare the value of an object variable."),
_("Number variable"),
_("Compare the number value of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
"res/conditions/var24.png",
@@ -632,7 +638,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"number", ParameterOptions::MakeNewOptions());
obj.AddCondition("VarObjetTxt",
_("Text of an object variable"),
_("Text variable"),
_("Compare the text of an object variable."),
_("the text of variable _PARAM1_"),
_("Variables"),
@@ -645,7 +651,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"string", ParameterOptions::MakeNewOptions());
obj.AddCondition("ObjectVariableAsBoolean",
_("Boolean value of an object variable"),
_("Boolean variable"),
_("Compare the boolean value of an object variable."),
_("The boolean value of variable _PARAM1_ of object "
"_PARAM0_ is _PARAM2_"),
@@ -659,7 +665,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddCondition("VarObjetDef",
"Variable defined",
"Check if the variable is defined.",
"Check if the object variable is defined.",
"Variable _PARAM1 of _PARAM0_ is defined",
_("Variables"),
"res/conditions/var24.png",
@@ -667,78 +673,131 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("string", _("Variable"))
.SetHidden();
.SetHidden(); // Deprecated.
obj.AddAction(
"ObjectVariablePush",
_("Append variable to an object array"),
_("Appends a variable to the end of an object array variable."),
_("Append variable _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
_("Add existing variable"),
_("Adds an existing variable to the end of an object array variable."),
_("Add variable _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("scenevar", _("Scene variable with the content to append"))
.SetParameterLongDescription(
_("The content of the variable will *be copied* and appended at the "
"end of the array."))
.AddParameter("scenevar", _("Scene variable with the content to add"))
.SetParameterLongDescription(_("The content of the object variable will "
"*be copied* and added at the "
"end of the array."))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariablePushString",
_("Append a string to an object array"),
_("Appends a string to the end of an object array variable."),
_("Append string _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
_("Add text variable"),
_("Adds a text (string) to the end of an object array variable."),
_("Add text _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("string", _("String to append"))
.AddParameter("string", _("Text to add"))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariablePushNumber",
_("Append a number to an object array"),
_("Appends a number to the end of an object array variable."),
_("Append number _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
"res/actions/var24.png",
"res/actions/var.png")
obj.AddAction("ObjectVariablePushNumber",
_("Add number variable"),
_("Adds a number to the end of an object array variable."),
_("Add number _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Number to append"))
.AddParameter("expression", _("Number to add"))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariablePushBool",
_("Append a boolean to an object array"),
_("Appends a boolean to the end of an object array variable."),
_("Append boolean _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
_("Add boolean variable"),
_("Adds a boolean to the end of an object array variable."),
_("Add boolean _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to append"))
.AddParameter("trueorfalse", _("Boolean to add"))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariableRemoveAt",
_("Remove variable from an object array (by index)"),
_("Remove variable by index"),
_("Removes a variable at the specified index of an object array "
"variable."),
_("Remove variable at index _PARAM2_ from array variable _PARAM1_ of "
"_PARAM0_"),
_("Variables/Collections/Arrays"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.MarkAsAdvanced();
obj.AddCondition(
"ObjectVariableChildCount",
_("Number of children"),
_("Compare the number of children in an object array variable."),
_("The number of children in the array variable _PARAM1_"),
_("Variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddStrExpression(
"ArrayVariableFirstString",
_("First text child"),
_("Get the value of the first element of an object array variable, if "
"it is a text (string) variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableFirstNumber",
_("First number child"),
_("Get the value of the first element of an object array variable, if "
"it is a number variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddStrExpression(
"ArrayVariableLastString",
_("Last text child"),
_("Get the value of the last element of an object array variable, if "
"it is a text (string) variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableLastNumber",
_("Last number child"),
_("Get the value of the last element of an object array variable, if "
"it is a number variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddCondition("BehaviorActivated",
_("Behavior activated"),
_("Check if the behavior is activated for the object."),
@@ -1115,23 +1174,24 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("expression", _("Target Y position"));
obj.AddExpression("Variable",
_("Value of an object variable"),
_("Value of an object variable"),
_("Number variable"),
_("Number value of an object variable"),
_("Variables"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"));
obj.AddExpression("VariableChildCount",
_("Number of children of an object variable"),
_("Number of children of an object variable"),
_("Variables"),
"res/actions/var.png")
obj.AddExpression(
"VariableChildCount",
_("Number of children"),
_("Number of children in an object array or structure variable"),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"));
.AddParameter("objectvar", _("Array or structure variable"));
obj.AddStrExpression("VariableString",
_("Text of an object variable"),
_("Text variable"),
_("Text of an object variable"),
_("Variables"),
"res/actions/var.png")
@@ -1265,6 +1325,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsSimple()
.SetRequiresBaseObjectCapability("effect");
obj.AddAction("SetIncludedInParentCollisionMask",
_("Include in parent collision mask"),
_("Include or exclude a child from its parent collision mask."),
_("Include _PARAM0_ in parent object collision mask: _PARAM1_"),
_("Collision"),
"res/function32.png",
"res/function32.png")
.AddParameter("object", _("Object"))
.AddParameter("yesorno", "Include in parent collision mask")
.SetRelevantForCustomObjectEventsOnly();
extension
.AddAction("Create",
_("Create an object"),
@@ -1278,7 +1349,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectListOrEmptyIfJustDeclared", _("Object to create"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.MarkAsSimple();
@@ -1293,7 +1364,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListOrEmptyIfJustDeclared", _("Group of potential objects"))
.AddParameter("objectListOrEmptyIfJustDeclared",
_("Group of potential objects"))
.SetParameterLongDescription(
_("Group containing objects that can be created by the action."))
.AddParameter("string", _("Name of the object to create"))
@@ -1302,7 +1374,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"with this name are found in the group, no object will be created."))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.MarkAsAdvanced();
@@ -1332,7 +1404,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Objects"),
"res/actions/ajouthasard24.png",
"res/actions/ajouthasard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectList", _("Object"))
.MarkAsSimple();
@@ -1391,7 +1463,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Objects"),
"res/conditions/add24.png",
"res/conditions/add.png")
.AddCodeOnlyParameter("currentScene", "")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectList", _("Object"))
.MarkAsAdvanced();
@@ -1406,7 +1478,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Objects"),
"res/conditions/ajouthasard24.png",
"res/conditions/ajouthasard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectList", _("Object"))
.MarkAsSimple();

View File

@@ -40,7 +40,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
@@ -72,7 +72,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
@@ -103,7 +103,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
@@ -119,7 +119,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
@@ -136,7 +136,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
@@ -153,7 +153,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
@@ -170,7 +170,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
@@ -187,7 +187,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
@@ -204,7 +204,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
@@ -322,7 +322,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression",
_("Value (1:Initial zoom, 2:Zoom x2, 0.5:Unzoom x2...)"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0");
@@ -354,46 +354,41 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
true)
.SetDefaultValue("yes")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
extension
.AddAction(
"ClampCamera",
_("Enforce camera boundaries"),
_("Enforce camera boundaries by moving the camera back inside specified boundaries."),
_("Enforce camera boundaries (left: _PARAM1_, top: _PARAM2_ "
"right: _PARAM3_, bottom: _PARAM4_, layer: _PARAM5_)"),
"",
"res/actions/camera24.png",
"res/actions/camera.png")
.AddAction("ClampCamera",
_("Enforce camera boundaries"),
_("Enforce camera boundaries by moving the camera back inside "
"specified boundaries."),
_("Enforce camera boundaries (left: _PARAM1_, top: _PARAM2_ "
"right: _PARAM3_, bottom: _PARAM4_, layer: _PARAM5_)"),
"",
"res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression",
_("Left bound X Position"))
.AddParameter("expression",
_("Top bound Y Position"))
.AddParameter("expression",
_("Right bound X Position"))
.AddParameter("expression",
_("Bottom bound Y Position"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("expression", _("Left bound X Position"))
.AddParameter("expression", _("Top bound Y Position"))
.AddParameter("expression", _("Right bound X Position"))
.AddParameter("expression", _("Bottom bound Y Position"))
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
extension
.AddAction(
"CentreCamera",
_("Center the camera on an object"),
_("Center the camera on the specified object."),
_("Center camera on _PARAM1_ (layer: _PARAM3_)"),
"",
"res/actions/camera24.png",
"res/actions/camera.png")
.AddAction("CentreCamera",
_("Center the camera on an object"),
_("Center the camera on the specified object."),
_("Center camera on _PARAM1_ (layer: _PARAM3_)"),
"",
"res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("objectPtr", _("Object"))
.AddParameter("yesorno",
@@ -401,7 +396,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
true)
.SetDefaultValue("yes")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
@@ -458,7 +453,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
@@ -477,7 +472,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
@@ -496,7 +491,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
@@ -512,7 +507,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.MarkAsAdvanced();
@@ -526,7 +521,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("yesorno", _("Enable"), "", true)
@@ -542,7 +537,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/time24.png",
"res/conditions/time.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters(
"number",
@@ -560,7 +555,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/time24.png",
"res/actions/time.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression",
_("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)"));
@@ -575,7 +570,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/layer24.png",
"res/conditions/layer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
@@ -592,7 +587,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/layer24.png",
"res/actions/layer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("New default Z order"));
@@ -607,7 +602,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/color24.png",
"res/actions/color.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"Lighting\"")
.AddParameter("color", _("Color"))
.MarkAsAdvanced();

View File

@@ -163,7 +163,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0");
@@ -185,7 +185,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0");
@@ -197,17 +197,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
extension.AddDuplicatedExpression("SourisY", "CursorY").SetHidden();
extension
.AddExpressionAndCondition(
"number",
"MouseOnlyCursorX",
_("Mouse cursor X position"),
_("the X position of the mouse cursor"),
_("the mouse cursor X position"),
"",
"res/conditions/mouse24.png")
.AddExpressionAndCondition("number",
"MouseOnlyCursorX",
_("Mouse cursor X position"),
_("the X position of the mouse cursor"),
_("the mouse cursor X position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
@@ -215,17 +214,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.SetHidden();
extension
.AddExpressionAndCondition(
"number",
"MouseOnlyCursorY",
_("Mouse cursor Y position"),
_("the Y position of the mouse cursor"),
_("the mouse cursor Y position"),
"",
"res/conditions/mouse24.png")
.AddExpressionAndCondition("number",
"MouseOnlyCursorY",
_("Mouse cursor Y position"),
_("the Y position of the mouse cursor"),
_("the mouse cursor Y position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
@@ -319,7 +317,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0");
@@ -335,7 +333,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0");
@@ -376,7 +374,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCondition(
"HasAnyTouchStarted",
_("A new touch has started"),
_("Check if a touch has just started on this frame. The touch identifiers can be "
_("Check if a touch has just started on this frame. The touch "
"identifiers can be "
"accessed using StartedTouchId() and StartedTouchCount()."),
_("A new touch has started"),
_("Multitouch"),
@@ -386,24 +385,24 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.SetHidden();
extension
.AddExpression(
"StartedTouchCount",
_("Started touch count"),
_("The number of touches that have just started on this frame. The touch identifiers can be "
"accessed using StartedTouchId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddExpression("StartedTouchCount",
_("Started touch count"),
_("The number of touches that have just started on this "
"frame. The touch identifiers can be "
"accessed using StartedTouchId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression(
"StartedTouchId",
_("Started touch identifier"),
_("The identifier of the touch that has just started on this frame. The touch number of touches can be "
"accessed using StartedTouchCount()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddExpression("StartedTouchId",
_("Started touch identifier"),
_("The identifier of the touch that has just started on "
"this frame. The number of touches can be "
"accessed using StartedTouchCount()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index"))
.SetHidden();
@@ -414,7 +413,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("A new touch has started"),
_("Check if a touch has just started or the mouse left button has "
"been pressed on this frame. The touch identifiers can be "
"accessed using StartedTouchOrMouseId() and StartedTouchOrMouseCount()."),
"accessed using StartedTouchOrMouseId() and "
"StartedTouchOrMouseCount()."),
_("A new touch has started"),
_("Multitouch"),
"res/conditions/touch24.png",
@@ -427,7 +427,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Started touch count"),
_("The number of touches (including the mouse) that have just "
"started on this frame. The touch identifiers can be "
"accessed using StartedTouchOrMouseCount()."),
"accessed using StartedTouchOrMouseId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
@@ -437,7 +437,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"StartedTouchOrMouseId",
_("Started touch identifier"),
_("The identifier of the touch or mouse that has just started on "
"this frame. The touch number of touches can be "
"this frame. The number of touches can be "
"accessed using StartedTouchOrMouseCount()."),
_("Multitouch"),
"res/conditions/touch.png")
@@ -445,14 +445,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddParameter("expression", _("Touch index"));
extension
.AddCondition(
"HasTouchEnded",
_("A touch has ended"),
_("Check if a touch has ended or a mouse left button has been released."),
_("The touch with identifier _PARAM1_ has ended"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCondition("HasTouchEnded",
_("A touch has ended"),
_("Check if a touch has ended or a mouse left button has "
"been released."),
_("The touch with identifier _PARAM1_ has ended"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"));

View File

@@ -27,9 +27,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition("VarScene",
_("Value of a scene variable"),
_("Compare the value of a scene variable."),
_("the scene variable _PARAM0_"),
_("Number variable"),
_("Compare the number value of a scene variable."),
_("The number of scene variable _PARAM0_"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
@@ -39,9 +39,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition("VarSceneTxt",
_("Text of a scene variable"),
_("Compare the text of a scene variable."),
_("the text of scene variable _PARAM0_"),
_("Text variable"),
_("Compare the text (string) of a scene variable."),
_("The text of scene variable _PARAM0_"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
@@ -52,7 +52,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition(
"SceneVariableAsBoolean",
_("Boolean value of a scene variable"),
_("Boolean variable"),
_("Compare the boolean value of a scene variable."),
_("The boolean value of scene variable _PARAM0_ is _PARAM1_"),
_("Scene variables"),
@@ -63,14 +63,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetDefaultValue("true");
extension
.AddCondition(
"VariableChildExists",
_("Child existence"),
_("Check if the specified child of the scene variable exists."),
_("Child _PARAM1_ of scene variable _PARAM0_ exists"),
_("Scene variables/Collections/Structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddCondition("VariableChildExists",
_("Child existence"),
_("Check if the specified child of the scene structure "
"variable exists."),
_("Child _PARAM1_ of scene variable _PARAM0_ exists"),
_("Scene variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("string", _("Name of the child"))
.MarkAsAdvanced();
@@ -78,10 +78,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition("GlobalVariableChildExists",
_("Child existence"),
_("Check if the specified child of the global "
_("Check if the specified child of the global structure "
"variable exists."),
_("Child _PARAM1_ of global variable _PARAM0_ exists"),
_("Global variables/Collections/Structures"),
_("Global variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
@@ -90,7 +90,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition("VarSceneDef",
"Test if a scene variable is defined",
"Variable defined",
"Test if the scene variable exists.",
"Scene variable _PARAM0_ is defined",
_("Scene variables"),
@@ -98,12 +98,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Variable"))
.SetHidden();
.SetHidden(); // Deprecated.
extension
.AddCondition("VarGlobal",
_("Value of a global variable"),
_("Compare the value of a global variable."),
_("Number variable"),
_("Compare the number value of a global variable."),
_("the global variable _PARAM0_"),
_("Global variables"),
"res/conditions/var24.png",
@@ -115,8 +115,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition("VarGlobalTxt",
_("Text of a global variable"),
_("Compare the text of a global variable."),
_("Text variable"),
_("Compare the text (string) of a global variable."),
_("the text of the global variable _PARAM0_"),
_("Global variables"),
"res/conditions/var24.png",
@@ -129,7 +129,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition(
"GlobalVariableAsBoolean",
_("Boolean value of a global variable"),
_("Boolean variable"),
_("Compare the boolean value of a global variable."),
_("The boolean value of global variable _PARAM0_ is _PARAM1_"),
_("Global variables"),
@@ -141,8 +141,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddCondition("VarGlobalDef",
"Test if a global variable is defined",
"Test if a global variable exists",
"Variable defined",
"Test if a global variable exists.",
"Global variable _PARAM0_ is defined",
_("Global variables"),
"res/conditions/var24.png",
@@ -150,12 +150,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Variable"))
.MarkAsAdvanced()
.SetHidden();
.SetHidden(); // Deprecated.
extension
.AddAction("ModVarScene",
_("Value of a scene variable"),
_("Change the value of a scene variable."),
_("Change number variable"),
_("Modify the number value of a scene variable."),
_("the scene variable _PARAM0_"),
_("Scene variables"),
"res/actions/var24.png",
@@ -166,8 +166,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction("ModVarSceneTxt",
_("String of a scene variable"),
_("Modify the text of a scene variable."),
_("Change text variable"),
_("Modify the text (string) of a scene variable."),
_("the text of scene variable _PARAM0_"),
_("Scene variables"),
"res/actions/var24.png",
@@ -179,7 +179,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction(
"SetSceneVariableAsBoolean",
_("Boolean value of a scene variable"),
_("Change boolean variable"),
_("Modify the boolean value of a scene variable."),
_("Set the boolean value of scene variable _PARAM0_ to _PARAM1_"),
_("Scene variables"),
@@ -190,7 +190,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction("ToggleSceneVariableAsBoolean",
_("Toggle boolean value of a scene variable"),
_("Toggle boolean variable"),
_("Toggle the boolean value of a scene variable.") + "\n" +
_("If it was true, it will become false, and if it was "
"false it will become true."),
@@ -202,8 +202,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction("ModVarGlobal",
_("Value of a global variable"),
_("Change the value of a global variable"),
_("Change number variable"),
_("Modify the number value of a global variable."),
_("the global variable _PARAM0_"),
_("Global variables"),
"res/actions/var24.png",
@@ -215,8 +215,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction("ModVarGlobalTxt",
_("String of a global variable"),
_("Modify the text of a global variable."),
_("Change text variable"),
_("Modify the text (string) of a global variable."),
_("the text of global variable _PARAM0_"),
_("Global variables"),
"res/actions/var24.png",
@@ -229,7 +229,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction(
"SetGlobalVariableAsBoolean",
_("Boolean value of a global variable"),
_("Change boolean variable"),
_("Modify the boolean value of a global variable."),
_("Set the boolean value of global variable _PARAM0_ to _PARAM1_"),
_("Global variables"),
@@ -240,7 +240,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddAction("ToggleGlobalVariableAsBoolean",
_("Toggle boolean value of a global variable"),
_("Toggle boolean variable"),
_("Toggle the boolean value of a global variable.") + "\n" +
_("If it was true, it will become false, and if it was "
"false it will become true."),
@@ -251,202 +251,324 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.AddParameter("globalvar", _("Variable"));
extension
.AddAction("VariableRemoveChild",
_("Remove a child"),
_("Remove a child from a scene variable."),
_("Remove child _PARAM1_ from scene variable _PARAM0_"),
_("Scene variables/Collections/Structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddAction(
"VariableRemoveChild",
_("Remove a child"),
_("Remove a child from a scene structure variable."),
_("Remove child _PARAM1_ from scene structure variable _PARAM0_"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.MarkAsAdvanced();
extension
.AddAction("GlobalVariableRemoveChild",
_("Remove a child"),
_("Remove a child from a global variable."),
_("Remove child _PARAM1_ from global variable _PARAM0_"),
_("Global variables/Collections/Structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddAction(
"GlobalVariableRemoveChild",
_("Remove a child"),
_("Remove a child from a global structure variable."),
_("Remove child _PARAM1_ from global structure variable _PARAM0_"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.MarkAsAdvanced();
extension
.AddAction("VariableClearChildren",
_("Clear scene variable"),
_("Remove all the children from the scene variable."),
_("Clear children"),
_("Remove all the children from the scene structure or array "
"variable."),
_("Clear children from scene variable _PARAM0_"),
_("Scene variables/Collections"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("scenevar", _("Structure or array variable"))
.MarkAsAdvanced();
extension
.AddAction("GlobalVariableClearChildren",
_("Clear global variable"),
_("Remove all the children from the global variable."),
_("Clear children"),
_("Remove all the children from the global structure or array "
"variable."),
_("Clear children from global variable _PARAM0_"),
_("Global variables/Collections"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("globalvar", _("Structure or array variable"))
.MarkAsAdvanced();
extension
.AddAction("SceneVariablePush",
_("Append variable to a scene array"),
_("Appends a variable at the end of a scene array variable."),
_("Append variable _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Collections/Arrays"),
_("Add existing variable"),
_("Adds an existing variable at the end of a scene array "
"variable."),
_("Add variable _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("scenevar", _("Scene variable with the content to append"))
.SetParameterLongDescription(_("The content of the variable will *be copied* and appended at the end of the array."))
.AddParameter("scenevar", _("Scene variable with the content to add"))
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.MarkAsAdvanced();
extension
.AddAction("SceneVariablePushString",
_("Append a string to a scene array"),
_("Appends a string at the end of a scene array variable."),
_("Append string _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Collections/Arrays"),
"res/actions/var24.png",
"res/actions/var.png")
.AddAction(
"SceneVariablePushString",
_("Add text variable"),
_("Adds a text (string) at the end of a scene array variable."),
_("Add text _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("string", _("String to append"))
.AddParameter("string", _("Text to add"))
.MarkAsAdvanced();
extension
.AddAction("SceneVariablePushNumber",
_("Append a number to a scene array"),
_("Appends a number at the end of a scene array variable."),
_("Append number _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Collections/Arrays"),
_("Add number variable"),
_("Adds a number at the end of a scene array variable."),
_("Add number _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Number to append"))
.AddParameter("expression", _("Number to add"))
.MarkAsAdvanced();
extension
.AddAction("SceneVariablePushBool",
_("Append a boolean to a scene array"),
_("Appends a boolean at the end of a scene array variable."),
_("Append boolean _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Collections/Arrays"),
_("Add boolean variable"),
_("Adds a boolean at the end of a scene array variable."),
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to append"))
.AddParameter("trueorfalse", _("Boolean to add"))
.MarkAsAdvanced();
extension
.AddAction(
"SceneVariableRemoveAt",
_("Remove variable from a scene array (by index)"),
_("Removes a variable at the specified index of a scene array variable."),
_("Remove variable at index _PARAM1_ from scene array variable _PARAM0_"),
_("Scene variables/Collections/Arrays"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddAction("SceneVariableRemoveAt",
_("Remove variable by index"),
_("Removes a variable at the specified index of a scene array "
"variable."),
_("Remove variable at index _PARAM1_ from scene array "
"variable _PARAM0_"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.MarkAsAdvanced();
extension
.AddAction("GlobalVariablePush",
_("Append variable to a global array"),
_("Appends a variable at the end of a global array variable."),
_("Append variable _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Collections/Arrays"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("scenevar", _("Scene variable with the content to append"))
.SetParameterLongDescription(_("The content of the variable will *be copied* and appended at the end of the array."))
.AddCondition(
"SceneVariableChildCount",
_("Number of children"),
_("Compare the number of children in a scene array variable."),
_("The number of children in the array variable _PARAM0_"),
_("Scene variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddStrExpression(
"SceneVariableFirstString",
_("First text child"),
_("Get the value of the first element of a scene array variable, if "
"it is a text (string)."),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"));
extension
.AddExpression(
"SceneVariableFirstNumber",
_("First number child"),
_("Get the value of the first element of a scene array variable, if "
"it is a number."),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"));
extension
.AddStrExpression(
"SceneVariableLastString",
_("Last text child"),
_("Get the value of the last element of a scene array variable, if "
"it is a text (string)."),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"));
extension
.AddExpression(
"SceneVariableLastNumber",
_("Last number child"),
_("Get the value of the last element of a scene array variable, if "
"it is a number."),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"));
extension
.AddAction(
"GlobalVariableRemoveAt",
_("Remove variable from a global array (by index)"),
_("Removes a variable at the specified index of a global array variable."),
_("Remove variable at index _PARAM1_ from global array variable _PARAM0_"),
_("Global variables/Collections/Arrays"),
"GlobalVariablePush",
_("Add existing variable"),
_("Adds an existing variable at the end of a global array variable."),
_("Add variable _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("globalvar", _("Array variable"))
.AddParameter("scenevar", _("Scene variable with the content to add"))
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.MarkAsAdvanced();
extension
.AddAction("GlobalVariableRemoveAt",
_("Remove variable by index"),
_("Removes a variable at the specified index of a global "
"array variable."),
_("Remove variable at index _PARAM1_ from global array "
"variable _PARAM0_"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.MarkAsAdvanced();
extension
.AddAction("GlobalVariablePushString",
_("Append a string to a global array"),
_("Appends a string at the end of a global array variable."),
_("Append string _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Collections/Arrays"),
"res/actions/var24.png",
"res/actions/var.png")
.AddAction(
"GlobalVariablePushString",
_("Add text variable"),
_("Adds a text (string) at the end of a global array variable."),
_("Add text _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("string", _("String to append"))
.AddParameter("string", _("Text to add"))
.MarkAsAdvanced();
extension
.AddAction("GlobalVariablePushNumber",
_("Append a number to a global array"),
_("Appends a number at the end of a global array variable."),
_("Append number _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Collections/Arrays"),
_("Add number variable"),
_("Adds a number at the end of a global array variable."),
_("Add number _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Number to append"))
.AddParameter("expression", _("Number to add"))
.MarkAsAdvanced();
extension
.AddAction("GlobalVariablePushBool",
_("Append a boolean to a global array"),
_("Appends a boolean at the end of a global array variable."),
_("Append boolean _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Collections/Arrays"),
_("Add boolean variable"),
_("Adds a boolean at the end of a global array variable."),
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to append"))
.AddParameter("trueorfalse", _("Boolean to add"))
.MarkAsAdvanced();
extension
.AddExpression("GlobalVariableChildCount",
_("Number of children of a global variable"),
_("Number of children of a global variable"),
_("Global variables"),
.AddCondition(
"GlobalVariableChildCount",
_("Number of children"),
_("Compare the number of children in a global array variable."),
_("The number of children of the array variable _PARAM0_"),
_("Global variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddStrExpression("GlobalVariableFirstString",
_("First text child"),
_("Value of the first element of a global array "
"variable, if it is a text (string) variable."),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"));
extension
.AddExpression("GlobalVariableFirstNumber",
_("First number child"),
_("Value of the first element of a global array "
"variable, if it is a number variable"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"));
.AddParameter("globalvar", _("Array variable"));
extension
.AddStrExpression(
"GlobalVariableLastString",
_("Last text child"),
_("Value of the last element of a global array variable, if "
"it is a text (string) variable."),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"));
extension
.AddExpression(
"GlobalVariableLastNumber",
_("Last number child"),
_("Value of the last element of a global array variable, if "
"it is a number variable"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"));
extension
.AddExpression("GlobalVariableChildCount",
_("Number of children"),
_("Number of children in a global array or "
"structure variable"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array or structure variable"));
extension
.AddExpression("VariableChildCount",
_("Number of children of a scene variable"),
_("Number of children of a scene variable"),
_("Scene variables"),
_("Number of children"),
_("Number of children in a scene array or "
"structure variable"),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"));
.AddParameter("scenevar", _("Array or structure variable"));
extension
.AddExpression("Variable",
_("Value of a scene variable"),
_("Value of a scene variable"),
_("Number variable"),
_("Number value of a scene variable"),
_("Scene variables"),
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"));
extension
.AddStrExpression("VariableString",
_("Text of a scene variable"),
_("Text variable"),
_("Text of a scene variable"),
_("Scene variables"),
"res/actions/var.png")
@@ -454,15 +576,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension
.AddExpression("GlobalVariable",
_("Value of a global variable"),
_("Value of a global variable"),
_("Number variable"),
_("Number value of a global variable"),
_("Global variables"),
"res/actions/var.png")
.AddParameter("globalvar", _("Name of the global variable"));
extension
.AddStrExpression("GlobalVariableString",
_("Text of a global variable"),
_("Text variable"),
_("Text of a global variable"),
_("Global variables"),
"res/actions/var.png")

View File

@@ -23,7 +23,8 @@ ExpressionMetadata::ExpressionMetadata(const gd::String& returnType_,
shown(true),
smallIconFilename(smallicon_),
extensionNamespace(extensionNamespace_),
isPrivate(false) {
isPrivate(false),
relevantContext("Any") {
}
ExpressionMetadata& ExpressionMetadata::SetHidden() {

View File

@@ -137,7 +137,7 @@ class GD_CORE_API ExpressionMetadata {
* to fulfill std::map requirements.
*/
ExpressionMetadata()
: returnType("unknown"), shown(false), isPrivate(false){};
: returnType("unknown"), shown(false), isPrivate(false), relevantContext("Any"){};
virtual ~ExpressionMetadata(){};
@@ -184,6 +184,67 @@ class GD_CORE_API ExpressionMetadata {
return *this;
}
/**
* Check if the instruction can be used in layouts or external events.
*/
bool IsRelevantForLayoutEvents() const {
return relevantContext == "Any" || relevantContext == "Layout";
}
/**
* Check if the instruction can be used in function events.
*/
bool IsRelevantForFunctionEvents() const {
return relevantContext == "Any" || relevantContext == "Function";
}
/**
* Check if the instruction can be used in asynchronous function events.
*/
bool IsRelevantForAsynchronousFunctionEvents() const {
return relevantContext == "Any" || relevantContext == "Function" ||
relevantContext == "AsynchronousFunction";
}
/**
* Check if the instruction can be used in custom object events.
*/
bool IsRelevantForCustomObjectEvents() const {
return relevantContext == "Any" || relevantContext == "Object";
}
/**
* Set that the instruction can be used in layouts or external events.
*/
ExpressionMetadata &SetRelevantForLayoutEventsOnly() {
relevantContext = "Layout";
return *this;
}
/**
* Set that the instruction can be used in function events.
*/
ExpressionMetadata &SetRelevantForFunctionEventsOnly() {
relevantContext = "Function";
return *this;
}
/**
* Set that the instruction can be used in asynchronous function events.
*/
ExpressionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
relevantContext = "AsynchronousFunction";
return *this;
}
/**
* Set that the instruction can be used in custom object events.
*/
ExpressionMetadata &SetRelevantForCustomObjectEventsOnly() {
relevantContext = "Object";
return *this;
}
/**
* \see gd::InstructionMetadata::AddParameter
*/
@@ -326,6 +387,7 @@ class GD_CORE_API ExpressionMetadata {
gd::String extensionNamespace;
bool isPrivate;
gd::String requiredBaseObjectCapability;
gd::String relevantContext;
};
} // namespace gd

View File

@@ -47,7 +47,8 @@ InstructionMetadata::InstructionMetadata(const gd::String& extensionNamespace_,
usageComplexity(5),
isPrivate(false),
isObjectInstruction(false),
isBehaviorInstruction(false) {}
isBehaviorInstruction(false),
relevantContext("Any") {}
InstructionMetadata& InstructionMetadata::AddParameter(
const gd::String& type,

View File

@@ -101,6 +101,67 @@ class GD_CORE_API InstructionMetadata {
return *this;
}
/**
* Check if the instruction can be used in layouts or external events.
*/
bool IsRelevantForLayoutEvents() const {
return relevantContext == "Any" || relevantContext == "Layout";
}
/**
* Check if the instruction can be used in function events.
*/
bool IsRelevantForFunctionEvents() const {
return relevantContext == "Any" || relevantContext == "Function";
}
/**
* Check if the instruction can be used in asynchronous function events.
*/
bool IsRelevantForAsynchronousFunctionEvents() const {
return relevantContext == "Any" || relevantContext == "Function" ||
relevantContext == "AsynchronousFunction";
}
/**
* Check if the instruction can be used in custom object events.
*/
bool IsRelevantForCustomObjectEvents() const {
return relevantContext == "Any" || relevantContext == "Object";
}
/**
* Set that the instruction can be used in layouts or external events.
*/
InstructionMetadata &SetRelevantForLayoutEventsOnly() {
relevantContext = "Layout";
return *this;
}
/**
* Set that the instruction can be used in function events.
*/
InstructionMetadata &SetRelevantForFunctionEventsOnly() {
relevantContext = "Function";
return *this;
}
/**
* Set that the instruction can be used in asynchronous function events.
*/
InstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
relevantContext = "AsynchronousFunction";
return *this;
}
/**
* Set that the instruction can be used in custom object events.
*/
InstructionMetadata &SetRelevantForCustomObjectEventsOnly() {
relevantContext = "Object";
return *this;
}
/**
* Check if the instruction is asynchronous - it will be running in the
* background, executing the instructions following it before the frame after
@@ -539,6 +600,7 @@ class GD_CORE_API InstructionMetadata {
bool isObjectInstruction;
bool isBehaviorInstruction;
gd::String requiredBaseObjectCapability;
gd::String relevantContext;
};
} // namespace gd

View File

@@ -46,7 +46,7 @@ class GD_CORE_API ObjectMetadata {
std::shared_ptr<gd::ObjectConfiguration> blueprintObject_);
/**
* \brief Construct an object metadata, without "blueprint" object
*
*
* \note This is used by events based objects.
*/
ObjectMetadata(const gd::String& extensionNamespace_,
@@ -295,6 +295,22 @@ class GD_CORE_API ObjectMetadata {
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() { return strExpressionsInfos; };
/**
* \brief Set the object to be hidden in the IDE.
*
* Used mainly when an object is deprecated.
*/
ObjectMetadata &SetHidden() {
hidden = true;
return *this;
}
/**
* \brief Return true if the instruction must be hidden in the IDE.
*/
bool IsHidden() const { return hidden; }
std::map<gd::String, gd::InstructionMetadata> conditionsInfos;
std::map<gd::String, gd::InstructionMetadata> actionsInfos;
std::map<gd::String, gd::ExpressionMetadata> expressionsInfos;
@@ -314,6 +330,7 @@ class GD_CORE_API ObjectMetadata {
gd::String iconFilename;
gd::String categoryFullName;
std::set<gd::String> unsupportedBaseObjectCapabilities;
bool hidden = false;
std::shared_ptr<gd::ObjectConfiguration>
blueprintObject; ///< The "blueprint" object to be copied when a new

View File

@@ -11,6 +11,8 @@
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "InstructionMetadata.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
namespace gd {
void ParameterMetadataTools::ParametersToObjectsContainer(
@@ -101,6 +103,56 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
}
}
void ParameterMetadataTools::IterateOverParametersWithIndex(
const gd::Platform &platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer, FunctionCallNode &node,
std::function<void(const gd::ParameterMetadata &parameterMetadata,
std::unique_ptr<gd::ExpressionNode> &parameterNode,
size_t parameterIndex, const gd::String &lastObjectName)>
fn) {
gd::String lastObjectName = node.objectName;
const bool isObjectFunction = !node.objectName.empty();
const gd::ExpressionMetadata &metadata =
isObjectFunction ? MetadataProvider::GetObjectAnyExpressionMetadata(
platform,
GetTypeOfObject(globalObjectsContainer,
objectsContainer, node.objectName),
node.functionName)
: MetadataProvider::GetAnyExpressionMetadata(
platform, node.functionName);
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
return;
}
size_t parameterIndex = 0;
for (size_t metadataIndex = (isObjectFunction ? 1 : 0);
metadataIndex < metadata.parameters.size() &&
parameterIndex < node.parameters.size();
++metadataIndex) {
auto &parameterMetadata = metadata.parameters[metadataIndex];
if (parameterMetadata.IsCodeOnly()) {
continue;
}
auto &parameterNode = node.parameters[parameterIndex];
++parameterIndex;
fn(parameterMetadata, parameterNode, parameterIndex, lastObjectName);
// Memorize the last object name. By convention, parameters that require
// an object (mainly, "objectvar" and "behavior") should be placed after
// the object in the list of parameters (if possible, just after).
// Search "lastObjectName" in the codebase for other place where this
// convention is enforced.
if (gd::ParameterMetadata::IsObject(parameterMetadata.GetType()))
// Object can't be expressions so it should always be the object name.
lastObjectName =
gd::ExpressionParser2NodePrinter::PrintNode(*parameterNode);
}
}
size_t ParameterMetadataTools::GetObjectParameterIndexFor(
const std::vector<gd::ParameterMetadata>& parametersMetadata,
size_t parameterIndex) {

View File

@@ -7,12 +7,16 @@
#ifndef ParameterMetadataTools_H
#define ParameterMetadataTools_H
#include <vector>
#include <memory>
#include "GDCore/String.h"
namespace gd {
class Platform;
class Project;
class ObjectsContainer;
class ParameterMetadata;
class Expression;
struct FunctionCallNode;
struct ExpressionNode;
} // namespace gd
namespace gd {
@@ -48,6 +52,21 @@ class GD_CORE_API ParameterMetadataTools {
size_t parameterIndex,
const gd::String& lastObjectName)> fn);
/**
* Iterate over the parameters of a FunctionCallNode.
* Callback function is called with the parameter metadata, its value
* and if applicable the name of the object it's linked to.
*/
static void IterateOverParametersWithIndex(
const gd::Platform &platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer, FunctionCallNode &node,
std::function<void(const gd::ParameterMetadata &parameterMetadata,
std::unique_ptr<gd::ExpressionNode> &parameterNode,
size_t parameterIndex,
const gd::String &lastObjectName)>
fn);
/**
* Given a parameter, return, if applicable, the index of the object parameter
* it's linked to.

View File

@@ -163,7 +163,6 @@ class GD_CORE_API ValueTypeMetadata {
} else if (type == "string") {
return parameterType == "string" || parameterType == "layer" ||
parameterType == "color" || parameterType == "file" ||
parameterType == "joyaxis" ||
parameterType == "stringWithSelector" ||
parameterType == "sceneName" ||
parameterType == "layerEffectName" ||

View File

@@ -0,0 +1,49 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "EventBasedBehaviorBrowser.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/IDE/Project/ArbitraryBehaviorSharedDataWorker.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
namespace gd {
void EventBasedBehaviorBrowser::ExposeEvents(
gd::Project &project, gd::ArbitraryEventsWorker &worker) const {
gd::ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
project, eventsBasedBehavior, worker);
}
void EventBasedBehaviorBrowser::ExposeEvents(
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) const {
gd::ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
project, eventsBasedBehavior, worker);
}
void EventBasedBehaviorBrowser::ExposeObjects(
gd::Project &project, gd::ArbitraryObjectsWorker &worker) const {}
void EventBasedBehaviorBrowser::ExposeFunctions(
gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) const {
worker.Launch(eventsBasedBehavior.GetEventsFunctions());
}
void EventBasedBehaviorBrowser::ExposeEventBasedBehaviors(
gd::Project &project,
gd::ArbitraryEventBasedBehaviorsWorker &worker) const {
worker.Launch(eventsBasedBehavior);
}
void EventBasedBehaviorBrowser::ExposeBehaviorSharedDatas(
gd::Project &project, gd::ArbitraryBehaviorSharedDataWorker &worker) const {}
} // namespace gd

View File

@@ -0,0 +1,86 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/IDE/ProjectBrowser.h"
namespace gd {
class Project;
class String;
class EventsFunctionsExtension;
class EventsFunction;
class EventsBasedBehavior;
class EventsBasedObject;
class ArbitraryEventsWorker;
class ArbitraryEventsWorkerWithContext;
class ArbitraryEventsFunctionsWorker;
class ArbitraryObjectsWorker;
class ArbitraryEventBasedBehaviorsWorker;
class ArbitraryBehaviorSharedDataWorker;
} // namespace gd
namespace gd {
/**
* \brief Expose event-based behavior contents to workers.
*/
class GD_CORE_API EventBasedBehaviorBrowser : public ProjectBrowser {
public:
EventBasedBehaviorBrowser(gd::EventsBasedBehavior &eventsBasedBehavior_)
: eventsBasedBehavior(eventsBasedBehavior_) {}
/**
* \brief Call the specified worker on all events of the event-based
* behavior.
*
* This should be the preferred way to traverse all the events of an event-based behavior.
*/
void ExposeEvents(gd::Project &project,
gd::ArbitraryEventsWorker &worker) const override;
/**
* \brief Call the specified worker on all events of the event-based
* behavior.
*
* This should be the preferred way to traverse all the events of an event-based behavior.
*/
void
ExposeEvents(gd::Project &project,
gd::ArbitraryEventsWorkerWithContext &worker) const override;
/**
* \brief Call the specified worker on all functions of the event-based behavior
*
* This should be the preferred way to traverse all the function signatures
* of an event-based behavior.
*/
void ExposeFunctions(gd::Project &project,
gd::ArbitraryEventsFunctionsWorker &worker) const override;
/**
* \brief Do nothing.
*/
void ExposeObjects(gd::Project &project,
gd::ArbitraryObjectsWorker &worker) const override;
/**
* \brief Call the specified worker on the event-based behavior.
*/
void ExposeEventBasedBehaviors(
gd::Project &project,
gd::ArbitraryEventBasedBehaviorsWorker &worker) const override;
/**
* \brief Do nothing.
*/
void ExposeBehaviorSharedDatas(gd::Project &project,
gd::ArbitraryBehaviorSharedDataWorker &worker) const override;
private:
gd::EventsBasedBehavior &eventsBasedBehavior;
};
} // namespace gd

View File

@@ -23,7 +23,7 @@ void ArbitraryEventsWorker::VisitEventList(gd::EventsList& events) {
DoVisitEventList(events);
for (std::size_t i = 0; i < events.size();) {
if (VisitEvent(events[i]))
if (events[i].AcceptVisitor(*this))
events.RemoveEvent(i);
else {
if (events[i].CanHaveSubEvents())
@@ -50,6 +50,10 @@ bool ArbitraryEventsWorker::VisitEvent(gd::BaseEvent& event) {
return false;
}
bool ArbitraryEventsWorker::VisitLinkEvent(gd::LinkEvent& linkEvent) {
return DoVisitLinkEvent(linkEvent);
}
void ArbitraryEventsWorker::VisitInstructionList(
gd::InstructionsList& instructions, bool areConditions) {
DoVisitInstructionList(instructions, areConditions);
@@ -80,7 +84,7 @@ void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events)
DoVisitEventList(events);
for (std::size_t i = 0; i < events.size(); ++i) {
VisitEvent(events[i]);
events[i].AcceptVisitor(*this);
if (events[i].CanHaveSubEvents()) {
VisitEventList(events[i].GetSubEvents());
@@ -103,6 +107,10 @@ void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
}
}
void ReadOnlyArbitraryEventsWorker::VisitLinkEvent(const gd::LinkEvent& linkEvent) {
DoVisitLinkEvent(linkEvent);
}
void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
const gd::InstructionsList& instructions, bool areConditions) {
DoVisitInstructionList(instructions, areConditions);

View File

@@ -9,10 +9,12 @@
#include <memory>
#include <vector>
#include "GDCore/Events/InstructionsList.h"
#include "GDCore/Events/EventVisitor.h"
#include "GDCore/String.h"
namespace gd {
class Instruction;
class BaseEvent;
class LinkEvent;
class EventsList;
class ObjectsContainer;
} // namespace gd
@@ -28,7 +30,7 @@ namespace gd {
*
* \ingroup IDE
*/
class GD_CORE_API ArbitraryEventsWorker {
class GD_CORE_API ArbitraryEventsWorker : private EventVisitor {
public:
ArbitraryEventsWorker(){};
virtual ~ArbitraryEventsWorker();
@@ -40,7 +42,8 @@ class GD_CORE_API ArbitraryEventsWorker {
private:
void VisitEventList(gd::EventsList& events);
bool VisitEvent(gd::BaseEvent& event);
bool VisitEvent(gd::BaseEvent& event) override;
bool VisitLinkEvent(gd::LinkEvent& linkEvent) override;
void VisitInstructionList(gd::InstructionsList& instructions,
bool areConditions);
bool VisitInstruction(gd::Instruction& instruction, bool isCondition);
@@ -52,11 +55,21 @@ class GD_CORE_API ArbitraryEventsWorker {
/**
* Called to do some work on an event
* \return true if the instruction must be deleted from the events list, false
* \return true if the event must be deleted from the events list, false
* otherwise (default).
*/
virtual bool DoVisitEvent(gd::BaseEvent& event) { return false; };
/**
* Called to do some work on a link event.
*
* Note that DoVisitEvent is also called with this event.
*
* \return true if the event must be deleted from the events list, false
* otherwise (default).
*/
virtual bool DoVisitLinkEvent(gd::LinkEvent& event) { return false; };
/**
* Called to do some work on an instruction list
*/
@@ -129,7 +142,7 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
*
* \ingroup IDE
*/
class GD_CORE_API ReadOnlyArbitraryEventsWorker {
class GD_CORE_API ReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
public:
ReadOnlyArbitraryEventsWorker(){};
virtual ~ReadOnlyArbitraryEventsWorker();
@@ -141,7 +154,8 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorker {
private:
void VisitEventList(const gd::EventsList& events);
void VisitEvent(const gd::BaseEvent& event);
void VisitEvent(const gd::BaseEvent& event) override;
void VisitLinkEvent(const gd::LinkEvent& linkEvent) override;
void VisitInstructionList(const gd::InstructionsList& instructions,
bool areConditions);
void VisitInstruction(const gd::Instruction& instruction, bool isCondition);
@@ -156,6 +170,13 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorker {
*/
virtual void DoVisitEvent(const gd::BaseEvent& event) {};
/**
* Called to do some work on a link event.
*
* Note that DoVisitEvent is also called with this event.
*/
virtual void DoVisitLinkEvent(const gd::LinkEvent& linkEvent) {};
/**
* Called to do some work on an instruction list
*/

View File

@@ -8,13 +8,10 @@
#define GDCORE_BEHAVIORTYPERENAMER_H
#include <set>
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/String.h"
namespace gd {
class Project;
class Object;
class Behavior;
} // namespace gd
@@ -23,17 +20,15 @@ namespace gd {
class GD_CORE_API BehaviorTypeRenamer : public ArbitraryObjectsWorker {
public:
BehaviorTypeRenamer(const gd::Project& project_,
const gd::String& oldType_,
const gd::String& newType_)
: project(project_), oldType(oldType_), newType(newType_){};
BehaviorTypeRenamer(const gd::String& oldType_,
const gd::String& newType_)
: oldType(oldType_), newType(newType_){};
virtual ~BehaviorTypeRenamer();
private:
void DoVisitObject(gd::Object& object) override;
void DoVisitBehavior(gd::Behavior& behavior) override;
const gd::Project& project;
gd::String oldType;
gd::String newType;
};

View File

@@ -8,13 +8,10 @@
#define GDCORE_CUSTOMOBJECTTYPERENAMER_H
#include <set>
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/String.h"
namespace gd {
class Project;
class Object;
class Behavior;
} // namespace gd
@@ -23,17 +20,15 @@ namespace gd {
class GD_CORE_API CustomObjectTypeRenamer : public ArbitraryObjectsWorker {
public:
CustomObjectTypeRenamer(const gd::Project& project_,
const gd::String& oldType_,
CustomObjectTypeRenamer(const gd::String& oldType_,
const gd::String& newType_)
: project(project_), oldType(oldType_), newType(newType_){};
: oldType(oldType_), newType(newType_){};
virtual ~CustomObjectTypeRenamer();
private:
void DoVisitObject(gd::Object& object) override;
void DoVisitBehavior(gd::Behavior& behavior) override;
const gd::Project& project;
gd::String oldType;
gd::String newType;
};

View File

@@ -202,7 +202,7 @@ std::set<gd::String> EventsIdentifiersFinder::FindAllIdentifierExpressions(
std::set<gd::String> results;
const bool isObjectIdentifier = identifierType.find("object") == 0;
// The object from the context is only relevent for object identifiers.
// The object from the context is only relevant for object identifiers.
auto& actualObjectName = isObjectIdentifier ? contextObjectName : "";
FindArgumentsInEventsAndDependencies(

View File

@@ -22,7 +22,7 @@ class EventsList;
namespace gd {
/**
* \brief List the values of the parameters of events and their type.
* \brief Allow to safely remove a bunch of events.
*
* \ingroup IDE
*/

View File

@@ -77,24 +77,42 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
MetadataProvider::GetBehaviorAnyExpressionMetadata(
platform, behaviorType, function.functionName);
if (!function.objectName.empty()) {
// If the function needs a capability on the object that may not be covered
// by all objects, check it now.
if (!metadata.GetRequiredBaseObjectCapability().empty()) {
const gd::ObjectMetadata &objectMetadata =
MetadataProvider::GetObjectMetadata(platform, objectType);
Type returnType = StringToType(metadata.GetReturnType());
if (objectMetadata.IsUnsupportedBaseObjectCapability(
metadata.GetRequiredBaseObjectCapability())) {
RaiseTypeError(
_("This expression exists, but it can't be used on this object."),
function.objectNameLocation);
return StringToType(metadata.GetReturnType());
}
}
if (!function.objectName.empty() &&
!globalObjectsContainer.HasObjectNamed(function.objectName) &&
!globalObjectsContainer.GetObjectGroups().Has(function.objectName) &&
!objectsContainer.HasObjectNamed(function.objectName) &&
!objectsContainer.GetObjectGroups().Has(function.objectName)) {
RaiseTypeError(_("This object doesn't exist."),
function.objectNameLocation, /*isFatal=*/false);
return returnType;
}
Type returnType = StringToType(metadata.GetReturnType());
if (!function.behaviorName.empty() &&
!gd::HasBehaviorInObjectOrGroup(globalObjectsContainer, objectsContainer,
function.objectName,
function.behaviorName)) {
RaiseTypeError(_("This behavior is not attached to this object."),
function.behaviorNameLocation, /*isFatal=*/false);
return returnType;
}
if (!function.objectName.empty() &&
// If the function needs a capability on the object that may not be covered
// by all objects, check it now.
!metadata.GetRequiredBaseObjectCapability().empty()) {
const gd::ObjectMetadata &objectMetadata =
MetadataProvider::GetObjectMetadata(platform, objectType);
if (objectMetadata.IsUnsupportedBaseObjectCapability(
metadata.GetRequiredBaseObjectCapability())) {
RaiseTypeError(
_("This expression exists, but it can't be used on this object."),
function.objectNameLocation);
return returnType;
}
}
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
RaiseError(
@@ -115,8 +133,8 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
"number to a string."),
function.location);
return returnType;
}
else if (parentType != Type::Number && parentType != Type::NumberOrString) {
} else if (parentType != Type::Number &&
parentType != Type::NumberOrString) {
RaiseTypeError(_("You tried to use an expression that returns a "
"number, but another type is expected:") +
" " + TypeToString(parentType),
@@ -131,8 +149,8 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
"string to a number."),
function.location);
return returnType;
}
else if (parentType != Type::String && parentType != Type::NumberOrString) {
} else if (parentType != Type::String &&
parentType != Type::NumberOrString) {
RaiseTypeError(_("You tried to use an expression that returns a "
"string, but another type is expected:") +
" " + TypeToString(parentType),
@@ -172,8 +190,7 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
_("You have not entered enough parameters for the expression.") + " " +
expectedCountMessage,
function.location);
}
else {
} else {
RaiseError(
"extra_parameter",
_("This parameter was not expected by this expression. Remove it "
@@ -217,8 +234,7 @@ ExpressionValidator::Type ExpressionValidator::ValidateFunction(const gd::Functi
"parameter."),
parameter->location);
}
}
else if (gd::ParameterMetadata::IsObject(expectedParameterType)) {
} else if (gd::ParameterMetadata::IsObject(expectedParameterType)) {
if (dynamic_cast<IdentifierNode *>(parameter.get()) == nullptr) {
RaiseError(
"malformed_object_parameter",

View File

@@ -45,7 +45,7 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
/**
* \brief Helper function to check if a given node does not contain
* any error.
* any error including non-fatal ones.
*/
static bool HasNoErrors(const gd::Platform &platform,
const gd::ObjectsContainer &globalObjectsContainer,
@@ -54,16 +54,25 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
gd::ExpressionNode& node) {
gd::ExpressionValidator validator(platform, globalObjectsContainer, objectsContainer, rootType);
node.Visit(validator);
return validator.GetErrors().empty();
return validator.GetAllErrors().empty();
}
/**
* \brief Get only the fatal errors
*
* Expressions with fatal error can't be generated.
*/
const std::vector<ExpressionParserDiagnostic*>& GetFatalErrors() {
return fatalErrors;
};
/**
* \brief Get all the errors
*
* No errors means that the expression is valid.
*/
const std::vector<ExpressionParserDiagnostic*>& GetErrors() {
return errors;
const std::vector<ExpressionParserDiagnostic*>& GetAllErrors() {
return allErrors;
};
protected:
@@ -239,20 +248,26 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
enum Type {Unknown = 0, Number, String, NumberOrString, Variable, Object, Empty};
Type ValidateFunction(const gd::FunctionCallNode& function);
void ReportAnyError(const ExpressionNode& node) {
void ReportAnyError(const ExpressionNode& node, bool isFatal = true) {
if (node.diagnostic && node.diagnostic->IsError()) {
// Syntax errors are holden by the AST nodes.
// It's fine to give pointers on them as the AST live longer than errors
// handling.
errors.push_back(node.diagnostic.get());
allErrors.push_back(node.diagnostic.get());
if (isFatal) {
fatalErrors.push_back(node.diagnostic.get());
}
}
}
void RaiseError(const gd::String &type,
const gd::String &message, const ExpressionParserLocation &location) {
const gd::String &message, const ExpressionParserLocation &location, bool isFatal = true) {
auto diagnostic = gd::make_unique<ExpressionParserError>(
type, message, location);
errors.push_back(diagnostic.get());
allErrors.push_back(diagnostic.get());
if (isFatal) {
fatalErrors.push_back(diagnostic.get());
}
// Errors found by the validator are not holden by the AST nodes.
// They must be owned by the validator to keep living while errors are
// handled by the caller.
@@ -260,8 +275,8 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
}
void RaiseTypeError(
const gd::String &message, const ExpressionParserLocation &location) {
RaiseError("type_error", message, location);
const gd::String &message, const ExpressionParserLocation &location, bool isFatal = true) {
RaiseError("type_error", message, location, isFatal);
}
void RaiseOperatorError(
@@ -306,7 +321,8 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
static const gd::String identifierTypeString;
static const gd::String emptyTypeString;
std::vector<ExpressionParserDiagnostic*> errors;
std::vector<ExpressionParserDiagnostic*> fatalErrors;
std::vector<ExpressionParserDiagnostic*> allErrors;
std::vector<std::unique_ptr<ExpressionParserDiagnostic>> supplementalErrors;
Type childType;
Type parentType;

View File

@@ -0,0 +1,24 @@
#include "InstructionsCountEvaluator.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
namespace gd {
const int InstructionsCountEvaluator::ScanProject(gd::Project &project) {
InstructionsCountEvaluator worker(project);
gd::ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(project,
worker);
return worker.instructionCount;
};
// Instructions scanner
bool InstructionsCountEvaluator::DoVisitInstruction(
gd::Instruction &instruction, bool isCondition) {
instructionCount++;
return false;
}
} // namespace gd

View File

@@ -0,0 +1,50 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_INSTRUCTIONS_COUNT_EVALUATOR_H
#define GDCORE_INSTRUCTIONS_COUNT_EVALUATOR_H
#include <set>
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/String.h"
namespace gd {
class Project;
class Object;
class Behavior;
} // namespace gd
namespace gd {
/**
* @brief Count the number of instructions in a project excluding extensions.
*
* This is used by the examples repository to evaluate examples size.
*
*/
class GD_CORE_API InstructionsCountEvaluator : public ArbitraryEventsWorker {
public:
/**
* Return the number of instructions in the project excluding extensions.
*/
static const int ScanProject(gd::Project &project);
private:
InstructionsCountEvaluator(gd::Project &project_)
: project(project_), instructionCount(0){};
gd::Project &project;
int instructionCount;
// Instructions Visitor
bool DoVisitInstruction(gd::Instruction &instruction,
bool isCondition) override;
};
}; // namespace gd
#endif

View File

@@ -0,0 +1,33 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "LinkEventTargetRenamer.h"
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Events/Builtin/LinkEvent.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace gd {
bool LinkEventTargetRenamer::DoVisitLinkEvent(gd::LinkEvent &linkEvent) {
if (linkEvent.GetTarget() == oldName) {
linkEvent.SetTarget(newName);
}
return false;
}
LinkEventTargetRenamer::~LinkEventTargetRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,44 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
class BaseEvent;
class LinkEvent;
class Platform;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Replace in link events the name of external events.
*
* \ingroup IDE
*/
class GD_CORE_API LinkEventTargetRenamer
: public ArbitraryEventsWorkerWithContext {
public:
LinkEventTargetRenamer(const gd::Platform &platform_,
const gd::String &oldName_, const gd::String &newName_)
: platform(platform_), oldName(oldName_), newName(newName_){};
virtual ~LinkEventTargetRenamer();
private:
bool DoVisitLinkEvent(gd::LinkEvent &linkEvent) override;
const gd::Platform &platform;
gd::String oldName;
gd::String newName;
};
} // namespace gd

View File

@@ -0,0 +1,198 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ProjectElementRenamer.h"
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/IDE/Events/ExpressionValidator.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace gd {
/**
* \brief Go through the nodes and find every function call parameter of a
* given type.
*
* \see gd::ExpressionParser2
*/
class GD_CORE_API ExpressionIdentifierStringFinder
: public ExpressionParser2NodeWorker {
public:
ExpressionIdentifierStringFinder(
const gd::Platform &platform_,
const gd::ObjectsContainer &globalObjectsContainer_,
const gd::ObjectsContainer &objectsContainer_,
const gd::String &expressionPlainString_,
const gd::String &parameterType_, const gd::String &objectName_,
const gd::String &layerName_, const gd::String &oldName_)
: platform(platform_), globalObjectsContainer(globalObjectsContainer_),
objectsContainer(objectsContainer_),
expressionPlainString(expressionPlainString_),
parameterType(parameterType_), objectName(objectName_),
layerName(layerName_), oldName(oldName_){};
virtual ~ExpressionIdentifierStringFinder(){};
const std::vector<gd::ExpressionParserLocation> GetOccurrences() const {
return occurrences;
}
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 {}
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode &node) override {}
void OnVisitFunctionCallNode(FunctionCallNode &node) override {
gd::String lastLayerName;
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
platform, globalObjectsContainer, objectsContainer, node,
[&](const gd::ParameterMetadata &parameterMetadata,
std::unique_ptr<gd::ExpressionNode> &parameterNode,
size_t parameterIndex, const gd::String &lastObjectName) {
if (parameterMetadata.GetType() == "layer") {
// Remove quotes, it won't match if it's not a literal anyway.
lastLayerName = expressionPlainString.substr(
parameterNode->location.GetStartPosition() + 1,
parameterNode->location.GetEndPosition() -
parameterNode->location.GetStartPosition() - 2);
}
if (parameterMetadata.GetType() == parameterType) {
auto parameterExpressionPlainString = expressionPlainString.substr(
parameterNode->location.GetStartPosition(),
parameterNode->location.GetEndPosition() -
parameterNode->location.GetStartPosition());
if ((objectName.empty() || lastObjectName == objectName) &&
(layerName.empty() || lastLayerName == layerName) &&
parameterExpressionPlainString == "\"" + oldName + "\"") {
occurrences.push_back(parameterNode->location);
} else {
parameterNode->Visit(*this);
}
}
});
}
void OnVisitEmptyNode(EmptyNode &node) override {}
private:
const gd::Platform &platform;
const gd::ObjectsContainer &globalObjectsContainer;
const gd::ObjectsContainer &objectsContainer;
/// It's used to extract parameter content.
const gd::String &expressionPlainString;
const gd::String &oldName;
/// The type of parameter to check.
const gd::String parameterType;
/// If not empty, parameters will be taken into account only if related to
/// this object.
const gd::String objectName;
/// If not empty, parameters will be taken into account only if related to
/// this layer.
const gd::String layerName;
std::vector<gd::ExpressionParserLocation> occurrences;
};
bool ProjectElementRenamer::DoVisitInstruction(gd::Instruction &instruction,
bool isCondition) {
const auto &metadata = isCondition
? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
gd::String lastLayerName;
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(), metadata.GetParameters(),
[&](const gd::ParameterMetadata &parameterMetadata,
const gd::Expression &parameterValue, size_t parameterIndex,
const gd::String &lastObjectName) {
if (parameterMetadata.GetType() == "layer") {
// Remove quotes, it won't match if it's not a literal anyway.
lastLayerName = parameterValue.GetPlainString().substr(
1, parameterValue.GetPlainString().length() - 2);
}
if (parameterMetadata.GetType() == parameterType &&
(objectName.empty() || lastObjectName == objectName) &&
(layerName.empty() || lastLayerName == layerName)) {
if (parameterValue.GetPlainString() == "\"" + oldName + "\"") {
instruction.SetParameter(parameterIndex,
gd::Expression("\"" + newName + "\""));
}
}
auto node = parameterValue.GetRootNode();
if (node) {
ExpressionIdentifierStringFinder finder(
platform, GetGlobalObjectsContainer(), GetObjectsContainer(),
parameterValue.GetPlainString(), parameterType, objectName,
layerName, oldName);
node->Visit(finder);
if (finder.GetOccurrences().size() > 0) {
gd::String newNameWithQuotes = "\"" + newName + "\"";
gd::String oldParameterValue = parameterValue.GetPlainString();
gd::String newParameterValue;
auto previousEndPosition = 0;
for (auto &&occurrenceLocation : finder.GetOccurrences()) {
newParameterValue += oldParameterValue.substr(
previousEndPosition,
occurrenceLocation.GetStartPosition() - previousEndPosition);
newParameterValue += newNameWithQuotes;
previousEndPosition = occurrenceLocation.GetEndPosition();
}
if (previousEndPosition < oldParameterValue.size()) {
newParameterValue += oldParameterValue.substr(
previousEndPosition,
oldParameterValue.size() - previousEndPosition);
}
instruction.SetParameter(parameterIndex,
gd::Expression(newParameterValue));
}
}
});
return false;
}
ProjectElementRenamer::~ProjectElementRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,63 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
class BaseEvent;
class Platform;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Replace in expressions and in parameters of actions or conditions
* occurrences of project element name. For instance, it can be layouts or
* object effects.
*
* \ingroup IDE
*/
class GD_CORE_API ProjectElementRenamer
: public ArbitraryEventsWorkerWithContext {
public:
ProjectElementRenamer(const gd::Platform &platform_,
const gd::String &parameterType_,
const gd::String &oldName_, const gd::String &newName_)
: platform(platform_), parameterType(parameterType_), oldName(oldName_),
newName(newName_){};
virtual ~ProjectElementRenamer();
void SetObjectConstraint(const gd::String &objectName_) {
objectName = objectName_;
}
void SetLayerConstraint(const gd::String &layerName_) {
layerName = layerName_;
}
private:
bool DoVisitInstruction(gd::Instruction &instruction,
bool isCondition) override;
const gd::Platform &platform;
const gd::String parameterType;
/// If not empty, parameters will be taken into account only if related to
/// this object.
gd::String objectName;
/// If not empty, parameters will be taken into account only if related to
/// this layer.
gd::String layerName;
const gd::String oldName;
const gd::String newName;
};
} // namespace gd

View File

@@ -4,6 +4,7 @@
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
#include "GDCore/Project/Behavior.h"
@@ -14,8 +15,8 @@ namespace gd {
const UsedExtensionsResult UsedExtensionsFinder::ScanProject(gd::Project& project) {
UsedExtensionsFinder worker(project);
gd::WholeProjectRefactorer::ExposeProjectObjects(project, worker);
gd::WholeProjectRefactorer::ExposeProjectEvents(project, worker);
gd::ProjectBrowserHelper::ExposeProjectObjects(project, worker);
gd::ProjectBrowserHelper::ExposeProjectEvents(project, worker);
return worker.result;
};

View File

@@ -0,0 +1,37 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ArbitraryBehaviorSharedDataWorker.h"
#include <iostream>
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/String.h"
using namespace std;
namespace gd {
ArbitraryBehaviorSharedDataWorker::~ArbitraryBehaviorSharedDataWorker() {}
void ArbitraryBehaviorSharedDataWorker::VisitSharedDatas(
const std::map<gd::String, std::unique_ptr<gd::BehaviorsSharedData>>
&sharedDatas) {
DoVisitSharedDatas(sharedDatas);
for (auto &behaviorSharedDataContent : sharedDatas) {
VisitSharedData(*behaviorSharedDataContent.second);
}
}
void ArbitraryBehaviorSharedDataWorker::VisitSharedData(
gd::BehaviorsSharedData &sharedData) {
DoVisitSharedData(sharedData);
}
} // namespace gd

View File

@@ -0,0 +1,55 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <map>
#include <memory>
#include <vector>
#include "GDCore/String.h"
#include "GDCore/Tools/SerializableWithNameList.h"
namespace gd {
class BehaviorsSharedData;
} // namespace gd
namespace gd {
/**
* \brief ArbitraryBehaviorSharedDataWorker is an abstract class used to browse
* shared data and do some work on them. It can be used to implement
* refactoring for example.
*
* \ingroup IDE
*/
class GD_CORE_API ArbitraryBehaviorSharedDataWorker {
public:
ArbitraryBehaviorSharedDataWorker(){};
virtual ~ArbitraryBehaviorSharedDataWorker();
/**
* \brief Launch the worker on the specified shared data.
*/
void Launch(const std::map<gd::String, std::unique_ptr<gd::BehaviorsSharedData>>& sharedDatas) { VisitSharedDatas(sharedDatas); };
private:
void VisitSharedDatas(const std::map<gd::String, std::unique_ptr<gd::BehaviorsSharedData>>& sharedDatas);
void VisitSharedData(gd::BehaviorsSharedData& behavior);
/**
* Called to do some work on shared data.
*/
virtual void DoVisitSharedDatas(const std::map<gd::String, std::unique_ptr<gd::BehaviorsSharedData>>& sharedDatas){};
/**
* Called to do some work on a shared data.
*/
virtual void DoVisitSharedData(gd::BehaviorsSharedData& sharedData){};
};
} // namespace gd

View File

@@ -0,0 +1,34 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ArbitraryEventBasedBehaviorsWorker.h"
#include <iostream>
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/String.h"
using namespace std;
namespace gd {
ArbitraryEventBasedBehaviorsWorker::~ArbitraryEventBasedBehaviorsWorker() {}
void ArbitraryEventBasedBehaviorsWorker::VisitEventBasedBehaviors(gd::SerializableWithNameList<gd::EventsBasedBehavior>& behaviors) {
DoVisitEventBasedBehaviors(behaviors);
for (auto&& eventsBasedBehavior : behaviors.GetInternalVector()) {
VisitEventBasedBehavior(*eventsBasedBehavior);
}
}
void ArbitraryEventBasedBehaviorsWorker::VisitEventBasedBehavior(gd::EventsBasedBehavior& behavior) {
DoVisitEventBasedBehavior(behavior);
}
} // namespace gd

View File

@@ -0,0 +1,59 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <map>
#include <memory>
#include <vector>
#include "GDCore/String.h"
#include "GDCore/Tools/SerializableWithNameList.h"
namespace gd {
class EventsBasedBehavior;
} // namespace gd
namespace gd {
/**
* \brief ArbitraryEventsFunctionsWorker is an abstract class used to browse
* event-based behaviors and do some work on them. It can be used to implement
* refactoring for example.
*
* \ingroup IDE
*/
class GD_CORE_API ArbitraryEventBasedBehaviorsWorker {
public:
ArbitraryEventBasedBehaviorsWorker(){};
virtual ~ArbitraryEventBasedBehaviorsWorker();
/**
* \brief Launch the worker on the specified event-based behaviors.
*/
void Launch(gd::SerializableWithNameList<gd::EventsBasedBehavior>& behaviors) { VisitEventBasedBehaviors(behaviors); };
/**
* \brief Launch the worker on the specified event-based behavior.
*/
void Launch(EventsBasedBehavior& behavior) { VisitEventBasedBehavior(behavior); };
private:
void VisitEventBasedBehaviors(gd::SerializableWithNameList<gd::EventsBasedBehavior>& behaviors);
void VisitEventBasedBehavior(gd::EventsBasedBehavior& behavior);
/**
* Called to do some work on event-based behaviors.
*/
virtual void DoVisitEventBasedBehaviors(gd::SerializableWithNameList<gd::EventsBasedBehavior>& behaviors){};
/**
* Called to do some work on an event-based behavior.
*/
virtual void DoVisitEventBasedBehavior(gd::EventsBasedBehavior& behavior){};
};
} // namespace gd

View File

@@ -0,0 +1,37 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ArbitraryEventsFunctionsWorker.h"
#include <iostream>
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/Project/EventsFunctionsContainer.h"
#include "GDCore/Extensions/Metadata/ParameterMetadata.h"
#include "GDCore/String.h"
using namespace std;
namespace gd {
ArbitraryEventsFunctionsWorker::~ArbitraryEventsFunctionsWorker() {}
void ArbitraryEventsFunctionsWorker::VisitEventsFunctionContainer(
gd::EventsFunctionsContainer& functions) {
DoVisitEventsFunctionsContainer(functions);
for (auto&& function : functions.GetInternalVector()) {
VisitEventsFunction(*function);
}
}
void ArbitraryEventsFunctionsWorker::VisitEventsFunction(gd::EventsFunction& eventsFunction) {
DoVisitEventsFunction(eventsFunction);
}
} // namespace gd

View File

@@ -0,0 +1,55 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <map>
#include <memory>
#include <vector>
#include "GDCore/String.h"
namespace gd {
class EventsFunction;
class EventsFunctionsContainer;
class ParameterMetadata;
} // namespace gd
namespace gd {
/**
* \brief ArbitraryEventsFunctionsWorker is an abstract class used to browse
* functions signatures and do some work on them. It can be used to implement
* refactoring for example.
*
* \ingroup IDE
*/
class GD_CORE_API ArbitraryEventsFunctionsWorker {
public:
ArbitraryEventsFunctionsWorker(){};
virtual ~ArbitraryEventsFunctionsWorker();
/**
* \brief Launch the worker on the specified function container.
*/
void Launch(gd::EventsFunctionsContainer& functions) { VisitEventsFunctionContainer(functions); };
private:
void VisitEventsFunctionContainer(gd::EventsFunctionsContainer& functions);
void VisitEventsFunction(gd::EventsFunction& eventsFunction);
/**
* Called to do some work on an function container.
*/
virtual void DoVisitEventsFunctionsContainer(gd::EventsFunctionsContainer& functions){};
/**
* Called to do some work on a function.
*/
virtual void DoVisitEventsFunction(gd::EventsFunction& eventsFunction){};
};
} // namespace gd

View File

@@ -33,7 +33,7 @@ class GD_CORE_API ArbitraryObjectsWorker {
virtual ~ArbitraryObjectsWorker();
/**
* \brief Launch the worker on the specified events list.
* \brief Launch the worker on the specified object container.
*/
void Launch(gd::ObjectsContainer& objects) { VisitObjectContainer(objects); };

View File

@@ -0,0 +1,25 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "BehaviorObjectTypeRenamer.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
void BehaviorObjectTypeRenamer::DoVisitEventBasedBehavior(
gd::EventsBasedBehavior &eventsBasedBehavior) {
if (eventsBasedBehavior.GetObjectType() == oldObjectType) {
eventsBasedBehavior.SetObjectType(newObjectType);
}
}
BehaviorObjectTypeRenamer::~BehaviorObjectTypeRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,45 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_BEHAVIOROBJECTTYPERENAMER_H
#define GDCORE_BEHAVIOROBJECTTYPERENAMER_H
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
class BaseEvent;
class Project;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Rename the object type in event-based behaviors.
*
* \ingroup IDE
*/
class GD_CORE_API BehaviorObjectTypeRenamer
: public ArbitraryEventBasedBehaviorsWorker {
public:
BehaviorObjectTypeRenamer(const gd::String &oldObjectType_,
const gd::String &newObjectType_)
: oldObjectType(oldObjectType_), newObjectType(newObjectType_){};
virtual ~BehaviorObjectTypeRenamer();
private:
void DoVisitEventBasedBehavior(gd::EventsBasedBehavior &behavior) override;
gd::String oldObjectType;
gd::String newObjectType;
};
} // namespace gd
#endif // GDCORE_BEHAVIOROBJECTTYPERENAMER_H

View File

@@ -0,0 +1,24 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "GDCore/IDE/Project/BehaviorsSharedDataBehaviorTypeRenamer.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
void BehaviorsSharedDataBehaviorTypeRenamer::DoVisitSharedData(
gd::BehaviorsSharedData &sharedData) {
if (sharedData.GetTypeName() == oldBehaviorType) {
sharedData.SetTypeName(newBehaviorType);
}
}
BehaviorsSharedDataBehaviorTypeRenamer::~BehaviorsSharedDataBehaviorTypeRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,42 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <map>
#include <memory>
#include <vector>
#include "GDCore/IDE/Project/ArbitraryBehaviorSharedDataWorker.h"
#include "GDCore/String.h"
namespace gd {
class BaseEvent;
class Project;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Rename the behavior type of shared data.
*
* \ingroup IDE
*/
class GD_CORE_API BehaviorsSharedDataBehaviorTypeRenamer : public ArbitraryBehaviorSharedDataWorker {
public:
BehaviorsSharedDataBehaviorTypeRenamer(const gd::String& oldBehaviorType_,
const gd::String& newBehaviorType_)
: oldBehaviorType(oldBehaviorType_), newBehaviorType(newBehaviorType_){};
virtual ~BehaviorsSharedDataBehaviorTypeRenamer();
private:
void DoVisitSharedData(gd::BehaviorsSharedData& behavior) override;
gd::String oldBehaviorType;
gd::String newBehaviorType;
};
} // namespace gd

View File

@@ -0,0 +1,28 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "FunctionParameterBehaviorTypeRenamer.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
void FunctionParameterBehaviorTypeRenamer::DoVisitEventsFunction(
gd::EventsFunction &eventsFunction) {
for (auto &&parameter : eventsFunction.GetParameters()) {
if (gd::ParameterMetadata::IsBehavior(parameter.GetType()) &&
parameter.GetExtraInfo() == oldBehaviorType) {
parameter.SetExtraInfo(newBehaviorType);
}
}
}
FunctionParameterBehaviorTypeRenamer::~FunctionParameterBehaviorTypeRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,42 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
class BaseEvent;
class Project;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Rename the type of behavior parameters in functions.
*
* \ingroup IDE
*/
class GD_CORE_API FunctionParameterBehaviorTypeRenamer
: public ArbitraryEventsFunctionsWorker {
public:
FunctionParameterBehaviorTypeRenamer(const gd::String &oldBehaviorType_,
const gd::String &newBehaviorType_)
: oldBehaviorType(oldBehaviorType_), newBehaviorType(newBehaviorType_){};
virtual ~FunctionParameterBehaviorTypeRenamer();
private:
virtual void DoVisitEventsFunction(gd::EventsFunction &eventsFunction) override;
gd::String oldBehaviorType;
gd::String newBehaviorType;
};
} // namespace gd

View File

@@ -0,0 +1,28 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "FunctionParameterObjectTypeRenamer.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
void FunctionParameterObjectTypeRenamer::DoVisitEventsFunction(
gd::EventsFunction &eventsFunction) {
for (auto &&parameter : eventsFunction.GetParameters()) {
if (gd::ParameterMetadata::IsObject(parameter.GetType()) &&
parameter.GetExtraInfo() == oldObjectType) {
parameter.SetExtraInfo(newObjectType);
}
}
}
FunctionParameterObjectTypeRenamer::~FunctionParameterObjectTypeRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,42 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
#include "GDCore/String.h"
#include <map>
#include <memory>
#include <vector>
namespace gd {
class BaseEvent;
class Project;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Rename the type of object parameters in functions.
*
* \ingroup IDE
*/
class GD_CORE_API FunctionParameterObjectTypeRenamer
: public ArbitraryEventsFunctionsWorker {
public:
FunctionParameterObjectTypeRenamer(const gd::String &oldObjectType_,
const gd::String &newObjectType_)
: oldObjectType(oldObjectType_), newObjectType(newObjectType_){};
virtual ~FunctionParameterObjectTypeRenamer();
private:
virtual void DoVisitEventsFunction(gd::EventsFunction &eventsFunction) override;
gd::String oldObjectType;
gd::String newObjectType;
};
} // namespace gd

View File

@@ -0,0 +1,35 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "GDCore/IDE/Project/RequiredBehaviorRenamer.h"
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/String.h"
namespace gd {
void RequiredBehaviorRenamer::DoVisitEventBasedBehavior(gd::EventsBasedBehavior& eventsBasedBehavior) {
for (size_t i = 0;
i < eventsBasedBehavior.GetPropertyDescriptors().GetCount();
i++) {
NamedPropertyDescriptor& propertyDescriptor =
eventsBasedBehavior.GetPropertyDescriptors().Get(i);
std::vector<gd::String>& extraInfo = propertyDescriptor.GetExtraInfo();
if (propertyDescriptor.GetType() == "Behavior" &&
extraInfo.size() > 0) {
const gd::String& requiredBehaviorType = extraInfo[0];
if (requiredBehaviorType == oldBehaviorType) {
extraInfo[0] = newBehaviorType;
}
}
}
}
RequiredBehaviorRenamer::~RequiredBehaviorRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,42 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_REQUIREDBEHAVIORRENAMER_H
#define GDCORE_REQUIREDBEHAVIORRENAMER_H
#include <map>
#include <memory>
#include <vector>
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
#include "GDCore/String.h"
namespace gd {
class BaseEvent;
class Project;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Rename the type of required behavior in event-based behaviors.
*
* \ingroup IDE
*/
class GD_CORE_API RequiredBehaviorRenamer : public ArbitraryEventBasedBehaviorsWorker {
public:
RequiredBehaviorRenamer(const gd::String& oldBehaviorType_,
const gd::String& newBehaviorType_)
: oldBehaviorType(oldBehaviorType_), newBehaviorType(newBehaviorType_){};
virtual ~RequiredBehaviorRenamer();
private:
void DoVisitEventBasedBehavior(gd::EventsBasedBehavior& behavior) override;
gd::String oldBehaviorType;
gd::String newBehaviorType;
};
} // namespace gd
#endif // GDCORE_REQUIREDBEHAVIORRENAMER_H

View File

@@ -4,9 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef GDCORE_RESOURCESRENAMER_H
#define GDCORE_RESOURCESRENAMER_H
#pragma once
#include <set>
#include <vector>
@@ -72,6 +70,3 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
};
} // namespace gd
#endif // GDCORE_RESOURCESRENAMER_H
#endif

View File

@@ -0,0 +1,89 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
namespace gd {
class Project;
class String;
class EventsFunctionsExtension;
class EventsFunction;
class EventsBasedBehavior;
class EventsBasedObject;
class ArbitraryEventsWorker;
class ArbitraryEventsWorkerWithContext;
class ArbitraryEventsFunctionsWorker;
class ArbitraryObjectsWorker;
class ArbitraryEventBasedBehaviorsWorker;
class ArbitraryBehaviorSharedDataWorker;
} // namespace gd
namespace gd {
/**
* \brief Expose a subset of the project to workers.
*/
class GD_CORE_API ProjectBrowser {
public:
/**
* \brief Call the specified worker on all events of a project subset.
*
* This should be the preferred way to traverse events of a project.
*/
virtual void ExposeEvents(gd::Project &project,
gd::ArbitraryEventsWorker &worker) const = 0;
/**
* \brief Call the specified worker on all events of a project subset.
*
* This should be the preferred way to traverse events of a project.
*/
virtual void
ExposeEvents(gd::Project &project,
gd::ArbitraryEventsWorkerWithContext &worker) const = 0;
/**
* \brief Call the specified worker on all ObjectContainer of a project subset
*
* This should be the preferred way to traverse all the objects of a project.
*/
virtual void ExposeObjects(gd::Project &project,
gd::ArbitraryObjectsWorker &worker) const = 0;
/**
* \brief Call the specified worker on all FunctionsContainer of a project
* subset.
*
* This should be the preferred way to traverse all the function signatures
* of a project.
*/
virtual void ExposeFunctions(gd::Project &project,
gd::ArbitraryEventsFunctionsWorker &worker) const = 0;
/**
* \brief Call the specified worker on all EventBasedBehavior of a project
* subset.
*
* This should be the preferred way to traverse all the event-based behavior
* of a project.
*/
virtual void ExposeEventBasedBehaviors(
gd::Project &project,
gd::ArbitraryEventBasedBehaviorsWorker &worker) const = 0;
/**
* \brief Call the specified worker on all SharedData of a project subset.
*
* This should be the preferred way to traverse all the shared data
* of a project.
*/
virtual void
ExposeBehaviorSharedDatas(gd::Project &project,
gd::ArbitraryBehaviorSharedDataWorker &worker) const = 0;
virtual ~ProjectBrowser(){};
};
} // namespace gd

View File

@@ -0,0 +1,256 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ProjectBrowserHelper.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/EventsFunctionTools.h"
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/IDE/Project/ArbitraryBehaviorSharedDataWorker.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
namespace gd {
void ProjectBrowserHelper::ExposeProjectEvents(
gd::Project &project, gd::ArbitraryEventsWorker &worker) {
// See also gd::Project::ExposeResources for a method that traverses the whole
// project (this time for resources).
ExposeProjectEventsWithoutExtensions(project, worker);
// Add events based extensions
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
// Add (free) events functions
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
for (auto &&eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
worker.Launch(eventsFunction->GetEvents());
}
// Add (behavior) events functions
for (auto &&eventsBasedBehavior :
eventsFunctionsExtension.GetEventsBasedBehaviors()
.GetInternalVector()) {
ExposeEventsBasedBehaviorEvents(project, *eventsBasedBehavior, worker);
}
// Add (object) events functions
for (auto &&eventsBasedObject :
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
auto &objectEventsFunctions = eventsBasedObject->GetEventsFunctions();
for (auto &&eventsFunction : objectEventsFunctions.GetInternalVector()) {
worker.Launch(eventsFunction->GetEvents());
}
}
}
}
void ProjectBrowserHelper::ExposeProjectEventsWithoutExtensions(
gd::Project& project, gd::ArbitraryEventsWorker& worker) {
// Add layouts events
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
worker.Launch(project.GetLayout(s).GetEvents());
}
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
worker.Launch(project.GetExternalEvents(s).GetEvents());
}
}
void ProjectBrowserHelper::ExposeLayoutEvents(
gd::Project &project, gd::Layout &layout,
gd::ArbitraryEventsWorker &worker) {
// Add layouts events
worker.Launch(layout.GetEvents());
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
auto &externalEvents = project.GetExternalEvents(s);
if (externalEvents.GetAssociatedLayout() == layout.GetName()) {
worker.Launch(externalEvents.GetEvents());
}
}
}
void ProjectBrowserHelper::ExposeLayoutEvents(
gd::Project &project, gd::Layout &layout,
gd::ArbitraryEventsWorkerWithContext &worker) {
// Add layouts events
worker.Launch(layout.GetEvents(), project, layout);
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
auto &externalEvents = project.GetExternalEvents(s);
if (externalEvents.GetAssociatedLayout() == layout.GetName()) {
worker.Launch(externalEvents.GetEvents(), project, layout);
}
}
}
void ProjectBrowserHelper::ExposeProjectEvents(
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) {
// See also gd::Project::ExposeResources for a method that traverse the whole
// project (this time for resources) and ExposeProjectEffects (this time for
// effects).
// Add layouts events
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
auto &layout = project.GetLayout(s);
worker.Launch(layout.GetEvents(), project, layout);
}
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
const auto &externalEvents = project.GetExternalEvents(s);
const gd::String &associatedLayout = externalEvents.GetAssociatedLayout();
if (project.HasLayoutNamed(associatedLayout)) {
worker.Launch(project.GetExternalEvents(s).GetEvents(), project,
project.GetLayout(associatedLayout));
}
}
// Add events based extensions
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
// Add (free) events functions
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
for (auto &&eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
gd::ObjectsContainer globalObjectsAndGroups;
gd::ObjectsContainer objectsAndGroups;
gd::EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
project, eventsFunctionsExtension, *eventsFunction,
globalObjectsAndGroups, objectsAndGroups);
worker.Launch(eventsFunction->GetEvents(), globalObjectsAndGroups,
objectsAndGroups);
}
// Add (behavior) events functions
for (auto &&eventsBasedBehavior :
eventsFunctionsExtension.GetEventsBasedBehaviors()
.GetInternalVector()) {
ExposeEventsBasedBehaviorEvents(project, *eventsBasedBehavior, worker);
}
// Add (object) events functions
for (auto &&eventsBasedObject :
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
ExposeEventsBasedObjectEvents(project, *eventsBasedObject, worker);
}
}
}
void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
gd::Project &project, const gd::EventsBasedBehavior &eventsBasedBehavior,
gd::ArbitraryEventsWorker &worker) {
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
for (auto &&eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
worker.Launch(eventsFunction->GetEvents());
}
}
void ProjectBrowserHelper::ExposeEventsBasedBehaviorEvents(
gd::Project &project, const gd::EventsBasedBehavior &eventsBasedBehavior,
gd::ArbitraryEventsWorkerWithContext &worker) {
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
for (auto &&eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
gd::ObjectsContainer globalObjectsAndGroups;
gd::ObjectsContainer objectsAndGroups;
gd::EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
project, eventsBasedBehavior, *eventsFunction, globalObjectsAndGroups,
objectsAndGroups);
worker.Launch(eventsFunction->GetEvents(), globalObjectsAndGroups,
objectsAndGroups);
}
}
void ProjectBrowserHelper::ExposeEventsBasedObjectEvents(
gd::Project &project, const gd::EventsBasedObject &eventsBasedObject,
gd::ArbitraryEventsWorkerWithContext &worker) {
auto &objectEventsFunctions = eventsBasedObject.GetEventsFunctions();
for (auto &&eventsFunction : objectEventsFunctions.GetInternalVector()) {
gd::ObjectsContainer globalObjectsAndGroups;
gd::ObjectsContainer objectsAndGroups;
gd::EventsFunctionTools::ObjectEventsFunctionToObjectsContainer(
project, eventsBasedObject, *eventsFunction, globalObjectsAndGroups,
objectsAndGroups);
worker.Launch(eventsFunction->GetEvents(), globalObjectsAndGroups,
objectsAndGroups);
}
}
void ProjectBrowserHelper::ExposeProjectObjects(
gd::Project &project, gd::ArbitraryObjectsWorker &worker) {
// Global objects
worker.Launch(project);
// Layers objects
for (size_t i = 0; i < project.GetLayoutsCount(); i++) {
worker.Launch(project.GetLayout(i));
}
// Event based objects children
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
for (auto &&eventsBasedObjectUniquePtr :
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
auto eventsBasedObject = eventsBasedObjectUniquePtr.get();
worker.Launch(*eventsBasedObject);
}
}
};
void ProjectBrowserHelper::ExposeProjectFunctions(
gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) {
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
worker.Launch(eventsFunctionsExtension);
for (auto &&eventsBasedBehavior :
eventsFunctionsExtension.GetEventsBasedBehaviors()
.GetInternalVector()) {
worker.Launch(eventsBasedBehavior->GetEventsFunctions());
}
for (auto &&eventsBasedObject :
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
worker.Launch(eventsBasedObject->GetEventsFunctions());
}
}
};
void ProjectBrowserHelper::ExposeProjectEventBasedBehaviors(
gd::Project &project, gd::ArbitraryEventBasedBehaviorsWorker &worker) {
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto &eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
worker.Launch(eventsFunctionsExtension.GetEventsBasedBehaviors());
}
}
void ProjectBrowserHelper::ExposeProjectSharedDatas(
gd::Project &project, gd::ArbitraryBehaviorSharedDataWorker &worker) {
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
gd::Layout &layout = project.GetLayout(i);
worker.Launch(layout.GetAllBehaviorSharedData());
}
}
} // namespace gd

View File

@@ -0,0 +1,144 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
namespace gd {
class Project;
class Layout;
class String;
class EventsFunctionsExtension;
class EventsFunction;
class EventsBasedBehavior;
class EventsBasedObject;
class ArbitraryEventsWorker;
class ArbitraryEventsWorkerWithContext;
class ArbitraryEventsFunctionsWorker;
class ArbitraryObjectsWorker;
class ArbitraryEventBasedBehaviorsWorker;
class ArbitraryBehaviorSharedDataWorker;
} // namespace gd
namespace gd {
/**
* \brief Expose a subset of the project to workers.
*/
class GD_CORE_API ProjectBrowserHelper {
public:
/**
* \brief Call the specified worker on all events of the project (layout,
* external events, events functions...)
*
* This should be the preferred way to traverse all the events of a project.
*/
static void ExposeProjectEvents(gd::Project &project,
gd::ArbitraryEventsWorker &worker);
/**
* \brief Call the specified worker on all events of the project (layout,
* external events, events functions...)
*
* This should be the preferred way to traverse all the events of a project.
*/
static void ExposeProjectEvents(gd::Project &project,
gd::ArbitraryEventsWorkerWithContext &worker);
/**
* \brief Call the specified worker on all events of the project (layout and
* external events) but not events from extensions.
*
* Only use this for stats.
*/
static void
ExposeProjectEventsWithoutExtensions(gd::Project &project,
gd::ArbitraryEventsWorker &worker);
/**
* \brief Call the specified worker on all events of a layout and
* its external events.
*/
static void ExposeLayoutEvents(gd::Project &project, gd::Layout &layout,
gd::ArbitraryEventsWorker &worker);
/**
* \brief Call the specified worker on all events of a layout and
* its external events.
*/
static void ExposeLayoutEvents(gd::Project &project, gd::Layout &layout,
gd::ArbitraryEventsWorkerWithContext &worker);
/**
* \brief Call the specified worker on all events of the event-based
* behavior
*
* This should be the preferred way to traverse all the events of an events
* based behavior.
*/
static void ExposeEventsBasedBehaviorEvents(
gd::Project &project, const gd::EventsBasedBehavior &eventsBasedBehavior,
gd::ArbitraryEventsWorker &worker);
/**
* \brief Call the specified worker on all events of the event-based
* behavior.
*
* This should be the preferred way to traverse all the events of an
* event-based behavior.
*/
static void ExposeEventsBasedBehaviorEvents(
gd::Project &project, const gd::EventsBasedBehavior &eventsBasedBehavior,
gd::ArbitraryEventsWorkerWithContext &worker);
/**
* \brief Call the specified worker on all events of the event-based
* behavior.
*
* This should be the preferred way to traverse all the events of an
* event-based behavior.
*/
static void
ExposeEventsBasedObjectEvents(gd::Project &project,
const gd::EventsBasedObject &eventsBasedObject,
gd::ArbitraryEventsWorkerWithContext &worker);
/**
* \brief Call the specified worker on all ObjectContainers of the project
* (global, layouts...)
*
* This should be the preferred way to traverse all the objects of a project.
*/
static void ExposeProjectObjects(gd::Project &project,
gd::ArbitraryObjectsWorker &worker);
/**
* \brief Call the specified worker on all FunctionsContainers of the project
* (global, layouts...)
*
* This should be the preferred way to traverse all the function signatures
* of a project.
*/
static void ExposeProjectFunctions(gd::Project &project,
gd::ArbitraryEventsFunctionsWorker &worker);
/**
* \brief Call the specified worker on all EventBasedBehavior of a project.
*
* This should be the preferred way to traverse all the event-based behavior
* of a project.
*/
static void ExposeProjectEventBasedBehaviors(
gd::Project &project, gd::ArbitraryEventBasedBehaviorsWorker &worker);
/**
* \brief Call the specified worker on all SharedData of a project.
*
* This should be the preferred way to traverse all the shared data
* of a project.
*/
static void ExposeProjectSharedDatas(gd::Project &project,
gd::ArbitraryBehaviorSharedDataWorker &worker);
};
} // namespace gd

View File

@@ -0,0 +1,49 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "WholeProjectBrowser.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/Project/ArbitraryEventBasedBehaviorsWorker.h"
#include "GDCore/IDE/Project/ArbitraryEventsFunctionsWorker.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/IDE/Project/ArbitraryBehaviorSharedDataWorker.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
namespace gd {
void WholeProjectBrowser::ExposeEvents(
gd::Project &project, gd::ArbitraryEventsWorker &worker) const {
gd::ProjectBrowserHelper::ExposeProjectEvents(project, worker);
}
void WholeProjectBrowser::ExposeEvents(
gd::Project &project, gd::ArbitraryEventsWorkerWithContext &worker) const {
gd::ProjectBrowserHelper::ExposeProjectEvents(project, worker);
}
void WholeProjectBrowser::ExposeObjects(
gd::Project &project, gd::ArbitraryObjectsWorker &worker) const {
gd::ProjectBrowserHelper::ExposeProjectObjects(project, worker);
}
void WholeProjectBrowser::ExposeFunctions(
gd::Project &project, gd::ArbitraryEventsFunctionsWorker &worker) const {
gd::ProjectBrowserHelper::ExposeProjectFunctions(project, worker);
}
void WholeProjectBrowser::ExposeEventBasedBehaviors(
gd::Project &project,
gd::ArbitraryEventBasedBehaviorsWorker &worker) const {
gd::ProjectBrowserHelper::ExposeProjectEventBasedBehaviors(project, worker);
}
void WholeProjectBrowser::ExposeBehaviorSharedDatas(
gd::Project &project, gd::ArbitraryBehaviorSharedDataWorker &worker) const {
gd::ProjectBrowserHelper::ExposeProjectSharedDatas(project, worker);
}
} // namespace gd

View File

@@ -0,0 +1,90 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/IDE/ProjectBrowser.h"
namespace gd {
class Project;
class String;
class EventsFunctionsExtension;
class EventsFunction;
class EventsBasedBehavior;
class EventsBasedObject;
class ArbitraryEventsWorker;
class ArbitraryEventsWorkerWithContext;
class ArbitraryEventsFunctionsWorker;
class ArbitraryObjectsWorker;
class ArbitraryEventBasedBehaviorsWorker;
class ArbitraryBehaviorSharedDataWorker;
} // namespace gd
namespace gd {
/**
* \brief Expose the whole project to workers.
*/
class GD_CORE_API WholeProjectBrowser : public ProjectBrowser {
public:
/**
* \brief Call the specified worker on all events of the project (layout,
* external events, events functions...)
*
* This should be the preferred way to traverse all the events of a project.
*/
void ExposeEvents(gd::Project &project,
gd::ArbitraryEventsWorker &worker) const override;
/**
* \brief Call the specified worker on all events of the project (layout,
* external events, events functions...)
*
* This should be the preferred way to traverse all the events of a project.
*/
void
ExposeEvents(gd::Project &project,
gd::ArbitraryEventsWorkerWithContext &worker) const override;
/**
* \brief Call the specified worker on all ObjectContainers of the project
* (global, layouts...)
*
* This should be the preferred way to traverse all the objects of a project.
*/
void ExposeObjects(gd::Project &project,
gd::ArbitraryObjectsWorker &worker) const override;
/**
* \brief Call the specified worker on all FunctionsContainers of the project
* (global, layouts...)
*
* This should be the preferred way to traverse all the function signatures
* of a project.
*/
void ExposeFunctions(gd::Project &project,
gd::ArbitraryEventsFunctionsWorker &worker) const override;
/**
* \brief Call the specified worker on all EventBasedBehavior of a project.
*
* This should be the preferred way to traverse all the event-based behavior
* of a project.
*/
void ExposeEventBasedBehaviors(
gd::Project &project,
gd::ArbitraryEventBasedBehaviorsWorker &worker) const override;
/**
* \brief Call the specified worker on all SharedData of a project.
*
* This should be the preferred way to traverse all the shared data
* of a project.
*/
void ExposeBehaviorSharedDatas(gd::Project &project,
gd::ArbitraryBehaviorSharedDataWorker &worker) const override;
};
} // namespace gd

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,8 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_WHOLEPROJECTREFACTORER_H
#define GDCORE_WHOLEPROJECTREFACTORER_H
#pragma once
#include <set>
#include <unordered_set>
#include <vector>
@@ -12,6 +12,7 @@ namespace gd {
class Platform;
class Project;
class Layout;
class Layer;
class Object;
class String;
class EventsFunctionsExtension;
@@ -21,10 +22,14 @@ class EventsBasedBehavior;
class EventsBasedObject;
class ArbitraryEventsWorker;
class ArbitraryObjectsWorker;
class ArbitraryEventsFunctionsWorker;
class ArbitraryEventsWorkerWithContext;
class ArbitraryEventBasedBehaviorsWorker;
class ArbitraryBehaviorSharedDataWorker;
class Behavior;
class BehaviorMetadata;
class UnfilledRequiredBehaviorPropertyProblem;
class ProjectBrowser;
} // namespace gd
namespace gd {
@@ -39,54 +44,6 @@ namespace gd {
*/
class GD_CORE_API WholeProjectRefactorer {
public:
/**
* \brief Call the specified worker on all events of the project (layout,
* external events, events functions...)
*
* This should be the preferred way to traverse all the events of a project.
*/
static void ExposeProjectEvents(gd::Project& project,
gd::ArbitraryEventsWorker& worker);
/**
* \brief Call the specified worker on all events of the project (layout,
* external events, events functions...)
*
* This should be the preferred way to traverse all the events of a project.
*/
static void ExposeProjectEvents(gd::Project& project,
gd::ArbitraryEventsWorkerWithContext& worker);
/**
* \brief Call the specified worker on all events of the events based behavior
*
* This should be the preferred way to traverse all the events of an events
* based behavior.
*/
static void ExposeEventsBasedBehaviorEvents(
gd::Project& project,
const gd::EventsBasedBehavior& eventsBasedBehavior,
gd::ArbitraryEventsWorkerWithContext& worker);
/**
* \brief Call the specified worker on all events of the events based object
*
* This should be the preferred way to traverse all the events of an events
* based object.
*/
static void ExposeEventsBasedObjectEvents(
gd::Project& project,
const gd::EventsBasedObject& eventsBasedObject,
gd::ArbitraryEventsWorkerWithContext& worker);
/**
* \brief Call the specified worker on all ObjectContainers of the project
* (global, layouts...)
*
* This should be the preferred way to traverse all the objects of a project.
*/
static void ExposeProjectObjects(gd::Project& project,
gd::ArbitraryObjectsWorker& worker);
/**
* \brief Refactor the project **before** an events function extension is
@@ -102,6 +59,16 @@ class GD_CORE_API WholeProjectRefactorer {
const gd::String& oldName,
const gd::String& newName);
/**
* \brief Refactor behavior events after the extension was placed in a new
* extension.
*/
static void UpdateExtensionNameInEventsBasedBehavior(
gd::Project& project,
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::String& sourceExtensionName);
/**
* \brief Refactor the project **before** an events function is renamed.
*
@@ -302,11 +269,63 @@ class GD_CORE_API WholeProjectRefactorer {
const gd::String& oldObjectName,
const gd::String& newObjectName);
/**
* \brief Refactor the project after a layout is renamed.
*/
static void RenameLayout(gd::Project &project, const gd::String &oldName,
const gd::String &newName);
/**
* \brief Refactor the project after an external layout is renamed.
*/
static void RenameExternalLayout(gd::Project &project,
const gd::String &oldName,
const gd::String &newName);
/**
* \brief Refactor the project after external events are renamed.
*/
static void RenameExternalEvents(gd::Project &project,
const gd::String &oldName,
const gd::String &newName);
/**
* \brief Refactor the project after a layer is renamed.
*/
static void RenameLayer(gd::Project &project, gd::Layout &layout,
const gd::String &oldName, const gd::String &newName);
/**
* \brief Refactor the project after a layer effect is renamed.
*/
static void RenameLayerEffect(gd::Project &project, gd::Layout &layout,
gd::Layer &layer, const gd::String &oldName,
const gd::String &newName);
/**
* \brief Refactor the project after an object animation is renamed.
*/
static void RenameObjectAnimation(gd::Project &project, gd::Layout &layout,
gd::Object &object,
const gd::String &oldName,
const gd::String &newName);
/**
* \brief Refactor the project after an object point is renamed.
*/
static void RenameObjectPoint(gd::Project &project, gd::Layout &layout,
gd::Object &object, const gd::String &oldName,
const gd::String &newName);
/**
* \brief Refactor the project after an object effect is renamed.
*/
static void RenameObjectEffect(gd::Project &project, gd::Layout &layout,
gd::Object &object, const gd::String &oldName,
const gd::String &newName);
/**
* \brief Refactor the project after an object is renamed in a layout
*
* This will update the layout, all external layouts associated with it
* and all external events used by the layout.
* and all external events associated with it.
*/
static void ObjectOrGroupRenamedInLayout(gd::Project& project,
gd::Layout& layout,
@@ -318,7 +337,7 @@ class GD_CORE_API WholeProjectRefactorer {
* \brief Refactor the project after an object is removed in a layout
*
* This will update the layout, all external layouts associated with it
* and all external events used by the layout.
* and all external events associated with it.
*/
static void ObjectOrGroupRemovedInLayout(gd::Project& project,
gd::Layout& layout,
@@ -435,19 +454,43 @@ class GD_CORE_API WholeProjectRefactorer {
private:
static std::vector<gd::String> GetAssociatedExternalLayouts(
gd::Project& project, gd::Layout& layout);
static std::vector<gd::String>
GetAssociatedExternalLayouts(gd::Project &project,
const gd::String &layoutName);
static std::vector<gd::String>
GetAssociatedExternalEvents(gd::Project &project,
const gd::String &layoutName);
static void DoRenameEventsFunction(gd::Project& project,
const gd::EventsFunction& eventsFunction,
const gd::String& oldFullType,
const gd::String& newFullType);
const gd::String& newFullType,
const gd::ProjectBrowser& projectBrowser);
static void DoRenameBehavior(gd::Project& project,
const gd::String& oldBehaviorType,
const gd::String& newBehaviorType);
const gd::String& newBehaviorType,
const gd::ProjectBrowser& projectBrowser);
static void DoRenameObject(gd::Project& project,
const gd::String& oldObjectType,
const gd::String& newObjectType);
const gd::String& newObjectType,
const gd::ProjectBrowser& projectBrowser);
/**
* \brief Refactor the project **before** an events function extension is
* renamed.
*
* \warning Do the renaming of the specified extension after calling this.
* This is because the extension is expected to have its old name for the
* refactoring.
*/
static void RenameEventsFunctionsExtension(
gd::Project& project,
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
const gd::String& oldName,
const gd::String& newName,
const gd::ProjectBrowser& projectBrowser);
static void FindDependentBehaviorNames(
const gd::Project& project,
@@ -462,5 +505,3 @@ class GD_CORE_API WholeProjectRefactorer {
};
} // namespace gd
#endif // GDCORE_WHOLEPROJECTREFACTORER_H

View File

@@ -151,6 +151,7 @@ class GD_CORE_API AbstractEventsBasedEntity {
gd::String description;
gd::EventsFunctionsContainer eventsFunctionsContainer;
SerializableWithNameList<NamedPropertyDescriptor> propertyDescriptors;
gd::String extensionName;
};
} // namespace gd

View File

@@ -43,18 +43,10 @@ std::map<gd::String, gd::PropertyDescriptor> CustomConfigurationHelper::GetPrope
const auto &propertyName = property->GetName();
const auto &propertyType = property->GetType();
// TODO Move this into a PropertyDescriptor copy method.
auto &newProperty = behaviorProperties[propertyName]
.SetType(property->GetType())
.SetDescription(property->GetDescription())
.SetGroup(property->GetGroup())
.SetLabel(property->GetLabel())
.SetValue(property->GetValue())
.SetHidden(property->IsHidden());
// Copy the property
behaviorProperties[propertyName] = *property;
for (auto &extraInfo : property->GetExtraInfo()) {
newProperty.AddExtraInfo(extraInfo);
}
auto &newProperty = behaviorProperties[propertyName];
if (configurationContent.HasChild(propertyName)) {
if (propertyType == "String" || propertyType == "Choice" ||

View File

@@ -72,6 +72,9 @@ void EventsFunction::SerializeTo(SerializerElement& element) const {
if (isPrivate) {
element.SetBoolAttribute("private", isPrivate);
}
if (isAsync) {
element.SetBoolAttribute("async", isAsync);
}
events.SerializeTo(element.AddChild("events"));
gd::String functionTypeStr = "Action";
@@ -115,6 +118,7 @@ void EventsFunction::UnserializeFrom(gd::Project& project,
group = element.GetStringAttribute("group");
getterName = element.GetStringAttribute("getterName");
isPrivate = element.GetBoolAttribute("private");
isAsync = element.GetBoolAttribute("async");
events.UnserializeFrom(project, element.GetChild("events"));
gd::String functionTypeStr = element.GetStringAttribute("functionType");

View File

@@ -211,6 +211,19 @@ class GD_CORE_API EventsFunction {
return *this;
}
/**
* \brief Returns true if the function is async.
*/
bool IsAsync() const { return isAsync; }
/**
* \brief Sets the asycronity of the function.
*/
EventsFunction& SetAsync(bool _isAsync) {
isAsync = _isAsync;
return *this;
}
/**
* \brief Return the events.
*/
@@ -291,6 +304,7 @@ class GD_CORE_API EventsFunction {
mutable std::vector<gd::ParameterMetadata> actionWithOperationParameters;
gd::ObjectGroupsContainer objectGroups;
bool isPrivate = false;
bool isAsync = false;
};
} // namespace gd

View File

@@ -507,6 +507,44 @@ gd::String GD_CORE_API GetTypeOfObject(const gd::ObjectsContainer& project,
return type;
}
bool GD_CORE_API HasBehaviorInObjectOrGroup(const gd::ObjectsContainer &project,
const gd::ObjectsContainer &layout,
const gd::String &objectOrGroupName,
const gd::String &behaviorName,
bool searchInGroups) {
// Search in objects
if (layout.HasObjectNamed(objectOrGroupName)) {
return layout.GetObject(objectOrGroupName).HasBehaviorNamed(behaviorName);
}
if (project.HasObjectNamed(objectOrGroupName)) {
return project.GetObject(objectOrGroupName).HasBehaviorNamed(behaviorName);
}
// Search in groups
const gd::ObjectsContainer *container;
if (layout.GetObjectGroups().Has(objectOrGroupName)) {
container = &layout;
} else if (project.GetObjectGroups().Has(objectOrGroupName)) {
container = &project;
} else {
return false;
}
const vector<gd::String> &groupsObjects =
container->GetObjectGroups().Get(objectOrGroupName).GetAllObjectsNames();
// Empty groups don't contain any behavior.
if (groupsObjects.empty()) {
return false;
}
// Check that all objects have the same type.
for (auto &&object : groupsObjects) {
if (!HasBehaviorInObjectOrGroup(project, layout, object, behaviorName,
false)) {
return false;
}
}
return true;
}
gd::String GD_CORE_API GetTypeOfBehavior(const gd::ObjectsContainer& project,
const gd::ObjectsContainer& layout,
gd::String name,

View File

@@ -442,7 +442,14 @@ gd::String GD_CORE_API GetTypeOfObject(const ObjectsContainer& game,
const ObjectsContainer& layout,
gd::String objectName,
bool searchInGroups = true);
/**
* \brief Check if an object or all object of a group has a behavior.
*/
bool GD_CORE_API HasBehaviorInObjectOrGroup(const gd::ObjectsContainer &project,
const gd::ObjectsContainer &layout,
const gd::String &objectOrGroupName,
const gd::String &behaviorName,
bool searchInGroups = true);
/**
* \brief Get a type from a behavior name
* @return Type of the behavior.

View File

@@ -11,7 +11,7 @@
namespace gd {
LoadingScreen::LoadingScreen()
: showGDevelopSplash(true),
: showGDevelopLogoDuringLoadingScreen(true),
gdevelopLogoStyle("light"),
backgroundImageResourceName(""),
backgroundColor(0),
@@ -27,16 +27,18 @@ LoadingScreen::LoadingScreen()
progressBarColor(0xFFFFFF){};
void LoadingScreen::SerializeTo(SerializerElement& element) const {
element.SetAttribute("showGDevelopSplash", showGDevelopSplash);
element.SetAttribute("gdevelopLogoStyle",
gdevelopLogoStyle);
element.SetAttribute("showGDevelopSplash",
showGDevelopLogoDuringLoadingScreen);
element.SetAttribute("gdevelopLogoStyle", gdevelopLogoStyle);
element.SetAttribute("backgroundImageResourceName",
backgroundImageResourceName);
element.SetAttribute("backgroundColor", backgroundColor);
element.SetAttribute("backgroundFadeInDuration", backgroundFadeInDuration);
element.SetAttribute("minDuration", minDuration);
element.SetAttribute("logoAndProgressFadeInDuration", logoAndProgressFadeInDuration);
element.SetAttribute("logoAndProgressLogoFadeInDelay", logoAndProgressLogoFadeInDelay);
element.SetAttribute("logoAndProgressFadeInDuration",
logoAndProgressFadeInDuration);
element.SetAttribute("logoAndProgressLogoFadeInDelay",
logoAndProgressLogoFadeInDelay);
element.SetAttribute("showProgressBar", showProgressBar);
element.SetAttribute("progressBarMinWidth", progressBarMinWidth);
element.SetAttribute("progressBarMaxWidth", progressBarMaxWidth);
@@ -46,21 +48,24 @@ void LoadingScreen::SerializeTo(SerializerElement& element) const {
}
void LoadingScreen::UnserializeFrom(const SerializerElement& element) {
showGDevelopSplash = element.GetBoolAttribute("showGDevelopSplash", true);
gdevelopLogoStyle =
element.GetStringAttribute("gdevelopLogoStyle", "light");
showGDevelopLogoDuringLoadingScreen =
element.GetBoolAttribute("showGDevelopSplash", true);
gdevelopLogoStyle = element.GetStringAttribute("gdevelopLogoStyle", "light");
backgroundImageResourceName =
element.GetStringAttribute("backgroundImageResourceName");
backgroundColor = element.GetIntAttribute("backgroundColor", 0);
backgroundFadeInDuration =
element.GetDoubleAttribute("backgroundFadeInDuration", 0.2);
minDuration = element.GetDoubleAttribute("minDuration", 1.5);
logoAndProgressFadeInDuration = element.GetDoubleAttribute("logoAndProgressFadeInDuration", 0.2);
logoAndProgressLogoFadeInDelay = element.GetDoubleAttribute("logoAndProgressLogoFadeInDelay", 0.2);
logoAndProgressFadeInDuration =
element.GetDoubleAttribute("logoAndProgressFadeInDuration", 0.2);
logoAndProgressLogoFadeInDelay =
element.GetDoubleAttribute("logoAndProgressLogoFadeInDelay", 0.2);
showProgressBar = element.GetBoolAttribute("showProgressBar", true);
progressBarMinWidth = element.GetDoubleAttribute("progressBarMinWidth", 40);
progressBarMaxWidth = element.GetDoubleAttribute("progressBarMaxWidth", 200);
progressBarWidthPercent = element.GetDoubleAttribute("progressBarWidthPercent", 30);
progressBarWidthPercent =
element.GetDoubleAttribute("progressBarWidthPercent", 30);
progressBarHeight = element.GetDoubleAttribute("progressBarHeight", 20);
progressBarColor = element.GetIntAttribute("progressBarColor", 0xFFFFFF);
}

View File

@@ -29,13 +29,13 @@ class GD_CORE_API LoadingScreen {
* \brief Return true if the GDevelop logo should be shown while loading
* assets.
*/
bool IsGDevelopSplashShown() const { return showGDevelopSplash; };
bool IsGDevelopLogoShownDuringLoadingScreen() const { return showGDevelopLogoDuringLoadingScreen; };
/**
* \brief Set if the GDevelop logo should be shown while loading assets.
*/
LoadingScreen& ShowGDevelopSplash(bool show) {
showGDevelopSplash = show;
LoadingScreen& ShowGDevelopLogoDuringLoadingScreen(bool show) {
showGDevelopLogoDuringLoadingScreen = show;
return *this;
};
@@ -157,7 +157,7 @@ class GD_CORE_API LoadingScreen {
///@}
private:
bool showGDevelopSplash;
bool showGDevelopLogoDuringLoadingScreen;
gd::String gdevelopLogoStyle;
gd::String backgroundImageResourceName;
int backgroundColor;

View File

@@ -7,6 +7,7 @@
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
#include <vector>
#include <algorithm>
namespace gd {
@@ -22,6 +23,49 @@ gd::MeasurementUnit MeasurementUnit::pixelAcceleration =
CreatePixelAcceleration();
gd::MeasurementUnit MeasurementUnit::newton = CreateNewton();
gd::MeasurementUnit MeasurementUnit::angularSpeed = CreateAngularSpeed();
std::vector<const gd::MeasurementUnit*> MeasurementUnit::defaultMeasurementUnits;
const std::vector<const gd::MeasurementUnit*> &
MeasurementUnit::GetDefaultMeasurementUnits() {
if (defaultMeasurementUnits.size() == 0) {
defaultMeasurementUnits.push_back(&undefined);
defaultMeasurementUnits.push_back(&dimensionless);
defaultMeasurementUnits.push_back(&degreeAngle);
defaultMeasurementUnits.push_back(&second);
defaultMeasurementUnits.push_back(&pixel);
defaultMeasurementUnits.push_back(&pixelSpeed);
defaultMeasurementUnits.push_back(&pixelAcceleration);
defaultMeasurementUnits.push_back(&angularSpeed);
defaultMeasurementUnits.push_back(&newton);
}
return defaultMeasurementUnits;
}
std::size_t MeasurementUnit::GetDefaultMeasurementUnitsCount() {
return GetDefaultMeasurementUnits().size();
}
const gd::MeasurementUnit &
MeasurementUnit::GetDefaultMeasurementUnitAtIndex(std::size_t index) {
return *GetDefaultMeasurementUnits().at(index);
}
bool MeasurementUnit::HasDefaultMeasurementUnitNamed(const gd::String &name) {
auto units = GetDefaultMeasurementUnits();
return std::find_if(units.begin(), units.end(),
[name](const gd::MeasurementUnit *unit) -> bool {
return unit->GetName() == name;
}) != units.end();
}
const gd::MeasurementUnit &
MeasurementUnit::GetDefaultMeasurementUnitByName(const gd::String &name) {
auto units = GetDefaultMeasurementUnits();
return **std::find_if(units.begin(), units.end(),
[name](const gd::MeasurementUnit *unit) -> bool {
return unit->GetName() == name;
});
}
void MeasurementUnit::ApplyTranslation() {
undefined = CreateUndefined();
@@ -33,6 +77,7 @@ void MeasurementUnit::ApplyTranslation() {
pixelAcceleration = CreatePixelAcceleration();
newton = CreateNewton();
angularSpeed = CreateAngularSpeed();
defaultMeasurementUnits.clear();
}
} // namespace gd

View File

@@ -74,31 +74,40 @@ public:
return elements.at(elementIndex).GetBaseUnit();
}
bool IsUndefined() const { return this == &gd::MeasurementUnit::undefined; }
bool IsUndefined() const {
return this == &gd::MeasurementUnit::undefined || name == "Undefined";
}
static void ApplyTranslation();
static gd::MeasurementUnit &GetUndefined() { return undefined; }
static const gd::MeasurementUnit &GetUndefined() { return undefined; }
static gd::MeasurementUnit &GetDimensionless() { return dimensionless; }
static const gd::MeasurementUnit &GetDimensionless() { return dimensionless; }
static gd::MeasurementUnit &GetDegreeAngle() { return degreeAngle; }
static const gd::MeasurementUnit &GetDegreeAngle() { return degreeAngle; }
static gd::MeasurementUnit &GetSecond() { return second; }
static const gd::MeasurementUnit &GetSecond() { return second; }
static gd::MeasurementUnit &GetPixel() { return pixel; }
static const gd::MeasurementUnit &GetPixel() { return pixel; }
static gd::MeasurementUnit &GetPixelSpeed() { return pixelSpeed; }
static const gd::MeasurementUnit &GetPixelSpeed() { return pixelSpeed; }
static gd::MeasurementUnit &GetPixelAcceleration() {
static const gd::MeasurementUnit &GetPixelAcceleration() {
return pixelAcceleration;
}
static gd::MeasurementUnit &GetAngularSpeed() { return angularSpeed; }
static const gd::MeasurementUnit &GetAngularSpeed() { return angularSpeed; }
static gd::MeasurementUnit &GetNewton() { return newton; }
static const gd::MeasurementUnit &GetNewton() { return newton; }
static const std::vector<const gd::MeasurementUnit*> &GetDefaultMeasurementUnits();
static std::size_t GetDefaultMeasurementUnitsCount();
static const gd::MeasurementUnit &GetDefaultMeasurementUnitAtIndex(std::size_t index);
static bool HasDefaultMeasurementUnitNamed(const gd::String &name);
static const gd::MeasurementUnit &GetDefaultMeasurementUnitByName(const gd::String &name);
private:
static std::vector<const gd::MeasurementUnit*> defaultMeasurementUnits;
static gd::MeasurementUnit undefined;
static gd::MeasurementUnit dimensionless;
static gd::MeasurementUnit degreeAngle;

View File

@@ -636,6 +636,7 @@ void Project::UnserializeFrom(const SerializerElement& element) {
platformSpecificAssets.UnserializeFrom(
propElement.GetChild("platformSpecificAssets"));
loadingScreen.UnserializeFrom(propElement.GetChild("loadingScreen"));
watermark.UnserializeFrom(propElement.GetChild("watermark"));
useExternalSourceFiles =
propElement.GetBoolAttribute("useExternalSourceFiles");
@@ -646,6 +647,13 @@ void Project::UnserializeFrom(const SerializerElement& element) {
for (std::size_t i = 0; i < authorIdsElement.GetChildrenCount(); ++i) {
authorIds.push_back(authorIdsElement.GetChild(i).GetStringValue());
}
authorUsernames.clear();
auto& authorUsernamesElement = propElement.GetChild("authorUsernames");
authorUsernamesElement.ConsiderAsArray();
for (std::size_t i = 0; i < authorUsernamesElement.GetChildrenCount(); ++i) {
authorUsernames.push_back(
authorUsernamesElement.GetChild(i).GetStringValue());
}
categories.clear();
auto& categoriesElement = propElement.GetChild("categories");
@@ -875,6 +883,7 @@ void Project::SerializeTo(SerializerElement& element) const {
platformSpecificAssets.SerializeTo(
propElement.AddChild("platformSpecificAssets"));
loadingScreen.SerializeTo(propElement.AddChild("loadingScreen"));
watermark.SerializeTo(propElement.AddChild("watermark"));
propElement.SetAttribute("useExternalSourceFiles", useExternalSourceFiles);
auto& authorIdsElement = propElement.AddChild("authorIds");
@@ -882,6 +891,11 @@ void Project::SerializeTo(SerializerElement& element) const {
for (const auto& authorId : authorIds) {
authorIdsElement.AddChild("").SetStringValue(authorId);
}
auto& authorUsernamesElement = propElement.AddChild("authorUsernames");
authorUsernamesElement.ConsiderAsArray();
for (const auto& authorUsername : authorUsernames) {
authorUsernamesElement.AddChild("").SetStringValue(authorUsername);
}
auto& categoriesElement = propElement.AddChild("categories");
categoriesElement.ConsiderAsArray();
@@ -977,7 +991,7 @@ bool Project::ValidateName(const gd::String& name) {
}
void Project::ExposeResources(gd::ArbitraryResourceWorker& worker) {
// See also gd::WholeProjectRefactorer::ExposeProjectEvents for a method that
// See also gd::ProjectBrowserHelper::ExposeProjectEvents for a method that
// traverse the whole project (this time for events) and ExposeProjectEffects
// (this time for effects). Ideally, this method could be moved outside of
// gd::Project.
@@ -1097,6 +1111,7 @@ void Project::Init(const gd::Project& game) {
author = game.author;
authorIds = game.authorIds;
authorUsernames = game.authorUsernames;
isPlayableWithKeyboard = game.isPlayableWithKeyboard;
isPlayableWithGamepad = game.isPlayableWithGamepad;
isPlayableWithMobile = game.isPlayableWithMobile;
@@ -1107,6 +1122,7 @@ void Project::Init(const gd::Project& game) {
latestCompilationDirectory = game.latestCompilationDirectory;
platformSpecificAssets = game.platformSpecificAssets;
loadingScreen = game.loadingScreen;
watermark = game.watermark;
objectGroups = game.objectGroups;
extensionProperties = game.extensionProperties;

View File

@@ -11,6 +11,7 @@
#include "GDCore/Project/ExtensionProperties.h"
#include "GDCore/Project/LoadingScreen.h"
#include "GDCore/Project/Watermark.h"
#include "GDCore/Project/ObjectGroupsContainer.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/PlatformSpecificAssets.h"
@@ -120,6 +121,16 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::vector<gd::String>& GetAuthorIds() { return authorIds; };
/**
* \brief Get the author usernames of the project.
*/
const std::vector<gd::String>& GetAuthorUsernames() const { return authorUsernames; };
/**
* \brief Get the author usernames of the project, to modify them (non-const).
*/
std::vector<gd::String>& GetAuthorUsernames() { return authorUsernames; };
/**
* Define the project as playable with a keyboard.
* \param enable True to define the project as playable with a keyboard.
@@ -256,6 +267,16 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
const gd::LoadingScreen& GetLoadingScreen() const { return loadingScreen; }
/**
* \brief Return a reference to watermark setup for the project
*/
gd::Watermark& GetWatermark() { return watermark; }
/**
* \brief Return a reference to watermark setup for the project
*/
const gd::Watermark& GetWatermark() const { return watermark; }
/**
* Change game's main window default width.
*
@@ -1043,6 +1064,8 @@ class GD_CORE_API Project : public ObjectsContainer {
gd::String author; ///< Game author name, for publishing purpose.
std::vector<gd::String>
authorIds; ///< Game author ids, from GDevelop users DB.
std::vector<gd::String>
authorUsernames; ///< Game author usernames, from GDevelop users DB.
std::vector<gd::String>
categories; ///< Game categories
bool isPlayableWithKeyboard; ///< The project is playable with a keyboard.
@@ -1062,6 +1085,7 @@ class GD_CORE_API Project : public ObjectsContainer {
currentPlatform; ///< The platform being used to edit the project.
gd::PlatformSpecificAssets platformSpecificAssets;
gd::LoadingScreen loadingScreen;
gd::Watermark watermark;
std::vector<std::unique_ptr<gd::ExternalEvents> >
externalEvents; ///< List of all externals events
ExtensionProperties

View File

@@ -17,6 +17,9 @@ PropertyDescriptor::~PropertyDescriptor() {}
void PropertyDescriptor::SerializeTo(SerializerElement& element) const {
element.AddChild("value").SetStringValue(currentValue);
element.AddChild("type").SetStringValue(type);
if (type == "Number" && !measurementUnit.IsUndefined()) {
element.AddChild("unit").SetStringValue(measurementUnit.GetName());
}
element.AddChild("label").SetStringValue(label);
element.AddChild("description").SetStringValue(description);
element.AddChild("group").SetStringValue(group);
@@ -32,6 +35,14 @@ void PropertyDescriptor::SerializeTo(SerializerElement& element) const {
void PropertyDescriptor::UnserializeFrom(const SerializerElement& element) {
currentValue = element.GetChild("value").GetStringValue();
type = element.GetChild("type").GetStringValue();
if (type == "Number") {
gd::String unitName = element.GetChild("unit").GetStringValue();
measurementUnit =
gd::MeasurementUnit::HasDefaultMeasurementUnitNamed(unitName)
? measurementUnit =
gd::MeasurementUnit::GetDefaultMeasurementUnitByName(unitName)
: gd::MeasurementUnit::GetUndefined();
}
label = element.GetChild("label").GetStringValue();
description = element.GetChild("description").GetStringValue();
group = element.GetChild("group").GetStringValue();

View File

@@ -0,0 +1,24 @@
/*
* GDevelop Core
* Copyright 2008-2018 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "Watermark.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
Watermark::Watermark() : showWatermark(true), placement("bottom-left"){};
void Watermark::SerializeTo(SerializerElement& element) const {
element.SetAttribute("showWatermark", showWatermark);
element.SetAttribute("placement", placement);
}
void Watermark::UnserializeFrom(const SerializerElement& element) {
showWatermark = element.GetBoolAttribute("showWatermark", true);
placement = element.GetStringAttribute("placement", "bottom-left");
}
} // namespace gd

View File

@@ -0,0 +1,70 @@
/*
* GDevelop Core
* Copyright 2008-2018 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_WATERMARK_H
#define GDCORE_WATERMARK_H
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
}
namespace gd {
/**
* \brief Describe the content and set up of the watermark
*
* \see gd::Watermark
*
* \ingroup PlatformDefinition
*/
class GD_CORE_API Watermark {
public:
Watermark();
virtual ~Watermark(){};
/**
* \brief Return true if the GDevelop watermark should be shown after
* the game has loaded its assets.
*/
bool IsGDevelopWatermarkShown() const { return showWatermark; };
/**
* \brief Set if the GDevelop watermark should be shown after the game
* has loaded its assets.
*/
Watermark& ShowGDevelopWatermark(bool show) {
showWatermark = show;
return *this;
};
const gd::String& GetPlacement() const { return placement; };
Watermark& SetPlacement(const gd::String& value) {
placement = value;
return *this;
}
/** \name Saving and loading
*/
///@{
/**
* \brief Serialize the watermark setup.
*/
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the watermark setup.
*/
void UnserializeFrom(const SerializerElement& element);
///@}
private:
bool showWatermark;
gd::String placement;
};
} // namespace gd
#endif // GDCORE_WATERMARK_H

View File

@@ -13,6 +13,8 @@
#include "GDCore/Project/Project.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Extensions/Metadata/ParameterOptions.h"
#include "catch.hpp"
// TODO Remove these 2 classes and write the test with events based behaviors.
@@ -122,6 +124,14 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
.AddParameter("expression", _("Number parameter"))
.SetRequiresBaseObjectCapability("effect")
.SetFunctionName("getSomethingRequiringEffectCapability");
baseObject
.AddExpression("GetFromBaseExpression",
"This works on any object.",
"",
"",
"")
.AddParameter("object", _("Object"), "")
.SetFunctionName("getFromBaseExpression");
// Create an extension with various stuff inside.
std::shared_ptr<gd::PlatformExtension> extension =
@@ -281,6 +291,21 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
.AddParameter("objectPtr", _("Object parameter"))
.SetFunctionName("getObjectStringWith2ObjectParam");
// Actions and expressions with several parameter types.
object
.AddAction("SetAnimationName", _("Change the animation (by name)"),
_("Change the animation of the object, using the name of the "
"animation."),
_("Set animation of _PARAM0_ to _PARAM1_"),
_("Animations and images"), "", "")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name"));
object
.AddExpression("AnimationFrameCount", _("Animation frame count"),
_("Return the number of frame in the animation."),
_("Animations and images"), "")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name"));
{
auto& behavior =
extension->AddBehavior("MyBehavior",
@@ -381,6 +406,65 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
.AddUnsupportedBaseObjectCapability("effect");
}
// Actions and expressions with several parameter types.
{
extension
->AddAction("CreateObjectsFromExternalLayout",
_("Create objects from an external layout"),
_("Create objects from an external layout."),
_("Create objects from the external layout named _PARAM1_"),
"", "", "")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("externalLayoutName", _("Name of the external layout"))
.AddParameter("expression", _("X position of the origin"), "", true)
.SetDefaultValue("0")
.AddParameter("expression", _("Y position of the origin"), "", true)
.SetDefaultValue("0");
extension
->AddAction("Scene", _("Change the scene"),
_("Stop this scene and start the specified one instead."),
_("Change to scene _PARAM1_"), "", "", "")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Name of the new scene"))
.AddParameter("yesorno", _("Stop any other paused scenes?"))
.SetDefaultValue("true");
extension
->AddExpressionAndConditionAndAction(
"number", "CameraCenterX", _("Camera center X position"),
_("the X position of the center of a camera"),
_("the X position of camera _PARAM4_ (layer: _PARAM3_)"), "", "")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"");
extension
->AddAction("EnableLayerEffect", _("Enable layer effect"),
_("Enable an effect on a layer"),
_("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"),
_("Effects"), "", "")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("yesorno", _("Enable"), "", true);
extension
->AddExpression(
"LayerEffectParameter",
_("Effect parameter (number)"),
_("Return the value of a parameter of an effect."),
_("Effects"),
"")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Parameter name"));
}
platform.AddExtension(commonInstructionsExtension);
platform.AddExtension(baseObjectExtension);
platform.AddExtension(extension);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "GDCore/IDE/Events/InstructionsCountEvaluator.h"
#include <algorithm>
#include "DummyPlatform.h"
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "catch.hpp"
namespace {
TEST_CASE("InstructionsCountEvaluator", "[events]") {
SECTION("Can count 1 action in a layout") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &layout1 = project.InsertNewLayout("Layout1", 0);
// Add an event with an action.
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("MyExtension::DoSomething");
instruction.SetParametersCount(1);
event.GetActions().Insert(instruction);
layout1.GetEvents().InsertEvent(event);
REQUIRE(gd::InstructionsCountEvaluator::ScanProject(project) == 1);
}
}
} // namespace

View File

@@ -15,6 +15,7 @@
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/IDE/Project/ProjectResourcesAdder.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
@@ -51,7 +52,7 @@ TEST_CASE("InstructionsParameterMover", "[common][events]") {
gd::InstructionsParameterMover mover(
project, "MyExtension::DoSomething", 0, 2);
gd::WholeProjectRefactorer::ExposeProjectEvents(project, mover);
gd::ProjectBrowserHelper::ExposeProjectEvents(project, mover);
REQUIRE(insertedInstruction.GetParameter(0).GetPlainString() == "Param2");
REQUIRE(insertedInstruction.GetParameter(1).GetPlainString() == "Param3");
REQUIRE(insertedInstruction.GetParameter(2).GetPlainString() == "Param1");
@@ -60,7 +61,7 @@ TEST_CASE("InstructionsParameterMover", "[common][events]") {
gd::InstructionsParameterMover mover(
project, "MyExtension::DoSomething", 0, 99);
gd::WholeProjectRefactorer::ExposeProjectEvents(project, mover);
gd::ProjectBrowserHelper::ExposeProjectEvents(project, mover);
REQUIRE(insertedInstruction.GetParameter(0).GetPlainString() == "Param2");
REQUIRE(insertedInstruction.GetParameter(1).GetPlainString() == "Param3");
REQUIRE(insertedInstruction.GetParameter(2).GetPlainString() == "Param1");
@@ -69,7 +70,7 @@ TEST_CASE("InstructionsParameterMover", "[common][events]") {
gd::InstructionsParameterMover mover(
project, "MyExtension::DoSomething", 99, 2);
gd::WholeProjectRefactorer::ExposeProjectEvents(project, mover);
gd::ProjectBrowserHelper::ExposeProjectEvents(project, mover);
REQUIRE(insertedInstruction.GetParameter(0).GetPlainString() == "Param1");
REQUIRE(insertedInstruction.GetParameter(1).GetPlainString() == "Param2");
REQUIRE(insertedInstruction.GetParameter(2).GetPlainString() == "Param3");

View File

@@ -30,6 +30,9 @@
#include "GDCore/Project/Variable.h"
#include "catch.hpp"
// TODO Extract test data in another file to allow to read them side by side
// with the test cases more easily.
// TODO EBO Add a test where a child is removed form the EventsBasedObject
// and check the configuration still gives access to other child configuration.
namespace {
@@ -53,6 +56,12 @@ GetEventFirstActionFirstParameterString(const gd::BaseEvent &event) {
return actions.Get(0).GetParameter(0).GetPlainString();
}
bool
AreActionsEmpty(const gd::BaseEvent &event) {
auto &actions = EnsureStandardEvent(event).GetActions();
return actions.IsEmpty();
}
const gd::String &GetEventFirstConditionType(const gd::BaseEvent &event) {
auto &conditions = EnsureStandardEvent(event).GetConditions();
REQUIRE(conditions.IsEmpty() == false);
@@ -75,6 +84,8 @@ enum TestEvent {
FreeActionWithOperator,
FreeFunctionWithObjects,
FreeFunctionWithObjectExpression,
FreeFunctionWithGroup,
FreeFunctionWithObjectExpressionOnGroup,
BehaviorAction,
BehaviorPropertyAction,
@@ -104,21 +115,49 @@ enum TestEvent {
ObjectActionWithOperator,
};
const std::vector<const gd::EventsList *> GetEventsLists(gd::Project &project) {
const std::vector<const gd::EventsList *> GetEventsListsAssociatedToScene(gd::Project &project) {
std::vector<const gd::EventsList *> eventLists;
auto &scene = project.GetLayout("Scene").GetEvents();
auto &externalEvents =
project.GetExternalEvents("ExternalEvents").GetEvents();
eventLists.push_back(&scene);
eventLists.push_back(&externalEvents);
return eventLists;
}
const std::vector<const gd::EventsList *> GetEventsListsNotAssociatedToScene(gd::Project &project) {
std::vector<const gd::EventsList *> eventLists;
auto &eventsExtension = project.GetEventsFunctionsExtension("MyEventsExtension");
auto &objectFunctionEvents =
project.GetEventsFunctionsExtension("MyEventsExtension")
eventsExtension
.GetEventsBasedObjects()
.Get("MyOtherEventsBasedObject")
.GetEventsFunctions()
.GetEventsFunction("MyObjectEventsFunction")
.GetEvents();
eventLists.push_back(&scene);
eventLists.push_back(&externalEvents);
auto &behaviorFunctionEvents =
eventsExtension.GetEventsBasedBehaviors()
.Get("MyOtherEventsBasedBehavior")
.GetEventsFunctions()
.GetEventsFunction("MyBehaviorEventsFunction")
.GetEvents();
auto &freeFunctionEvents =
eventsExtension.GetEventsFunction("MyOtherEventsFunction").GetEvents();
eventLists.push_back(&objectFunctionEvents);
eventLists.push_back(&behaviorFunctionEvents);
eventLists.push_back(&freeFunctionEvents);
return eventLists;
}
const std::vector<const gd::EventsList *> GetEventsLists(gd::Project &project) {
std::vector<const gd::EventsList *> eventLists;
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
eventLists.push_back(eventsList);
}
for (auto *eventsList : GetEventsListsNotAssociatedToScene(project)) {
eventLists.push_back(eventsList);
}
return eventLists;
}
@@ -271,6 +310,38 @@ const void SetupEvents(gd::EventsList &eventList) {
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != FreeFunctionWithGroup) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to a group.
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyExtension::DoSomethingWithObjects");
action.SetParametersCount(2);
action.SetParameter(0, gd::Expression("GroupWithMyBehavior"));
action.SetParameter(1, gd::Expression("MyCustomObject"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != FreeFunctionWithObjectExpressionOnGroup) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event referring to a group in an expression.
{
gd::StandardEvent event;
gd::Instruction action;
action.SetType("MyExtension::DoSomething");
action.SetParametersCount(1);
action.SetParameter(
0,
gd::Expression(
"GroupWithMyBehavior.GetObjectNumber()"));
event.GetActions().Insert(action);
eventList.InsertEvent(event);
}
}
// Add some events based behavior usages in events
@@ -807,7 +878,7 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("OtherObject")
.SetName("ObjectWithMyBehavior")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(
@@ -815,6 +886,8 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetName("OtherBehavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
auto &group = behaviorAction.GetObjectGroups().InsertNew("GroupWithMyBehavior");
group.AddObject("ObjectWithMyBehavior");
auto &behaviorExpression =
behaviorEventsFunctions
@@ -930,6 +1003,48 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetType("Number");
}
// Add another events based behavior that uses previously defined events based
// object and behavior.
{
auto &eventsBasedBehavior =
eventsExtension.GetEventsBasedBehaviors().InsertNew(
"MyOtherEventsBasedBehavior", 0);
eventsBasedBehavior.SetFullName("My events based behavior");
eventsBasedBehavior.SetDescription("An events based behavior for test");
eventsBasedBehavior.SetObjectType("MyEventsExtension::MyEventsBasedObject");
// Add functions, and parameters that should be there by convention.
auto &behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
auto &behaviorAction = behaviorEventsFunctions.InsertNewEventsFunction(
"MyBehaviorEventsFunction", 0);
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Object")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("Behavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
// Define the same objects as in the layout to be consistent with events.
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("ObjectWithMyBehavior")
.SetType("object")
.SetExtraInfo("MyExtension::Sprite"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("MyBehavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
behaviorAction.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("MyCustomObject")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
}
// Add an other events based object that uses previously defined events based
// object and behavior.
{
@@ -953,6 +1068,8 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
auto &childObject = eventsBasedObject.InsertNewObject(
project, "MyExtension::Sprite", "ObjectWithMyBehavior", 0);
childObject.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
auto &group = eventsBasedObject.GetObjectGroups().InsertNew("GroupWithMyBehavior");
group.AddObject(childObject.GetName());
eventsBasedObject.InsertNewObject(
project, "MyEventsExtension::MyEventsBasedObject", "MyCustomObject", 1);
@@ -1001,6 +1118,32 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.SetGetterName("MyEventsFunctionExpressionAndCondition");
}
// Add another free function that uses previously defined events based
// object and behavior.
{
// Add functions, and parameters that should be there by convention.
auto &action =
eventsExtension.InsertNewEventsFunction("MyOtherEventsFunction", 0);
// Define the same objects as in the layout to be consistent with events.
action.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("ObjectWithMyBehavior")
.SetType("object")
.SetExtraInfo("MyExtension::Sprite"));
action.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("MyBehavior")
.SetType("behavior")
.SetExtraInfo("MyEventsExtension::MyEventsBasedBehavior"));
action.GetParameters().push_back(
gd::ParameterMetadata()
.SetName("MyCustomObject")
.SetType("object")
.SetExtraInfo("MyEventsExtension::MyEventsBasedObject"));
auto &group = action.GetObjectGroups().InsertNew("GroupWithMyBehavior");
group.AddObject("ObjectWithMyBehavior");
}
// Add some usages in events
{
auto &layout = project.InsertNewLayout("Scene", 0);
@@ -1011,6 +1154,8 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
auto &object = layout.InsertNewObject(project, "MyExtension::Sprite",
"ObjectWithMyBehavior", 0);
object.AddNewBehavior(project, "MyEventsExtension::MyEventsBasedBehavior", "MyBehavior");
auto &group = layout.GetObjectGroups().InsertNew("GroupWithMyBehavior", 0);
group.AddObject("ObjectWithMyBehavior");
auto &globalObject = project.InsertNewObject(
project, "MyExtension::Sprite", "GlobalObjectWithMyBehavior", 0);
@@ -1030,6 +1175,13 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
.GetEventsFunctions()
.GetEventsFunction("MyObjectEventsFunction")
.GetEvents());
SetupEvents(eventsExtension.GetEventsBasedBehaviors()
.Get("MyOtherEventsBasedBehavior")
.GetEventsFunctions()
.GetEventsFunction("MyBehaviorEventsFunction")
.GetEvents());
SetupEvents(eventsExtension.GetEventsFunction("MyOtherEventsFunction")
.GetEvents());
}
return eventsExtension;
@@ -1142,6 +1294,29 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(externalLayout2.GetInitialInstances().HasInstancesOfObject(
"GlobalObject1") == false);
}
SECTION("Events") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &layout = project.GetLayout("Scene");
// Trigger the refactoring after removing an object
gd::WholeProjectRefactorer::ObjectOrGroupRemovedInLayout(
project, layout, "ObjectWithMyBehavior", /* isObjectGroup=*/false);
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
// Check actions with the object in parameters have been removed.
REQUIRE(
AreActionsEmpty(eventsList->GetEvent(FreeFunctionWithObjects)));
// Check actions with the object in expressions have been removed.
REQUIRE(AreActionsEmpty(
eventsList->GetEvent(FreeFunctionWithObjectExpression)));
}
}
}
SECTION("Object renamed (in layout)") {
@@ -1260,7 +1435,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(externalLayout2.GetInitialInstances().HasInstancesOfObject(
"GlobalObject3") == true);
}
SECTION("Events") {
gd::Project project;
gd::Platform platform;
@@ -1271,57 +1446,145 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
// Trigger the refactoring after the renaming of an object
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInLayout(
project, layout, "ObjectWithMyBehavior", "RenamedObjectWithMyBehavior",
project, layout, "ObjectWithMyBehavior",
"RenamedObjectWithMyBehavior",
/* isObjectGroup=*/false);
// Check object name has been renamed in action parameters.
REQUIRE(GetEventFirstActionFirstParameterString(
layout.GetEvents().GetEvent(FreeFunctionWithObjects)) ==
"RenamedObjectWithMyBehavior");
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
// Check object name has been renamed in action parameters.
REQUIRE(GetEventFirstActionFirstParameterString(eventsList->GetEvent(
FreeFunctionWithObjects)) == "RenamedObjectWithMyBehavior");
// Check object name has been renamed in expressions.
REQUIRE(GetEventFirstActionFirstParameterString(
layout.GetEvents().GetEvent(FreeFunctionWithObjectExpression)) ==
// Check object name has been renamed in expressions.
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(FreeFunctionWithObjectExpression)) ==
"RenamedObjectWithMyBehavior.GetObjectNumber()");
}
}
}
SECTION("Group deleted (in layout)") {
SECTION("Events") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &layout = project.GetLayout("Scene");
// Trigger the refactoring after removing a group
gd::WholeProjectRefactorer::ObjectOrGroupRemovedInLayout(
project, layout, "GroupWithMyBehavior", /* isObjectGroup=*/true);
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
// Check actions with the group in parameters have been removed.
REQUIRE(AreActionsEmpty(eventsList->GetEvent(FreeFunctionWithGroup)));
// Check actions with the group in expressions have been removed.
REQUIRE(AreActionsEmpty(
eventsList->GetEvent(FreeFunctionWithObjectExpressionOnGroup)));
}
}
}
SECTION("Group renamed (in layout)") {
SECTION("Events") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &layout = project.GetLayout("Scene");
// Trigger the refactoring after the renaming of a group
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInLayout(
project, layout, "GroupWithMyBehavior", "RenamedGroupWithMyBehavior",
/* isObjectGroup=*/true);
for (auto *eventsList : GetEventsListsAssociatedToScene(project)) {
// Check group name has been renamed in action parameters.
REQUIRE(GetEventFirstActionFirstParameterString(eventsList->GetEvent(
FreeFunctionWithGroup)) == "RenamedGroupWithMyBehavior");
// Check group name has been renamed in expressions.
REQUIRE(GetEventFirstActionFirstParameterString(eventsList->GetEvent(
FreeFunctionWithObjectExpressionOnGroup)) ==
"RenamedGroupWithMyBehavior.GetObjectNumber()");
}
}
}
SECTION("Object renamed (in events function)") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
SECTION("Group") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
// Add a (free) function with an object group
gd::EventsFunction &eventsFunction =
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
gd::ObjectGroup &objectGroup =
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
objectGroup.AddObject("Object1");
objectGroup.AddObject("Object2");
// In theory, we would add the object parameters, but we're not testing
// events in this test.
// Add a (free) function with an object group
gd::EventsFunction &eventsFunction =
eventsExtension.InsertNewEventsFunction("MyEventsFunction", 0);
gd::ObjectGroup &objectGroup =
eventsFunction.GetObjectGroups().InsertNew("MyGroup", 0);
objectGroup.AddObject("Object1");
objectGroup.AddObject("Object2");
// In theory, we would add the object parameters, but we're not testing
// events in this test.
// Create the objects container for the events function
gd::ObjectsContainer globalObjectsContainer;
gd::ObjectsContainer objectsContainer;
gd::ParameterMetadataTools::ParametersToObjectsContainer(
project, eventsFunction.GetParameters(), objectsContainer);
// (this is strictly not necessary because we're not testing events in this
// test)
// Create the objects container for the events function
gd::ObjectsContainer globalObjectsContainer;
gd::ObjectsContainer objectsContainer;
gd::ParameterMetadataTools::ParametersToObjectsContainer(
project, eventsFunction.GetParameters(), objectsContainer);
// (this is strictly not necessary because we're not testing events in
// this test)
// Trigger the refactoring after the renaming of an object
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
project, eventsFunction, globalObjectsContainer, objectsContainer,
"Object1", "RenamedObject1",
/* isObjectGroup=*/false);
// Trigger the refactoring after the renaming of an object
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
project, eventsFunction, globalObjectsContainer, objectsContainer,
"Object1", "RenamedObject1",
/* isObjectGroup=*/false);
REQUIRE(objectGroup.Find("Object1") == false);
REQUIRE(objectGroup.Find("RenamedObject1") == true);
REQUIRE(objectGroup.Find("Object2") == true);
REQUIRE(objectGroup.Find("Object1") == false);
REQUIRE(objectGroup.Find("RenamedObject1") == true);
REQUIRE(objectGroup.Find("Object2") == true);
// Events are not tested
// Events are not tested
}
SECTION("Events") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &eventsFunction =
eventsExtension.GetEventsFunction("MyOtherEventsFunction");
// Create the objects container for the events function
gd::ObjectsContainer globalObjectsContainer;
gd::ObjectsContainer objectsContainer;
gd::ParameterMetadataTools::ParametersToObjectsContainer(
project, eventsFunction.GetParameters(), objectsContainer);
// Trigger the refactoring after the renaming of an object
gd::WholeProjectRefactorer::ObjectOrGroupRenamedInEventsFunction(
project, eventsFunction, globalObjectsContainer, objectsContainer,
"ObjectWithMyBehavior", "RenamedObjectWithMyBehavior",
/* isObjectGroup=*/false);
// Check object name has been renamed in action parameters.
REQUIRE(
GetEventFirstActionFirstParameterString(
eventsFunction.GetEvents().GetEvent(FreeFunctionWithObjects)) ==
"RenamedObjectWithMyBehavior");
// Check object name has been renamed in expressions.
REQUIRE(GetEventFirstActionFirstParameterString(
eventsFunction.GetEvents().GetEvent(
FreeFunctionWithObjectExpression)) ==
"RenamedObjectWithMyBehavior.GetObjectNumber()");
}
}
SECTION("Object renamed (in events-based object)") {
@@ -1556,6 +1819,50 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
}
}
SECTION("Events extension renamed in instructions scoped to one behavior") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
// A behavior is copied from one extension to another.
auto &destinationExtension =
project.InsertNewEventsFunctionsExtension("DestinationExtension", 0);
// Add the function used by the instruction that is checked in this test.
// When the function doesn't exist the destination extension, the
// instruction keeps pointing to the old extension.
destinationExtension.InsertNewEventsFunction("MyEventsFunction", 0);
auto &copiedBehavior =
destinationExtension.GetEventsBasedBehaviors().InsertNew(
"MyOtherEventsBasedBehavior", 0);
copiedBehavior.SetFullName("My events based behavior");
copiedBehavior.SetDescription("An events based behavior for test");
copiedBehavior.SetObjectType("MyEventsExtension::MyEventsBasedObject");
// Add the copied events.
auto &behaviorEventsFunctions = copiedBehavior.GetEventsFunctions();
auto &behaviorAction = behaviorEventsFunctions.InsertNewEventsFunction(
"MyBehaviorEventsFunction", 0);
SetupEvents(behaviorAction.GetEvents());
gd::WholeProjectRefactorer::UpdateExtensionNameInEventsBasedBehavior(
project, destinationExtension, copiedBehavior, "MyEventsExtension");
// Check that events function calls in instructions have been renamed
REQUIRE(GetEventFirstActionType(behaviorAction.GetEvents().GetEvent(
FreeFunctionAction)) == "DestinationExtension::MyEventsFunction");
for (auto *eventsList : GetEventsLists(project)) {
// Check that events function calls in instructions have NOT been renamed
// outside of the copied behavior.
REQUIRE(
GetEventFirstActionType(eventsList->GetEvent(FreeFunctionAction)) ==
"MyEventsExtension::MyEventsFunction");
}
}
SECTION("Events extension renamed in parameters") {
gd::Project project;
gd::Platform platform;
@@ -2929,3 +3236,426 @@ TEST_CASE("WholeProjectRefactorer (FindDependentBehaviorNames failing cases)",
}
}
}
TEST_CASE("RenameExternalEvents", "[common]") {
SECTION("Can update an event link to external events") {
gd::Project project;
gd::Platform platform;
project.AddPlatform(platform);
auto &layout = project.InsertNewLayout("My layout", 0);
auto &externalLayout =
project.InsertNewExternalLayout("My external layout", 0);
externalLayout.SetAssociatedLayout("My layout");
auto &externalEvents =
project.InsertNewExternalEvents("My external events", 0);
externalEvents.SetAssociatedLayout("My layout");
auto &events = layout.GetEvents();
gd::LinkEvent event;
event.SetTarget("My external events");
gd::LinkEvent &linkEvent =
dynamic_cast<gd::LinkEvent &>(events.InsertEvent(event));
gd::WholeProjectRefactorer::RenameExternalEvents(
project, "My external events", "My renamed external events");
REQUIRE(linkEvent.GetTarget() == "My renamed external events");
}
}
TEST_CASE("RenameExternalLayout", "[common]") {
SECTION("Can update external layout names in parameters") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &layout = project.InsertNewLayout("My layout", 0);
auto &externalLayout =
project.InsertNewExternalLayout("My external layout", 0);
externalLayout.SetAssociatedLayout("My layout");
auto &externalEvents =
project.InsertNewExternalEvents("My external events", 0);
externalEvents.SetAssociatedLayout("My layout");
auto &events = layout.GetEvents();
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::CreateObjectsFromExternalLayout");
action.SetParametersCount(2);
action.SetParameter(1, gd::Expression("\"My external layout\""));
event.GetActions().Insert(action);
gd::WholeProjectRefactorer::RenameExternalLayout(
project, "My external layout", "My renamed external layout");
REQUIRE(event.GetActions().at(0).GetParameter(1).GetPlainString() ==
"\"My renamed external layout\"");
}
}
TEST_CASE("RenameLayout", "[common]") {
SECTION("Can update layout names in parameters and external targets") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &layout = project.InsertNewLayout("My layout", 0);
auto &externalLayout =
project.InsertNewExternalLayout("My external layout", 0);
externalLayout.SetAssociatedLayout("My layout");
auto &externalEvents =
project.InsertNewExternalEvents("My external events", 0);
externalEvents.SetAssociatedLayout("My layout");
auto &events = layout.GetEvents();
gd::StandardEvent &event0 = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::Scene");
action.SetParametersCount(2);
action.SetParameter(1, gd::Expression("\"My layout\""));
event0.GetActions().Insert(action);
gd::LinkEvent event1;
event1.SetTarget("My layout");
gd::LinkEvent &linkEvent =
dynamic_cast<gd::LinkEvent &>(events.InsertEvent(event1));
gd::WholeProjectRefactorer::RenameLayout(project, "My layout",
"My renamed layout");
REQUIRE(event0.GetActions().at(0).GetParameter(1).GetPlainString() ==
"\"My renamed layout\"");
REQUIRE(linkEvent.GetTarget() == "My renamed layout");
REQUIRE(externalLayout.GetAssociatedLayout() == "My renamed layout");
REQUIRE(externalEvents.GetAssociatedLayout() == "My renamed layout");
}
}
namespace {
const gd::Instruction &CreateActionWithLayerParameter(gd::Project &project,
gd::EventsList &events) {
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::SetCameraCenterX");
action.SetParametersCount(4);
action.SetParameter(3, gd::Expression("\"My layer\""));
return event.GetActions().Insert(action);
}
const gd::Instruction &
CreateExpressionWithLayerParameter(gd::Project &project,
gd::EventsList &events) {
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::DoSomething");
action.SetParametersCount(1);
action.SetParameter(
0, gd::Expression("MyExtension::CameraCenterX(\"My layer\") + "
"MyExtension::CameraCenterX(\"My layer\")"));
return event.GetActions().Insert(action);
}
} // namespace
TEST_CASE("RenameLayer", "[common]") {
SECTION("Can update layer names in events") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &layout = project.InsertNewLayout("My layout", 0);
auto &otherLayout = project.InsertNewLayout("My other layout", 1);
auto &externalEvents =
project.InsertNewExternalEvents("My external events", 0);
externalEvents.SetAssociatedLayout("My layout");
auto &otherExternalEvents =
project.InsertNewExternalEvents("My external events", 0);
otherExternalEvents.SetAssociatedLayout("My other layout");
auto &layoutAction =
CreateActionWithLayerParameter(project, layout.GetEvents());
auto &externalAction =
CreateActionWithLayerParameter(project, externalEvents.GetEvents());
auto &otherLayoutAction =
CreateActionWithLayerParameter(project, otherLayout.GetEvents());
auto &otherExternalAction = CreateActionWithLayerParameter(
project, otherExternalEvents.GetEvents());
auto &layoutExpression =
CreateExpressionWithLayerParameter(project, layout.GetEvents());
auto &externalExpression =
CreateExpressionWithLayerParameter(project, externalEvents.GetEvents());
auto &otherLayoutExpression =
CreateExpressionWithLayerParameter(project, otherLayout.GetEvents());
auto &otherExternalExpression = CreateExpressionWithLayerParameter(
project, otherExternalEvents.GetEvents());
gd::WholeProjectRefactorer::RenameLayer(project, layout, "My layer",
"My renamed layer");
REQUIRE(layoutAction.GetParameter(3).GetPlainString() ==
"\"My renamed layer\"");
REQUIRE(externalAction.GetParameter(3).GetPlainString() ==
"\"My renamed layer\"");
// The event from the other layout are untouched.
REQUIRE(otherLayoutAction.GetParameter(3).GetPlainString() ==
"\"My layer\"");
REQUIRE(otherExternalAction.GetParameter(3).GetPlainString() ==
"\"My layer\"");
REQUIRE(layoutExpression.GetParameter(0).GetPlainString() ==
"MyExtension::CameraCenterX(\"My renamed layer\") + "
"MyExtension::CameraCenterX(\"My renamed layer\")");
REQUIRE(externalExpression.GetParameter(0).GetPlainString() ==
"MyExtension::CameraCenterX(\"My renamed layer\") + "
"MyExtension::CameraCenterX(\"My renamed layer\")");
// The event from the other layout are untouched.
REQUIRE(otherLayoutExpression.GetParameter(0).GetPlainString() ==
"MyExtension::CameraCenterX(\"My layer\") + "
"MyExtension::CameraCenterX(\"My layer\")");
REQUIRE(otherExternalExpression.GetParameter(0).GetPlainString() ==
"MyExtension::CameraCenterX(\"My layer\") + "
"MyExtension::CameraCenterX(\"My layer\")");
}
SECTION("Can update layer names in expressions with a smaller name") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &layout = project.InsertNewLayout("My layout", 0);
auto &layoutExpression =
CreateExpressionWithLayerParameter(project, layout.GetEvents());
gd::WholeProjectRefactorer::RenameLayer(project, layout, "My layer",
"layerA");
REQUIRE(layoutExpression.GetParameter(0).GetPlainString() ==
"MyExtension::CameraCenterX(\"layerA\") + "
"MyExtension::CameraCenterX(\"layerA\")");
}
}
namespace {
const gd::Instruction &CreateActionWithAnimationParameter(gd::Project &project,
gd::EventsList &events,
const gd::String &objectName) {
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::SetAnimationName");
action.SetParametersCount(2);
action.SetParameter(0, objectName);
action.SetParameter(1, gd::Expression("\"My animation\""));
return event.GetActions().Insert(action);
}
const gd::Instruction &
CreateExpressionWithAnimationParameter(gd::Project &project,
gd::EventsList &events,
const gd::String &objectName) {
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::DoSomething");
action.SetParametersCount(1);
action.SetParameter(
0, gd::Expression(objectName + ".AnimationFrameCount(\"My animation\") + " +
objectName + ".AnimationFrameCount(\"My animation\")"));
return event.GetActions().Insert(action);
}
} // namespace
TEST_CASE("RenameObjectAnimation", "[common]") {
SECTION("Can update object animation names in event") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &layout = project.InsertNewLayout("My layout", 0);
auto &otherLayout = project.InsertNewLayout("My other layout", 1);
auto &externalEvents =
project.InsertNewExternalEvents("My external events", 0);
externalEvents.SetAssociatedLayout("My layout");
auto &otherExternalEvents =
project.InsertNewExternalEvents("My external events", 0);
otherExternalEvents.SetAssociatedLayout("My other layout");
auto &object = layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite2", 1);
otherLayout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
auto &layoutAction =
CreateActionWithAnimationParameter(project, layout.GetEvents(), "MySprite");
auto &externalAction =
CreateActionWithAnimationParameter(project, externalEvents.GetEvents(), "MySprite");
auto &otherLayoutAction =
CreateActionWithAnimationParameter(project, otherLayout.GetEvents(), "MySprite");
auto &otherExternalAction = CreateActionWithAnimationParameter(
project, otherExternalEvents.GetEvents(), "MySprite");
auto &wrongObjectAction =
CreateActionWithAnimationParameter(project, layout.GetEvents(), "MySprite2");
auto &layoutExpression =
CreateExpressionWithAnimationParameter(project, layout.GetEvents(), "MySprite");
auto &externalExpression =
CreateExpressionWithAnimationParameter(project, externalEvents.GetEvents(), "MySprite");
auto &otherLayoutExpression =
CreateExpressionWithAnimationParameter(project, otherLayout.GetEvents(), "MySprite");
auto &otherExternalExpression = CreateExpressionWithAnimationParameter(
project, otherExternalEvents.GetEvents(), "MySprite");
auto &wrongObjectExpression =
CreateExpressionWithAnimationParameter(project, layout.GetEvents(), "MySprite2");
gd::WholeProjectRefactorer::RenameObjectAnimation(project, layout, object, "My animation",
"My renamed animation");
REQUIRE(layoutAction.GetParameter(1).GetPlainString() ==
"\"My renamed animation\"");
REQUIRE(externalAction.GetParameter(1).GetPlainString() ==
"\"My renamed animation\"");
// The event from the other layout are untouched.
REQUIRE(otherLayoutAction.GetParameter(1).GetPlainString() ==
"\"My animation\"");
REQUIRE(otherExternalAction.GetParameter(1).GetPlainString() ==
"\"My animation\"");
REQUIRE(wrongObjectAction.GetParameter(1).GetPlainString() ==
"\"My animation\"");
REQUIRE(layoutExpression.GetParameter(0).GetPlainString() ==
"MySprite.AnimationFrameCount(\"My renamed animation\") + "
"MySprite.AnimationFrameCount(\"My renamed animation\")");
REQUIRE(externalExpression.GetParameter(0).GetPlainString() ==
"MySprite.AnimationFrameCount(\"My renamed animation\") + "
"MySprite.AnimationFrameCount(\"My renamed animation\")");
// The event from the other layout are untouched.
REQUIRE(otherLayoutExpression.GetParameter(0).GetPlainString() ==
"MySprite.AnimationFrameCount(\"My animation\") + "
"MySprite.AnimationFrameCount(\"My animation\")");
REQUIRE(otherExternalExpression.GetParameter(0).GetPlainString() ==
"MySprite.AnimationFrameCount(\"My animation\") + "
"MySprite.AnimationFrameCount(\"My animation\")");
REQUIRE(wrongObjectExpression.GetParameter(0).GetPlainString() ==
"MySprite2.AnimationFrameCount(\"My animation\") + "
"MySprite2.AnimationFrameCount(\"My animation\")");
}
}
namespace {
const gd::Instruction &CreateActionWithLayerEffectParameter(gd::Project &project,
gd::EventsList &events,
const gd::String &layerName) {
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::EnableLayerEffect");
action.SetParametersCount(3);
action.SetParameter(1, gd::Expression("\"" + layerName + "\""));
action.SetParameter(2, gd::Expression("\"My effect\""));
return event.GetActions().Insert(action);
}
const gd::Instruction &
CreateExpressionWithLayerEffectParameter(gd::Project &project,
gd::EventsList &events,
const gd::String &layerName) {
gd::StandardEvent &event = dynamic_cast<gd::StandardEvent &>(
events.InsertNewEvent(project, "BuiltinCommonInstructions::Standard"));
gd::Instruction action;
action.SetType("MyExtension::DoSomething");
action.SetParametersCount(1);
action.SetParameter(
0, gd::Expression("MyExtension::LayerEffectParameter(\"" + layerName + "\", \"My effect\") + "
"MyExtension::LayerEffectParameter(\"" + layerName + "\", \"My effect\")"));
return event.GetActions().Insert(action);
}
} // namespace
TEST_CASE("RenameLayerEffect", "[common]") {
SECTION("Can update layer effect names in event") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &layout = project.InsertNewLayout("My layout", 0);
layout.InsertNewLayer("My layer", 0);
auto &layer = layout.GetLayer("My layer");
auto &otherLayout = project.InsertNewLayout("My other layout", 1);
auto &externalEvents =
project.InsertNewExternalEvents("My external events", 0);
externalEvents.SetAssociatedLayout("My layout");
auto &otherExternalEvents =
project.InsertNewExternalEvents("My external events", 0);
otherExternalEvents.SetAssociatedLayout("My other layout");
auto &object = layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
layout.InsertNewObject(project, "MyExtension::Sprite", "MySprite2", 1);
otherLayout.InsertNewObject(project, "MyExtension::Sprite", "MySprite", 0);
auto &layoutAction =
CreateActionWithLayerEffectParameter(project, layout.GetEvents(), "My layer");
auto &externalAction =
CreateActionWithLayerEffectParameter(project, externalEvents.GetEvents(), "My layer");
auto &otherLayoutAction =
CreateActionWithLayerEffectParameter(project, otherLayout.GetEvents(), "My layer");
auto &otherExternalAction = CreateActionWithLayerEffectParameter(
project, otherExternalEvents.GetEvents(), "My layer");
auto &wrongLayerAction =
CreateActionWithLayerEffectParameter(project, layout.GetEvents(), "My layer 2");
auto &layoutExpression =
CreateExpressionWithLayerEffectParameter(project, layout.GetEvents(), "My layer");
auto &externalExpression =
CreateExpressionWithLayerEffectParameter(project, externalEvents.GetEvents(), "My layer");
auto &otherLayoutExpression =
CreateExpressionWithLayerEffectParameter(project, otherLayout.GetEvents(), "My layer");
auto &otherExternalExpression = CreateExpressionWithLayerEffectParameter(
project, otherExternalEvents.GetEvents(), "My layer");
auto &wrongLayerExpression =
CreateExpressionWithLayerEffectParameter(project, layout.GetEvents(), "My layer 2");
std::cout << "RenameLayerEffect" << std::endl;
gd::WholeProjectRefactorer::RenameLayerEffect(project, layout, layer, "My effect",
"My renamed effect");
REQUIRE(layoutAction.GetParameter(2).GetPlainString() ==
"\"My renamed effect\"");
REQUIRE(externalAction.GetParameter(2).GetPlainString() ==
"\"My renamed effect\"");
// The event from the other layout are untouched.
REQUIRE(otherLayoutAction.GetParameter(2).GetPlainString() ==
"\"My effect\"");
REQUIRE(otherExternalAction.GetParameter(2).GetPlainString() ==
"\"My effect\"");
REQUIRE(wrongLayerAction.GetParameter(2).GetPlainString() ==
"\"My effect\"");
REQUIRE(layoutExpression.GetParameter(0).GetPlainString() ==
"MyExtension::LayerEffectParameter(\"My layer\", \"My renamed effect\") + "
"MyExtension::LayerEffectParameter(\"My layer\", \"My renamed effect\")");
REQUIRE(externalExpression.GetParameter(0).GetPlainString() ==
"MyExtension::LayerEffectParameter(\"My layer\", \"My renamed effect\") + "
"MyExtension::LayerEffectParameter(\"My layer\", \"My renamed effect\")");
// The event from the other layout are untouched.
REQUIRE(otherLayoutExpression.GetParameter(0).GetPlainString() ==
"MyExtension::LayerEffectParameter(\"My layer\", \"My effect\") + "
"MyExtension::LayerEffectParameter(\"My layer\", \"My effect\")");
REQUIRE(otherExternalExpression.GetParameter(0).GetPlainString() ==
"MyExtension::LayerEffectParameter(\"My layer\", \"My effect\") + "
"MyExtension::LayerEffectParameter(\"My layer\", \"My effect\")");
REQUIRE(wrongLayerExpression.GetParameter(0).GetPlainString() ==
"MyExtension::LayerEffectParameter(\"My layer 2\", \"My effect\") + "
"MyExtension::LayerEffectParameter(\"My layer 2\", \"My effect\")");
}
}

View File

@@ -30,7 +30,7 @@ module.exports = {
'AdMob',
_('AdMob'),
_(
'Allow to display AdMob banners, interstitials and reward video ads.'
'Allow to display AdMob banners, app open, interstitials, rewarded interstitials and rewarded video ads.'
),
'Florian Rival',
'MIT'
@@ -57,8 +57,8 @@ module.exports = {
.addDependency()
.setName('AdMob Cordova plugin')
.setDependencyType('cordova')
.setExportName('gdevelop-cordova-admob-plus')
.setVersion('0.45.0')
.setExportName('admob-plus-cordova')
.setVersion('1.28.0')
.setExtraSetting(
'APP_ID_ANDROID',
new gd.PropertyDescriptor('AdMobAppIdAndroid').setType(
@@ -100,23 +100,120 @@ module.exports = {
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.setTestMode');
// Banner
// App Open
extension
.addCondition(
'BannerLoading',
_('Banner loading'),
_(
'Check if a banner is currently loading. It will be shown automatically when loaded.'
),
_('Banner is loading'),
'AppOpenLoading',
_('App open loading'),
_('Check if an app open is currently loading.'),
_('App open is loading'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isBannerLoading');
.setFunctionName('gdjs.adMob.isAppOpenLoading');
extension
.addCondition(
'AppOpenReady',
_('App open ready'),
_('Check if an app open is ready to be displayed.'),
_('App open is ready'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isAppOpenReady');
extension
.addCondition(
'AppOpenShowing',
_('App open showing'),
_('Check if there is an app open being displayed.'),
_('App open is showing'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isAppOpenShowing');
extension
.addCondition(
'AppOpenErrored',
_('App open errored'),
_('Check if there was a error while loading the app open.'),
_('App open had an error'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isAppOpenErrored');
extension
.addAction(
'LoadAppOpen',
_('Load app open'),
_(
'Start loading an app open (that can be displayed automatically when the loading is finished).\nIf test mode is set, a test app open will be displayed.'
),
_(
'Load app open with Android ad unit ID: _PARAM0_, iOS ad unit ID: _PARAM1_ (landscape: _PARAM2_, display automatically when loaded: _PARAM3_)'
),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.addParameter('string', _('Android app open ID'), '', false)
.setParameterLongDescription(
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/3419835294"` for loading a test app open.'
)
.addParameter('string', _('iOS app open ID'), '', false)
.setParameterLongDescription(
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/5662855259"` for loading a test app open.'
)
.addParameter(
'yesorno',
_('Display in landscape? (portait otherwise)'),
'',
false
)
.setDefaultValue('false')
.addParameter(
'yesorno',
_('Displayed automatically when loading is finished?'),
'',
false
)
.setDefaultValue('true')
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.loadAppOpen');
extension
.addAction(
'ShowAppOpen',
_('Show app open'),
_(
'Show the app open that was loaded. Will work only when the app open is fully loaded.'
),
_('Show the loaded app open'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.showAppOpen');
// Banner
extension
.addCondition(
'BannerShowing',
@@ -131,6 +228,34 @@ module.exports = {
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isBannerShowing');
extension
.addCondition(
'BannerConfigured',
_('Banner configured'),
_('Check if there is a banner correctly configured ready to be shown.'),
_('Banner is configured'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isBannerConfigured');
extension
.addCondition(
'BannerLoaded',
_('Banner loaded'),
_('Check if there is a banner correctly loaded ready to be shown.'),
_('Banner is loaded'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isBannerLoaded');
extension
.addCondition(
'BannerErrored',
@@ -149,6 +274,9 @@ module.exports = {
extension
.addDuplicatedCondition('BannerReady', 'BannerShowing')
.setHidden();
extension
.addDuplicatedCondition('Bannerloading', 'BannerShowing')
.setHidden();
extension
.addDuplicatedCondition('BannerExists', 'BannerShowing')
.setHidden();
@@ -158,7 +286,7 @@ module.exports = {
'SetupBanner',
_('Configure the banner'),
_(
"Configure a banner, which can then be displayed.\nIf test mode is set, a test banner will be displayed.\n\nOnce a banner is positioned (at the top or bottom of the game), it can't be moved anymore."
"Configure a banner, which can then be displayed.\nIf a banner is already displayed, it will be removed\nIf test mode is set, a test banner will be displayed.\n\nOnce a banner is positioned (at the top or bottom of the game), it can't be moved anymore."
),
_(
'Configure the banner with Android ad unit ID: _PARAM0_, iOS ad unit ID: _PARAM1_, display at top: _PARAM2_'
@@ -173,7 +301,7 @@ module.exports = {
)
.addParameter('string', _('iOS banner ID'), '', false)
.setParameterLongDescription(
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/6300978111"` for showing a test banner.'
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/2934735716"` for showing a test banner.'
)
.addParameter(
'yesorno',
@@ -298,7 +426,7 @@ module.exports = {
)
.addParameter('string', _('iOS interstitial ID'), '', false)
.setParameterLongDescription(
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/1033173712"` for loading a test interstitial.'
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/4411468910"` for loading a test interstitial.'
)
.addParameter(
'yesorno',
@@ -327,90 +455,266 @@ module.exports = {
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.showInterstitial');
// Reward video
// Rewarded Interstitial
extension
.addCondition(
'VideoLoading',
_('Video loading'),
_('Check if a reward video is currently loading.'),
_('Reward video is loading'),
'RewardedInterstitialLoading',
_('Rewarded interstitial loading'),
_('Check if a rewarded interstitial is currently loading.'),
_('Rewarded interstitial is loading'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isVideoLoading');
.setFunctionName('gdjs.adMob.isRewardedInterstitialLoading');
extension
.addCondition(
'VideoReady',
_('Video ready'),
_('Check if a reward video is ready to be displayed.'),
_('Reward video is ready'),
'RewardedInterstitialReady',
_('Rewarded interstitial ready'),
_('Check if a rewarded interstitial is ready to be displayed.'),
_('Rewarded interstitial is ready'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isVideoReady');
.setFunctionName('gdjs.adMob.isRewardedInterstitialReady');
extension
.addCondition(
'VideoShowing',
_('Video showing'),
_('Check if there is a reward video being displayed.'),
_('Reward video is showing'),
'RewardedInterstitialShowing',
_('Rewarded interstitial showing'),
_('Check if there is a rewarded interstitial being displayed.'),
_('Rewarded interstitial is showing'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isVideoShowing');
.setFunctionName('gdjs.adMob.isRewardedInterstitialShowing');
extension
.addCondition(
'VideoErrored',
_('Video had an error'),
_('Check if there was a error while loading the rewarded video.'),
_('Video ad had an error'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isVideoErrored');
extension
.addCondition(
'VideoReward',
_('Video reward received'),
'RewardedInterstitialErrored',
_('Rewarded interstitial had an error'),
_(
'Check if the reward of the video was given to the user.\nYou can mark this reward as cleared, so that the condition will be false and you can show later another reward video.'
'Check if there was a error while loading the rewarded interstitial.'
),
_('Rewarded Interstitial had an error'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isRewardedInterstitialErrored');
extension
.addCondition(
'RewardedInterstitialRewardReceived',
_('Rewarded Interstitial reward received'),
_(
'Check if the reward of the rewarded interstitial was given to the user.\nYou can mark this reward as cleared, so that the condition will be false and you can show later another rewarded interstitial.'
),
_(
'User got the reward of the rewarded interstitial (and clear this reward: _PARAM0_)'
),
_('User got the reward of the video (and clear this reward: _PARAM0_)'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.addParameter(
'yesorno',
_('Clear the reward (needed to show another video)'),
_('Clear the reward (needed to show another rewarded interstitial)'),
'',
false
)
.setDefaultValue('true')
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.wasVideoRewardReceived');
.setFunctionName('gdjs.adMob.wasRewardedInterstitialRewardReceived');
extension
.addAction(
'LoadVideo',
_('Load video'),
'LoadRewardedInterstitial',
_('Load rewarded interstitial'),
_(
'Start loading a rewarded interstitial (that can be displayed automatically when the loading is finished).\nIf test mode is set, a test rewarded interstitial will be displayed.\nThis is similar to a rewarded video, but can be displayed at any time, and the user can close it.'
),
_(
'Load rewarded interstitial with Android ad unit ID: _PARAM0_, iOS ad unit ID: _PARAM1_ (display automatically when loaded: _PARAM2_)'
),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.addParameter('string', _('Android rewarded interstitial ID'), '', false)
.setParameterLongDescription(
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/5354046379"` for loading a test rewarded interstitial.'
)
.addParameter('string', _('iOS interstitial ID'), '', false)
.setParameterLongDescription(
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/6978759866"` for loading a test rewarded interstitial.'
)
.addParameter(
'yesorno',
_('Displayed automatically when loading is finished?'),
'',
false
)
.setDefaultValue('true')
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.loadRewardedInterstitial');
extension
.addAction(
'ShowRewardedInterstitial',
_('Show rewarded interstitial'),
_(
'Show the rewarded interstitial that was loaded. Will work only when the rewarded interstitial is fully loaded.'
),
_('Show the loaded rewarded interstitial'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.showRewardedInterstitial');
extension
.addAction(
'ClaimRewardedInterstitialReward',
_('Mark the reward of the rewarded interstitial as claimed'),
_(
'Mark the rewarded interstitial reward as claimed. Useful if you used the condition to check if the reward was given to the user without clearing the reward.'
),
_('Mark the reward of the rewarded interstitial as claimed'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.markRewardedInterstitialRewardAsClaimed');
// Rewarded video
extension
.addCondition(
'RewardedVideoLoading',
_('Rewarded video loading'),
_('Check if a rewarded video is currently loading.'),
_('Rewarded video is loading'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isRewardedVideoLoading');
// Deprecated condition (was renamed):
extension
.addDuplicatedCondition('VideoLoading', 'RewardedVideoLoading')
.setHidden();
extension
.addCondition(
'RewardedVideoReady',
_('Rewarded video ready'),
_('Check if a rewarded video is ready to be displayed.'),
_('Rewarded video is ready'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isRewardedVideoReady');
// Deprecated condition (was renamed):
extension
.addDuplicatedCondition('VideoReady', 'RewardedVideoReady')
.setHidden();
extension
.addCondition(
'RewardedVideoShowing',
_('Rewarded video showing'),
_('Check if there is a rewarded video being displayed.'),
_('Rewarded video is showing'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isRewardedVideoShowing');
// Deprecated condition (was renamed):
extension
.addDuplicatedCondition('VideoShowing', 'RewardedVideoShowing')
.setHidden();
extension
.addCondition(
'RewardedVideoErrored',
_('Rewarded video had an error'),
_('Check if there was a error while loading the rewarded video.'),
_('Rewarded video ad had an error'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.isRewardedVideoErrored');
// Deprecated condition (was renamed):
extension
.addDuplicatedCondition('VideoErrored', 'RewardedVideoErrored')
.setHidden();
extension
.addCondition(
'RewardedVideoRewardReceived',
_('Rewarded Video reward received'),
_(
'Check if the reward of the rewarded video was given to the user.\nYou can mark this reward as cleared, so that the condition will be false and you can show later another rewarded video.'
),
_(
'User got the reward of the rewarded video (and clear this reward: _PARAM0_)'
),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.addParameter(
'yesorno',
_('Clear the reward (needed to show another rewarded video)'),
'',
false
)
.setDefaultValue('true')
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.wasRewardedVideoRewardReceived');
// Deprecated condition (was renamed):
extension
.addDuplicatedCondition('VideoReward', 'RewardedVideoRewardReceived')
.setHidden();
extension
.addAction(
'LoadRewardedVideo',
_('Load rewarded video'),
_(
'Start loading a reward video (that can be displayed automatically when the loading is finished).\nIf test mode is set, a test video will be displayed.'
),
@@ -427,7 +731,7 @@ module.exports = {
)
.addParameter('string', _('iOS reward video ID'), '', false)
.setParameterLongDescription(
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/5224354917"` for loading a test rewarded video.'
'Get it from your AdMob account. You can use `"ca-app-pub-3940256099942544/1712485313"` for loading a test rewarded video.'
)
.addParameter(
'yesorno',
@@ -438,12 +742,15 @@ module.exports = {
.setDefaultValue('true')
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.loadVideo');
.setFunctionName('gdjs.adMob.loadRewardedVideo');
// Deprecated action (was renamed):
extension.addDuplicatedAction('LoadVideo', 'LoadRewardedVideo').setHidden();
extension
.addAction(
'ShowVideo',
_('Show video'),
'ShowRewardedVideo',
_('Show rewarded video'),
_(
'Show the reward video that was loaded. Will work only when the video is fully loaded.'
),
@@ -454,23 +761,31 @@ module.exports = {
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.showVideo');
.setFunctionName('gdjs.adMob.showRewardedVideo');
// Deprecated action (was renamed):
extension.addDuplicatedAction('ShowVideo', 'ShowRewardedVideo').setHidden();
extension
.addAction(
'ClaimReward',
_('Mark the reward of the video as claimed'),
'ClaimRewardedVideoReward',
_('Mark the reward of the rewarded video as claimed'),
_(
'Mark the video reward as claimed. Useful if you used the condition to check if the reward was given to the user without clearing the reward.'
'Mark the rewarded video reward as claimed. Useful if you used the condition to check if the reward was given to the user without clearing the reward.'
),
_('Mark the reward of the video as claimed'),
_('Mark the reward of the rewarded video as claimed'),
'',
'JsPlatform/Extensions/admobicon24.png',
'JsPlatform/Extensions/admobicon16.png'
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/AdMob/admobtools.js')
.setFunctionName('gdjs.adMob.markVideoRewardAsClaimed');
.setFunctionName('gdjs.adMob.markRewardedVideoRewardAsClaimed');
// Deprecated action (was renamed):
extension
.addDuplicatedAction('ClaimReward', 'ClaimRewardedVideoReward')
.setHidden();
return extension;
},

View File

@@ -1,10 +1,46 @@
namespace gdjs {
declare var admob: any;
declare var cordova: any;
export namespace adMob {
const logger = new gdjs.Logger('AdMob');
export enum AdSizeType {
const testAdIds = {
appOpen: {
android: 'ca-app-pub-3940256099942544/3419835294',
ios: 'ca-app-pub-3940256099942544/5662855259',
},
banner: {
android: 'ca-app-pub-3940256099942544/6300978111',
ios: 'ca-app-pub-3940256099942544/2934735716',
},
interstitial: {
android: 'ca-app-pub-3940256099942544/1033173712',
ios: 'ca-app-pub-3940256099942544/4411468910',
},
interstitialVideo: {
android: 'ca-app-pub-3940256099942544/8691691433',
ios: 'ca-app-pub-3940256099942544/5135589807',
},
rewarded: {
android: 'ca-app-pub-3940256099942544/5224354917',
ios: 'ca-app-pub-3940256099942544/1712485313',
},
rewardedInterstitial: {
android: 'ca-app-pub-3940256099942544/5354046379',
ios: 'ca-app-pub-3940256099942544/6978759866',
},
native: {
android: 'ca-app-pub-3940256099942544/2247696110',
ios: 'ca-app-pub-3940256099942544/3986624511',
},
nativeVideo: {
android: 'ca-app-pub-3940256099942544/1044960115',
ios: 'ca-app-pub-3940256099942544/2521693316',
},
};
enum AdSizeType {
BANNER,
LARGE_BANNER,
MEDIUM_RECTANGLE,
@@ -13,31 +49,113 @@ namespace gdjs {
SMART_BANNER,
}
// Banner
let bannerAndroidId = '';
let bannerIosId = '';
let bannerPosition: 'top' | 'bottom' = 'top';
let bannerRequestedAdSizeType: AdSizeType = AdSizeType.SMART_BANNER;
const adSizeTypes = {
BANNER: AdSizeType.BANNER,
LARGE_BANNER: AdSizeType.LARGE_BANNER,
MEDIUM_RECTANGLE: AdSizeType.MEDIUM_RECTANGLE,
FULL_BANNER: AdSizeType.FULL_BANNER,
LEADERBOARD: AdSizeType.LEADERBOARD,
SMART_BANNER: AdSizeType.SMART_BANNER,
};
let bannerLoading = false;
let bannerErrored = false;
let bannerShowing = false;
enum AppOpenAdOrientation {
Portrait = 1,
PortraitUpsideDown = 2,
LandscapeRight = 3,
LandscapeLeft = 4,
}
// Admob does not initialize automatically, so we store a flag to know if it's initialized.
let admobStarted = false;
let isUsingTestAds = false;
// Banner
let banner;
let bannerRequestedAdSizeType: AdSizeType = AdSizeType.SMART_BANNER;
let bannerConfigured = false; // Becomes true when the user configures the ad id and the position of the banner.
let bannerLoaded = false; // Becomes true when the banner is loaded by loaded.
let bannerShowing = false; // Becomes true when loaded or when the user shows/hides the banner.
let bannerErrored = false; // Becomes true when the banner fails to load.
// Interstitial
let interstitialLoading = false;
let interstitialReady = false;
let interstitialErrored = false;
let interstitialShowing = false;
let interstitial;
let interstitialLoading = false; // Becomes true when the interstitial is loading.
let interstitialReady = false; // Becomes true when the interstitial is loaded and ready to be shown.
let interstitialShowing = false; // Becomes true when the interstitial is showing.
let interstitialErrored = false; // Becomes true when the interstitial fails to load.
// Reward video
let videoLoading = false;
let videoReady = false;
let videoErrored = false;
let videoShowing = false;
let videoRewardReceived = false;
// App Open
let appOpen;
let appOpenLoading = false; // Becomes true when the appOpen is loading.
let appOpenReady = false; // Becomes true when the appOpen is loaded and ready to be shown.
let appOpenShowing = false; // Becomes true when the appOpen is showing.
let appOpenErrored = false; // Becomes true when the appOpen fails to load.
// Rewarded interstitial
let rewardedInterstitial;
let rewardedInterstitialLoading = false; // Becomes true when the interstitial is loading.
let rewardedInterstitialReady = false; // Becomes true when the interstitial is loaded and ready to be shown.
let rewardedInterstitialShowing = false; // Becomes true when the interstitial is showing.
let rewardedInterstitialRewardReceived = false; // Becomes true when the interstitial is closed and the reward is received.
let rewardedInterstitialErrored = false; // Becomes true when the interstitial fails to load.
// Rewarded video
let rewardedVideo;
let rewardedVideoLoading = false; // Becomes true when the video is loading.
let rewardedVideoReady = false; // Becomes true when the video is loaded and ready to be shown.
let rewardedVideoShowing = false; // Becomes true when the video is showing.
let rewardedVideoRewardReceived = false; // Becomes true when the video is closed and the reward is received.
let rewardedVideoErrored = false; // Becomes true when the video fails to load.
let npaValue = '0'; // TODO: expose an API to change this and also an automatic way using the consent SDK.
// Admob initialization listener
document.addEventListener(
'deviceready',
async () => {
// Obtain user consent ?
await admob.start();
logger.info('AdMob succesfully started.');
admobStarted = true;
},
false
);
/**
* Helper to know if we are on mobile and admob is correctly initialized.
*/
const checkIfAdMobIsAvailable = () => {
if (typeof cordova === 'undefined') {
logger.warn('We are not on mobile, AdMob will not be available.');
return false;
}
if (typeof admob === 'undefined' || !admobStarted) {
logger.warn('AdMob has not been configured or started properly.');
return false;
}
return true;
};
/**
* Helper to get the correct ad id depending on the platform. Android and iOS use different ids.
*/
const getAdUnitId = (androidAdUnitId, iosAdUnitId, type) => {
if (typeof cordova === 'undefined') {
logger.warn('Cordova is not available.');
return;
}
if (cordova.platformId === 'android') {
return isUsingTestAds ? testAdIds[type].android : androidAdUnitId;
} else if (cordova.platformId === 'ios') {
return isUsingTestAds ? testAdIds[type].ios : iosAdUnitId;
}
logger.error('Unsupported platform: ', cordova.platformId);
return null;
};
/**
* Activate or deactivate the test mode ("development" mode).
* When activated, tests ads will be served instead of real ones.
@@ -47,43 +165,116 @@ namespace gdjs {
* account being flagged for invalid activity.
*/
export const setTestMode = (enable: boolean) => {
if (typeof admob === 'undefined') {
if (!checkIfAdMobIsAvailable()) return;
isUsingTestAds = enable;
};
// -------------------
// ---- App Open -----
// -------------------
export const isAppOpenLoading = () => appOpenLoading;
export const isAppOpenReady = () => appOpenReady;
export const isAppOpenShowing = () => appOpenShowing;
export const isAppOpenErrored = () => appOpenErrored;
/** Load an AppOpen. */
export const loadAppOpen = async (
androidAdUnitId,
iosAdUnitId,
displayLandscape,
displayWhenLoaded
) => {
if (!checkIfAdMobIsAvailable()) return;
// If an appOpen is already loading or showing, we don't stop it.
if (appOpenLoading || appOpenShowing) {
return;
}
admob.setDevMode(enable);
const adUnitId = getAdUnitId(androidAdUnitId, iosAdUnitId, 'appOpen');
if (!adUnitId) return;
appOpenLoading = true;
appOpenReady = false;
appOpenErrored = false;
appOpen = new admob.AppOpenAd({
adUnitId,
orientation: displayLandscape
? AppOpenAdOrientation.LandscapeLeft
: AppOpenAdOrientation.Portrait,
});
appOpen.on('load', () => {
appOpenReady = true;
appOpenLoading = false;
});
appOpen.on('loadfail', () => {
appOpenLoading = false;
appOpenErrored = true;
});
appOpen.on('show', () => {
appOpenShowing = true;
appOpenReady = false;
});
appOpen.on('showfail', () => {
appOpenShowing = false;
appOpenErrored = true;
});
appOpen.on('dismiss', () => {
appOpenShowing = false;
});
try {
logger.info('Loading Admob App Open.');
await appOpen.load();
logger.info('AdMob App Open successfully loaded.');
appOpenLoading = false;
appOpenReady = true;
if (displayWhenLoaded) showAppOpen();
} catch (error) {
logger.error('Error while loading an App Open:', error);
appOpenLoading = false;
appOpenReady = false;
appOpenErrored = true;
}
};
// Banner
/** Check if a banner is loading. */
export const isBannerLoading = () => {
return bannerLoading;
};
/** Check if a banner is being shown on screen. */
export const isBannerShowing = () => {
return bannerShowing;
};
/** Check if the banner had an error while loading it. */
export const isBannerErrored = () => {
return bannerErrored;
};
/** Show the loaded appOpen. */
export const showAppOpen = async () => {
if (!checkIfAdMobIsAvailable()) return;
/**
* Set up a banner that can then be displayed by calling `showBanner`.
*/
export const setupBanner = function (androidID, iosID, atTop) {
if (typeof admob === 'undefined') {
if (!appOpen) {
logger.warn('App Open has not been set up, call loadAppOpen first.');
return;
}
if (!appOpenReady) {
logger.info('App Open not loaded yet, cannot display it.');
return;
}
appOpenErrored = false;
bannerAndroidId = androidID;
bannerIosId = iosID;
bannerPosition = atTop ? 'top' : 'bottom';
try {
logger.info('Showing AdMob App Open.');
await appOpen.show();
// AppOpen will be shown and
// `appOpenShowing` will be updated thanks to events
// (but it's too early to change it now).
} catch (error) {
logger.error('Error while showing an AdMob App Open:', error);
appOpenShowing = false;
appOpenErrored = true;
}
};
/**
* Set the size of the banner to be shown when `showBanner` is called.
* @param bannerAdSizeType The type of the banner to displayed
*/
// -----------------
// ---- Banner -----
// -----------------
export const isBannerConfigured = () => bannerConfigured;
export const isBannerLoaded = () => bannerLoaded;
export const isBannerShowing = () => bannerShowing;
export const isBannerErrored = () => bannerErrored;
export const setBannerAdSizeType = (
bannerAdSizeType:
| 'BANNER'
@@ -93,288 +284,421 @@ namespace gdjs {
| 'LEADERBOARD'
| 'SMART_BANNER'
) => {
const adSizeTypes = {
BANNER: AdSizeType.BANNER,
LARGE_BANNER: AdSizeType.LARGE_BANNER,
MEDIUM_RECTANGLE: AdSizeType.MEDIUM_RECTANGLE,
FULL_BANNER: AdSizeType.FULL_BANNER,
LEADERBOARD: AdSizeType.LEADERBOARD,
SMART_BANNER: AdSizeType.SMART_BANNER,
};
bannerRequestedAdSizeType =
adSizeTypes[bannerAdSizeType] || AdSizeType.SMART_BANNER;
};
/**
* Display the banner that was set up with `loadBanner` (and `setBannerAdSizeType`).
* Set up a banner that can then be displayed by calling `showBanner`.
* If a banner is already set up, it will be hidden and replaced by the new one.
*/
export const showBanner = () => {
if (typeof admob === 'undefined') {
return;
export const setupBanner = async (androidAdUnitId, iosAdUnitId, atTop) => {
if (!checkIfAdMobIsAvailable()) return;
const adUnitId = getAdUnitId(androidAdUnitId, iosAdUnitId, 'banner');
if (!adUnitId) return;
if (banner && bannerShowing) {
logger.info('Banner already visible, hiding it to display new one.');
await hideBanner();
}
bannerLoading = true;
bannerShowing = false;
bannerErrored = false;
admob.banner
.show({
id: {
android: bannerAndroidId,
ios: bannerIosId,
},
position: bannerPosition,
size: bannerRequestedAdSizeType,
})
.then(
() => {
bannerShowing = true;
bannerLoading = false;
logger.info('AdMob banner successfully shown.');
},
(error) => {
bannerShowing = false;
bannerLoading = false;
bannerErrored = true;
logger.error('Error while showing an AdMob banner:', error);
}
);
};
/** Hide the banner shown on screen. */
export const hideBanner = () => {
if (typeof admob === 'undefined') {
return;
}
bannerConfigured = false;
bannerLoaded = false;
bannerShowing = false;
admob.banner.hide({
android: bannerAndroidId,
ios: bannerIosId,
banner = new admob.BannerAd({
adUnitId,
position: atTop ? 'top' : 'bottom',
size: bannerRequestedAdSizeType,
});
banner.on('load', () => {
bannerShowing = true;
bannerLoaded = true;
});
banner.on('loadfail', () => {
bannerShowing = false;
bannerLoaded = false;
bannerErrored = true;
});
bannerConfigured = true;
};
// Interstitial
/** Check if the interstitial is loading. */
export const isInterstitialLoading = () => {
return interstitialLoading;
/**
* Display a banner that was set up with `setupBanner` (and `setBannerAdSizeType`).
*/
export const showBanner = async () => {
if (!banner) {
logger.info('Banner not configured, use setupBanner first.');
return;
}
if (bannerShowing) {
logger.info('Banner already visible. Ignoring.');
return;
}
bannerErrored = false;
try {
logger.info('Showing AdMob banner.');
await banner.show();
if (bannerLoaded) {
// Banner is already loaded, so it will be shown immediately.
bannerShowing = true;
}
} catch (error) {
bannerShowing = false;
bannerErrored = true;
logger.error('Error while showing an AdMob banner:', error);
}
};
/** Check if the interstitial is ready to display. */
export const isInterstitialReady = () => {
return interstitialReady;
};
/** Check if the interstitial is shown on screen. */
export const isInterstitialShowing = () => {
return interstitialShowing;
};
/** Check if the interstitial had an error while loading it. */
export const isInterstitialErrored = () => {
return interstitialErrored;
/** Hide the banner shown on screen. */
export const hideBanner = async () => {
if (!checkIfAdMobIsAvailable()) return;
if (!banner || !bannerShowing) {
logger.warn('No banner is being shown.');
return;
}
await banner.hide();
bannerShowing = false;
// Note that the banner is still loaded, which is why bannerLoaded is not set to false.
// We hide the banner, but keep it configured to display it again if needed.
};
// -----------------------
// ---- Interstitial -----
// -----------------------
export const isInterstitialLoading = () => interstitialLoading;
export const isInterstitialReady = () => interstitialReady;
export const isInterstitialShowing = () => interstitialShowing;
export const isInterstitialErrored = () => interstitialErrored;
/** Load an interstitial. */
export const loadInterstitial = (androidID, iosID, displayWhenLoaded) => {
if (typeof admob === 'undefined') {
return;
}
if (interstitialLoading || interstitialReady || interstitialShowing) {
export const loadInterstitial = async (
androidAdUnitId,
iosAdUnitId,
displayWhenLoaded
) => {
if (!checkIfAdMobIsAvailable()) return;
// If an interstitial is already loading or showing, we don't stop it.
if (interstitialLoading || interstitialShowing) {
return;
}
const adUnitId = getAdUnitId(
androidAdUnitId,
iosAdUnitId,
'interstitial'
);
if (!adUnitId) return;
interstitialLoading = true;
interstitialReady = false;
interstitialErrored = false;
admob.interstitial
.load({
id: {
android: androidID,
ios: iosID,
},
npa: npaValue,
})
.then(
() => {
logger.info('AdMob interstitial successfully loaded.');
if (displayWhenLoaded) showInterstitial();
},
(error) => {
interstitialLoading = false;
interstitialReady = false;
interstitialErrored = true;
logger.error('Error while loading a interstitial:', error);
}
);
interstitial = new admob.InterstitialAd({
adUnitId,
npa: npaValue,
});
interstitial.on('load', () => {
interstitialReady = true;
interstitialLoading = false;
});
interstitial.on('loadfail', () => {
interstitialLoading = false;
interstitialErrored = true;
});
interstitial.on('show', () => {
interstitialShowing = true;
interstitialReady = false;
});
interstitial.on('showfail', () => {
interstitialShowing = false;
interstitialErrored = true;
});
interstitial.on('dismiss', () => {
interstitialShowing = false;
});
try {
logger.info('Loading Admob interstitial.');
await interstitial.load();
logger.info('AdMob interstitial successfully loaded.');
interstitialLoading = false;
interstitialReady = true;
if (displayWhenLoaded) showInterstitial();
} catch (error) {
logger.error('Error while loading a interstitial:', error);
interstitialLoading = false;
interstitialReady = false;
interstitialErrored = true;
}
};
/** Show the loaded interstitial. */
export const showInterstitial = () => {
if (typeof admob === 'undefined') {
export const showInterstitial = async () => {
if (!checkIfAdMobIsAvailable()) return;
if (!interstitial) {
logger.warn(
'Interstitial has not been set up, call loadInterstitial first.'
);
return;
}
admob.interstitial.show().then(
() => {
// Interstitial will be shown and
// `interstitialShowing` will be updated thanks to events
// (but it's too early to change it now).
},
(error) => {
interstitialShowing = false;
interstitialErrored = true;
logger.error('Error while trying to show an interstitial:', error);
}
);
if (!interstitialReady) {
logger.info('Interstitial not loaded yet, cannot display it.');
return;
}
interstitialErrored = false;
try {
logger.info('Showing AdMob interstitial.');
await interstitial.show();
// Interstitial will be shown and
// `interstitialShowing` will be updated thanks to events
// (but it's too early to change it now).
} catch (error) {
logger.error('Error while showing an AdMob interstitial:', error);
interstitialShowing = false;
interstitialErrored = true;
}
};
// Reward video
/** Check if the video is loading. */
export const isVideoLoading = () => {
return videoLoading;
};
/** Check if the video is ready to display. */
export const isVideoReady = () => {
return videoReady;
};
/** Check if the video is shown on screen. */
export const isVideoShowing = () => {
return videoShowing;
};
/** Check if the video had an error while loading it. */
export const isVideoErrored = () => {
return videoErrored;
};
// --------------------------------
// ---- Rewarded Interstitial -----
// --------------------------------
export const isRewardedInterstitialLoading = () =>
rewardedInterstitialLoading;
export const isRewardedInterstitialReady = () => rewardedInterstitialReady;
export const isRewardedInterstitialShowing = () =>
rewardedInterstitialShowing;
export const isRewardedInterstitialErrored = () =>
rewardedInterstitialErrored;
/** Check if the reward of the video was received. */
export const wasVideoRewardReceived = function (markAsClaimed) {
const reward = videoRewardReceived;
/** Check if the reward of the rewarded interstitial was received. */
export const wasRewardedInterstitialRewardReceived = function (
markAsClaimed
) {
const reward = rewardedInterstitialRewardReceived;
if (markAsClaimed) {
videoRewardReceived = false;
rewardedInterstitialRewardReceived = false;
}
return reward;
};
/** Load a reward video. */
export const loadVideo = function (androidID, iosID, displayWhenLoaded) {
if (typeof admob === 'undefined') {
return;
}
if (videoLoading || videoReady || videoShowing) {
/** Load a rewarded interstitial. */
export const loadRewardedInterstitial = async (
androidAdUnitID,
iosAdUnitID,
displayWhenLoaded
) => {
if (!checkIfAdMobIsAvailable()) return;
if (rewardedInterstitialLoading || rewardedInterstitialShowing) {
return;
}
videoLoading = true;
videoReady = false;
videoErrored = false;
admob.rewardVideo
.load({
id: {
android: androidID,
ios: iosID,
},
npa: npaValue,
})
.then(
() => {
logger.info('AdMob reward video successfully loaded.');
const adUnitId = getAdUnitId(
androidAdUnitID,
iosAdUnitID,
'rewardedInterstitial'
);
if (!adUnitId) return;
if (displayWhenLoaded) showVideo();
},
(error) => {
videoLoading = false;
videoReady = false;
videoErrored = true;
logger.error('Error while loading a reward video:', error);
}
rewardedInterstitialLoading = true;
rewardedInterstitialReady = false;
rewardedInterstitialErrored = false;
rewardedInterstitial = new admob.RewardedInterstitialAd({
adUnitId,
npa: npaValue,
});
// Rewarded video event listeners
rewardedInterstitial.on('load', () => {
rewardedInterstitialReady = true;
rewardedInterstitialLoading = false;
});
rewardedInterstitial.on('loadfail', () => {
rewardedInterstitialLoading = false;
rewardedInterstitialErrored = true;
});
rewardedInterstitial.on('show', () => {
rewardedInterstitialShowing = true;
rewardedInterstitialReady = false;
});
rewardedInterstitial.on('showfail', () => {
rewardedInterstitialShowing = false;
rewardedInterstitialErrored = true;
});
rewardedInterstitial.on('dismiss', () => {
rewardedInterstitialShowing = false;
});
rewardedInterstitial.on('reward', () => {
rewardedInterstitialRewardReceived = true;
});
try {
logger.info('Loading AdMob rewarded interstitial.');
await rewardedInterstitial.load();
logger.info('AdMob rewarded interstitial successfully loaded.');
rewardedInterstitialLoading = false;
rewardedInterstitialReady = true;
if (displayWhenLoaded) showRewardedInterstitial();
} catch (error) {
rewardedInterstitialLoading = false;
rewardedInterstitialReady = false;
rewardedInterstitialErrored = true;
logger.error('Error while loading a rewarded interstitial:', error);
}
};
/** Show the loaded reward interstitial. */
export const showRewardedInterstitial = async () => {
if (!checkIfAdMobIsAvailable()) return;
if (!rewardedInterstitial) {
logger.warn(
'interstitial has not been set up, call loadRewardedInterstitial first.'
);
return;
}
if (!rewardedInterstitialReady) {
logger.info('Rewarded interstitial not loaded yet, cannot display it.');
}
rewardedInterstitialErrored = false;
try {
logger.info('Showing AdMob rewarded interstitial.');
await rewardedInterstitial.show();
// Rewarded interstitial will be shown and
// `rewardedInterstitialShowing` will be updated thanks to events
// (but it's too early to change it now).
} catch (error) {
logger.error(
'Error while showing an AdMob rewarded interstitial:',
error
);
rewardedInterstitialShowing = false;
rewardedInterstitialErrored = true;
}
};
/** Mark the reward of the interstitial as claimed. */
export const markRewardedInterstitialRewardAsClaimed = () => {
rewardedInterstitialRewardReceived = false;
};
// -------------------------
// ---- Rewarded Video -----
// -------------------------
export const isRewardedVideoLoading = () => rewardedVideoLoading;
export const isRewardedVideoReady = () => rewardedVideoReady;
export const isRewardedVideoShowing = () => rewardedVideoShowing;
export const isRewardedVideoErrored = () => rewardedVideoErrored;
/** Check if the reward of the rewarded video was received. */
export const wasRewardedVideoRewardReceived = function (markAsClaimed) {
const reward = rewardedVideoRewardReceived;
if (markAsClaimed) {
rewardedVideoRewardReceived = false;
}
return reward;
};
/** Load a rewarded video. */
export const loadRewardedVideo = async (
androidAdUnitID,
iosAdUnitID,
displayWhenLoaded
) => {
if (!checkIfAdMobIsAvailable()) return;
if (rewardedVideoLoading || rewardedVideoShowing) {
return;
}
const adUnitId = getAdUnitId(androidAdUnitID, iosAdUnitID, 'rewarded');
if (!adUnitId) return;
rewardedVideoLoading = true;
rewardedVideoReady = false;
rewardedVideoErrored = false;
rewardedVideo = new admob.RewardedAd({
adUnitId,
npa: npaValue,
});
// Rewarded video event listeners
rewardedVideo.on('load', () => {
rewardedVideoReady = true;
rewardedVideoLoading = false;
});
rewardedVideo.on('loadfail', () => {
rewardedVideoLoading = false;
rewardedVideoErrored = true;
});
rewardedVideo.on('show', () => {
rewardedVideoShowing = true;
rewardedVideoReady = false;
});
rewardedVideo.on('showfail', () => {
rewardedVideoShowing = false;
rewardedVideoErrored = true;
});
rewardedVideo.on('dismiss', () => {
rewardedVideoShowing = false;
});
rewardedVideo.on('reward', () => {
rewardedVideoRewardReceived = true;
});
try {
logger.info('Loading AdMob rewarded video.');
await rewardedVideo.load();
logger.info('AdMob rewarded video successfully loaded.');
rewardedVideoLoading = false;
rewardedVideoReady = true;
if (displayWhenLoaded) showRewardedVideo();
} catch (error) {
rewardedVideoLoading = false;
rewardedVideoReady = false;
rewardedVideoErrored = true;
logger.error('Error while loading a rewarded video:', error);
}
};
/** Show the loaded reward video. */
export const showVideo = () => {
if (typeof admob === 'undefined') {
export const showRewardedVideo = async () => {
if (!checkIfAdMobIsAvailable()) return;
if (!rewardedVideo) {
logger.warn('Video has not been set up, call loadRewardedVideo first.');
return;
}
if (!rewardedVideoReady) {
logger.info('Rewarded video not loaded yet, cannot display it.');
}
rewardedVideoErrored = false;
admob.rewardVideo.show().then(
() => {
// Video will be shown and
// `videoShowing` will be updated thanks to events
// (but it's too early to change it now).
},
(error) => {
videoShowing = false;
videoErrored = true;
logger.error('Error while trying to show a reward video:', error);
}
);
try {
logger.info('Showing AdMob rewarded video.');
await rewardedVideo.show();
// Rewarded video will be shown and
// `rewardedVideoShowing` will be updated thanks to events
// (but it's too early to change it now).
} catch (error) {
logger.error('Error while showing an AdMob rewarded video:', error);
rewardedVideoShowing = false;
rewardedVideoErrored = true;
}
};
/** Mark the reward of the video as claimed. */
export const markVideoRewardAsClaimed = () => {
videoRewardReceived = false;
export const markRewardedVideoRewardAsClaimed = () => {
rewardedVideoRewardReceived = false;
};
// Banner event listeners:
document.addEventListener('admob.banner.load', () => {
bannerShowing = true;
bannerLoading = false;
});
document.addEventListener('admob.banner.load_fail', () => {
bannerLoading = false;
});
document.addEventListener('admob.banner.open', () => {
// Not implemented.
});
document.addEventListener('admob.banner.exit_app', () => {
// Not implemented.
});
document.addEventListener('admob.banner.close', () => {
// Not implemented.
});
// Interstitial event listeners
document.addEventListener('admob.interstitial.load', () => {
interstitialReady = true;
interstitialLoading = false;
});
document.addEventListener('admob.interstitial.load_fail', () => {
interstitialLoading = false;
});
document.addEventListener('admob.interstitial.open', () => {
interstitialShowing = true;
interstitialReady = false;
});
document.addEventListener('admob.interstitial.close', () => {
interstitialShowing = false;
});
document.addEventListener('admob.interstitial.exit_app', () => {
// Not implemented.
});
// Reward video event listeners
document.addEventListener('admob.reward_video.load', () => {
videoReady = true;
videoLoading = false;
});
document.addEventListener('admob.reward_video.load_fail', () => {
videoLoading = false;
});
document.addEventListener('admob.reward_video.open', () => {
videoShowing = true;
videoReady = false;
});
document.addEventListener('admob.reward_video.close', () => {
videoShowing = false;
});
document.addEventListener('admob.reward_video.start', () => {
// Not implemented.
});
document.addEventListener('admob.reward_video.complete', () => {
// Not implemented.
});
document.addEventListener('admob.reward_video.reward', () => {
videoRewardReceived = true;
});
document.addEventListener('admob.reward_video.exit_app', () => {
// Not implemented.
});
}
}

View File

@@ -1,10 +1,7 @@
// @ts-check
describe('gdjs.AnchorRuntimeBehavior', function () {
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
resources: { resources: [] },
// @ts-ignore
properties: { windowWidth: 1000, windowHeight: 1000 },
const runtimeGame = gdjs.getPixiRuntimeGame({
propertiesOverrides: { windowHeight: 1000, windowWidth: 1000 },
});
const anchorBehaviorName = 'Anchor';
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);

View File

@@ -36,7 +36,7 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/objects/bbtext')
.setCategory('User interface');
.setCategory('Text');
extension
.addInstructionOrExpressionGroupMetadata(_('BBCode Text Object'))
.setIcon('JsPlatform/Extensions/bbcode32.png');
@@ -174,7 +174,7 @@ module.exports = {
.addIncludeFile(
'Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js'
)
.setCategoryFullName(_('User interface'));
.setCategoryFullName(_('Text'));
/**
* Utility function to add both a setter and a getter to a property from a list.

View File

@@ -36,9 +36,10 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/objects/bitmap_text')
.setCategory('User interface');
extension.addInstructionOrExpressionGroupMetadata(_("Bitmap Text"))
.setIcon("JsPlatform/Extensions/bitmapfont32.png");
.setCategory('Text');
extension
.addInstructionOrExpressionGroupMetadata(_('Bitmap Text'))
.setIcon('JsPlatform/Extensions/bitmapfont32.png');
const bitmapTextObject = new gd.ObjectJsImplementation();
// $FlowExpectedError
@@ -91,7 +92,7 @@ module.exports = {
.setType('resource')
.addExtraInfo('bitmapFont') //fnt or xml files
.setLabel(_('Bitmap Font'))
.setGroup(_("Font"));
.setGroup(_('Font'));
objectProperties
.getOrCreate('textureAtlasResourceName')
@@ -99,7 +100,7 @@ module.exports = {
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Bitmap atlas image'))
.setGroup(_("Font"));
.setGroup(_('Font'));
objectProperties
.getOrCreate('scale')
@@ -113,7 +114,7 @@ module.exports = {
.setValue(objectContent.tint)
.setType('color')
.setLabel(_('Font tint'))
.setGroup(_("Font"));
.setGroup(_('Font'));
objectProperties
.getOrCreate('wordWrap')
@@ -174,7 +175,7 @@ module.exports = {
.addIncludeFile(
'Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.js'
)
.setCategoryFullName(_('User interface'));
.setCategoryFullName(_('Text'));
object
.addExpressionAndConditionAndAction(
@@ -652,8 +653,7 @@ module.exports = {
// This is called to update the PIXI object on the scene editor
RenderedBitmapTextInstance.prototype.update = function () {
const properties = this._associatedObjectConfiguration
.getProperties();
const properties = this._associatedObjectConfiguration.getProperties();
// Update the rendered text properties (note: Pixi is only
// applying changes if there were changed).

View File

@@ -1,11 +1,6 @@
// @ts-check
describe('gdjs.DraggableRuntimeBehavior', function () {
var runtimeGame = new gdjs.RuntimeGame({
variables: [],
resources: { resources: [] },
// @ts-ignore
properties: { windowWidth: 800, windowHeight: 600 },
});
const runtimeGame = gdjs.getPixiRuntimeGame();
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [

View File

@@ -176,12 +176,12 @@ module.exports = {
.setType('number');
bevelProperties
.getOrCreate('lightColor')
.setValue('#ffffff')
.setValue('255;255;255')
.setLabel(_('Light color (color of the outline)'))
.setType('color');
bevelProperties
.getOrCreate('shadowColor')
.setValue('#000000')
.setValue('0;0;0')
.setLabel(_('Shadow color (color of the outline)'))
.setType('color');
bevelProperties
@@ -333,13 +333,13 @@ module.exports = {
const colorReplaceProperties = colorReplaceEffect.getProperties();
colorReplaceProperties
.getOrCreate('originalColor')
.setValue('#ff0000')
.setValue('252;3;65')
.setLabel(_('Original Color'))
.setType('color')
.setDescription('The color that will be changed');
colorReplaceProperties
.getOrCreate('newColor')
.setValue('#000000')
.setValue('255;255;255')
.setLabel(_('New Color'))
.setType('color')
.setDescription('The new color');
@@ -517,7 +517,7 @@ module.exports = {
.setType('number');
dropShadowProperties
.getOrCreate('color')
.setValue('#000000')
.setValue('255;255;255')
.setLabel(_('Color of the shadow'))
.setType('color');
dropShadowProperties
@@ -646,7 +646,7 @@ module.exports = {
.setType('number');
glowProperties
.getOrCreate('color')
.setValue('#ffffff')
.setValue('255;255;255')
.setLabel(_('Color (color of the outline)'))
.setType('color');
@@ -868,7 +868,7 @@ module.exports = {
.setType('number');
outlineProperties
.getOrCreate('color')
.setValue('1')
.setValue('255;255;255')
.setLabel(_('Color of the outline'))
.setType('color');
outlineProperties

View File

@@ -89,7 +89,7 @@ module.exports = {
.addExtraInfo('image');
dummyEffectProperties
.getOrCreate('someColor')
.setValue('#0022FF')
.setValue('255;3;62')
.setLabel(_("Color (won't be used, just for demonstration purpose)"))
.setType('color')
.setDescription(_('Another optional description.'));

View File

@@ -75,7 +75,8 @@ module.exports = {
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.makeDirectory');
.setFunctionName('gdjs.fileSystem.makeDirectory')
.setAsyncFunctionName('gdjs.fileSystem.makeDirectoryAsync');
extension
.addAction(
@@ -127,7 +128,8 @@ module.exports = {
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.saveStringToFileAsync');
.setFunctionName('gdjs.fileSystem.saveStringToFileAsync')
.setAsyncFunctionName('gdjs.fileSystem.saveStringToFileAsyncTask');
extension
.addAction(
@@ -179,7 +181,8 @@ module.exports = {
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.saveVariableToJSONFileAsync');
.setFunctionName('gdjs.fileSystem.saveVariableToJSONFileAsync')
.setAsyncFunctionName('gdjs.fileSystem.saveVariableToJSONFileAsyncTask');
extension
.addAction(
@@ -217,7 +220,8 @@ module.exports = {
.setDefaultValue('yes')
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.loadStringFromFileAsync');
.setFunctionName('gdjs.fileSystem.loadStringFromFileAsync')
.setAsyncFunctionName('gdjs.fileSystem.loadStringFromFileAsyncTask');
extension
.addAction(
@@ -331,7 +335,10 @@ module.exports = {
.setDefaultValue('yes')
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.loadVariableFromJSONFileAsync');
.setFunctionName('gdjs.fileSystem.loadVariableFromJSONFileAsync')
.setAsyncFunctionName(
'gdjs.fileSystem.loadVariableFromJSONFileAsyncTask'
);
extension
.addAction(
@@ -379,7 +386,8 @@ module.exports = {
)
.getCodeExtraInformation()
.setIncludeFile('Extensions/FileSystem/filesystemtools.js')
.setFunctionName('gdjs.fileSystem.deleteFileAsync');
.setFunctionName('gdjs.fileSystem.deleteFileAsync')
.setAsyncFunctionName('gdjs.fileSystem.deleteFileAsyncTask');
extension
.addStrExpression(

Some files were not shown because too many files have changed in this diff Show More