Compare commits

...

635 Commits

Author SHA1 Message Date
Clément Pasteau
959988d147 Allow managing Game from the Projects list in the Build section 2022-12-20 17:27:39 +01:00
AlexandreS
53828a6b61 Add possibility to drag n drop items in the project manager (scenes, external layouts, external events, extensions) (#4720) 2022-12-20 16:54:58 +01:00
github-actions[bot]
eb797281cf Update translations [skip ci] (#4696)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-12-20 14:54:38 +01:00
Florian Rival
80f5a9a0d6 Add the asset store on the homepage (#4692)
* You can now browse free and premium asset packs from the home page, under the tab "Shop".
* When you have found great assets for your game, it's easy to add them in your game in a click. You can choose them to add them to a specific scene or to the whole project as global objects.
* If you're interested to sell your assets on the GDevelop asset store, check our wiki page to find how it works and the form to send us your assets: https://wiki.gdevelop.io/gdevelop5/community/sell-asset-pack-store
2022-12-20 14:49:54 +01:00
D8H
07ab4c938b Fix event-based objects properties that were changing for all instances at once (#4717)
* It was only affecting properties defined in the event-based objects not the one from child-object configurations.
2022-12-20 14:20:19 +01:00
AlexandreS
41fa153ddf Add description to a certain amount of parameters in actions and conditions (#4716) 2022-12-20 13:59:10 +01:00
Clément Pasteau
4cdac65944 Put beginner courses on top of Learn section (#4715) 2022-12-19 15:18:25 +01:00
AlexandreS
7b5036286f Fix scene background color setting via the textfield (#4713) 2022-12-19 12:42:27 +01:00
AlexandreS
fd4dd62f9b Allow text selection on game feedback cards (#4712) 2022-12-19 10:55:11 +01:00
Clément Pasteau
6701a52a88 Update shortcut to close project and quit app to match other app standards (#4711) 2022-12-19 10:51:42 +01:00
AlexandreS
0b61bb5053 Fix: Close all the dialogs at the same time when creating a project from an example (#4710) 2022-12-19 10:34:49 +01:00
AlexandreS
259e35d941 Use a constant zoom speed on the scene editor and on image preview, regardless of zoom factor (#4674) 2022-12-19 09:02:49 +01:00
Clément Pasteau
b9ac22208b Replace most float with double for better precision (#4689)
Do not show in changelog
2022-12-16 14:50:11 +01:00
Clément Pasteau
a991283bb5 Correctly display asset authors coming from premium asset packs (#4688) 2022-12-16 11:21:46 +01:00
Clément Pasteau
bf3ecceb06 Update service worker to put translations in cache (#4693)
* This should prevent unwanted {0} appearing on the web for each update
2022-12-16 09:24:32 +01:00
github-actions[bot]
b3bc1dd21b Update translations [skip ci] (#4685)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-12-15 12:34:23 +01:00
Clément Pasteau
d63b83b606 Improve instance number properties by hiding unnecessary decimals (#4557)
* "resize", "drag" or "rotate" of an instance in the editor will now round the properties to the nearest integer for ease of use.
  * This does not prevent entering digits in the instance properties directly
* The fields do not update the instance with "0" when a user is still typing (ex: "19," does not update the field)
* The "width/height/x/y/angle" properties can now correctly accept precise float numbers, avoiding excessive and inaccurate digits
2022-12-15 12:16:12 +01:00
AlexandreS
05e222c92d Bump newIDE version (#4684) 2022-12-14 14:56:53 +01:00
github-actions[bot]
d843a9e607 Update translations [skip ci] (#4670)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-12-14 14:51:53 +01:00
AlexandreS
5d3f1a502c Fix release 152 issues (#4683)
Do not show in changelog
2022-12-14 14:47:56 +01:00
AlexandreS
fbcc63a0d0 Add message in build section when unable to fetch cloud projects (#4681)
Don't show in changelog
2022-12-13 16:59:37 +01:00
D8H
46a459bdb4 Fix the authors list on extension wiki pages (#4680)
* Don't show in changelog
2022-12-13 14:15:57 +01:00
Florian Rival
86c8467cdc Fix export of cloud projects on Windows (#4679)
Don't show in changelog
2022-12-13 12:50:11 +01:00
AlexandreS
5426f656cb Refresh cloud project after save as [skip ci] (#4677)
Don't show in changelog
2022-12-13 12:47:38 +01:00
AlexandreS
b7f4f3166e Use non clickable project manager section title [skip ci] (#4678) 2022-12-13 12:46:35 +01:00
D8H
e62b90d5ff Fix the wiki extension page generator and make it use headers instead of extension files (#4676)
* Don't show in changelog
2022-12-13 12:08:56 +01:00
AlexandreS
45c1c6c38a Fix import issue (#4675)
Don't show in changelog
2022-12-13 10:19:32 +01:00
Florian Rival
82524fba12 Make the extension markdown document generator script fails if an error occurred
Only show in developer changelog
2022-12-12 22:46:22 +01:00
AlexandreS
40fb6e4874 Remove cloud projects feature flag (#4673)
Don't show in changelog
2022-12-12 17:37:09 +01:00
AlexandreS
52742cfa10 Remove unused import (#4671)
Do not show in changelog
2022-12-12 16:13:39 +01:00
AlexandreS
702c71390b Remove unused macro conditions (#4669)
Do not show in changelog
2022-12-12 15:32:35 +01:00
github-actions[bot]
1a6074b8ea Update translations [skip ci] (#4649) 2022-12-12 15:26:56 +01:00
AlexandreS
0e45d468ea Bump newIDE version
Don't show in changelog
2022-12-12 15:25:31 +01:00
AlexandreS
ed900befd4 Hide project settings in new project setup dialog if creating from example (#4663)
Do not show in changelog
2022-12-12 15:24:44 +01:00
Clément Pasteau
16ccd168e0 Embed in-app tutorials in the editor so that they're available offline (#4646) 2022-12-12 14:55:55 +01:00
D8H
74cc7ac684 Fix extension function missing code files when exporting a project (#4665)
* The issue happened when a behavior used a function from its extension which itself also used another function.
2022-12-12 14:32:23 +01:00
D8H
52278180ab Allow to set the text alignment for text objects by property (#4648) 2022-12-12 14:17:16 +01:00
D8H
471053da11 Add a tooltip on the button to open extension functions (#4666) 2022-12-12 13:26:48 +01:00
AlexandreS
237786b0a0 Add lerp angle expression which takes the shortest path between two angles (#4664)
Co-authored-by: Tristan Rhodes <tristan.rhodes@gmail.com>
2022-12-12 11:37:43 +01:00
AlexandreS
ba52577c24 Use same design for open from dialog as for save to dialog (#4655)
Do not show in changelog
2022-12-12 09:58:25 +01:00
D8H
e99c3800e4 Fix the required behavior type field that were missing (#4659)
* Don't show in changelog
2022-12-12 09:30:40 +01:00
Florian Rival
c780b6c6d6 Alternate paid and free asset packs (#4656)
Don't show in changelog
2022-12-09 18:32:42 +01:00
AlexandreS
70380dc056 Support possibility to deprecate an in-app tutorial step (#4653)
Do not show in changelog
2022-12-09 16:25:48 +01:00
Daniel R
c1bed2ebb2 Fix picking a folder not updating the input field when creating a new project (#4654)
Co-authored-by: Daniel Redondo <dani@easydevel.com>
2022-12-09 16:05:45 +01:00
Florian Rival
d639f87f31 Improve the design of the project manager (#4652)
Don't show in changelog
2022-12-09 15:47:59 +01:00
Florian Rival
e8888bbe76 Fix context menus not working anymore on mobile/touchscreens (#4650)
Don't show in changelog
2022-12-09 13:58:52 +01:00
AlexandreS
4797ce3a8a Update translations post translation bug (#4651)
Don't show in changelog
2022-12-09 11:03:22 +01:00
AlexandreS
a44a20d1d5 Add a few setup options when creating a new project (#4645) 2022-12-09 09:41:21 +01:00
Florian Rival
5f717643b3 Display just icons in the toolbar for preview/publish on small screens
Don't show in changelog
2022-12-08 18:51:43 +01:00
github-actions[bot]
346e08192c Update translations [skip ci] (#4641)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-12-08 17:18:10 +01:00
Florian Rival
f2eddd9c88 Add back the project manager icon in the home page for now
To avoid disturbing existing users too much and because otherwise it's super hidden in the main menu.
Will be better once "existing projects" listing is improved with a button to open the project manager.

Don't show in changelog
2022-12-08 17:04:26 +01:00
Florian Rival
d6e21d0854 Improve menus on the web-app (#4644)
* Faster navigation: submenus open when their item is hovered.
* Shortcuts are now shown like on the desktop app.
* Menu items height are fixed and always the same.
2022-12-08 16:01:39 +01:00
Florian Rival
db11465b87 Improve the split buttons and the preview button to make it clearer (#4642)
Don't show in changelog
2022-12-08 15:33:04 +01:00
AlexandreS
48c532ad71 Add object name in instruction keys and ids to avoid duplicates (#4623)
Do not show in changelog
2022-12-08 14:59:00 +01:00
AlexandreS
72319df6f1 Add possibility to install any resource in project (#4640)
Do not show in changelog
2022-12-08 12:23:14 +01:00
Florian Rival
c596335b7b Add some space to drag the titlebar even if a lot of tabs are opened
Don't show in changelog
2022-12-08 11:21:00 +01:00
github-actions[bot]
a9b42de64b Update translations [skip ci] (#4639)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-12-08 10:40:17 +01:00
AlexandreS
64ea3461d0 Make autocomplete dropdowns more visible (#4634)
Do not show in changelog
2022-12-08 09:34:25 +01:00
Florian Rival
cef473ca0e Update GitHub screenshot [skip ci]
Don't show in changelog
2022-12-07 18:12:14 +01:00
github-actions[bot]
9378b325d0 Update translations [skip ci] (#4635)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-12-07 17:56:45 +01:00
Clément Pasteau
238043655c Send gdevelopVersion for in-app-tutorials (#4636)
Do not show in changelog
2022-12-07 17:39:52 +01:00
Florian Rival
731a64aa0f Redesign the top tabs and toolbars in the app, so the app looks modern and takes less space on the top of the screens (#4630)
* On desktop, the titlebar is now gone and replaced by the tabs and a button to open the main menu of the app.
* On the web-app, if installed (available on Chrome and Edge), the titlebar can also be retracted. Whatever your system or device, the menu can be accessed from the top left.
* The top toolbars have been entirely redesigned to be integrated below the tabs - which is more intuitive for new users. All the icons have been reworked to be cleaner, take less space, and be more modern.
* The debugger toolbar was also improved to display just Play/Pause according to the game state.
* Finally, the project manager was slightly redesigned to use new icons.
2022-12-07 17:22:38 +01:00
github-actions[bot]
e1e7344ca5 Update translations [skip ci] (#4617)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-12-07 17:04:51 +01:00
Clément Pasteau
a5d5f0b7a5 Fix allowing to type "/" inside the path for project folder (#4633)
Do not show in changelog
2022-12-07 16:49:02 +01:00
Clément Pasteau
3dcbe46fc7 Improve warning when a project autosave is detected on Desktop (#4632)
* Autosave will not be displayed if the files are the same
* Prevent showing a warning when a project with an autosave is opened after being zipped
* Improve overall wording and dialogs
2022-12-07 16:46:38 +01:00
Florian Rival
4d3d96a889 Fix SemiControlledAutoComplete not using the value entered when pressing Enter in a InlineParameterEditor
Don't show in changelog
2022-12-07 12:03:10 +01:00
Clément Pasteau
23631cc2ce Allow entering a donation link on the user profile (#4628)
* Accepts any type of donation page, Ko-fi, Patreon, Paypal, Github...
* Once entered, it will appear on your Liluo.io Game and Profile pages
2022-12-06 17:21:34 +01:00
AlexandreS
3937b59d73 Use same border radius between command palette and autocomplete picker (#4629)
Do not show in changelog
2022-12-06 11:44:54 +01:00
Florian Rival
3b594ded7d Add Enter as a key to validate changes to a parameter in an event sheet (#4621)
* Shift+Enter can be used to enter new lines in expressions when editing a parameter inline
2022-12-06 10:37:55 +01:00
AlexandreS
e8a7cad17c Restore possibility to search texts with parenthesis in events parameters (#4625) 2022-12-06 10:30:18 +01:00
Clément Pasteau
2557cf556c Allow leaderboard color customisation (#4612)
* Silver and Gold subscribers can now customize their leaderboard with 4 different colors
2022-12-05 18:05:37 +01:00
AlexandreS
7c51f0af81 Add link to asset store license + Add message when no projects in the list (#4624)
Do not show in changelog
2022-12-05 16:56:41 +01:00
D8H
dc146a7411 Add a command to generate an action and an expression for a custom object property (#4620)
* Don't show in changelog
2022-12-04 20:27:17 +01:00
D8H
7620bac88a Enable serialization of JS code events and extension descriptions as arrays of strings (#4613)
* Only show in developer changelog
2022-12-04 13:38:08 +01:00
AlexandreS
c51e4be22d Display password prompt when requesting checkout session for asset pack (#4616)
Do not show in changelog
2022-12-02 18:17:38 +01:00
github-actions[bot]
98499dfc53 Update translations [skip ci] (#4610)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-12-02 12:17:48 +01:00
AlexandreS
36de82c93f Few fixes (#4611)
Do not show in changelog
2022-12-02 11:55:43 +01:00
Daniel R
7e97edcad0 Add a new tab "Folders" in Preferences to allow to choose the default folder where local projects are created (#4582) 2022-12-02 11:50:58 +01:00
D8H
5abb0fd9e3 Fix boolean property condition sentences (#4605) 2022-12-02 11:45:13 +01:00
D8H
d80c21244f Boolean property generated actions no longer miss the "Value" parameter (#4594) 2022-12-02 11:44:17 +01:00
D8H
70f4d545b4 Display some behavior properties in one row (#4606) 2022-12-02 11:37:32 +01:00
github-actions[bot]
85355c3f17 Update translations [skip ci] (#4609)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-12-01 17:27:19 +01:00
github-actions[bot]
044cc5354f Update translations [skip ci] (#4607)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-12-01 17:11:46 +01:00
AlexandreS
5ff02b11fc Fix a few MUI component imports (#4608)
Do not show in changelog
2022-12-01 17:05:23 +01:00
github-actions[bot]
9bf24f9baf Update translations [skip ci] (#4604)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-12-01 16:30:12 +01:00
AlexandreS
958482ee44 Suggest a new and more complete 3-chapter in-app tutorial (#4476) 2022-12-01 16:18:42 +01:00
AlexandreS
7a1fb5b033 Improve loading of Home Build section to reduce layout shifts (#4603) 2022-12-01 11:28:49 +01:00
D8H
33b2fb0168 Show unit of measurements on properties of built-in extensions (#4576) 2022-11-30 21:18:54 +01:00
Clément Pasteau
5cad2be194 Improve Toggle styling (#4602) 2022-11-30 15:23:43 +01:00
Clément Pasteau
2b38aa5445 Simplify assets loading to prevent unnecessary calls (#4601)
Do not show in changelog
2022-11-30 14:26:38 +01:00
D8H
32279f02e9 Fix function name collision between event-based objects from the same extension (#4598) 2022-11-30 14:10:52 +01:00
Clément Pasteau
7452358656 Trigger Rename & Focus for Object, Group, Layout, Events (#4591) 2022-11-30 10:52:15 +01:00
D8H
d2ec483d71 Changing custom object opacity now works (#4597) 2022-11-29 10:43:17 +01:00
github-actions[bot]
4cb62d15bf Update translations [skip ci] (#4589)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-28 15:53:08 +01:00
AlexandreS
96bdbfc70b Correctly deactivate cloud projects on desktop app in prod (#4592)
Do not show in changelog
2022-11-28 15:47:55 +01:00
Clément Pasteau
a64815f500 Fix missing text formatting (#4587)
Do not show in changelog
2022-11-28 15:47:39 +01:00
Clément Pasteau
5ab8a3cd73 Improve initial dialog logic to avoid opening tab on subsequent profile openings. (#4590)
Do not show in changelog
2022-11-28 15:45:12 +01:00
D8H
7d0ecf113a Add a command to generate an action and an expression for a property (#4565) 2022-11-28 14:30:03 +01:00
D8H
de30049182 Show parameters description in expression documentations (#4585) 2022-11-28 13:19:42 +01:00
Clément Pasteau
c2a1fb63e1 Fix opening initial dialog again after closing it (#4588) 2022-11-28 12:34:22 +01:00
github-actions[bot]
8562019953 Update translations [skip ci] (#4572)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-11-28 10:34:59 +01:00
Florian Rival
f8232953b5 Add support for cloud projects to the desktop app (#4240)
* Also add support for the asset store in the objects editors - like on the web-app.
2022-11-27 18:09:27 +01:00
AlexandreS
d52ac6fc3e Send subscription dialog opening reason (#4586)
Do not show in changelog
2022-11-25 18:12:03 +01:00
Clément Pasteau
be4aab6d5c Allow opening up the feedback tab from URL query params (#4574)
Do not show in changelog
2022-11-25 17:18:32 +01:00
Clément Pasteau
4ed8ff15dd Improve Asset pack install dialog (#4583)
Do not show in changelog
2022-11-25 11:33:00 +01:00
Clément Pasteau
2dd1105a10 Improve Game Feedback management (#4579)
* Display the average game ratings at the top
* Add an option to mark all as read
* improve readability by adding a number for each rating
2022-11-25 10:12:11 +01:00
Clément Pasteau
0fce6aaaaa Fix missing scroll on points and collision mask editors (#4578) 2022-11-24 15:51:22 +01:00
Florian Rival
29797b7a2f Add analytics data when opening an asset pack or an asset (#4573)
Don't show in changelog
2022-11-24 09:41:24 +01:00
Clément Pasteau
7df7f9f458 Remove help button on additional info dialog (#4570)
Do not show in changelog
2022-11-23 15:20:52 +01:00
github-actions[bot]
fc61fa2c54 Update translations [skip ci] (#4571)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-23 15:20:36 +01:00
D8H
fccd3b8f2e Fix the drag and drop of the extension editor. (#4568)
* Items were not drop at the right position when they were moved down.
2022-11-23 15:08:33 +01:00
github-actions[bot]
5ca91cfac4 Update translations [skip ci] (#4569)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-23 15:08:17 +01:00
Clément Pasteau
628d18ac5a Improve login and signup flow (#4566)
* Small design improvements to the Log in & Sign up flows
* A dialog is now shown for every user on signup to gather a bit of information about who they are.
  * This information stays of course private and is helpful to gather information about GDevelop's usage
2022-11-23 14:58:17 +01:00
github-actions[bot]
61d5c08549 Update translations [skip ci] (#4555)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-23 14:54:05 +01:00
Clément Pasteau
34497c2783 Fix cleaning the resource URL when added from the resource store (#4567)
Do not show in changelog
2022-11-22 19:11:18 +01:00
Clément Pasteau
4627facfd5 Improve Searchbar's design and usability (#4553) 2022-11-21 16:16:07 +01:00
D8H
aee15424f2 Save the scroll position of the asset store (#4528) 2022-11-18 17:06:10 +01:00
D8H
6c44f6e937 Physics2 behavior no longer step before the first frame (#4559)
* It allows events to access to the initial object positions.
2022-11-18 17:05:28 +01:00
Clément Pasteau
a115df260f Revert time before showing warning in object edition (#4558)
Do not show in changelog
2022-11-18 10:24:56 +01:00
Clément Pasteau
6e7bc9c809 Improve the snackbar messages when saving a cloud project (#4554) 2022-11-16 16:42:23 +01:00
Clément Pasteau
57ce8dcbbf Bump to 5.1.151 (#4552) 2022-11-15 14:50:36 +01:00
Clément Pasteau
f86d0197c1 Fix stories crashing storybook (#4551)
Do not show in changelog
2022-11-15 14:49:05 +01:00
github-actions[bot]
c7b0f345c7 Update translations [skip ci] (#4549)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-15 14:44:40 +01:00
Clément Pasteau
9803b4b8f4 Fix points and collision editor not showing scrollbars (#4550)
Do not show in changelog
2022-11-15 14:30:59 +01:00
D8H
ef4815a37e Tabs no longer disappear when scrolling in the extension editor dialogs (#4545) 2022-11-15 12:00:34 +01:00
D8H
fd7d27e727 Include tags in the search for extensions and examples (#4544) 2022-11-15 11:55:52 +01:00
D8H
ce94c6ae2f Fix a typo in the "Related expression and condition" field (#4548)
* Don't show in changelog
2022-11-15 11:46:10 +01:00
Florian Rival
c638a38275 Add a button to redeem a code for subscriptions (#4542) 2022-11-14 17:57:25 +01:00
github-actions[bot]
e539fdb0e9 Update translations (#4536)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-14 11:22:27 +01:00
Clément Pasteau
2a9193e4c2 Hide warning if backdrop behavior is set to cancel (#4543)
Do not show in changelog
2022-11-14 11:13:35 +01:00
github-actions[bot]
cf8361be0c Update translations (#4534)
Do not show in changelog
2022-11-10 15:57:05 +01:00
Clément Pasteau
2ba5f03e67 Fix animation preview not taking full space (#4535)
Do not show in changelog
2022-11-10 15:53:14 +01:00
Clément Pasteau
d9435eda5a Bump version to 5.1.150 (#4530) 2022-11-10 13:28:04 +01:00
github-actions[bot]
bc807acf8a Update translations [skip ci] (#4512)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-10 13:27:52 +01:00
Clément Pasteau
194b60aa72 Rework Dialogs and tabs design (#4520)
* Overall redesign or the dialogs to display a title and more margins, helping buttons be more discernable from the content + cross at the top to close them easily.
* Redesign of the tabs to be more intuitive.
2022-11-10 12:59:54 +01:00
D8H
02bbdfecd4 Allow event-based behaviors to declare scene properties (#4464) 2022-11-10 11:43:16 +01:00
D8H
bf19ec5a68 [PathFinding] Improve pathfinding with a property to smooth the path. (#4515) 2022-11-10 11:40:07 +01:00
Florian Rival
59094110ca Serialize JS code events and extension descriptions as arrays of strings to make collaboration/reviews easier (#4468)
Only show in developer changelog
2022-11-09 18:39:23 +01:00
D8H
a35ead0ab2 Panel sprite objects now respect the resource smoothing option (#4526) 2022-11-09 15:21:31 +01:00
Clément Pasteau
669c10c462 Slightly improve animation preview zoom for the image to fit the canvas (#4527) 2022-11-09 14:16:57 +01:00
Clément Pasteau
2859f2a3b6 Improve Selection of resources in parameters (#4524)
* A button is now available to pick a file
* When there is only 1 external editor like Piskel, the button is made more visible
2022-11-09 10:41:35 +01:00
D8H
be675fc5e6 [Platformer] Make tests with events side effects more realistic (#4518)
* Don't show in changelog
2022-11-08 12:41:48 +01:00
Aurélien Vivet
2be238bc9e Fix Inconsistency in JSON Parsing events wording (#4514) 2022-11-08 11:26:36 +01:00
AlexandreS
5c08fb06d8 Display leaderboard limit in leaderboard admin for free accounts (#4497) 2022-11-07 16:52:18 +01:00
D8H
8ec96a7446 Fix the color property definition editor layout (#4513)
* Don't show in changelog
2022-11-07 15:30:25 +01:00
D8H
792ce82a28 Add a setting to show the custom object editor (#4503) 2022-11-07 12:06:33 +01:00
github-actions[bot]
da444d53cd Update translations [skip ci] (#4511)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-11-07 10:38:28 +01:00
D8H
62a6d42488 Add autocompletion for choices and color property private actiton and condition parameters (#4481) 2022-11-07 10:24:53 +01:00
D8H
53e70c5a8f Add conditions to compare function parameter values (#4498) 2022-11-07 10:21:55 +01:00
Clément Pasteau
74ffba0f17 Fix Posthog alias (#4496)
Do not show in changelog
2022-11-07 10:18:26 +01:00
Clément Pasteau
4e03cf559d Handle new format for public asset resources (#4457)
Do not show in changelog
2022-11-07 10:16:12 +01:00
github-actions[bot]
4f5690503e Update translations [skip ci] (#4459)
* Don't show in changelog
2022-11-06 13:30:23 +01:00
D8H
8ac7284118 Allow to declare private event-based behaviors (#4479)
* It allows event-based objects to use behaviors internally without showing them to extension users.
2022-11-05 20:45:29 +01:00
D8H
16cdc9a047 Fix: parameter default value changes were not saved (#4489)
* Don't show in changelog
2022-11-04 18:16:46 +01:00
Clément Pasteau
ee43afa301 Show a warning when closing an editor dialog with a few unsaved changes (#4490)
* Applies on multiple editors: Object, Object group, Project properties, Variables list and Layers
2022-11-04 16:20:43 +01:00
AlexandreS
92bc846190 Add possibility to use markdown for asset descriptions (#4492)
Do not show in changelog
2022-11-04 14:18:38 +01:00
D8H
beb832be8b Fix flip instruction icons for custom objects (#4482)
* Don't show in changlog
2022-11-03 21:30:43 +01:00
D8H
961c78b468 Fix number expression field. (#4483)
* Don't show in changelog
2022-11-03 21:30:00 +01:00
D8H
2d7467bc27 Avoid to use regex look ahead as Safari doesn't support it. (#4480) 2022-11-03 09:33:16 +01:00
Clément Pasteau
0a9d9b940b Fix Animation Preview not taking full height and being stuck when duplicating an image (#4470) 2022-11-02 13:41:35 +01:00
D8H
f8bd457346 Translate event-based extension categories (#4471) 2022-11-02 10:21:35 +01:00
AlexandreS
6deeae76c5 Do not prevent inline parameter editor to be opened after dragging an action/condition 2022-11-02 10:18:31 +01:00
Clément Pasteau
473b16bbc1 Introduce no-unused-vars ts rule for GDJS & Extensions (#4469)
Do not show in changelog
2022-10-31 14:52:03 +01:00
Clément Pasteau
20a328dcd6 Fix Changelog displaying extensions bullet points properly (#4472) 2022-10-31 14:49:34 +01:00
AlexandreS
578aae7a69 Fix animation finished condition firing too early (#4444)
The condition was firing as soon as the animation was entering its last frame.
It now waits for the last frame to be displayed long enough (based on frame interval duration).
This fix applies to all future "Animation finished" conditions, current ones are not affected.
2022-10-31 09:06:15 +01:00
D8H
27f89b1b0f Fix events sheet warping when it contains a JS event (#4466) 2022-10-30 19:51:13 +01:00
D8H
bc75d6003c Add back parts of a revert for the TextImput fix (#4453)
* Don't show in changelog
2022-10-30 14:20:53 +01:00
D8H
fd03deb4ea Allow event extensions to define conditions and actions with an operator (#3909) 2022-10-29 23:20:10 +02:00
D8H
71f20d7852 Refactor to make some ParameterMetadata attributes private (type, supplementaryInformation and optional) (#4437) 2022-10-29 13:02:18 +02:00
D8H
9d121d0085 Suffix properties private instruction names with "property" to avoid them to overlap public ones (#4436) 2022-10-29 13:01:07 +02:00
Clément Pasteau
6292e338bc Fix importing path correctly on web (#4458) 2022-10-28 17:58:24 +02:00
Clément Pasteau
c5eb0bcc00 Bump version to 5.1.149 (#4451) 2022-10-28 11:23:50 +02:00
github-actions[bot]
a732fda4d9 Update translations [skip ci] (#4430)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-10-28 11:20:33 +02:00
Clément Pasteau
398bff8492 Fix input not being positioned properly (#4450) 2022-10-28 11:11:24 +02:00
D8H
f30e92a953 Make scene properties look the same as behavior properties (#4448)
* For instance, scene properties are used by the Physics2 behavior.
2022-10-27 21:48:52 +02:00
AlexandreS
8210c25acb UI improvements (#4440)
- Make some popovers and panels more discernable from the background
- Use the same drag and drop behavior for layers list as for the objects list on the scene editor
- Add object icons in the list of objects in a group
2022-10-27 10:23:05 +02:00
AlexandreS
6a13940e17 Add possibility to send instances to back or to front (Z order) in context menu (#4443) 2022-10-27 09:47:54 +02:00
AlexandreS
622aa7c08c Add warning message when updating liluo.io thumbnail from the project icons dialog (#4438) 2022-10-26 11:52:49 +02:00
Clément Pasteau
a71558a490 Create condition to know when a draggable object was just dropped (#4441) 2022-10-26 09:31:14 +02:00
Clément Pasteau
37539aa788 Rename Panel actions for consistency (#4439) 2022-10-25 18:45:23 +02:00
AlexandreS
789f819f25 Fix events sheet not wrapping on small screens (#4434) 2022-10-25 10:43:27 +02:00
AlexandreS
52ebfb8100 Remove starting value in tween variable actions
Also:
- Change phrasing for object tweens
2022-10-25 08:53:37 +02:00
Clément Pasteau
ecc5c689d2 Revert service worker update (#4432)
Do not show in changelog
2022-10-24 18:48:30 +02:00
Florian Rival
5b1e169557 Show variables that were used in the events, but not defined, in the autocompletions by default
* If you've not activated this since this was introduced, you can do so in the preferences.
2022-10-24 17:43:30 +02:00
Clément Pasteau
386e23b042 Bump version to 5.1.148 (#4429) 2022-10-24 12:11:18 +02:00
github-actions[bot]
fc76bafc7c Update translations [skip ci] (#4393)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-10-24 12:11:00 +02:00
AlexandreS
de53f4df4f Fix project name not updating in recent project files after saving (#4428) 2022-10-24 12:02:16 +02:00
D8H
9fedf124db Allow assets to declare extension dependencies without behaviors (#4354) 2022-10-22 14:40:47 +02:00
Clément Pasteau
2c68bb4bdd Modify the asset store to handle priced asset packs 2022-10-21 18:16:38 +02:00
AlexandreS
2360cf899f Performance optimization: Prevent pixi from rendering if any dialog is opened (#4415) 2022-10-21 15:01:04 +02:00
AlexandreS
3fc57c2b06 Add some particle emitter actions conditions and expressions (#4419)
- Max number of displayed particles
- Particle rotation min and max speeds
- Additive rendering setting
2022-10-21 14:04:44 +02:00
AlexandreS
b4f41e96ae Fix: Set line particle emitter origin at 0 to prevent rotation offset (#4421) 2022-10-21 12:29:09 +02:00
AlexandreS
b20108ddcb Fix particle emitter incoherent rotation speed of the particles (#4417) 2022-10-21 12:28:09 +02:00
AlexandreS
a58b039994 Update instance properties panel after a layer was created or renamed (#4420) 2022-10-21 12:13:57 +02:00
D8H
a7f218622e Add a button to export custom objects for the asset store (#4363)
* Don't show in changelog
2022-10-21 11:38:32 +02:00
AlexandreS
8d95eb4269 Fix: Ensure particle max force is not zero to prevent PIXI bug (#4418) 2022-10-20 18:20:27 +02:00
AlexandreS
4e46690418 Create homemade solution to display in app tutorials (#4394)
Do not show in changelog
2022-10-20 15:39:12 +02:00
Florian Rival
db1737281e Add word wrap in the code editors to avoid horizontal scrolling (#4413)
* Also fix some text overflowing out of the screen for some languages.

Fix #4412
2022-10-19 14:38:57 +02:00
AlexandreS
d5eecda570 Improve new scrollbars on scene editor canvas (#4411)
Do not show in changelog
2022-10-19 11:22:07 +02:00
D8H
80cb6d697c Handle custom objects at runtime (#4294)
* Don't show in changelog
2022-10-18 13:36:48 +02:00
Clément Pasteau
6b08fec747 Add missing translation for pasting an object (#4408) 2022-10-18 12:31:00 +02:00
D8H
2c92ce74ce Fix custom object configurations copy constructor (#4404)
* Don't show in changelog
2022-10-17 16:26:27 +02:00
D8H
30643ced07 Add some stories for event-based objects (#4401)
* Don't show in changelog
2022-10-16 23:57:18 +02:00
Peter Anderson
bf27761cff Fix grammar: change 'let' to 'leave'. (#4399) 2022-10-16 13:43:14 +02:00
Florian Rival
58df3aeca1 Show an error message if a sentence of a function of an extension is using a parameter that does not exist (#4395) 2022-10-14 23:15:30 +02:00
AlexandreS
69f8961e9e Fix: Keep variable name checks only for top level variables (#4392) 2022-10-14 15:57:59 +02:00
github-actions[bot]
1abb39ec17 Update translations [skip ci] (#4360)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-10-14 14:31:07 +02:00
Clément Pasteau
c5226c1e45 Fix clearing storage provider on project close (#4390)
Do not show in changelog
2022-10-14 14:06:02 +02:00
Florian Rival
d40789005b Add link to Liluo.io in the README
Don't show in changelog
2022-10-13 18:24:02 +02:00
D8H
fcbe5c364e Add a field to define behavior property descriptions (#4389) 2022-10-13 15:38:09 +02:00
D8H
df3433c55f Add autocompletion for timers, tweens and other extensions identifiers (#4386) 2022-10-13 13:39:53 +02:00
D8H
7d892fd976 Update extension field hints to fit the good practices (#4375) 2022-10-13 13:19:51 +02:00
D8H
56320d7253 Move some stories to LayoutEditor and ObjectEditor (#4388)
* Add a story for a custom object property editor.
* Add a story for the particle emitter editor.
2022-10-13 09:51:49 +02:00
AlexandreS
05acd061bd Fix leaderboard entry creation duplicate conditions to avoid spamming servers 2022-10-12 18:03:01 +02:00
Clément Pasteau
7991ceb351 Improve the editor scrollbars to be more intuitive (#4377) 2022-10-12 16:35:27 +02:00
Clément Pasteau
bf6d18ccbe Notify when a new version is available to be automatically installed on the web (#4371) 2022-10-12 16:31:58 +02:00
AlexandreS
536b7dcc62 Fix: Wrap text of game feedback when it's a single really long word 2022-10-12 11:45:51 +02:00
AlexandreS
a157f32d4a Fix: Update window border in scene editor when the project resolution is changed 2022-10-12 11:02:37 +02:00
Clément Pasteau
49f579f32d Allow using private assets in the asset store (#4355)
* Once a pack is bought, the assets are visible in the asset store directly
* The asset can be added when the project is saved locally, or on the cloud
* Fix Storage Provider being correctly reset when closing/opening a project
2022-10-11 13:59:40 +02:00
Clément Pasteau
8f4ecd373f Get Game categories from backend allowing more flexibility for jams (#4370)
Do not show in changelog
2022-10-07 18:32:33 +02:00
Aurélien Vivet
a3a53415b1 Add missing id for the onboarding (#4369)
Don't show in changelog
2022-10-07 15:49:13 +02:00
Aurélien Vivet
c278c0a432 Fix parameters order in the events sheet sentence of "Change the gradient of the text" action (#4368) 2022-10-07 10:40:39 +02:00
AlexandreS
862f270b83 Fix extension icon store displaying white hard-to-see icons on light theme 2022-10-07 09:56:55 +02:00
AlexandreS
7232dbc2fa Fix: Reinitialize object default hitboxes when reinitializing it (#4362) 2022-10-06 17:38:39 +02:00
AlexandreS
78cbe48718 Fix points editor not updating correctly when deleting points 2022-10-06 12:40:04 +02:00
Florian Rival
e153d295de Bump newIDE version 2022-10-06 10:35:33 +02:00
AlexandreS
1b8510655e Revert "Add expression and condition to get highest z order of a layer (#4346)" (#4359)
Don't show in changelog
2022-10-06 10:34:41 +02:00
github-actions[bot]
bd88127563 Update translations [skip ci] (#4342)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-10-06 10:25:39 +02:00
AlexandreS
01b9f09604 Fix: Add parameter to file reading actions to remove CR characters from files (#4352)
⚠️ If you had encountered an issue linked to this and changed your events to fix it, you might need to update your project and set this new parameter to "No"
2022-10-05 14:11:21 +02:00
Florian Rival
0db30f02c9 Add support for opening onboarding directly on the web-app
https://editor.gdevelop.io/?initial-dialog=onboarding

Don't show in changelog
2022-10-04 16:03:12 +02:00
D8H
a852e91690 Add missing expression group icons (#4353) 2022-10-04 14:56:59 +02:00
AlexandreS
79d6281061 Add expression and condition to get highest z order of a layer (#4346) 2022-10-04 14:31:49 +02:00
AlexandreS
eba6b2540c Add price to assets home private asset packs thumbnails and display them in their dialog (#4350)
Don't show in changelog
2022-10-04 12:13:25 +02:00
D8H
0706a54305 Reorganize extensions categories (#4345) 2022-10-04 10:37:27 +02:00
D8H
d929fd6e48 Add a test on sprite hit-boxes after a camera displacement (#4349)
* Don't show in changelog
2022-10-03 14:17:01 +02:00
Florian Rival
4dbabab052 Bump newIDE version 2022-09-30 15:43:18 +02:00
D8H
827c5d6442 Add an extension category filter (#4341) 2022-09-30 15:14:23 +02:00
Florian Rival
46be0e0ffc Change previews so that they use the development environment for GDevelop APIs if running GDevelop development version (#4343)
Only show in developer changelog
2022-09-30 14:55:50 +02:00
github-actions[bot]
72e3cf5b99 Update translations (#4313) 2022-09-30 10:12:34 +02:00
D8H
54f32a2542 Add new categories for extensions (#4331) 2022-09-29 18:24:06 +02:00
D8H
b826f66455 Make the custom object renderer works better with 9-patch and text child-objects (#4335)
* Don't show in changelogs.
2022-09-29 17:16:41 +02:00
D8H
6fc03cccc6 Add help buttons in the expression editor and the extension details dialog (#4337) 2022-09-29 15:44:16 +02:00
AlexandreS
ed7313a330 Add invert condition shortcut (J key by default - configurable in your preferences) (#4334) 2022-09-29 11:18:33 +02:00
D8H
7390f7cd6a Ensure required behavior properties can't be hidden (#4336) 2022-09-29 09:54:01 +02:00
D8H
4619ae824b Allow event-based objects to define a default name for created objects (#4329)
* Don't show in changelogs
2022-09-28 17:43:51 +02:00
D8H
0f69ee435f Add tests on behavior properties initialization and unserialization (#4314)
* Don't show in changelogs
2022-09-28 17:43:18 +02:00
AlexandreS
f46241d5a2 Fix bug that prevented converting a variable to JSON when one previously tried to access an out-of-index child in a variable array (#4333) 2022-09-28 17:39:53 +02:00
D8H
4c8ec48004 Add subsections for extensions categories in the Wiki (#4332)
* Add a warning message on pages for extensions from the community list.
2022-09-28 15:34:03 +02:00
AlexandreS
3ac121be4c Add asset packs that can be purchased in the Asset store home (#4328)
Do not show in changelog
2022-09-28 15:29:45 +02:00
D8H
3aa636861c Custom objects take the icon of one of their sprite child (#4316)
* Don't show in changelogs.
2022-09-27 16:19:12 +02:00
D8H
6d4b422be6 Fix extension description links on the Wiki (#4325) 2022-09-27 16:18:18 +02:00
Clément Pasteau
b8ee27f62c Improve player authentication
* Improve player authentication by indicating when the game is not registered
* Show a link to open the window if blocked

Do not show in changelog
2022-09-27 15:19:06 +02:00
AlexandreS
6996ff452d Fix various memory leaks when using the app (#4323) 2022-09-23 18:34:34 +02:00
AlexandreS
da7934c6ac Add context menu items to manipulate the view on the scene editor (#4307)
- Return to initial position (view matches the game resolution)
- Fit zoom to selected instances
- Fit zoom to the whole scene
- Select all instances of an object on the scene (in the context menu of an object)
2022-09-23 13:27:40 +02:00
Clément Pasteau
90bebcb404 Create GDevelop Authentication extension
* This is an experimental extension!
* It allows you to provide a login/register form to your players, with 1 action
* It connects the player automatically when they launch your game again
* It also provides a new action to submit a leaderboard entry without having to enter a username
* This is the beginning of Player Authentication and more features will come allowing creators to interact with their players
2022-09-23 10:44:58 +02:00
D8H
a29e7aae44 Bump newIDE version (#4317) 2022-09-22 12:22:11 +02:00
D8H
52201e2a36 Fix tiles rotation that was no longer applied in tile maps (#4315) 2022-09-22 10:25:38 +02:00
Florian Rival
50465badd7 Bump newIDE version 2022-09-21 10:01:17 +02:00
D8H
6e1bfb0190 Fix properties on the scene of the Physics behavior not working ("shared data" of behaviors not handled properly) (#4310) 2022-09-21 09:56:38 +02:00
Aurélien Vivet
40c7c57670 Add issue template for Asset Store Submission [skip ci] (#4309)
Don't show in changelog
2022-09-20 21:43:43 +02:00
github-actions[bot]
e51c73b293 Update translations [skip ci] (#4306)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-09-19 11:16:17 +02:00
Florian Rival
29d5d5fe75 Bump newIDE version 2022-09-19 10:23:17 +02:00
AlexandreS
6e1f2c4eee Fix parameter fields being reset to their old value after being changed (#4308) 2022-09-19 09:28:50 +02:00
Florian Rival
2f2a89faf6 Use a purple heart instead of a red one to look less like an error
Don't show in changelog
2022-09-16 12:23:15 +02:00
AlexandreS
4100b24dfd Improve display of black icons on dark themes (#4302) 2022-09-16 12:22:11 +02:00
AlexandreS
c616abe1c5 Bump newIDE version 2022-09-16 10:45:10 +02:00
Aurélien Vivet
35084de4f6 Add a new expression: Pi number (3.1415...) (#4304) 2022-09-16 10:30:46 +02:00
github-actions[bot]
6ecb5e9d8c Update translations [skip ci] (#4291)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-09-16 10:09:03 +02:00
D8H
9532a8f6de Fix extension upgrades that was leaving duplicated behaviors. (#4301)
- Don't show in changelogs (the regression is between the 140 and the 141)
2022-09-15 15:43:28 +02:00
D8H
00a5b0b402 Fix events-based behavior default name. (#4300)
* Don't show in changelogs (the regression is between the 140 and the 141)
2022-09-15 11:57:28 +02:00
D8H
629567ad21 Fix tile maps with rectangular tiles (#4299) 2022-09-14 19:04:42 +02:00
D8H
5f21229ccc Remove a file commited by mistake (#4296) 2022-09-14 18:40:48 +02:00
Florian Rival
27cf2ef596 Remove shadow on home page menu buttons
Don't show in changelog
2022-09-14 16:44:47 +02:00
AlexandreS
2bc9a6d19d Fix previews on private navigation for cloud projects
Do not show in changelog
2022-09-14 16:29:15 +02:00
Florian Rival
c6c586459c Update the subscriptions plans to reflect the new ones and their updated benefits (#4290)
* Read [the blog post](https://gdevelop.io/blog/new-premium-subscriptions-online-services) for a full description of the updates and online services unlocked by the updated (and the existing) plans.
2022-09-14 11:33:37 +02:00
AlexandreS
a930011d8d Bump newIDE version 2022-09-14 10:24:54 +02:00
github-actions[bot]
51d723bd3d Update translations [skip ci] (#4284) 2022-09-14 10:21:23 +02:00
D8H
b63f968011 Fix resource refactoring for child-objects (#4289)
* Don't show in changelogs.
2022-09-14 09:41:07 +02:00
Florian Rival
3387c553d8 Fix previews not loading audio/font/json resources uploaded with the web-app (#4285)
Don't show in changelog
2022-09-13 16:41:33 +02:00
D8H
441cd20846 Fix a crash when renaming a child-object (#4281)
* Add tests for object renaming in events.
* Don't show in changelogs.
2022-09-13 12:46:20 +02:00
AlexandreS
f9871bd63d Add supported formats mimtypes to resource selector input accept attributes (#4283)
[skip-ci]
2022-09-13 11:51:22 +02:00
github-actions[bot]
bac11b3818 Update translations [skip ci] (#4230)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-09-13 10:37:01 +02:00
D8H
3e32cb8cea Fix the events-based objects editor that were never showing up in dev mode (#4279)
* Don't show in changelogs
2022-09-12 10:48:22 +02:00
Florian Rival
db74a59730 Add support for markdown in announcements (#4280)
Don't show in changelog
2022-09-12 10:28:32 +02:00
D8H
e7d09531b7 Fix event-based behavior properties default values that were ignored (#4276)
* Don't show in changelogs
2022-09-09 17:56:27 +02:00
Florian Rival
97cf19180b Rename Behaviors/Functions to Extensions in the project manager (#4272)
Don't show in changelog
2022-09-09 14:08:13 +02:00
Florian Rival
5cc999c0a3 Add announcements and news in the homepage community tab (#4273)
* Also display "urgent" announcements at the top of the home page (which can be dismissed).
2022-09-09 10:50:49 +02:00
D8H
5eb0aa9e14 Add an instance render for custom objects (#4251)
* Don't show in changelogs
2022-09-06 12:41:38 +02:00
D8H
7f528649d7 Revert the RendererInstance parameter for the tile map extension (#4260)
* Don't show in changelogs
2022-09-05 19:38:47 +02:00
D8H
c4f44daa8c Expose a gdObject constructor for the asset script (#4268)
* Don't show in changelogs.
2022-09-05 16:14:54 +02:00
AlexandreS
7d00e78628 Change the name of exports to be based on the name and version of the game 2022-09-05 12:12:39 +02:00
Aurélien Vivet
887ced270a Add the possibility to receive the GDevelop newsletter from the Profile and on Signup (#4256) 2022-09-05 10:32:30 +02:00
D8H
b8e9bc801a Add a properties editor for custom objects (#4227)
* Don't show in changelogs
2022-09-02 14:13:41 +02:00
D8H
7f023e1a58 Remove useless SetIncludeFile call. (#4255)
- Most of them has a wrong path anyway.
- Don't show in changelogs.
2022-09-01 14:30:24 +02:00
AlexandreS
6606ddb260 Improve SVG display in Resource Store for dark themes 2022-09-01 09:31:04 +02:00
Clément Pasteau
a682c1baa8 Update "Submit New Extension" link with new format (#4254) 2022-08-31 14:47:32 +02:00
Clément Pasteau
d581af20e1 Improve Signup and Edit profile to show when a username is not available 2022-08-31 13:59:14 +02:00
Florian Rival
2abf636283 Fix tests on Windows
Don't show in changelog
2022-08-30 18:15:08 +02:00
D8H
7d09853c12 Fix tile maps layer filtering (#4249) 2022-08-30 14:31:28 +02:00
AlexandreS
bb88f3ae4d Add button to release notes in about dialog
Do not show in changelog
2022-08-30 13:52:10 +02:00
D8H
44b06039e1 Upgrade the Pixi tile map extension to 3.2.2 (#4212)
* It also lifts the 16,000 tiles limit.
2022-08-30 13:11:59 +02:00
Clément Pasteau
9c7f2e4293 Remove user public profile search type (#4243)
Do not show in changelog
2022-08-30 11:26:12 +02:00
AlexandreS
facbbe614d Add button in changelog dialog to read on Github to benefit from browser translator 2022-08-30 11:09:15 +02:00
AlexandreS
d5cadadf82 Fix browser translator crashing the app 2022-08-29 11:30:52 +02:00
D8H
aed4b76a3f Refactor behavior configuration model (#4217)
* Merge BehaviorContent into Behavior and add CustomBehavior
* Don't show in changelogs
2022-08-29 09:21:21 +02:00
Florian Rival
b1e03f4555 Add support for uploading your own files from your device for cloud project on the web-app (#4225)
* You can now upload your own files when working on the web-app, when your project is saved as a Cloud project.
* This means the web-app can be used without limits to build any game you could build on the desktop app.
* Support for Cloud projects on the desktop app will be available soon. You will also be able to save an existing project on your computer as a cloud project, or vice versa.
2022-08-28 22:30:58 +02:00
D8H
93be3153b5 Fix useless "Change" prefix in some actions name (#4238) 2022-08-28 21:44:23 +02:00
Aurélien Vivet
d0c9ff6754 Fix the action to tween the number of a scene variable (#4235) 2022-08-28 16:53:16 +02:00
AlexandreS
a5cf0896bc Fix the wording of the layer field when the layer is not optional (though it has a default value: the base layer) (#4232) 2022-08-26 17:12:40 +02:00
Clément Pasteau
7f6ce26c43 Handle players logging in to GDevelop and becoming creators (#4231)
Do not show in changelog
2022-08-26 13:51:45 +02:00
AlexandreS
eda9db6b40 Fix points coordinates inputs not losing focus when moving points on the preview 2022-08-26 09:55:37 +02:00
github-actions[bot]
b9405f5e7d Update translations [skip ci] (#4220)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-08-26 09:26:08 +02:00
Clément Pasteau
ca591f60d6 Improve game templates visibility
* Change "Create a new project" action from the command palette to directly open a blank project
* Add 2 new actions in the Desktop menu "Create an empty project" and "Create a project from a template"
* Templates are now displayed at the top of the Build section
* The button "Create a project" in the Build section now directly opens a blank project
2022-08-25 16:49:37 +02:00
Peter Anderson
214e012ec4 Rename object variables expression names to differentiate number and text variables. 2022-08-25 15:32:39 +02:00
Aurélien Vivet
9cc0172a60 Add Educational tag for games on Liluo.io (#4222) 2022-08-25 10:20:34 +02:00
Florian Rival
6e01228ae6 Fix Safari/iOS unable to load some images in the app (#4148) 2022-08-24 12:25:33 +02:00
github-actions[bot]
e22611625e Update translations [skip ci] (#4205)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-08-22 14:58:20 +02:00
Clément Pasteau
28ccb55a06 Improve onboarding banner (#4216)
Do not show in changelog
2022-08-22 14:41:07 +02:00
D8H
7893b892a3 Add an events-based object editor prototype (#4208)
* don't show in change logs
2022-08-22 14:05:58 +02:00
Arthur Pacaud
10b3c50a42 Fix parameter to specify the P2P port not being an expression (#4215) 2022-08-22 12:00:09 +02:00
D8H
8c5fbc6e34 Add missing translations for some messages shown when renaming an object (#4213) 2022-08-21 19:00:10 +02:00
Aurélien Vivet
a40382333b Fix the name of the "End Opacity" condition of the particle emitters (#4214) 2022-08-21 16:47:43 +02:00
Florian Rival
fb95f26fbb Update artifacts download script to include arm64 build artifacts [skip ci] [ci skip]
Don't show in changelog
2022-08-18 10:14:08 +02:00
Florian Rival
48a90ae86d Display a super thin or invisible scrollbars for the toolbar and tabs, according to the browser 2022-08-18 09:16:49 +02:00
Florian Rival
6303a50a9d Enable macOS build for Apple Silicon and arm64 builds for Linux (#4031) 2022-08-17 16:02:25 +02:00
D8H
a47ec5199e Limit the number of autocompletion elements displayed for extensions search tags. (#4207)
Don't show in changelog
2022-08-17 11:43:24 +02:00
D8H
a6921c2de3 Fix the extensions search bar that was only using the first 30 tags alphabetically (#4206) 2022-08-17 10:17:57 +02:00
Florian Rival
b21b6f0dfb Bump newIDE version 2022-08-16 18:01:34 +02:00
Florian Rival
c0d4480099 Update AdMob to declare AD_ID permission on Android, as required for Android 13 2022-08-16 17:50:53 +02:00
github-actions[bot]
56277ff5d3 Update translations [skip ci] (#4204)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-08-16 17:04:22 +02:00
Florian Rival
4fa1fbd5e2 Remove useless files being scanned for translations
Don't show in changelog
2022-08-16 16:51:30 +02:00
Florian Rival
f61ef1be2e Add monetization tab in game dashboard
* Allow to enable or disable ads on the game page if published on Liluo.io
* In the future, games that generate enough revenue will be able to opt-in into "revenue share", so that as a creator you can start earning from your game sessions.
* This also this allows to maintain free publishing on Liluo.io for all.
2022-08-16 16:40:52 +02:00
github-actions[bot]
bf387631ec Update translations [skip ci] (#4173)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-08-16 14:18:32 +02:00
Florian Rival
981752af26 Make compile-translations script more robust
Don't show in changelog
2022-08-16 14:09:52 +02:00
Florian Rival
58e5933c75 Update GDevelop logo in the about dialog
Don't show in changelog
2022-08-12 22:47:23 +02:00
Florian Rival
237ad8ce39 Show the full version number in the About dialog, and the update status for the web-app (#4202) 2022-08-12 20:41:23 +02:00
Florian Rival
02225cb0ec Move the preferences button in the home page (#4201)
* Also display the full GDevelop version number in the "About GDevelop" button in the home page - useful to check if you're on the latest version when using the web-app
2022-08-12 19:26:09 +02:00
Florian Rival
b34426e084 Add support for Android 12 splashscreen icon (#4200) 2022-08-12 18:48:10 +02:00
Florian Rival
23c09f3472 Fix buttons to download exported games not shown as primary buttons 2022-08-12 17:01:59 +02:00
D8H
59a7690748 Fix the "move parameter" refactor for expressions in the extension editor (#3968) 2022-08-12 14:04:12 +02:00
Aurélien Vivet
3e97d4b878 Clarify the name of the actions to resume a paused sound/music (#4199) 2022-08-12 12:20:27 +02:00
Florian Rival
d710dd0335 Fix sourcemap of Box2D wasm source wrongly included when exporting
Don't show in changelog
2022-08-11 21:53:13 +02:00
Aurélien Vivet
78695b6b17 Fix wrong description of Firebase "Check for a document's existence" action (#4198) 2022-08-11 21:48:24 +02:00
Florian Rival
4e3dec4356 Upgrade Admob so that it works with the latest Android SDK, required to publish apps on the Play Store (#4197) 2022-08-11 17:33:40 +02:00
D8H
f373e3b8d1 Fix the export of game using Box2d WASM library (#4195)
Don't show in changelog
2022-08-11 15:42:47 +02:00
Clément Pasteau
3e71c3a63f Fix saving project after creation (#4194)
Do not show in changelog
2022-08-10 11:31:49 +02:00
Clément Pasteau
86cad044d4 Add a test button to display staging assets in dev (#4170)
Do not show in changelog
2022-08-10 11:18:03 +02:00
Florian Rival
21b525ab98 Fix raycast condition not working properly on objects with multiple hitboxes (#4186) 2022-08-09 11:21:57 +02:00
Clément Pasteau
fb328fd0f5 Install fixes (#4190)
Do not show in changelog
2022-08-09 10:06:49 +02:00
Aurélien Vivet
afdb934a8a Fix typo (#4191) 2022-08-08 17:56:41 +02:00
AlexandreS
530f756e47 Add possibility to seal an instance (impossible to select it on the canvas) 2022-08-08 14:20:11 +02:00
Sebastian Krzyszkowiak
b1fb207a08 Minimize in game/real cursor flickering when showing/hiding the cursor (#4184) 2022-08-05 23:17:35 +02:00
Florian Rival
5f87213ccd Improve messages when reaching the maximum count of cloud projects 2022-08-05 22:56:21 +02:00
Florian Rival
9065454bfe Add more cloud projects for GDevelop online subscribers (#4183)
Don't show in changelog
2022-08-05 18:33:14 +02:00
Florian Rival
801fbb4b10 Fix orange outline sometimes appearing around the scene editor canvas 2022-08-05 18:29:22 +02:00
D8H
cfa538ec3d Fix the collision mask of rotated tiles that were sometimes misplaced (#4181) 2022-08-05 18:10:06 +02:00
D8H
504443dea4 Fix a game analytics test (#4182)
It was building data with fixed dates that were processed using the real today date.
Don't show in change logs.
2022-08-05 16:56:39 +02:00
Florian Rival
bdbc665d2e Fix exported WebManifest file having a syntax error when the game description has line breaks
Fix #4180
2022-08-05 09:13:25 +02:00
D8H
1d77f2da23 Replace the Box2D library with a WebAssembly one (#4153)
* It fixes a crash of the old Box2D library when a lot of objects with the Physics2 behavior were created.
* The same version of Box2d (2.3.1) is still used so there should not be any behavior change.
2022-08-04 18:11:00 +02:00
AlexandreS
7b6aa78aeb Fix memory leak at the end of a cloud project save (#4178)
Do not show in changelog
2022-08-04 16:19:09 +02:00
AlexandreS
e9aaed9d41 Fix json resource removed from project resources although it is used in event 2022-08-04 14:05:42 +02:00
Florian Rival
982c9e38c1 Add support for subscribing to GDevelop premium accounts with PayPal (#4166)
* You can now get a subscription, support GDevelop development and get more one-click online exports every day, using PayPal (or using credit cards as done previously).
2022-08-03 23:00:08 +02:00
Arthur Pacaud
c86388018c Add tween actions for camera zoom and camera rotation (#4174) 2022-08-03 22:21:45 +02:00
AlexandreS
6ae1b62df7 Add possibility to remove a project from the recent project list
Do not show in changelog
2022-08-03 17:42:33 +02:00
AlexandreS
ea745a49d7 Set storage provider before opening file metadata (#4175)
Do not show in changelog
2022-08-03 17:28:16 +02:00
AlexandreS
48fc2f640b Fix google drive project display in build section
Do not show in changelog
2022-08-03 16:31:15 +02:00
github-actions[bot]
a86ee8c338 Update translations [skip ci] (#4139)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-08-03 15:52:37 +02:00
AlexandreS
1787b3c5c8 Improve communication around cloud projects
Do not show in changelog
2022-08-03 15:42:20 +02:00
D8H
3e246e3cf0 Fix the loading of tile map atlases that was aborted when the image contains unused pixels at the right or bottom. (#4167) 2022-08-02 10:53:04 +02:00
AlexandreS
5035d16bd4 Improve game dashboard naming
Do not show in changelog
2022-08-01 17:04:41 +02:00
AlexandreS
2f6109a21c Display a custom error message when user has too may cloud projects
Do not show in changelog
2022-08-01 14:42:21 +02:00
D8H
0792fdadc7 Fix the tile map collision mask debug rendering that wasn't refreshed when there was no collision condition nor bahavior (#4162) 2022-08-01 10:21:17 +02:00
Clément Pasteau
0ca596e287 Remove scrolling on liluo iframe (#4159) 2022-07-29 18:13:27 +02:00
Florian Rival
899a252ddd Fix starters shown at the bottom of the example list on Firefox 2022-07-29 17:32:50 +02:00
AlexandreS
d92bf23e58 Fix double opening of project
Do not show in changelog
2022-07-29 15:11:20 +02:00
AlexandreS
37ae451178 Improve Homepage project list with more context actions and better display for local projects 2022-07-29 14:30:36 +02:00
Clément Pasteau
9c47a92ea6 Move asset store actions to be at the bottom of the dialog 2022-07-29 13:22:34 +02:00
Aurélien Vivet
1afd4b94be Fix a typo: Remove a double from (#4154)
Don't show in the changelog
2022-07-29 10:47:07 +02:00
Clément Pasteau
4d5a3f499f Rework play section to display Liluo games (#4151)
* Rework play section to display Liluo games

* ensure message origin
2022-07-29 10:12:02 +02:00
AlexandreS
13da1c56fd Add GDevelop own Cloud storage for web-app project
In order to make the life easier for our users on the web-app, we created GDevelop's cloud storage.
With a GDevelop account on the web-app, you can now save your project online and retrieve it from any device.
2022-07-28 15:26:41 +02:00
Clément Pasteau
8131ffcdb5 Fix Asset cards text color to be visible on light theme (#4152) 2022-07-28 14:55:39 +02:00
AlexandreS
77f948bfbf Improve search and replace in event sheet
- Fix a bug that hangs GDevelop when replacing with an empty search text
- Allow to replace with an empty string to mimic a "Delete search text" feature
2022-07-27 15:33:28 +02:00
D8H
c6abfc5433 Add type definitions on the Physics2 extension (#4147) 2022-07-27 09:47:32 +02:00
Florian Rival
2777e458ae Fix Add condition/action buttons overflowing outside of their column on small screens 2022-07-26 23:13:19 +02:00
Florian Rival
1d0695d722 Improve again rendering of the examples list on small screens
Don't show in changelog
2022-07-26 23:00:33 +02:00
Florian Rival
1820575f52 Fix display of the examples/starters on small screens (#4146) 2022-07-26 18:16:41 +02:00
Arthur Pacaud
f62236788d Add various improvements to the P2P extension (#4145)
- Updated PeerJS.
- Fixes for Safari.
- Improved typings.
- New default TURN server.
- Add a JavaScript API to get access to the raw connection.
  This allows to send custom messages from JavaScript. This allows to use a binary protocol from JavaScript.
- Use Map instead of JavaScript objects in places where it makes sense (more performant and less error prone).
- Avoid making a redundant get for every connection on the map containing the connections.

Only show in developer changelog
2022-07-26 14:25:08 +02:00
D8H
247e2f39e0 Add actions to change the tile map dimensions (#4141) 2022-07-26 09:20:27 +02:00
D8H
30898058a4 Fix layer names in drop-down lists were translated even though they are defined by users (#4130) 2022-07-25 18:53:30 +02:00
D8H
4e5d268f63 Handle tile maps with invalid resources (#4140)
* Fix an uncatched exceptions when a tile map resource is not set.
* Show place-holders for tile map with invalid resources in the instances editor.
* Give a better default name to tile map collision mask objects.
* Add a border around the tile map collision mask objects in the instance editor.
2022-07-25 17:33:08 +02:00
github-actions[bot]
fc4072b055 Update translations [skip ci] (#4132)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-07-25 11:18:38 +02:00
Clément Pasteau
9adec3ac72 Fix manual export URLs crashing the app on web (#4138) 2022-07-25 11:17:35 +02:00
D8H
95c2efbe07 Fix tilemaps object boxes to keep the empty tiles margins (#4133)
* It makes the same boxes as the tilemaps collision mask object to ease positioning.
* If the extra margin is not intended the right size can be set with Tiled.
2022-07-25 10:51:20 +02:00
Florian Rival
5a71b3a05f Add the unit (milliseconds) in the Tween behavior action parameters (#4137) 2022-07-24 22:23:35 +02:00
Florian Rival
fe87150cd4 Fix rendering of the home page on Safari (#4136) 2022-07-24 20:14:10 +02:00
Florian Rival
ddd3dc095a Fix wrong colors on the progress bar of the leaderboard creation dialog (#4135)
Don't show in changelog
2022-07-24 18:49:19 +02:00
Florian Rival
43bd02f99f Fix groups being redlined in the events sheet (#4134)
Do not show in changelog
2022-07-24 16:05:47 +02:00
github-actions[bot]
7ebf3c559b Update translations [skip ci] (#4122)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-07-22 14:04:30 +02:00
D8H
a5dca5fcb7 Fix: tilemaps were making the webapp crash due to a broken link. (#4131) 2022-07-22 14:03:19 +02:00
VegeTato
179a130d30 Update AboutDialog.js (#4127)
Added my twitter link beside my name :)
2022-07-22 11:00:50 +02:00
Peter Anderson
9953d33764 Issue #4119: Fix colours of expanded/collapsed arrows on event sheet. (#4129) 2022-07-22 10:58:58 +02:00
Clément Pasteau
5cb8603b56 Reduce max size of get started tiles (#4126)
Do not show in changelog
2022-07-22 10:10:04 +02:00
D8H
5278628480 Show typing errors of object parameters directly on the event sheet (#4121) 2022-07-21 09:23:40 +02:00
github-actions[bot]
99b615c573 Update translations [skip ci] (#4117)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-07-19 11:34:30 +02:00
Clément Pasteau
0ffc88a470 Small fixes (#4116)
Do not show in changelog
2022-07-18 18:25:27 +02:00
Clément Pasteau
b389b3cc90 Fix onboarding flow for web (#4115) 2022-07-18 16:22:50 +02:00
Clément Pasteau
41a70ec1e7 Bump IDE version to 139 (#4113) 2022-07-18 12:26:07 +02:00
D8H
1844d826f9 [PathFinding] Add a warn for too long searches (#4112)
* Don't show in changelogs
2022-07-18 12:25:54 +02:00
github-actions[bot]
e7e45e9c9b Update translations [skip ci] (#4102)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-07-18 12:14:34 +02:00
Clément Pasteau
7f7dc0e07f Final fixes release 139 (#4111)
* Fix MultiAutoComplete resetting after each input
* Always open a scene when opening a project
2022-07-18 12:13:43 +02:00
D8H
7af0153ceb [Platformer] Fix: platformer characters can now jump when moving against a wall that is part of the same object as the floor. (#4106)
* This bug could happen when using a tilemap collision mask object and not sustaining the jump.
2022-07-18 12:07:15 +02:00
D8H
9aaabbcc1d Fix the box of collision masks in the editor (#4105)
* Don't show in changelogs
2022-07-18 10:14:56 +02:00
Florian Rival
55cc75e990 Update wording of games not visible on Liluo on the games dashboard
Don't show in changelog
2022-07-13 18:47:19 +02:00
AlexandreS
d3d6c50790 Fix custom tooltip crashing when payload is undefined (#4101)
Don't show in changelog
2022-07-13 18:04:05 +02:00
github-actions[bot]
c7f2e4312c Update translations [skip ci] (#4058)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-07-13 15:49:36 +02:00
Peter Anderson
38cff7bbce Fix typos: replace 'Musics' with 'Music' (#4099) 2022-07-13 15:36:27 +02:00
AlexandreS
761de213ac Fix tabs and links colors
Do not show in changelog
2022-07-13 15:14:05 +02:00
D8H
f871b64011 [TileMap] Collision mask object (#3313)
* The collision mask is read from the tile maps exported by Tiled 1.9+.
* Several collision masks can be used for instance to have platforms and ladders.
* Take a look to the wiki for more details https://wiki.gdevelop.io/gdevelop5/objects/tilemap
2022-07-13 15:12:12 +02:00
AlexandreS
9441d3a2d2 Adapt themes' colors for better contrast across the app 2022-07-13 11:31:36 +02:00
Florian Rival
e86348727e Add a button, in the Profile, to manage online the subscription to GDevelop services (#4096)
This allows to easily update a payment method or switch to another plan/cancel (though this can already be done from the interface)
2022-07-13 10:59:41 +02:00
Peter Anderson
754845e5cd Fix grammar for the description of the Platform behavior (#4098) 2022-07-13 10:49:50 +02:00
Fannie Yan
1b86c23b92 Replace leaderboards when a user opens a game template (#4094)
* Replace leaderboards when a user opens a game template
2022-07-12 15:33:55 +02:00
AlexandreS
3c44602486 Fix Physics2 behaviors (#4074)
* Make it possible to activate and reactivate physics 2 behaviour
* Fix behaviour for objects modified or destroyed during events life cycle
* Make Physics2 Collision condition valid in any step of behaviour life cycles
2022-07-12 14:46:49 +02:00
D8H
b0f1e962a4 Automatically select and rename new behaviors or functions in the extension editor (#4092) 2022-07-11 16:27:22 +02:00
D8H
c48c86a51f Make radian or degree explicit in descriptions for angles (#4091) 2022-07-11 14:47:21 +02:00
Florian Rival
2b83ec9871 Revert color changes in themes (#4089)
* Primary color is the one that is displaying well, with good contrast, on the background.
* Secondary is the "accent" one that works well for raised button, selected buttons, etc...

Don't show in changelog
2022-07-11 10:36:15 +02:00
Florian Rival
c340f8ad06 Fix display of games showcase
Don't show in changelog
2022-07-08 17:53:41 +02:00
Clément Pasteau
07341f1e00 Improve the new Homepage Learn section by categorising tutorials
* Tutorials are now organised into Full Games, Game Mechanics, and official videos from Beginner to Advanced!
2022-07-08 16:06:57 +02:00
Sebastian Krzyszkowiak
7402d4f29f Add an option in the Resources editor to preload audio files in cache without decoding (#4010)
* This is helpful to load the audio files at the loading of the game (so even if the internet connection is lost, they will be available in the "browser cache") but without decoding them in memory (which could make too much work for low end devices, resulting in crashes)
2022-07-07 12:56:32 +02:00
AlexandreS
8599a1cfa7 Allow to display up to 50 leaderboard entries in Liluo/in-game 2022-07-06 15:39:59 +02:00
Clément Pasteau
98bfc7a4e0 Revamp GDevelop Homepage
* New "Get Started" section, to guide newcomers on where to start with GDevelop
* New "Build" section, the entry point for your projects
* New "Learn" section, the entry point to tutorials and future help tools
* New "Play" section, the entry point for all games created with GDevelop
* New "Community" section, the entry point to stay informed with the GDevelop world
2022-07-06 14:00:46 +02:00
D8H
cef352276d Add a duplicate action in the functions lists contextual menu. (#4085) 2022-07-06 12:33:52 +02:00
Fannie Yan
49ea27fd54 Slightly rework games dashboard (#4084)
Don't show in changelog
2022-07-06 12:12:24 +02:00
D8H
23b5b16bdf Select copied element on behaviors and functions lists (#4083) 2022-07-06 11:06:12 +02:00
Arthur Pacaud
2124133b4a Add an option to wait for a network request action to end before running other actions (#4023)
* In the future, there will be other actions where you can optionally wait for their tasks to be finished before running the rest of the actions. It makes logic easier and more straightforward to express in events.
* This is similar to the Wait action, except that it's optional.
2022-07-05 23:58:08 +02:00
Florian Rival
905344f396 Fix contrast of expressions in Rosé Pine theme 2022-07-05 15:08:43 +02:00
Florian Rival
84b78dfe0f Order extensions according to what is specified in the extensions repository (#4080)
Don't show in changelog
2022-07-03 22:47:18 +02:00
Ehan
1d8086b2f4 Add a new "Rosé Pine" theme (Code Editor & UI Theme) (#4079)
* Based on https://rosepinetheme.com/ and adapted by @EhanAhamed for GDevelop.
2022-07-03 18:20:19 +02:00
Florian Rival
22d5d46601 Add a toggle to display community extensions (#4078)
* Community extensions are extensions made by a community member, but which are not reviewed by the GDevelop extension team.
  They can be useful, but also need to be carefully reviewed if you use some (inspect them or reach out to their author in case of doubt).
* If you want to submit an extension, see the [GitHub repository of community extensions](https://github.com/gdevelopapp/gdevelop-extensions).
2022-07-02 13:36:37 +02:00
Fannie Yan
a5d56c37c9 Allow user to manage builds (#4075)
* In build tab:
  - Allow users to edit build names
  - Allow users to delete builds
* In feedback tab:
  - Display build name if a feedback is linked to one and allow users to filter feedbacks on builds
2022-07-01 10:44:29 +02:00
Florian Rival
5025ad9fb9 Avoid bad expression warnings in the console when using force actions without changing the force type (#4073) 2022-06-30 19:20:32 +02:00
D8H
daae78e802 Add version locks for rechart. (#4076)
Don't show in changelogs.
2022-06-30 16:28:02 +02:00
Florian Rival
9ee4b704da Clean more deprecated include files in extensions (#4072)
Don't show in changelog
2022-06-30 12:09:17 +02:00
D8H
a8991b7c9b Add game analytics charts (#4046)
The game dash board shows new charts to understand how well a game is doing on several aspects:
* the popularity (number of players)
* the player engagement (how long the game is played)

Note that players data are anonymized.
2022-06-30 12:06:03 +02:00
Florian Rival
cf061638b8 Avoid warnings in the console during preview/export by cleaning old C++ include files (#4070)
Only show in developer changelog
2022-06-28 19:26:25 +02:00
Arthur Pacaud
0686e02e27 Don't show objects already in a group in the selector to add a new object to this group (#4069) 2022-06-28 10:52:46 +02:00
Arthur Pacaud
e65b576e4b Adding actions to tween the value of a scene variable or a layer camera position (#4022)
* Like tweens added on objects, these tweens can be manipulated: paused, resumed or stopped.
2022-06-27 23:56:16 +02:00
Florian Rival
aacfed02a1 Allow the web-app to use relative resources if found when the project is opened from a public URL (#4066)
* For example, this can be useful to open a desktop project stored on a public space like GitHub (using the "raw" raw.githubusercontent.com/... urls given by GitHub)

Only show in developer changelog
2022-06-27 15:59:13 +02:00
Fannie Yan
6a25a9ad77 Allow user to open their games for feedbacks (#4045)
* Rework slighlty the game dashboard to allow users to make their game discoverable on Liluo.io, add a banner asking for feedback on their game pages on Liluo.io and add a banner asking for feedback on their build pages
* Add a tab Feedback when managing games, accessible through the games dashboard that allows users to see and process the feedbacks given to their game.
2022-06-27 15:23:43 +02:00
Clément Pasteau
e1140609d0 Add a button to start (or redo) the onboarding on the homepage
* Also add new languages FR, PT & ES
2022-06-27 15:18:15 +02:00
AlexandreS
81ef11163d Bump newIDE version 2022-06-21 16:41:38 +02:00
AlexandreS
fcc19a6dcf Fix collision bug introduced when fixing a collision bug 2022-06-21 16:41:18 +02:00
github-actions[bot]
bcad2d5667 Update translations [skip ci] (#4042)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2022-06-21 16:01:54 +02:00
D8H
3c83e5d24a No longer count pauses (when the tab is hidden) for the players session duration statistics (#4054) 2022-06-21 15:04:41 +02:00
Florian Rival
d07088900f Bump newIDE version 2022-06-16 18:28:13 +02:00
github-actions[bot]
fcb0c27e23 Update translations [skip ci] (#4030) 2022-06-16 17:06:43 +02:00
Fannie Yan
a6ee1c3e1c Allow more freedom on horizontal movements in events sheet (#4037)
* Allow more freedom on horizontal movements in events sheet
2022-06-16 11:09:26 +02:00
D8H
5669eae198 [Physics] Add mass and moment of inertia expressions (#4000) 2022-06-16 10:29:28 +02:00
AlexandreS
8f97a5ba69 Fix: Detect Physics2 contacts between objects that happen between frames 2022-06-16 10:12:15 +02:00
D8H
d57a755b2f Extract the analytics panel from the game detail dialog (#4038)
* Don't show in changelogs
2022-06-15 19:33:14 +02:00
Fannie Yan
5118421de7 Suggest all expression types in Text fields (#4033)
* Suggest all expressions in autocompletion suggestion and in expression selector for Text parameter fields
* Automatically convert number expressions to Text (using ToString()) when needed
2022-06-15 15:58:06 +02:00
Arthur Pacaud
ff15a37da7 Add WebManifest to exported web games (#4021)
* This allows a game hosted on a website to have a proper icon and orientation when a shortcut to it is added to the home screen on Android or iOS
2022-06-14 15:15:35 +02:00
Florian Rival
beac19089f Upgrade gh-pages to avoid history of the published web-app to take useless space
* history option was not working previously

Don't show in changelog
2022-06-13 15:45:37 +02:00
Florian Rival
e86e4ef9f5 Update all dark themes and rework the light theme to use the modern look'n'feel (#4028) 2022-06-13 12:54:10 +02:00
github-actions[bot]
693a2dbd2c Update translations [skip ci] (#4006)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2022-06-13 12:32:11 +02:00
AlexandreS
23318c2c28 Fix: Remove clicks on checkboxes that are far from the label on the same line 2022-06-13 10:55:11 +02:00
Clément Pasteau
3e811f1b9d Fix asset thumbnail sometimes having a wrong size when navigating the Asset store 2022-06-13 10:26:46 +02:00
Florian Rival
9ea6c034c3 Fix category of "Error of last save attempt" leaderboard expression 2022-06-12 17:47:24 +02:00
Sebastian Krzyszkowiak
b0ac0b1254 Fix music files staying muted after loading after upgrading to Howler.js 2.2.3 (#4011)
* This is caused by a bug in recent versions of Howler.js. Since there's no fix in Howler yet, this change reverts the problematic commit (0323af9b84) on top of v2.2.3 release.
* See https://github.com/goldfire/howler.js/issues/1603 for more details.

Only show in developer changelog
2022-06-09 10:19:42 +02:00
Florian Rival
e8b34ca535 Fix camera actions/conditions/expressions broken since introducing new expressions (#4012)
Removed some logs so that it's easier to spot errors reported.

Don't show in changelog
2022-06-09 10:09:14 +02:00
Clément Pasteau
70226f45aa Rework Asset Pack add to a list of filtered assets
Do not show in changelog
2022-06-08 17:10:58 +02:00
Clément Pasteau
b1572102c7 Bump IDE to 5.0.136
Do not show in changelog
2022-06-08 15:10:49 +02:00
Sebastian Krzyszkowiak
63da874469 Preload sounds sequentially to avoid overloading the browser
- Trying to preload all sounds at once can overwhelm the browser
in case of projects with many big sound files. Load the files
sequentially, the same way images are being preloaded.
2022-06-08 15:02:54 +02:00
Sebastian Krzyszkowiak
0963f2b8f6 Fix sounds being looped correctly on Firefox
- Upgrading Howler.js to v2.2.3 fixes sounds not being looped under recent Firefox versions (see https://github.com/goldfire/howler.js/issues/1442)
2022-06-08 15:00:01 +02:00
github-actions[bot]
5aa4fd5739 Update translations [skip ci] (#3924) 2022-06-08 14:57:29 +02:00
Oxey405
11c0248df5 Added an option to remove all unused resources 2022-06-08 14:53:11 +02:00
Fannie Yan
5bdc9769df Add camera borders expressions and conditions (#3999)
* Add CameraBorderLeft, CameraBorderRight, CameraBorderTop and CameraBorderBottom expressions and conditions
* Add CameraCenterX and CameraCenterY expressions and hide CameraX and CameraY expressions
2022-06-08 10:01:45 +02:00
Clément Pasteau
998ea7aa40 improve small things for Asset store and Events drag and drop (#3993)
* Hide Cancel action while installing

* Reset Pack Install disabled status on homepage

* Remove pointer from SelectField

* Create Chip component to harmonize cursor behavior to default

* Fix InlineCheckbox random cursors

* Improve drop indicator style

* Fix chip delete icon hover cursor

* Change drop indicator for multiple themes to be more visible
2022-06-07 10:32:42 +02:00
Fannie Yan
124003b4ac Save template slug in project (#3988)
only show in developer changelog
2022-06-07 10:26:30 +02:00
Florian Rival
96435530cd Set search bars to be rounded in the modern theme (#3994)
* Search bar have rounding and margins in most dialogs
* In lists, they stay "integrated" (no rounding, no margins)
* Also fix an icon that was too big

Don't show in changelog
2022-06-06 14:42:34 +02:00
D8H
8013ff0d7d Show the tag name as the asset page title (#3992)
Don't show in changelog
2022-06-06 10:43:59 +02:00
D8H
763aa0aa25 Show expression errors directly in the event sheet (#3823) 2022-06-03 23:02:51 +02:00
D8H
46dfb57859 Allow to go back to previous asset pages (#3986) 2022-06-03 19:16:35 +02:00
Fannie Yan
186eb4fcf0 Fix undo and redo in events sheet (#3981)
* Scroll to last change
* Select all events where a change occured
2022-06-03 16:28:27 +02:00
Florian Rival
c78c5def05 Add support for displaying external (optionally, paid) asset packs in the Asset Store (#3987)
* If you're an author of a paid asset pack, feel free to reach out to the GDevelop team on Discord or on the forum to get your pack listed!
2022-06-03 16:20:08 +02:00
Clément Pasteau
d694458fae Update all dialogs to have a way to close, except the ones with significant change (#3985) 2022-06-03 15:20:21 +02:00
D8H
74d6e51a2d Give asset suggestions after selecting an asset in the store 2022-06-03 15:12:31 +02:00
AlexandreS
ca5c3a27b0 Fix leaderboard reset action that used to timeout 2022-06-03 11:05:27 +02:00
Clément Pasteau
9ccdd2a0fa Give the possibility to add an asset pack as a whole
* New Dialog indicating how many assets are already in the project
* Option to add only the remaining assets
* Improved design/UX overall
2022-06-02 18:28:37 +02:00
D8H
9ec7fc71a8 The asset store remembers the opened page (#3982) 2022-06-02 12:41:53 +02:00
D8H
0f0a4034b9 Fix the hook dependency of the search. (#3980)
Don't show in changelog
2022-06-01 22:43:03 +02:00
D8H
6f831fe471 Cleanup filters context (#3979)
Don't show in changelogs.
2022-06-01 19:21:27 +02:00
D8H
0403882a18 Keep assets from a pack in order (#3978) 2022-06-01 18:30:21 +02:00
Florian Rival
318b1a62c9 Display the modern Dark theme by default for new users 2022-06-01 17:04:07 +02:00
Aurélien Vivet
41c9069289 Disable the autocomplete for Text Input objects (#3895) 2022-06-01 16:56:19 +02:00
Florian Rival
e98c96b5a4 Add a new "Modern" dark theme (#3974)
* This theme brings some changes to make the interface more readable to new users (outlined buttons) and a more modern approach (vibrant color, rounded buttons). It's still based on Material Design and similar to other themes, but is a first step toward an improved interface.
2022-06-01 14:36:07 +02:00
AlexandreS
893013e102 Fix loss of data when editing variables from the instance properties panel 2022-06-01 11:58:32 +02:00
D8H
dc41ec862c Sort asset search results and make the color filter not excluding. (#3965) 2022-06-01 10:39:10 +02:00
Florian Rival
5495257732 Reduce size of events in JSON by not writing empty events/sub-instructions arrays (#3975)
Only show in developer changelog
2022-05-31 17:24:01 +02:00
D8H
8c0a3221de Update the mouse buttons status when the cursor comes back inside the game view (#3970) 2022-05-30 13:35:55 +02:00
Florian Rival
70db787161 Automatically removing smoothing on pixel art assets added from the Asset Store 2022-05-27 15:06:10 +02:00
Florian Rival
cfd5a4b99e Fix asset store details page Link size and hrefs
Don't show in changelog
2022-05-27 13:11:02 +02:00
Clément Pasteau
fbb7f16d29 Rework the Asset Store details page to show a preview of the animation(s) of the object (#3930) 2022-05-27 12:58:42 +02:00
Fannie Yan
2c5374b87a Rework events Drag&Drop in events sheet (#3936) 2022-05-27 10:41:43 +02:00
Florian Rival
20075411bf Add links to extension creators public profile pages in the extension pages on the wiki (#3963) 2022-05-25 17:34:47 +02:00
Fannie Yan
a07efcd94e Clear authors and publishers when opening project after creation (#3964) 2022-05-25 17:06:28 +02:00
D8H
fcef430784 Add filters on animation, viewpoint, dimension, object type, color and license to the assets store (#3915) 2022-05-25 16:34:39 +02:00
AlexandreS
b9d27184b2 Enable backdrop click on new behavior dialog
Do not show in changelog
2022-05-25 14:58:29 +02:00
LuniMoon
1ae0ddbf66 Optimise copy of the new feature issue template (#3961)
Modified copy to send the user to the optimised channel for feature request and user feedback (Forum).

Don't show in changelog
2022-05-25 14:26:03 +02:00
Fannie Yan
1ec60f9d55 Add context in search placeholder (#3958)
* Specify search scope in search placeholder
2022-05-25 14:09:21 +02:00
Clément Pasteau
ecef111981 Update yarn editor folder hash (#3959)
Do not show in changelog
2022-05-25 11:23:52 +02:00
Fannie Yan
33ddda1070 Remove "Create functions or behavior" from project manager tab (#3953)
* Move "+ Create functions or behavior" button in extension search dialog
2022-05-25 10:37:28 +02:00
Clément Pasteau
029c9c853b Bump version to 135
Do not show in changelog
2022-05-25 09:54:52 +02:00
Clément Pasteau
e38a70ad10 Fix Yarn editor not saving anymore
* Pass down remote to Yarn to fix saving with Electron > 18
2022-05-25 09:43:09 +02:00
AlexandreS
78b48601a1 Fix: Allow use of debugger when not connected to Internet 2022-05-24 17:01:00 +02:00
AlexandreS
e91a794d91 Fix: Prevent runtime from trying to parse js map files to avoid Chrome logging warnings 2022-05-24 13:59:03 +02:00
Florian Rival
6fefd6d36e Fix formatting
Don't show in changelog
2022-05-24 13:45:48 +02:00
Florian Rival
0cf05b71ba Fix various links to docs and update links to new domain
Don't show in changelog
2022-05-24 11:44:55 +02:00
Florian Rival
1ab023e211 Add a comment explaining how to generate latest.yml files if necessary (#3946)
Don't show in changelog
2022-05-23 11:14:20 +02:00
AlexandreS
aa4e9e25bf Bump newIDE version 2022-05-23 11:02:13 +02:00
Clément Pasteau
bc235ef492 Revert publish declaration in package.json for latest.yml generation (#3944)
Do not show in changelog
2022-05-23 10:40:39 +02:00
AlexandreS
eabd1a4f23 Compute object variable suggestions on each object change in the expression builder 2022-05-23 08:58:30 +02:00
Florian Rival
62ef3e729b Speed up the editor development server startup time by 3x (#3941)
* Patch Webpack config to avoid processing the locale message files (translation files)

Only show in developer changelog
2022-05-22 21:24:49 +02:00
Florian Rival
802ee0c03f Upgrade Electron to 18.2 and React dev tools to latest version (#3893)
Only show in developer changelog
2022-05-21 17:00:47 +02:00
Florian Rival
7ef2050de7 Normalise imports to avoid .js suffix (#3938)
Don't show in changelog
2022-05-21 12:54:50 +02:00
AlexandreS
eeea1b99f4 New variables list improvements
* Fix drop down styling on light theme for selected rows
* Make sure the toolbar is fixed on every dialog the dialog is used in
* When adding a variable, scroll to the new row and focus name
* When searching, display children of collections to enable the user path "Search by collection name > Find child of interest > change child value".
  * If one changes a variable name that justifies its display during the search, the row does not disappear as soon as one is done with editing the name
2022-05-20 15:33:09 +02:00
Florian Rival
e75d49ea51 Upgrade to latest React v16 and react-scripts v4 (#3934)
* This enables "Fast Refresh" of React components (hot reloading after a change is made)
* This prepares the codebase for a migration to React v17/v18 later.

Only show in developer changelog
2022-05-20 15:04:23 +02:00
Florian Rival
048674a7d0 Fix ObjectGroupsList story not working
Don't show in changelog
2022-05-20 13:18:23 +02:00
Florian Rival
0502bd1f7a Fix properties of a custom behavior edited in an extension not taking the full width of the dialog 2022-05-20 13:01:53 +02:00
Florian Rival
66b84441ea Fix the GDJS development watcher making the electron renderer process crash when reloading (#3931)
Only show in developer changelog
2022-05-19 21:46:16 +02:00
D8H
d9e27dc4f3 Review change: rename the function (#3926)
Do not show in changelog
2022-05-19 14:20:39 +02:00
D8H
a3c3ffc3bb Fix missing exported extension functions (#3908) 2022-05-19 11:36:39 +02:00
Fannie Yan
dc33b6cc01 Fix typo in Leaderboard sort order (#3925)
Don't show in changelog
2022-05-19 11:16:23 +02:00
github-actions[bot]
4a0c1c5ad2 Update translations [skip ci] (#3891)
Do not show in changelog
2022-05-19 10:14:29 +02:00
AlexandreS
5820c5dd3e Bump newIDE version 2022-05-19 10:13:04 +02:00
D8H
606f5aff1b Fix: resource folder won't open on Windows (#3922)
Don't show in changelogs
2022-05-18 17:56:51 +02:00
AlexandreS
1f42374417 Reorder effects with drag n drop
Effects are applied in order and different orders may give different results, so ordering them is important. You can now do it with drag n drop.
Also, when renaming effects, a few checks are now done in order to prevent unexpected results.
2022-05-18 16:25:11 +02:00
AlexandreS
3356400026 Redesign of the variables editor
* Each row should be easier to read in a glance
* You can now collapse collection variables for a better readability
* Reorder and move of variables is now available with drag n drop
* You can now undo and redo changes
* Paste one or more variables at any level of depth you want
* Search in the names and values of each variables with a filter effect
2022-05-18 15:18:54 +02:00
Clément Pasteau
b811b1e873 Track asset packs opening analytics (#3919) 2022-05-18 14:24:13 +02:00
Florian Rival
e985b11971 Prevent layout shift when opening the asset store
Don't show in changelog
2022-05-16 21:16:48 +02:00
Florian Rival
aefc5e2fed Fix warning
Don't show in changelog
2022-05-16 20:57:43 +02:00
Clément Pasteau
0ccb7c3216 Add an asset pack gallery in the asset store (#3896) 2022-05-16 19:09:07 +02:00
Florian Rival
33c2c9c6cf Make GDevelop.js build happen on branches/Pull Requests (but not from forks) (#3914) 2022-05-16 19:04:44 +02:00
AlexandreS
55a6306f05 Fix range of volume on fade sound/music action
* ⚠️ This action was introduced with a buggy range (0 to 1 instead of 0 to 100). If you happen to use it, please update the range of volume used once the GDevelop new version is installed
2022-05-16 17:00:02 +02:00
AlexandreS
d766e32a18 Fix: Align image frame and full-size collision mask in collision mask editor 2022-05-16 16:47:39 +02:00
AlexandreS
7cdf4e1184 Fix: Prevent users to type a game slug longer than the limit 2022-05-16 16:19:29 +02:00
Fannie Yan
2540bf3c3e Allow user to limit score values saved in leaderboards (#3910)
Add a Dialog in a game's dashboard leaderboard tab allowing users to chose sort direction and limit possible scores for their games.
2022-05-16 16:10:59 +02:00
Florian Rival
6adec363d5 Enable C++ tests by default in CMake
Only show in developer changelog
2022-05-13 17:47:16 +00:00
D8H
91a02d132f Remove the dependency to SFML (#3865)
* This allows to run Core tests more easily.
2022-05-13 13:27:41 +02:00
Florian Rival
67718a364b Fix missing https in wiki links
Don't show in changelog
2022-05-13 12:49:02 +02:00
Florian Rival
e9b600d885 Update links to the new wiki
Don't show in changelog
2022-05-13 12:43:25 +02:00
Florian Rival
696dfcb746 Allow to choose installation directory when installing GDevelop on Windows (#3889)
* Also allow to choose if GDevelop must be installed system-wide or just for the user.
2022-05-13 12:06:33 +02:00
Fannie Yan
437edd1fe7 Make anchor behavior more intuitive (#3892)
* Anchor an edge of an object to set its distance from the window edges. Single anchor will not stretch the object anymore; you will need to set anchors to object's opposite edges for this effect.
* Add a button to switch between legacy and new behavior.
2022-05-13 10:50:40 +02:00
Florian Rival
48599ae9ca Improve consistency of some dialogs
Don't show in changelog
2022-05-12 22:30:57 +02:00
Florian Rival
c288700f2d Fix warnings
Don't show in changelog
2022-05-12 21:55:08 +02:00
Florian Rival
fbfb5dbaa6 Improve design of the alerts/messages and make margins consistent in the app (#3897) 2022-05-12 21:50:18 +02:00
Florian Rival
dfa27df64b Fix parameters of extensions actions/conditions made in the editor not having a default proper name
* This was creating a crash, because of infinite warnings, if clicking on a parameter with an empty name and then clicking on another parameter also having an empty name.

Fix #3888
2022-05-12 15:44:05 +02:00
Florian Rival
1ef404b9a9 Update the preview to create the BrowserWindow from the electron main process (#3890)
Only show in the developer changelog
2022-05-11 16:58:40 +02:00
github-actions[bot]
785dd6f08b Update translations [skip ci] (#3867)
Co-authored-by: fannieyan <fannieyan@users.noreply.github.com>
2022-05-11 10:33:46 +02:00
Fannie Yan
59bc76e144 Add tutorials in app (#3870)
- Added dismissable tutorials in events sheet, variable editors and object variable tab, add object dialog, sprite animations tab, export game for web tab, add new extension dialog.

- Added a tutorial button.
2022-05-10 17:42:45 +02:00
Florian Rival
d873d9747a Display all autocompletions in the expression editor when listing them (#3886)
* The list is not truncated anymore so you can scroll or use the arrow keys to browse all the completions (useful to see everything: objects, expressions, but also the available easing for tweens, etc...)
2022-05-10 13:07:38 +02:00
Florian Rival
a7fe36f351 Fix web-app recent files wrongly containing URLs to examples (#3885) 2022-05-10 09:15:52 +02:00
Florian Rival
252eeb86b1 Upgrade the underlying runtime running the desktop app, and exported desktop games, to Electron 18 (#3806) (#3854)
* This brings improved performance and compatibility for the desktop app with Windows, macOS and Linux.
* In particular, tilemap performance should be greatly improved both in the scene editor, the preview and exported games on Linux.
* This should also improve performance of both the editor and games on macOS when running on Apple Silicon (M1 cpus).
* Thanks to @nilaymajorwar for the ground work on this upgrade.

Only show the rest in developer changelog:

* More work is needed to isolate the Electron "renderer" process from the "main" process (both for the editor and for games), by using `contextBridge` and preload scripts (https://www.electronjs.org/docs/latest/tutorial/process-model). Your help is welcome to progressively do this migration.

Co-authored-by: Nilay Majorwar <nilaymajorwar@gmail.com>
2022-05-08 17:24:49 +02:00
Clément Pasteau
66145ce506 Specify supported languages for the Microsoft Store version (appx) (#3873) 2022-05-07 22:23:49 +02:00
Clément Pasteau
0dd10d2fce Fix history not working well on the Events Sheet
* Fix changes not being detected for history when editing an event Inline
* Fix losing focus when switching tabs
2022-05-06 12:15:31 +02:00
Clément Pasteau
5d35241c4c Fix not setting authors correctly when publishing to Liluo
* Also fix project being correctly saved
* And disabled the fields while publishing
2022-05-06 12:07:53 +02:00
AlexandreS
ba368d9eed Improve points and collision masks editors
- Make coordinates inputs more user friendly
  - Removal of unnecessary decimal places
  - Do not replace empty value with 0 to allow whole value erasing
- Better understanding of which point is which
  - Add possibility to select points in the list so that it is highlighted in the preview (same for hovered points)
  - Allow drag n drop for custom collision mask points
- Open image preview at a zoom factor that is adapted to the sprite size so that one doesn't have to zoom at each opening.
2022-05-06 09:56:06 +02:00
Florian Rival
fbeeb589a2 Fix package-lock.json
Don't show in changelog
2022-05-05 15:04:34 +02:00
Florian Rival
3ec4e3b6dd Add missing metric about desktop or web-app
* Also fix the dev version sending analytics

Don't show in changelog
2022-05-05 12:13:32 +02:00
Florian Rival
11ccaf2ea4 Add Posthog for following app usage analytics
* Fix UUID not reset when a user was logging out
* This should allow to create public dashboard showing various app usage (like popular extensions), with more accurate numbers than using Keen.io
2022-05-05 11:40:38 +02:00
Florian Rival
274d31f563 Update help links for the Time extension
Don't show in changelog
2022-05-04 18:56:40 +02:00
AlexandreS
c37049cd72 Add new settings to leaderboards
* Add parameter to control number of entries to display
* Add possibility to set a default leaderboard, displayed on Liluo game page by default
2022-05-04 10:37:01 +02:00
Florian Rival
7cdc92c776 Introduce the "Wait X seconds" action (#3852)
* This action allow to wait for a few seconds before continuing to run the next actions and sub-events.
* It is perfect to create cut scenes, advanced logic or just run things progressively without relying on timers. In a lot of cases, it's simpler and faster to use this new action.
* The action remember the picked objects: it works like an usual event, but run the actions (and sub-events) a bit later in time. While the action wait, other events continue to run as usual.
* Thanks to @arthuro555 for the ground work and follow up on this new feature.

Only show the rest in developer changelog:

* Add support for asynchronous actions (including for objects).
* Add exhaustive test cases for asynchronous actions. 

Co-authored-by: Arthur Pacaud <arthur.pacaud@hotmail.fr>
2022-05-02 19:44:15 +02:00
Florian Rival
471cd61d82 Add test for "Or" condition with objects
Don't show in changelog
2022-05-02 18:23:56 +02:00
Fannie Yan
afb66f213d Add tutorials in behavior, objects, conditions and actions (#3869)
* Add tutorials in behavior, objects, conditions and actions
2022-05-02 17:49:48 +02:00
Clément Pasteau
8ad70e57cc Encode thumbnail URL before sending it to the GDevelop services
* This prevents a bug where the thumbnail would not work when the filename has non-conventional characters
2022-04-29 15:40:54 +02:00
Arthur Pacaud
d9ea04e059 Allow webp images to be selected for object resources, and webm for videos (#3862)
* These formats are providing better compression than PNG or MP4, but they might not work on older devices - be sure to double check if the devices or browsers of your audience support them.
2022-04-29 11:40:07 +02:00
github-actions[bot]
bb3abdb1fa Update translations [skip ci] (#3831)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-04-28 16:40:10 +02:00
Oxey405
cdddcafa68 Add an action to fade a sound or a music on a channel to a new volume (#3724) 2022-04-28 11:17:46 +02:00
AlexandreS
14175c334e Do not show in changelog - Trim player name when formatting it 2022-04-28 11:02:12 +02:00
D8H
6bd4dff03e Remove variable parameters from SavePlayerScore action (#3860)
Do not show in changelog
2022-04-28 11:01:36 +02:00
Clément Pasteau
ceec39f6a2 Bump version to 5.0.132
Do not show in changelog
2022-04-27 17:59:58 +02:00
AlexandreS
5abf80a0c9 Add possibility to customize leaderboard score column appearance (#3857) 2022-04-27 17:46:15 +02:00
AlexandreS
7f955d8703 Add expressions to specify decimal place where to round, floor and ceil 2022-04-27 16:47:14 +02:00
D8H
781dd42ccb Add analytics for extensions (#3848) 2022-04-26 09:16:01 +02:00
Fannie Yan
e584fa952d Make loader screen cover input fields (#3850)
Don't show in changelog
2022-04-25 09:57:21 +02:00
Florian Rival
5681667dde Add a gitpod.io configuration file (experimental)
* This is useful to edit some part of the codebase on gitpod.io

Only show in developer changelog
2022-04-24 14:29:11 +00:00
Florian Rival
d16f04f4a2 Change AlertMessage design to be flat
Avoid shadows if not really needed.

Don't show in changelog
2022-04-24 14:23:08 +00:00
Aurélien Vivet
e9b464beba Improve wording consistency (#3851) 2022-04-23 16:35:51 +02:00
Florian Rival
7597dbe0d1 Add (new) conditions and expressions to compare the number of instances picked or living on the scene (#3842)
* Add `PickedInstancesCount` and `SceneInstancesCount` expressions, to replace `Count`. These expressions don't do any "picking" of instances, so they are safe to use anywhere without "weird" side effects.
* Equivalent conditions are available for all objects. These conditions allow to check at any point in your events the number of instances living on the scene or picked by actions/conditions.
  * This is useful to check if enough objects are picked by a condition before launching an action. 
  * Because this condition does not change the already picked objects, it's safe to use anywhere without any side effect.

Only show the rest in the developer changelog:
* Allow to read events missing some fields (like `disabled`, `folded`).
* Reduce the useless information stored in project JSON files by not storing the fields if they have their default value.
2022-04-23 16:35:10 +02:00
Clément Pasteau
4777f0a824 Save project after creation on Desktop app 2022-04-22 19:11:34 +02:00
AlexandreS
5b2532f8f3 Remove unused variables
Do not show in changelog
2022-04-21 15:02:41 +02:00
AlexandreS
2c43de5120 Improve objects and groups lists
* Use same drag and drop effect for both lists
* Add possibility to duplicate group
* Add possibility to move multiple objects at once
2022-04-21 14:26:42 +02:00
Florian Rival
124ce1101d Fix leaderboards category icon 2022-04-20 14:27:38 +02:00
AlexandreS
eb3d6c2670 Send events when opening and finalizing events extraction as function
Don't show in changelog
2022-04-20 12:17:09 +02:00
Clément Pasteau
f737fa479f Don't allow picking image URLs that will fail when building the game on the web application
- targeting specifically images with failed CORS
2022-04-19 17:45:48 +02:00
Florian Rival
f93b3bc3b4 Fix crash when an empty effect is added to a layer
Fix #3835
2022-04-19 12:47:20 +02:00
Elairyx
5c6eb2dadb Polish the wording of particle emitter actions, conditions and expressions (#3829) 2022-04-15 16:24:51 +01:00
AlexandreS
3e6ca186f8 Add action to change image for particle emitter using project resources 2022-04-15 15:37:38 +02:00
github-actions[bot]
860e9d36e4 Update translations [skip ci] (#3808)
Co-authored-by: fannieyan <fannieyan@users.noreply.github.com>
2022-04-14 11:40:38 +02:00
Fannie Yan
c8b461cc5f Merge game management buttons in games dashboard (#3826)
* Merge game management button into one in Games dashboard
2022-04-14 10:51:48 +02:00
AlexandreS
36cdc5720a Bump newIDE version 2022-04-14 10:47:33 +02:00
AlexandreS
a7cd53b921 Add built-in leaderboard feature (actions, conditions, administration) (#3759) 2022-04-14 10:25:48 +02:00
D8H
01a25400ff New touch event functions that allow to get them several times (#3820)
* It allows extensions to handle touch events without conflicting with the scene event sheets.
* Existing touch functions continue to work and can be used alongside new ones without any issue.
2022-04-13 12:00:33 +02:00
D8H
2b484c0cf1 The url slug of a game can be verified and changed right before publication (#3811) 2022-04-12 20:39:34 +02:00
Fannie Yan
13204e4b53 Add a button "Access public profile" in one's profile details (#3819)
Add a button in profile details that opens the user's public profile on Liluo.io
2022-04-11 14:41:08 +02:00
D8H
c6d6466d54 Fix the input checkboxes "Playable with [...]" randomly checked when publishing a game for the first time (#3818) 2022-04-08 11:45:20 +01:00
Clément Pasteau
6cf737ac70 Remove unused imports (#3809)
Do not show in changelog
2022-04-06 15:00:04 +02:00
Arthur Pacaud
5b8cdbbace Update the button label in the dialog of an extension to show if the extension will be updated or (re)installed (#3777) 2022-04-06 13:47:36 +01:00
Clément Pasteau
a7df37a0dc Bump version to 131 (#3807) 2022-04-06 14:47:20 +02:00
D8H
7721f56dde Allow to specify a slug to be used in liluo.io games URL
* From the Game Details Dashboard, you can now select a username and a game name to create a custom unique URL for your game on Liluo.io, which can look like this: liluo.io/your-username/your-game-name
2022-04-06 14:35:50 +02:00
github-actions[bot]
08ada4f595 Update translations [skip ci] (#3764) 2022-04-06 13:21:28 +01:00
D8H
caa46a2fb0 Allow to define a default value for a "string with options" property (#3803) 2022-04-06 09:49:50 +02:00
D8H
660cdd753c [TopDownMovement] Add a condition to check which key was used or simulated and actions to change the current velocity (#3800) 2022-04-05 19:32:31 +02:00
D8H
3b9a1354ee [TopDownMovement] Fix the velocity value that wasn't exactly 0 when moving horizontally or vertically (#3799) 2022-04-04 23:47:17 +02:00
D8H
02fce4132a Add a condition to check if the mouse is inside the window. (#3787) 2022-04-01 12:01:53 +02:00
D8H
41241d75e1 Fix the camera rounding to work when following objects with even dimensions and pixel perfect mode is enabled (#3789) 2022-04-01 12:00:47 +02:00
Clément Pasteau
fc3e73f360 Rework the Game publishing on Liluo
* Display a summary of the Game that will be published when pushing a new build
* Add a helper message to change the game thumbnail
* Add option to save project by default when publishing to Liluo.io
* Allow defining if your game should be discoverable on Liluo.io or not
2022-04-01 10:50:05 +02:00
Florian Rival
230493039c Display an icon for the Home tab (instead of the label "Home") (#3792) 2022-04-01 09:40:22 +01:00
Florian Rival
50326e4d21 Add missing Text Input to the web-app (#3785)
Don't show in changelog
2022-03-29 13:17:44 +02:00
Florian Rival
cec7960a7d Add slug to ExampleShortHeader and Example type
Don't show in changelog
2022-03-28 16:22:49 +02:00
Florian Rival
cec901d4c2 Fix npm not installing git:// dependencies (#3780)
Don't show in changelog
2022-03-28 14:55:01 +02:00
Florian Rival
29f0567140 Add Linux zip and deb target to the packaged desktop app (#3776)
Only show in developer changelog
2022-03-27 12:55:50 +02:00
Clément Pasteau
94af33c815 Switch game metrics from live ones to cached ones for performance
Do not show in changelog
2022-03-25 14:19:14 +01:00
Florian Rival
3ad7585f92 Add a linter rule to avoid importing prop-types
Don't show in changelog
2022-03-24 11:48:07 +01:00
AlexandreS
acb69c447d Improve events sheet search with new shortcuts and put back the "Edit variable" row in variable editor 2022-03-23 15:40:57 +01:00
Elairyx
fa928b35cb Add autocompletion for the "Simulate control" action of the Top Down movement behavior (#3767) 2022-03-21 23:15:02 +01:00
Florian Rival
67810b79ce Refactor some redundant code in Text Input tests (#3768)
Don't show in changelog
2022-03-21 23:08:54 +01:00
Clément Pasteau
0a77e0264d Bump version to 5.0.130 2022-03-21 11:53:52 +01:00
Clément Pasteau
4cc8d15f4b Fix invalid game thumbnail URL 2022-03-21 11:42:36 +01:00
Clément Pasteau
a2f0b3384e Bump newIDE version to 5.0.129 2022-03-17 14:57:32 +01:00
github-actions[bot]
432ffebf80 Update translations [skip ci] (#3695)
Co-authored-by: Bouh <Bouh@users.noreply.github.com>
2022-03-17 14:40:24 +01:00
Aurélien Vivet
165470d9c1 Add D as shortcut to toggle disabled event, also added in right click context menu in the event sheet (#3751) 2022-03-17 11:35:38 +01:00
D8H
53eab0ed62 Fix the "Is moving" condition of platformer characters by removing the 1 pixel per frame detection limit (#3730)
This can be important for games with low resolution.
2022-03-16 19:09:14 +01:00
Florian Rival
649a36ac30 Fix text input wrongly staying visible even if hidden or layer visibility turned off (#3755) 2022-03-16 18:56:11 +01:00
2751 changed files with 180117 additions and 168564 deletions

View File

@@ -2,10 +2,17 @@
# on the Electron runtime (newIDE/electron-app) for macOS and Linux.
# For Windows, see the appveyor.yml file.
# This also builds GDevelop.js and store it on a S3 so it can be used to run
# GDevelop without building it from scratch.
# Note that these CircleCI builds/tests are not launched on Pull Requests from forks,
# to avoid sharing secrets.
version: 2.1
orbs:
aws-cli: circleci/aws-cli@2.0.6
jobs:
# Build the **entire** app for macOS.
build-macos:
macos:
xcode: 12.5.1
@@ -61,7 +68,7 @@ jobs:
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf "newIDE/electron-app/dist/mac/GDevelop 5.app"
command: rm -rf "newIDE/electron-app/dist/mac/GDevelop 5.app" && rm -rf "newIDE/electron-app/dist/mac-arm64/GDevelop 5.app"
# Upload artifacts (CircleCI)
- store_artifacts:
@@ -75,6 +82,7 @@ jobs:
name: Deploy to S3 (latest)
command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
# Build the **entire** app for Linux.
build-linux:
# CircleCI docker workers are failing if they don't have enough memory (no swap)
resource_class: xlarge
@@ -135,11 +143,11 @@ jobs:
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
- run:
name: Build GDevelop IDE
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --linux AppImage --publish=never
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --linux --publish=never
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf newIDE/electron-app/dist/linux-unpacked
command: rm -rf newIDE/electron-app/dist/linux-unpacked && rm -rf newIDE/electron-app/dist/linux-arm64-unpacked
# Upload artifacts (CircleCI)
- store_artifacts:
@@ -153,10 +161,67 @@ jobs:
name: Deploy to S3 (latest)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
# Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use).
build-gdevelop_js-wasm-only:
docker:
- image: cimg/node:16.13
working_directory: ~/GDevelop
steps:
- checkout
- aws-cli/setup
# System dependencies (for Emscripten)
- run:
name: Install dependencies for Emscripten
command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# GDevelop.js dependencies
- restore_cache:
keys:
- gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# fallback to using the latest cache if no exact match is found
- gdevelop.js-linux-nodejs-dependencies-
- run:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && npm install && cd ..
# Build GDevelop.js (and run tests to ensure it works)
- run:
name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
- save_cache:
paths:
- GDevelop.js/node_modules
key: gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# Upload artifacts (CircleCI)
- store_artifacts:
path: Binaries/embuild/GDevelop.js
# Upload artifacts (AWS)
- run:
name: Deploy to S3 (specific commit)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
- run:
name: Deploy to S3 (latest)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/latest/
workflows:
builds:
jobs:
- build-gdevelop_js-wasm-only
- build-macos:
filters:
branches:

View File

@@ -0,0 +1,19 @@
---
name: "📦 Asset Store submission"
about: Submit a free asset pack for the GDevelop Asset Store.
title: ''
labels: "📦 Asset Store submission"
assignees: ''
---
BEFORE opening a new submission, please make sure that you:
- You have packaged the asset pack according [these rules](https://wiki.gdevelop.io/gdevelop5/community/contribute-to-the-assets-store). Otherwise, your package may be rejected or we will ask you to do the changes.
## Description
- License:
- Author:
- Link to the original website:
- Zip file:

View File

@@ -10,11 +10,11 @@ assignees: ''
BEFORE opening a new feature request, please make sure that you:
- Discussed it on the discord or the forum,
- There is not already a suggestion about it in the issues or in the roadmap: https://trello.com/b/qf0lM7k8/gdevelop-roadmap
- Consider commenting on the roadmap if something is important for you
- Understand the implications of your feature with the help of [the Forum](https://forum.gdevelop.io/c/gdevelop-general/feature-requests/35), OR
- Peer-reviewed it with other users on Discord,
- Consider commenting on the [Feature Request Forum](https://forum.gdevelop.io/c/gdevelop-general/feature-requests/35) if something is important for you
AFTER opening the feature request, the issue will be closed by a maintainer (@4ian or someone else) and a card will be added in the roadmap if it's relevant and does not exist yet :)
AFTER opening the feature request, the issue will be closed by a maintainer (@4ian or someone else) and a card will be added in [the public roadmap](https://trello.com/b/qf0lM7k8/gdevelop-ideas-box) if it's relevant and does not exist yet :)
## Description

View File

@@ -4,14 +4,14 @@ contact_links:
url: https://discord.gg/rjdYHvj
about: Discuss on the forum or on the Discord to get help creating a game or identifying a bug.
- name: GDevelop Forums
url: https://forum.gdevelop-app.com
url: https://forum.gdevelop.io
about: You can also discuss game creation, new feature requests and bugs on the forum.
- name: GDevelop Roadmap
url: https://trello.com/b/qf0lM7k8/gdevelop-roadmap
about: Look at the roadmap and vote on features that you want to see in GDevelop.
- name: Submit a new game example that you created
url: https://github.com/GDevelopApp/GDevelop-examples/issues/new/choose
about: You can submit a game that you made to be added to examples in the "GDevelop-examples" repository
about: You can submit a game that you made to be added to examples in the "GDevelop-examples" repository
- name: Submit a new game extension that you created
url: https://github.com/4ian/GDevelop-extensions/issues/new/choose
about: You can submit an extension that you made in the "GDevelop-extensions" repository
about: You can submit an extension that you made in the "GDevelop-extensions" repository

View File

@@ -12,7 +12,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
type: "body"
regex: ".*Scroll down to '\\.\\.\\.\\.'.*"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop-app.com/), the Discord chat or [read the documentation](http://wiki.compilgames.net/doku.php/gdevelop5/start) to learn more about GDevelop. Thanks!"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop.io/), the Discord chat or [read the documentation](https://wiki.gdevelop.io/gdevelop5/start) to learn more about GDevelop. Thanks!"
- name: Autoclose known beta 105 web-app update bug
uses: arkon/issue-closer-action@v1.1
with:

1
.gitignore vendored
View File

@@ -8,6 +8,7 @@
/Binaries/.embuild*
/Binaries/build*
/Binaries/embuild*
/emsdk
*.dll
*.exe
*.a

25
.gitpod.yml Normal file
View File

@@ -0,0 +1,25 @@
# This is a configuration file allowing to quickly set up a development environment
# on GitPod (https://www.gitpod.io/).
# Also check GitHub codespaces if you're interested in working
# on a remote development server.
# This works well for:
# - The editor web-app, including the C++ classes.
# This is not yet adapted for:
# - Working on the game engine or extensions, as they can't be easily tested on the web-app.
# - Working on the desktop app (Electron).
tasks:
- name: Install dependencies for Emscripten and build GDevelop.js
init: |
sudo apt-get update
sudo apt install cmake python-is-python3 python3-distutils -y
git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
cd GDevelop.js
npm install
source ../emsdk/emsdk_env.sh && npm run build -- --dev
cd ..
- name: Install GDevelop IDE dependencies
init: cd newIDE/app && npm install && cd ../electron-app && npm install

View File

@@ -1,9 +1,6 @@
# Travis CI configuration to build and run all tests
# (and typing/formatting) for the Core, newIDE, GDJS.
#
# This builds GDevelop.js and store it on a S3 so it can be used to run
# GDevelop without building it.
#
# See also Semaphore CI for quick tests (not building GDevelop.js, so
# faster but not always reliable).
@@ -17,18 +14,7 @@ cache:
directories:
- $HOME/.npm
services:
# Virtual Framebuffer 'fake' X server for SFML
- xvfb
addons:
artifacts:
s3_region: "us-east-1"
target_paths:
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/commit/$(git rev-parse HEAD)
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/latest
paths:
- Binaries/embuild/GDevelop.js
apt:
sources:
- ubuntu-toolchain-r-test
@@ -36,20 +22,8 @@ addons:
# Build dependencies:
- cmake
- p7zip-full
# SFML dependencies:
- libopenal-dev
- libjpeg-dev
- libglew-dev
- libudev-dev
- libxrandr-dev
- libsndfile1-dev
- libglu1-mesa-dev
- libfreetype6-dev
before_install:
#Activate X Virtual Framebuffer to allow tests to
#use SFML.
- "export DISPLAY=:99.0"
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
- wget -q -O libstdc++6 http://security.ubuntu.com/ubuntu/pool/main/g/gcc-5/libstdc++6_5.4.0-6ubuntu1~16.04.12_amd64.deb
- sudo dpkg --force-all -i libstdc++6

View File

@@ -7,11 +7,9 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"defines": [
@@ -27,7 +25,6 @@
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
@@ -48,7 +45,6 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
@@ -78,7 +74,6 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"${workspaceRoot}"
],
"defines": [
@@ -101,4 +96,4 @@
}
],
"version": 4
}
}

14
.vscode/launch.json vendored
View File

@@ -15,6 +15,20 @@
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/GDevelop.js"
},
{
"type": "node",
"request": "launch",
"name": "newIDE/app Jest tests (current file)",
"program": "${workspaceFolder}/newIDE/app/node_modules/.bin/react-scripts",
"args": [
"test", "--env=node",
"${fileBasenameNoExtension}"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/newIDE/app"
},
{
"type": "node",
"request": "launch",

View File

@@ -115,7 +115,6 @@
"files.exclude": {
"Binaries/*build*": true,
"Binaries/Output": true,
"ExtLibs/SFML": true,
"GDJS/Runtime-dist": true,
"docs": true,
"newIDE/electron-app/dist": true,

View File

@@ -17,7 +17,7 @@ endmacro()
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library")
gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform")
gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions")
gd_set_option(BUILD_TESTS FALSE BOOL "TRUE to build the tests")
gd_set_option(BUILD_TESTS TRUE BOOL "TRUE to build the tests")
# Disable deprecated code
set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.

View File

@@ -14,7 +14,6 @@ set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SY
#Dependencies on external libraries:
###
include_directories(${sfml_include_dir})
#Defines
###
@@ -68,14 +67,6 @@ set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMA
set(ARCHIVE_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
set(RUNTIME_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
#Linker files
###
IF(EMSCRIPTEN)
#Nothing.
ELSE()
target_link_libraries(GDCore ${sfml_LIBRARIES})
ENDIF()
#Tests
###
if(BUILD_TESTS)
@@ -88,5 +79,5 @@ if(BUILD_TESTS)
add_executable(GDCore_tests ${test_source_files})
set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) #Allow finding dependencies directly from build path on Mac OS X.
target_link_libraries(GDCore_tests GDCore)
target_link_libraries(GDCore_tests ${sfml_LIBRARIES})
target_link_libraries(GDCore_tests ${CMAKE_DL_LIBS})
endif()

View File

@@ -13,7 +13,6 @@
#include <string>
#include <vector>
#include "Utf8/utf8.h"
#include <SFML/System/String.hpp>
#ifdef __GNUC__
#define GD_DEPRECATED __attribute__((deprecated))

View File

@@ -0,0 +1,36 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "AsyncEvent.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Serialization.h"
#include "GDCore/Serialization/SerializerElement.h"
using namespace std;
namespace gd {
AsyncEvent::AsyncEvent() : BaseEvent() {}
AsyncEvent::~AsyncEvent(){};
vector<const gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() const {
vector<const gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
vector<gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() {
vector<gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
} // namespace gd

View File

@@ -0,0 +1,61 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_ASYNCEVENT_H
#define GDCORE_ASYNCEVENT_H
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
namespace gd {
class Instruction;
class Project;
} // namespace gd
namespace gd {
/**
* \brief Internal event for asynchronous actions.
* This event gets added internally to the events tree when an
* asynchronous action is used.
*/
class GD_CORE_API AsyncEvent : public gd::BaseEvent {
public:
AsyncEvent();
AsyncEvent(const gd::Instruction &asyncAction_,
const gd::InstructionsList &actions_,
const gd::EventsList &subEvents_)
: asyncAction(asyncAction_), actions(actions_), subEvents(subEvents_) {
SetType("BuiltinAsync::Async");
};
virtual ~AsyncEvent();
virtual gd::AsyncEvent *Clone() const { return new AsyncEvent(*this); }
virtual bool IsExecutable() const { return true; }
virtual bool CanHaveSubEvents() const { return true; }
virtual const gd::EventsList &GetSubEvents() const { return subEvents; };
virtual gd::EventsList &GetSubEvents() { return subEvents; };
const gd::InstructionsList &GetActions() const { return actions; };
gd::InstructionsList &GetActions() { return actions; };
const gd::Instruction &GetInstruction() const { return asyncAction; };
gd::Instruction &GetInstruction() { return asyncAction; };
virtual std::vector<const gd::InstructionsList *>
GetAllActionsVectors() const;
virtual std::vector<gd::InstructionsList *> GetAllActionsVectors();
private:
gd::Instruction asyncAction;
gd::InstructionsList actions;
EventsList subEvents;
};
} // namespace gd
#endif // GDCORE_STANDARDEVENT_H

View File

@@ -23,8 +23,9 @@ vector<gd::String> CommentEvent::GetAllSearchableStrings() const {
bool CommentEvent::ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString) {
if (newSearchableString[0] == com1) return false;
SetComment(newSearchableString[0]);
return newSearchableString[0] == com1;
return true;
}
void CommentEvent::SerializeTo(SerializerElement &element) const {

View File

@@ -53,8 +53,10 @@ void ForEachChildVariableEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
if (!events.IsEmpty())
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
}
void ForEachChildVariableEvent::UnserializeFrom(gd::Project& project,
@@ -66,8 +68,12 @@ void ForEachChildVariableEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
events.Clear();
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
}
} // namespace gd

View File

@@ -74,8 +74,10 @@ void ForEachEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
if (!events.IsEmpty())
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
}
void ForEachEvent::UnserializeFrom(gd::Project& project,
@@ -86,8 +88,12 @@ void ForEachEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
events.Clear();
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
}
} // namespace gd

View File

@@ -29,8 +29,9 @@ vector<gd::String> GroupEvent::GetAllSearchableStrings() const {
bool GroupEvent::ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString) {
if (newSearchableString[0] == name) return false;
SetName(newSearchableString[0]);
return newSearchableString[0] == name;
return true;
}
void GroupEvent::SerializeTo(SerializerElement& element) const {

View File

@@ -75,8 +75,10 @@ void RepeatEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
if (!events.IsEmpty())
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
}
void RepeatEvent::UnserializeFrom(gd::Project& project,
@@ -89,8 +91,12 @@ void RepeatEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
events.Clear();
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
}
} // namespace gd

View File

@@ -53,8 +53,10 @@ void StandardEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
if (!events.IsEmpty())
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
}
void StandardEvent::UnserializeFrom(gd::Project& project,
@@ -63,8 +65,12 @@ void StandardEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
events.Clear();
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
}
} // namespace gd

View File

@@ -52,8 +52,10 @@ void WhileEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
if (!events.IsEmpty())
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
}
void WhileEvent::UnserializeFrom(gd::Project& project,
@@ -68,8 +70,12 @@ void WhileEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
events.Clear();
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
}
} // namespace gd

View File

@@ -4,7 +4,9 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include <set>
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
@@ -14,7 +16,7 @@ using namespace std;
namespace gd {
void EventsCodeGenerationContext::InheritsFrom(
const EventsCodeGenerationContext& parent_) {
EventsCodeGenerationContext& parent_) {
parent = &parent_;
// Objects lists declared by parent became "already declared" in the child
@@ -24,8 +26,8 @@ void EventsCodeGenerationContext::InheritsFrom(
parent_.objectsListsToBeDeclared.end(),
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
std::copy(parent_.objectsListsWithoutPickingToBeDeclared.begin(),
parent_.objectsListsWithoutPickingToBeDeclared.end(),
std::copy(parent_.objectsListsOrEmptyToBeDeclared.begin(),
parent_.objectsListsOrEmptyToBeDeclared.end(),
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
std::copy(parent_.emptyObjectsListsToBeDeclared.begin(),
@@ -33,6 +35,8 @@ void EventsCodeGenerationContext::InheritsFrom(
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
nearestAsyncParent = parent_.IsAsyncCallback() ? &parent_ : parent_.nearestAsyncParent;
asyncDepth = parent_.asyncDepth;
depthOfLastUse = parent_.depthOfLastUse;
customConditionDepth = parent_.customConditionDepth;
contextDepth = parent_.GetContextDepth() + 1;
@@ -42,33 +46,59 @@ void EventsCodeGenerationContext::InheritsFrom(
}
}
void EventsCodeGenerationContext::InheritsAsAsyncCallbackFrom(
EventsCodeGenerationContext& parent_) {
// Increasing the async depth is enough to mark the context as an async callback.
InheritsFrom(parent_);
asyncDepth = parent_.asyncDepth + 1;
}
void EventsCodeGenerationContext::Reuse(
const EventsCodeGenerationContext& parent_) {
EventsCodeGenerationContext& parent_) {
InheritsFrom(parent_);
if (parent_.CanReuse())
contextDepth = parent_.GetContextDepth(); // Keep same context depth
}
void EventsCodeGenerationContext::NotifyAsyncParentsAboutDeclaredObject(const gd::String& objectName) {
gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
for (;
asyncContext != nullptr;
asyncContext = asyncContext->parent->nearestAsyncParent)
asyncContext->allObjectsListToBeDeclaredAcrossChildren.insert(objectName);
}
void EventsCodeGenerationContext::ObjectsListNeeded(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName))
if (!IsToBeDeclared(objectName)) {
objectsListsToBeDeclared.insert(objectName);
if (IsInsideAsync()) {
NotifyAsyncParentsAboutDeclaredObject(objectName);
}
}
depthOfLastUse[objectName] = GetContextDepth();
}
void EventsCodeGenerationContext::ObjectsListWithoutPickingNeeded(
void EventsCodeGenerationContext::ObjectsListNeededOrEmptyIfJustDeclared(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName))
objectsListsWithoutPickingToBeDeclared.insert(objectName);
if (!IsToBeDeclared(objectName)) {
objectsListsOrEmptyToBeDeclared.insert(objectName);
if (IsInsideAsync()) {
NotifyAsyncParentsAboutDeclaredObject(objectName);
}
}
depthOfLastUse[objectName] = GetContextDepth();
}
void EventsCodeGenerationContext::EmptyObjectsListNeeded(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName))
if (!IsToBeDeclared(objectName)) {
emptyObjectsListsToBeDeclared.insert(objectName);
}
depthOfLastUse[objectName] = GetContextDepth();
}
@@ -77,8 +107,8 @@ std::set<gd::String> EventsCodeGenerationContext::GetAllObjectsToBeDeclared()
const {
std::set<gd::String> allObjectListsToBeDeclared(
objectsListsToBeDeclared.begin(), objectsListsToBeDeclared.end());
allObjectListsToBeDeclared.insert(objectsListsWithoutPickingToBeDeclared.begin(),
objectsListsWithoutPickingToBeDeclared.end());
allObjectListsToBeDeclared.insert(objectsListsOrEmptyToBeDeclared.begin(),
objectsListsOrEmptyToBeDeclared.end());
allObjectListsToBeDeclared.insert(emptyObjectsListsToBeDeclared.begin(),
emptyObjectsListsToBeDeclared.end());
@@ -102,4 +132,21 @@ bool EventsCodeGenerationContext::IsSameObjectsList(
otherContext.GetLastDepthObjectListWasNeeded(objectName);
}
bool EventsCodeGenerationContext::ShouldUseAsyncObjectsList(
const gd::String& objectName) const {
if (!IsInsideAsync()) return false;
// Check if the objects list was used after (or in) the nearest async callback context.
const gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
if (parent->GetLastDepthObjectListWasNeeded(objectName) >= asyncContext->GetContextDepth()) {
// The object was used in a context after (or in) the nearest async parent context, so we're not getting it from the
// async object lists (it was already gotten from there in this previous context).
return false;
}
// If the objects list is declared in a parent of the nearest async context, it means
// the async context had to use an async objects list to access it.
return asyncContext->ObjectAlreadyDeclaredByParents(objectName);
};
} // namespace gd

View File

@@ -8,6 +8,7 @@
#include <map>
#include <memory>
#include <set>
#include "GDCore/String.h"
namespace gd {
@@ -33,11 +34,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* updated to contain the maximal scope depth reached.
*/
EventsCodeGenerationContext(unsigned int* maxDepthLevel_ = nullptr)
: contextDepth(0),
customConditionDepth(0),
maxDepthLevel(maxDepthLevel_),
parent(NULL),
reuseExplicitlyForbidden(false){};
: maxDepthLevel(maxDepthLevel_){};
virtual ~EventsCodeGenerationContext(){};
/**
@@ -45,7 +42,13 @@ class GD_CORE_API EventsCodeGenerationContext {
* another one. The child will then for example not declare again objects
* already declared by its parent.
*/
void InheritsFrom(const EventsCodeGenerationContext& parent);
void InheritsFrom(EventsCodeGenerationContext& parent);
/**
* Call this method to make an EventsCodeGenerationContext as a "child" of
* another one, but in the context of an async function.
*/
void InheritsAsAsyncCallbackFrom(EventsCodeGenerationContext& parent);
/**
* \brief As InheritsFrom, mark the context as being the child of another one,
@@ -53,7 +56,7 @@ class GD_CORE_API EventsCodeGenerationContext {
*
* Used for example for optimizing the last event of a list.
*/
void Reuse(const EventsCodeGenerationContext& parent);
void Reuse(EventsCodeGenerationContext& parent);
/**
* \brief Forbid any optimization that would reuse and modify the object list
@@ -88,19 +91,19 @@ class GD_CORE_API EventsCodeGenerationContext {
const EventsCodeGenerationContext* GetParentContext() const { return parent; }
/**
* Mark the object has being the object being handled by the instruction
* Mark the object as being the object being handled by the instruction.
*/
void SetCurrentObject(const gd::String& objectName) {
currentObject = objectName;
};
/**
* Set that no particular object is being handled by an instruction
* Set that no particular object is being handled by an instruction.
*/
void SetNoCurrentObject() { currentObject = ""; };
/**
* Get the object being handled by the instruction
* Get the object being handled by the instruction.
*/
const gd::String& GetCurrentObject() const { return currentObject; };
@@ -109,7 +112,7 @@ class GD_CORE_API EventsCodeGenerationContext {
*
* The list will be filled with objects from the scene if it is the first time
* it is requested, unless there is already an object list with this name
* (i.e. `ObjectAlreadyDeclared(objectName)` returns true).
* (i.e. `ObjectAlreadyDeclaredByParents(objectName)` returns true).
*/
void ObjectsListNeeded(const gd::String& objectName);
@@ -121,7 +124,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* from the scene. If there is already an objects list with this name, no new
* list will be declared again.
*/
void ObjectsListWithoutPickingNeeded(const gd::String& objectName);
void ObjectsListNeededOrEmptyIfJustDeclared(const gd::String& objectName);
/**
* Call this when an instruction in the event needs an empty object list,
@@ -134,29 +137,21 @@ class GD_CORE_API EventsCodeGenerationContext {
void EmptyObjectsListNeeded(const gd::String& objectName);
/**
* Return true if an object list has already been declared (or is going to be
* declared).
* Return true if an object list has already been declared by the parent contexts.
*/
bool ObjectAlreadyDeclared(const gd::String& objectName) const {
bool ObjectAlreadyDeclaredByParents(const gd::String& objectName) const {
return (alreadyDeclaredObjectsLists.find(objectName) !=
alreadyDeclaredObjectsLists.end());
};
/**
* \brief Consider that \a objectName is now declared in the context.
*/
void SetObjectDeclared(const gd::String& objectName) {
alreadyDeclaredObjectsLists.insert(objectName);
}
/**
* Return all the objects lists which will be declared by the current context
* ( the non empty as well as the empty objects lists )
* (normal, potentially empty or empty).
*/
std::set<gd::String> GetAllObjectsToBeDeclared() const;
/**
* Return the objects lists which will be declared by the current context
* Return the objects lists which will be declared by the current context.
*/
const std::set<gd::String>& GetObjectsListsToBeDeclared() const {
return objectsListsToBeDeclared;
@@ -166,9 +161,9 @@ class GD_CORE_API EventsCodeGenerationContext {
* Return the objects lists which will be will be declared, without filling
* them with objects from the scene.
*/
const std::set<gd::String>& GetObjectsListsToBeDeclaredWithoutPicking()
const std::set<gd::String>& GetObjectsListsToBeEmptyIfJustDeclared()
const {
return objectsListsWithoutPickingToBeDeclared;
return objectsListsOrEmptyToBeDeclared;
};
/**
@@ -184,7 +179,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* Return the objects lists which are already declared and can be used in the
* current context without declaration.
*/
const std::set<gd::String>& GetObjectsListsAlreadyDeclared() const {
const std::set<gd::String>& GetObjectsListsAlreadyDeclaredByParents() const {
return alreadyDeclaredObjectsLists;
};
@@ -227,22 +222,55 @@ class GD_CORE_API EventsCodeGenerationContext {
*/
size_t GetCurrentConditionDepth() const { return customConditionDepth; }
private:
/**
* \brief Returns the list of all objects declared in this context
* and subcontexts.
* \warning Only works on an async callback's context.
*
* It is to be used by the Async event code generator to know what objects
* lists to backup for the async callback and async callbacks after it.
*/
const std::set<gd::String>& GetAllDeclaredObjectsAcrossChildren() {
return allObjectsListToBeDeclaredAcrossChildren;
};
/**
* Returns true if an object list should be gotten from a backed up
* objects list instead of the parent context. This can happen inside an
* asynchronous callback or a child context of an asynchronous callback (i.e:
* the `asyncDepth` is not 0).
*/
bool ShouldUseAsyncObjectsList(const gd::String& objectName) const;
/**
* Returns true if the code currently being generated is inside an
* asynchronous context (either in an asynchronous callback, or in a children of
* an asynchronous callback).
*/
bool IsInsideAsync() const { return asyncDepth != 0; };
/**
* Returns true if the code currently being generated is an asynchronous
* callback (but not a child of an asynchronous callback).
*/
bool IsAsyncCallback() const { return parent != nullptr && parent->asyncDepth != asyncDepth; }
/**
* \brief Returns true if the given object is already going to be declared
* (either as a traditional objects list, or one without picking, or one
* empty).
*
* in this context (either as a traditional objects list, or an empty one).
*/
bool IsToBeDeclared(const gd::String& objectName) {
return objectsListsToBeDeclared.find(objectName) !=
objectsListsToBeDeclared.end() ||
objectsListsWithoutPickingToBeDeclared.find(objectName) !=
objectsListsWithoutPickingToBeDeclared.end() ||
objectsListsOrEmptyToBeDeclared.find(objectName) !=
objectsListsOrEmptyToBeDeclared.end() ||
emptyObjectsListsToBeDeclared.find(objectName) !=
emptyObjectsListsToBeDeclared.end();
};
private:
void NotifyAsyncParentsAboutDeclaredObject(const gd::String& objectName);
std::set<gd::String>
alreadyDeclaredObjectsLists; ///< Objects lists already needed in a
///< parent context.
@@ -250,7 +278,7 @@ class GD_CORE_API EventsCodeGenerationContext {
objectsListsToBeDeclared; ///< Objects lists that will be declared in
///< this context.
std::set<gd::String>
objectsListsWithoutPickingToBeDeclared; ///< Objects lists that will be
objectsListsOrEmptyToBeDeclared; ///< Objects lists that will be
///< declared in this context,
///< but not filled with scene's
///< objects.
@@ -260,21 +288,40 @@ class GD_CORE_API EventsCodeGenerationContext {
///< but not filled with scene's
///< objects and not filled with any
///< previously existing objects list.
std::set<gd::String>
allObjectsListToBeDeclaredAcrossChildren; ///< This is only to be used by
///< the async callback
///< contexts to know all
///< objects declared across
///< all children, so that the
///< necessary objects can be
///< backed up.
std::map<gd::String, unsigned int>
depthOfLastUse; ///< The context depth when an object was last used.
gd::String
currentObject; ///< The object being used by an action or condition.
unsigned int contextDepth; ///< The depth of the context : 0 for a newly
///< created context, n+1 for any context
///< inheriting from context with depth n.
unsigned int
customConditionDepth; ///< The depth of the conditions being generated.
unsigned int contextDepth = 0; ///< The depth of the context: 0 for a newly
///< created context, n+1 for any context
///< inheriting from context with depth n.
unsigned int customConditionDepth =
0; ///< The depth of the conditions being generated.
unsigned int asyncDepth =
0; ///< If higher than 0, the current context is an asynchronous callback,
///< or a child context of an asynchronous callback:
///< - If the parent's async depth != the current context async depth,
///< then the current context is an asynchronous callback context.
///< - Otherwise, it's a child of an asynchronous callback.
unsigned int* maxDepthLevel; ///< A pointer to a unsigned int updated with
///< the maximum depth reached.
const EventsCodeGenerationContext*
parent; ///< The parent of the current context. Can be NULL.
bool reuseExplicitlyForbidden; ///< If set to true, forbid children context
///< to reuse this one without inheriting.
const EventsCodeGenerationContext* parent =
nullptr; ///< The parent of the current context. Can be NULL.
EventsCodeGenerationContext* nearestAsyncParent =
nullptr; ///< The nearest parent context that is an async callback
///< context.
bool reuseExplicitlyForbidden =
false; ///< If set to true, forbid children contexts
///< to reuse this one without inheriting.
};
} // namespace gd

View File

@@ -43,7 +43,7 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
std::size_t relationalOperatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "relationalOperator")
if (instrInfos.parameters[i].GetType() == "relationalOperator")
relationalOperatorIndex = i;
}
// Ensure that there is at least one parameter after the relational operator
@@ -95,7 +95,7 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
@@ -164,7 +164,7 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
@@ -215,7 +215,7 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
@@ -293,7 +293,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
// Verify that there are no mismatchs between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter =
condition.GetParameter(pNb).GetPlainString();
@@ -303,11 +303,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
instrInfos.parameters[pNb].GetExtraInfo()) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -450,7 +450,9 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
* Generate code for an action.
*/
gd::String EventsCodeGenerator::GenerateActionCode(
gd::Instruction& action, EventsCodeGenerationContext& context) {
gd::Instruction& action,
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
gd::String actionCode;
const gd::InstructionMetadata& instrInfos =
@@ -466,6 +468,14 @@ gd::String EventsCodeGenerator::GenerateActionCode(
action, *this, context);
}
// Get the correct function name depending on whether it should be async or
// not.
const gd::String& functionCallName =
instrInfos.IsAsync() &&
(!instrInfos.IsOptionallyAsync() || action.IsAwaited())
? instrInfos.codeExtraInformation.asyncFunctionCallName
: instrInfos.codeExtraInformation.functionCallName;
// Be sure there is no lack of parameter.
while (action.GetParameters().size() < instrInfos.parameters.size()) {
vector<gd::Expression> parameters = action.GetParameters();
@@ -475,7 +485,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
// Verify that there are no mismatchs between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
@@ -483,11 +493,11 @@ gd::String EventsCodeGenerator::GenerateActionCode(
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
instrInfos.parameters[pNb].GetExtraInfo()) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -518,8 +528,13 @@ gd::String EventsCodeGenerator::GenerateActionCode(
// Prepare arguments and generate the whole action code
vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateObjectAction(
realObjects[i], objInfo, arguments, instrInfos, context);
actionCode += GenerateObjectAction(realObjects[i],
objInfo,
functionCallName,
arguments,
instrInfos,
context,
optionalAsyncCallbackName);
context.SetNoCurrentObject();
}
@@ -550,9 +565,11 @@ gd::String EventsCodeGenerator::GenerateActionCode(
GenerateBehaviorAction(realObjects[i],
action.GetParameter(1).GetPlainString(),
autoInfo,
functionCallName,
arguments,
instrInfos,
context);
context,
optionalAsyncCallbackName);
context.SetNoCurrentObject();
}
@@ -560,12 +577,75 @@ gd::String EventsCodeGenerator::GenerateActionCode(
} else {
vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateFreeAction(arguments, instrInfos, context);
actionCode += GenerateFreeAction(functionCallName,
arguments,
instrInfos,
context,
optionalAsyncCallbackName);
}
return actionCode;
}
const EventsCodeGenerator::CallbackDescriptor
EventsCodeGenerator::GenerateCallback(
const gd::String& callbackID,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents) {
gd::EventsCodeGenerationContext callbackContext;
callbackContext.InheritsAsAsyncCallbackFrom(parentContext);
const gd::String callbackFunctionName =
GetCodeNamespaceAccessor() + "asyncCallback" + callbackID;
const gd::String callbackFunctionArguments =
GenerateEventsParameters(callbackContext);
// Generate actions
gd::String actionsCode = GenerateActionsListCode(actions, callbackContext);
// Generate subevents
if (subEvents != nullptr) // Sub events
{
actionsCode += "\n{ //Subevents\n";
actionsCode += GenerateEventsListCode(*subEvents, callbackContext);
actionsCode += "} //End of subevents\n";
}
// Compose the callback function and add outside main
const gd::String actionsDeclarationsCode =
GenerateObjectsDeclarationCode(callbackContext);
const gd::String callbackCode = callbackFunctionName + " = function (" +
GenerateEventsParameters(callbackContext) +
") {\n" + actionsDeclarationsCode +
actionsCode + "}\n";
AddCustomCodeOutsideMain(callbackCode);
std::set<gd::String> requiredObjects;
// Build the list of all objects required by the callback. Any object that has
// already been declared could have gone through previous object picking, so
// if such an object is used by the actions or subevents of this callback, we
// must ask the caller to pass the already existing objects lists through a
// `LongLivedObjectsList` to the callback function.
for (const auto& objectUsedInSubTree :
callbackContext.GetAllDeclaredObjectsAcrossChildren()) {
if (callbackContext.ObjectAlreadyDeclaredByParents(objectUsedInSubTree))
requiredObjects.insert(objectUsedInSubTree);
};
return CallbackDescriptor(
callbackFunctionName, callbackFunctionArguments, requiredObjects);
};
const gd::String EventsCodeGenerator::GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context) {
gd::String parameters = "runtimeScene";
if (!HasProjectAndLayout()) parameters += ", eventsFunctionContext";
if (context.IsInsideAsync()) parameters += ", asyncObjectsList";
return parameters;
};
/**
* Generate actions code.
*/
@@ -590,8 +670,20 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
return outputCode;
}
const gd::String EventsCodeGenerator::GenerateRelationalOperatorCodes(const gd::String &operatorString) {
if (operatorString == "=") {
return "==";
}
if (operatorString != "<" && operatorString != ">" &&
operatorString != "<=" && operatorString != ">=" && operatorString != "!=") {
cout << "Warning: Bad relational operator: Set to == by default." << endl;
return "==";
}
return operatorString;
}
gd::String EventsCodeGenerator::GenerateParameterCodes(
const gd::String& parameter,
const gd::Expression& parameter,
const gd::ParameterMetadata& metadata,
gd::EventsCodeGenerationContext& context,
const gd::String& lastObjectName,
@@ -599,30 +691,25 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
supplementaryParametersTypes) {
gd::String argOutput;
if (ParameterMetadata::IsExpression("number", metadata.type)) {
if (ParameterMetadata::IsExpression("number", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "number", parameter);
} else if (ParameterMetadata::IsExpression("string", metadata.type)) {
*this, context, "number", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("string", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "string", parameter);
} else if (ParameterMetadata::IsExpression("variable", metadata.type)) {
*this, context, "string", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, metadata.type, parameter, lastObjectName);
} else if (ParameterMetadata::IsObject(metadata.type)) {
*this, context, metadata.GetType(), parameter, lastObjectName);
} else if (ParameterMetadata::IsObject(metadata.GetType())) {
// It would be possible to run a gd::ExpressionCodeGenerator if later
// objects can have nested objects, or function returning objects.
argOutput = GenerateObject(parameter, metadata.type, context);
} else if (metadata.type == "relationalOperator") {
argOutput += parameter == "=" ? "==" : parameter;
if (argOutput != "==" && argOutput != "<" && argOutput != ">" &&
argOutput != "<=" && argOutput != ">=" && argOutput != "!=") {
cout << "Warning: Bad relational operator: Set to == by default." << endl;
argOutput = "==";
}
argOutput =
GenerateObject(parameter.GetPlainString(), metadata.GetType(), context);
} else if (metadata.GetType() == "relationalOperator") {
argOutput += GenerateRelationalOperatorCodes(parameter.GetPlainString());
argOutput = "\"" + argOutput + "\"";
} else if (metadata.type == "operator") {
argOutput += parameter;
} else if (metadata.GetType() == "operator") {
argOutput += parameter.GetPlainString();
if (argOutput != "=" && argOutput != "+" && argOutput != "-" &&
argOutput != "/" && argOutput != "*") {
cout << "Warning: Bad operator: Set to = by default." << endl;
@@ -630,48 +717,52 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
}
argOutput = "\"" + argOutput + "\"";
} else if (ParameterMetadata::IsBehavior(metadata.type)) {
argOutput = GenerateGetBehaviorNameCode(parameter);
} else if (metadata.type == "key") {
argOutput = "\"" + ConvertToString(parameter) + "\"";
} else if (metadata.type == "audioResource" ||
metadata.type == "bitmapFontResource" ||
metadata.type == "fontResource" ||
metadata.type == "imageResource" ||
metadata.type == "jsonResource" ||
metadata.type == "videoResource" ||
} else if (ParameterMetadata::IsBehavior(metadata.GetType())) {
argOutput = GenerateGetBehaviorNameCode(parameter.GetPlainString());
} else if (metadata.GetType() == "key") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.GetType() == "audioResource" ||
metadata.GetType() == "bitmapFontResource" ||
metadata.GetType() == "fontResource" ||
metadata.GetType() == "imageResource" ||
metadata.GetType() == "jsonResource" ||
metadata.GetType() == "videoResource" ||
// Deprecated, old parameter names:
metadata.type == "password" || metadata.type == "musicfile" ||
metadata.type == "soundfile" || metadata.type == "police") {
argOutput = "\"" + ConvertToString(parameter) + "\"";
} else if (metadata.type == "mouse") {
argOutput = "\"" + ConvertToString(parameter) + "\"";
} else if (metadata.type == "yesorno") {
argOutput += (parameter == "yes" || parameter == "oui") ? GenerateTrue()
: GenerateFalse();
} else if (metadata.type == "trueorfalse") {
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.GetType() == "mouse") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.GetType() == "yesorno") {
auto parameterString = parameter.GetPlainString();
argOutput += (parameterString == "yes" || parameterString == "oui")
? GenerateTrue()
: GenerateFalse();
} else if (metadata.GetType() == "trueorfalse") {
auto parameterString = parameter.GetPlainString();
// This is duplicated in AdvancedExtension.cpp for GDJS
argOutput += (parameter == "True" || parameter == "Vrai") ? GenerateTrue()
: GenerateFalse();
argOutput += (parameterString == "True" || parameterString == "Vrai")
? GenerateTrue()
: GenerateFalse();
}
// Code only parameter type
else if (metadata.type == "inlineCode") {
argOutput += metadata.supplementaryInformation;
else if (metadata.GetType() == "inlineCode") {
argOutput += metadata.GetExtraInfo();
} else {
// Try supplementary types if provided
if (supplementaryParametersTypes) {
for (std::size_t i = 0; i < supplementaryParametersTypes->size(); ++i) {
if ((*supplementaryParametersTypes)[i].first == metadata.type)
if ((*supplementaryParametersTypes)[i].first == metadata.GetType())
argOutput += (*supplementaryParametersTypes)[i].second;
}
}
// Type unknown
if (argOutput.empty()) {
if (!metadata.type.empty())
cout << "Warning: Unknown type of parameter \"" << metadata.type
if (!metadata.GetType().empty())
cout << "Warning: Unknown type of parameter \"" << metadata.GetType()
<< "\"." << std::endl;
argOutput += "\"" + ConvertToString(parameter) + "\"";
argOutput += "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
}
}
@@ -691,7 +782,7 @@ vector<gd::String> EventsCodeGenerator::GenerateParametersCodes(
parametersInfo,
[this, &context, &supplementaryParametersTypes, &arguments](
const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::Expression& parameterValue,
const gd::String& lastObjectName) {
gd::String argOutput =
GenerateParameterCodes(parameterValue,
@@ -743,23 +834,21 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
gd::String declarationsCode;
for (auto object : context.GetObjectsListsToBeDeclared()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclared(object)) {
if (!context.ObjectAlreadyDeclaredByParents(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) +
" = runtimeContext->GetObjectsRawPointers(\"" +
ConvertToString(object) + "\");\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = declareObjectList(object, context);
declarationsCode += objectListDeclaration + "\n";
}
for (auto object : context.GetObjectsListsToBeDeclaredWithoutPicking()) {
for (auto object : context.GetObjectsListsToBeEmptyIfJustDeclared()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclared(object)) {
if (!context.ObjectAlreadyDeclaredByParents(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = declareObjectList(object, context);
@@ -767,10 +856,9 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
}
for (auto object : context.GetObjectsListsToBeDeclaredEmpty()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclared(object)) {
if (!context.ObjectAlreadyDeclaredByParents(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
@@ -785,7 +873,7 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
* Generate events list code.
*/
gd::String EventsCodeGenerator::GenerateEventsListCode(
gd::EventsList& events, const EventsCodeGenerationContext& parentContext) {
gd::EventsList& events, EventsCodeGenerationContext& parentContext) {
gd::String output;
for (std::size_t eId = 0; eId < events.size(); ++eId) {
// Each event has its own context : Objects picked in an event are totally
@@ -801,6 +889,8 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
// operation.
bool reuseParentContext =
parentContext.CanReuse() && eId == events.size() - 1;
// TODO: avoid creating if useless.
gd::EventsCodeGenerationContext reusedContext;
reusedContext.Reuse(parentContext);
@@ -945,7 +1035,7 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
for (std::size_t i = 0; i < instrInfos.parameters.size();
++i) // Some conditions already have a "conditionInverted" parameter
{
if (instrInfos.parameters[i].type == "conditionInverted")
if (instrInfos.parameters[i].GetType() == "conditionInverted")
conditionAlreadyTakeCareOfInversion = true;
}
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
@@ -966,7 +1056,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
// Prepare call
// Add a static_cast if necessary
gd::String objectFunctionCallNamePart =
(!instrInfos.parameters[0].supplementaryInformation.empty())
(!instrInfos.parameters[0].GetExtraInfo().empty())
? "static_cast<" + objInfo.className + "*>(" +
GetObjectListName(objectName, context) + "[i])->" +
instrInfos.codeExtraInformation.functionCallName
@@ -1013,9 +1103,11 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
}
gd::String EventsCodeGenerator::GenerateFreeAction(
const gd::String& functionCallName,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context) {
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
// Generate call
gd::String call;
if (instrInfos.codeExtraInformation.type == "number" ||
@@ -1025,32 +1117,39 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
call = GenerateOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName,
functionCallName,
instrInfos.codeExtraInformation.optionalAssociatedInstruction);
else if (instrInfos.codeExtraInformation.accessType ==
gd::InstructionMetadata::ExtraInformation::Mutators)
call =
GenerateMutatorCall(instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName);
functionCallName);
else
call = GenerateCompoundOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName);
functionCallName);
} else {
call = instrInfos.codeExtraInformation.functionCallName + "(" +
call = functionCallName + "(" +
GenerateArgumentsList(arguments) + ")";
}
if (!optionalAsyncCallbackName.empty())
call = "runtimeScene.getAsyncTasksManager().addTask(" + call + ", " +
optionalAsyncCallbackName + ")";
return call + ";\n";
}
gd::String EventsCodeGenerator::GenerateObjectAction(
const gd::String& objectName,
const gd::ObjectMetadata& objInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context) {
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
// Create call
gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1060,25 +1159,26 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
call = GenerateOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName,
functionCallName,
instrInfos.codeExtraInformation.optionalAssociatedInstruction,
2);
else
call = GenerateCompoundOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName,
2);
instrInfos, arguments, functionCallName, 2);
return "For each picked object \"" + objectName + "\", call " + call +
".\n";
} else {
gd::String argumentsStr = GenerateArgumentsList(arguments, 1);
call = instrInfos.codeExtraInformation.functionCallName + "(" +
argumentsStr + ")";
call = functionCallName + "(" + argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ").\n";
argumentsStr + ")" +
(optionalAsyncCallbackName.empty()
? ""
: (", then call" + optionalAsyncCallbackName)) +
".\n";
}
}
@@ -1086,9 +1186,11 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
const gd::String& objectName,
const gd::String& behaviorName,
const gd::BehaviorMetadata& autoInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context) {
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
// Create call
gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1098,24 +1200,29 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
call = GenerateOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName,
functionCallName,
instrInfos.codeExtraInformation.optionalAssociatedInstruction,
2);
else
call = GenerateCompoundOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName,
functionCallName,
2);
return "For each picked object \"" + objectName + "\", call " + call +
" for behavior \"" + behaviorName + "\".\n";
} else {
gd::String argumentsStr = GenerateArgumentsList(arguments, 2);
call = instrInfos.codeExtraInformation.functionCallName + "(" +
call = functionCallName + "(" +
argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ")" + " for behavior \"" + behaviorName + "\".\n";
argumentsStr + ")" + " for behavior \"" + behaviorName + "\"" +
(optionalAsyncCallbackName.empty()
? ""
: (", then call" + optionalAsyncCallbackName)) +
".\n";
}
}
@@ -1163,7 +1270,7 @@ gd::String EventsCodeGenerator::GenerateArgumentsList(
return argumentsStr;
}
EventsCodeGenerator::EventsCodeGenerator(gd::Project& project_,
EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
const gd::Layout& layout,
const gd::Platform& platform_)
: platform(platform_),
@@ -1180,7 +1287,7 @@ EventsCodeGenerator::EventsCodeGenerator(gd::Project& project_,
EventsCodeGenerator::EventsCodeGenerator(
const gd::Platform& platform_,
gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& objectsAndGroups_)
: platform(platform_),
globalObjectsAndGroups(globalObjectsAndGroups_),

View File

@@ -48,7 +48,7 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Construct a code generator for the specified
* platform/project/layout.
*/
EventsCodeGenerator(gd::Project& project_,
EventsCodeGenerator(const gd::Project& project_,
const gd::Layout& layout,
const gd::Platform& platform_);
@@ -57,7 +57,7 @@ class GD_CORE_API EventsCodeGenerator {
* objects/groups and platform
*/
EventsCodeGenerator(const gd::Platform& platform,
gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& objectsAndGroups_);
virtual ~EventsCodeGenerator(){};
@@ -77,7 +77,7 @@ class GD_CORE_API EventsCodeGenerator {
* \return Code
*/
virtual gd::String GenerateEventsListCode(
gd::EventsList& events, const EventsCodeGenerationContext& context);
gd::EventsList& events, EventsCodeGenerationContext& context);
/**
* \brief Generate code for executing a condition list
@@ -154,8 +154,54 @@ class GD_CORE_API EventsCodeGenerator {
* \param context Context used for generation
* \return Code
*/
gd::String GenerateActionCode(gd::Instruction& action,
EventsCodeGenerationContext& context);
gd::String GenerateActionCode(
gd::Instruction& action,
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
struct CallbackDescriptor {
CallbackDescriptor(const gd::String functionName_,
const gd::String argumentsList_,
const std::set<gd::String> requiredObjects_)
: functionName(functionName_),
argumentsList(argumentsList_),
requiredObjects(requiredObjects_){};
/**
* The name by which the function can be invoked.
*/
const gd::String functionName;
/**
* The comma separated list of arguments that the function takes.
*/
const gd::String argumentsList;
/**
* A set of all objects that need to be backed up to be passed to the
* callback code.
*/
const std::set<gd::String> requiredObjects;
};
/**
* \brief Generates actions and events as a callback.
*
* This is used by asynchronous functions to run the code out of the normal
* events flow.
*
* \returns A set with all objects required by the callback code.
* The caller must take care of backing them up in a LongLivedObjectsList,
* and to pass it to the callback function as the last argument.
*/
virtual const CallbackDescriptor GenerateCallback(
const gd::String& callbackFunctionName,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents = nullptr);
/**
* \brief Generates the parameters list of an event's generated function.
*/
const gd::String GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context);
/**
* \brief Generate code for declaring objects lists.
@@ -283,7 +329,7 @@ class GD_CORE_API EventsCodeGenerator {
/**
* \brief Get the global objects/groups used for code generation.
*/
gd::ObjectsContainer& GetGlobalObjectsAndGroups() const {
const gd::ObjectsContainer& GetGlobalObjectsAndGroups() const {
return globalObjectsAndGroups;
}
@@ -304,7 +350,7 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Get the project the code is being generated for.
* \warning This is only valid if HasProjectAndLayout() is true.
*/
gd::Project& GetProject() const { return *project; }
const gd::Project& GetProject() const { return *project; }
/**
* \brief Get the layout the code is being generated for.
@@ -435,6 +481,9 @@ class GD_CORE_API EventsCodeGenerator {
*/
size_t GenerateSingleUsageUniqueIdForEventsList();
virtual const gd::String GenerateRelationalOperatorCodes(
const gd::String& operatorString);
protected:
/**
* \brief Generate the code for a single parameter.
@@ -462,25 +511,18 @@ class GD_CORE_API EventsCodeGenerator {
* Other standard parameters type that should be implemented by platforms:
* - currentScene: Reference to the current runtime scene.
* - objectList : a map containing lists of objects which are specified by the
object name in another parameter. Example:
* \code
AddExpression("Count", _("Object count"), _("Count the number of picked
objects"), _("Objects"), "res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.SetFunctionName("getPickedObjectsCount");
* \endcode
* - objectListWithoutPicking : Same as objectList but do not pick object if
they are not already picked.
* - objectPtr : Return a reference to the object specified by the object name in
another parameter. Example:
object name in another parameter.
* - objectListOrEmptyIfJustDeclared : Same as `objectList` but do not pick
object if they are not already picked.
* - objectPtr: Return a reference to the object specified by the object name
in another parameter. Example:
* \code
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Target object"))
* \endcode
*/
virtual gd::String GenerateParameterCodes(
const gd::String& parameter,
const gd::Expression& parameter,
const gd::ParameterMetadata& metadata,
gd::EventsCodeGenerationContext& context,
const gd::String& lastObjectName,
@@ -663,24 +705,30 @@ class GD_CORE_API EventsCodeGenerator {
gd::EventsCodeGenerationContext& context);
virtual gd::String GenerateFreeAction(
const gd::String& functionCallName,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context);
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
virtual gd::String GenerateObjectAction(
const gd::String& objectName,
const gd::ObjectMetadata& objInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context);
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
virtual gd::String GenerateBehaviorAction(
const gd::String& objectName,
const gd::String& behaviorName,
const gd::BehaviorMetadata& autoInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context);
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
gd::String GenerateRelationalOperatorCall(
const gd::InstructionMetadata& instrInfos,
@@ -730,13 +778,13 @@ class GD_CORE_API EventsCodeGenerator {
const gd::Platform& platform; ///< The platform being used.
gd::ObjectsContainer& globalObjectsAndGroups;
const gd::ObjectsContainer& globalObjectsAndGroups;
const gd::ObjectsContainer& objectsAndGroups;
bool hasProjectAndLayout; ///< true only if project and layout are valid
///< references. If false, they should not be used.
gd::Project* project; ///< The project being used.
const gd::Layout* scene; ///< The scene being generated.
const gd::Project* project; ///< The project being used.
const gd::Layout* scene; ///< The scene being generated.
bool errorOccurred; ///< Must be set to true if an error occured.
bool compilationForRuntime; ///< Is set to true if the code generation is

View File

@@ -25,36 +25,38 @@
#include "GDCore/IDE/Events/ExpressionValidator.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
namespace gd {
gd::String ExpressionCodeGenerator::GenerateExpressionCode(
EventsCodeGenerator& codeGenerator,
EventsCodeGenerationContext& context,
const gd::String& type,
const gd::String& expression,
const gd::String& objectName) {
gd::ExpressionParser2 parser(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups());
ExpressionCodeGenerator generator(codeGenerator, context);
const gd::String& rootType,
const gd::Expression& expression,
const gd::String& rootObjectName) {
ExpressionCodeGenerator generator(rootType, rootObjectName, codeGenerator, context);
auto node = parser.ParseExpression(type, expression, objectName);
auto node = expression.GetRootNode();
if (!node) {
std::cout << "Error: error while parsing: \"" << expression << "\" ("
<< type << ")" << std::endl;
std::cout << "Error: error while parsing: \"" << expression.GetPlainString()
<< "\" (" << rootType << ")" << std::endl;
return generator.GenerateDefaultValue(type);
return generator.GenerateDefaultValue(rootType);
}
gd::ExpressionValidator validator;
gd::ExpressionValidator validator(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType);
node->Visit(validator);
if (!validator.GetErrors().empty()) {
std::cout << "Error: \"" << validator.GetErrors()[0]->GetMessage()
<< "\" in: \"" << expression << "\" (" << type << ")"
<< std::endl;
<< "\" in: \"" << expression.GetPlainString() << "\" ("
<< rootType << ")" << std::endl;
return generator.GenerateDefaultValue(type);
return generator.GenerateDefaultValue(rootType);
}
node->Visit(generator);
@@ -97,15 +99,24 @@ void ExpressionCodeGenerator::OnVisitTextNode(TextNode& node) {
void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
// This "translation" from the type to an enum could be avoided
// if all types were moved to an enum.
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
EventsCodeGenerator::VariableScope scope =
node.type == "globalvar"
type == "globalvar"
? gd::EventsCodeGenerator::PROJECT_VARIABLE
: ((node.type == "scenevar")
: ((type == "scenevar")
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootObjectName,
node);
output += codeGenerator.GenerateGetVariable(
node.name, scope, context, node.objectName);
node.name, scope, context, objectName);
if (node.child) node.child->Visit(*this);
}
@@ -117,7 +128,7 @@ void ExpressionCodeGenerator::OnVisitVariableAccessorNode(
void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode& node) {
ExpressionCodeGenerator generator(codeGenerator, context);
ExpressionCodeGenerator generator("string", "", codeGenerator, context);
node.expression->Visit(generator);
output +=
codeGenerator.GenerateVariableBracketAccessor(generator.GetOutput());
@@ -125,39 +136,79 @@ void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
}
void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
if (gd::ParameterMetadata::IsObject(node.type)) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
if (gd::ParameterMetadata::IsObject(type)) {
output +=
codeGenerator.GenerateObject(node.identifierName, node.type, context);
} else {
codeGenerator.GenerateObject(node.identifierName, type, context);
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
EventsCodeGenerator::VariableScope scope =
type == "globalvar"
? gd::EventsCodeGenerator::PROJECT_VARIABLE
: ((type == "scenevar")
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootObjectName,
node);
output += codeGenerator.GenerateGetVariable(
node.identifierName, scope, context, objectName);
if (!node.childIdentifierName.empty()) {
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
}
} else if (node.childIdentifierName.empty()) {
output += "/* Error during generation, unrecognized identifier type: " +
codeGenerator.ConvertToString(node.type) + " with value " +
codeGenerator.ConvertToString(type) + " with value " +
codeGenerator.ConvertToString(node.identifierName) + " */ " +
codeGenerator.ConvertToStringExplicit(node.identifierName);
}
else {
// This is for function names that are put in IdentifierNode
// because the type is needed to tell them appart from variables.
output += GenerateDefaultValue(type);
}
}
void ExpressionCodeGenerator::OnVisitFunctionCallNode(FunctionCallNode& node) {
if (gd::MetadataProvider::IsBadExpressionMetadata(node.expressionMetadata)) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
node);
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
output += "/* Error during generation, function not found: " +
codeGenerator.ConvertToString(node.functionName) + " */ " +
GenerateDefaultValue(node.type);
GenerateDefaultValue(type);
return;
}
if (!node.objectName.empty()) {
if (!node.behaviorName.empty()) {
output += GenerateBehaviorFunctionCode(node.type,
output += GenerateBehaviorFunctionCode(type,
node.objectName,
node.behaviorName,
node.parameters,
node.expressionMetadata);
metadata);
} else {
output += GenerateObjectFunctionCode(
node.type, node.objectName, node.parameters, node.expressionMetadata);
type, node.objectName, node.parameters, metadata);
}
} else {
output +=
GenerateFreeFunctionCode(node.parameters, node.expressionMetadata);
GenerateFreeFunctionCode(node.parameters, metadata);
}
}
@@ -305,18 +356,21 @@ gd::String ExpressionCodeGenerator::GenerateParametersCodes(
auto& parameterMetadata = expressionMetadata.parameters[i];
if (!parameterMetadata.IsCodeOnly()) {
ExpressionCodeGenerator generator(codeGenerator, context);
if (nonCodeOnlyParameterIndex < parameters.size()) {
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootObjectName,
*parameters[nonCodeOnlyParameterIndex].get());
ExpressionCodeGenerator generator(parameterMetadata.GetType(), objectName, codeGenerator, context);
parameters[nonCodeOnlyParameterIndex]->Visit(generator);
parametersCode += generator.GetOutput();
} else if (parameterMetadata.IsOptional()) {
ExpressionCodeGenerator generator(parameterMetadata.GetType(), "", codeGenerator, context);
// Optional parameters default value were not parsed at the time of the
// expression parsing. Parse them now.
ExpressionParser2 parser(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups());
auto node = parser.ParseExpression(parameterMetadata.GetType(),
parameterMetadata.GetDefaultValue());
ExpressionParser2 parser;
auto node = parser.ParseExpression(parameterMetadata.GetDefaultValue());
node->Visit(generator);
parametersCode += generator.GetOutput();
@@ -374,12 +428,22 @@ gd::String ExpressionCodeGenerator::GenerateDefaultValue(
}
void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
output += GenerateDefaultValue(node.type);
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
output += GenerateDefaultValue(type);
}
void ExpressionCodeGenerator::OnVisitObjectFunctionNameNode(
ObjectFunctionNameNode& node) {
output += GenerateDefaultValue(node.type);
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
output += GenerateDefaultValue(type);
}
} // namespace gd

View File

@@ -9,7 +9,6 @@
#include <memory>
#include <vector>
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/String.h"
@@ -35,9 +34,11 @@ namespace gd {
*/
class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
public:
ExpressionCodeGenerator(EventsCodeGenerator& codeGenerator_,
ExpressionCodeGenerator(const gd::String &rootType_,
const gd::String &rootObjectName_,
EventsCodeGenerator& codeGenerator_,
EventsCodeGenerationContext& context_)
: codeGenerator(codeGenerator_), context(context_){};
: rootType(rootType_), rootObjectName(rootObjectName_), codeGenerator(codeGenerator_), context(context_){};
virtual ~ExpressionCodeGenerator(){};
/**
@@ -57,7 +58,7 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
static gd::String GenerateExpressionCode(EventsCodeGenerator& codeGenerator,
EventsCodeGenerationContext& context,
const gd::String& type,
const gd::String& expression,
const gd::Expression& expression,
const gd::String& objectName = "");
const gd::String& GetOutput() { return output; };
@@ -103,6 +104,8 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
gd::String output;
EventsCodeGenerator& codeGenerator;
EventsCodeGenerationContext& context;
const gd::String rootType;
const gd::String rootObjectName;
};
} // namespace gd

View File

@@ -5,8 +5,11 @@
*/
#include "GDCore/Events/Event.h"
#include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
@@ -65,10 +68,41 @@ gd::String BaseEvent::GenerateEventCode(
return "";
}
void BaseEvent::PreprocessAsyncActions(const gd::Platform& platform) {
if (!CanHaveSubEvents()) return;
for (const auto& actionsList : GetAllActionsVectors())
for (std::size_t aId = 0; aId < actionsList->size(); ++aId) {
const auto& action = actionsList->at(aId);
const gd::InstructionMetadata& actionMetadata =
gd::MetadataProvider::GetActionMetadata(platform, action.GetType());
if (actionMetadata.IsAsync() &&
(!actionMetadata.IsOptionallyAsync() || action.IsAwaited())) {
gd::InstructionsList remainingActions;
remainingActions.InsertInstructions(
*actionsList, aId + 1, actionsList->size() - 1);
gd::AsyncEvent asyncEvent(action, remainingActions, GetSubEvents());
// Ensure that the local event no longer has any of the actions/subevent
// after the async function
actionsList->RemoveAfter(aId);
GetSubEvents().Clear();
GetSubEvents().InsertEvent(asyncEvent);
// We just moved all the rest, there's nothing left to do in this event.
return;
}
}
};
void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator,
gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList) {
if (IsDisabled() || !MustBePreprocessed()) return;
if (IsDisabled()) return;
PreprocessAsyncActions(codeGenerator.GetPlatform());
if (!MustBePreprocessed()) return;
try {
if (type.empty()) return;

View File

@@ -10,6 +10,7 @@
#include <iostream>
#include <memory>
#include <vector>
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
@@ -23,7 +24,7 @@ class EventsCodeGenerationContext;
class Platform;
class SerializerElement;
class Instruction;
}
} // namespace gd
namespace gd {
@@ -136,13 +137,15 @@ class GD_CORE_API BaseEvent {
* \note Used to preprocess or search in the expressions of the event.
*/
virtual std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() {
GetAllExpressionsWithMetadata() {
std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> > noExpr;
return noExpr;
};
virtual std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() const {
std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> > noExpr;
virtual std::vector<
std::pair<const gd::Expression*, const gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() const {
std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
noExpr;
return noExpr;
};
@@ -206,6 +209,11 @@ class GD_CORE_API BaseEvent {
gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList);
/**
* A function that turns all async member actions into an Async subevent for code generation.
*/
void PreprocessAsyncActions(const gd::Platform& platform);
/**
* \brief If MustBePreprocessed is redefined to return true, the
* gd::EventMetadata::preprocessing associated to the event will be called to

View File

@@ -0,0 +1,41 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Events/Expression.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/String.h"
namespace gd {
Expression::Expression() : node(nullptr) {};
Expression::Expression(gd::String plainString_)
: node(nullptr), plainString(plainString_) {};
Expression::Expression(const char* plainString_)
: node(nullptr), plainString(plainString_) {};
Expression::Expression(const Expression& copy)
: node(nullptr), plainString{copy.plainString} {};
Expression& Expression::operator=(const Expression& expression) {
plainString = expression.plainString;
node = nullptr;
return *this;
};
Expression::~Expression(){};
ExpressionNode* Expression::GetRootNode() const {
if (!node) {
gd::ExpressionParser2 parser = ExpressionParser2();
node = std::move(parser.ParseExpression(plainString));
}
return node.get();
}
} // namespace gd

View File

@@ -6,7 +6,15 @@
#ifndef GDCORE_EXPRESSION_H
#define GDCORE_EXPRESSION_H
#include "GDCore/String.h"
#include <memory>
namespace gd {
class ExpressionParser2;
class ObjectsContainer;
struct ExpressionNode;
} // namespace gd
namespace gd {
@@ -24,32 +32,49 @@ class GD_CORE_API Expression {
/**
* \brief Construct an empty expression
*/
Expression(){};
Expression();
/**
* \brief Construct an expression from a string
*/
Expression(gd::String plainString_) : plainString(plainString_){};
Expression(gd::String plainString_);
/**
* \brief Construct an expression from a const char *
*/
Expression(const char* plainString_) : plainString(plainString_){};
Expression(const char* plainString_);
/**
* \brief Copy construct an expression.
*/
Expression(const Expression& copy);
/**
* \brief Expression affectation overriding.
*/
Expression& operator=(const Expression& expression);
/**
* \brief Get the plain string representing the expression
*/
inline const gd::String& GetPlainString() const { return plainString; };
/**
* @brief Get the expression node.
* @return std::unique_ptr<gd::ExpressionNode>
*/
gd::ExpressionNode* GetRootNode() const;
/**
* \brief Mimics std::string::c_str
*/
inline const char* c_str() const { return plainString.c_str(); };
virtual ~Expression(){};
virtual ~Expression();
private:
gd::String plainString; ///< The expression string
mutable std::unique_ptr<gd::ExpressionNode> node;
};
} // namespace gd

View File

@@ -55,6 +55,10 @@ void Instruction::SetParameter(std::size_t nb, const gd::Expression& val) {
parameters[nb] = val;
}
void Instruction::AddParameter(const gd::Expression& val) {
parameters.push_back(val);
}
std::shared_ptr<Instruction> GD_CORE_API
CloneRememberingOriginalElement(std::shared_ptr<Instruction> instruction) {
std::shared_ptr<Instruction> copy =

View File

@@ -72,6 +72,22 @@ class GD_CORE_API Instruction {
*/
void SetInverted(bool inverted_) { inverted = inverted_; }
/**
* \brief Return true if the async instruction should be awaited.
* This is not relevant if the instruction is not optionally asynchronous.
*
* \return true if the instruction is to be awaited
*/
bool IsAwaited() const { return awaitAsync; }
/**
* \brief Set if the async instruction is to be awaited or not.
* This is not relevant if the instruction is not optionally asynchronous.
*
* \param inverted true if the instruction must be awaited
*/
void SetAwaited(bool awaited) { awaitAsync = awaited; }
/**
* \brief Return the number of parameters of the instruction.
*/
@@ -107,6 +123,11 @@ class GD_CORE_API Instruction {
*/
void SetParameter(std::size_t nb, const gd::Expression& val);
/** Add a parameter at the end
* \param val The new value of the parameter
*/
void AddParameter(const gd::Expression& val);
/** \brief Get a reference to the std::vector containing the parameters.
* \return A std::vector containing the parameters
*/
@@ -139,7 +160,9 @@ class GD_CORE_API Instruction {
* Useful to get reference to the original instruction in memory during code
* generation, to ensure stable unique identifiers.
*/
std::weak_ptr<Instruction> GetOriginalInstruction() { return originalInstruction; };
std::weak_ptr<Instruction> GetOriginalInstruction() {
return originalInstruction;
};
friend std::shared_ptr<Instruction> CloneRememberingOriginalElement(
std::shared_ptr<Instruction> instruction);
@@ -148,6 +171,9 @@ class GD_CORE_API Instruction {
gd::String type; ///< Instruction type
bool inverted; ///< True if the instruction if inverted. Only applicable for
///< instruction used as conditions by events
bool awaitAsync =
false; ///< Tells the code generator whether the optionally asynchronous
///< instruction should be generated as asynchronous (awaited) or not.
mutable std::vector<gd::Expression>
parameters; ///< Vector containing the parameters
gd::InstructionsList subInstructions; ///< Sub instructions, if applicable.

View File

@@ -5,6 +5,7 @@
*/
#include "InstructionsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Project/Project.h"
#include "Serialization.h"
@@ -31,6 +32,10 @@ void InstructionsList::InsertInstructions(const InstructionsList& list,
}
}
void InstructionsList::RemoveAfter(const size_t position) {
elements.resize(position);
}
void InstructionsList::SerializeTo(SerializerElement& element) const {
EventsListSerialization::SerializeInstructionsTo(*this, element);
}

View File

@@ -6,9 +6,10 @@
#ifndef GDCORE_INSTRUCTIONSLIST_H
#define GDCORE_INSTRUCTIONSLIST_H
#include "GDCore/Tools/SPtrList.h"
#include <memory>
#include <vector>
#include "GDCore/Tools/SPtrList.h"
namespace gd {
class Instruction;
}
@@ -22,11 +23,11 @@ class SerializerElement;
namespace gd {
class InstructionsList : public SPtrList<gd::Instruction> {
public:
void InsertInstructions(const InstructionsList& list,
size_t begin,
size_t end,
size_t position = (size_t)-1);
public:
void InsertInstructions(const InstructionsList &list, size_t begin,
size_t end, size_t position = (size_t)-1);
void RemoveAfter(size_t position);
/** \name Serialization
*/
@@ -35,17 +36,17 @@ class InstructionsList : public SPtrList<gd::Instruction> {
* \brief Serialize the instructions to the specified element
* \see EventsListSerialization
*/
void SerializeTo(gd::SerializerElement& element) const;
void SerializeTo(gd::SerializerElement &element) const;
/**
* \brief Load the instructions from the specified element
* \see EventsListSerialization
*/
void UnserializeFrom(gd::Project& project,
const gd::SerializerElement& element);
void UnserializeFrom(gd::Project &project,
const gd::SerializerElement &element);
///@}
};
} // namespace gd
} // namespace gd
#endif

View File

@@ -26,132 +26,16 @@ namespace gd {
gd::String ExpressionParser2::NAMESPACE_SEPARATOR = "::";
ExpressionParser2::ExpressionParser2(
const gd::Platform& platform_,
const gd::ObjectsContainer& globalObjectsContainer_,
const gd::ObjectsContainer& objectsContainer_)
ExpressionParser2::ExpressionParser2()
: expression(""),
currentPosition(0),
platform(platform_),
globalObjectsContainer(globalObjectsContainer_),
objectsContainer(objectsContainer_) {}
namespace {
/**
* Return the minimum number of parameters, starting from a given parameter
* (by convention, 1 for object functions and 2 for behavior functions).
*/
size_t GetMinimumParametersNumber(
const std::vector<gd::ParameterMetadata>& parameters,
size_t initialParameterIndex) {
size_t nb = 0;
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
if (!parameters[i].optional && !parameters[i].codeOnly) nb++;
}
return nb;
}
/**
* Return the maximum number of parameters, starting from a given parameter
* (by convention, 1 for object functions and 2 for behavior functions).
*/
size_t GetMaximumParametersNumber(
const std::vector<gd::ParameterMetadata>& parameters,
size_t initialParameterIndex) {
size_t nb = 0;
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
if (!parameters[i].codeOnly) nb++;
}
return nb;
}
} // namespace
std::unique_ptr<ExpressionParserDiagnostic> ExpressionParser2::ValidateFunction(
const gd::String& type,
const gd::FunctionCallNode& function,
size_t functionStartPosition) {
if (gd::MetadataProvider::IsBadExpressionMetadata(
function.expressionMetadata)) {
return gd::make_unique<ExpressionParserError>(
"invalid_function_name",
_("Cannot find an expression with this name: ") +
function.functionName + "\n" +
_("Double check that you've not made any typo in the name."),
functionStartPosition,
GetCurrentPosition());
}
// Validate the type of the function
const gd::String& returnType = function.expressionMetadata.GetReturnType();
if (returnType == "number") {
if (type == "string")
return RaiseTypeError(
_("You tried to use an expression that returns a number, but a "
"string is expected. Use `ToString` if you need to convert a "
"number to a string."),
functionStartPosition);
else if (type != "number" && type != "number|string")
return RaiseTypeError(_("You tried to use an expression that returns a "
"number, but another type is expected:") +
" " + type,
functionStartPosition);
} else if (returnType == "string") {
if (type == "number")
return RaiseTypeError(
_("You tried to use an expression that returns a string, but a "
"number is expected. Use `ToNumber` if you need to convert a "
"string to a number."),
functionStartPosition);
else if (type != "string" && type != "number|string")
return RaiseTypeError(_("You tried to use an expression that returns a "
"string, but another type is expected:") +
" " + type,
functionStartPosition);
} else {
if (type != returnType)
return RaiseTypeError(
_("You tried to use an expression with the wrong return type:") + " " +
returnType,
functionStartPosition);
}
// Validate parameters count
size_t minParametersCount = GetMinimumParametersNumber(
function.expressionMetadata.parameters,
WrittenParametersFirstIndex(function.objectName, function.behaviorName));
size_t maxParametersCount = GetMaximumParametersNumber(
function.expressionMetadata.parameters,
WrittenParametersFirstIndex(function.objectName, function.behaviorName));
if (function.parameters.size() < minParametersCount ||
function.parameters.size() > maxParametersCount) {
gd::String expectedCountMessage =
minParametersCount == maxParametersCount
? _("The number of parameters must be exactly ") +
gd::String::From(minParametersCount)
: _("The number of parameters must be: ") +
gd::String::From(minParametersCount) + "-" +
gd::String::From(maxParametersCount);
if (function.parameters.size() < minParametersCount) {
return gd::make_unique<ExpressionParserError>(
"too_few_parameters",
"You have not entered enough parameters for the expression. " +
expectedCountMessage,
functionStartPosition,
GetCurrentPosition());
}
}
return gd::make_unique<ExpressionParserDiagnostic>();
}
currentPosition(0) {}
std::unique_ptr<TextNode> ExpressionParser2::ReadText() {
size_t textStartPosition = GetCurrentPosition();
SkipAllWhitespaces();
if (!CheckIfChar(IsQuote)) {
auto text = gd::make_unique<TextNode>("");
// It can't happen.
text->diagnostic =
RaiseSyntaxError(_("A text must start with a double quote (\")."));
text->location =

View File

@@ -40,9 +40,7 @@ namespace gd {
*/
class GD_CORE_API ExpressionParser2 {
public:
ExpressionParser2(const gd::Platform &platform_,
const gd::ObjectsContainer &globalObjectsContainer_,
const gd::ObjectsContainer &objectsContainer_);
ExpressionParser2();
virtual ~ExpressionParser2(){};
/**
@@ -58,13 +56,11 @@ class GD_CORE_API ExpressionParser2 {
* \return The node representing the expression as a parsed tree.
*/
std::unique_ptr<ExpressionNode> ParseExpression(
const gd::String &type,
const gd::String &expression_,
const gd::String &objectName = "") {
const gd::String &expression_) {
expression = expression_;
currentPosition = 0;
return Start(type, objectName);
return Start();
}
/**
@@ -88,18 +84,16 @@ class GD_CORE_API ExpressionParser2 {
* Each method is a part of the grammar.
*/
///@{
std::unique_ptr<ExpressionNode> Start(const gd::String &type,
const gd::String &objectName = "") {
std::unique_ptr<ExpressionNode> Start() {
size_t expressionStartPosition = GetCurrentPosition();
auto expression = Expression(type, objectName);
const gd::String &inferredType = expression->type;
auto expression = Expression();
// Check for extra characters at the end of the expression
if (!IsEndReached()) {
auto op = gd::make_unique<OperatorNode>(inferredType, ' ');
auto op = gd::make_unique<OperatorNode>(' ');
op->leftHandSide = std::move(expression);
op->rightHandSide = ReadUntilEnd("unknown");
op->rightHandSide = ReadUntilEnd();
op->rightHandSide->parent = op.get();
op->rightHandSide->diagnostic = RaiseSyntaxError(
_("The expression has extra character at the end that should be "
@@ -113,61 +107,49 @@ class GD_CORE_API ExpressionParser2 {
return expression;
}
std::unique_ptr<ExpressionNode> Expression(
const gd::String &type, const gd::String &objectName = "") {
std::unique_ptr<ExpressionNode> Expression() {
SkipAllWhitespaces();
size_t expressionStartPosition = GetCurrentPosition();
std::unique_ptr<ExpressionNode> leftHandSide = Term(type, objectName);
const gd::String &inferredType = leftHandSide->type;
std::unique_ptr<ExpressionNode> leftHandSide = Term();
SkipAllWhitespaces();
if (IsEndReached()) return leftHandSide;
if (CheckIfChar(IsExpressionEndingChar)) return leftHandSide;
if (CheckIfChar(IsExpressionOperator)) {
auto op = gd::make_unique<OperatorNode>(inferredType, GetCurrentChar());
auto op = gd::make_unique<OperatorNode>(GetCurrentChar());
op->leftHandSide = std::move(leftHandSide);
op->diagnostic = ValidateOperator(inferredType, GetCurrentChar());
op->leftHandSide->parent = op.get();
op->diagnostic = ValidateOperator(GetCurrentChar());
SkipChar();
op->rightHandSide = Expression(inferredType, objectName);
op->rightHandSide = Expression();
op->rightHandSide->parent = op.get();
op->location = ExpressionParserLocation(expressionStartPosition,
GetCurrentPosition());
return std::move(op);
}
if (inferredType == "string") {
leftHandSide->diagnostic = RaiseSyntaxError(
"You must add the operator + between texts or expressions. For "
"example: \"Your name: \" + VariableString(PlayerName).");
} else if (inferredType == "number") {
leftHandSide->diagnostic = RaiseSyntaxError(
"No operator found. Did you forget to enter an operator (like +, -, "
"* or /) between numbers or expressions?");
} else {
leftHandSide->diagnostic = RaiseSyntaxError(
"More than one term was found. Verify that your expression is "
"properly written.");
}
leftHandSide->diagnostic = RaiseSyntaxError(
"More than one term was found. Verify that your expression is "
"properly written.");
auto op = gd::make_unique<OperatorNode>(inferredType, ' ');
auto op = gd::make_unique<OperatorNode>(' ');
op->leftHandSide = std::move(leftHandSide);
op->rightHandSide = Expression(inferredType, objectName);
op->leftHandSide->parent = op.get();
op->rightHandSide = Expression();
op->rightHandSide->parent = op.get();
op->location =
ExpressionParserLocation(expressionStartPosition, GetCurrentPosition());
return std::move(op);
}
std::unique_ptr<ExpressionNode> Term(const gd::String &type,
const gd::String &objectName) {
std::unique_ptr<ExpressionNode> Term() {
SkipAllWhitespaces();
size_t expressionStartPosition = GetCurrentPosition();
std::unique_ptr<ExpressionNode> factor = Factor(type, objectName);
const gd::String &inferredType = factor->type;
std::unique_ptr<ExpressionNode> factor = Factor();
SkipAllWhitespaces();
@@ -175,11 +157,13 @@ class GD_CORE_API ExpressionParser2 {
// to guarantee the proper operator precedence. (Expression could also
// be reworked to use a while loop).
while (CheckIfChar(IsTermOperator)) {
auto op = gd::make_unique<OperatorNode>(inferredType, GetCurrentChar());
auto op = gd::make_unique<OperatorNode>(GetCurrentChar());
op->leftHandSide = std::move(factor);
op->diagnostic = ValidateOperator(inferredType, GetCurrentChar());
op->leftHandSide->parent = op.get();
op->diagnostic = ValidateOperator(GetCurrentChar());
SkipChar();
op->rightHandSide = Factor(inferredType, objectName);
op->rightHandSide = Factor();
op->rightHandSide->parent = op.get();
op->location = ExpressionParserLocation(expressionStartPosition,
GetCurrentPosition());
SkipAllWhitespaces();
@@ -190,54 +174,35 @@ class GD_CORE_API ExpressionParser2 {
return factor;
};
std::unique_ptr<ExpressionNode> Factor(const gd::String &type,
const gd::String &objectName) {
std::unique_ptr<ExpressionNode> Factor() {
SkipAllWhitespaces();
size_t expressionStartPosition = GetCurrentPosition();
if (CheckIfChar(IsQuote)) {
std::unique_ptr<ExpressionNode> factor = ReadText();
if (type == "number")
factor->diagnostic =
RaiseTypeError(_("You entered a text, but a number was expected."),
expressionStartPosition);
else if (type != "string" && type != "number|string")
factor->diagnostic = RaiseTypeError(
_("You entered a text, but this type was expected:") + type,
expressionStartPosition);
return factor;
} else if (CheckIfChar(IsUnaryOperator)) {
auto unaryOperatorCharacter = GetCurrentChar();
SkipChar();
auto operatorOperand = Factor(type, objectName);
const gd::String &inferredType = operatorOperand->type;
auto operatorOperand = Factor();
auto unaryOperator = gd::make_unique<UnaryOperatorNode>(
inferredType, unaryOperatorCharacter);
unaryOperatorCharacter);
unaryOperator->diagnostic = ValidateUnaryOperator(
inferredType, unaryOperatorCharacter, expressionStartPosition);
unaryOperatorCharacter, expressionStartPosition);
unaryOperator->factor = std::move(operatorOperand);
unaryOperator->factor->parent = unaryOperator.get();
unaryOperator->location = ExpressionParserLocation(
expressionStartPosition, GetCurrentPosition());
return std::move(unaryOperator);
} else if (CheckIfChar(IsNumberFirstChar)) {
std::unique_ptr<ExpressionNode> factor = ReadNumber();
if (type == "string")
factor->diagnostic = RaiseTypeError(
_("You entered a number, but a text was expected (in quotes)."),
expressionStartPosition);
else if (type != "number" && type != "number|string")
factor->diagnostic = RaiseTypeError(
_("You entered a number, but this type was expected:") + type,
expressionStartPosition);
return factor;
} else if (CheckIfChar(IsOpeningParenthesis)) {
SkipChar();
std::unique_ptr<ExpressionNode> factor = SubExpression(type, objectName);
std::unique_ptr<ExpressionNode> factor = SubExpression();
if (!CheckIfChar(IsClosingParenthesis)) {
factor->diagnostic =
@@ -247,29 +212,20 @@ class GD_CORE_API ExpressionParser2 {
SkipIfChar(IsClosingParenthesis);
return factor;
} else if (IsIdentifierAllowedChar()) {
// This is a place where the grammar differs according to the
// type being expected.
if (gd::ParameterMetadata::IsExpression("variable", type)) {
return Variable(type, objectName);
} else {
return Identifier(type);
}
return Identifier();
}
std::unique_ptr<ExpressionNode> factor = ReadUntilWhitespace(type);
factor->diagnostic = RaiseEmptyError(type, expressionStartPosition);
std::unique_ptr<ExpressionNode> factor = ReadUntilWhitespace();
return factor;
}
std::unique_ptr<SubExpressionNode> SubExpression(
const gd::String &type, const gd::String &objectName) {
std::unique_ptr<SubExpressionNode> SubExpression() {
size_t expressionStartPosition = GetCurrentPosition();
auto expression = Expression(type, objectName);
const gd::String &inferredType = expression->type;
auto expression = Expression();
auto subExpression =
gd::make_unique<SubExpressionNode>(inferredType, std::move(expression));
gd::make_unique<SubExpressionNode>(std::move(expression));
subExpression->location =
ExpressionParserLocation(expressionStartPosition, GetCurrentPosition());
@@ -277,7 +233,7 @@ class GD_CORE_API ExpressionParser2 {
};
std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
Identifier(const gd::String &type) {
Identifier() {
auto identifierAndLocation = ReadIdentifierName();
gd::String name = identifierAndLocation.name;
auto nameLocation = identifierAndLocation.location;
@@ -304,47 +260,28 @@ class GD_CORE_API ExpressionParser2 {
if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar();
return FreeFunction(type, name, nameLocation, openingParenthesisLocation);
return FreeFunction(name, nameLocation, openingParenthesisLocation);
} else if (CheckIfChar(IsDot)) {
ExpressionParserLocation dotLocation = SkipChar();
SkipAllWhitespaces();
return ObjectFunctionOrBehaviorFunction(
type, name, nameLocation, dotLocation);
} else {
auto identifier = gd::make_unique<IdentifierNode>(name, type);
if (type == "string") {
identifier->diagnostic =
RaiseTypeError(_("You must wrap your text inside double quotes "
"(example: \"Hello world\")."),
nameLocation.GetStartPosition());
} else if (type == "number") {
identifier->diagnostic = RaiseTypeError(
_("You must enter a number."), nameLocation.GetStartPosition());
} else if (type == "number|string") {
identifier->diagnostic = RaiseTypeError(
_("You must enter a number or a text, wrapped inside double quotes "
"(example: \"Hello world\")."),
nameLocation.GetStartPosition());
} else if (!gd::ParameterMetadata::IsObject(type)) {
identifier->diagnostic = RaiseTypeError(
_("You've entered a name, but this type was expected:") + type,
nameLocation.GetStartPosition());
}
name, nameLocation, dotLocation);
} else if (CheckIfChar(IsOpeningSquareBracket)) {
return Variable(name, nameLocation);
}
else {
auto identifier = gd::make_unique<IdentifierNode>(name);
identifier->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition());
identifier->identifierNameLocation = identifier->location;
return std::move(identifier);
}
}
std::unique_ptr<VariableNode> Variable(const gd::String &type,
const gd::String &objectName) {
auto identifierAndLocation = ReadIdentifierName();
const gd::String &name = identifierAndLocation.name;
const auto &nameLocation = identifierAndLocation.location;
auto variable = gd::make_unique<VariableNode>(type, name, objectName);
std::unique_ptr<VariableNode> Variable(const gd::String &name, gd::ExpressionParserLocation nameLocation) {
auto variable = gd::make_unique<VariableNode>(name);
variable->child = VariableAccessorOrVariableBracketAccessor();
variable->child->parent = variable.get();
variable->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition());
@@ -359,8 +296,8 @@ class GD_CORE_API ExpressionParser2 {
SkipAllWhitespaces();
if (CheckIfChar(IsOpeningSquareBracket)) {
SkipChar();
auto child = gd::make_unique<VariableBracketAccessorNode>(
Expression("number|string"));
auto child = gd::make_unique<VariableBracketAccessorNode>(Expression());
child->expression->parent = child.get();
if (!CheckIfChar(IsClosingSquareBracket)) {
child->diagnostic =
@@ -369,6 +306,7 @@ class GD_CORE_API ExpressionParser2 {
}
SkipIfChar(IsClosingSquareBracket);
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->location =
ExpressionParserLocation(childStartPosition, GetCurrentPosition());
@@ -381,6 +319,7 @@ class GD_CORE_API ExpressionParser2 {
auto child =
gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->nameLocation = identifierAndLocation.location;
child->dotLocation = dotLocation;
child->location =
@@ -389,40 +328,21 @@ class GD_CORE_API ExpressionParser2 {
return std::move(child);
}
return std::move(
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>());
return std::move(gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>());
}
std::unique_ptr<FunctionCallNode> FreeFunction(
const gd::String &type,
const gd::String &functionFullName,
const ExpressionParserLocation &identifierLocation,
const ExpressionParserLocation &openingParenthesisLocation) {
// TODO: error if trying to use function for type != "number" && != "string"
// + Test for it
const gd::ExpressionMetadata &metadata =
MetadataProvider::GetAnyExpressionMetadata(platform, functionFullName);
// In case we can't find a valid expression, ensure the node has the type
// that is requested by the parent, so we avoid putting "unknown" (which
// would be also correct, but less precise and would prevent completions to
// be shown to the user)
const gd::String returnType =
gd::MetadataProvider::IsBadExpressionMetadata(metadata) == true
? type
: metadata.GetReturnType();
auto parametersNode = Parameters(metadata.parameters);
auto function =
gd::make_unique<FunctionCallNode>(returnType,
std::move(parametersNode.parameters),
metadata,
functionFullName);
gd::make_unique<FunctionCallNode>(functionFullName);
auto parametersNode = Parameters(function.get());
function->parameters = std::move(parametersNode.parameters);
function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic) // TODO: reverse the order of diagnostic?
function->diagnostic = ValidateFunction(
type, *function, identifierLocation.GetStartPosition());
function->location = ExpressionParserLocation(
identifierLocation.GetStartPosition(), GetCurrentPosition());
@@ -434,16 +354,15 @@ class GD_CORE_API ExpressionParser2 {
return std::move(function);
}
std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode>
std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
ObjectFunctionOrBehaviorFunction(
const gd::String &type,
const gd::String &objectName,
const ExpressionParserLocation &objectNameLocation,
const ExpressionParserLocation &objectNameDotLocation) {
auto identifierAndLocation = ReadIdentifierName();
const gd::String &objectFunctionOrBehaviorName = identifierAndLocation.name;
const auto &objectFunctionOrBehaviorNameLocation =
identifierAndLocation.location;
const gd::String &parentIdentifier,
const ExpressionParserLocation &parentIdentifierLocation,
const ExpressionParserLocation &parentIdentifierDotLocation) {
auto childIdentifierAndLocation = ReadIdentifierName();
const gd::String &childIdentifierName = childIdentifierAndLocation.name;
const auto &childIdentifierNameLocation =
childIdentifierAndLocation.location;
SkipAllWhitespaces();
@@ -451,87 +370,68 @@ class GD_CORE_API ExpressionParser2 {
ExpressionParserLocation namespaceSeparatorLocation =
SkipNamespaceSeparator();
SkipAllWhitespaces();
return BehaviorFunction(type,
objectName,
objectFunctionOrBehaviorName,
objectNameLocation,
objectNameDotLocation,
objectFunctionOrBehaviorNameLocation,
return BehaviorFunction(parentIdentifier,
childIdentifierName,
parentIdentifierLocation,
parentIdentifierDotLocation,
childIdentifierNameLocation,
namespaceSeparatorLocation);
} else if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar();
gd::String objectType =
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName);
const gd::ExpressionMetadata &metadata =
MetadataProvider::GetObjectAnyExpressionMetadata(
platform, objectType, objectFunctionOrBehaviorName);
// In case we can't find a valid expression, ensure the node has the type
// that is requested by the parent, so we avoid putting "unknown" (which
// would be also correct, but less precise and would prevent completions
// to be shown to the user)
const gd::String returnType =
gd::MetadataProvider::IsBadExpressionMetadata(metadata) == true
? type
: metadata.GetReturnType();
auto parametersNode = Parameters(metadata.parameters, objectName);
auto function = gd::make_unique<FunctionCallNode>(
returnType,
objectName,
std::move(parametersNode.parameters),
metadata,
objectFunctionOrBehaviorName);
parentIdentifier,
childIdentifierName);
auto parametersNode = Parameters(function.get(), parentIdentifier);
function->parameters = std::move(parametersNode.parameters),
function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic) // TODO: reverse the order of diagnostic?
function->diagnostic = ValidateFunction(
type, *function, objectNameLocation.GetStartPosition());
// 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);
if (objectMetadata.IsUnsupportedBaseObjectCapability(
metadata.GetRequiredBaseObjectCapability())) {
function->diagnostic = RaiseTypeError(
_("This expression exists, but it can't be used on this object."),
objectNameLocation.GetStartPosition());
}
}
function->location = ExpressionParserLocation(
objectNameLocation.GetStartPosition(), GetCurrentPosition());
function->objectNameLocation = objectNameLocation;
function->objectNameDotLocation = objectNameDotLocation;
function->functionNameLocation = objectFunctionOrBehaviorNameLocation;
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
function->objectNameLocation = parentIdentifierLocation;
function->objectNameDotLocation = parentIdentifierDotLocation;
function->functionNameLocation = childIdentifierNameLocation;
function->openingParenthesisLocation = openingParenthesisLocation;
function->closingParenthesisLocation =
parametersNode.closingParenthesisLocation;
return std::move(function);
} else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) {
auto variable = gd::make_unique<VariableNode>(parentIdentifier);
auto child =
gd::make_unique<VariableAccessorNode>(childIdentifierName);
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->nameLocation = childIdentifierNameLocation;
child->dotLocation = parentIdentifierDotLocation;
child->location = ExpressionParserLocation(
parentIdentifierDotLocation.GetStartPosition(), GetCurrentPosition());
variable->child = std::move(child);
variable->child->parent = variable.get();
variable->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
variable->nameLocation = parentIdentifierLocation;
return std::move(variable);
}
auto node = gd::make_unique<ObjectFunctionNameNode>(
type, objectName, objectFunctionOrBehaviorName);
node->diagnostic = RaiseSyntaxError(
_("An opening parenthesis (for an object expression), or double colon "
"(::) was expected (for a behavior expression)."));
auto node = gd::make_unique<IdentifierNode>(
parentIdentifier, childIdentifierName);
if (!CheckIfChar(IsParameterSeparator) && !CheckIfChar(IsClosingParenthesis) && !IsEndReached()) {
node->diagnostic = RaiseSyntaxError(
_("An opening parenthesis (for an object expression), a double colon "
"(:: for a behavior expression), a dot or an opening bracket (for "
"a child variable) where expected."));
}
node->location = ExpressionParserLocation(
objectNameLocation.GetStartPosition(), GetCurrentPosition());
node->objectNameLocation = objectNameLocation;
node->objectNameDotLocation = objectNameDotLocation;
node->objectFunctionOrBehaviorNameLocation =
objectFunctionOrBehaviorNameLocation;
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
node->identifierNameLocation = parentIdentifierLocation;
node->identifierNameDotLocation = parentIdentifierDotLocation;
node->childIdentifierNameLocation = childIdentifierNameLocation;
return std::move(node);
}
std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode> BehaviorFunction(
const gd::String &type,
const gd::String &objectName,
const gd::String &behaviorName,
const ExpressionParserLocation &objectNameLocation,
@@ -547,35 +447,14 @@ class GD_CORE_API ExpressionParser2 {
if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar();
gd::String behaviorType = GetTypeOfBehavior(
globalObjectsContainer, objectsContainer, behaviorName);
const gd::ExpressionMetadata &metadata =
MetadataProvider::GetBehaviorAnyExpressionMetadata(
platform, behaviorType, functionName);
// In case we can't find a valid expression, ensure the node has the type
// that is requested by the parent, so we avoid putting "unknown" (which
// would be also correct, but less precise and would prevent completions
// to be shown to the user)
const gd::String returnType =
gd::MetadataProvider::IsBadExpressionMetadata(metadata) == true
? type
: metadata.GetReturnType();
auto parametersNode =
Parameters(metadata.parameters, objectName, behaviorName);
auto function = gd::make_unique<FunctionCallNode>(
returnType,
objectName,
behaviorName,
std::move(parametersNode.parameters),
metadata,
functionName);
auto parametersNode =
Parameters(function.get(), objectName, behaviorName);
function->parameters = std::move(parametersNode.parameters);
function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic) // TODO: reverse the order of diagnostic?
function->diagnostic = ValidateFunction(
type, *function, objectNameLocation.GetStartPosition());
function->location = ExpressionParserLocation(
objectNameLocation.GetStartPosition(), GetCurrentPosition());
@@ -591,7 +470,7 @@ class GD_CORE_API ExpressionParser2 {
return std::move(function);
} else {
auto node = gd::make_unique<ObjectFunctionNameNode>(
type, objectName, behaviorName, functionName);
objectName, behaviorName, functionName);
node->diagnostic = RaiseSyntaxError(
_("An opening parenthesis was expected here to call a function."));
@@ -615,7 +494,7 @@ class GD_CORE_API ExpressionParser2 {
};
ParametersNode Parameters(
std::vector<gd::ParameterMetadata> parameterMetadata,
FunctionCallNode *functionCallNode,
const gd::String &objectName = "",
const gd::String &behaviorName = "") {
std::vector<std::unique_ptr<ExpressionNode>> parameters;
@@ -626,77 +505,25 @@ class GD_CORE_API ExpressionParser2 {
size_t parameterIndex =
WrittenParametersFirstIndex(objectName, behaviorName);
bool previousCharacterIsParameterSeparator = false;
while (!IsEndReached()) {
SkipAllWhitespaces();
if (CheckIfChar(IsClosingParenthesis)) {
if (CheckIfChar(IsClosingParenthesis) && !previousCharacterIsParameterSeparator) {
auto closingParenthesisLocation = SkipChar();
return ParametersNode{
std::move(parameters), nullptr, closingParenthesisLocation};
} else {
if (parameterIndex < parameterMetadata.size()) {
const gd::String &type = parameterMetadata[parameterIndex].GetType();
if (parameterMetadata[parameterIndex].IsCodeOnly()) {
// Do nothing, code only parameters are not written in expressions.
} else if (gd::ParameterMetadata::IsExpression("number", type)) {
parameters.push_back(Expression("number"));
} else if (gd::ParameterMetadata::IsExpression("string", type)) {
parameters.push_back(Expression("string"));
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
parameters.push_back(Expression(
type, lastObjectName.empty() ? objectName : lastObjectName));
} else if (gd::ParameterMetadata::IsObject(type)) {
size_t parameterStartPosition = GetCurrentPosition();
std::unique_ptr<ExpressionNode> objectExpression = Expression(type);
// 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 (auto identifierNode =
dynamic_cast<IdentifierNode *>(objectExpression.get())) {
lastObjectName = identifierNode->identifierName;
} else {
objectExpression->diagnostic =
gd::make_unique<ExpressionParserError>(
"malformed_object_parameter",
_("An object name was expected but something else was "
"written. Enter just the name of the object for this "
"parameter."),
parameterStartPosition,
GetCurrentPosition());
}
parameters.push_back(std::move(objectExpression));
} else {
size_t parameterStartPosition = GetCurrentPosition();
parameters.push_back(Expression("unknown"));
parameters.back()->diagnostic =
gd::make_unique<ExpressionParserError>(
"unknown_parameter_type",
_("This function is improperly set up. Reach out to the "
"extension developer or a GDevelop maintainer to fix "
"this issue"),
parameterStartPosition,
GetCurrentPosition());
}
} else {
size_t parameterStartPosition = GetCurrentPosition();
parameters.push_back(Expression("unknown"));
parameters.back()
->diagnostic = gd::make_unique<ExpressionParserError>(
"extra_parameter",
_("This parameter was not expected by this expression. Remove it "
"or verify that you've entered the proper expression name."),
parameterStartPosition,
GetCurrentPosition());
}
SkipAllWhitespaces();
SkipIfChar(IsParameterSeparator);
parameterIndex++;
}
bool isEmptyParameter = CheckIfChar(IsParameterSeparator)
|| (CheckIfChar(IsClosingParenthesis) && previousCharacterIsParameterSeparator);
auto parameter = isEmptyParameter ? gd::make_unique<EmptyNode>() : Expression();
parameter->parent = functionCallNode;
parameters.push_back(std::move(parameter));
SkipAllWhitespaces();
previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator);
SkipIfChar(IsParameterSeparator);
parameterIndex++;
}
ExpressionParserLocation invalidClosingParenthesisLocation;
@@ -708,92 +535,32 @@ class GD_CORE_API ExpressionParser2 {
}
///@}
/** \name Validators
* Return a diagnostic if any error is found
*/
///@{
std::unique_ptr<ExpressionParserDiagnostic> ValidateFunction(
const gd::String &type,
const gd::FunctionCallNode &function,
size_t functionStartPosition);
std::unique_ptr<ExpressionParserDiagnostic> ValidateOperator(
const gd::String &type, gd::String::value_type operatorChar) {
if (type == "number") {
if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' ||
operatorChar == '*') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an operator that is not supported. Operator should be "
"either +, -, / or *."),
GetCurrentPosition());
} else if (type == "string") {
if (operatorChar == '+') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an operator that is not supported. Only + can be used "
"to concatenate texts."),
GetCurrentPosition());
} else if (gd::ParameterMetadata::IsObject(type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -, /, *) can't be used with an object name. Remove "
"the operator."),
GetCurrentPosition());
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -, /, *) can't be used in variable names. Remove "
"the operator from the variable name."),
GetCurrentPosition());
gd::String::value_type operatorChar) {
if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' ||
operatorChar == '*') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserDiagnostic>();
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an operator that is not supported. Operator should be "
"either +, -, / or *."),
GetCurrentPosition());
}
std::unique_ptr<ExpressionParserDiagnostic> ValidateUnaryOperator(
const gd::String &type,
gd::String::value_type operatorChar,
size_t position) {
if (type == "number") {
if (operatorChar == '+' || operatorChar == '-') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an \"unary\" operator that is not supported. Operator "
"should be "
"either + or -."),
position);
} else if (type == "string") {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an operator that is not supported. Only + can be used "
"to concatenate texts, and must be placed between two texts (or "
"expressions)."),
position);
} else if (gd::ParameterMetadata::IsObject(type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -) can't be used with an object name. Remove the "
"operator."),
position);
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -) can't be used in variable names. Remove "
"the operator from the variable name."),
position);
if (operatorChar == '+' || operatorChar == '-') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserDiagnostic>();
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an \"unary\" operator that is not supported. Operator "
"should be "
"either + or -."),
position);
}
///@}
@@ -981,7 +748,7 @@ class GD_CORE_API ExpressionParser2 {
std::unique_ptr<NumberNode> ReadNumber();
std::unique_ptr<EmptyNode> ReadUntilWhitespace(gd::String type) {
std::unique_ptr<EmptyNode> ReadUntilWhitespace() {
size_t startPosition = GetCurrentPosition();
gd::String text;
while (currentPosition < expression.size() &&
@@ -990,13 +757,13 @@ class GD_CORE_API ExpressionParser2 {
currentPosition++;
}
auto node = gd::make_unique<EmptyNode>(type, text);
auto node = gd::make_unique<EmptyNode>(text);
node->location =
ExpressionParserLocation(startPosition, GetCurrentPosition());
return node;
}
std::unique_ptr<EmptyNode> ReadUntilEnd(gd::String type) {
std::unique_ptr<EmptyNode> ReadUntilEnd() {
size_t startPosition = GetCurrentPosition();
gd::String text;
while (currentPosition < expression.size()) {
@@ -1004,7 +771,7 @@ class GD_CORE_API ExpressionParser2 {
currentPosition++;
}
auto node = gd::make_unique<EmptyNode>(type, text);
auto node = gd::make_unique<EmptyNode>(text);
node->location =
ExpressionParserLocation(startPosition, GetCurrentPosition());
return node;
@@ -1037,34 +804,11 @@ class GD_CORE_API ExpressionParser2 {
return std::move(gd::make_unique<ExpressionParserError>(
"type_error", message, beginningPosition, GetCurrentPosition()));
}
std::unique_ptr<ExpressionParserError> RaiseEmptyError(
const gd::String &type, size_t beginningPosition) {
gd::String message;
if (type == "number") {
message = _("You must enter a number or a valid expression call.");
} else if (type == "string") {
message = _(
"You must enter a text (between quotes) or a valid expression call.");
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
message = _("You must enter a variable name.");
} else if (gd::ParameterMetadata::IsObject(type)) {
message = _("You must enter a valid object name.");
} else {
message = _("You must enter a valid expression.");
}
return std::move(RaiseTypeError(message, beginningPosition));
}
///@}
gd::String expression;
std::size_t currentPosition;
const gd::Platform &platform;
const gd::ObjectsContainer &globalObjectsContainer;
const gd::ObjectsContainer &objectsContainer;
static gd::String NAMESPACE_SEPARATOR;
};

View File

@@ -17,6 +17,7 @@ class ObjectsContainer;
class Platform;
class ParameterMetadata;
class ExpressionMetadata;
struct FunctionCallNode;
} // namespace gd
namespace gd {
@@ -57,6 +58,10 @@ struct GD_CORE_API ExpressionParserDiagnostic {
* \brief An error that can be attached to a gd::ExpressionNode.
*/
struct GD_CORE_API ExpressionParserError : public ExpressionParserDiagnostic {
ExpressionParserError(const gd::String &type_,
const gd::String &message_,
const ExpressionParserLocation &location_)
: type(type_), message(message_), location(location_){};
ExpressionParserError(const gd::String &type_,
const gd::String &message_,
size_t position_)
@@ -86,7 +91,7 @@ struct GD_CORE_API ExpressionParserError : public ExpressionParserDiagnostic {
* an expression inherits from.
*/
struct GD_CORE_API ExpressionNode {
ExpressionNode(const gd::String &type_) : type(type_){};
ExpressionNode() : parent(nullptr) {};
virtual ~ExpressionNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker){};
@@ -97,17 +102,12 @@ struct GD_CORE_API ExpressionNode {
/// function can store the position of the
/// object name, the dot, the function
/// name, etc...
gd::String type; // Actual type of the node.
// "string", "number", type supported by
// gd::ParameterMetadata::IsObject, types supported by
// gd::ParameterMetadata::IsExpression or "unknown".
ExpressionNode *parent;
};
struct GD_CORE_API SubExpressionNode : public ExpressionNode {
SubExpressionNode(const gd::String &type_,
std::unique_ptr<ExpressionNode> expression_)
: ExpressionNode(type_), expression(std::move(expression_)){};
SubExpressionNode(std::unique_ptr<ExpressionNode> expression_)
: ExpressionNode(), expression(std::move(expression_)){};
virtual ~SubExpressionNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitSubExpressionNode(*this);
@@ -120,8 +120,8 @@ struct GD_CORE_API SubExpressionNode : public ExpressionNode {
* \brief An operator node. For example: "lhs + rhs".
*/
struct GD_CORE_API OperatorNode : public ExpressionNode {
OperatorNode(const gd::String &type_, gd::String::value_type op_)
: ExpressionNode(type_), op(op_){};
OperatorNode(gd::String::value_type op_)
: ExpressionNode(), op(op_){};
virtual ~OperatorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitOperatorNode(*this);
@@ -136,8 +136,8 @@ struct GD_CORE_API OperatorNode : public ExpressionNode {
* \brief A unary operator node. For example: "-2".
*/
struct GD_CORE_API UnaryOperatorNode : public ExpressionNode {
UnaryOperatorNode(const gd::String &type_, gd::String::value_type op_)
: ExpressionNode(type_), op(op_){};
UnaryOperatorNode(gd::String::value_type op_)
: ExpressionNode(), op(op_){};
virtual ~UnaryOperatorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitUnaryOperatorNode(*this);
@@ -153,7 +153,7 @@ struct GD_CORE_API UnaryOperatorNode : public ExpressionNode {
*/
struct GD_CORE_API NumberNode : public ExpressionNode {
NumberNode(const gd::String &number_)
: ExpressionNode("number"), number(number_){};
: ExpressionNode(), number(number_){};
virtual ~NumberNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitNumberNode(*this);
@@ -168,7 +168,7 @@ struct GD_CORE_API NumberNode : public ExpressionNode {
* Its `type` is always "string".
*/
struct GD_CORE_API TextNode : public ExpressionNode {
TextNode(const gd::String &text_) : ExpressionNode("string"), text(text_){};
TextNode(const gd::String &text_) : ExpressionNode(), text(text_){};
virtual ~TextNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitTextNode(*this);
@@ -177,32 +177,88 @@ struct GD_CORE_API TextNode : public ExpressionNode {
gd::String text;
};
struct GD_CORE_API IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode
: public ExpressionNode {
IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode()
: ExpressionNode(){};
};
/**
* \brief An identifier node, usually representing an object or a variable
* with an optional function name or child variable name respectively.
*
* The name of a function to call on an object or the behavior,
* for example: "MyObject.Function" or "MyObject.Physics".
*
* A variable, potentially with accessor to its child,
* for example: MyVariable or MyVariable.MyChild
*/
struct GD_CORE_API IdentifierNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
IdentifierNode(
const gd::String &identifierName_)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(),
identifierName(identifierName_),
childIdentifierName(""){};
IdentifierNode(
const gd::String &identifierName_,
const gd::String &childIdentifierName_)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(),
identifierName(identifierName_),
childIdentifierName(childIdentifierName_){};
virtual ~IdentifierNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitIdentifierNode(*this);
};
gd::String identifierName; ///< The object or variable name.
gd::String childIdentifierName; ///< The object function or variable child name.
ExpressionParserLocation
identifierNameLocation; ///< Location of the object or variable name.
ExpressionParserLocation
identifierNameDotLocation; ///< Location of the "." after the object or variable name.
ExpressionParserLocation childIdentifierNameLocation; ///< Location of object
/// function, behavior or
/// child variable name.
};
struct GD_CORE_API FunctionCallOrObjectFunctionNameOrEmptyNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
FunctionCallOrObjectFunctionNameOrEmptyNode()
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(){};
virtual ~FunctionCallOrObjectFunctionNameOrEmptyNode(){};
void Visit(ExpressionParser2NodeWorker &worker) override{};
};
struct GD_CORE_API VariableAccessorOrVariableBracketAccessorNode : public ExpressionNode {
VariableAccessorOrVariableBracketAccessorNode() : ExpressionNode(""){};
VariableAccessorOrVariableBracketAccessorNode() : ExpressionNode(){};
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> child;
};
/**
* \brief A variable, potentially with accessor to its children.
*
* Example: MyVariable or MyVariable.MyChildren
* \brief A variable with bracket accessor or at least 2 "dot" accessors.
*
* Example: MyVariable[MyChildren] or MyVariable.MyChildren.MyGranChildren.
*
* Other cases like "MyVariable" or "MyVariable.MyChildren" are IdentifierNode
* to allow handling ambiguities.
*
* \see gd::IdentifierNode
* \see gd::VariableAccessorNode
* \see gd::VariableBracketAccessorNode
*/
struct GD_CORE_API VariableNode : public ExpressionNode {
VariableNode(const gd::String &type_,
const gd::String &name_,
const gd::String &objectName_)
: ExpressionNode(type_), name(name_), objectName(objectName_){};
struct GD_CORE_API VariableNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
VariableNode(const gd::String &name_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(), name(name_){};
virtual ~VariableNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitVariableNode(*this);
};
gd::String name;
gd::String objectName;
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
child; // Can be nullptr if no accessor
@@ -216,7 +272,8 @@ struct GD_CORE_API VariableNode : public ExpressionNode {
*/
struct GD_CORE_API VariableAccessorNode
: public VariableAccessorOrVariableBracketAccessorNode {
VariableAccessorNode(const gd::String &name_) : name(name_){};
VariableAccessorNode(const gd::String &name_)
: VariableAccessorOrVariableBracketAccessorNode(), name(name_){};
virtual ~VariableAccessorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitVariableAccessorNode(*this);
@@ -234,7 +291,7 @@ struct GD_CORE_API VariableAccessorNode
struct GD_CORE_API VariableBracketAccessorNode
: public VariableAccessorOrVariableBracketAccessorNode {
VariableBracketAccessorNode(std::unique_ptr<ExpressionNode> expression_)
: expression(std::move(expression_)){};
: VariableAccessorOrVariableBracketAccessorNode(), expression(std::move(expression_)){};
virtual ~VariableBracketAccessorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitVariableBracketAccessorNode(*this);
@@ -243,55 +300,26 @@ struct GD_CORE_API VariableBracketAccessorNode
std::unique_ptr<ExpressionNode> expression;
};
struct GD_CORE_API IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode
: public ExpressionNode {
IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(
const gd::String &type)
: ExpressionNode(type){};
};
/**
* \brief An identifier node, usually representing an object or a function name.
*/
struct GD_CORE_API IdentifierNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
IdentifierNode(const gd::String &identifierName_, const gd::String &type_)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(type_),
identifierName(identifierName_){};
virtual ~IdentifierNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitIdentifierNode(*this);
};
gd::String identifierName;
};
struct GD_CORE_API FunctionCallOrObjectFunctionNameOrEmptyNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
FunctionCallOrObjectFunctionNameOrEmptyNode(const gd::String &type)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(type){};
virtual ~FunctionCallOrObjectFunctionNameOrEmptyNode(){};
void Visit(ExpressionParser2NodeWorker &worker) override{};
};
/**
* \brief The name of a function to call on an object or the behavior
* For example: "MyObject.Function" or "MyObject.Physics" or
* "MyObject.Physics::LinearVelocity".
* For example: "MyObject.Physics::LinearVelocity".
*
* Other cases like "MyObject.Function" or "MyObject.Physics" are IdentifierNode
* to allow handling ambiguities.
*
* \see gd::IdentifierNode
*/
struct GD_CORE_API ObjectFunctionNameNode
: public FunctionCallOrObjectFunctionNameOrEmptyNode {
ObjectFunctionNameNode(const gd::String &type_,
const gd::String &objectName_,
ObjectFunctionNameNode(const gd::String &objectName_,
const gd::String &objectFunctionOrBehaviorName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
objectName(objectName_),
objectFunctionOrBehaviorName(objectFunctionOrBehaviorName_) {}
ObjectFunctionNameNode(const gd::String &type_,
const gd::String &objectName_,
ObjectFunctionNameNode(const gd::String &objectName_,
const gd::String &behaviorName_,
const gd::String &behaviorFunctionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
objectName(objectName_),
objectFunctionOrBehaviorName(behaviorName_),
behaviorFunctionName(behaviorFunctionName_) {}
@@ -334,39 +362,24 @@ struct GD_CORE_API ObjectFunctionNameNode
*/
struct GD_CORE_API FunctionCallNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
/** \brief Construct a free function call node. */
FunctionCallNode(const gd::String &type_,
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
const ExpressionMetadata &expressionMetadata_,
const gd::String &functionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
parameters(std::move(parameters_)),
expressionMetadata(expressionMetadata_),
FunctionCallNode(const gd::String &functionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
functionName(functionName_){};
/** \brief Construct an object function call node. */
FunctionCallNode(const gd::String &type_,
const gd::String &objectName_,
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
const ExpressionMetadata &expressionMetadata_,
FunctionCallNode(const gd::String &objectName_,
const gd::String &functionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
objectName(objectName_),
parameters(std::move(parameters_)),
expressionMetadata(expressionMetadata_),
functionName(functionName_){};
/** \brief Construct a behavior function call node. */
FunctionCallNode(const gd::String &type_,
const gd::String &objectName_,
FunctionCallNode(const gd::String &objectName_,
const gd::String &behaviorName_,
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
const ExpressionMetadata &expressionMetadata_,
const gd::String &functionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
: FunctionCallOrObjectFunctionNameOrEmptyNode(),
objectName(objectName_),
behaviorName(behaviorName_),
parameters(std::move(parameters_)),
expressionMetadata(expressionMetadata_),
functionName(functionName_){};
virtual ~FunctionCallNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
@@ -376,7 +389,6 @@ struct GD_CORE_API FunctionCallNode : public FunctionCallOrObjectFunctionNameOrE
gd::String objectName;
gd::String behaviorName;
std::vector<std::unique_ptr<ExpressionNode>> parameters;
const ExpressionMetadata &expressionMetadata;
gd::String functionName;
ExpressionParserLocation
@@ -401,8 +413,8 @@ struct GD_CORE_API FunctionCallNode : public FunctionCallOrObjectFunctionNameOrE
* encountered and any other node could not make sense.
*/
struct GD_CORE_API EmptyNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
EmptyNode(const gd::String &type_, const gd::String &text_ = "")
: FunctionCallOrObjectFunctionNameOrEmptyNode(type_), text(text_){};
EmptyNode(const gd::String &text_ = "")
: FunctionCallOrObjectFunctionNameOrEmptyNode(), text(text_){};
virtual ~EmptyNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitEmptyNode(*this);

View File

@@ -91,6 +91,9 @@ class GD_CORE_API ExpressionParser2NodePrinter
}
void OnVisitIdentifierNode(IdentifierNode& node) override {
output += node.identifierName;
if (!node.childIdentifierName.empty()) {
output += "." + node.childIdentifierName;
}
}
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
if (!node.behaviorFunctionName.empty()) {

View File

@@ -4,6 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Events/Serialization.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
@@ -183,8 +184,8 @@ void EventsListSerialization::UpdateInstructionsFromGD2x(
for (std::size_t j = 0;
j < parameters.size() && j < metadata.parameters.size();
++j) {
if (metadata.parameters[j].type == "relationalOperator" ||
metadata.parameters[j].type == "operator") {
if (metadata.parameters[j].GetType() == "relationalOperator" ||
metadata.parameters[j].GetType() == "operator") {
if (j == parameters.size() - 1) {
std::cout << "ERROR: No more parameters after a [relational]operator "
"when trying to update an instruction from GD2.x";
@@ -218,8 +219,8 @@ void EventsListSerialization::UnserializeEventsFrom(
event = std::make_shared<EmptyEvent>();
}
event->SetDisabled(eventElem.GetBoolAttribute("disabled"));
event->SetFolded(eventElem.GetBoolAttribute("folded"));
event->SetDisabled(eventElem.GetBoolAttribute("disabled", false));
event->SetFolded(eventElem.GetBoolAttribute("folded", false));
list.InsertEvent(event, list.GetEventsCount());
}
@@ -232,8 +233,9 @@ void EventsListSerialization::SerializeEventsTo(const EventsList& list,
const gd::BaseEvent& event = list.GetEvent(j);
SerializerElement& eventElem = events.AddChild("event");
eventElem.SetAttribute("disabled", event.IsDisabled());
eventElem.SetAttribute("folded", event.IsFolded());
if (event.IsDisabled())
eventElem.SetAttribute("disabled", event.IsDisabled());
if (event.IsFolded()) eventElem.SetAttribute("folded", event.IsFolded());
eventElem.AddChild("type").SetValue(event.GetType());
event.SerializeTo(eventElem);
@@ -267,6 +269,9 @@ void gd::EventsListSerialization::UnserializeInstructionsFrom(
instrElement.GetChild("type", 0, "Type")
.GetBoolAttribute("inverted", false, "Contraire"));
instruction.SetAwaited(
instrElement.GetChild("type", 0, "Type").GetBoolAttribute("await"));
// Read parameters
vector<gd::Expression> parameters;
@@ -340,9 +345,12 @@ void gd::EventsListSerialization::SerializeInstructionsTo(
instructions.ConsiderAsArrayOf("instruction");
for (std::size_t k = 0; k < list.size(); k++) {
SerializerElement& instruction = instructions.AddChild("instruction");
instruction.AddChild("type")
.SetAttribute("value", list[k].GetType())
.SetAttribute("inverted", list[k].IsInverted());
instruction.AddChild("type").SetAttribute("value", list[k].GetType());
if (list[k].IsInverted())
instruction.GetChild("type").SetAttribute("inverted", true);
if (list[k].IsAwaited())
instruction.GetChild("type").SetAttribute("await", true);
// Parameters
SerializerElement& parameters = instruction.AddChild("parameters");
@@ -352,9 +360,10 @@ void gd::EventsListSerialization::SerializeInstructionsTo(
.SetValue(list[k].GetParameter(l).GetPlainString());
// Sub instructions
SerializerElement& subInstructions =
instruction.AddChild("subInstructions");
SerializeInstructionsTo(list[k].GetSubInstructions(), subInstructions);
if (!list[k].GetSubInstructions().empty()) {
SerializeInstructionsTo(list[k].GetSubInstructions(),
instruction.AddChild("subInstructions"));
}
}
}

View File

@@ -81,7 +81,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.AddExpression(
"GetArgumentAsNumber",
_("Get function parameter value"),
_("Get function parameter (also called \"argument\") value"),
_("Get function parameter (also called \"argument\") value."),
"",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name");
@@ -90,10 +90,36 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.AddStrExpression(
"GetArgumentAsString",
_("Get function parameter text"),
_("Get function parameter (also called \"argument\") text "),
_("Get function parameter (also called \"argument\") text."),
"",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name");
extension
.AddCondition(
"CompareArgumentAsNumber",
_("Compare function parameter value"),
_("Compare function parameter (also called \"argument\") value."),
_("Parameter _PARAM0_"),
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
extension
.AddCondition(
"CompareArgumentAsString",
_("Compare function parameter text"),
_("Compare function parameter (also called \"argument\") text."),
_("Parameter _PARAM0_"),
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions());
}
} // namespace gd

View File

@@ -42,6 +42,7 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsTimeExtension(gd::PlatformExtension& extension);
static void ImplementsVariablesExtension(gd::PlatformExtension& extension);
static void ImplementsWindowExtension(gd::PlatformExtension& extension);
static void ImplementsAsyncExtension(gd::PlatformExtension& extension);
};
} // namespace gd

View File

@@ -0,0 +1,32 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "AllBuiltinExtensions.h"
#include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
gd::PlatformExtension &extension) {
extension
.SetExtensionInformation(
"BuiltinAsync",
_("Async functions"),
_("Functions that defer the execution of the events after it."),
"Arthur Pacaud (arthuro555)",
"Open source (MIT License)")
.SetCategory("Advanced");
extension.AddEvent("Async",
_("Async event"),
_("Internal event for asynchronous actions"),
"",
"res/eventaddicon.png",
std::make_shared<gd::AsyncEvent>());
}
} // namespace gd

View File

@@ -14,14 +14,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
extension
.SetExtensionInformation(
"BuiltinAudio",
_("Sounds and musics"),
_("Sounds and music"),
_("GDevelop provides several conditions and actions to play audio "
"files. They can be either long musics or short sound effects."),
"files. They can be either long music or short sound effects."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/audio")
.SetCategory("Audio");
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds and musics"))
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds and music"))
.SetIcon("res/actions/music24.png");
extension
@@ -73,9 +73,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
extension
.AddAction("RePlaySoundCanal",
_("Play the sound of a channel"),
_("Play the sound of the channel."),
_("Play the sound of channel _PARAM1_"),
_("Resume playing a sound on a channel"),
_("Resume playing a sound on a channel that was paused."),
_("Resume the sound of channel _PARAM1_"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
@@ -132,9 +132,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
extension
.AddAction("RePlayMusicCanal",
_("Play the music of a channel"),
_("Play the music of the channel."),
_("Play the music of channel _PARAM1_"),
_("Resume playing a music on a channel"),
_("Resume playing a music on a channel that was paused."),
_("Resume the music of channel _PARAM1_"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
@@ -146,69 +146,83 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddAction("ModVolumeSoundCanal",
_("Volume of the sound on a channel"),
_("This action modifies the volume of the sound on the "
"specified channel. The volume is between 0 and 100."),
"specified channel."),
_("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"),
"res/actions/sonVolume24.png",
"res/actions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced();
extension
.AddAction("ModVolumeMusicCanal",
_("Volume of the music on a channel"),
_("This action modifies the volume of the music on the "
"specified channel. The volume is between 0 and 100."),
"specified channel."),
_("the volume of the music on channel _PARAM1_"),
_("Music on channels"),
"res/actions/musicVolume24.png",
"res/actions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced();
extension
.AddAction("ModGlobalVolume",
_("Game global volume"),
_("This action modifies the global volume of the game. The "
"volume is between 0 and 100."),
_("This action modifies the global volume of the game."),
_("the global sound level"),
"",
"res/actions/volume24.png",
"res/actions/volume.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsSimple();
extension
.AddAction("ModPitchSoundChannel",
_("Pitch of the sound of a channel"),
_("This action modifies the pitch (speed) of the sound on a "
"channel.\n1 is the default pitch."),
"channel."),
_("the pitch of the sound on channel _PARAM1_"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced();
extension
.AddAction("ModPitchMusicChannel",
_("Pitch of the music on a channel"),
_("This action modifies the pitch of the music on the "
"specified channel. 1 is the default pitch"),
"specified channel."),
_("the pitch of the music on channel _PARAM1_"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced();
extension
@@ -222,7 +236,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced();
extension
@@ -236,7 +253,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced();
extension
@@ -343,6 +363,34 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsComplex();
extension
.AddAction(
"FadeSoundVolume",
_("Fade the volume of a sound played on a channel."),
_("Fade the volume of a sound played on a channel to the specified volume within the specified duration."),
_("Fade the sound on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddAction(
"FadeMusicVolume",
_("Fade the volume of a music played on a channel."),
_("Fade the volume of a music played on a channel to the specified volume within the specified duration."),
_("Fade the music on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddCondition("MusicPlaying",
@@ -420,15 +468,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddCondition(
"SoundCanalVolume",
_("Volume of the sound on a channel"),
_("Test the volume of the sound on the specified channel. The volume "
"is between 0 and 100."),
_("Test the volume of the sound on the specified channel."),
_("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"),
"res/conditions/sonVolume24.png",
"res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced();
extension
@@ -443,7 +493,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced();
extension
@@ -456,7 +509,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/volume24.png",
"res/conditions/volume.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")));
extension
.AddCondition(
@@ -470,22 +526,27 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced();
extension
.AddCondition(
"MusicChannelPitch",
_("Pitch of the music on a channel"),
_("Test the pitch (speed) of the music on a specified channel. 1 is "
"the default pitch."),
_("Test the pitch (speed) of the music on a specified channel."),
_("the pitch of the music on channel _PARAM1_"),
_("Music on channels"),
"res/conditions/musicVolume24.png",
"res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced();
extension
@@ -499,7 +560,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced();
extension
@@ -513,7 +577,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced();
extension

View File

@@ -28,7 +28,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
extension.AddInstructionOrExpressionGroupMetadata(_("Movement using forces"))
.SetIcon("res/actions/force24.png");
gd::ObjectMetadata& obj = extension.AddObject<gd::Object>(
gd::ObjectMetadata& obj = extension.AddObject<gd::ObjectConfiguration>(
"", _("Base object"), _("Base object"), "res/objeticon24.png");
obj.AddCondition("PosX",
@@ -36,11 +36,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Compare the X position of the object."),
_("the X position"),
_("Position"),
"res/conditions/position24.png",
"res/conditions/position.png")
"res/conditions/position24_black.png",
"res/conditions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddAction("MettreX",
@@ -48,11 +49,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the X position of an object."),
_("the X position"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddCondition("PosY",
@@ -60,11 +62,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Compare the Y position of an object."),
_("the Y position"),
_("Position"),
"res/conditions/position24.png",
"res/conditions/position.png")
"res/conditions/position24_black.png",
"res/conditions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddAction("MettreY",
@@ -72,11 +75,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the Y position of an object."),
_("the Y position"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddAction("MettreXY",
@@ -85,8 +89,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Change the position of _PARAM0_: _PARAM1_ _PARAM2_ (x "
"axis), _PARAM3_ _PARAM4_ (y axis)"),
_("Position"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("operator", _("Modification's sign"), "number")
@@ -102,8 +106,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"_PARAM2_ (x "
"axis), _PARAM3_ _PARAM4_ (y axis)"),
_("Position/Center"),
"res/actions/position24.png",
"res/actions/position.png")
"res/actions/position24_black.png",
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("operator", _("Modification's sign"), "number")
.AddParameter("expression", _("X position"))
@@ -118,9 +122,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the X position of the center of rotation"),
_("the X position of the center"),
_("Position/Center"),
"res/actions/position24.png")
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndConditionAndAction(
"number",
@@ -129,9 +133,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the Y position of the center of rotation"),
_("the Y position of the center"),
_("Position/Center"),
"res/actions/position24.png")
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxLeft",
@@ -140,9 +144,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) left position"),
_("the bounding box left position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-left.svg")
"res/conditions/bounding-box-left_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition(
"number",
@@ -151,9 +155,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("the bounding box (the area encapsulating the object) top position"),
_("the bounding box top position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-top.svg")
"res/conditions/bounding-box-top_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxRight",
@@ -162,9 +166,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) right position"),
_("the bounding box right position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-right.svg")
"res/conditions/bounding-box-right_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxBottom",
@@ -173,9 +177,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) bottom position"),
_("the bounding box bottom position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-bottom.svg")
"res/conditions/bounding-box-bottom_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxCenterX",
@@ -184,9 +188,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) center X position"),
_("the bounding box center X position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-center.svg")
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxCenterY",
@@ -195,9 +199,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"the object) center Y position"),
_("the bounding box center Y position"),
_("Position/Bounding Box"),
"res/conditions/bounding-box-center.svg")
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddAction("MettreAutourPos",
_("Put around a position"),
@@ -219,14 +223,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddAction("SetAngle",
_("Angle"),
_("Change the angle of rotation of an object."),
_("Change the angle of rotation of an object (in degrees)."),
_("the angle"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/direction24_black.png",
"res/actions/direction_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Angle (in degrees)")));
obj.AddAction("Rotate",
_("Rotate"),
@@ -234,8 +241,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"counterclockwise otherwise."),
_("Rotate _PARAM0_ at speed _PARAM1_ deg/second"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angular speed (in degrees per second)"))
@@ -248,8 +255,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Rotate an object towards an angle with the specified speed."),
_("Rotate _PARAM0_ towards _PARAM1_ at speed _PARAM2_ deg/second"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle to rotate towards (in degrees)"))
@@ -264,8 +271,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Rotate _PARAM0_ towards _PARAM1_;_PARAM2_ at speed "
"_PARAM3_ deg/second"),
_("Angle"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("X position"))
@@ -289,7 +296,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Speed on X axis (in pixels per second)"))
.AddParameter("expression", _("Speed on Y axis (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"));
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0");
obj.AddAction("AddForceAL",
_("Add a force (angle)"),
@@ -305,7 +313,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
obj.AddAction(
@@ -323,7 +332,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
obj.AddAction(
@@ -379,7 +389,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/planicon.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions());
obj.AddAction("ChangeLayer",
_("Layer"),
@@ -390,7 +401,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/layer.png")
.AddParameter("object", _("Object"))
.AddParameter("layer", _("Move it to this layer (base layer if empty)"))
.AddParameter("layer", _("Move it to this layer"))
.SetDefaultValue("\"\"")
.MarkAsAdvanced();
@@ -404,7 +415,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions());
obj.AddAction("ModVarObjetTxt",
_("Text of an object variable"),
@@ -416,7 +428,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("string");
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions());
obj.AddAction("SetObjectVariableAsBoolean",
_("Boolean value of an object variable"),
@@ -509,11 +522,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Compare the angle of the specified object."),
_("the angle (in degrees)"),
_("Angle"),
"res/conditions/direction24.png",
"res/conditions/direction.png")
"res/conditions/direction24_black.png",
"res/conditions/direction_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Angle to compare to (in degrees)")))
.MarkAsAdvanced();
obj.AddCondition("Plan",
@@ -525,7 +541,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/planicon.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("Layer",
@@ -582,7 +599,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/vitesse.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("AngleOfDisplacement",
@@ -610,7 +628,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions());
obj.AddCondition("VarObjetTxt",
_("Text of an object variable"),
@@ -622,7 +641,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters("string");
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions());
obj.AddCondition("ObjectVariableAsBoolean",
_("Boolean value of an object variable"),
@@ -756,7 +776,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Target Object"))
.AddParameter("expression", _("Speed (in pixels per second)"))
.AddParameter("forceMultiplier", _("Force multiplier"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
obj.AddAction(
@@ -776,7 +797,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectPtr", _("Rotate around this object"))
.AddParameter("expression", _("Speed (in degrees per second)"))
.AddParameter("expression", _("Distance (in pixels)"))
.AddParameter("forceMultiplier", _("Force multiplier"))
.AddParameter("forceMultiplier", _("Force multiplier"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
obj.AddAction("MettreAutour",
@@ -881,7 +903,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timer24.png",
"res/conditions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("expression", _("Time in seconds"))
.SetHidden();
@@ -895,7 +917,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timer24.png",
"res/conditions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.AddParameter("relationalOperator", _("Sign of the test"), "time")
.AddParameter("expression", _("Time in seconds"))
.SetManipulatedType("number");
@@ -908,7 +930,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/timerPaused24.png",
"res/conditions/timerPaused.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddAction(
@@ -921,7 +943,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddAction("PauseObjectTimer",
_("Pause an object timer"),
@@ -931,7 +953,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/pauseTimer24.png",
"res/actions/pauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddAction("UnPauseObjectTimer",
@@ -942,7 +964,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/unPauseTimer24.png",
"res/actions/unPauseTimer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddAction("RemoveObjectTimer",
@@ -953,28 +975,28 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "objectTimer")
.MarkAsAdvanced();
obj.AddExpression("X",
_("X position"),
_("X position of the object"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Y",
_("Y position"),
_("Y position of the object"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Angle",
_("Angle"),
_("Current angle, in degrees, of the object"),
_("Angle"),
"res/actions/direction.png")
"res/actions/direction_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("ForceX",
@@ -993,7 +1015,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddExpression("ForceAngle",
_("Angle of the sum of forces"),
_("Angle of the sum of forces"),
_("Angle of the sum of forces (in degrees)"),
_("Movement using forces"),
"res/actions/force.png")
.AddParameter("object", _("Object"));
@@ -1017,14 +1039,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Width"),
_("Width of the object"),
_("Size"),
"res/actions/scaleWidth.png")
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Largeur",
_("Width"),
_("Width of the object"),
_("Size"),
"res/actions/scaleWidth.png")
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"))
.SetHidden();
@@ -1032,14 +1054,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Height"),
_("Height of the object"),
_("Size"),
"res/actions/scaleHeight.png")
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"));
obj.AddExpression("Hauteur",
_("Height"),
_("Height of the object"),
_("Size"),
"res/actions/scaleHeight.png")
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"))
.SetHidden();
@@ -1093,7 +1115,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("expression", _("Target Y position"));
obj.AddExpression("Variable",
_("Object variable"),
_("Value of an object variable"),
_("Value of an object variable"),
_("Variables"),
"res/actions/var.png")
@@ -1109,7 +1131,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"));
obj.AddStrExpression("VariableString",
_("Object variable"),
_("Text of an object variable"),
_("Text of an object variable"),
_("Variables"),
"res/actions/var.png")
@@ -1122,14 +1144,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Object timers"),
"res/actions/time.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "objectTimer");
obj.AddExpression("AngleToObject",
_("Angle between two objects"),
_("Compute the angle between two objects. If you need the "
"angle to an arbitrary position, use AngleToPosition."),
_("Compute the angle between two objects (in degrees). "
"If you need the angle to an arbitrary position, "
"use AngleToPosition."),
_("Angle"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Object"));
@@ -1140,7 +1163,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"getting the cartesian coordinates of a 2D vector, using "
"its polar coordinates."),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance"));
@@ -1152,7 +1175,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"getting the cartesian coordinates of a 2D vector, using "
"its polar coordinates."),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance"));
@@ -1160,10 +1183,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddExpression("AngleToPosition",
_("Angle between an object and a position"),
_("Compute the angle between the object center and a "
"\"target\" position. If you need the angle between two "
"objects, use AngleToObject."),
"\"target\" position (in degrees). If you need the angle "
"between two objects, use AngleToObject."),
_("Angle"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Target X position"))
.AddParameter("expression", _("Target Y position"));
@@ -1252,7 +1275,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListWithoutPicking", _("Object to create"))
.AddParameter("objectListOrEmptyIfJustDeclared", _("Object to create"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
@@ -1270,7 +1293,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListWithoutPicking", _("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"))
@@ -1417,7 +1440,38 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/nbObjet24.png",
"res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsSimple()
.SetHidden();
extension
.AddExpressionAndCondition(
"number",
"SceneInstancesCount",
_("Number of object instances on the scene"),
_("the number of instances of the specified objects living on the "
"scene"),
_("the number of _PARAM1_ living on the scene"),
_("Objects"),
"res/conditions/nbObjet24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListOrEmptyWithoutPicking", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsSimple();
extension
.AddExpressionAndCondition(
"number",
"PickedInstancesCount",
_("Number of object instances currently picked"),
_("the number of instances picked by the previous conditions (or "
"actions)"),
_("the number of _PARAM0_ currently picked"),
_("Objects"),
"res/conditions/nbObjet24.png")
.AddParameter("objectListOrEmptyWithoutPicking", _("Object"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsSimple();
extension
@@ -1497,7 +1551,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"object will become the only one taken into account.\nIf "
"the condition is inverted, the object to be intersected "
"will be the farthest one within the ray radius."),
_("Cast a ray from from _PARAM1_;_PARAM2_ to _PARAM3_;_PARAM4_ "
_("Cast a ray from _PARAM1_;_PARAM2_ to _PARAM3_;_PARAM4_ "
"against _PARAM0_, and save the "
"result in _PARAM5_, _PARAM6_"),
"",
@@ -1526,13 +1580,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"currently picked in the event"),
"",
"res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"));
.AddParameter("objectList", _("Object"))
.SetHidden(); // Deprecated
obj.AddStrExpression("ObjectName",
_("Object name"),
_("Return the name of the object"),
"",
"res/conditions/text.png")
"res/conditions/text_black.png")
.AddParameter("object", _("Object"));
obj.AddStrExpression("Layer",

View File

@@ -22,6 +22,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"object or a position.",
"Florian Rival",
"Open source (MIT License)")
.SetCategory("Camera")
.SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras");
extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras"))
.SetIcon("res/conditions/camera24.png");
@@ -29,46 +30,66 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension
.AddExpressionAndConditionAndAction(
"number",
"CameraX",
"CameraCenterX",
_("Camera center X position"),
_("the X position of the center of a camera"),
_("the X position of camera _PARAM4_ (layer: _PARAM3_)"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
// Compatibility with GD <= 5.0.135
extension.AddDuplicatedCondition("CameraX", "CameraCenterX")
.SetHidden(); // Deprecated
extension.AddDuplicatedExpression("CameraX", "CameraCenterX")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("SetCameraX", "SetCameraCenterX")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("CameraX", "SetCameraX")
.SetHidden(); // Deprecated
extension.AddDuplicatedExpression("VueX", "CameraX")
.SetHidden(); // Deprecated
// end of compatibility code
extension
.AddExpressionAndConditionAndAction(
"number",
"CameraY",
"CameraCenterY",
_("Camera center Y position"),
_("the Y position of the center of a camera"),
_("the Y position of camera _PARAM4_ (layer: _PARAM3_)"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
// Compatibility with GD <= 5.0.135
extension.AddDuplicatedCondition("CameraY", "CameraCenterY")
.SetHidden(); // Deprecated
extension.AddDuplicatedExpression("CameraY", "CameraCenterY")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("SetCameraY", "SetCameraCenterY")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("CameraY", "SetCameraY")
.SetHidden(); // Deprecated
extension.AddDuplicatedExpression("VueY", "CameraY")
.SetHidden(); // Deprecated
// end of compatibility code
extension
.AddExpressionAndCondition(
@@ -80,10 +101,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"))
.UseStandardParameters("number")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -96,10 +117,78 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"))
.UseStandardParameters("number")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderLeft",
_("Camera left border position"),
_("the position of the left border of a camera"),
_("the position of the left border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderRight",
_("Camera right border position"),
_("the position of the right border of a camera"),
_("the position of the right border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderTop",
_("Camera top border position"),
_("the position of the top border of a camera"),
_("the position of the top border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderBottom",
_("Camera bottom border position"),
_("the position of the bottom border of a camera"),
_("the position of the bottom border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -107,12 +196,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"number",
"CameraAngle",
_("Angle of a camera of a layer"),
_("the angle of rotation of a camera"),
_("the angle of rotation of a camera (in degrees)"),
_("the angle of camera (layer: _PARAM3_, camera: _PARAM4_)"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -133,7 +222,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer"))
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Width"), "", true)
.AddParameter("expression", _("Height"), "", true)
@@ -168,7 +257,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer"))
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"))
.MarkAsComplex();
@@ -184,7 +273,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer"))
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"))
.AddParameter("expression", _("Width"))
@@ -202,7 +291,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer"))
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"))
.AddParameter(
@@ -221,7 +310,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension
.AddAction("ZoomCamera",
_("Change camera zoom"),
_("Camera zoom"),
_("Change camera zoom."),
_("Change camera zoom to _PARAM1_ (layer: _PARAM2_, camera: "
"_PARAM3_)"),
@@ -325,7 +414,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/layer24.png",
"res/actions/layer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer"))
.SetDefaultValue("\"\"")
.MarkAsAdvanced();
@@ -338,7 +427,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/layer24.png",
"res/actions/layer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer"))
.SetDefaultValue("\"\"")
.MarkAsAdvanced();
@@ -351,7 +440,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/layer24.png",
"res/conditions/layer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"))
.AddParameter("layer", _("Layer"))
.SetDefaultValue("\"\"")
.MarkAsAdvanced();
@@ -453,7 +542,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Time scale (1 by default)")))
.MarkAsAdvanced();
extension
@@ -483,12 +575,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddAction("SetLayerDefaultZOrder",
_("Change layer default Z order"),
_("Layer default Z order"),
_("Change the default Z order set to objects when they are "
"created on a layer."),
_("Set the default Z order of objects created on _PARAM1_ to "

View File

@@ -21,14 +21,14 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/common-conversions");
extension.AddInstructionOrExpressionGroupMetadata(_("Conversion"))
.SetIcon("res/conditions/toujours24.png");
.SetIcon("res/conditions/toujours24_black.png");
extension
.AddExpression("ToNumber",
_("Text > Number"),
_("Convert the text to a number"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text to convert to a number"));
extension
@@ -36,7 +36,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Number > Text"),
_("Convert the result of the expression to text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Expression to be converted to text"));
extension
@@ -45,7 +45,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert the result of the expression to text, "
"without using the scientific notation"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Expression to be converted to text"));
extension
@@ -54,7 +54,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Degrees > Radians"),
_("Converts the angle, expressed in degrees, into radians"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Angle, in degrees"));
extension
@@ -63,7 +63,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Radians > Degrees"),
_("Converts the angle, expressed in radians, into degrees"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Angle, in radians"));
extension
@@ -71,7 +71,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert scene variable to JSON"),
_("Convert a scene variable to JSON"),
_("JSON"),
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("scenevar", _("Scene variable to be stringified"));
extension
@@ -79,7 +79,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert global variable to JSON"),
_("Convert a global variable to JSON"),
_("JSON"),
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("globalvar", _("The global variable to be stringified"));
extension
@@ -87,7 +87,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Convert object variable to JSON"),
_("Convert an object variable to JSON"),
_("JSON"),
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("objectPtr", _("The object with the variable"))
.AddParameter("objectvar", _("The object variable to be stringified"));
@@ -96,7 +96,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
"JSONToVariableStructure",
_("Convert JSON to a scene variable"),
_("Parse a JSON object and store it into a scene variable"),
_("Parse JSON string _PARAM0_ and store it into variable _PARAM1_"),
_("Convert JSON string _PARAM0_ and store it into variable _PARAM1_"),
"",
"res/actions/net24.png",
"res/actions/net.png")
@@ -108,7 +108,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
.AddAction("JSONToGlobalVariableStructure",
_("Convert JSON to global variable"),
_("Parse a JSON object and store it into a global variable"),
_("Parse JSON string _PARAM0_ and store it into global "
_("Convert JSON string _PARAM0_ and store it into global "
"variable _PARAM1_"),
"",
"res/actions/net24.png",

View File

@@ -33,7 +33,7 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
.SetExtensionHelpPath("/all-features/advanced-conditions");
extension
.AddInstructionOrExpressionGroupMetadata(_("Events and control flow"))
.SetIcon("res/conditions/toujours24.png");
.SetIcon("res/conditions/toujours24_black.png");
extension
.AddCondition("Always",
@@ -42,8 +42,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
"the condition is inverted)."),
_("Always"),
"",
"res/conditions/toujours24.png",
"res/conditions/toujours.png")
"res/conditions/toujours24_black.png",
"res/conditions/toujours_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced();
@@ -61,8 +61,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Check if one of the sub conditions is true"),
_("If one of these conditions is true:"),
"",
"res/conditions/or24.png",
"res/conditions/or.png")
"res/conditions/or24_black.png",
"res/conditions/or_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
@@ -72,8 +72,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Check if all sub conditions are true"),
_("If all of these conditions are true:"),
"",
"res/conditions/and24.png",
"res/conditions/and.png")
"res/conditions/and24_black.png",
"res/conditions/and_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
@@ -84,8 +84,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Return the contrary of the result of the sub conditions"),
_("Invert the logical result of these conditions:"),
"",
"res/conditions/not24.png",
"res/conditions/not.png")
"res/conditions/not24_black.png",
"res/conditions/not_black.png")
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
@@ -104,8 +104,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Compare the two numbers."),
_("_PARAM0_ _PARAM1_ _PARAM2_"),
"",
"res/conditions/egal24.png",
"res/conditions/egal.png")
"res/conditions/egal24_black.png",
"res/conditions/egal_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("expression", _("First expression"))
.AddParameter("relationalOperator", _("Sign of the test"), "number")
@@ -125,8 +125,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Compare the two strings."),
_("_PARAM0_ _PARAM1_ _PARAM2_"),
"",
"res/conditions/egal24.png",
"res/conditions/egal.png")
"res/conditions/egal24_black.png",
"res/conditions/egal_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("string", _("First string expression"))
.AddParameter("relationalOperator", _("Sign of the test"), "string")

View File

@@ -21,7 +21,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/storage")
.SetCategory("Device");
.SetCategory("Advanced");
extension.AddInstructionOrExpressionGroupMetadata(_("Storage"))
.SetIcon("res/conditions/fichier24.png");

View File

@@ -96,13 +96,13 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
_("Difference between two angles"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("First angle"))
.AddParameter("expression", _("Second angle"));
.AddParameter("expression", _("First angle, in degrees"))
.AddParameter("expression", _("Second angle, in degrees"));
extension
.AddExpression("AngleBetweenPositions",
_("Angle between two positions"),
_("Compute the angle between two positions."),
_("Compute the angle between two positions (in degrees)."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("First point X position"))
@@ -159,7 +159,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension
.AddExpression("acos",
_("Arccosine"),
_("Arccosine"),
_("Arccosine, return an angle (in radian). "
"`ToDeg` allows to convert it to degrees."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
@@ -175,7 +176,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension
.AddExpression("asin",
_("Arcsine"),
_("Arcsine"),
_("Arcsine, return an angle (in radian). "
"`ToDeg` allows to convert it to degrees."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
@@ -191,7 +193,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension
.AddExpression("atan",
_("Arctangent"),
_("Arctangent"),
_("Arctangent, return an angle (in radian). "
"`ToDeg` allows to convert it to degrees."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
@@ -229,6 +232,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("ceilTo",
_("Ceil (round up) to a decimal point"),
_("Round number up to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("floor",
_("Floor (round down)"),
@@ -237,10 +249,20 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("floorTo",
_("Floor (round down) to a decimal point"),
_("Round number down to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("cos",
_("Cosine"),
_("Cosine of a number"),
_("Cosine of an angle (in radian). "
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
@@ -295,6 +317,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("roundTo",
_("Round to a decimal point"),
_("Round a number to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("exp",
_("Exponential"),
@@ -373,7 +404,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension
.AddExpression("sin",
_("Sine"),
_("Sine of a number"),
_("Sine of an angle (in radian). "
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
@@ -397,7 +429,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension
.AddExpression("tan",
_("Tangent"),
_("Tangent of a number"),
_("Tangent of an angle (in radian). "
"If you want to use degrees, use`ToRad`: `tan(ToRad(45))`."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
@@ -452,6 +485,23 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance"));
extension
.AddExpression("Pi",
_("Number Pi (3.1415...)"),
_("The number Pi (3.1415...)"),
"",
"res/mathfunction.png")
.SetHelpPath("/all-features/expressions");
extension
.AddExpression("lerpAngle",
_("Lerp (Linear interpolation) between two angles"),
_("Linearly interpolates between two angles (in degrees) by taking the shortest direction around the circle."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Starting angle, in degrees"))
.AddParameter("expression", _("Destination angle, in degrees"))
.AddParameter("expression", _("Interpolation value between 0 and 1."));
}
} // namespace gd

View File

@@ -160,7 +160,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -180,7 +180,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -190,6 +190,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
extension.AddDuplicatedCondition("SourisY", "MouseY").SetHidden();
extension.AddDuplicatedExpression("SourisY", "MouseY").SetHidden();
extension
.AddCondition("IsMouseInsideCanvas",
_("Mouse cursor is inside the window"),
_("Check if the mouse cursor is inside the window."),
_("The mouse cursor is inside the window"),
"",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsAdvanced();
extension
.AddCondition("MouseButtonPressed",
_("Mouse button pressed or touch held"),
@@ -265,7 +276,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -281,7 +292,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -300,7 +311,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddCondition(
@@ -315,8 +327,54 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddCondition(
"HasAnyTouchStarted",
_("A new touch has started"),
_("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"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
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")
.AddCodeOnlyParameter("currentScene", "");
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")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index"));
extension
.AddCondition(
"HasTouchEnded",
_("A touch has ended"),
_("Check if a touch has ended."),
_("The touch with identifier _PARAM1_ has ended"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"));
extension
.AddExpression("MouseWheelDelta",
_("Mouse wheel: Displacement"),
@@ -331,7 +389,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Identifier of the last touch"),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression("LastEndedTouchId",
@@ -339,7 +398,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Identifier of the last ended touch"),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
}
} // namespace gd

View File

@@ -112,7 +112,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
extension
.AddAction("SceneBackground",
_("Change background color"),
_("Background color"),
_("Change the background color of the scene."),
_("Set background color to _PARAM1_"),
"",

View File

@@ -4,8 +4,10 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
#include <iostream>
#include <vector>
#include "GDCore/CommonTools.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include "GDCore/Serialization/SerializerElement.h"
@@ -29,6 +31,15 @@ const Sprite& Direction::GetSprite(std::size_t nb) const { return sprites[nb]; }
Sprite& Direction::GetSprite(std::size_t nb) { return sprites[nb]; }
const std::vector<gd::String>& Direction::GetSpriteNames() const {
static std::vector<gd::String> spriteNames;
spriteNames.clear();
for (std::size_t i = 0; i < sprites.size(); ++i) {
spriteNames.push_back(sprites[i].GetImageName());
}
return spriteNames;
}
void Direction::RemoveSprite(std::size_t index) {
if (index < sprites.size()) sprites.erase(sprites.begin() + index);
}
@@ -121,7 +132,7 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
polygonElement.GetChild(k);
polygon.vertices.push_back(
sf::Vector2f(verticeElement.GetDoubleAttribute("x"),
gd::Vector2f(verticeElement.GetDoubleAttribute("x"),
verticeElement.GetDoubleAttribute("y")));
}

View File

@@ -72,6 +72,13 @@ class GD_CORE_API Direction {
*/
Sprite& GetSprite(std::size_t nb);
/**
* \brief Return a vector of references to sprite names.
*
* \return A vector of all sprite names references.
*/
const std::vector<gd::String>& GetSpriteNames() const;
/**
* \brief Check if the direction contains sprites.
*

View File

@@ -31,7 +31,7 @@ class GD_CORE_API Point {
/**
* Change point position.
*/
void SetXY(float x_, float y_) {
void SetXY(double x_, double y_) {
x = x_;
y = y_;
}
@@ -39,27 +39,27 @@ class GD_CORE_API Point {
/**
* Change point X position.
*/
void SetX(float x_) { x = x_; }
void SetX(double x_) { x = x_; }
/**
* Change point Y position.
*/
void SetY(float y_) { y = y_; }
void SetY(double y_) { y = y_; }
/**
* Get point X position.
*/
float GetX() const { return x; }
double GetX() const { return x; }
/**
* Get point Y position.
*/
float GetY() const { return y; }
double GetY() const { return y; }
private:
gd::String name;
float x;
float y;
double x;
double y;
};
#endif // GDCORE_POINT_H

View File

@@ -4,13 +4,15 @@
* reserved. This project is released under the MIT License.
*/
#include "Polygon2d.h"
#include <SFML/System/Vector2.hpp>
#include <cmath>
#include <iostream>
void Polygon2d::Rotate(float angle) {
float t, cosa = cos(-angle),
sina = sin(-angle); // We want a clockwise rotation
#include "GDCore/Vector2.h"
void Polygon2d::Rotate(double angle) {
double t, cosa = cos(-angle),
sina = sin(-angle); // We want a clockwise rotation
for (std::size_t i = 0; i < vertices.size(); ++i) {
t = vertices[i].x;
@@ -19,7 +21,7 @@ void Polygon2d::Rotate(float angle) {
}
}
void Polygon2d::Move(float x, float y) {
void Polygon2d::Move(double x, double y) {
for (std::size_t i = 0; i < vertices.size(); i++) {
vertices[i].x += x;
vertices[i].y += y;
@@ -28,7 +30,7 @@ void Polygon2d::Move(float x, float y) {
}
void Polygon2d::ComputeEdges() const {
sf::Vector2f v1, v2;
gd::Vector2f v1, v2;
edges.clear();
for (std::size_t i = 0; i < vertices.size(); i++) {
@@ -50,20 +52,20 @@ bool Polygon2d::IsConvex() const {
(edges[0].x * edges[0 + 1].y - edges[0].y * edges[0 + 1].x) > 0;
for (std::size_t i = 1; i < edges.size() - 1; ++i) {
float zCrossProduct =
double zCrossProduct =
edges[i].x * edges[i + 1].y - edges[i].y * edges[i + 1].x;
if ((zCrossProduct > 0) != zProductIsPositive) return false;
}
float lastZCrossProduct = edges[edges.size() - 1].x * edges[0].y -
edges[edges.size() - 1].y * edges[0].x;
double lastZCrossProduct = edges[edges.size() - 1].x * edges[0].y -
edges[edges.size() - 1].y * edges[0].x;
if ((lastZCrossProduct > 0) != zProductIsPositive) return false;
return true;
}
sf::Vector2f Polygon2d::ComputeCenter() const {
sf::Vector2f center;
gd::Vector2f Polygon2d::ComputeCenter() const {
gd::Vector2f center;
for (std::size_t i = 0; i < vertices.size(); i++) {
center.x += vertices[i].x;
@@ -75,12 +77,12 @@ sf::Vector2f Polygon2d::ComputeCenter() const {
return center;
}
Polygon2d Polygon2d::CreateRectangle(float width, float height) {
Polygon2d Polygon2d::CreateRectangle(double width, double height) {
Polygon2d rect;
rect.vertices.push_back(sf::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(sf::Vector2f(+width / 2.0f, -height / 2.0f));
rect.vertices.push_back(sf::Vector2f(+width / 2.0f, +height / 2.0f));
rect.vertices.push_back(sf::Vector2f(-width / 2.0f, +height / 2.0f));
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, +height / 2.0f));
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, +height / 2.0f));
return rect;
}

View File

@@ -5,9 +5,10 @@
*/
#ifndef GDCORE_POLYGON_H
#define GDCORE_POLYGON_H
#include <SFML/System/Vector2.hpp>
#include <vector>
#include "GDCore/Vector2.h"
/**
* \brief Represents a polygon. Usually used for collisions masks.
*
@@ -22,19 +23,19 @@ class GD_CORE_API Polygon2d {
Polygon2d(){};
virtual ~Polygon2d(){};
std::vector<sf::Vector2f> vertices; ///< The vertices composing the polygon
mutable std::vector<sf::Vector2f>
std::vector<gd::Vector2f> vertices; ///< The vertices composing the polygon
mutable std::vector<gd::Vector2f>
edges; ///< Edges. Can be computed from vertices using ComputeEdges()
/**
* \brief Get the vertices composing the polygon.
*/
std::vector<sf::Vector2f>& GetVertices() { return vertices; }
std::vector<gd::Vector2f>& GetVertices() { return vertices; }
/**
* \brief Get the vertices composing the polygon.
*/
const std::vector<sf::Vector2f>& GetVertices() const { return vertices; }
const std::vector<gd::Vector2f>& GetVertices() const { return vertices; }
/**
* \brief Moves each vertices from the given amount.
@@ -42,7 +43,7 @@ class GD_CORE_API Polygon2d {
* \note Edges are updated, there is no need to call ComputeEdges after
* calling Move.
*/
void Move(float x, float y);
void Move(double x, double y);
/**
* \brief Rotate the polygon.
@@ -52,7 +53,7 @@ class GD_CORE_API Polygon2d {
* \warning edges vector is not updated, you have to call ComputeEdges if
* needed.
*/
void Rotate(float angle);
void Rotate(double angle);
/**
* \brief Automatically fill edges vector using vertices.
@@ -68,7 +69,7 @@ class GD_CORE_API Polygon2d {
/**
* \brief Return the position of the center of the polygon
*/
sf::Vector2f ComputeCenter() const;
gd::Vector2f ComputeCenter() const;
/** \name Tools
* Tool functions
@@ -77,7 +78,7 @@ class GD_CORE_API Polygon2d {
/**
* \brief Create a rectangle
*/
static Polygon2d CreateRectangle(float width, float height);
static Polygon2d CreateRectangle(double width, double height);
///@}
};

View File

@@ -4,7 +4,6 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include <SFML/Graphics/Sprite.hpp>
#include <iostream>
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"

View File

@@ -6,7 +6,6 @@
#ifndef SPRITE_H
#define SPRITE_H
#include <SFML/Graphics/Sprite.hpp>
#include <memory>
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"

View File

@@ -22,6 +22,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects/sprite");
extension.AddInstructionOrExpressionGroupMetadata(_("Sprite"))
.SetIcon("CppPlatform/Extensions/spriteicon.png");
gd::ObjectMetadata& obj =
extension
@@ -33,7 +35,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetCategoryFullName(_("General"));
obj.AddAction("Opacity",
_("Change sprite opacity"),
_("Sprite opacity"),
_("Change the opacity of a Sprite. 0 is fully transparent, 255 "
"is opaque (default)."),
_("the opacity"),
@@ -42,7 +44,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/opacity.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity (0-255)")))
.MarkAsSimple();
obj.AddAction("ChangeAnimation",
@@ -55,7 +60,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddAction("SetAnimationName",
@@ -79,12 +85,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"is in 8 directions mode, the valid directions are 0..7"),
_("the direction"),
_("Direction"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/direction24_black.png",
"res/actions/direction_black.png")
.SetHidden() // Hide as 8 direction is not supported officially in the
// interface.
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("ChangeSprite",
@@ -96,7 +103,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("PauseAnimation",
@@ -132,7 +140,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Speed scale")))
.MarkAsSimple();
obj.AddAction("TourneVersPos",
@@ -140,8 +150,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"Rotate an object towards a position.",
"Rotate _PARAM0_ towards _PARAM1_;_PARAM2_",
_("Direction"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object to be rotated"), "Sprite")
.AddParameter("expression", _("X position"))
@@ -156,11 +166,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Modify the scale of the specified object."),
_("the scale"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scale24_black.png",
"res/actions/scale_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddAction("ChangeScaleWidth",
@@ -168,11 +181,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Modify the scale of the width of an object."),
_("the width's scale"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleWidth24_black.png",
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddAction("ChangeScaleHeight",
@@ -180,11 +196,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Modify the scale of the height of an object."),
_("the height's scale"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleHeight24_black.png",
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddAction("ChangeWidth",
@@ -192,11 +211,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Change the width of a Sprite object."),
_("the width"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleWidth24_black.png",
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("Width",
@@ -204,11 +224,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the width of a Sprite object."),
_("the width"),
_("Size"),
"res/conditions/scaleWidth24.png",
"res/conditions/scaleWidth.png")
"res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("ChangeHeight",
@@ -216,11 +237,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Change the height of a Sprite object."),
_("the height"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scaleHeight24_black.png",
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("Height",
@@ -228,11 +250,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the height of a Sprite object."),
_("the height"),
_("Size"),
"res/conditions/scaleHeight24.png",
"res/conditions/scaleHeight.png")
"res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("SetSize",
@@ -240,8 +263,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Change the size of an object."),
_("Change the size of _PARAM0_: set to _PARAM1_x_PARAM2_"),
_("Size"),
"res/actions/scale24.png",
"res/actions/scale.png")
"res/actions/scale24_black.png",
"res/actions/scale_black.png")
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Width"))
@@ -258,7 +281,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("AnimationName",
@@ -281,12 +305,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"from 0 to 7. Otherwise, the direction is in degrees."),
_("the direction"),
_("Direction"),
"res/conditions/direction24.png",
"res/conditions/direction.png")
"res/conditions/direction24_black.png",
"res/conditions/direction_black.png")
.SetHidden() // Hide as 8 direction is not supported officially in the
// interface.
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions());
obj.AddCondition("Sprite",
_("Current frame"),
@@ -299,7 +324,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/sprite.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("AnimStopped",
@@ -322,6 +348,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation24.png",
"res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.MarkAsSimple()
.SetHidden();
obj.AddCondition("AnimationEnded2",
_("Animation finished"),
_("Check if the animation being played by the Sprite object "
"is finished."),
_("The animation of _PARAM0_ is finished"),
_("Animations and images"),
"res/conditions/animation24.png",
"res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.MarkAsSimple();
@@ -330,11 +369,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the scale of the width of an object."),
_("the width's scale"),
_("Size"),
"res/conditions/scaleWidth24.png",
"res/conditions/scaleWidth.png")
"res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddCondition("ScaleHeight",
@@ -342,11 +384,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Compare the scale of the height of an object."),
_("the height's scale"),
_("Size"),
"res/conditions/scaleHeight24.png",
"res/conditions/scaleHeight.png")
"res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddCondition("Opacity",
@@ -359,7 +404,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/opacity.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity to compare to (0-255)")))
.MarkAsSimple();
obj.AddCondition(
@@ -372,7 +420,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/opacity.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("ChangeColor",
@@ -449,8 +498,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"Rotate an object towards another.",
"Rotate _PARAM0_ towards _PARAM1_",
_("Direction"),
"res/actions/direction24.png",
"res/actions/direction.png")
"res/actions/rotate24_black.png",
"res/actions/rotate_black.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPtr", "Rotate toward this object")
@@ -461,7 +510,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("X position of a point"),
_("X position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"), "", true);
@@ -470,7 +519,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Y position of a point"),
_("Y position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"), "", true);
@@ -479,7 +528,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("X position of a point"),
_("X position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"));
@@ -488,7 +537,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Y position of a point"),
_("Y position of a point"),
_("Position"),
"res/actions/position.png")
"res/actions/position_black.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"));
@@ -497,7 +546,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Direction"),
_("Direction of the object"),
_("Direction"),
"res/actions/direction.png")
"res/actions/direction_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
@@ -505,7 +554,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Direction"),
_("Direction of the object"),
_("Direction"),
"res/actions/direction.png")
"res/actions/direction_black.png")
.SetHidden() // Hide as 8 direction is not supported officially in the
// interface.
.AddParameter("object", _("Object"), "Sprite");
@@ -550,14 +599,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale of the width of an object"),
_("Scale of the width of an object"),
_("Size"),
"res/actions/scaleWidth.png")
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleY",
_("Scale of the height of an object"),
_("Scale of the height of an object"),
_("Size"),
"res/actions/scaleHeight.png")
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("Opacity",

View File

@@ -6,7 +6,6 @@
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
#include <SFML/Graphics.hpp>
#include <algorithm>
#include "GDCore/CommonTools.h"
@@ -26,8 +25,7 @@ namespace gd {
Animation SpriteObject::badAnimation;
SpriteObject::SpriteObject(gd::String name_)
: Object(name_), updateIfNotVisible(false) {}
SpriteObject::SpriteObject() : updateIfNotVisible(false) {}
SpriteObject::~SpriteObject(){};

View File

@@ -36,11 +36,11 @@ namespace gd {
* \see gd::BuiltinExtensionsImplementer::ImplementsSpriteExtension
* \ingroup SpriteObjectExtension
*/
class GD_CORE_API SpriteObject : public gd::Object {
class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
public:
SpriteObject(gd::String name_);
SpriteObject();
virtual ~SpriteObject();
std::unique_ptr<gd::Object> Clone() const override {
std::unique_ptr<gd::ObjectConfiguration> Clone() const override {
return gd::make_unique<SpriteObject>(*this);
}

View File

@@ -21,20 +21,20 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
extension.AddInstructionOrExpressionGroupMetadata(_("Text manipulation"))
.SetIcon("res/actions/text24.png");
.SetIcon("res/actions/text24_black.png");
extension.AddStrExpression("NewLine",
_("Insert a new line"),
_("Insert a new line"),
"",
"res/conditions/toujours24.png");
"res/conditions/toujours24_black.png");
extension
.AddStrExpression("FromCodePoint",
_("Get character from code point"),
_("Get character from code point"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("expression", _("Code point"));
@@ -43,7 +43,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Uppercase a text"),
_("Uppercase a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"));
@@ -52,7 +52,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Lowercase a text"),
_("Lowercase a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"));
@@ -61,7 +61,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Get a portion of a text"),
_("Get a portion of a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("expression",
@@ -74,7 +74,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Get a character from a text"),
_("Get a character from a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter(
@@ -86,7 +86,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Repeat a text"),
_("Repeat a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text to repeat"))
.AddParameter("expression", _("Repetition count"));
@@ -96,7 +96,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Length of a text"),
_("Length of a text"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"));
@@ -106,7 +106,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Search in a text (return the position of the result or "
"-1 if not found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"));
@@ -117,7 +117,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"Search in a text from the end (return the position of "
"the result or -1 if not found)",
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))
@@ -131,7 +131,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"the result, from the beginning of the string, or -1 if not "
"found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"));
@@ -142,7 +142,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Search in a text, starting from a position (return the "
"position of the result or -1 if not found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))
@@ -157,7 +157,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"Search in a text from the end, starting from a position (return "
"the position of the result or -1 if not found)",
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))
@@ -175,7 +175,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
" the position of the result, from the beginning of the string, or "
"-1 if not found)"),
"",
"res/conditions/toujours24.png")
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text"))
.AddParameter("string", _("Text to search for"))

View File

@@ -20,10 +20,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"for slow motion effects).",
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/timers");
extension.AddInstructionOrExpressionGroupMetadata(
_("Timers and time")
)
.SetExtensionHelpPath("/all-features/timers-and-time");
extension.AddInstructionOrExpressionGroupMetadata(_("Timers and time"))
.SetIcon("res/conditions/timer24.png");
// Deprecated and replaced by CompareTimer
@@ -38,7 +36,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/conditions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Time in seconds"))
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.SetHidden();
extension
@@ -52,7 +50,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/conditions/timer24.png",
"res/conditions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.AddParameter("relationalOperator", _("Sign of the test"), "time")
.AddParameter("expression", _("Time in seconds"))
.SetManipulatedType("number");
@@ -67,7 +65,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/conditions/time24.png",
"res/conditions/time.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Time scale (1 by default)")))
.MarkAsAdvanced();
extension
@@ -80,7 +81,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/conditions/timerPaused24.png",
"res/conditions/timerPaused.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
@@ -95,7 +96,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
extension
.AddAction("PauseTimer",
@@ -107,7 +108,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/pauseTimer24.png",
"res/actions/pauseTimer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
@@ -120,7 +121,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/unPauseTimer24.png",
"res/actions/unPauseTimer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
@@ -133,15 +134,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"res/actions/timer24.png",
"res/actions/timer.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"))
.AddParameter("identifier", _("Timer's name"), "sceneTimer")
.MarkAsAdvanced();
extension
.AddAction("ChangeTimeScale",
_("Change time scale"),
_("Time scale"),
_("Change the time scale of the scene."),
_("Set the time scale of the scene to _PARAM1_"),
"",
"res/actions/time24.png",
"res/actions/time.png")
@@ -149,6 +149,18 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
.AddParameter("expression",
_("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)"));
extension
.AddAction("Wait",
_("Wait X seconds (experimental)"),
_("Waits a number of seconds before running "
"the next actions (and sub-events)."),
_("Wait _PARAM0_ seconds"),
"",
"res/timer_black.svg",
"res/timer_black.svg")
.AddParameter("expression", _("Time to wait in seconds"))
.SetHelpPath("/all-features/timers-and-time/wait-action");
extension
.AddExpression("TimeDelta",
_("Time elapsed since the last frame"),
@@ -182,7 +194,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"",
"res/actions/time.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Timer's name"));
.AddParameter("identifier", _("Timer's name"), "sceneTimer");
extension
.AddExpression("TimeFromStart",

View File

@@ -34,7 +34,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions());
extension
.AddCondition("VarSceneTxt",
@@ -45,7 +46,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardRelationalOperatorParameters("string");
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions());
extension
.AddCondition(
@@ -107,7 +109,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -119,7 +122,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardRelationalOperatorParameters("string")
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -157,7 +161,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions());
extension
.AddAction("ModVarSceneTxt",
@@ -168,7 +173,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardOperatorParameters("string");
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions());
extension
.AddAction(
@@ -203,7 +209,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -215,7 +222,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardOperatorParameters("string")
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension

View File

@@ -20,6 +20,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
"these features can be applied.",
"Florian Rival",
"Open source (MIT License)")
.SetCategory("User interface")
.SetExtensionHelpPath("/all-features/window");
extension
.AddInstructionOrExpressionGroupMetadata(
@@ -55,7 +56,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
extension
.AddAction("SetWindowMargins",
_("Change the window's margins"),
_("Window's margins"),
_("This action changes the margins, in pixels, between the "
"game frame and the window borders."),
_("Set margins of game window to "
@@ -71,7 +72,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
extension
.AddAction("SetGameResolutionSize",
_("Change the resolution of the game"),
_("Game resolution"),
_("Changes the resolution of the game, effectively changing "
"the game area size. This won't change the size of the "
"window in which the game is running."),
@@ -117,7 +118,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
extension
.AddAction("SetGameResolutionResizeMode",
_("Change the game resolution resize mode"),
_("Game resolution resize mode"),
_("Set if the width or the height of the game resolution "
"should be changed to fit the game window - or if the game "
"resolution should not be updated automatically."),
@@ -153,7 +154,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
extension
.AddAction("SetWindowIcon",
_("Change the window's icon"),
_("Window's icon"),
_("This action changes the icon of the game's window."),
_("Use _PARAM1_ as the icon for the game's window."),
"",
@@ -164,7 +165,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
extension
.AddAction("SetWindowTitle",
_("Change the window's title"),
_("Window's title"),
_("This action changes the title of the game's window."),
_("Change window title to _PARAM1_"),
"",

View File

@@ -14,12 +14,14 @@
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/MakeUnique.h"
#include "GDCore/Tools/Log.h"
namespace gd {
BehaviorMetadata::BehaviorMetadata(
const gd::String& extensionNamespace_,
const gd::String& name_,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
@@ -29,21 +31,50 @@ BehaviorMetadata::BehaviorMetadata(
std::shared_ptr<gd::Behavior> instance_,
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance_)
: extensionNamespace(extensionNamespace_),
className(className_),
iconFilename(icon24x24),
instance(instance_),
sharedDatasInstance(sharedDatasInstance_) {
#if defined(GD_IDE_ONLY)
sharedDatasInstance(sharedDatasInstance_),
isEventBased(false) {
SetFullName(gd::String(fullname_));
SetDescription(gd::String(description_));
SetDefaultName(gd::String(defaultName_));
SetGroup(group_);
className = className_;
iconFilename = icon24x24;
#endif
if (instance) instance->SetTypeName(name_);
if (sharedDatasInstance) sharedDatasInstance->SetTypeName(name_);
if (!instance) {
gd::LogFatalError(
"Trying to create a BehaviorMetadata that has no "
"behavior. This will crash - please double check that the "
"BehaviorMetadata is valid for: " + nameWithNamespace);
}
if (instance) instance->SetTypeName(nameWithNamespace);
if (sharedDatasInstance) sharedDatasInstance->SetTypeName(nameWithNamespace);
}
BehaviorMetadata::BehaviorMetadata(
const gd::String& extensionNamespace,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
const gd::String& group_,
const gd::String& icon24x24_): BehaviorMetadata(
extensionNamespace,
nameWithNamespace,
fullname_,
defaultName_,
description_,
group_,
icon24x24_,
// Class name is the name, actually unused
defaultName_,
// It is only used to get the name for GetName.
gd::make_unique<gd::Behavior>("", nameWithNamespace),
nullptr){
isEventBased = true;
};
gd::InstructionMetadata& BehaviorMetadata::AddCondition(
const gd::String& name,
const gd::String& fullname,
@@ -52,7 +83,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddCondition(
const gd::String& group,
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace =
extensionNamespace.empty() ? name : extensionNamespace + name;
conditionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
@@ -66,7 +96,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddCondition(
.SetHelpPath(GetHelpPath())
.SetIsBehaviorInstruction();
return conditionsInfos[nameWithNamespace];
#endif
}
gd::InstructionMetadata& BehaviorMetadata::AddAction(
@@ -77,7 +106,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddAction(
const gd::String& group,
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace =
extensionNamespace.empty() ? name : extensionNamespace + name;
actionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
@@ -91,7 +119,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddAction(
.SetHelpPath(GetHelpPath())
.SetIsBehaviorInstruction();
return actionsInfos[nameWithNamespace];
#endif
}
gd::InstructionMetadata& BehaviorMetadata::AddScopedCondition(
@@ -102,7 +129,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddScopedCondition(
const gd::String& group,
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace =
GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
conditionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
@@ -116,7 +142,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddScopedCondition(
.SetHelpPath(GetHelpPath())
.SetIsBehaviorInstruction();
return conditionsInfos[nameWithNamespace];
#endif
}
gd::InstructionMetadata& BehaviorMetadata::AddScopedAction(
@@ -127,7 +152,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddScopedAction(
const gd::String& group,
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace =
GetName() + gd::PlatformExtension::GetNamespaceSeparator() + name;
actionsInfos[nameWithNamespace] = InstructionMetadata(extensionNamespace,
@@ -141,7 +165,6 @@ gd::InstructionMetadata& BehaviorMetadata::AddScopedAction(
.SetHelpPath(GetHelpPath())
.SetIsBehaviorInstruction();
return actionsInfos[nameWithNamespace];
#endif
}
gd::ExpressionMetadata& BehaviorMetadata::AddExpression(
@@ -150,7 +173,6 @@ gd::ExpressionMetadata& BehaviorMetadata::AddExpression(
const gd::String& description,
const gd::String& group,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
// Be careful, behaviors expression do not have namespace (not necessary as
// we refer to the behavior name in the expression).
expressionsInfos[name] = ExpressionMetadata("number",
@@ -162,7 +184,6 @@ gd::ExpressionMetadata& BehaviorMetadata::AddExpression(
smallicon)
.SetHelpPath(GetHelpPath());
return expressionsInfos[name];
#endif
}
gd::ExpressionMetadata& BehaviorMetadata::AddStrExpression(
@@ -171,7 +192,6 @@ gd::ExpressionMetadata& BehaviorMetadata::AddStrExpression(
const gd::String& description,
const gd::String& group,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
// Be careful, behaviors expression do not have namespace (not necessary as
// we refer to the behavior name in the expression).
strExpressionsInfos[name] = ExpressionMetadata("string",
@@ -183,7 +203,6 @@ gd::ExpressionMetadata& BehaviorMetadata::AddStrExpression(
smallicon)
.SetHelpPath(GetHelpPath());
return strExpressionsInfos[name];
#endif
}
gd::MultipleInstructionMetadata BehaviorMetadata::AddExpressionAndCondition(
@@ -288,7 +307,6 @@ BehaviorMetadata::AddExpressionAndConditionAndAction(
expression, condition, action);
}
#if defined(GD_IDE_ONLY)
gd::InstructionMetadata& BehaviorMetadata::AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName) {
gd::String newNameWithNamespace = extensionNamespace + newActionName;
@@ -356,49 +374,44 @@ gd::ExpressionMetadata& BehaviorMetadata::AddDuplicatedStrExpression(
return strExpressionsInfos[newNameWithNamespace];
}
#endif
BehaviorMetadata& BehaviorMetadata::SetFullName(const gd::String& fullname_) {
#if defined(GD_IDE_ONLY)
fullname = fullname_;
#endif
return *this;
}
BehaviorMetadata& BehaviorMetadata::SetDefaultName(
const gd::String& defaultName_) {
#if defined(GD_IDE_ONLY)
defaultName = defaultName_;
#endif
return *this;
}
BehaviorMetadata& BehaviorMetadata::SetDescription(
const gd::String& description_) {
#if defined(GD_IDE_ONLY)
description = description_;
#endif
return *this;
}
BehaviorMetadata& BehaviorMetadata::SetGroup(const gd::String& group_) {
#if defined(GD_IDE_ONLY)
group = group_;
#endif
return *this;
}
BehaviorMetadata& BehaviorMetadata::SetIncludeFile(
const gd::String& includeFile) {
#if defined(GD_IDE_ONLY)
includeFiles.clear();
includeFiles.push_back(includeFile);
#endif
return *this;
}
BehaviorMetadata& BehaviorMetadata::AddIncludeFile(
const gd::String& includeFile) {
#if defined(GD_IDE_ONLY)
if (std::find(includeFiles.begin(), includeFiles.end(), includeFile) ==
includeFiles.end())
includeFiles.push_back(includeFile);
#endif
return *this;
}
BehaviorMetadata& BehaviorMetadata::AddRequiredFile(
const gd::String& requiredFile) {
if (std::find(requiredFiles.begin(), requiredFiles.end(), requiredFile) ==
requiredFiles.end())
requiredFiles.push_back(requiredFile);
return *this;
}
@@ -407,13 +420,25 @@ const gd::String& BehaviorMetadata::GetName() const {
}
gd::Behavior& BehaviorMetadata::Get() const {
if (!instance)
if (isEventBased) {
gd::LogFatalError("Error: Event-based behaviors don't have blueprint. "
"This method should not never be called.");
}
if (!instance) {
gd::LogFatalError(
"Trying to get a behavior from a BehaviorMetadata that has no "
"behavior. This will crash - please double check that the "
"BehaviorMetadata is valid.");
"BehaviorMetadata is valid for: " + className);
}
return *instance;
}
gd::BehaviorsSharedData* BehaviorMetadata::GetSharedDataInstance() const {
if (isEventBased) {
gd::LogFatalError("Error: Event-based behaviors don't have blueprint. "
"This method should not never be called.");
}
return sharedDatasInstance.get();
}
} // namespace gd

View File

@@ -29,7 +29,7 @@ class GD_CORE_API BehaviorMetadata {
public:
BehaviorMetadata(
const gd::String& extensionNamespace,
const gd::String& name_,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
@@ -38,6 +38,21 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& className_,
std::shared_ptr<gd::Behavior> instance,
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance);
/**
* \brief Construct a behavior metadata, without "blueprint" behavior.
*
* \note This is used by events based behaviors.
*/
BehaviorMetadata(
const gd::String& extensionNamespace,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
const gd::String& group_,
const gd::String& icon24x24_);
BehaviorMetadata(){};
virtual ~BehaviorMetadata(){};
@@ -195,6 +210,13 @@ class GD_CORE_API BehaviorMetadata {
*/
BehaviorMetadata& AddIncludeFile(const gd::String& includeFile);
/**
* \brief Add a file to the already existing required files.
* \note These files are required for the behavior to work,
* but they are not executable.
*/
BehaviorMetadata& AddRequiredFile(const gd::String& requiredFile);
/**
* Get the help path of the behavior, relative to the GDevelop documentation
* root.
@@ -214,7 +236,6 @@ class GD_CORE_API BehaviorMetadata {
}
const gd::String& GetName() const;
#if defined(GD_IDE_ONLY)
const gd::String& GetFullName() const { return fullname; }
const gd::String& GetDefaultName() const { return defaultName; }
const gd::String& GetDescription() const { return description; }
@@ -235,20 +256,38 @@ class GD_CORE_API BehaviorMetadata {
* \note An empty string means the base object, so any object.
*/
const gd::String& GetObjectType() const { return objectType; }
#endif
/**
* Check if the behavior is private - it can't be used outside of its
* extension.
*/
bool IsPrivate() const { return isPrivate; }
/**
* Set that the behavior is private - it can't be used outside of its
* extension.
*/
BehaviorMetadata &SetPrivate() {
isPrivate = true;
return *this;
}
/**
* \brief Return the associated gd::Behavior, handling behavior contents.
*
* \note Returns a dumb Behavior for events based behaviors as CustomBehavior
* are using EventBasedBehavior.
*/
gd::Behavior& Get() const;
/**
* \brief Return the associated gd::BehaviorsSharedData, handling behavior
* shared data, if any (nullptr if none).
*
* \note Returns nullptr for events based behaviors as they don't declare
* shared data yet.
*/
gd::BehaviorsSharedData* GetSharedDataInstance() const {
return sharedDatasInstance.get();
}
gd::BehaviorsSharedData* GetSharedDataInstance() const;
/**
* \brief Return a reference to a map containing the names of the actions
@@ -271,30 +310,30 @@ class GD_CORE_API BehaviorMetadata {
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() { return strExpressionsInfos; };
#if defined(GD_IDE_ONLY)
std::map<gd::String, gd::InstructionMetadata> conditionsInfos;
std::map<gd::String, gd::InstructionMetadata> actionsInfos;
std::map<gd::String, gd::ExpressionMetadata> expressionsInfos;
std::map<gd::String, gd::ExpressionMetadata> strExpressionsInfos;
std::vector<gd::String> includeFiles;
std::vector<gd::String> requiredFiles;
gd::String className;
#endif
private:
gd::String extensionNamespace;
gd::String helpPath;
#if defined(GD_IDE_ONLY)
gd::String fullname;
gd::String defaultName;
gd::String description;
gd::String group;
gd::String iconFilename;
gd::String objectType;
#endif
bool isPrivate = false;
// TODO: Nitpicking: convert these to std::unique_ptr to clarify ownership.
std::shared_ptr<gd::Behavior> instance;
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance;
bool isEventBased;
};
} // namespace gd

View File

@@ -8,6 +8,7 @@
#include <functional>
#include <map>
#include <memory>
#include <algorithm>
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/String.h"

View File

@@ -37,22 +37,24 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
const gd::String& supplementaryInformation,
bool parameterIsOptional) {
gd::ParameterMetadata info;
info.type = type;
info.SetType(type);
info.description = description;
info.codeOnly = false;
info.optional = parameterIsOptional;
info.supplementaryInformation =
info.SetOptional(parameterIsOptional);
info.SetExtraInfo(
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
(gd::ParameterMetadata::IsObject(type) ||
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
supplementaryInformation //... so prefix it with the extension
// namespace.
)
: supplementaryInformation; // Otherwise don't change anything
: supplementaryInformation); // Otherwise don't change anything
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
@@ -64,9 +66,9 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
gd::ExpressionMetadata& ExpressionMetadata::AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation) {
gd::ParameterMetadata info;
info.type = type;
info.SetType(type);
info.codeOnly = true;
info.supplementaryInformation = supplementaryInformation;
info.SetExtraInfo(supplementaryInformation);
parameters.push_back(info);
return *this;

View File

@@ -222,6 +222,18 @@ class GD_CORE_API ExpressionMetadata {
return *this;
};
/**
* \brief Set the additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter), for the last added parameter.
*
* \see AddParameter
*/
ExpressionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
}
/**
* \brief Mark this (object) expression as requiring the specified capability,
* offered by the base object.
@@ -256,7 +268,30 @@ class GD_CORE_API ExpressionMetadata {
*/
ExpressionCodeGenerationInformation& GetCodeExtraInformation() {
return codeExtraInformation;
};
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
}
ExpressionCodeGenerationInformation codeExtraInformation;

View File

@@ -55,15 +55,17 @@ InstructionMetadata& InstructionMetadata::AddParameter(
const gd::String& supplementaryInformation,
bool parameterIsOptional) {
ParameterMetadata info;
info.type = type;
info.SetType(type);
info.description = description;
info.codeOnly = false;
info.optional = parameterIsOptional;
info.supplementaryInformation =
info.SetOptional(parameterIsOptional);
info.SetExtraInfo(
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
(gd::ParameterMetadata::IsObject(type) ||
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
@@ -71,7 +73,7 @@ InstructionMetadata& InstructionMetadata::AddParameter(
// extension
// namespace.
)
: supplementaryInformation; // Otherwise don't change anything
: supplementaryInformation); // Otherwise don't change anything
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
@@ -83,20 +85,24 @@ InstructionMetadata& InstructionMetadata::AddParameter(
InstructionMetadata& InstructionMetadata::AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation) {
ParameterMetadata info;
info.type = type;
info.SetType(type);
info.codeOnly = true;
info.supplementaryInformation = supplementaryInformation;
info.SetExtraInfo(supplementaryInformation);
parameters.push_back(info);
return *this;
}
InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
const gd::String& type) {
SetManipulatedType(type);
const gd::String& type, const ParameterOptions &options) {
const gd::String& expressionValueType =
gd::ValueTypeMetadata::GetPrimitiveValueType(type);
SetManipulatedType(expressionValueType);
if (type == "boolean") {
AddParameter("yesorno", _("New value"));
AddParameter(
"yesorno",
options.description.empty() ? _("New value") : options.description);
size_t valueParamIndex = parameters.size() - 1;
if (isObjectInstruction || isBehaviorInstruction) {
@@ -117,8 +123,10 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
"_PARAM" + gd::String::From(valueParamIndex) + "_");
}
} else {
AddParameter("operator", _("Modification's sign"), type);
AddParameter(type == "number" ? "expression" : type, _("Value"));
AddParameter("operator", _("Modification's sign"), expressionValueType);
AddParameter(type,
options.description.empty() ? _("Value") : options.description,
options.typeExtraInfo);
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;
@@ -151,8 +159,10 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
InstructionMetadata&
InstructionMetadata::UseStandardRelationalOperatorParameters(
const gd::String& type) {
SetManipulatedType(type);
const gd::String& type, const ParameterOptions &options) {
const gd::String& expressionValueType =
gd::ValueTypeMetadata::GetPrimitiveValueType(type);
SetManipulatedType(expressionValueType);
if (type == "boolean") {
if (isObjectInstruction || isBehaviorInstruction) {
@@ -168,8 +178,10 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
templateSentence.FindAndReplace("<subject>", sentence);
}
} else {
AddParameter("relationalOperator", _("Sign of the test"), type);
AddParameter(type == "number" ? "expression" : type, _("Value to compare"));
AddParameter("relationalOperator", _("Sign of the test"), expressionValueType);
AddParameter(type,
options.description.empty() ? _("Value to compare") : options.description,
options.typeExtraInfo);
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;

View File

@@ -6,6 +6,7 @@
#ifndef INSTRUCTIONMETADATA_H
#define INSTRUCTIONMETADATA_H
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
@@ -13,6 +14,8 @@
#include "GDCore/Events/Instruction.h"
#include "GDCore/String.h"
#include "ParameterMetadata.h"
#include "ParameterOptions.h"
namespace gd {
class Project;
class Layout;
@@ -98,6 +101,23 @@ class GD_CORE_API InstructionMetadata {
return *this;
}
/**
* Check if the instruction is asynchronous - it will be running in the
* background, executing the instructions following it before the frame after
* it resolved.
*/
bool IsAsync() const {
return !codeExtraInformation.asyncFunctionCallName.empty();
}
/**
* Check if the instruction asynchronicity is optional. If it is, it can
* either be used synchronously or asynchronously, with one function for each.
*/
bool IsOptionallyAsync() const {
return IsAsync() && !codeExtraInformation.functionCallName.empty();
}
/**
* Notify that the instruction can have sub instructions.
*/
@@ -188,7 +208,7 @@ class GD_CORE_API InstructionMetadata {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
};
}
/**
* \brief Set the additional information, used for some parameters
@@ -200,20 +220,27 @@ class GD_CORE_API InstructionMetadata {
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
};
}
/**
* \brief Add the default parameters for an instruction manipulating the
* specified type ("string", "number") with the default operators.
*
* \note The type "string" can be declined in several subtypes.
* \see ParameterMetadata
*/
InstructionMetadata &UseStandardOperatorParameters(const gd::String &type);
InstructionMetadata &UseStandardOperatorParameters(
const gd::String &type, const ParameterOptions &options);
/**
* \brief Add the default parameters for an instruction comparing the
* specified type ("string", "number") with the default relational operators.
*
* \note The type "string" can be declined in several subtypes.
* \see ParameterMetadata
*/
InstructionMetadata &UseStandardRelationalOperatorParameters(
const gd::String &type);
const gd::String &type, const ParameterOptions &options);
/**
* \brief Mark the instruction as an object instruction. Automatically called
@@ -258,7 +285,7 @@ class GD_CORE_API InstructionMetadata {
*/
const gd::String &GetRequiredBaseObjectCapability() const {
return requiredBaseObjectCapability;
};
}
/**
* \brief Consider that the instruction is easy for a user to understand.
@@ -301,14 +328,27 @@ class GD_CORE_API InstructionMetadata {
virtual ~ExtraInformation(){};
/**
* Set the function name which will be used when generating the code.
* \param functionName the name of the function to call
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
*/
ExtraInformation &SetFunctionName(const gd::String &functionName_) {
functionCallName = functionName_;
return *this;
}
/**
* Set the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*
* \param functionName the name of the function doing asynchronous work to
* call.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName_) {
asyncFunctionCallName = functionName_;
return *this;
}
/**
* Declare if the instruction being declared is somewhat manipulating in a
* standard way.
@@ -331,12 +371,12 @@ class GD_CORE_API InstructionMetadata {
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text.png");
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString").SetIncludeFile("MyExtension/TextObject.h");
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString");
*
* DECLARE_END_OBJECT_ACTION()
* \endcode
@@ -404,6 +444,7 @@ class GD_CORE_API InstructionMetadata {
bool HasCustomCodeGenerator() const { return hasCustomCodeGenerator; }
gd::String functionCallName;
gd::String asyncFunctionCallName;
gd::String type;
AccessType accessType;
gd::String optionalAssociatedInstruction;
@@ -436,15 +477,49 @@ class GD_CORE_API InstructionMetadata {
}
/**
* \brief Set the function that should be called when generating the source
* code from events.
* \param functionName the name of the function to call
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
ExtraInformation &SetFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetFunctionName(functionName);
}
/**
* Set the name of the function, doing asynchronous work, which will be called
* in the generated code. This function should return an asynchronous task
* (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*
* \param functionName the name of the function doing asynchronous work to
* call. \note Shortcut for `codeExtraInformation.SetAsyncFunctionName`.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetAsyncFunctionName(functionName);
}
/**
* \brief Erase any existing include file and add the specified include.
*/
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
};
std::vector<ParameterMetadata> parameters;
private:

View File

@@ -13,7 +13,9 @@
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Layout.h" // For GetTypeOfObject and GetTypeOfBehavior
#include "GDCore/String.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
using namespace std;
@@ -30,12 +32,9 @@ ExtensionAndMetadata<BehaviorMetadata>
MetadataProvider::GetExtensionAndBehaviorMetadata(const gd::Platform& platform,
gd::String behaviorType) {
for (auto& extension : platform.GetAllPlatformExtensions()) {
auto behaviorTypes = extension->GetBehaviorsTypes();
for (std::size_t j = 0; j < behaviorTypes.size(); ++j) {
if (behaviorTypes[j] == behaviorType)
return ExtensionAndMetadata<BehaviorMetadata>(
*extension, extension->GetBehaviorMetadata(behaviorType));
}
if (extension->HasBehavior(behaviorType))
return ExtensionAndMetadata<BehaviorMetadata>(
*extension, extension->GetBehaviorMetadata(behaviorType));
}
return ExtensionAndMetadata<BehaviorMetadata>(badExtension, badBehaviorMetadata);
@@ -202,8 +201,7 @@ MetadataProvider::GetExtensionAndBehaviorExpressionMetadata(
const gd::Platform& platform, gd::String autoType, gd::String exprType) {
auto& extensions = platform.GetAllPlatformExtensions();
for (auto& extension : extensions) {
const auto& autos = extension->GetBehaviorsTypes();
if (find(autos.begin(), autos.end(), autoType) != autos.end()) {
if (extension->HasBehavior(autoType)) {
const auto& allAutoExpressions =
extension->GetAllExpressionsForBehavior(autoType);
if (allAutoExpressions.find(exprType) != allAutoExpressions.end())
@@ -292,8 +290,7 @@ MetadataProvider::GetExtensionAndBehaviorStrExpressionMetadata(
const gd::Platform& platform, gd::String autoType, gd::String exprType) {
auto& extensions = platform.GetAllPlatformExtensions();
for (auto& extension : extensions) {
const auto& autos = extension->GetBehaviorsTypes();
if (find(autos.begin(), autos.end(), autoType) != autos.end()) {
if (extension->HasBehavior(autoType)) {
const auto& allBehaviorStrExpressions =
extension->GetAllStrExpressionsForBehavior(autoType);
if (allBehaviorStrExpressions.find(exprType) !=
@@ -350,28 +347,30 @@ const gd::ExpressionMetadata& MetadataProvider::GetAnyExpressionMetadata(
const gd::Platform& platform, gd::String exprType) {
const auto& numberExpressionMetadata =
GetExpressionMetadata(platform, exprType);
if (&numberExpressionMetadata != &badExpressionMetadata) {
return numberExpressionMetadata;
}
const auto& stringExpressionMetadata =
GetStrExpressionMetadata(platform, exprType);
return &numberExpressionMetadata != &badExpressionMetadata
? numberExpressionMetadata
: &stringExpressionMetadata != &badExpressionMetadata
? stringExpressionMetadata
: badExpressionMetadata;
if (&stringExpressionMetadata != &badExpressionMetadata) {
return stringExpressionMetadata;
}
return badExpressionMetadata;
}
const gd::ExpressionMetadata& MetadataProvider::GetObjectAnyExpressionMetadata(
const gd::Platform& platform, gd::String objectType, gd::String exprType) {
const auto& numberExpressionMetadata =
GetObjectExpressionMetadata(platform, objectType, exprType);
if (&numberExpressionMetadata != &badExpressionMetadata) {
return numberExpressionMetadata;
}
const auto& stringExpressionMetadata =
GetObjectStrExpressionMetadata(platform, objectType, exprType);
return &numberExpressionMetadata != &badExpressionMetadata
? numberExpressionMetadata
: &stringExpressionMetadata != &badExpressionMetadata
? stringExpressionMetadata
: badExpressionMetadata;
if (&stringExpressionMetadata != &badExpressionMetadata) {
return stringExpressionMetadata;
}
return badExpressionMetadata;
}
const gd::ExpressionMetadata&
@@ -380,14 +379,98 @@ MetadataProvider::GetBehaviorAnyExpressionMetadata(const gd::Platform& platform,
gd::String exprType) {
const auto& numberExpressionMetadata =
GetBehaviorExpressionMetadata(platform, autoType, exprType);
if (&numberExpressionMetadata != &badExpressionMetadata) {
return numberExpressionMetadata;
}
const auto& stringExpressionMetadata =
GetBehaviorStrExpressionMetadata(platform, autoType, exprType);
if (&stringExpressionMetadata != &badExpressionMetadata) {
return stringExpressionMetadata;
}
return badExpressionMetadata;
}
return &numberExpressionMetadata != &badExpressionMetadata
? numberExpressionMetadata
: &stringExpressionMetadata != &badExpressionMetadata
? stringExpressionMetadata
: badExpressionMetadata;
const gd::ExpressionMetadata& MetadataProvider::GetFunctionCallMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& node) {
if (!node.behaviorName.empty()) {
gd::String behaviorType =
GetTypeOfBehavior(globalObjectsContainer, objectsContainer, node.behaviorName);
return MetadataProvider::GetBehaviorAnyExpressionMetadata(
platform, behaviorType, node.functionName);
}
else if (!node.objectName.empty()) {
gd::String objectType =
GetTypeOfObject(globalObjectsContainer, objectsContainer, node.objectName);
return MetadataProvider::GetObjectAnyExpressionMetadata(
platform, objectType, node.functionName);
}
return MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
}
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
ExpressionNode& parameter) {
int parameterIndex = -1;
for (int i = 0; i < functionCall.parameters.size(); i++) {
if (functionCall.parameters.at(i).get() == &parameter) {
parameterIndex = i;
break;
}
}
if (parameterIndex < 0) {
return nullptr;
}
return MetadataProvider::GetFunctionCallParameterMetadata(
platform,
globalObjectsContainer,
objectsContainer,
functionCall,
parameterIndex);
}
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
int parameterIndex) {
// Search the parameter metadata index skipping invisible ones.
size_t visibleParameterIndex = 0;
size_t metadataParameterIndex =
ExpressionParser2::WrittenParametersFirstIndex(
functionCall.objectName, functionCall.behaviorName);
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
platform, globalObjectsContainer, objectsContainer, functionCall);
if (IsBadExpressionMetadata(metadata)) {
return nullptr;
}
// TODO use a badMetadata instead of a nullptr?
const gd::ParameterMetadata* parameterMetadata = nullptr;
while (metadataParameterIndex <
metadata.parameters.size()) {
if (!metadata.parameters[metadataParameterIndex]
.IsCodeOnly()) {
if (visibleParameterIndex == parameterIndex) {
parameterMetadata = &metadata.parameters[metadataParameterIndex];
}
visibleParameterIndex++;
}
metadataParameterIndex++;
}
const int visibleParameterCount = visibleParameterIndex;
// It can be null if there are too many parameters in the expression, this text node is
// not actually linked to a parameter expected by the function call.
return parameterMetadata;
}
MetadataProvider::~MetadataProvider() {}

View File

@@ -15,6 +15,8 @@ class ExpressionMetadata;
class ExpressionMetadata;
class Platform;
class PlatformExtension;
struct FunctionCallNode;
struct ExpressionNode;
} // namespace gd
namespace gd {
@@ -234,6 +236,26 @@ class GD_CORE_API MetadataProvider {
static const gd::ExpressionMetadata& GetObjectAnyExpressionMetadata(
const gd::Platform& platform, gd::String objectType, gd::String exprType);
static const gd::ExpressionMetadata& GetFunctionCallMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& node);
static const gd::ParameterMetadata* GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
ExpressionNode& parameter);
static const gd::ParameterMetadata* GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
int parameterIndex);
/**
* Get information about an expression from its type.
* Works for behavior expressions.

View File

@@ -8,6 +8,8 @@
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h"
#include "ParameterOptions.h"
namespace gd {} // namespace gd
namespace gd {
@@ -32,8 +34,7 @@ class GD_CORE_API MultipleInstructionMetadata {
return MultipleInstructionMetadata(expression, condition, action);
}
static MultipleInstructionMetadata WithConditionAndAction(
gd::InstructionMetadata &condition,
gd::InstructionMetadata &action) {
gd::InstructionMetadata &condition, gd::InstructionMetadata &action) {
return MultipleInstructionMetadata(condition, action);
}
@@ -80,6 +81,17 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
};
/**
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
MultipleInstructionMetadata &SetParameterExtraInfo(
const gd::String &defaultValue) {
if (expression) expression->SetParameterExtraInfo(defaultValue);
if (condition) condition->SetParameterExtraInfo(defaultValue);
if (action) action->SetParameterExtraInfo(defaultValue);
return *this;
};
/**
* \see gd::InstructionMetadata::SetParameterLongDescription
*/
@@ -116,9 +128,11 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::UseStandardOperatorParameters
* \see gd::InstructionMetadata::UseStandardRelationalOperatorParameters
*/
MultipleInstructionMetadata &UseStandardParameters(const gd::String &type) {
if (condition) condition->UseStandardRelationalOperatorParameters(type);
if (action) action->UseStandardOperatorParameters(type);
MultipleInstructionMetadata &UseStandardParameters(
const gd::String &type, const ParameterOptions &options) {
if (condition)
condition->UseStandardRelationalOperatorParameters(type, options);
if (action) action->UseStandardOperatorParameters(type, options);
return *this;
}
@@ -154,6 +168,29 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
if (expression)
return expression->GetCodeExtraInformation().GetIncludeFiles();
if (condition)
return condition->GetCodeExtraInformation().GetIncludeFiles();
if (action) return action->GetCodeExtraInformation().GetIncludeFiles();
// It can't actually happen.
throw std::logic_error("no instruction metadata");
}
/**
* \see gd::InstructionMetadata::SetPrivate
*/
MultipleInstructionMetadata &SetPrivate() {
if (expression) expression->SetPrivate();
if (condition) condition->SetPrivate();
if (action) action->SetPrivate();
return *this;
}
/**
* \see gd::InstructionMetadata::MarkAsSimple
*/

View File

@@ -14,6 +14,7 @@
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/Log.h"
namespace gd {
@@ -22,45 +23,53 @@ ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
const gd::String& fullname_,
const gd::String& description_,
const gd::String& icon24x24,
std::shared_ptr<gd::Object> blueprintObject_)
: extensionNamespace(extensionNamespace_),
blueprintObject(blueprintObject_) {
name = name_;
#if defined(GD_IDE_ONLY)
SetFullName(gd::String(fullname_));
SetDescription(gd::String(description_));
iconFilename = icon24x24;
#endif
createFunPtr =
[blueprintObject_](gd::String name) -> std::unique_ptr<gd::Object> {
if (blueprintObject_ == std::shared_ptr<gd::Object>()) {
std::cout
<< "Error: Unable to create object. Have you declared an extension "
"(or ObjectMetadata) without specifying an object as blueprint?"
<< std::endl;
std::shared_ptr<gd::ObjectConfiguration> blueprintObject_)
: ObjectMetadata(extensionNamespace_,
name_,
fullname_,
description_,
icon24x24,
[blueprintObject_]() -> std::unique_ptr<gd::ObjectConfiguration> {
if (blueprintObject_ == std::shared_ptr<gd::ObjectConfiguration>()) {
gd::LogFatalError(
"Error: Unable to create object. Have you declared an extension "
"(or ObjectMetadata) without specifying an object as blueprint?");
return nullptr;
}
std::unique_ptr<gd::Object> newObject = blueprintObject_->Clone();
newObject->SetName(name);
return newObject;
};
return blueprintObject_->Clone();
}) {
blueprintObject = blueprintObject_;
}
ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
const gd::String& name_,
const gd::String& fullname_,
const gd::String& description_,
const gd::String& icon24x24)
: ObjectMetadata(extensionNamespace_,
name_,
fullname_,
description_,
icon24x24,
[]() -> std::unique_ptr<gd::ObjectConfiguration> {
gd::LogFatalError(
"Error: Event-based objects don't have blueprint. "
"This method should not never be called.");
return nullptr;
}) {}
ObjectMetadata::ObjectMetadata(const gd::String& extensionNamespace_,
const gd::String& name_,
const gd::String& fullname_,
const gd::String& description_,
const gd::String& icon24x24,
CreateFunPtr createFunPtrP)
: extensionNamespace(extensionNamespace_) {
name = name_;
#if defined(GD_IDE_ONLY)
: name(name_),
iconFilename(icon24x24),
createFunPtr(createFunPtrP),
extensionNamespace(extensionNamespace_) {
SetFullName(gd::String(fullname_));
SetDescription(gd::String(description_));
iconFilename = icon24x24;
#endif
createFunPtr = createFunPtrP;
}
gd::InstructionMetadata& ObjectMetadata::AddCondition(

View File

@@ -13,6 +13,7 @@
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectConfiguration.h"
#include "GDCore/String.h"
namespace gd {
class InstructionMetadata;
@@ -20,7 +21,7 @@ class MultipleInstructionMetadata;
class ExpressionMetadata;
} // namespace gd
typedef std::function<std::unique_ptr<gd::Object>(gd::String name)>
typedef std::function<std::unique_ptr<gd::ObjectConfiguration>()>
CreateFunPtr;
namespace gd {
@@ -42,7 +43,17 @@ class GD_CORE_API ObjectMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& icon24x24_,
std::shared_ptr<gd::Object> blueprintObject_);
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_,
const gd::String& name_,
const gd::String& fullname_,
const gd::String& description_,
const gd::String& icon24x24_);
/**
* \brief Construct an object metadata, with a function that will be called
@@ -304,10 +315,12 @@ class GD_CORE_API ObjectMetadata {
gd::String categoryFullName;
std::set<gd::String> unsupportedBaseObjectCapabilities;
std::shared_ptr<gd::Object>
std::shared_ptr<gd::ObjectConfiguration>
blueprintObject; ///< The "blueprint" object to be copied when a new
///< object is asked. Can be null in case a creation
///< function is passed.
///< function is passed or for events based objects
///< (CustomObject are using EventBasedObject, they
///< don't need blueprints).
};
} // namespace gd

View File

@@ -10,28 +10,25 @@
namespace gd {
ParameterMetadata::ParameterMetadata() : optional(false), codeOnly(false) {}
ParameterMetadata::ParameterMetadata() : codeOnly(false) {}
void ParameterMetadata::SerializeTo(SerializerElement& element) const {
element.SetAttribute("type", type);
element.SetAttribute("supplementaryInformation", supplementaryInformation);
element.SetAttribute("optional", optional);
valueTypeMetadata.SerializeTo(element);
element.SetAttribute("description", description);
element.SetAttribute("longDescription", longDescription);
element.SetAttribute("codeOnly", codeOnly);
element.SetAttribute("defaultValue", defaultValue);
if (!longDescription.empty()) {
element.SetAttribute("longDescription", longDescription);
}
if (codeOnly) {
element.SetAttribute("codeOnly", codeOnly);
}
element.SetAttribute("name", name);
}
void ParameterMetadata::UnserializeFrom(const SerializerElement& element) {
type = element.GetStringAttribute("type");
supplementaryInformation =
element.GetStringAttribute("supplementaryInformation");
optional = element.GetBoolAttribute("optional");
valueTypeMetadata.UnserializeFrom(element);
description = element.GetStringAttribute("description");
longDescription = element.GetStringAttribute("longDescription");
codeOnly = element.GetBoolAttribute("codeOnly");
defaultValue = element.GetStringAttribute("defaultValue");
name = element.GetStringAttribute("name");
}

View File

@@ -6,15 +6,13 @@
#ifndef PARAMETER_METADATA_H
#define PARAMETER_METADATA_H
#if defined(GD_IDE_ONLY)
#include <map>
#include <memory>
#include "GDCore/String.h"
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
namespace gd {
class Project;
class Layout;
class EventsCodeGenerator;
class EventsCodeGenerationContext;
class SerializerElement;
} // namespace gd
@@ -31,17 +29,32 @@ class GD_CORE_API ParameterMetadata {
ParameterMetadata();
virtual ~ParameterMetadata(){};
/**
* \brief Return the metadata of the parameter type.
*/
gd::ValueTypeMetadata &GetValueTypeMetadata() { return valueTypeMetadata; }
/**
* \brief Set the metadata of the parameter type.
*/
ParameterMetadata &SetValueTypeMetadata(const gd::ValueTypeMetadata &valueTypeMetadata_) {
valueTypeMetadata = valueTypeMetadata_;
return *this;
}
/**
* \brief Return the type of the parameter.
* \see gd::ParameterMetadata::IsObject
* \deprecated Use gd::ValueTypeMetadata instead.
*/
const gd::String &GetType() const { return type; }
const gd::String &GetType() const { return valueTypeMetadata.GetName(); }
/**
* \brief Set the type of the parameter.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
ParameterMetadata &SetType(const gd::String &type_) {
type = type_;
valueTypeMetadata.SetName(type_);
return *this;
}
@@ -70,29 +83,33 @@ class GD_CORE_API ParameterMetadata {
* \brief Return an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
* \deprecated Use gd::ValueTypeMetadata instead.
*/
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
const gd::String &GetExtraInfo() const { return valueTypeMetadata.GetExtraInfo(); }
/**
* \brief Set an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
* \deprecated Use gd::ValueTypeMetadata instead.
*/
ParameterMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
supplementaryInformation = supplementaryInformation_;
valueTypeMetadata.SetExtraInfo(supplementaryInformation_);
return *this;
}
/**
* \brief Return true if the parameter is optional.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
bool IsOptional() const { return optional; }
bool IsOptional() const { return valueTypeMetadata.IsOptional(); }
/**
* \brief Set if the parameter is optional.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
ParameterMetadata &SetOptional(bool optional_ = true) {
optional = optional_;
valueTypeMetadata.SetOptional(optional_);
return *this;
}
@@ -127,13 +144,15 @@ class GD_CORE_API ParameterMetadata {
/**
* \brief Get the default value for the parameter.
*/
const gd::String &GetDefaultValue() const { return defaultValue; }
const gd::String &GetDefaultValue() const {
return valueTypeMetadata.GetDefaultValue();
}
/**
* \brief Set the default value, if the parameter is optional.
*/
ParameterMetadata &SetDefaultValue(const gd::String &defaultValue_) {
defaultValue = defaultValue_;
valueTypeMetadata.SetDefaultValue(defaultValue_);
return *this;
}
@@ -150,25 +169,27 @@ class GD_CORE_API ParameterMetadata {
return *this;
}
// TODO Remove these deprecated functions.
/**
* \brief Return true if the type of the parameter is "object", "objectPtr" or
* "objectList".
* \brief Return true if the type of the parameter is representing one object
* (or more, i.e: an object group).
*
* \see gd::ParameterMetadata::GetType
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static bool IsObject(const gd::String &parameterType) {
return parameterType == "object" || parameterType == "objectPtr" ||
parameterType == "objectList" ||
parameterType == "objectListWithoutPicking";
return gd::ValueTypeMetadata::IsTypeObject(parameterType);
}
/**
* \brief Return true if the type of the parameter is "behavior".
*
* \see gd::ParameterMetadata::GetType
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static bool IsBehavior(const gd::String &parameterType) {
return parameterType == "behavior";
return gd::ValueTypeMetadata::IsTypeBehavior(parameterType);
}
/**
@@ -177,31 +198,21 @@ class GD_CORE_API ParameterMetadata {
* \note If you had a new type of parameter, also add it in the IDE (
* see EventsFunctionParametersEditor, ParameterRenderingService
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static bool IsExpression(const gd::String &type,
const gd::String &parameterType) {
if (type == "number") {
return parameterType == "expression" || parameterType == "camera" ||
parameterType == "forceMultiplier";
} else if (type == "string") {
return parameterType == "string" || parameterType == "layer" ||
parameterType == "color" || parameterType == "file" ||
parameterType == "joyaxis" ||
parameterType == "stringWithSelector" ||
parameterType == "sceneName" ||
parameterType == "layerEffectName" ||
parameterType == "layerEffectParameterName" ||
parameterType == "objectEffectName" ||
parameterType == "objectEffectParameterName" ||
parameterType == "objectPointName" ||
parameterType == "objectAnimationName" ||
parameterType == "functionParameterName" ||
parameterType == "externalLayoutName";
} else if (type == "variable") {
return parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";
}
return false;
return gd::ValueTypeMetadata::IsTypeExpression(type, parameterType);
}
/**
* \brief Return the expression type from the parameter type.
* Declinations of "number" and "string" types (like "forceMultiplier" or
* "sceneName") are replaced by "number" and "string".
* \deprecated Use gd::ValueTypeMetadata instead.
*/
static const gd::String &GetExpressionValueType(const gd::String &parameterType) {
return gd::ValueTypeMetadata::GetPrimitiveValueType(parameterType);
}
/** \name Serialization
@@ -220,22 +231,17 @@ class GD_CORE_API ParameterMetadata {
// TODO: Deprecated public fields. Any direct usage should be moved to
// getter/setter.
gd::String type; ///< Parameter type
gd::String supplementaryInformation; ///< Used if needed
bool optional; ///< True if the parameter is optional
gd::String description; ///< Description shown in editor
bool codeOnly; ///< True if parameter is relative to code generation only,
///< i.e. must not be shown in editor
private:
gd::ValueTypeMetadata valueTypeMetadata; ///< Parameter type
gd::String longDescription; ///< Long description shown in the editor.
gd::String defaultValue; ///< Used as a default value in editor or if an
///< optional parameter is empty.
gd::String name; ///< The name of the parameter to be used in code
///< generation. Optional.
};
} // namespace gd
#endif
#endif // PARAMETER_METADATA_H

View File

@@ -14,7 +14,7 @@
namespace gd {
void ParameterMetadataTools::ParametersToObjectsContainer(
gd::Project& project,
const gd::Project& project,
const std::vector<gd::ParameterMetadata>& parameters,
gd::ObjectsContainer& outputObjectsContainer) {
outputObjectsContainer.GetObjects().clear();
@@ -59,13 +59,13 @@ void ParameterMetadataTools::IterateOverParameters(
const std::vector<gd::Expression>& parameters,
const std::vector<gd::ParameterMetadata>& parametersMetadata,
std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::Expression& parameterValue,
const gd::String& lastObjectName)> fn) {
IterateOverParametersWithIndex(
parameters,
parametersMetadata,
[&fn](const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
fn(parameterMetadata, parameterValue, lastObjectName);
@@ -76,17 +76,17 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
const std::vector<gd::Expression>& parameters,
const std::vector<gd::ParameterMetadata>& parametersMetadata,
std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName)> fn) {
gd::String lastObjectName = "";
for (std::size_t pNb = 0; pNb < parametersMetadata.size(); ++pNb) {
const gd::ParameterMetadata& parameterMetadata = parametersMetadata[pNb];
const gd::String& parameterValue =
const gd::Expression& parameterValue =
pNb < parameters.size() ? parameters[pNb].GetPlainString() : "";
const gd::String& parameterValueOrDefault =
parameterValue.empty() && parameterMetadata.optional
? parameterMetadata.GetDefaultValue()
const gd::Expression& parameterValueOrDefault =
parameterValue.GetPlainString().empty() && parameterMetadata.IsOptional()
? Expression(parameterMetadata.GetDefaultValue())
: parameterValue;
fn(parameterMetadata, parameterValueOrDefault, pNb, lastObjectName);
@@ -97,7 +97,7 @@ void ParameterMetadataTools::IterateOverParametersWithIndex(
// Search "lastObjectName" in the codebase for other place where this
// convention is enforced.
if (gd::ParameterMetadata::IsObject(parameterMetadata.GetType()))
lastObjectName = parameterValueOrDefault;
lastObjectName = parameterValueOrDefault.GetPlainString();
}
}

View File

@@ -19,7 +19,7 @@ namespace gd {
class GD_CORE_API ParameterMetadataTools {
public:
static void ParametersToObjectsContainer(
gd::Project& project,
const gd::Project& project,
const std::vector<gd::ParameterMetadata>& parameters,
gd::ObjectsContainer& outputObjectsContainer);
@@ -32,7 +32,7 @@ class GD_CORE_API ParameterMetadataTools {
const std::vector<gd::Expression>& parameters,
const std::vector<gd::ParameterMetadata>& parametersMetadata,
std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::Expression& parameterValue,
const gd::String& lastObjectName)> fn);
/**
@@ -44,7 +44,7 @@ class GD_CORE_API ParameterMetadataTools {
const std::vector<gd::Expression>& parameters,
const std::vector<gd::ParameterMetadata>& parametersMetadata,
std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName)> fn);

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.
*/
#ifndef PARAMETEROPTIONS_H
#define PARAMETEROPTIONS_H
#include "GDCore/String.h"
#include "ParameterMetadata.h"
namespace gd {} // namespace gd
namespace gd {
struct GD_CORE_API ParameterOptions {
gd::String description;
gd::String typeExtraInfo;
ParameterOptions &SetDescription(const gd::String &description_) {
description = description_;
return *this;
}
ParameterOptions &SetTypeExtraInfo(const gd::String &typeExtraInfo_) {
typeExtraInfo = typeExtraInfo_;
return *this;
}
static ParameterOptions MakeNewOptions() {
ParameterOptions emptyOptions;
return emptyOptions;
}
};
}
#endif // PARAMETEROPTIONS_H

View File

@@ -0,0 +1,70 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "ValueTypeMetadata.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
ValueTypeMetadata::ValueTypeMetadata() : optional(false) {}
void ValueTypeMetadata::SerializeTo(SerializerElement& element) const {
element.SetAttribute("type", name);
if (!supplementaryInformation.empty()) {
element.SetAttribute("supplementaryInformation", supplementaryInformation);
}
if (optional) {
element.SetAttribute("optional", optional);
}
if (!defaultValue.empty()) {
element.SetAttribute("defaultValue", defaultValue);
}
}
void ValueTypeMetadata::UnserializeFrom(const SerializerElement& element) {
name = element.GetStringAttribute("type");
supplementaryInformation =
element.GetStringAttribute("supplementaryInformation");
optional = element.GetBoolAttribute("optional");
defaultValue = element.GetStringAttribute("defaultValue");
}
const gd::String ValueTypeMetadata::numberType = "number";
const gd::String ValueTypeMetadata::stringType = "string";
const gd::String &ValueTypeMetadata::GetPrimitiveValueType(const gd::String &parameterType) {
if (parameterType == "number" || gd::ValueTypeMetadata::IsTypeExpression("number", parameterType)) {
return ValueTypeMetadata::numberType;
}
if (parameterType == "string" || gd::ValueTypeMetadata::IsTypeExpression("string", parameterType)) {
return ValueTypeMetadata::stringType;
}
return parameterType;
}
const gd::String ValueTypeMetadata::numberValueType = "number";
const gd::String ValueTypeMetadata::booleanValueType = "boolean";
const gd::String ValueTypeMetadata::colorValueType = "color";
const gd::String ValueTypeMetadata::choiceValueType = "stringWithSelector";
const gd::String ValueTypeMetadata::stringValueType = "string";
const gd::String &ValueTypeMetadata::ConvertPropertyTypeToValueType(
const gd::String &propertyType) {
if (propertyType == "Number") {
return numberValueType;
} else if (propertyType == "Boolean") {
return booleanValueType;
} else if (propertyType == "Color") {
return colorValueType;
} else if (propertyType == "Choice") {
return choiceValueType;
}
// For "String" or default
return stringValueType;
};
} // namespace gd

View File

@@ -0,0 +1,231 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef VALUE_TYPE_METADATA_H
#define VALUE_TYPE_METADATA_H
#include <map>
#include <memory>
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
} // namespace gd
namespace gd {
/**
* \brief Define a type for parameters of a function (action, condition or
* expression) or the returned value of an expression.
*
* \see gd::EventsFunction
* \ingroup Events
*/
class GD_CORE_API ValueTypeMetadata {
public:
ValueTypeMetadata();
virtual ~ValueTypeMetadata(){};
/**
* \brief Return the string representation of the type.
*/
const gd::String &GetName() const { return name; }
/**
* \brief Set the string representation of the type.
*/
ValueTypeMetadata &SetName(const gd::String &name_) {
name = name_;
return *this;
}
/**
* \brief Return an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
*/
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
/**
* \brief Set an optional additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter).
*/
ValueTypeMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
supplementaryInformation = supplementaryInformation_;
return *this;
}
/**
* \brief Return true if the parameter is optional.
*/
bool IsOptional() const { return optional; }
/**
* \brief Set if the parameter is optional.
*/
ValueTypeMetadata &SetOptional(bool optional_ = true) {
optional = optional_;
return *this;
}
/**
* \brief Get the default value for the parameter.
*/
const gd::String &GetDefaultValue() const { return defaultValue; }
/**
* \brief Set the default value, if the parameter is optional.
*/
ValueTypeMetadata &SetDefaultValue(const gd::String &defaultValue_) {
defaultValue = defaultValue_;
return *this;
}
/**
* \brief Return true if the type is defined.
*/
bool IsDefined() const {
return !name.empty();
}
/**
* \brief Return true if the type is representing one object
* (or more, i.e: an object group).
*/
bool IsObject() const {
return gd::ValueTypeMetadata::IsTypeObject(name);
}
/**
* \brief Return true if the type is "behavior".
*/
bool IsBehavior() const {
return gd::ValueTypeMetadata::IsTypeBehavior(name);
}
/**
* \brief Return true if the type is an expression of the
* given type.
*/
bool IsNumber() const {
return gd::ValueTypeMetadata::IsTypeExpression("number", name);
}
/**
* \brief Return true if the type is a string.
*/
bool IsString() const {
return gd::ValueTypeMetadata::IsTypeExpression("string", name);
}
/**
* \brief Return true if the type of the parameter is a number.
* \note If you had a new type of parameter, also add it in the IDE (
* see EventsFunctionParametersEditor, ParameterRenderingService
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
*/
bool IsVariable() const {
return gd::ValueTypeMetadata::IsTypeExpression("variable", name);
}
/**
* \brief Return true if the type is representing one object
* (or more, i.e: an object group).
*/
static bool IsTypeObject(const gd::String &parameterType) {
return parameterType == "object" || parameterType == "objectPtr" ||
parameterType == "objectList" ||
parameterType == "objectListOrEmptyIfJustDeclared" ||
parameterType == "objectListOrEmptyWithoutPicking";
}
/**
* \brief Return true if the type is "behavior".
*/
static bool IsTypeBehavior(const gd::String &parameterType) {
return parameterType == "behavior";
}
/**
* \brief Return true if the type is an expression of the given type.
* \note If you are adding a new type of parameter, also add it in the IDE (
* see EventsFunctionParametersEditor, ParameterRenderingService
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
*/
static bool IsTypeExpression(const gd::String &type,
const gd::String &parameterType) {
if (type == "number") {
return parameterType == "number" || parameterType == "expression" ||
parameterType == "camera" || parameterType == "forceMultiplier";
} else if (type == "string") {
return parameterType == "string" || parameterType == "layer" ||
parameterType == "color" || parameterType == "file" ||
parameterType == "joyaxis" ||
parameterType == "stringWithSelector" ||
parameterType == "sceneName" ||
parameterType == "layerEffectName" ||
parameterType == "layerEffectParameterName" ||
parameterType == "objectEffectName" ||
parameterType == "objectEffectParameterName" ||
parameterType == "objectPointName" ||
parameterType == "objectAnimationName" ||
parameterType == "functionParameterName" ||
parameterType == "externalLayoutName" ||
parameterType == "leaderboardId" ||
parameterType == "identifier";
} else if (type == "variable") {
return parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";
}
return false;
}
/**
* \brief Return the expression type from the parameter type.
* Declinations of "number" and "string" types (like "forceMultiplier" or
* "sceneName") are replaced by "number" and "string".
*/
static const gd::String &GetPrimitiveValueType(const gd::String &parameterType);
static const gd::String numberType;
static const gd::String stringType;
/**
* \brief Return the ValueTypeMetadata name for a property type.
* \see gd::PropertyDescriptor
*/
static const gd::String &ConvertPropertyTypeToValueType(const gd::String &propertyType);
/** \name Serialization
*/
///@{
/**
* \brief Serialize the ParameterMetadata to the specified element
*/
void SerializeTo(gd::SerializerElement &element) const;
/**
* \brief Load the ParameterMetadata from the specified element
*/
void UnserializeFrom(const gd::SerializerElement &element);
///@}
private:
gd::String name; ///< Parameter type
gd::String supplementaryInformation; ///< Used if needed
bool optional; ///< True if the parameter is optional
gd::String defaultValue; ///< Used as a default value in editor or if an
///< optional parameter is empty.
static const gd::String numberValueType;
static const gd::String booleanValueType;
static const gd::String colorValueType;
static const gd::String choiceValueType;
static const gd::String stringValueType;
};
} // namespace gd
#endif // VALUE_TYPE_METADATA_H

View File

@@ -7,7 +7,9 @@
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectConfiguration.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
using namespace std;
@@ -91,24 +93,22 @@ std::shared_ptr<gd::PlatformExtension> Platform::GetExtension(
return std::shared_ptr<gd::PlatformExtension>();
}
std::unique_ptr<gd::Object> Platform::CreateObject(
gd::String type, const gd::String& name) const {
std::unique_ptr<gd::ObjectConfiguration> Platform::CreateObjectConfiguration(
gd::String type) const {
if (creationFunctionTable.find(type) == creationFunctionTable.end()) {
std::cout << "Tried to create an object with an unknown type: " << type
<< " for platform " << GetName() << "!" << std::endl;
gd::LogWarning("Tried to create an object with an unknown type: " + type
+ " for platform " + GetName() + "!");
type = "";
if (creationFunctionTable.find("") == creationFunctionTable.end()) {
std::cout << "Unable to create a Base object!" << std::endl;
gd::LogError("Unable to create a Base object!");
return nullptr;
}
}
// Create a new object with the type we want.
std::unique_ptr<gd::Object> object =
(creationFunctionTable.find(type)->second)(name);
object->SetType(type);
return std::unique_ptr<gd::Object>(std::move(object));
auto objectConfiguration = (creationFunctionTable.find(type)->second)();
objectConfiguration->SetType(type);
return objectConfiguration;
}
#if defined(GD_IDE_ONLY)

View File

@@ -16,6 +16,7 @@ namespace gd {
class InstructionsMetadataHolder;
class Project;
class Object;
class ObjectConfiguration;
class Behavior;
class BehaviorMetadata;
class ObjectMetadata;
@@ -26,7 +27,7 @@ class LayoutEditorCanvas;
class ProjectExporter;
} // namespace gd
typedef std::function<std::unique_ptr<gd::Object>(gd::String name)>
typedef std::function<std::unique_ptr<gd::ObjectConfiguration>()>
CreateFunPtr;
#undef CreateEvent
@@ -146,8 +147,8 @@ class GD_CORE_API Platform {
/**
* \brief Create an object of given type with the specified name.
*/
std::unique_ptr<gd::Object> CreateObject(gd::String type,
const gd::String& name) const;
std::unique_ptr<gd::ObjectConfiguration> CreateObjectConfiguration(
gd::String type) const;
/**
* \brief Create an event of given type

View File

@@ -18,19 +18,18 @@
#include "GDCore/Extensions/Platform.h"
#include "GDCore/IDE/PlatformManager.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/ObjectConfiguration.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Tools/Localization.h"
namespace gd {
#if defined(GD_IDE_ONLY)
std::map<gd::String, gd::InstructionMetadata>
PlatformExtension::badConditionsMetadata;
std::map<gd::String, gd::InstructionMetadata>
PlatformExtension::badActionsMetadata;
std::map<gd::String, gd::ExpressionMetadata>
PlatformExtension::badExpressionsMetadata;
#endif
gd::InstructionMetadata& PlatformExtension::AddCondition(
const gd::String& name,
@@ -40,7 +39,6 @@ gd::InstructionMetadata& PlatformExtension::AddCondition(
const gd::String& group,
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace = GetNameSpace() + name;
conditionsInfos[nameWithNamespace] = InstructionMetadata(GetNameSpace(),
nameWithNamespace,
@@ -52,7 +50,6 @@ gd::InstructionMetadata& PlatformExtension::AddCondition(
smallicon)
.SetHelpPath(GetHelpPath());
return conditionsInfos[nameWithNamespace];
#endif
}
gd::InstructionMetadata& PlatformExtension::AddAction(
@@ -63,7 +60,6 @@ gd::InstructionMetadata& PlatformExtension::AddAction(
const gd::String& group,
const gd::String& icon,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace = GetNameSpace() + name;
actionsInfos[nameWithNamespace] = InstructionMetadata(GetNameSpace(),
nameWithNamespace,
@@ -75,7 +71,6 @@ gd::InstructionMetadata& PlatformExtension::AddAction(
smallicon)
.SetHelpPath(GetHelpPath());
return actionsInfos[nameWithNamespace];
#endif
}
gd::ExpressionMetadata& PlatformExtension::AddExpression(
@@ -84,7 +79,6 @@ gd::ExpressionMetadata& PlatformExtension::AddExpression(
const gd::String& description,
const gd::String& group,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace = GetNameSpace() + name;
expressionsInfos[nameWithNamespace] = ExpressionMetadata("number",
GetNameSpace(),
@@ -95,7 +89,6 @@ gd::ExpressionMetadata& PlatformExtension::AddExpression(
smallicon)
.SetHelpPath(GetHelpPath());
return expressionsInfos[nameWithNamespace];
#endif
}
gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
@@ -104,7 +97,6 @@ gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
const gd::String& description,
const gd::String& group,
const gd::String& smallicon) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace = GetNameSpace() + name;
strExpressionsInfos[nameWithNamespace] = ExpressionMetadata("string",
GetNameSpace(),
@@ -115,7 +107,6 @@ gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
smallicon)
.SetHelpPath(GetHelpPath());
return strExpressionsInfos[nameWithNamespace];
#endif
}
gd::MultipleInstructionMetadata PlatformExtension::AddExpressionAndCondition(
@@ -219,19 +210,17 @@ PlatformExtension::AddExpressionAndConditionAndAction(
expression, condition, action);
}
#if defined(GD_IDE_ONLY)
gd::DependencyMetadata& PlatformExtension::AddDependency() {
extensionDependenciesMetadata.push_back(DependencyMetadata());
return extensionDependenciesMetadata.back();
}
#endif
gd::ObjectMetadata& PlatformExtension::AddObject(
const gd::String& name,
const gd::String& fullname,
const gd::String& description,
const gd::String& icon24x24,
std::shared_ptr<gd::Object> instance) {
std::shared_ptr<gd::ObjectConfiguration> instance) {
gd::String nameWithNamespace = GetNameSpace() + name;
objectsInfos[nameWithNamespace] = ObjectMetadata(GetNameSpace(),
nameWithNamespace,
@@ -244,6 +233,21 @@ gd::ObjectMetadata& PlatformExtension::AddObject(
return objectsInfos[nameWithNamespace];
}
gd::ObjectMetadata& PlatformExtension::AddEventsBasedObject(
const gd::String& name,
const gd::String& fullname,
const gd::String& description,
const gd::String& icon24x24) {
gd::String nameWithNamespace = GetNameSpace() + name;
objectsInfos[nameWithNamespace] = ObjectMetadata(GetNameSpace(),
nameWithNamespace,
fullname,
description,
icon24x24)
.SetHelpPath(GetHelpPath());
return objectsInfos[nameWithNamespace];
}
gd::BehaviorMetadata& PlatformExtension::AddBehavior(
const gd::String& name,
const gd::String& fullname,
@@ -269,6 +273,25 @@ gd::BehaviorMetadata& PlatformExtension::AddBehavior(
return behaviorsInfo[nameWithNamespace];
}
gd::BehaviorMetadata& PlatformExtension::AddEventsBasedBehavior(
const gd::String& name,
const gd::String& fullname,
const gd::String& description,
const gd::String& group,
const gd::String& icon24x24) {
gd::String nameWithNamespace = GetNameSpace() + name;
behaviorsInfo[nameWithNamespace] = BehaviorMetadata(GetNameSpace(),
nameWithNamespace,
fullname,
// Default name is the name
name,
description,
group,
icon24x24)
.SetHelpPath(GetHelpPath());
return behaviorsInfo[nameWithNamespace];
}
gd::EffectMetadata& PlatformExtension::AddEffect(const gd::String& name) {
gd::String nameWithNamespace = GetNameSpace() + name;
effectsMetadata[nameWithNamespace] = EffectMetadata(nameWithNamespace);
@@ -282,7 +305,6 @@ gd::EventMetadata& PlatformExtension::AddEvent(
const gd::String& group_,
const gd::String& smallicon_,
std::shared_ptr<gd::BaseEvent> instance_) {
#if defined(GD_IDE_ONLY)
gd::String nameWithNamespace = GetNameSpace() + name_;
eventsInfos[nameWithNamespace] = gd::EventMetadata(nameWithNamespace,
fullname_,
@@ -291,7 +313,6 @@ gd::EventMetadata& PlatformExtension::AddEvent(
smallicon_,
instance_);
return eventsInfos[nameWithNamespace];
#endif
}
PlatformExtension& PlatformExtension::SetExtensionInformation(
@@ -346,6 +367,11 @@ gd::BehaviorMetadata& PlatformExtension::GetBehaviorMetadata(
return badBehaviorMetadata;
}
bool PlatformExtension::HasBehavior(
const gd::String& behaviorType) const {
return behaviorsInfo.find(behaviorType) != behaviorsInfo.end();
}
gd::EffectMetadata& PlatformExtension::GetEffectMetadata(
const gd::String& effectName) {
if (effectsMetadata.find(effectName) != effectsMetadata.end())
@@ -366,8 +392,6 @@ std::vector<gd::String> PlatformExtension::GetBehaviorsTypes() const {
return behaviors;
}
#if defined(GD_IDE_ONLY)
gd::InstructionMetadata& PlatformExtension::AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName) {
gd::String newNameWithNamespace = GetNameSpace() + newActionName;
@@ -375,7 +399,7 @@ gd::InstructionMetadata& PlatformExtension::AddDuplicatedAction(
auto copiedAction = actionsInfos.find(copiedNameWithNamespace);
if (copiedAction == actionsInfos.end()) {
gd::LogWarning("Could not find an action with name " +
gd::LogError("Could not find an action with name " +
copiedNameWithNamespace + " to copy.");
} else {
actionsInfos[newNameWithNamespace] = copiedAction->second;
@@ -395,7 +419,7 @@ gd::InstructionMetadata& PlatformExtension::AddDuplicatedCondition(
auto copiedCondition = conditionsInfos.find(copiedNameWithNamespace);
if (copiedCondition == conditionsInfos.end()) {
gd::LogWarning("Could not find a condition with name " +
gd::LogError("Could not find a condition with name " +
copiedNameWithNamespace + " to copy.");
} else {
conditionsInfos[newNameWithNamespace] = copiedCondition->second;
@@ -412,7 +436,7 @@ gd::ExpressionMetadata& PlatformExtension::AddDuplicatedExpression(
auto copiedExpression = expressionsInfos.find(copiedNameWithNamespace);
if (copiedExpression == expressionsInfos.end()) {
gd::LogWarning("Could not find an expression with name " +
gd::LogError("Could not find an expression with name " +
copiedNameWithNamespace + " to copy.");
} else {
expressionsInfos[newNameWithNamespace] = copiedExpression->second;
@@ -429,7 +453,7 @@ gd::ExpressionMetadata& PlatformExtension::AddDuplicatedStrExpression(
auto copiedExpression = strExpressionsInfos.find(copiedNameWithNamespace);
if (copiedExpression == strExpressionsInfos.end()) {
gd::LogWarning("Could not find a string expression with name " +
gd::LogError("Could not find a string expression with name " +
copiedNameWithNamespace + " to copy.");
} else {
strExpressionsInfos[newNameWithNamespace] = copiedExpression->second;
@@ -546,7 +570,6 @@ gd::BaseEventSPtr PlatformExtension::CreateEvent(
return std::shared_ptr<gd::BaseEvent>();
}
#endif
CreateFunPtr PlatformExtension::GetObjectCreationFunctionPtr(
const gd::String& objectType) const {
@@ -625,7 +648,6 @@ bool PlatformExtension::IsBuiltin() const {
builtinExtensions.end();
}
#if defined(GD_IDE_ONLY)
void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
for (std::map<gd::String, gd::InstructionMetadata>::iterator it =
GetAllActions().begin();
@@ -770,7 +792,40 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
++it;
}
}
#endif
gd::String
PlatformExtension::GetEventsFunctionFullType(const gd::String &extensionName,
const gd::String &functionName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + functionName;
}
gd::String PlatformExtension::GetBehaviorEventsFunctionFullType(
const gd::String &extensionName, const gd::String &behaviorName,
const gd::String &functionName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + behaviorName + separator + functionName;
}
gd::String
PlatformExtension::GetBehaviorFullType(const gd::String &extensionName,
const gd::String &behaviorName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + behaviorName;
}
gd::String PlatformExtension::GetObjectEventsFunctionFullType(
const gd::String &extensionName, const gd::String &objectName,
const gd::String &functionName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + objectName + separator + functionName;
}
gd::String PlatformExtension::GetObjectFullType(const gd::String &extensionName,
const gd::String &objectName) {
const auto &separator = GetNamespaceSeparator();
return extensionName + separator + objectName;
}
PlatformExtension::PlatformExtension()
: deprecated(false), category(_("General")) {}

View File

@@ -37,9 +37,10 @@ class ArbitraryResourceWorker;
class BehaviorsSharedData;
class Behavior;
class Object;
class ObjectConfiguration;
} // namespace gd
typedef std::function<std::unique_ptr<gd::Object>(gd::String name)>
typedef std::function<std::unique_ptr<gd::ObjectConfiguration>()>
CreateFunPtr;
namespace gd {
@@ -242,7 +243,21 @@ class GD_CORE_API PlatformExtension {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& icon_,
std::shared_ptr<gd::Object> instance);
std::shared_ptr<gd::ObjectConfiguration> instance);
/**
* \brief Declare a new events based object as being part of the extension.
*
* \param name The name of the object
* \param fullname The user friendly name of the object
* \param description The user friendly description of the object
* \param icon The icon of the object.
*/
gd::ObjectMetadata& AddEventsBasedObject(
const gd::String& name_,
const gd::String& fullname_,
const gd::String& description_,
const gd::String& icon_);
/**
* \brief Declare a new behavior as being part of the extension.
@@ -267,6 +282,21 @@ class GD_CORE_API PlatformExtension {
std::shared_ptr<gd::Behavior> instance,
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance);
/**
* \brief Declare a new events based behavior as being part of the extension.
*
* \param name The name of the behavior
* \param fullname The user friendly name of the behavior
* \param description The user friendly description of the behavior
* \param icon The icon of the behavior.
*/
gd::BehaviorMetadata& AddEventsBasedBehavior(
const gd::String& name_,
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& icon_);
/**
* \brief Declare a new effect as being part of the extension.
* \param name The internal name of the effect (also called effect type).
@@ -467,6 +497,12 @@ class GD_CORE_API PlatformExtension {
*/
BehaviorMetadata& GetBehaviorMetadata(const gd::String& behaviorType);
/**
* \brief Return true if the extension contains a behavior associated to \a
* behaviorType
*/
bool HasBehavior(const gd::String& behaviorType) const;
/**
* \brief Return the metadata for the effect with the given name.
*/
@@ -584,7 +620,26 @@ class GD_CORE_API PlatformExtension {
*/
static gd::String GetNamespaceSeparator() { return "::"; }
private:
static gd::String GetEventsFunctionFullType(const gd::String &extensionName,
const gd::String &functionName);
static gd::String
GetBehaviorEventsFunctionFullType(const gd::String &extensionName,
const gd::String &behaviorName,
const gd::String &functionName);
static gd::String GetBehaviorFullType(const gd::String &extensionName,
const gd::String &behaviorName);
static gd::String
GetObjectEventsFunctionFullType(const gd::String &extensionName,
const gd::String &objectName,
const gd::String &functionName);
static gd::String GetObjectFullType(const gd::String &extensionName,
const gd::String &objectName);
private:
/**
* Set the namespace (the string all actions/conditions/expressions start
* with).

View File

@@ -25,8 +25,8 @@ gd::ObjectMetadata& PlatformExtension::AddObject(const gd::String& name,
fullname,
description,
icon24x24,
[](gd::String name) -> std::unique_ptr<gd::Object> {
return gd::make_unique<T>(name);
[]() -> std::unique_ptr<gd::ObjectConfiguration> {
return gd::make_unique<T>();
})
.SetHelpPath(GetHelpPath());

View File

@@ -3,7 +3,6 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef SCENECANVASSETTINGS_H
#define SCENECANVASSETTINGS_H
#include "GDCore/String.h"
@@ -43,4 +42,3 @@ private:
} // namespace gd
#endif // SCENECANVASSETTINGS_H
#endif

View File

@@ -73,4 +73,54 @@ bool ArbitraryEventsWorker::VisitInstruction(gd::Instruction& instruction,
ArbitraryEventsWorkerWithContext::~ArbitraryEventsWorkerWithContext() {}
ReadOnlyArbitraryEventsWorker::~ReadOnlyArbitraryEventsWorker() {}
void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events) {
DoVisitEventList(events);
for (std::size_t i = 0; i < events.size(); ++i) {
VisitEvent(events[i]);
if (events[i].CanHaveSubEvents()) {
VisitEventList(events[i].GetSubEvents());
}
}
}
void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
DoVisitEvent(event);
const vector<const gd::InstructionsList*> conditionsVectors =
event.GetAllConditionsVectors();
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
VisitInstructionList(*conditionsVectors[j], true);
}
const vector<const gd::InstructionsList*> actionsVectors = event.GetAllActionsVectors();
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
VisitInstructionList(*actionsVectors[j], false);
}
}
void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
const gd::InstructionsList& instructions, bool areConditions) {
DoVisitInstructionList(instructions, areConditions);
for (std::size_t i = 0; i < instructions.size(); ++i) {
VisitInstruction(instructions[i], areConditions);
if (!instructions[i].GetSubInstructions().empty()) {
VisitInstructionList(instructions[i].GetSubInstructions(),
areConditions);
}
}
}
void ReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& instruction,
bool isCondition) {
DoVisitInstruction(instruction, isCondition);
}
ReadOnlyArbitraryEventsWorkerWithContext::~ReadOnlyArbitraryEventsWorkerWithContext() {}
} // namespace gd

View File

@@ -121,6 +121,101 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
const gd::ObjectsContainer* currentObjectsContainer;
};
/**
* \brief ReadOnlyArbitraryEventsWorker is an abstract class used to browse events (and
* instructions). It can be used to implement autocompletion for example.
*
* \see gd::ReadOnlyArbitraryEventsWorkerWithContext
*
* \ingroup IDE
*/
class GD_CORE_API ReadOnlyArbitraryEventsWorker {
public:
ReadOnlyArbitraryEventsWorker(){};
virtual ~ReadOnlyArbitraryEventsWorker();
/**
* \brief Launch the worker on the specified events list.
*/
void Launch(const gd::EventsList& events) { VisitEventList(events); };
private:
void VisitEventList(const gd::EventsList& events);
void VisitEvent(const gd::BaseEvent& event);
void VisitInstructionList(const gd::InstructionsList& instructions,
bool areConditions);
void VisitInstruction(const gd::Instruction& instruction, bool isCondition);
/**
* Called to do some work on an event list.
*/
virtual void DoVisitEventList(const gd::EventsList& events){};
/**
* Called to do some work on an event
*/
virtual void DoVisitEvent(const gd::BaseEvent& event) {};
/**
* Called to do some work on an instruction list
*/
virtual void DoVisitInstructionList(const gd::InstructionsList& instructions,
bool areConditions){};
/**
* Called to do some work on an instruction.
*/
virtual void DoVisitInstruction(const gd::Instruction& instruction,
bool isCondition) {};
};
/**
* \brief An events worker that will know about the context (the objects
* container). Useful for workers working on expressions notably.
*
* \see gd::ReadOnlyArbitraryEventsWorker
*
* \ingroup IDE
*/
class GD_CORE_API ReadOnlyArbitraryEventsWorkerWithContext
: public ReadOnlyArbitraryEventsWorker {
public:
ReadOnlyArbitraryEventsWorkerWithContext()
: currentGlobalObjectsContainer(nullptr),
currentObjectsContainer(nullptr){};
virtual ~ReadOnlyArbitraryEventsWorkerWithContext();
/**
* \brief Launch the worker on the specified events list,
* giving the objects container on which the events are applying to.
*/
void Launch(const gd::EventsList& events,
const gd::ObjectsContainer& globalObjectsContainer_,
const gd::ObjectsContainer& objectsContainer_) {
currentGlobalObjectsContainer = &globalObjectsContainer_;
currentObjectsContainer = &objectsContainer_;
ReadOnlyArbitraryEventsWorker::Launch(events);
};
void Launch(gd::EventsList& events) = delete;
protected:
const gd::ObjectsContainer& GetGlobalObjectsContainer() {
// Pointers are guaranteed to be not nullptr after
// Launch was called.
return *currentGlobalObjectsContainer;
};
const gd::ObjectsContainer& GetObjectsContainer() {
// Pointers are guaranteed to be not nullptr after
// Launch was called.
return *currentObjectsContainer;
};
private:
const gd::ObjectsContainer* currentGlobalObjectsContainer;
const gd::ObjectsContainer* currentObjectsContainer;
};
} // namespace gd
#endif // GDCORE_ARBITRARYEVENTSWORKER_H

View File

@@ -0,0 +1,25 @@
#include "BehaviorTypeRenamer.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
namespace gd {
void BehaviorTypeRenamer::DoVisitObject(gd::Object& object) {
};
void BehaviorTypeRenamer::DoVisitBehavior(gd::Behavior& behavior) {
if (behavior.GetTypeName() == oldType) {
behavior.SetTypeName(newType);
}
};
BehaviorTypeRenamer::~BehaviorTypeRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,43 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_BEHAVIORTYPERENAMER_H
#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
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_){};
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;
};
}; // namespace gd
#endif // GDCORE_BEHAVIORTYPERENAMER_H

View File

@@ -0,0 +1,24 @@
#include "CustomObjectTypeRenamer.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
namespace gd {
void CustomObjectTypeRenamer::DoVisitObject(gd::Object& object) {
if (object.GetType() == oldType) {
object.SetType(newType);
}
};
void CustomObjectTypeRenamer::DoVisitBehavior(gd::Behavior& behavior) {};
CustomObjectTypeRenamer::~CustomObjectTypeRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,43 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_CUSTOMOBJECTTYPERENAMER_H
#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
namespace gd {
class GD_CORE_API CustomObjectTypeRenamer : public ArbitraryObjectsWorker {
public:
CustomObjectTypeRenamer(const gd::Project& project_,
const gd::String& oldType_,
const gd::String& newType_)
: project(project_), 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;
};
}; // namespace gd
#endif // GDCORE_CUSTOMOBJECTTYPERENAMER_H

View File

@@ -11,7 +11,6 @@
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
@@ -118,27 +117,20 @@ bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
instruction.GetParameters(),
metadata.GetParameters(),
[&](const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::Expression& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
const gd::String& type = parameterMetadata.type;
const gd::String& type = parameterMetadata.GetType();
if (gd::ParameterMetadata::IsBehavior(type)) {
if (lastObjectName == objectName) {
if (parameterValue == oldBehaviorName) {
if (parameterValue.GetPlainString() == oldBehaviorName) {
instruction.SetParameter(parameterIndex,
gd::Expression(newBehaviorName));
}
}
} else {
gd::ExpressionParser2 parser(
platform, GetGlobalObjectsContainer(), GetObjectsContainer());
auto node =
gd::ParameterMetadata::IsExpression("number", type)
? parser.ParseExpression("number", parameterValue)
: (gd::ParameterMetadata::IsExpression("string", type)
? parser.ParseExpression("string", parameterValue)
: std::unique_ptr<gd::ExpressionNode>());
auto node = parameterValue.GetRootNode();
if (node) {
ExpressionBehaviorRenamer renamer(GetGlobalObjectsContainer(),
GetObjectsContainer(),

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