Compare commits

...

316 Commits

Author SHA1 Message Date
Clément Pasteau
3476c043f8 wip not working 2023-02-21 14:40:21 +01:00
AlexandreS
e85229d38e Drag project manager items using icon and not label (#4988) 2023-02-20 16:51:54 +01:00
Clément Pasteau
e7381a7229 Simplify slug management so that is reads the cache value (#4973)
Do not show in changelog
2023-02-20 15:20:04 +01:00
D8H
257ba78486 Allow event-based objects to define a rotation center point (#4910)
* It will allow sliders to work vertically.
2023-02-20 11:55:53 +01:00
Aurélien Vivet
fb3d821368 Add a value range (#4877)
Don't show in changelog
2023-02-20 11:45:15 +01:00
Aurélien Vivet
a5068d8fcf Add a line about Silver plan unlocking the watermark & GD logo when the game loads. (#4979) 2023-02-20 10:58:22 +01:00
Florian Rival
d20b3228cf Fix Debugger crashing when GDevelop logo was enabled (#4980) 2023-02-19 19:29:06 +01:00
D8H
aae54ef331 Link the extension installation page on every extension page (#4974) 2023-02-18 16:07:20 +01:00
AlexandreS
caa5105651 Improve some things on mobile (#4971)
Don't show in changelog
2023-02-17 12:50:07 +01:00
Florian Rival
5eccdde332 Allow authentication to player accounts using an iframe in some exceptional cases (#4968)
Don't show in changelog
2023-02-17 11:49:23 +01:00
AlexandreS
c34d758ccf Fix display of Social network share buttons on mobile (#4969)
Don't show in changelog
2023-02-16 18:29:59 +01:00
AlexandreS
4e57d6aee9 Do not display importing resources dialog full screen (#4967)
Don't show in changelog
2023-02-16 16:52:00 +01:00
AlexandreS
74d208f736 Allow export dialog to only have the online web export (#4965)
Don't show in changelog
2023-02-16 16:19:10 +01:00
github-actions[bot]
d88b76becf Update translations [skip ci] (#4938)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-02-16 15:49:51 +01:00
D8H
4a0e2481e6 Fix author chips wrapping on small screens (#4943) 2023-02-16 12:59:25 +01:00
D8H
612b041da4 Add tags for the code size and difficulty level of examples (#4958) 2023-02-16 11:16:56 +01:00
AlexandreS
3df7cd8e80 Add check on project file content existence at opening (#4961)
Don't show in changelog
2023-02-16 11:01:32 +01:00
AlexandreS
7ba96ed0ab Use safe area only on portrait (#4962)
Don't show in changelog
2023-02-15 19:17:18 +01:00
AlexandreS
689cd14947 Use device orientation to define default scene editor layout (#4960) 2023-02-15 17:55:10 +01:00
AlexandreS
de50dc7967 Use safe area to correctly display a few elements (#4959)
Don't show in changelog
2023-02-15 15:39:58 +01:00
Florian Rival
1aa2afaf85 Fix "Insert new..." menu option not doing anything if objects list was closed 2023-02-15 11:58:28 +01:00
Clément Pasteau
9120a52a08 Rename Liluo.io to gd.games (#4954) 2023-02-14 17:42:46 +01:00
AlexandreS
b0ffaebe91 Fix subscription diamond svg not displaying on Safari and Firefox (#4948)
Don't show in changelog
2023-02-14 16:09:34 +01:00
D8H
64a4a0b3a1 Add a tool to count the number of instructions of examples (#4952)
* Only show in "Internal changes" changelog
2023-02-14 15:52:53 +01:00
AlexandreS
cdfd7a7ab1 Autotranslate improvements (#4951)
Don't show in changelog
2023-02-14 14:08:57 +01:00
Florian Rival
a944ac43db Update README
Don't show in changelog
2023-02-14 12:40:59 +01:00
Clément Pasteau
b7a1a96e7b Update storybook urls (#4949)
Do not show in changelog
2023-02-14 09:54:02 +01:00
Clément Pasteau
29d71796cc Remove unused ravenjs (sentry) (#4940)
Do not show in changelog
2023-02-13 16:41:28 +01:00
AlexandreS
78a1361897 Use form in account related actions to simplify mobile experience (#4917)
Don't show in changelog
2023-02-13 14:27:05 +01:00
AlexandreS
e340784ad6 Prevent google translate issue (#4937)
Don't show in changelog
2023-02-13 14:22:08 +01:00
github-actions[bot]
511466f0b8 Update translations [skip ci] (#4909)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-02-13 10:39:08 +01:00
Florian Rival
3f4e372acb Fix check of subscriptions
Don't show in changelog
2023-02-10 17:01:18 +01:00
D8H
a73a92d748 Fix tile map loading for collision mask objects (#4916) 2023-02-10 15:52:06 +01:00
AlexandreS
6e131d8a17 Display asset pack categories in asset store homepage (#4905) 2023-02-10 14:57:24 +01:00
D8H
9ac4c021e0 Fix the number parameter color in the events (#4915) 2023-02-10 11:37:38 +01:00
AlexandreS
a1fbf91ac7 Add Eye icon to switch password visibility (#4914) 2023-02-09 17:16:13 +01:00
Clément Pasteau
3f8d01e25e Improve subscription messages when a redeem code has been used (#4912) 2023-02-09 16:56:54 +01:00
AlexandreS
03b4170d74 Fix resource store display for extension icon (#4913)
Don't show in changelog
2023-02-09 15:34:13 +01:00
AlexandreS
0146ad9c38 Add error boundary at the app level (#4911)
Don't show in changelog
2023-02-09 12:19:26 +01:00
Clément Pasteau
fbb23f86cd Rename and add more actions, conditions and expressions to manipulate array variables (#4904) 2023-02-08 16:53:57 +01:00
github-actions[bot]
1fdaeea4f8 Update translations [skip ci] (#4893)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-08 11:21:06 +01:00
Clément Pasteau
32b97f2c40 Improve search accuracy in the app (instructions, examples, objects, tags) (#4906)
* Use tokenized search to improve search with multiple words looking into multiple keys (ex: name & description)
2023-02-08 09:41:27 +01:00
AlexandreS
d61f8336a8 Fix firebase extension tests (#4907)
Don't show in changelog
2023-02-07 17:11:16 +01:00
Clément Pasteau
3448cd57fe Allow showing an alertMessage without an icon (#4903) 2023-02-06 16:41:55 +01:00
Clément Pasteau
b7333612aa Prompt for email verification when logging in or signing up (#4898) 2023-02-06 11:45:32 +01:00
Aurélien Vivet
de82182b37 fix typo (#4899)
Do not show in changelog
2023-02-06 08:47:53 +01:00
Clément Pasteau
a8177b0e6f Upgrade electron-builder (#4892)
* This should fix the auto-updater uninstalling GDevelop without re-installing it on Windows, if installed "for all users"
2023-02-03 13:48:43 +01:00
AlexandreS
9716ff14ed Fix: Use correct default values for effects with color parameters (#4891) 2023-02-03 12:06:26 +01:00
Clément Pasteau
f0e1d7a6d9 Bump to 5.1.157 (#4886)
Do not show in changelog
2023-02-02 15:48:45 +01:00
github-actions[bot]
dd89562405 Update translations [skip ci] (#4887)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-02 15:48:29 +01:00
Clément Pasteau
f0e56c4513 Update tutorials for offline use (#4888)
Do not show in changelog
2023-02-02 15:47:59 +01:00
Clément Pasteau
ad2ea0abb8 Improve search accuracy for conditions and actions (#4885) 2023-02-02 15:38:42 +01:00
D8H
7ff71ea11f Make the button to open condition/action extensions easier to see (#4884) 2023-02-02 15:35:01 +01:00
github-actions[bot]
cd1d82f7ee Update translations [skip ci] (#4839)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-02-02 15:34:09 +01:00
Clément Pasteau
0724b7d113 Move save to toolbar (#4883)
Do not show in changelog
2023-02-02 15:26:26 +01:00
Clément Pasteau
c58ea73631 Upgrade AdMob extension (#4881)
* Updated internal Google Ads SDK version
* Added "App open" ads
* Added "Rewarded Interstitial" ads
2023-02-02 13:03:41 +01:00
Arthur Pacaud
b1039c6146 Add support for asynchronous actions in extensions in the editor (#4819)
* By marking an action as asynchronous, the actions and sub-events following it will wait for it to end. This is similar to the "Wait X seconds" action.
* Don't forget to use the action *"End asynchronous function"* in the events to mark the end of the action. Otherwise, the action will never end.
2023-02-02 12:30:17 +01:00
D8H
1b5acc9fa9 Fix the instruction group of event functions with operator (#4882) 2023-02-02 11:38:16 +01:00
Clément Pasteau
54cf91f180 Display new objects in the New Object Dialog (#4871)
* Buttons
* Toggles, Switches and Sliders
* Multitouch Joysticks
* Health and loading bars
* (Those objects were previously available through the asset store and are now visible when creating an object from scratch)
2023-02-02 11:27:49 +01:00
D8H
a434e4d9a9 Add a button to jump to behavior events (#4878)
---------

Co-authored-by: Florian Rival <Florian.Rival@gmail.com>
2023-02-02 10:45:36 +01:00
Florian Rival
2f339dd170 Add a save icon button to the top left next to the app main menu 2023-02-01 22:33:07 +01:00
Florian Rival
e843ca67ad Update comment [skip ci]
Don't show in changelog
2023-02-01 15:32:30 +01:00
Florian Rival
e4286b2021 Show expiration date and clearer explanations when using a redemption code (#4879) 2023-02-01 09:37:45 +01:00
Florian Rival
4579568866 Fix formatting and improve namings
Don't show in changelog
2023-02-01 09:35:14 +01:00
Florian Rival
4543a03530 Render the grid of the scene in realtime when a change is made to the grid setup (#4880) 2023-02-01 09:26:33 +01:00
Florian Rival
5aed25a02f Hide labels from buttons to add objects (or other items) when a list is too narrow
Don't show in changelog
2023-01-31 22:16:09 +01:00
Florian Rival
6fd9cfe4c3 Fix Events Sheet crashes and inconsistent order or location of pasting (#4876)
* Fix extracting events to a function or to a group crashing sometimes the app
* Also ensure events are copied/pasted or moved in their order of selection
* Events or actions/conditions are now only pasted at a single location
  * We previously allowed pasted events/actions/conditions to be inserted multiple times for each selected event, but this was more confusing than useful.
  * Now, the pasted elements are only pasted on the last selected event/action/condition (usually the one you just right clicked)
2023-01-31 17:56:35 +01:00
D8H
091324d93b Add a condition to check if the player has just closed the leaderboard view (#4875) 2023-01-31 15:16:28 +01:00
D8H
d802bd14b9 Add an action to hide the player login banner (#4874) 2023-01-31 12:55:12 +01:00
D8H
f46a6dc421 Optimize the z-order action (#4868)
- Scenes should be faster to load
- Games that y-sort a lot of moving objects should run much faster.
2023-01-30 13:29:50 +01:00
Florian Rival
b09e783b06 Remove help buttons for each accordion in the editor of a custom object
Don't show in changelog
2023-01-30 12:43:27 +01:00
Florian Rival
e2a050b717 Reduce size of text alignment icons 2023-01-30 12:41:32 +01:00
Florian Rival
ae22d1b876 Fix warning
Don't show in changelog
2023-01-28 17:26:34 +01:00
Florian Rival
9e6e7166ef Allow to retry uploading a file that failed to be uploaded
Don't show in changelog
2023-01-28 16:56:29 +01:00
Florian Rival
22c71a8aef Fix regression in font loading
Don't show in changelog
2023-01-27 19:32:08 +01:00
Florian Rival
4908c84494 Adapt loading of resources to allow a token instead of a cookie (#4870)
Don't show in changelog
2023-01-27 18:11:39 +01:00
AlexandreS
e4f44f7899 Add possibility to display GDevelop watermark that opens Liluo creator page on click/touch (#4811) 2023-01-24 18:26:39 +01:00
AlexandreS
c441610123 Improve in app tutorial element highlighting (#4865)
Don't show in changelog
2023-01-24 17:48:55 +01:00
D8H
d724712aa4 Fix direction actions on Sprites after an animation change with custom origin (#4860)
* Impacted actions are "Turn toward a position" and "Add a force toward a position".
2023-01-24 15:04:36 +01:00
Florian Rival
08fc7d3e9f Fix typos in description of StartedTouchOrMouseId and StartedTouchOrMouseCount 2023-01-22 20:49:29 +01:00
Florian Rival
ba30665811 Open the file chooser when adding a sprite or choosing a resource with less clicks for Cloud projects (#4859)
*Choosing a file from the device/computer is also the default choice when adding any resource, like for local projects.
2023-01-22 19:17:27 +01:00
Florian Rival
c72658e2d6 Fix some missing extensions accepted for files for Cloud projects (#4858) 2023-01-22 18:35:19 +01:00
AlexandreS
a3fc7585b4 Show the number of instances on a layer in the dialog confirming its deletion (#4854) 2023-01-21 18:33:46 +01:00
Florian Rival
244bc7e274 Fix error when trying to save in Piskel immediately after saving a project in the cloud for the first time (#4857) 2023-01-21 17:06:35 +01:00
Florian Rival
5a5bf60aac Add a selector in external editors to choose if new files must be created, or existing files be edited (#4855) 2023-01-21 14:26:07 +01:00
Florian Rival
33a69849d9 Temporarily revert game with login template to use gdevelop-app.com to prevent CORS issue
Don't show in changelog
2023-01-20 16:56:07 +01:00
Florian Rival
131ee1534a Fix performance issue when pinching to zoom on the scene editor (#4852) 2023-01-20 16:54:40 +01:00
AlexandreS
614c324a63 Change SortableVirtualizedItemList ItemRow to use text field with same fontsize as when not editing (#4851)
Don't show in changelog
2023-01-20 15:12:31 +01:00
AlexandreS
ca4ff1fa6d Decrease line height in comments (#4850)
Don't show in changelog
2023-01-20 14:53:05 +01:00
AlexandreS
0e9ed86b4d Improved comment and group events display (#4846)
* Fix bug that added a new line when one typed Enter key to edit a comment event
* Focus comment or group event after adding it (so that one doesn't have to click on it after adding it)
* Keep the same style when editing a group or comment event
* Submit modifications of group or comment event with Ctrl/Cmd + Enter
2023-01-20 13:53:26 +01:00
Florian Rival
3961c2af4a Remove useless analytics event
Don't show in changelog
2023-01-20 10:33:22 +01:00
Daniel R
cc4d78b08a Don't snap to grid when resizing an instance if Alt key is pressed (#4847)
* This is similar to pressing Alt key when moving an object - it won't snap to the grid.
2023-01-20 09:12:46 +01:00
AlexandreS
8d13285c97 Fix GDJS tests (#4845)
Don't show in changelog
2023-01-19 09:36:21 +01:00
Florian Rival
7b7e13817c Hide the old, deprecated Text Entry object when creating a new object from scratch
* Instead, use the Text Input object to display a field to let the player write something.
2023-01-18 14:44:13 +01:00
Florian Rival
129ebeb4e4 Fix previews not automatically opened on iOS and Safari for the web-app (#4843) 2023-01-18 13:58:14 +01:00
Florian Rival
808f2bc802 Fix new images made with Piskel wrongly smoothed when the project is configured for pixel-art (#4844) 2023-01-18 13:35:43 +01:00
AlexandreS
c5935232f7 Add legacy flag on former plans (#4842)
Don't show in changelog
2023-01-18 12:37:06 +01:00
AlexandreS
35a8341964 Display former subscriptions (indie and pro) in user profile (#4841) 2023-01-18 11:02:24 +01:00
AlexandreS
95783fd58f Bump newIDE version 2023-01-17 15:49:19 +01:00
github-actions[bot]
a78aa4af6e Update translations [skip ci] (#4794) 2023-01-17 15:48:47 +01:00
D8H
4f4b2b7901 Replace touch conditions to also handle the mouse (#4785)
* Add expressions to get the mouse cursor position without touches moving it.
2023-01-17 15:27:58 +01:00
Tristan Rhodes
957f672b90 Add LinearVelocityAngle() expression for the Physics behavior (#4798) 2023-01-17 14:11:21 +01:00
AlexandreS
b9e932d0de Fix flaky animation frame setting action (#4835) 2023-01-17 14:04:11 +01:00
Florian Rival
fdd2362dae Show link to business plans in the subscription dialog (#4838)
As we're having more and more professionals (game designers, game studios), startups and large-scale companies using GDevelop, we're now providing dedicated plans for businesses: https://gdevelop.io/pricing. They come with dedicated support, ability to apply custom branding and more things for usage by enterprises or game studios.
2023-01-17 12:28:48 +01:00
AlexandreS
47583e3092 Fix: Display new resource created with Jfxr or Yarn in resource selector dropdown (#4834) 2023-01-16 15:24:58 +01:00
AlexandreS
8d7967d71a Commit variable name changes after build (#4833)
Do not show in changelog
2023-01-16 15:08:25 +01:00
AlexandreS
72142a62c4 Fix bug that prevented to close parameter popover on the event sheet (#4832) 2023-01-16 14:49:48 +01:00
D8H
619890a25f Fix extension life-cycle functions were not exported (#4830) 2023-01-16 14:39:55 +01:00
AlexandreS
debcd3045f Add autocompletions for some fields that can contain object groups (#4831)
* Effect name
* Effect parameter name
* Sprite point name
2023-01-16 14:37:46 +01:00
D8H
86635e4f66 Add a condition to check if the game has just resumed (#4824)
* It can be useful to display a pause menu when the player come back to the game.
2023-01-16 13:34:38 +01:00
D8H
eedc68b0f2 Fix pathfinding movement angle condition (#4825)
* Add a condition to check the movement angle of the top-down movement behavior.
2023-01-16 10:30:00 +01:00
Florian Rival
b1a6425ab8 Display, when available, video tutorials translated in other languages (#4829)
* For example, some French tutorials have been translated by https://www.youtube.com/@videogamecoder6395
* If you have some translated tutorials, please send them to us using this form: https://airtable.com/shrv295oHlsuS69el - the GDevelop team will review them and add them for your language.
2023-01-15 21:24:45 +01:00
Florian Rival
3d1ee5efcc Update yarn.lock
Don't show in changelog
2023-01-15 12:00:19 +01:00
Florian Rival
4d1fde608b Fix missing translation marker
Don't show in changelog
2023-01-14 14:19:06 +01:00
Florian Rival
e40666bd73 Improve wording of the action to set a Text Input read-only 2023-01-14 14:15:44 +01:00
Florian Rival
4a6c075e41 Fix plural in variable child count in the variables editor 2023-01-14 14:04:14 +01:00
Florian Rival
82426fa564 Fix tinting of deleted sprites sometimes wrongly used to render newly created objects (#4823)
Fix #4822
2023-01-13 14:35:37 +01:00
Florian Rival
a21eef6930 Rename the signing options to make clearer that the legacy options must not be used
Some users were trying to change the upload key when they wanted to update their app,
because they thought "new upload key" would generate a new upload key at every packaging,
instead of using the "default" key - while the other option uses a legacy key that must not
be used in 99.9% of cases

Don't show in changelog
2023-01-13 10:41:55 +01:00
D8H
c6112a1549 Allow custom objects to define an origin point (#4821)
*  Fix camera renderer position update when the center stays the same but dimensions change.
* Don't show in changelog.
2023-01-12 18:47:57 +01:00
D8H
d8350396df Add an action to toggle boolean property values (#4800) 2023-01-12 12:10:47 +01:00
Florian Rival
a8282aaf83 Add conditions to check if the game is exported as a native mobile or desktop app (#4820) 2023-01-12 11:27:47 +01:00
D8H
7de7fc7193 Allow anchored child-objects to scale with the child-object they target (#4818)
* Don't show in changelogs.
2023-01-11 23:49:08 +01:00
AlexandreS
81c5829267 Fix selection rectangle around an instance not displaying correctly for sprites with custom center (#4817) 2023-01-11 16:04:41 +01:00
D8H
07cf1a90a4 Fix a crash when an event-based object tries to access scene variables (#4816)
* Internal changes (for developers)
2023-01-11 14:11:19 +01:00
Florian Rival
3213985a81 Add two expressions to replace one or all occurrences of a text in another (#4809)
* `StrReplaceOne` can be used to replace one occurrence of a "pattern" in a text by another.
* `StrReplaceAll` can be used to replace all occurrences of a "pattern" in a text by another.
2023-01-10 12:39:59 +01:00
Clément Pasteau
d4441fda99 Disable player auth checkbox if offline and improve error message (#4810)
Do not show in changelog
2023-01-10 11:54:39 +01:00
Florian Rival
91c55fcf94 Ask for company name/size or goal when asking about GDevelop usage (#4807)
* Also ask for what's the goal for people using GDevelop for a personal/student usage. Useful to better understand the motivation of the user base.
2023-01-10 11:09:57 +01:00
D8H
6d7b5ac7d3 Add missing icons in the instruction tree (#4797) 2023-01-09 13:45:50 +01:00
Florian Rival
903b353b7b Fix LDtk maps not properly loaded when not having a IntGrid layer (#4806)
Fix #4803
2023-01-09 13:20:31 +01:00
Clément Pasteau
4dd189512b Show contact information from a feedback (#4804) 2023-01-09 12:42:09 +01:00
Clément Pasteau
535fa39a7b Fix renaming children objects of event-based Object (#4805)
Do not show in changelog
2023-01-09 12:41:41 +01:00
Daniel R
78c0cb944f Use F2 as a shortcut for renaming object in the Objects List Panel (#4682)
Thanks @danired!
Co-authored-by: Daniel Redondo <dani@easydevel.com>
2023-01-09 11:02:29 +01:00
Clément Pasteau
55e037484f Allow accessing user profile of a game feedback made by a connected player (#4796) 2023-01-09 10:58:49 +01:00
D8H
84392c08b2 Add an event that returns true when a new condition is added to an extension (#4802) 2023-01-09 09:25:47 +01:00
Florian Rival
0061b1cb8b Allow to close the Home page menu drawer by tapping outside
Don't show in changelog
2023-01-08 21:25:40 +01:00
github-actions[bot]
9e19aa8886 Update translations [skip ci] (#4750)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-01-06 14:40:33 +01:00
Clément Pasteau
f4b812ab29 Small fixes player auth (#4792)
* Prevent listening for liluo connection if not on web
* Catch any error when interacting with localstorage

Do not show in changelog
2023-01-06 14:39:21 +01:00
Florian Rival
106d9de47c Fix naming of filenames created from resources in an external editor (#4791)
Don't show in changelog
2023-01-05 22:52:29 +01:00
Florian Rival
ecbafe60d1 Fix crash sometimes happening when an action/condition was stored with more parameters than expected (#4786)
Don't show in changelog
2023-01-05 16:11:28 +01:00
D8H
c0ba26f1d5 Allow to add a vertex to a collision mask by pulling an edge (#4778)
* Vertices can also be removed by dropping them next to one of their neighbors.
2023-01-05 12:58:02 +01:00
AlexandreS
089be66e82 Fix top down behavior "Rotation speed" property keeping the value 180° for no reason (#4764) 2023-01-05 10:52:20 +01:00
Florian Rival
ffb8a399cd Add support for Piskel, Jfxr and Yarn on the web-app (#4779)
* When you're using the web version of GDevelop, be it on a mobile phone, tablet, Chromebook, traditional computer, on iOS, Android, Windows, Linux or macOS, you can now create and edit images with Piskel, sounds with Jfxr and dialogue trees with Yarn.
2023-01-04 22:42:50 +01:00
Clément Pasteau
63482a0cda Allow automatic player login when the game is hosted on Liluo (#4776)
Do not show in changelog
2023-01-03 16:49:25 +01:00
Clément Pasteau
4fe8dcaf0c Improve default build name (#4777)
Do not show in changelog
2023-01-03 15:35:22 +01:00
Florian Rival
9729461aa1 Add support for using Piskel (image editor), Jfxr (sound editor) and Yarn (dialogue editor) for Cloud projects on desktop (#4769) 2023-01-03 11:41:40 +01:00
D8H
26fcc9770b Add new collision mask vertices on the middle of edges (#4774) 2023-01-03 11:10:42 +01:00
D8H
c62f9c5c65 Fix missing export files for extensions (#4773) 2023-01-02 19:11:11 +01:00
Daniel R
9b199d5aa0 Fix missing space between "Add action" and "paste actions" labels (#4772) 2023-01-02 09:01:48 +01:00
AlexandreS
46e1a5c6e8 Fix Text object Scale X condition and action (#4768) 2022-12-30 11:39:03 +01:00
Aurélien Vivet
052a6240c5 Fix typo (#4766)
Don't show in changelog
2022-12-30 09:10:24 +01:00
AlexandreS
d081711838 Allow to use Escape key as way to cancel rename of object/group/scene/external layout (#4765)
* Also fix drag and drop of project manager items preventing to select text when renaming item
2022-12-30 09:05:03 +01:00
AlexandreS
f0151b2e1f Improve subscription panel and user experience (#4755) 2022-12-29 11:03:37 +01:00
AlexandreS
e2f42ca290 Fix unwelcome opening of keyboard on mobile on the app 2022-12-27 17:59:32 +01:00
Clément Pasteau
b7a3d85287 Allow opening the Game Dashboard from the Home Build page (#4730)
* This will work by default for new games
* For existing games, the option will appear the next time you save your project
2022-12-27 12:43:30 +01:00
Clément Pasteau
4b542e071a Allow navigating through asset packs of an Asset Creator from their profile (#4697) 2022-12-27 11:59:29 +01:00
Florian Rival
64cad25b81 Bump newIDE version (#4752) 2022-12-26 16:24:35 +01:00
Florian Rival
8472e30342 Show a warning about Piskel/Jfxr/Yarn not being available yet for cloud projects on desktop (#4751) 2022-12-26 16:23:29 +01:00
Clément Pasteau
1b7d258727 Remove mentions of "experimental" for features and tools widely used and supported (#4749) 2022-12-26 15:02:56 +01:00
github-actions[bot]
946b77093d Update translations [skip ci] (#4742)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-12-26 14:10:34 +01:00
Florian Rival
74c882f219 Fix wrong scrollbars in the Sprite editor 2022-12-26 12:50:40 +01:00
Florian Rival
abd417c494 Fix games crash because of some extensions not included in the generated games
Revert "Fix missing export files by including the free functions of every extension that is actually used (#4672)" (#4746) (commit 93121d1a1c)
2022-12-26 12:36:39 +01:00
Florian Rival
2005f9c37b Bump newIDE version 2022-12-24 11:30:25 +01:00
github-actions[bot]
b749ac1106 Update translations [skip ci] (#4736)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-12-24 11:21:40 +01:00
Baptiste Augrain
f34f901fa7 Add support for opacity of layers for Tiled tilemaps (#4739) 2022-12-24 11:21:03 +01:00
Florian Rival
c74110c058 Fix the storage provider default choice not being always the optimal one when running the tutorial 2022-12-23 23:29:44 +01:00
Baptiste Augrain
2a38be827c Add support for Tileset resources with .tsj extension (#4737) 2022-12-23 23:09:16 +01:00
D8H
7cd97e8cc4 Disable "missing shared data" error logs for custom objects. (#4735)
* Don't in changelog
2022-12-23 18:31:19 +01:00
github-actions[bot]
4c9445f6f5 Update translations [skip ci] (#4734)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-12-23 18:08:28 +01:00
Baptiste Augrain
b7772520b5 Add support for selecting directly .ldtk and .tmj files from the interface (#4733)
* Files saved from LDtk or from Tiled (using the .tmj format) can be now selected directly when choosing a Tilemap to be displayed by a Tilemap object.
2022-12-23 17:46:17 +01:00
D8H
93121d1a1c Fix missing export files by including the free functions of every extension that is actually used (#4672) 2022-12-23 17:33:52 +01:00
D8H
9f7c1a1748 Better display custom objects in the editor (#4643) 2022-12-23 17:21:47 +01:00
Florian Rival
f6fc2406a5 Fix missing menu items on web-app
Don't show in changelog
2022-12-23 15:32:37 +01:00
github-actions[bot]
daede19d0d Update translations [skip ci] (#4718)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-12-23 12:42:26 +01:00
Florian Rival
36e835c461 Don't enable player authentication if a tutorial is running when creating a new project
Don't show in changelog
2022-12-23 10:49:16 +01:00
Florian Rival
8d0b3ef53e Fix MarkdownText using a div instead of a span when not a standalone text
* Also add a missing translation
* Also enable player authentication by default when creating a new game
2022-12-23 10:13:58 +01:00
Florian Rival
7ccd2cd146 Update README with link to GDevelop-tutorials repository [skip ci]
* This is where the step-by-step onboarding is stored and future tutorials can be built by the community: https://github.com/GDevelopApp/GDevelop-tutorials

Only show in developer changelog
2022-12-22 22:59:40 +01:00
D8H
49974131d0 Improve installation of assets containing custom objects, like menu buttons, so that if an extension needs an update, a confirmation dialog is shown (#4724) 2022-12-22 19:27:54 +01:00
Baptiste Augrain
77320ce12e Add support for LDtk Tilemaps (#4575)
* Tilemaps made with [LDtk](https://ldtk.io/), a modern 2D level editor, can be now used directly. Make sure to save your map made in LDtk as a JSON file, create a new Tilemap object in GDevelop and in the Tilemap field, choose the LDtk file.
* Tilesets used by the LDtk Tilemap are automatically imported in your game - you don't need to import them separately.
* For more information, read about the [Tilemap object on the wiki](https://wiki.gdevelop.io/gdevelop5/objects/tilemap).

Co-authored-by: Davy Hélard <davy.helard@gmail.com>
Co-authored-by: Florian Rival <Florian.Rival@gmail.com>
2022-12-22 18:44:27 +01:00
Clément Pasteau
35833e6e23 Allow adding default player authentication when creating a project (#4714)
* New checkbox in the Project Creation dialog, which will apply best practices for player authentication on the empty project
2022-12-22 16:20:13 +01:00
AlexandreS
7436032787 Fix asset store preview (#4729)
Do not show in changelog
2022-12-22 15:48:15 +01:00
AlexandreS
aa4fd1bda9 Prefer scroll in homepage header rather than uncontrolled wrap (#4728)
Do not show in changelog
2022-12-22 11:46:04 +01:00
AlexandreS
e10dd57fed In the scene editor, paste cut instances at highest z order (#4726) 2022-12-22 10:53:26 +01:00
Florian Rival
893257491a Launch automatically the search in the asset store when typing (#4725) 2022-12-21 22:12:05 +01:00
AlexandreS
b8f04515f3 Do not close context menu when clicking on checkbox items (#4690) 2022-12-21 12:46:45 +01:00
AlexandreS
4a807b6053 Fix editor that was setting the z order of a new instance a bit randomly 2022-12-21 12:41:49 +01:00
AlexandreS
dbfef27d2e Fix leaderboard admin closing when trying to remove a leaderboard (#4691) 2022-12-21 11:08:24 +01:00
D8H
72b69e4cdf Add a sprite editor for custom objects with a locked animation list (#4719) 2022-12-21 09:32:24 +01:00
D8H
2f11cd667b Add an expression to get the number of frames in the current animation of a sprite object (#4722) 2022-12-21 09:30:03 +01:00
Florian Rival
d9de2a3177 Fix the asset store search
Don't show in changelog
2022-12-20 17:52:21 +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
2039 changed files with 63583 additions and 103861 deletions

View File

@@ -57,8 +57,8 @@ jobs:
- name: Log urls to the Storybook
run: |
echo "Find the latest Storybook for this branch on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html"
echo "Find the Storybook for this commit on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html"
echo "Find the latest Storybook for this branch on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html"
echo "Find the Storybook for this commit on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html"
# Publish on Chromatic, only when manually launched (too costly to run on every commit).
- name: Publish Storybook to Chromatic

View File

@@ -726,6 +726,8 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
metadata.GetType() == "fontResource" ||
metadata.GetType() == "imageResource" ||
metadata.GetType() == "jsonResource" ||
metadata.GetType() == "tilemapResource" ||
metadata.GetType() == "tilesetResource" ||
metadata.GetType() == "videoResource" ||
// Deprecated, old parameter names:
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||

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

@@ -123,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
*/

View File

@@ -105,7 +105,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
extension
.AddCondition(
@@ -117,7 +118,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.UseStandardRelationalOperatorParameters("string");
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions());
}
} // namespace gd

View File

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

View File

@@ -23,6 +23,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.SetCategory("Audio");
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds and music"))
.SetIcon("res/actions/music24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds on channels"))
.SetIcon("res/actions/son24.png");
extension
.AddAction("PlaySoundCanal",
@@ -146,69 +148,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 +238,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 +255,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
@@ -448,15 +470,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
@@ -471,7 +495,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
@@ -484,7 +511,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(
@@ -498,22 +528,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
@@ -527,7 +562,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
@@ -541,7 +579,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

@@ -40,7 +40,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddAction("MettreX",
@@ -52,7 +53,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddCondition("PosY",
@@ -64,7 +66,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddAction("MettreY",
@@ -76,7 +79,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/position_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsSimple();
obj.AddAction("MettreXY",
@@ -120,7 +124,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Center"),
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndConditionAndAction(
"number",
@@ -131,7 +135,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Center"),
"res/actions/position24_black.png")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxLeft",
@@ -142,7 +146,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Bounding Box"),
"res/conditions/bounding-box-left_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition(
"number",
@@ -153,7 +157,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Bounding Box"),
"res/conditions/bounding-box-top_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxRight",
@@ -164,7 +168,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Bounding Box"),
"res/conditions/bounding-box-right_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxBottom",
@@ -175,7 +179,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Bounding Box"),
"res/conditions/bounding-box-bottom_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxCenterX",
@@ -186,7 +190,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Bounding Box"),
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddExpressionAndCondition("number",
"BoundingBoxCenterY",
@@ -197,7 +201,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Position/Bounding Box"),
"res/conditions/bounding-box-center_black.svg")
.AddParameter("object", _("Object"))
.UseStandardParameters("number");
.UseStandardParameters("number", ParameterOptions::MakeNewOptions());
obj.AddAction("MettreAutourPos",
_("Put around a position"),
@@ -226,7 +230,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/direction_black.png")
.AddParameter("object", _("Object"))
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Angle (in degrees)")));
obj.AddAction("Rotate",
_("Rotate"),
@@ -382,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"),
@@ -398,8 +406,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddAction("ModVarObjet",
_("Value of an object variable"),
_("Change the value of an object variable."),
_("Change number variable"),
_("Modify the number value of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
"res/actions/var24.png",
@@ -407,11 +415,12 @@ 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"),
_("Change the text of an object variable."),
_("Change text variable"),
_("Modify the text of an object variable."),
_("the text of variable _PARAM1_"),
_("Variables"),
"res/actions/var24.png",
@@ -419,11 +428,12 @@ 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"),
_("Change the boolean value of an object variable."),
_("Change boolean variable"),
_("Modify the boolean value of an object variable."),
_("Set the boolean value of variable _PARAM1_ of "
"_PARAM0_ to _PARAM2_"),
_("Variables"),
@@ -436,7 +446,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddAction(
"ToggleObjectVariableAsBoolean",
_("Toggle the boolean value of an object variable"),
_("Toggle boolean variable"),
_("Toggles the boolean value of an object variable.") + "\n" +
_("If it was true, it will become false, and if it was false "
"it will become true."),
@@ -451,37 +461,39 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddCondition("ObjectVariableChildExists",
_("Child existence"),
_("Check if the specified child of the variable exists."),
_("Check if the specified child of the object "
"structure variable exists."),
_("Child _PARAM2_ of variable _PARAM1_ of _PARAM0_ exists"),
_("Variables/Collections/Structures"),
_("Variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Name of the child"))
.MarkAsAdvanced();
obj.AddAction("ObjectVariableRemoveChild",
_("Remove a child"),
_("Remove a child from an object variable."),
_("Remove a child from an object structure variable."),
_("Remove child _PARAM2_ from variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Structures"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.MarkAsAdvanced();
obj.AddAction("ObjectVariableClearChildren",
_("Clear variable"),
_("Remove all the children from the object variable."),
_("Clear children"),
_("Remove all the children from the object array or structure "
"variable."),
_("Clear children from variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Array or structure variable"))
.MarkAsAdvanced();
obj.AddAction("Cache",
@@ -516,7 +528,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"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",
@@ -528,7 +543,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/planicon.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("Layer",
@@ -585,7 +601,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/vitesse.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("AngleOfDisplacement",
@@ -604,8 +621,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddCondition("VarObjet",
_("Value of an object variable"),
_("Compare the value of an object variable."),
_("Number variable"),
_("Compare the number value of an object variable."),
_("the variable _PARAM1_"),
_("Variables"),
"res/conditions/var24.png",
@@ -613,10 +630,11 @@ 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"),
_("Text variable"),
_("Compare the text of an object variable."),
_("the text of variable _PARAM1_"),
_("Variables"),
@@ -625,10 +643,11 @@ 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"),
_("Boolean variable"),
_("Compare the boolean value of an object variable."),
_("The boolean value of variable _PARAM1_ of object "
"_PARAM0_ is _PARAM2_"),
@@ -642,7 +661,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddCondition("VarObjetDef",
"Variable defined",
"Check if the variable is defined.",
"Check if the object variable is defined.",
"Variable _PARAM1 of _PARAM0_ is defined",
_("Variables"),
"res/conditions/var24.png",
@@ -650,78 +669,131 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("string", _("Variable"))
.SetHidden();
.SetHidden(); // Deprecated.
obj.AddAction(
"ObjectVariablePush",
_("Append variable to an object array"),
_("Appends a variable to the end of an object array variable."),
_("Append variable _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
_("Add existing variable"),
_("Adds an existing variable to the end of an object array variable."),
_("Add variable _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("scenevar", _("Scene variable with the content to append"))
.SetParameterLongDescription(
_("The content of the variable will *be copied* and appended at the "
"end of the array."))
.AddParameter("scenevar", _("Scene variable with the content to add"))
.SetParameterLongDescription(_("The content of the object variable will "
"*be copied* and added at the "
"end of the array."))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariablePushString",
_("Append a string to an object array"),
_("Appends a string to the end of an object array variable."),
_("Append string _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
_("Add text variable"),
_("Adds a text (string) to the end of an object array variable."),
_("Add text _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("string", _("String to append"))
.AddParameter("string", _("Text to add"))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariablePushNumber",
_("Append a number to an object array"),
_("Appends a number to the end of an object array variable."),
_("Append number _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
"res/actions/var24.png",
"res/actions/var.png")
obj.AddAction("ObjectVariablePushNumber",
_("Add number variable"),
_("Adds a number to the end of an object array variable."),
_("Add number _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Number to append"))
.AddParameter("expression", _("Number to add"))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariablePushBool",
_("Append a boolean to an object array"),
_("Appends a boolean to the end of an object array variable."),
_("Append boolean _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Collections/Arrays"),
_("Add boolean variable"),
_("Adds a boolean to the end of an object array variable."),
_("Add boolean _PARAM2_ to array variable _PARAM1_ of _PARAM0_"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to append"))
.AddParameter("trueorfalse", _("Boolean to add"))
.MarkAsAdvanced();
obj.AddAction(
"ObjectVariableRemoveAt",
_("Remove variable from an object array (by index)"),
_("Remove variable by index"),
_("Removes a variable at the specified index of an object array "
"variable."),
_("Remove variable at index _PARAM2_ from array variable _PARAM1_ of "
"_PARAM0_"),
_("Variables/Collections/Arrays"),
_("Variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.AddParameter("objectvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.MarkAsAdvanced();
obj.AddCondition(
"ObjectVariableChildCount",
_("Number of children"),
_("Compare the number of children in an object array variable."),
_("The number of children in the array variable _PARAM1_"),
_("Variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddStrExpression(
"ArrayVariableFirstString",
_("First text child"),
_("Get the value of the first element of an object array variable, if "
"it is a text (string) variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableFirstNumber",
_("First number child"),
_("Get the value of the first element of an object array variable, if "
"it is a number variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddStrExpression(
"ArrayVariableLastString",
_("Last text child"),
_("Get the value of the last element of an object array variable, if "
"it is a text (string) variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddExpression(
"ArrayVariableLastNumber",
_("Last number child"),
_("Get the value of the last element of an object array variable, if "
"it is a number variable."),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Array variable"));
obj.AddCondition("BehaviorActivated",
_("Behavior activated"),
_("Check if the behavior is activated for the object."),
@@ -1098,23 +1170,24 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("expression", _("Target Y position"));
obj.AddExpression("Variable",
_("Value of an object variable"),
_("Value of an object variable"),
_("Number variable"),
_("Number value of an object variable"),
_("Variables"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"));
obj.AddExpression("VariableChildCount",
_("Number of children of an object variable"),
_("Number of children of an object variable"),
_("Variables"),
"res/actions/var.png")
obj.AddExpression(
"VariableChildCount",
_("Number of children"),
_("Number of children in an object array or structure variable"),
_("Variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"));
.AddParameter("objectvar", _("Array or structure variable"));
obj.AddStrExpression("VariableString",
_("Text of an object variable"),
_("Text variable"),
_("Text of an object variable"),
_("Variables"),
"res/actions/var.png")
@@ -1276,7 +1349,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListOrEmptyIfJustDeclared", _("Group of potential objects"))
.AddParameter("objectListOrEmptyIfJustDeclared",
_("Group of potential objects"))
.SetParameterLongDescription(
_("Group containing objects that can be created by the action."))
.AddParameter("string", _("Name of the object to create"))
@@ -1423,34 +1497,39 @@ 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")
.MarkAsSimple();
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")
.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
.AddCondition(
@@ -1559,7 +1638,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"",
"res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.SetHidden(); // Deprecated
.SetHidden(); // Deprecated
obj.AddStrExpression("ObjectName",
_("Object name"),

View File

@@ -26,6 +26,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras");
extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras"))
.SetIcon("res/conditions/camera24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect24.png");
extension
.AddExpressionAndConditionAndAction(
@@ -37,7 +39,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"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)
@@ -69,7 +71,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"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)
@@ -104,7 +106,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -120,7 +122,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -137,7 +139,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -154,7 +156,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -171,7 +173,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -188,7 +190,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
@@ -201,7 +203,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"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)
@@ -453,8 +455,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"),
"res/conditions/camera24.png",
"res/conditions/camera.png")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
@@ -472,8 +474,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"),
"res/conditions/camera24.png",
"res/conditions/camera.png")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
@@ -491,8 +493,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"names) in the effects window."),
_("Enable _PARAM3_ for effect _PARAM2_ of layer _PARAM1_: _PARAM4_"),
_("Effects"),
"res/conditions/camera24.png",
"res/conditions/camera.png")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
@@ -506,9 +508,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Layer effect is enabled"),
_("The effect on a layer is enabled"),
_("Effect _PARAM2_ on layer _PARAM1_ is enabled"),
_("Effects"),
"res/conditions/camera24.png",
"res/conditions/camera.png")
_(""),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
@@ -521,8 +523,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Enable an effect on a layer"),
_("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"),
_("Effects"),
"res/conditions/camera24.png",
"res/conditions/camera.png")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
@@ -542,7 +544,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
@@ -572,7 +577,8 @@ 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
@@ -597,7 +603,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Set the ambient light color of the lighting layer in format "
"\"R;G;B\" string."),
_("Set the ambient color of the lighting layer _PARAM1_ to _PARAM2_"),
_("Lighting"),
_(""),
"res/actions/color24.png",
"res/actions/color.png")
.AddCodeOnlyParameter("currentScene", "")

View File

@@ -492,6 +492,16 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"",
"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

@@ -27,6 +27,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.SetCategory("Input");
extension.AddInstructionOrExpressionGroupMetadata(_("Mouse and touch"))
.SetIcon("res/actions/mouse24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Multitouch"))
.SetIcon("res/conditions/touch24.png");
extension
.AddCondition(
@@ -153,42 +155,80 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
extension
.AddExpressionAndCondition(
"number",
"MouseX",
"CursorX",
_("Cursor X position"),
_("the X position of the cursor or of a touch"),
_("the cursor (or touch) X position"),
"",
"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)
.SetDefaultValue("0");
// Support for deprecated names:
extension.AddDuplicatedCondition("SourisX", "MouseX").SetHidden();
extension.AddDuplicatedExpression("SourisX", "MouseX").SetHidden();
extension.AddDuplicatedCondition("MouseX", "CursorX").SetHidden();
extension.AddDuplicatedExpression("MouseX", "CursorX").SetHidden();
extension.AddDuplicatedCondition("SourisX", "CursorX").SetHidden();
extension.AddDuplicatedExpression("SourisX", "CursorX").SetHidden();
extension
.AddExpressionAndCondition(
"number",
"MouseY",
"CursorY",
_("Cursor Y position"),
_("the Y position of the cursor or of a touch"),
_("the cursor (or touch) Y position"),
"",
"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)
.SetDefaultValue("0");
// Support for deprecated names:
extension.AddDuplicatedCondition("SourisY", "MouseY").SetHidden();
extension.AddDuplicatedExpression("SourisY", "MouseY").SetHidden();
extension.AddDuplicatedCondition("MouseY", "CursorY").SetHidden();
extension.AddDuplicatedExpression("MouseY", "CursorY").SetHidden();
extension.AddDuplicatedCondition("SourisY", "CursorY").SetHidden();
extension.AddDuplicatedExpression("SourisY", "CursorY").SetHidden();
extension
.AddExpressionAndCondition("number",
"MouseOnlyCursorX",
_("Mouse cursor X position"),
_("the X position of the mouse cursor"),
_("the mouse cursor X position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
// It's only useful for extensions as they can't use TouchSimulateMouse.
.SetHidden();
extension
.AddExpressionAndCondition("number",
"MouseOnlyCursorY",
_("Mouse cursor Y position"),
_("the Y position of the mouse cursor"),
_("the mouse cursor Y position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
// It's only useful for extensions as they can't use TouchSimulateMouse.
.SetHidden();
extension
.AddCondition("IsMouseInsideCanvas",
@@ -276,7 +316,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)
@@ -292,7 +332,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)
@@ -334,44 +374,85 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCondition(
"HasAnyTouchStarted",
_("A new touch has started"),
_("Check if a touch has just started on this frame. The touch identifiers can be "
_("Check if a touch has just started on this frame. The touch "
"identifiers can be "
"accessed using StartedTouchId() and StartedTouchCount()."),
_("A new touch has started"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression("StartedTouchCount",
_("Started touch count"),
_("The number of touches that have just started on this "
"frame. The touch identifiers can be "
"accessed using StartedTouchId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression("StartedTouchId",
_("Started touch identifier"),
_("The identifier of the touch that has just started on "
"this frame. The number of touches can be "
"accessed using StartedTouchCount()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index"))
.SetHidden();
extension
.AddCondition(
"HasAnyTouchOrMouseStarted",
_("A new touch has started"),
_("Check if a touch has just started or the mouse left button has "
"been pressed on this frame. The touch identifiers can be "
"accessed using StartedTouchOrMouseId() and "
"StartedTouchOrMouseCount()."),
_("A new touch has started"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
extension
.AddExpression(
"StartedTouchCount",
"StartedTouchOrMouseCount",
_("Started touch count"),
_("The number of touches that have just started on this frame. The touch identifiers can be "
"accessed using StartedTouchId()."),
_("The number of touches (including the mouse) that have just "
"started on this frame. The touch identifiers can be "
"accessed using StartedTouchOrMouseId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
extension
.AddExpression(
"StartedTouchId",
"StartedTouchOrMouseId",
_("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()."),
_("The identifier of the touch or mouse that has just started on "
"this frame. The number of touches can be "
"accessed using StartedTouchOrMouseCount()."),
_("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")
.AddCondition("HasTouchEnded",
_("A touch has ended"),
_("Check if a touch has ended or a mouse left button has "
"been released."),
_("The touch with identifier _PARAM1_ has ended"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"));

View File

@@ -136,6 +136,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("yesorno", _("Deactivate input when focus is lost"))
.MarkAsAdvanced();
extension
.AddCondition(
"HasGameJustResumed",
_("Game has just resumed"),
_("Check if the game has just resumed from being hidden. It "
"happens when the game tab is selected, a minimized window is "
"restored or the application is put back on front."),
_("Game has just resumed"),
"",
"res/actions/window24.png",
"res/actions/window.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "");
}
} // namespace gd

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 "GDCore/Vector2.h"
#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;
@@ -50,13 +52,13 @@ 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;
@@ -75,7 +77,7 @@ gd::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(gd::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, -height / 2.0f));

View File

@@ -5,9 +5,10 @@
*/
#ifndef GDCORE_POLYGON_H
#define GDCORE_POLYGON_H
#include "GDCore/Vector2.h"
#include <vector>
#include "GDCore/Vector2.h"
/**
* \brief Represents a polygon. Usually used for collisions masks.
*
@@ -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.
@@ -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

@@ -44,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",
@@ -57,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",
@@ -86,7 +90,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.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",
@@ -98,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",
@@ -134,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",
@@ -162,7 +170,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scale_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddAction("ChangeScaleWidth",
@@ -174,7 +185,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddAction("ChangeScaleHeight",
@@ -186,7 +200,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddAction("ChangeWidth",
@@ -198,7 +215,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("Width",
@@ -210,7 +228,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("ChangeHeight",
@@ -222,7 +241,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("Height",
@@ -234,7 +254,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("SetSize",
@@ -260,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",
@@ -288,7 +310,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.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"),
@@ -301,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",
@@ -349,7 +373,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddCondition("ScaleHeight",
@@ -361,7 +388,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddCondition("Opacity",
@@ -374,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(
@@ -387,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",
@@ -549,7 +583,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
obj.AddExpression("Sprite",
_("Image"),
_("Animation frame of the object"),
_("Current frame of the animation of the object"),
_("Animations and images"),
"res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("AnimationFrameCount",
_("Number of frames"),
_("Number of frames in the current animation of the object"),
_("Animations and images"),
"res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite");

View File

@@ -183,6 +183,26 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Position of the last character in the string to be "
"considered in the search"));
extension
.AddStrExpression("StrReplaceOne",
_("Replace the first occurrence of a text by another."),
_("Replace the first occurrence of a text by another."),
"",
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text in which the replacement must be done"))
.AddParameter("string", _("Text to find inside the first text"))
.AddParameter("string", _("Replacement to put instead of the text to find"));
extension
.AddStrExpression("StrReplaceAll",
_("Replace all occurrences of a text by another."),
_("Replace all occurrences of a text by another."),
"",
"res/conditions/toujours24_black.png")
.AddParameter("string", _("Text in which the replacement(s) must be done"))
.AddParameter("string", _("Text to find inside the first text"))
.AddParameter("string", _("Replacement to put instead of the text to find"));
}
} // namespace gd

View File

@@ -65,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
@@ -148,14 +151,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
extension
.AddAction("Wait",
_("Wait X seconds (experimental)"),
_("Wait X seconds"),
_("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")
.AddParameter("expression", _("Time to wait in seconds"))
.SetHelpPath("/all-features/timers-and-time/wait-action");
extension

View File

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

View File

@@ -94,13 +94,15 @@ InstructionMetadata& InstructionMetadata::AddCodeOnlyParameter(
}
InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
const gd::String& type, const gd::String& typeExtraInfo) {
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) {
@@ -122,7 +124,9 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
}
} else {
AddParameter("operator", _("Modification's sign"), expressionValueType);
AddParameter(type, _("Value"), typeExtraInfo);
AddParameter(type,
options.description.empty() ? _("Value") : options.description,
options.typeExtraInfo);
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;
@@ -155,7 +159,7 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
InstructionMetadata&
InstructionMetadata::UseStandardRelationalOperatorParameters(
const gd::String& type, const gd::String& typeExtraInfo) {
const gd::String& type, const ParameterOptions &options) {
const gd::String& expressionValueType =
gd::ValueTypeMetadata::GetPrimitiveValueType(type);
SetManipulatedType(expressionValueType);
@@ -175,7 +179,9 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
}
} else {
AddParameter("relationalOperator", _("Sign of the test"), expressionValueType);
AddParameter(type, _("Value to compare"), typeExtraInfo);
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

@@ -14,6 +14,8 @@
#include "GDCore/Events/Instruction.h"
#include "GDCore/String.h"
#include "ParameterMetadata.h"
#include "ParameterOptions.h"
namespace gd {
class Project;
class Layout;
@@ -109,8 +111,8 @@ class GD_CORE_API InstructionMetadata {
}
/**
* Check if the instruction asynchronicity is optional. If it is, it can either
* be used synchronously or asynchronously, with one function for each.
* 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();
@@ -223,21 +225,22 @@ class GD_CORE_API InstructionMetadata {
/**
* \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, const gd::String& typeExtraInfo = "");
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& typeExtraInfo = "");
const gd::String &type, const ParameterOptions &options);
/**
* \brief Mark the instruction as an object instruction. Automatically called
@@ -334,11 +337,12 @@ class GD_CORE_API InstructionMetadata {
}
/**
* 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).
* 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.
* \param functionName the name of the function doing asynchronous work to
* call.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName_) {
asyncFunctionCallName = functionName_;
@@ -482,12 +486,12 @@ class GD_CORE_API InstructionMetadata {
}
/**
* Set the name of the function, doing asynchronous work, which will be called in
* the generated code. This function should return an asynchronous task
* 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`.
* \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);
@@ -512,7 +516,7 @@ class GD_CORE_API InstructionMetadata {
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
const std::vector<gd::String> &GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
};

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);
}
@@ -83,7 +84,8 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
MultipleInstructionMetadata &SetParameterExtraInfo(const gd::String &defaultValue) {
MultipleInstructionMetadata &SetParameterExtraInfo(
const gd::String &defaultValue) {
if (expression) expression->SetParameterExtraInfo(defaultValue);
if (condition) condition->SetParameterExtraInfo(defaultValue);
if (action) action->SetParameterExtraInfo(defaultValue);
@@ -126,9 +128,11 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::UseStandardOperatorParameters
* \see gd::InstructionMetadata::UseStandardRelationalOperatorParameters
*/
MultipleInstructionMetadata &UseStandardParameters(const gd::String &type, const gd::String& typeExtraInfo = "") {
if (condition) condition->UseStandardRelationalOperatorParameters(type, typeExtraInfo);
if (action) action->UseStandardOperatorParameters(type, typeExtraInfo);
MultipleInstructionMetadata &UseStandardParameters(
const gd::String &type, const ParameterOptions &options) {
if (condition)
condition->UseStandardRelationalOperatorParameters(type, options);
if (action) action->UseStandardOperatorParameters(type, options);
return *this;
}
@@ -167,13 +171,12 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
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();
if (action) return action->GetCodeExtraInformation().GetIncludeFiles();
// It can't actually happen.
throw std::logic_error("no instruction metadata");
}
@@ -182,12 +185,9 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::SetPrivate
*/
MultipleInstructionMetadata &SetPrivate() {
if (expression)
expression->SetPrivate();
if (condition)
condition->SetPrivate();
if (action)
action->SetPrivate();
if (expression) expression->SetPrivate();
if (condition) condition->SetPrivate();
if (action) action->SetPrivate();
return *this;
}

View File

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

View File

@@ -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

@@ -46,4 +46,25 @@ const gd::String &ValueTypeMetadata::GetPrimitiveValueType(const gd::String &par
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

@@ -192,6 +192,12 @@ class GD_CORE_API ValueTypeMetadata {
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
*/
///@{
@@ -212,6 +218,12 @@ class GD_CORE_API ValueTypeMetadata {
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

View File

@@ -24,14 +24,12 @@
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,
@@ -41,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,
@@ -53,7 +50,6 @@ gd::InstructionMetadata& PlatformExtension::AddCondition(
smallicon)
.SetHelpPath(GetHelpPath());
return conditionsInfos[nameWithNamespace];
#endif
}
gd::InstructionMetadata& PlatformExtension::AddAction(
@@ -64,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,
@@ -76,7 +71,6 @@ gd::InstructionMetadata& PlatformExtension::AddAction(
smallicon)
.SetHelpPath(GetHelpPath());
return actionsInfos[nameWithNamespace];
#endif
}
gd::ExpressionMetadata& PlatformExtension::AddExpression(
@@ -85,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(),
@@ -96,7 +89,6 @@ gd::ExpressionMetadata& PlatformExtension::AddExpression(
smallicon)
.SetHelpPath(GetHelpPath());
return expressionsInfos[nameWithNamespace];
#endif
}
gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
@@ -105,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(),
@@ -116,7 +107,6 @@ gd::ExpressionMetadata& PlatformExtension::AddStrExpression(
smallicon)
.SetHelpPath(GetHelpPath());
return strExpressionsInfos[nameWithNamespace];
#endif
}
gd::MultipleInstructionMetadata PlatformExtension::AddExpressionAndCondition(
@@ -220,12 +210,10 @@ 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,
@@ -317,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_,
@@ -326,7 +313,6 @@ gd::EventMetadata& PlatformExtension::AddEvent(
smallicon_,
instance_);
return eventsInfos[nameWithNamespace];
#endif
}
PlatformExtension& PlatformExtension::SetExtensionInformation(
@@ -406,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;
@@ -586,7 +570,6 @@ gd::BaseEventSPtr PlatformExtension::CreateEvent(
return std::shared_ptr<gd::BaseEvent>();
}
#endif
CreateFunPtr PlatformExtension::GetObjectCreationFunctionPtr(
const gd::String& objectType) const {
@@ -665,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();
@@ -810,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

@@ -620,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

@@ -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

@@ -773,15 +773,18 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
const gd::String& ignored_characters =
EventsRefactorer::searchIgnoredCharacters;
search.replace_if(
search.begin(),
search.end(),
[ignored_characters](const char& c) {
return ignored_characters.find(c) != gd::String::npos;
},
"");
search = search.LeftTrim().RightTrim();
search.RemoveConsecutiveOccurrences(search.begin(), search.end(), ' ');
if (inEventSentences) {
// Remove ignored characters only when searching in event sentences.
search.replace_if(
search.begin(),
search.end(),
[ignored_characters](const char& c) {
return ignored_characters.find(c) != gd::String::npos;
},
"");
search = search.LeftTrim().RightTrim();
search.RemoveConsecutiveOccurrences(search.begin(), search.end(), ' ');
}
for (std::size_t i = 0; i < events.size(); ++i) {
bool eventAddedInResults = false;

View File

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

View File

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

View File

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

View File

@@ -2,6 +2,7 @@
#include "GDCore/Events/Instruction.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/WholeProjectRefactorer.h"
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
@@ -11,30 +12,36 @@
namespace gd {
std::set<gd::String> UsedExtensionsFinder::ScanProject(gd::Project& project) {
const UsedExtensionsResult UsedExtensionsFinder::ScanProject(gd::Project& project) {
UsedExtensionsFinder worker(project);
gd::WholeProjectRefactorer::ExposeProjectObjects(project, worker);
gd::WholeProjectRefactorer::ExposeProjectEvents(project, worker);
return worker.usedExtensions;
return worker.result;
};
// Objects scanner
void UsedExtensionsFinder::DoVisitObject(gd::Object& object) {
usedExtensions.insert(gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), object.GetType())
.GetExtension()
.GetName());
void UsedExtensionsFinder::DoVisitObject(gd::Object &object) {
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), object.GetType());
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
result.GetUsedIncludeFiles().insert(includeFile);
}
};
// Behaviors scanner
void UsedExtensionsFinder::DoVisitBehavior(gd::Behavior& behavior) {
usedExtensions.insert(
gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
project.GetCurrentPlatform(), behavior.GetTypeName())
.GetExtension()
.GetName());
void UsedExtensionsFinder::DoVisitBehavior(gd::Behavior &behavior) {
auto metadata = gd::MetadataProvider::GetExtensionAndBehaviorMetadata(
project.GetCurrentPlatform(), behavior.GetTypeName());
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
result.GetUsedIncludeFiles().insert(includeFile);
}
for (auto &&includeFile : metadata.GetMetadata().requiredFiles) {
result.GetUsedRequiredFiles().insert(includeFile);
}
};
// Instructions scanner
@@ -46,23 +53,29 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
project.GetCurrentPlatform(), instruction.GetType())
: gd::MetadataProvider::GetExtensionAndActionMetadata(
project.GetCurrentPlatform(), instruction.GetType());
usedExtensions.insert(metadata.GetExtension().GetName());
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
result.GetUsedIncludeFiles().insert(includeFile);
}
size_t i = 0;
for (auto expression : instruction.GetParameters()) {
const gd::String& parameterType =
metadata.GetMetadata().GetParameter(i).GetType();
i++;
gd::ParameterMetadataTools::IterateOverParameters(
instruction.GetParameters(),
metadata.GetMetadata().GetParameters(),
[this](const gd::ParameterMetadata& parameterMetadata,
const gd::Expression& parameterValue,
const gd::String& lastObjectName) {
const gd::String& parameterType = parameterMetadata.GetType();
if (gd::ParameterMetadata::IsExpression("string", parameterType)) {
rootType = "string";
expression.GetRootNode()->Visit(*this);
parameterValue.GetRootNode()->Visit(*this);
} else if (gd::ParameterMetadata::IsExpression("number", parameterType)) {
rootType = "number";
expression.GetRootNode()->Visit(*this);
parameterValue.GetRootNode()->Visit(*this);
} else if (gd::ParameterMetadata::IsExpression("variable", parameterType))
usedExtensions.insert("BuiltinVariables");
}
result.GetUsedExtensions().insert("BuiltinVariables");
});
return false;
}
@@ -93,31 +106,35 @@ void UsedExtensionsFinder::OnVisitUnaryOperatorNode(UnaryOperatorNode& node) {
// Add variable extension and visit sub-expressions on variable nodes
void UsedExtensionsFinder::OnVisitVariableNode(VariableNode& node) {
usedExtensions.insert("BuiltinVariables");
result.GetUsedExtensions().insert("BuiltinVariables");
if (node.child) node.child->Visit(*this);
};
void UsedExtensionsFinder::OnVisitVariableAccessorNode(
VariableAccessorNode& node) {
usedExtensions.insert("BuiltinVariables");
result.GetUsedExtensions().insert("BuiltinVariables");
if (node.child) node.child->Visit(*this);
};
void UsedExtensionsFinder::OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode& node) {
usedExtensions.insert("BuiltinVariables");
result.GetUsedExtensions().insert("BuiltinVariables");
node.expression->Visit(*this);
if (node.child) node.child->Visit(*this);
};
// Add extensions bound to Objects/Behaviors/Functions
void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(project.GetCurrentPlatform(), GetGlobalObjectsContainer(), GetObjectsContainer(), rootType, node);
void UsedExtensionsFinder::OnVisitIdentifierNode(IdentifierNode &node) {
auto type = gd::ExpressionTypeFinder::GetType(
project.GetCurrentPlatform(), GetGlobalObjectsContainer(),
GetObjectsContainer(), rootType, node);
if (gd::ParameterMetadata::IsObject(type)) {
usedExtensions.insert(gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), node.identifierName)
.GetExtension()
.GetName());
auto metadata = gd::MetadataProvider::GetExtensionAndObjectMetadata(
project.GetCurrentPlatform(), node.identifierName);
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
for (auto &&includeFile : metadata.GetMetadata().includeFiles) {
result.GetUsedIncludeFiles().insert(includeFile);
}
}
};
@@ -138,7 +155,10 @@ void UsedExtensionsFinder::OnVisitFunctionCallNode(FunctionCallNode& node) {
return;
}
usedExtensions.insert(metadata.GetExtension().GetName());
result.GetUsedExtensions().insert(metadata.GetExtension().GetName());
for (auto&& includeFile : metadata.GetMetadata().GetIncludeFiles()) {
result.GetUsedIncludeFiles().insert(includeFile);
}
};
} // namespace gd

View File

@@ -21,18 +21,62 @@ class Behavior;
namespace gd {
class GD_CORE_API UsedExtensionsResult {
public:
/**
* The extensions used by the project (or part of it).
*/
const std::set<gd::String> &GetUsedExtensions() const {
return usedExtensions;
}
/**
* The include files used at runtime by the project (or part of it).
*/
const std::set<gd::String> &GetUsedIncludeFiles() const {
return usedIncludeFiles;
}
/**
* The additional files required at runtime by the project (or part of it).
*/
const std::set<gd::String> &GetUsedRequiredFiles() const {
return usedRequiredFiles;
}
/**
* The extensions used by the project (or part of it).
*/
std::set<gd::String> &GetUsedExtensions() { return usedExtensions; }
/**
* The include files used at runtime by the project (or part of it).
*/
std::set<gd::String> &GetUsedIncludeFiles() { return usedIncludeFiles; }
/**
* The additional files required at runtime by the project (or part of it).
*/
std::set<gd::String> &GetUsedRequiredFiles() { return usedRequiredFiles; }
private:
std::set<gd::String> usedExtensions;
std::set<gd::String> usedIncludeFiles;
std::set<gd::String> usedRequiredFiles;
};
class GD_CORE_API UsedExtensionsFinder
: public ArbitraryObjectsWorker,
public ArbitraryEventsWorkerWithContext,
public ExpressionParser2NodeWorker {
public:
static std::set<gd::String> ScanProject(gd::Project& project);
static const UsedExtensionsResult ScanProject(gd::Project& project);
private:
UsedExtensionsFinder(gd::Project& project_) : project(project_){};
gd::Project& project;
gd::String rootType;
std::set<gd::String> usedExtensions;
UsedExtensionsResult result;
// Object Visitor
void DoVisitObject(gd::Object& object) override;

View File

@@ -35,6 +35,16 @@ void ArbitraryResourceWorker::ExposeJson(gd::String& jsonName){
// do.
};
void ArbitraryResourceWorker::ExposeTilemap(gd::String& tilemapName){
// Nothing to do by default - each child class can define here the action to
// do.
};
void ArbitraryResourceWorker::ExposeTileset(gd::String& tilesetName){
// Nothing to do by default - each child class can define here the action to
// do.
};
void ArbitraryResourceWorker::ExposeVideo(gd::String& videoName){
// Nothing to do by default - each child class can define here the action to
// do.
@@ -92,6 +102,67 @@ void ArbitraryResourceWorker::ExposeResources(
}
}
void ArbitraryResourceWorker::ExposeEmbeddeds(gd::String& resourceName) {
if (resourcesManagers.empty()) return;
gd::ResourcesManager* resourcesManager = resourcesManagers[0];
gd::Resource& resource = resourcesManager->GetResource(resourceName);
if (!resource.GetMetadata().empty()) {
gd::SerializerElement serializerElement =
gd::Serializer::FromJSON(resource.GetMetadata());
if (serializerElement.HasChild("embeddedResourcesMapping")) {
bool anyEmbeddedResourceNameWasRenamed = false;
gd::SerializerElement& embeddedResourcesMappingElement =
serializerElement.GetChild("embeddedResourcesMapping");
for (const auto& child :
embeddedResourcesMappingElement.GetAllChildren()) {
const gd::String& targetResourceName =
child.second->GetValue().GetString();
if (resourcesManager->HasResource(targetResourceName)) {
std::cout << targetResourceName << std::endl;
gd::Resource& targetResource =
resourcesManager->GetResource(targetResourceName);
const gd::String& targetResourceKind = targetResource.GetKind();
gd::String potentiallyUpdatedTargetResourceName = targetResourceName;
if (targetResourceKind == "audio") {
ExposeAudio(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "bitmapFont") {
ExposeBitmapFont(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "font") {
ExposeFont(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "image") {
ExposeImage(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "json") {
ExposeJson(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "tilemap") {
ExposeTilemap(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "tileset") {
ExposeTileset(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "video") {
ExposeVideo(potentiallyUpdatedTargetResourceName);
}
if (potentiallyUpdatedTargetResourceName != targetResourceName) {
// The resource name was renamed. Also update the mapping.
child.second->SetStringValue(potentiallyUpdatedTargetResourceName);
anyEmbeddedResourceNameWasRenamed = true;
}
}
}
if (anyEmbeddedResourceNameWasRenamed) {
resource.SetMetadata(gd::Serializer::ToJSON(serializerElement));
}
}
}
}
void ArbitraryResourceWorker::ExposeResource(gd::Resource& resource) {
if (!resource.UseFile()) return;
@@ -154,6 +225,14 @@ class ResourceWorkerInEventsWorker : public ArbitraryEventsWorker {
gd::String updatedParameterValue = parameterValue;
worker.ExposeJson(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
} else if (parameterMetadata.GetType() == "tilemapResource") {
gd::String updatedParameterValue = parameterValue;
worker.ExposeTilemap(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
} else if (parameterMetadata.GetType() == "tilesetResource") {
gd::String updatedParameterValue = parameterValue;
worker.ExposeTileset(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
}
});

View File

@@ -75,6 +75,16 @@ class GD_CORE_API ArbitraryResourceWorker {
*/
virtual void ExposeJson(gd::String &jsonName);
/**
* \brief Expose a Tilemap, which is always a reference to a "tilemap" resource.
*/
virtual void ExposeTilemap(gd::String &tilemapName);
/**
* \brief Expose a Tileset, which is always a reference to a "tileset" resource.
*/
virtual void ExposeTileset(gd::String &tilesetName);
/**
* \brief Expose a video, which is always a reference to a "video" resource.
*/
@@ -96,6 +106,11 @@ class GD_CORE_API ArbitraryResourceWorker {
*/
virtual void ExposeFile(gd::String &resourceFileName) = 0;
/**
* \brief Expose the embedded resources of the specified resource.
*/
virtual void ExposeEmbeddeds(gd::String &resourceName);
protected:
const std::vector<gd::ResourcesManager *> &GetResources() {
return resourcesManagers;

View File

@@ -40,6 +40,8 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
std::set<gd::String>& GetAllAudios() { return GetAll("audio"); };
std::set<gd::String>& GetAllFonts() { return GetAll("font"); };
std::set<gd::String>& GetAllJsons() { return GetAll("json"); };
std::set<gd::String>& GetAllTilemaps() { return GetAll("tilemap"); };
std::set<gd::String>& GetAllTilesets() { return GetAll("tileset"); };
std::set<gd::String>& GetAllVideos() { return GetAll("video"); };
std::set<gd::String>& GetAllBitmapFonts() { return GetAll("bitmapFont"); };
std::set<gd::String>& GetAll(const gd::String& resourceType) {
@@ -47,6 +49,8 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
if (resourceType == "audio") return allAudios;
if (resourceType == "font") return allFonts;
if (resourceType == "json") return allJsons;
if (resourceType == "tilemap") return allTilemaps;
if (resourceType == "tileset") return allTilesets;
if (resourceType == "video") return allVideos;
if (resourceType == "bitmapFont") return allBitmapFonts;
@@ -68,6 +72,12 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
virtual void ExposeJson(gd::String& jsonResourceName) override {
allJsons.insert(jsonResourceName);
};
virtual void ExposeTilemap(gd::String& tilemapResourceName) override {
allTilemaps.insert(tilemapResourceName);
};
virtual void ExposeTileset(gd::String& tilesetResourceName) override {
allTilesets.insert(tilesetResourceName);
};
virtual void ExposeVideo(gd::String& videoResourceName) override {
allVideos.insert(videoResourceName);
};
@@ -80,6 +90,8 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
std::set<gd::String> allAudios;
std::set<gd::String> allFonts;
std::set<gd::String> allJsons;
std::set<gd::String> allTilemaps;
std::set<gd::String> allTilesets;
std::set<gd::String> allVideos;
std::set<gd::String> allBitmapFonts;
std::set<gd::String> emptyResources;

View File

@@ -49,6 +49,12 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
virtual void ExposeJson(gd::String& jsonResourceName) override {
RenameIfNeeded(jsonResourceName);
};
virtual void ExposeTilemap(gd::String& tilemapResourceName) override {
RenameIfNeeded(tilemapResourceName);
};
virtual void ExposeTileset(gd::String& tilesetResourceName) override {
RenameIfNeeded(tilesetResourceName);
};
virtual void ExposeVideo(gd::String& videoResourceName) override {
RenameIfNeeded(videoResourceName);
};

View File

@@ -0,0 +1,314 @@
/*
* GDevelop Core
* Copyright 2008-2022 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "PropertyFunctionGenerator.h"
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/String.h"
namespace gd {
void PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::NamedPropertyDescriptor &property, bool isSharedProperties) {
GenerateGetterAndSetter(project, extension, eventsBasedBehavior, property,
eventsBasedBehavior.GetObjectType(), true,
isSharedProperties);
}
void PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::EventsBasedObject &eventsBasedObject,
const gd::NamedPropertyDescriptor &property) {
GenerateGetterAndSetter(project, extension, eventsBasedObject, property, "",
false, false);
}
void PropertyFunctionGenerator::GenerateGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
bool isBehavior, bool isSharedProperties) {
auto &propertyName = property.GetName();
auto &functionsContainer = eventsBasedEntity.GetEventsFunctions();
gd::String capitalizedName = CapitalizeFirstLetter(property.GetName());
gd::String setterName = "Set" + capitalizedName;
gd::String functionGroupName =
(eventsBasedEntity.GetFullName().empty()
? eventsBasedEntity.GetName()
: eventsBasedEntity.GetFullName()) +
(property.GetGroup().empty()
? ""
: " " + UnCapitalizeFirstLetter(property.GetGroup())) +
" configuration";
gd::String propertyLabel =
property.GetLabel().empty() ? property.GetName() : property.GetLabel();
gd::String descriptionSubject =
(property.GetType() == "Boolean" ? "if " : "the ") +
UnCapitalizeFirstLetter(propertyLabel) +
(isSharedProperties || property.GetType() == "Boolean"
? "."
: " of the object.") +
(property.GetDescription().empty() ? ""
: " " + property.GetDescription()) +
(isSharedProperties
? " While an object is needed, this will apply to all "
"objects using the behavior."
: "");
gd::String propertyGetterName =
(isSharedProperties ? "SharedProperty" : "Property") + property.GetName();
gd::String getterType =
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
extension.GetName(), eventsBasedEntity.GetName(), propertyGetterName);
gd::String setterType =
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
extension.GetName(), eventsBasedEntity.GetName(),
"Set" + propertyGetterName);
gd::String getterName = capitalizedName;
gd::String numberOrString =
property.GetType() == "Number" ? "Number" : "String";
if (!functionsContainer.HasEventsFunctionNamed(getterName)) {
auto &getter = functionsContainer.InsertNewEventsFunction(
getterName, functionsContainer.GetEventsFunctionsCount());
auto &expressionType =
gd::ValueTypeMetadata::ConvertPropertyTypeToValueType(
property.GetType());
// TODO Stop replacing number by expression when it"s handled by the UI
// and released.
auto &legacyExpressionType =
expressionType == "number" ? "expression" : expressionType;
getter.GetExpressionType()
.SetName(legacyExpressionType)
.SetExtraInfo(GetStringifiedExtraInfo(property));
getter.SetFullName(propertyLabel).SetGroup(functionGroupName);
if (property.GetType() == "Boolean") {
getter.SetFunctionType(gd::EventsFunction::Condition)
.SetDescription("Check " + descriptionSubject)
.SetSentence("_PARAM0_ " + UnCapitalizeFirstLetter(propertyLabel));
} else {
getter.SetFunctionType(gd::EventsFunction::ExpressionAndCondition)
.SetDescription(descriptionSubject)
.SetSentence("the " + UnCapitalizeFirstLetter(propertyLabel));
}
auto &event =
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard", 0));
if (property.GetType() == "Boolean") {
gd::Instruction condition;
condition.SetType(getterType);
condition.AddParameter("Object");
if (isBehavior) {
condition.AddParameter("Behavior");
}
event.GetConditions().Insert(condition, 0);
gd::Instruction action;
action.SetType("SetReturnBoolean");
action.AddParameter("True");
event.GetActions().Insert(action, 0);
} else {
gd::Instruction action;
action.SetType("SetReturn" + numberOrString);
gd::String receiver = isBehavior ? "Object.Behavior::" : "Object.";
gd::String propertyPrefix =
(isSharedProperties ? "SharedProperty" : "Property");
action.AddParameter(receiver + propertyPrefix + property.GetName() +
"()");
event.GetActions().Insert(action, 0);
}
}
if (!functionsContainer.HasEventsFunctionNamed(setterName)) {
auto &setter = functionsContainer.InsertNewEventsFunction(
setterName, functionsContainer.GetEventsFunctionsCount());
if (property.GetType() == "Boolean") {
setter.SetFunctionType(gd::EventsFunction::Action)
.SetFullName(propertyLabel)
.SetGroup(functionGroupName)
.SetDescription("Change " + descriptionSubject)
.SetSentence("_PARAM0_ " + UnCapitalizeFirstLetter(propertyLabel) +
(isBehavior ? ": _PARAM2_" : ": _PARAM1_"));
gd::ParameterMetadata objectParameter;
objectParameter.SetType("object")
.SetName("Object")
.SetDescription("Object")
.SetExtraInfo(objectType);
if (!isBehavior) {
gd::String objectFullType = gd::PlatformExtension::GetObjectFullType(
extension.GetName(), eventsBasedEntity.GetName());
objectParameter.SetExtraInfo(objectFullType);
}
setter.GetParameters().push_back(objectParameter);
if (isBehavior) {
gd::ParameterMetadata behaviorParameter;
gd::String behaviorFullType =
gd::PlatformExtension::GetBehaviorFullType(
extension.GetName(), eventsBasedEntity.GetName());
behaviorParameter.SetType("behavior")
.SetName("Behavior")
.SetDescription("Behavior")
.SetExtraInfo(behaviorFullType);
setter.GetParameters().push_back(behaviorParameter);
}
gd::ParameterMetadata valueParameter;
valueParameter.SetType("yesorno")
.SetName("Value")
.SetDescription(capitalizedName)
.SetOptional(true)
.SetDefaultValue("yes");
setter.GetParameters().push_back(valueParameter);
} else {
setter.SetFunctionType(gd::EventsFunction::ActionWithOperator);
setter.SetGetterName(getterName);
}
if (property.GetType() == "Boolean") {
{
auto &event =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard", 0));
gd::Instruction condition;
condition.SetType("GetArgumentAsBoolean");
condition.AddParameter("\"Value\"");
event.GetConditions().Insert(condition, 0);
gd::Instruction action;
action.SetType(setterType);
action.AddParameter("Object");
if (isBehavior) {
action.AddParameter("Behavior");
action.AddParameter("yes");
} else {
action.AddParameter("yes");
}
event.GetActions().Insert(action, 0);
}
{
auto &event =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard", 0));
gd::Instruction condition;
condition.SetType("GetArgumentAsBoolean");
condition.AddParameter("\"Value\"");
condition.SetInverted(true);
event.GetConditions().Insert(condition, 0);
gd::Instruction action;
action.SetType(setterType);
action.AddParameter("Object");
if (isBehavior) {
action.AddParameter("Behavior");
action.AddParameter("no");
} else {
action.AddParameter("no");
}
event.GetActions().Insert(action, 0);
}
} else {
auto &event =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard", 0));
gd::Instruction action;
action.SetType(setterType);
action.AddParameter("Object");
gd::String parameterGetterCall =
"GetArgumentAs" + numberOrString + "(\"Value\")";
if (isBehavior) {
action.AddParameter("Behavior");
action.AddParameter("=");
action.AddParameter(parameterGetterCall);
} else {
action.AddParameter("=");
action.AddParameter(parameterGetterCall);
}
event.GetActions().Insert(action, 0);
}
}
}
bool PropertyFunctionGenerator::CanGenerateGetterAndSetter(
const gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property) {
auto &type = property.GetType();
if (type != "Boolean" && type != "Number" && type != "String" &&
type != "Choice" && type != "Color") {
return false;
}
auto &functionsContainer = eventsBasedEntity.GetEventsFunctions();
auto getterName = CapitalizeFirstLetter(property.GetName());
auto setterName = "Set" + getterName;
return !functionsContainer.HasEventsFunctionNamed(setterName) &&
!functionsContainer.HasEventsFunctionNamed(getterName);
};
gd::String PropertyFunctionGenerator::GetStringifiedExtraInfo(
const gd::PropertyDescriptor &property) {
if (property.GetType() == "Choice") {
gd::String arrayString;
arrayString += "[";
bool isFirst = true;
for (const gd::String &choice : property.GetExtraInfo()) {
if (!isFirst) {
arrayString += ",";
}
isFirst = false;
arrayString += "\"" + choice + "\"";
}
arrayString += "]";
return arrayString;
}
return "";
}
gd::String
PropertyFunctionGenerator::CapitalizeFirstLetter(const gd::String &string) {
if (string.empty()) {
return string;
}
return string.substr(0, 1).UpperCase() + string.substr(1);
}
gd::String
PropertyFunctionGenerator::UnCapitalizeFirstLetter(const gd::String &string) {
if (string.empty()) {
return string;
}
return string.substr(0, 1).LowerCase() + string.substr(1);
}
void PropertyFunctionGenerator::GenerateConditionSkeleton(
gd::Project &project, gd::EventsFunction &eventFunction) {
auto &event = dynamic_cast<gd::StandardEvent &>(
eventFunction.GetEvents().InsertNewEvent(
project, "BuiltinCommonInstructions::Standard", 0));
gd::Instruction action;
action.SetType("SetReturnBoolean");
action.AddParameter("True");
event.GetActions().Insert(action, 0);
}
} // namespace gd

View File

@@ -0,0 +1,72 @@
/*
* GDevelop Core
* Copyright 2008-2022 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_PROPERTYFUNCTIONGENERATOR_H
#define GDCORE_PROPERTYFUNCTIONGENERATOR_H
namespace gd {
class String;
class Project;
class EventsFunctionsExtension;
class EventsFunction;
class EventsBasedBehavior;
class EventsBasedObject;
class AbstractEventsBasedEntity;
class PropertyDescriptor;
class NamedPropertyDescriptor;
} // namespace gd
namespace gd {
/**
* \brief Generate a getter and a setter functions for properties.
*/
class GD_CORE_API PropertyFunctionGenerator {
public:
/**
* \brief Generate a getter and a setter for the given behavior property.
*/
static void GenerateBehaviorGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::NamedPropertyDescriptor &property, bool isSharedProperties);
/**
* \brief Generate a getter and a setter for the given object property.
*/
static void
GenerateObjectGetterAndSetter(gd::Project &project,
gd::EventsFunctionsExtension &extension,
gd::EventsBasedObject &eventsBasedObject,
const gd::NamedPropertyDescriptor &property);
static bool CanGenerateGetterAndSetter(
const gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property);
/**
* \brief Generate an event with a "return" action.
*/
static void GenerateConditionSkeleton(gd::Project &project,
gd::EventsFunction &eventFunction);
~PropertyFunctionGenerator();
private:
static void GenerateGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
bool isBehavior, bool isSharedProperties);
static gd::String CapitalizeFirstLetter(const gd::String &string);
static gd::String UnCapitalizeFirstLetter(const gd::String &string);
static gd::String
GetStringifiedExtraInfo(const gd::PropertyDescriptor &property);
PropertyFunctionGenerator();
};
} // namespace gd
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H

View File

@@ -35,40 +35,6 @@
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace {
// These functions are doing the reverse of what is done when adding
// instructions/expression to extension/behaviors. If needed, they could be
// moved to gd::PlatformExtension to colocate the usage of the namespace
// separator?
gd::String GetEventsFunctionFullType(const gd::String& extensionName,
const gd::String& functionName) {
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
return extensionName + separator + functionName;
}
gd::String GetBehaviorEventsFunctionFullType(const gd::String& extensionName,
const gd::String& behaviorName,
const gd::String& functionName) {
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
return extensionName + separator + behaviorName + separator + functionName;
}
gd::String GetBehaviorFullType(const gd::String& extensionName,
const gd::String& behaviorName) {
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
return extensionName + separator + behaviorName;
}
gd::String GetObjectEventsFunctionFullType(const gd::String& extensionName,
const gd::String& objectName,
const gd::String& functionName) {
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
return extensionName + separator + objectName + separator + functionName;
}
gd::String GetObjectFullType(const gd::String& extensionName,
const gd::String& objectName) {
const auto& separator = gd::PlatformExtension::GetNamespaceSeparator();
return extensionName + separator + objectName;
}
} // namespace
namespace gd {
// By convention, the first parameter of an events based behavior method is
@@ -83,14 +49,8 @@ void WholeProjectRefactorer::ExposeProjectEvents(
// See also gd::Project::ExposeResources for a method that traverse the whole
// project (this time for resources).
// Add layouts events
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
worker.Launch(project.GetLayout(s).GetEvents());
}
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
worker.Launch(project.GetExternalEvents(s).GetEvents());
}
ExposeProjectEventsWithoutExtensions(project, worker);
// Add events based extensions
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
@@ -124,6 +84,18 @@ void WholeProjectRefactorer::ExposeProjectEvents(
}
}
void WholeProjectRefactorer::ExposeProjectEventsWithoutExtensions(
gd::Project& project, gd::ArbitraryEventsWorker& worker) {
// Add layouts events
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
worker.Launch(project.GetLayout(s).GetEvents());
}
// Add external events events
for (std::size_t s = 0; s < project.GetExternalEventsCount(); s++) {
worker.Launch(project.GetExternalEvents(s).GetEvents());
}
}
void WholeProjectRefactorer::ExposeProjectEvents(
gd::Project& project, gd::ArbitraryEventsWorkerWithContext& worker) {
// See also gd::Project::ExposeResources for a method that traverse the whole
@@ -252,7 +224,7 @@ WholeProjectRefactorer::GetAllObjectTypesUsingEventsBasedBehavior(
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
const gd::EventsBasedBehavior& eventsBasedBehavior) {
std::set<gd::String> allTypes;
const gd::String behaviorType = GetBehaviorFullType(
const gd::String behaviorType = gd::PlatformExtension::GetBehaviorFullType(
eventsFunctionsExtension.GetName(), eventsBasedBehavior.GetName());
auto addTypesOfObjectsIn =
@@ -295,7 +267,7 @@ void WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
.SetType("behavior")
.SetName("Behavior")
.SetDescription("Behavior")
.SetExtraInfo(GetBehaviorFullType(eventsFunctionsExtension.GetName(),
.SetExtraInfo(gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()));
}
}
@@ -315,7 +287,7 @@ void WholeProjectRefactorer::EnsureObjectEventsFunctionsProperParameters(
.SetType("object")
.SetName(parentObjectParameterName)
.SetDescription("Object")
.SetExtraInfo(GetObjectFullType(eventsFunctionsExtension.GetName(),
.SetExtraInfo(gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName()));
}
}
@@ -330,8 +302,8 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
DoRenameEventsFunction(
project,
eventsFunction,
GetEventsFunctionFullType(oldName, eventsFunction.GetName()),
GetEventsFunctionFullType(newName, eventsFunction.GetName()));
gd::PlatformExtension::GetEventsFunctionFullType(oldName, eventsFunction.GetName()),
gd::PlatformExtension::GetEventsFunctionFullType(newName, eventsFunction.GetName()));
};
auto renameBehaviorEventsFunction =
@@ -344,10 +316,10 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(oldName,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(oldName,
eventsBasedBehavior.GetName(),
eventsFunction.GetName()),
GetBehaviorEventsFunctionFullType(newName,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(newName,
eventsBasedBehavior.GetName(),
eventsFunction.GetName()));
ExposeProjectEvents(project, renamer);
@@ -360,12 +332,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
const gd::NamedPropertyDescriptor& property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
oldName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetPropertyActionName(
property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
newName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetPropertyActionName(
@@ -375,12 +347,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
gd::InstructionsTypeRenamer conditionRenamer =
gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
oldName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetPropertyConditionName(
property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
newName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetPropertyConditionName(
@@ -397,12 +369,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
const gd::NamedPropertyDescriptor& property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
oldName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyActionName(
property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
newName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyActionName(
@@ -412,12 +384,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
gd::InstructionsTypeRenamer conditionRenamer =
gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
oldName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyConditionName(
property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
newName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyConditionName(
@@ -438,10 +410,10 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(oldName,
gd::PlatformExtension::GetObjectEventsFunctionFullType(oldName,
eventsBasedObject.GetName(),
eventsFunction.GetName()),
GetObjectEventsFunctionFullType(newName,
gd::PlatformExtension::GetObjectEventsFunctionFullType(newName,
eventsBasedObject.GetName(),
eventsFunction.GetName()));
ExposeProjectEvents(project, renamer);
@@ -454,12 +426,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
const gd::NamedPropertyDescriptor& property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
oldName,
eventsBasedObject.GetName(),
gd::EventsBasedObject::GetPropertyActionName(
property.GetName())),
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
newName,
eventsBasedObject.GetName(),
gd::EventsBasedObject::GetPropertyActionName(
@@ -469,12 +441,12 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
gd::InstructionsTypeRenamer conditionRenamer =
gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
oldName,
eventsBasedObject.GetName(),
gd::EventsBasedObject::GetPropertyConditionName(
property.GetName())),
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
newName,
eventsBasedObject.GetName(),
gd::EventsBasedObject::GetPropertyConditionName(
@@ -566,8 +538,8 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
DoRenameBehavior(
project,
GetBehaviorFullType(oldName, eventsBasedBehavior->GetName()),
GetBehaviorFullType(newName, eventsBasedBehavior->GetName()));
gd::PlatformExtension::GetBehaviorFullType(oldName, eventsBasedBehavior->GetName()),
gd::PlatformExtension::GetBehaviorFullType(newName, eventsBasedBehavior->GetName()));
}
// Finally, rename custom objects type
@@ -575,8 +547,8 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
eventsFunctionsExtension.GetEventsBasedObjects().GetInternalVector()) {
DoRenameObject(
project,
GetObjectFullType(oldName, eventsBasedObject->GetName()),
GetObjectFullType(newName, eventsBasedObject->GetName()));
gd::PlatformExtension::GetObjectFullType(oldName, eventsBasedObject->GetName()),
gd::PlatformExtension::GetObjectFullType(newName, eventsBasedObject->GetName()));
}
}
@@ -593,9 +565,9 @@ void WholeProjectRefactorer::RenameEventsFunction(
DoRenameEventsFunction(
project,
eventsFunction,
GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
oldFunctionName),
GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetEventsFunctionFullType(eventsFunctionsExtension.GetName(),
newFunctionName));
if (eventsFunction.GetFunctionType() == gd::EventsFunction::ExpressionAndCondition) {
@@ -628,7 +600,7 @@ void WholeProjectRefactorer::RenameBehaviorEventsFunction(
gd::ExpressionsRenamer renamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
renamer.SetReplacedBehaviorExpression(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
oldFunctionName,
newFunctionName);
@@ -637,10 +609,10 @@ void WholeProjectRefactorer::RenameBehaviorEventsFunction(
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
oldFunctionName),
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
newFunctionName));
ExposeProjectEvents(project, renamer);
@@ -672,7 +644,7 @@ void WholeProjectRefactorer::RenameObjectEventsFunction(
gd::ExpressionsRenamer renamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
renamer.SetReplacedObjectExpression(
GetObjectFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName()),
oldFunctionName,
newFunctionName);
@@ -681,10 +653,10 @@ void WholeProjectRefactorer::RenameObjectEventsFunction(
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
oldFunctionName),
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
newFunctionName));
ExposeProjectEvents(project, renamer);
@@ -711,7 +683,7 @@ void WholeProjectRefactorer::MoveEventsFunctionParameter(
const gd::EventsFunction& eventsFunction =
eventsFunctionsExtension.GetEventsFunction(functionName);
const gd::String& eventsFunctionType = GetEventsFunctionFullType(
const gd::String& eventsFunctionType = gd::PlatformExtension::GetEventsFunctionFullType(
eventsFunctionsExtension.GetName(), functionName);
if (eventsFunction.IsExpression()) {
@@ -746,7 +718,7 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
eventsFunctions.GetEventsFunction(functionName);
const gd::String& eventsFunctionType =
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
functionName);
@@ -754,7 +726,7 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
gd::ExpressionsParameterMover mover =
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
mover.SetBehaviorExpressionMovedParameter(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
functionName,
oldIndex,
@@ -786,7 +758,7 @@ void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
eventsFunctions.GetEventsFunction(functionName);
const gd::String& eventsFunctionType =
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
functionName);
@@ -794,7 +766,7 @@ void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
gd::ExpressionsParameterMover mover =
gd::ExpressionsParameterMover(project.GetCurrentPlatform());
mover.SetObjectExpressionMovedParameter(
GetObjectFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName()),
functionName,
oldIndex,
@@ -846,7 +818,7 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
gd::ExpressionsRenamer expressionRenamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
expressionRenamer.SetReplacedBehaviorExpression(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
EventsBasedBehavior::GetPropertyExpressionName(oldPropertyName),
EventsBasedBehavior::GetPropertyExpressionName(newPropertyName));
@@ -854,11 +826,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyActionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyActionName(newPropertyName)));
@@ -866,11 +838,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyConditionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyConditionName(newPropertyName)));
@@ -912,7 +884,7 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorSharedProperty(
gd::ExpressionsRenamer expressionRenamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
expressionRenamer.SetReplacedBehaviorExpression(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
EventsBasedBehavior::GetSharedPropertyExpressionName(oldPropertyName),
EventsBasedBehavior::GetSharedPropertyExpressionName(newPropertyName));
@@ -920,11 +892,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorSharedProperty(
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyActionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyActionName(newPropertyName)));
@@ -932,11 +904,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorSharedProperty(
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyConditionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyConditionName(newPropertyName)));
@@ -962,7 +934,7 @@ void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
gd::ExpressionsRenamer expressionRenamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
expressionRenamer.SetReplacedObjectExpression(
GetObjectFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName()),
EventsBasedObject::GetPropertyExpressionName(oldPropertyName),
EventsBasedObject::GetPropertyExpressionName(newPropertyName));
@@ -970,11 +942,11 @@ void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
EventsBasedObject::GetPropertyActionName(oldPropertyName)),
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
EventsBasedObject::GetPropertyActionName(newPropertyName)));
@@ -982,11 +954,11 @@ void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
EventsBasedObject::GetPropertyConditionName(oldPropertyName)),
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
EventsBasedObject::GetPropertyConditionName(newPropertyName)));
@@ -1223,11 +1195,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldBehaviorName,
eventsFunction.GetName()),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newBehaviorName,
eventsFunction.GetName()));
@@ -1243,11 +1215,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldBehaviorName,
EventsBasedBehavior::GetPropertyActionName(property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newBehaviorName,
EventsBasedBehavior::GetPropertyActionName(property.GetName())));
@@ -1255,11 +1227,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldBehaviorName,
EventsBasedBehavior::GetPropertyConditionName(property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newBehaviorName,
EventsBasedBehavior::GetPropertyConditionName(property.GetName())));
@@ -1277,11 +1249,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldBehaviorName,
EventsBasedBehavior::GetSharedPropertyActionName(property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newBehaviorName,
EventsBasedBehavior::GetSharedPropertyActionName(property.GetName())));
@@ -1289,11 +1261,11 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldBehaviorName,
EventsBasedBehavior::GetSharedPropertyConditionName(property.GetName())),
GetBehaviorEventsFunctionFullType(
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newBehaviorName,
EventsBasedBehavior::GetSharedPropertyConditionName(property.GetName())));
@@ -1332,8 +1304,8 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
DoRenameBehavior(
project,
GetBehaviorFullType(eventsFunctionsExtension.GetName(), oldBehaviorName),
GetBehaviorFullType(eventsFunctionsExtension.GetName(), newBehaviorName));
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(), oldBehaviorName),
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(), newBehaviorName));
}
void WholeProjectRefactorer::RenameEventsBasedObject(
@@ -1362,11 +1334,11 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
if (eventsFunction.IsAction() || eventsFunction.IsCondition()) {
gd::InstructionsTypeRenamer renamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldObjectName,
eventsFunction.GetName()),
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newObjectName,
eventsFunction.GetName()));
@@ -1382,11 +1354,11 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldObjectName,
EventsBasedObject::GetPropertyActionName(property.GetName())),
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newObjectName,
EventsBasedObject::GetPropertyActionName(property.GetName())));
@@ -1394,11 +1366,11 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldObjectName,
EventsBasedObject::GetPropertyConditionName(property.GetName())),
GetObjectEventsFunctionFullType(
gd::PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newObjectName,
EventsBasedObject::GetPropertyConditionName(property.GetName())));
@@ -1435,8 +1407,8 @@ void WholeProjectRefactorer::RenameEventsBasedObject(
DoRenameObject(
project,
GetObjectFullType(eventsFunctionsExtension.GetName(), oldObjectName),
GetObjectFullType(eventsFunctionsExtension.GetName(), newObjectName));
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(), oldObjectName),
gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(), newObjectName));
}
void WholeProjectRefactorer::DoRenameEventsFunction(

View File

@@ -47,6 +47,14 @@ class GD_CORE_API WholeProjectRefactorer {
*/
static void ExposeProjectEvents(gd::Project& project,
gd::ArbitraryEventsWorker& worker);
/**
* \brief Call the specified worker on all events of the project (layout and
* external events) but not events from extensions.
*
* Only use this for stats.
*/
static void ExposeProjectEventsWithoutExtensions(gd::Project& project,
gd::ArbitraryEventsWorker& worker);
/**
* \brief Call the specified worker on all events of the project (layout,

View File

@@ -125,6 +125,11 @@ class GD_CORE_API AbstractEventsBasedEntity {
*/
static gd::String GetPropertyExpressionName(const gd::String& propertyName) { return "Property" + propertyName; };
/**
* \brief Get the name of the action to toggle a boolean property.
*/
static gd::String GetPropertyToggleActionName(const gd::String& propertyName) { return "ToggleProperty" + propertyName; };
/** \name Serialization
*/
///@{

View File

@@ -38,7 +38,7 @@ gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(
return badObjectConfiguration;
}
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
if (!eventsBasedObject.HasObjectNamed(objectName)) {
gd::LogError("Tried to get the configuration of a child-object:" + objectName
+ " that doesn't exist in the event-based object: " + GetType());
@@ -78,7 +78,7 @@ bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
}
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
const auto &properties = eventsBasedObject.GetPropertyDescriptors();
return gd::CustomConfigurationHelper::UpdateProperty(
properties,
objectContent,
@@ -125,8 +125,7 @@ void CustomObjectConfiguration::DoUnserializeFrom(Project& project,
}
}
void CustomObjectConfiguration::ExposeResources(
gd::ArbitraryResourceWorker& worker) {
void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& worker) {
std::map<gd::String, gd::PropertyDescriptor> properties = GetProperties();
for (auto& property : properties) {
@@ -148,6 +147,10 @@ void CustomObjectConfiguration::ExposeResources(
worker.ExposeVideo(newPropertyValue);
} else if (resourceType == "json") {
worker.ExposeJson(newPropertyValue);
} else if (resourceType == "tilemap") {
worker.ExposeTilemap(newPropertyValue);
} else if (resourceType == "tileset") {
worker.ExposeTileset(newPropertyValue);
} else if (resourceType == "bitmapFont") {
worker.ExposeBitmapFont(newPropertyValue);
}

View File

@@ -87,9 +87,9 @@ class CustomObjectConfiguration : public gd::ObjectConfiguration {
/**
* Initialize configuration using another configuration. Used by copy-ctor
* and assign-op.
*
*
* Don't forget to update me if members were changed!
*
*
* It's needed because there is no default copy for childObjectConfigurations
* and it must be a deep copy.
*/

View File

@@ -125,6 +125,13 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
return "SharedProperty" + propertyName;
};
/**
* \brief Get the name of the action to toggle a boolean shared property.
*/
static gd::String GetSharedPropertyToggleActionName(const gd::String &propertyName) {
return "ToggleSharedProperty" + propertyName;
};
void SerializeTo(SerializerElement& element) const override;
void UnserializeFrom(gd::Project& project,

View File

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

View File

@@ -145,6 +145,11 @@ class GD_CORE_API EventsFunction {
*/
const gd::ValueTypeMetadata& GetExpressionType() const { return expressionType; }
/**
* \brief Get the type of the expression
*/
gd::ValueTypeMetadata& GetExpressionType() { return expressionType; }
enum FunctionType {
Action,
Condition,
@@ -206,6 +211,19 @@ class GD_CORE_API EventsFunction {
return *this;
}
/**
* \brief Returns true if the function is async.
*/
bool IsAsync() const { return isAsync; }
/**
* \brief Sets the asycronity of the function.
*/
EventsFunction& SetAsync(bool _isAsync) {
isAsync = _isAsync;
return *this;
}
/**
* \brief Return the events.
*/
@@ -286,6 +304,7 @@ class GD_CORE_API EventsFunction {
mutable std::vector<gd::ParameterMetadata> actionWithOperationParameters;
gd::ObjectGroupsContainer objectGroups;
bool isPrivate = false;
bool isAsync = false;
};
} // namespace gd

View File

@@ -7,13 +7,14 @@
#ifndef GDCORE_INITIALINSTANCE_H
#define GDCORE_INITIALINSTANCE_H
#include <map>
#include "GDCore/Project/VariablesContainer.h"
#include "GDCore/String.h"
namespace gd {
class PropertyDescriptor;
class Project;
class Layout;
}
} // namespace gd
namespace gd {
@@ -127,7 +128,8 @@ class GD_CORE_API InitialInstance {
void SetCustomHeight(double height_) { height = height_; }
/**
* \brief Return true if the instance is locked and cannot be moved in the IDE.
* \brief Return true if the instance is locked and cannot be moved in the
* IDE.
*/
bool IsLocked() const { return locked; };
@@ -240,7 +242,7 @@ class GD_CORE_API InitialInstance {
* \brief Set the value of a string property stored in the instance.
*/
void SetRawStringProperty(const gd::String& name, const gd::String& value);
///@}
///@}
/** \name Saving and loading
* Members functions related to serialization.
@@ -272,18 +274,19 @@ class GD_CORE_API InitialInstance {
stringProperties; ///< More data which can be used by the object
gd::String objectName; ///< Object name
double x; ///< Object initial X position
double y; ///< Object initial Y position
double angle; ///< Object initial angle
double x; ///< Object initial X position
double y; ///< Object initial Y position
double angle; ///< Object initial angle
int zOrder; ///< Object initial Z order
gd::String layer; ///< Object initial layer
bool personalizedSize; ///< True if object has a custom size
double width; ///< Object custom width
double height; ///< Object custom height
double width; ///< Object custom width
double height; ///< Object custom height
gd::VariablesContainer initialVariables; ///< Instance specific variables
bool locked; ///< True if the instance is locked
bool sealed; ///< True if the instance is sealed
mutable gd::String persistentUuid; ///< A persistent random version 4 UUID, useful for hot reloading.
mutable gd::String persistentUuid; ///< A persistent random version 4 UUID,
///< useful for hot reloading.
static gd::String*
badStringProperyValue; ///< Empty string returned by GetRawStringProperty

View File

@@ -60,7 +60,6 @@ void InitialInstancesContainer::IterateOverInstancesWithZOrdering(
for (auto& instance : sortedInstances) func(instance);
}
#if defined(GD_IDE_ONLY)
gd::InitialInstance& InitialInstancesContainer::InsertNewInitialInstance() {
gd::InitialInstance newInstance;
initialInstances.push_back(newInstance);
@@ -173,7 +172,6 @@ void InitialInstancesContainer::SerializeTo(SerializerElement& element) const {
}
void InitialInstancesContainer::Clear() { initialInstances.clear(); }
#endif
InitialInstanceFunctor::~InitialInstanceFunctor(){};

View File

@@ -11,7 +11,7 @@
namespace gd {
LoadingScreen::LoadingScreen()
: showGDevelopSplash(true),
: showGDevelopLogoDuringLoadingScreen(false),
gdevelopLogoStyle("light"),
backgroundImageResourceName(""),
backgroundColor(0),
@@ -27,7 +27,7 @@ LoadingScreen::LoadingScreen()
progressBarColor(0xFFFFFF){};
void LoadingScreen::SerializeTo(SerializerElement& element) const {
element.SetAttribute("showGDevelopSplash", showGDevelopSplash);
element.SetAttribute("showGDevelopSplash", showGDevelopLogoDuringLoadingScreen);
element.SetAttribute("gdevelopLogoStyle",
gdevelopLogoStyle);
element.SetAttribute("backgroundImageResourceName",
@@ -46,7 +46,7 @@ void LoadingScreen::SerializeTo(SerializerElement& element) const {
}
void LoadingScreen::UnserializeFrom(const SerializerElement& element) {
showGDevelopSplash = element.GetBoolAttribute("showGDevelopSplash", true);
showGDevelopLogoDuringLoadingScreen = element.GetBoolAttribute("showGDevelopSplash", true);
gdevelopLogoStyle =
element.GetStringAttribute("gdevelopLogoStyle", "light");
backgroundImageResourceName =

View File

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

View File

@@ -0,0 +1,27 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "MeasurementBaseUnit.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Localization.h"
#include <vector>
namespace gd {
MeasurementBaseUnit::~MeasurementBaseUnit() {}
const gd::MeasurementBaseUnit MeasurementBaseUnit::degreeAngle =
MeasurementBaseUnit("degree", "deg", "");
const gd::MeasurementBaseUnit MeasurementBaseUnit::pixel =
MeasurementBaseUnit("pixel", "px", "distance");
const gd::MeasurementBaseUnit MeasurementBaseUnit::meter =
MeasurementBaseUnit("meter", "m", "distance");
const gd::MeasurementBaseUnit MeasurementBaseUnit::second =
MeasurementBaseUnit("second", "s", "time");
const gd::MeasurementBaseUnit MeasurementBaseUnit::kilogram =
MeasurementBaseUnit("kilogram", "Kg", "mass");
} // namespace gd

View File

@@ -0,0 +1,57 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_MEASUREMENTBASEUNIT
#define GDCORE_MEASUREMENTBASEUNIT
#include <vector>
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
}
namespace gd {
/**
* \brief An atomic unit of measurement.
*/
class GD_CORE_API MeasurementBaseUnit {
public:
MeasurementBaseUnit(gd::String name_, gd::String symbol_,
gd::String quantity_)
: name(name_), symbol(symbol_), quantity(quantity_) {}
virtual ~MeasurementBaseUnit();
/**
* \brief Return the unit name.
*/
const gd::String &GetName() const { return name; }
/**
* \brief Return the unit symbol.
*/
const gd::String &GetSymbol() const { return symbol; }
/**
* \brief Return the physical quantity.
*/
const gd::String &GetQuantity() const { return quantity; }
static const gd::MeasurementBaseUnit degreeAngle;
static const gd::MeasurementBaseUnit pixel;
static const gd::MeasurementBaseUnit meter;
static const gd::MeasurementBaseUnit second;
static const gd::MeasurementBaseUnit kilogram;
private:
gd::String name; ///< The unit name
gd::String symbol; ///< The unit symbol
gd::String quantity; ///< The physical quantity
};
} // namespace gd
#endif // GDCORE_MEASUREMENTBASEUNIT

View File

@@ -0,0 +1,38 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "MeasurementUnit.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
#include <vector>
namespace gd {
MeasurementUnit::~MeasurementUnit() {}
gd::MeasurementUnit MeasurementUnit::undefined = CreateUndefined();
gd::MeasurementUnit MeasurementUnit::dimensionless = CreateDimensionless();
gd::MeasurementUnit MeasurementUnit::degreeAngle = CreateDegreeAngle();
gd::MeasurementUnit MeasurementUnit::second = CreateSecond();
gd::MeasurementUnit MeasurementUnit::pixel = CreatePixel();
gd::MeasurementUnit MeasurementUnit::pixelSpeed = CreatePixelSpeed();
gd::MeasurementUnit MeasurementUnit::pixelAcceleration =
CreatePixelAcceleration();
gd::MeasurementUnit MeasurementUnit::newton = CreateNewton();
gd::MeasurementUnit MeasurementUnit::angularSpeed = CreateAngularSpeed();
void MeasurementUnit::ApplyTranslation() {
undefined = CreateUndefined();
dimensionless = CreateDimensionless();
degreeAngle = CreateDegreeAngle();
second = CreateSecond();
pixel = CreatePixel();
pixelSpeed = CreatePixelSpeed();
pixelAcceleration = CreatePixelAcceleration();
newton = CreateNewton();
angularSpeed = CreateAngularSpeed();
}
} // namespace gd

View File

@@ -0,0 +1,197 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_MEASUREMENTUNIT
#define GDCORE_MEASUREMENTUNIT
#include <vector>
#include "GDCore/Project/MeasurementUnitElement.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Localization.h"
namespace gd {
class SerializerElement;
class MeasurementBaseUnit;
} // namespace gd
namespace gd {
/**
* \brief A unit of measurement.
*/
class GD_CORE_API MeasurementUnit {
public:
MeasurementUnit(const std::vector<gd::MeasurementUnitElement> &elements_,
gd::String name_, gd::String label_,
gd::String elementsWithWords_, gd::String description_ = "")
: elements(elements_), name(name_), label(label_),
description(description_), elementsWithWords(elementsWithWords_) {}
MeasurementUnit(gd::String name_, gd::String label_,
gd::String elementsWithWords_, gd::String description_ = "")
: name(name_), label(label_), description(description_),
elementsWithWords(elementsWithWords_) {}
virtual ~MeasurementUnit();
/**
* \brief Return the unit name.
*/
const gd::String &GetName() const { return name; }
/**
* \brief Return the unit label.
*/
const gd::String &GetLabel() const { return label; }
/**
* \brief Return the unit description.
*/
const gd::String &GetDescription() const { return description; }
/**
* \brief Return the unit description.
*/
const gd::String &GetElementsWithWords() const { return elementsWithWords; }
/**
* \brief Return the unit elements.
*/
const std::vector<gd::MeasurementUnitElement> &GetElements() const {
return elements;
}
std::size_t GetElementsCount() const { return elements.size(); }
int GetElementPower(std::size_t elementIndex) const {
return elements.at(elementIndex).GetPower();
}
const gd::MeasurementBaseUnit &
GetElementBaseUnit(std::size_t elementIndex) const {
return elements.at(elementIndex).GetBaseUnit();
}
bool IsUndefined() const { return this == &gd::MeasurementUnit::undefined; }
static void ApplyTranslation();
static gd::MeasurementUnit &GetUndefined() { return undefined; }
static gd::MeasurementUnit &GetDimensionless() { return dimensionless; }
static gd::MeasurementUnit &GetDegreeAngle() { return degreeAngle; }
static gd::MeasurementUnit &GetSecond() { return second; }
static gd::MeasurementUnit &GetPixel() { return pixel; }
static gd::MeasurementUnit &GetPixelSpeed() { return pixelSpeed; }
static gd::MeasurementUnit &GetPixelAcceleration() {
return pixelAcceleration;
}
static gd::MeasurementUnit &GetAngularSpeed() { return angularSpeed; }
static gd::MeasurementUnit &GetNewton() { return newton; }
private:
static gd::MeasurementUnit undefined;
static gd::MeasurementUnit dimensionless;
static gd::MeasurementUnit degreeAngle;
static gd::MeasurementUnit second;
static gd::MeasurementUnit pixel;
static gd::MeasurementUnit pixelSpeed;
static gd::MeasurementUnit pixelAcceleration;
static gd::MeasurementUnit newton;
static gd::MeasurementUnit angularSpeed;
static gd::MeasurementUnit CreateUndefined() {
return MeasurementUnit("Undefined", _("Undefined"), "");
}
static gd::MeasurementUnit CreateDimensionless() {
return MeasurementUnit("Dimensionless", _("Dimensionless"), "");
}
static gd::MeasurementUnit CreateDegreeAngle() {
std::vector<gd::MeasurementUnitElement> elements;
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::degreeAngle, 1));
return MeasurementUnit(elements, "DegreeAngle", _("Angle"), _("degree"));
}
static gd::MeasurementUnit CreateSecond() {
std::vector<gd::MeasurementUnitElement> elements;
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::second, 1));
return MeasurementUnit(elements, "Second", _("Duration"), _("second"));
}
static gd::MeasurementUnit CreatePixel() {
std::vector<gd::MeasurementUnitElement> elements;
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::pixel, 1));
return MeasurementUnit(elements, "Pixel", _("Distance"), _("pixel"));
}
static gd::MeasurementUnit CreatePixelSpeed() {
std::vector<gd::MeasurementUnitElement> elements;
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::pixel, 1));
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -1));
return MeasurementUnit(elements, "PixelSpeed", _("Speed"),
_("pixel per second"),
_("How much distance is covered per second."));
}
static gd::MeasurementUnit CreatePixelAcceleration() {
std::vector<gd::MeasurementUnitElement> elements;
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::pixel, 1));
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -2));
return MeasurementUnit(elements, "PixelAcceleration", _("Acceleration"),
_("pixel per second, per second"),
_("How much speed is gained (or lost) per second."));
}
static gd::MeasurementUnit CreateNewton() {
std::vector<gd::MeasurementUnitElement> elements;
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::meter, 1));
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::kilogram, 1));
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -2));
return MeasurementUnit(
elements, "Newton",
_("Force (in Newton)"), _("meter kilogram per second, per second"),
_("A unit to measure forces."));
}
static gd::MeasurementUnit CreateAngularSpeed() {
std::vector<gd::MeasurementUnitElement> elements;
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::degreeAngle, 1));
elements.push_back(
MeasurementUnitElement(gd::MeasurementBaseUnit::second, -1));
return MeasurementUnit(elements, "AngularSpeed", _("Angular speed"),
_("degree per second"),
_("How much angle is covered per second."));
}
gd::String name; ///< The unit name.
gd::String label; ///< The unit label.
gd::String description; ///< The unit description.
gd::String elementsWithWords; ///< The unit elements put in words.
std::vector<gd::MeasurementUnitElement> elements; ///< The unit elements.
};
} // namespace gd
#endif // GDCORE_MEASUREMENTUNIT

View File

@@ -0,0 +1,15 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "MeasurementUnitElement.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
#include <vector>
namespace gd {
MeasurementUnitElement::~MeasurementUnitElement() {}
} // namespace gd

View File

@@ -0,0 +1,46 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_MEASUREMENTUNITELEMENT
#define GDCORE_MEASUREMENTUNITELEMENT
#include <vector>
#include "GDCore/Project/MeasurementBaseUnit.h"
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
}
namespace gd {
/**
* \brief A couple of an atomic unit of measurement and its power.
*/
class GD_CORE_API MeasurementUnitElement {
public:
MeasurementUnitElement(const gd::MeasurementBaseUnit &baseUnit_, int power_)
: baseUnit(baseUnit_), power(power_) {}
virtual ~MeasurementUnitElement();
/**
* \brief Return the base unit.
*/
const gd::MeasurementBaseUnit &GetBaseUnit() const { return baseUnit; }
/**
* \brief Return the power on the base unit.
*/
int GetPower() const { return power; }
private:
gd::MeasurementBaseUnit baseUnit; ///< The base unit.
int power; ///< The power on the base unit.
};
} // namespace gd
#endif // GDCORE_MEASUREMENTUNITELEMENT

View File

@@ -12,6 +12,7 @@
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/EffectsContainer.h"
#include "GDCore/Project/ResourcesManager.h"
#include "GDCore/Project/VariablesContainer.h"
#include "GDCore/String.h"
#include "GDCore/Tools/MakeUnique.h"

View File

@@ -22,8 +22,8 @@
#include "GDCore/IDE/Events/UsedExtensionsFinder.h"
#include "GDCore/IDE/PlatformManager.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/CustomObjectConfiguration.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/ExternalLayout.h"
#include "GDCore/Project/Layout.h"
@@ -347,6 +347,49 @@ void Project::RemoveExternalEvents(const gd::String& name) {
externalEvents.erase(events);
}
void Project::MoveLayout(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= scenes.size() || newIndex >= scenes.size()) return;
std::unique_ptr<gd::Layout> scene = std::move(scenes[oldIndex]);
scenes.erase(scenes.begin() + oldIndex);
scenes.insert(scenes.begin() + newIndex, std::move(scene));
};
void Project::MoveExternalEvents(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= externalEvents.size() || newIndex >= externalEvents.size())
return;
std::unique_ptr<gd::ExternalEvents> externalEventsItem =
std::move(externalEvents[oldIndex]);
externalEvents.erase(externalEvents.begin() + oldIndex);
externalEvents.insert(externalEvents.begin() + newIndex,
std::move(externalEventsItem));
};
void Project::MoveExternalLayout(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= externalLayouts.size() || newIndex >= externalLayouts.size())
return;
std::unique_ptr<gd::ExternalLayout> externalLayout =
std::move(externalLayouts[oldIndex]);
externalLayouts.erase(externalLayouts.begin() + oldIndex);
externalLayouts.insert(externalLayouts.begin() + newIndex,
std::move(externalLayout));
};
void Project::MoveEventsFunctionsExtension(std::size_t oldIndex,
std::size_t newIndex) {
if (oldIndex >= eventsFunctionsExtensions.size() ||
newIndex >= eventsFunctionsExtensions.size())
return;
std::unique_ptr<gd::EventsFunctionsExtension> eventsFunctionsExtension =
std::move(eventsFunctionsExtensions[oldIndex]);
eventsFunctionsExtensions.erase(eventsFunctionsExtensions.begin() + oldIndex);
eventsFunctionsExtensions.insert(eventsFunctionsExtensions.begin() + newIndex,
std::move(eventsFunctionsExtension));
};
void Project::SwapExternalEvents(std::size_t first, std::size_t second) {
if (first >= externalEvents.size() || second >= externalEvents.size()) return;
@@ -593,6 +636,7 @@ void Project::UnserializeFrom(const SerializerElement& element) {
platformSpecificAssets.UnserializeFrom(
propElement.GetChild("platformSpecificAssets"));
loadingScreen.UnserializeFrom(propElement.GetChild("loadingScreen"));
watermark.UnserializeFrom(propElement.GetChild("watermark"));
useExternalSourceFiles =
propElement.GetBoolAttribute("useExternalSourceFiles");
@@ -603,6 +647,13 @@ void Project::UnserializeFrom(const SerializerElement& element) {
for (std::size_t i = 0; i < authorIdsElement.GetChildrenCount(); ++i) {
authorIds.push_back(authorIdsElement.GetChild(i).GetStringValue());
}
authorUsernames.clear();
auto& authorUsernamesElement = propElement.GetChild("authorUsernames");
authorUsernamesElement.ConsiderAsArray();
for (std::size_t i = 0; i < authorUsernamesElement.GetChildrenCount(); ++i) {
authorUsernames.push_back(
authorUsernamesElement.GetChild(i).GetStringValue());
}
categories.clear();
auto& categoriesElement = propElement.GetChild("categories");
@@ -832,6 +883,7 @@ void Project::SerializeTo(SerializerElement& element) const {
platformSpecificAssets.SerializeTo(
propElement.AddChild("platformSpecificAssets"));
loadingScreen.SerializeTo(propElement.AddChild("loadingScreen"));
watermark.SerializeTo(propElement.AddChild("watermark"));
propElement.SetAttribute("useExternalSourceFiles", useExternalSourceFiles);
auto& authorIdsElement = propElement.AddChild("authorIds");
@@ -839,6 +891,11 @@ void Project::SerializeTo(SerializerElement& element) const {
for (const auto& authorId : authorIds) {
authorIdsElement.AddChild("").SetStringValue(authorId);
}
auto& authorUsernamesElement = propElement.AddChild("authorUsernames");
authorUsernamesElement.ConsiderAsArray();
for (const auto& authorUsername : authorUsernames) {
authorUsernamesElement.AddChild("").SetStringValue(authorUsername);
}
auto& categoriesElement = propElement.AddChild("categories");
categoriesElement.ConsiderAsArray();
@@ -939,8 +996,10 @@ void Project::ExposeResources(gd::ArbitraryResourceWorker& worker) {
// (this time for effects). Ideally, this method could be moved outside of
// gd::Project.
gd::ResourcesManager* resourcesManager = &GetResourcesManager();
// Add project resources
worker.ExposeResources(&GetResourcesManager());
worker.ExposeResources(resourcesManager);
platformSpecificAssets.ExposeResources(worker);
// Add layouts resources
@@ -1052,6 +1111,7 @@ void Project::Init(const gd::Project& game) {
author = game.author;
authorIds = game.authorIds;
authorUsernames = game.authorUsernames;
isPlayableWithKeyboard = game.isPlayableWithKeyboard;
isPlayableWithGamepad = game.isPlayableWithGamepad;
isPlayableWithMobile = game.isPlayableWithMobile;
@@ -1062,6 +1122,7 @@ void Project::Init(const gd::Project& game) {
latestCompilationDirectory = game.latestCompilationDirectory;
platformSpecificAssets = game.platformSpecificAssets;
loadingScreen = game.loadingScreen;
watermark = game.watermark;
objectGroups = game.objectGroups;
extensionProperties = game.extensionProperties;

View File

@@ -11,6 +11,7 @@
#include "GDCore/Project/ExtensionProperties.h"
#include "GDCore/Project/LoadingScreen.h"
#include "GDCore/Project/Watermark.h"
#include "GDCore/Project/ObjectGroupsContainer.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/PlatformSpecificAssets.h"
@@ -120,6 +121,16 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::vector<gd::String>& GetAuthorIds() { return authorIds; };
/**
* \brief Get the author usernames of the project.
*/
const std::vector<gd::String>& GetAuthorUsernames() const { return authorUsernames; };
/**
* \brief Get the author usernames of the project, to modify them (non-const).
*/
std::vector<gd::String>& GetAuthorUsernames() { return authorUsernames; };
/**
* Define the project as playable with a keyboard.
* \param enable True to define the project as playable with a keyboard.
@@ -165,7 +176,7 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
const gd::String& GetPackageName() const { return packageName; }
/**
/**
* \brief Change the slug of the template from which the project is created.
*/
void SetTemplateSlug(const gd::String& templateSlug_) {
@@ -256,6 +267,16 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
const gd::LoadingScreen& GetLoadingScreen() const { return loadingScreen; }
/**
* \brief Return a reference to watermark setup for the project
*/
gd::Watermark& GetWatermark() { return watermark; }
/**
* \brief Return a reference to watermark setup for the project
*/
const gd::Watermark& GetWatermark() const { return watermark; }
/**
* Change game's main window default width.
*
@@ -458,7 +479,7 @@ class GD_CORE_API Project : public ObjectsContainer {
/**
* Create an object of the given type with the specified name.
*
*
* \param type The type of the object
* \param name The name of the object
*/
@@ -467,7 +488,7 @@ class GD_CORE_API Project : public ObjectsContainer {
/**
* Create an object configuration of the given type.
*
*
* \param type The type of the object
*/
std::unique_ptr<gd::ObjectConfiguration> CreateObjectConfiguration(
@@ -525,6 +546,11 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::size_t GetLayoutPosition(const gd::String& name) const;
/**
* Change the position of the specified layout.
*/
void MoveLayout(std::size_t oldIndex, std::size_t newIndex);
/**
* \brief Swap the specified layouts.
*
@@ -628,6 +654,11 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::size_t GetExternalEventsPosition(const gd::String& name) const;
/**
* Change the position of the specified external events.
*/
void MoveExternalEvents(std::size_t oldIndex, std::size_t newIndex);
/**
* \brief Swap the specified external events.
*
@@ -702,6 +733,11 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::size_t GetExternalLayoutPosition(const gd::String& name) const;
/**
* Change the position of the specified external layout.
*/
void MoveExternalLayout(std::size_t oldIndex, std::size_t newIndex);
/**
* \brief Swap the specified external layouts.
*
@@ -791,6 +827,11 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::size_t GetEventsFunctionsExtensionPosition(const gd::String& name) const;
/**
* Change the position of the specified events function extension.
*/
void MoveEventsFunctionsExtension(std::size_t oldIndex, std::size_t newIndex);
/**
* \brief Swap the specified events functions extensions.
*
@@ -1023,6 +1064,8 @@ class GD_CORE_API Project : public ObjectsContainer {
gd::String author; ///< Game author name, for publishing purpose.
std::vector<gd::String>
authorIds; ///< Game author ids, from GDevelop users DB.
std::vector<gd::String>
authorUsernames; ///< Game author usernames, from GDevelop users DB.
std::vector<gd::String>
categories; ///< Game categories
bool isPlayableWithKeyboard; ///< The project is playable with a keyboard.
@@ -1042,6 +1085,7 @@ class GD_CORE_API Project : public ObjectsContainer {
currentPlatform; ///< The platform being used to edit the project.
gd::PlatformSpecificAssets platformSpecificAssets;
gd::LoadingScreen loadingScreen;
gd::Watermark watermark;
std::vector<std::unique_ptr<gd::ExternalEvents> >
externalEvents; ///< List of all externals events
ExtensionProperties

View File

@@ -8,6 +8,8 @@
#include <vector>
#include "GDCore/String.h"
#include "GDCore/Project/MeasurementUnit.h"
namespace gd {
class SerializerElement;
}
@@ -28,12 +30,12 @@ class GD_CORE_API PropertyDescriptor {
* \param propertyValue The value of the property.
*/
PropertyDescriptor(gd::String propertyValue)
: currentValue(propertyValue), type("string"), label(""), hidden(false) {}
: currentValue(propertyValue), type("string"), label(""), hidden(false), measurementUnit(gd::MeasurementUnit::GetUndefined()) {}
/**
* \brief Empty constructor creating an empty property to be displayed.
*/
PropertyDescriptor() : hidden(false){};
PropertyDescriptor() : hidden(false), measurementUnit(gd::MeasurementUnit::GetUndefined()) {};
/**
* \brief Destructor
@@ -103,12 +105,21 @@ class GD_CORE_API PropertyDescriptor {
extraInformation.push_back(info);
return *this;
}
/**
* \brief Change the unit of measurement of the property value.
*/
PropertyDescriptor& SetMeasurementUnit(const gd::MeasurementUnit &measurementUnit_) {
measurementUnit = measurementUnit_;
return *this;
}
const gd::String& GetValue() const { return currentValue; }
const gd::String& GetType() const { return type; }
const gd::String& GetLabel() const { return label; }
const gd::String& GetDescription() const { return description; }
const gd::String& GetGroup() const { return group; }
const gd::MeasurementUnit& GetMeasurementUnit() const { return measurementUnit; }
const std::vector<gd::String>& GetExtraInfo() const {
return extraInformation;
@@ -168,6 +179,7 @@ class GD_CORE_API PropertyDescriptor {
///< choices, if a property is a displayed as a combo
///< box.
bool hidden;
gd::MeasurementUnit measurementUnit; //< The unit of measurement of the property vale.
};
} // namespace gd

View File

@@ -85,6 +85,10 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
return std::make_shared<VideoResource>();
else if (kind == "json")
return std::make_shared<JsonResource>();
else if (kind == "tilemap")
return std::make_shared<TilemapResource>();
else if (kind == "tileset")
return std::make_shared<TilesetResource>();
else if (kind == "bitmapFont")
return std::make_shared<BitmapFontResource>();
@@ -650,6 +654,74 @@ bool JsonResource::UpdateProperty(const gd::String& name,
return true;
}
void TilemapResource::SetFile(const gd::String& newFile) {
file = NormalizePathSeparator(newFile);
}
void TilemapResource::UnserializeFrom(const SerializerElement& element) {
SetUserAdded(element.GetBoolAttribute("userAdded"));
SetFile(element.GetStringAttribute("file"));
DisablePreload(element.GetBoolAttribute("disablePreload", false));
}
void TilemapResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute("file", GetFile());
element.SetAttribute("disablePreload", IsPreloadDisabled());
}
std::map<gd::String, gd::PropertyDescriptor> TilemapResource::GetProperties()
const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties["disablePreload"]
.SetValue(disablePreload ? "true" : "false")
.SetType("Boolean")
.SetLabel(_("Disable preloading at game startup"));
return properties;
}
bool TilemapResource::UpdateProperty(const gd::String& name,
const gd::String& value) {
if (name == "disablePreload") disablePreload = value == "1";
return true;
}
void TilesetResource::SetFile(const gd::String& newFile) {
file = NormalizePathSeparator(newFile);
}
void TilesetResource::UnserializeFrom(const SerializerElement& element) {
SetUserAdded(element.GetBoolAttribute("userAdded"));
SetFile(element.GetStringAttribute("file"));
DisablePreload(element.GetBoolAttribute("disablePreload", false));
}
void TilesetResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute("file", GetFile());
element.SetAttribute("disablePreload", IsPreloadDisabled());
}
std::map<gd::String, gd::PropertyDescriptor> TilesetResource::GetProperties()
const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties["disablePreload"]
.SetValue(disablePreload ? "true" : "false")
.SetType("Boolean")
.SetLabel(_("Disable preloading at game startup"));
return properties;
}
bool TilesetResource::UpdateProperty(const gd::String& name,
const gd::String& value) {
if (name == "disablePreload") disablePreload = value == "1";
return true;
}
void BitmapFontResource::SetFile(const gd::String& newFile) {
file = NormalizePathSeparator(newFile);
}

View File

@@ -373,6 +373,88 @@ class GD_CORE_API JsonResource : public Resource {
gd::String file;
};
/**
* \brief Describe a tilemap file used by a project.
*
* \see Resource
* \ingroup ResourcesManagement
*/
class GD_CORE_API TilemapResource : public Resource {
public:
TilemapResource() : Resource(), disablePreload(false) { SetKind("tilemap"); };
virtual ~TilemapResource(){};
virtual TilemapResource* Clone() const override {
return new TilemapResource(*this);
}
virtual const gd::String& GetFile() const override { return file; };
virtual void SetFile(const gd::String& newFile) override;
virtual bool UseFile() const override { return true; }
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const override;
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
void SerializeTo(SerializerElement& element) const override;
void UnserializeFrom(const SerializerElement& element) override;
/**
* \brief Return true if the loading at game startup must be disabled
*/
bool IsPreloadDisabled() const { return disablePreload; }
/**
* \brief Set if the tilemap preload at game startup must be disabled
*/
void DisablePreload(bool disable = true) { disablePreload = disable; }
private:
bool disablePreload; ///< If "true", don't load the tilemap at game startup
gd::String file;
};
/**
* \brief Describe a tileset file used by a project.
*
* \see Resource
* \ingroup ResourcesManagement
*/
class GD_CORE_API TilesetResource : public Resource {
public:
TilesetResource() : Resource(), disablePreload(false) { SetKind("tileset"); };
virtual ~TilesetResource(){};
virtual TilesetResource* Clone() const override {
return new TilesetResource(*this);
}
virtual const gd::String& GetFile() const override { return file; };
virtual void SetFile(const gd::String& newFile) override;
virtual bool UseFile() const override { return true; }
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const override;
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
void SerializeTo(SerializerElement& element) const override;
void UnserializeFrom(const SerializerElement& element) override;
/**
* \brief Return true if the loading at game startup must be disabled
*/
bool IsPreloadDisabled() const { return disablePreload; }
/**
* \brief Set if the tilemap preload at game startup must be disabled
*/
void DisablePreload(bool disable = true) { disablePreload = disable; }
private:
bool disablePreload; ///< If "true", don't load the tilemap at game startup
gd::String file;
};
/**
* \brief Describe a bitmap font file used by a project.
*

View File

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

View File

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

View File

@@ -289,9 +289,8 @@ void SerializerElement::Init(const gd::SerializerElement& other) {
deprecatedArrayOf = other.deprecatedArrayOf;
}
// TODO Remove shouldAlwayUseSetString in a release that follows the 150.
void SerializerElement::SetMultilineStringValue(const gd::String& value, bool shouldAlwayUseSetString) {
if (shouldAlwayUseSetString || value.find('\n') == gd::String::npos) {
void SerializerElement::SetMultilineStringValue(const gd::String& value) {
if (value.find('\n') == gd::String::npos) {
SetStringValue(value);
return;
}

View File

@@ -183,7 +183,7 @@ class GD_CORE_API SerializerElement {
* \brief Save the value either as a string or as an array of strings if it
* has line breaks.
*/
void SetMultilineStringValue(const gd::String &value, bool shouldAlwayUseSetString = true);
void SetMultilineStringValue(const gd::String &value);
/**
* \brief Read the value, either represented as a string or as an array of strings,

View File

@@ -3,8 +3,7 @@
#ifndef GDCORE_VECTOR2_H
#define GDCORE_VECTOR2_H
namespace gd
{
namespace gd {
////////////////////////////////////////////////////////////
//
@@ -12,11 +11,12 @@ namespace gd
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
// In no event will the authors be held liable for any damages arising from the
// use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.

View File

@@ -12,6 +12,7 @@
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "catch.hpp"
// TODO Remove these 2 classes and write the test with events based behaviors.
@@ -94,6 +95,13 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
// Don't show extension loading logs for tests (too verbose).
platform.EnableExtensionLoadingLogs(false);
// Required for tests on event generation.
std::shared_ptr<gd::PlatformExtension> commonInstructionsExtension =
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
commonInstructionsExtension->SetExtensionInformation(
"BuiltinCommonInstructions", "instruction extension", "", "", "");
commonInstructionsExtension->AddEvent("Standard", "Standard event", "", "", "", std::make_shared<gd::StandardEvent>());
std::shared_ptr<gd::PlatformExtension> baseObjectExtension =
std::shared_ptr<gd::PlatformExtension>(new gd::PlatformExtension);
@@ -179,7 +187,7 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
.SetDefaultValue("\"\"")
.AddParameter("camera", _("Camera"), "", true)
.SetDefaultValue("0")
.SetFunctionName("getMouseX");
.SetFunctionName("getCursorX");
extension
->AddExpression("GetGlobalVariableAsNumber",
"Get me a global variable value",
@@ -373,6 +381,7 @@ void SetupProjectWithDummyPlatform(gd::Project& project,
.AddUnsupportedBaseObjectCapability("effect");
}
platform.AddExtension(commonInstructionsExtension);
platform.AddExtension(baseObjectExtension);
platform.AddExtension(extension);
project.AddPlatform(platform);

View File

@@ -217,7 +217,7 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
REQUIRE(node);
node->Visit(expressionCodeGenerator);
REQUIRE(expressionCodeGenerator.GetOutput() ==
"getMouseX(\"\", \"layer1\", 2 + 2)");
"getCursorX(\"\", \"layer1\", 2 + 2)");
// (first argument is the currentScene)
}
SECTION("with last optional parameter omit") {
@@ -231,7 +231,7 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
REQUIRE(node);
node->Visit(expressionCodeGenerator);
REQUIRE(expressionCodeGenerator.GetOutput() ==
"getMouseX(\"\", \"layer1\", 0)");
"getCursorX(\"\", \"layer1\", 0)");
// (first argument is the currentScene)
}
SECTION("with last optional parameter omit (deprecated way)") {
@@ -245,7 +245,7 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
REQUIRE(node);
node->Visit(expressionCodeGenerator);
REQUIRE(expressionCodeGenerator.GetOutput() ==
"getMouseX(\"\", \"layer1\", 0)");
"getCursorX(\"\", \"layer1\", 0)");
// (first argument is the currentScene)
}
SECTION("with explicit comma (deprecated way)") {
@@ -258,7 +258,7 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
REQUIRE(node);
node->Visit(expressionCodeGenerator);
REQUIRE(expressionCodeGenerator.GetOutput() ==
"getMouseX(\"\", \"\", 0)");
"getCursorX(\"\", \"\", 0)");
// (first argument is the currentScene)
}
}
@@ -624,7 +624,7 @@ TEST_CASE("ExpressionCodeGenerator", "[common][events]") {
REQUIRE(node);
node->Visit(expressionCodeGenerator);
REQUIRE(expressionCodeGenerator.GetOutput() ==
"-(+(-(getMouseX(\"\", \"\", 0))))");
"-(+(-(getCursorX(\"\", \"\", 0))))");
// (first argument is the currentScene)
}
}

View File

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

View File

@@ -0,0 +1,739 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
/**
* @file Tests covering common features of GDevelop Core.
*/
#include "GDCore/IDE/PropertyFunctionGenerator.h"
#include "DummyPlatform.h"
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Extensions/Metadata/ValueTypeMetadata.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "catch.hpp"
namespace {
gd::EventsBasedBehavior &
CreateBehavior(gd::EventsFunctionsExtension &eventsExtension) {
auto &eventsBasedBehavior =
eventsExtension.GetEventsBasedBehaviors().InsertNew(
"MyEventsBasedBehavior", 0);
eventsBasedBehavior.SetFullName("My events based behavior");
eventsBasedBehavior.SetDescription("An events based behavior for test");
eventsBasedBehavior.SetObjectType("");
return eventsBasedBehavior;
};
gd::EventsBasedObject &
CreateObject(gd::EventsFunctionsExtension &eventsExtension) {
auto &eventsBasedObject = eventsExtension.GetEventsBasedObjects().InsertNew(
"MyEventsBasedObject", 0);
eventsBasedObject.SetFullName("My events based object");
eventsBasedObject.SetDescription("An events based object for test");
return eventsBasedObject;
};
} // namespace
TEST_CASE("PropertyFunctionGenerator", "[common]") {
SECTION("Can generate functions for a number property in a behavior") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number")
.SetLabel("Movement angle")
.SetDescription("The angle of the trajectory direction.")
.SetGroup("Movement");
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
project, extension, behavior, property, false);
REQUIRE(
behavior.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
"SetMovementAngle"));
{
auto &getter =
behavior.GetEventsFunctions().GetEventsFunction("MovementAngle");
REQUIRE(getter.GetFunctionType() ==
gd::EventsFunction::ExpressionAndCondition);
REQUIRE(getter.GetExpressionType().GetName() == "expression");
REQUIRE(getter.GetFullName() == "Movement angle");
REQUIRE(getter.GetGroup() ==
"My events based behavior movement configuration");
REQUIRE(getter.GetDescription() ==
"the movement angle of the object. The "
"angle of the trajectory direction.");
REQUIRE(getter.GetSentence() == "the movement angle");
// Object and behavior parameters are added automatically.
REQUIRE(getter.GetParameters().size() == 0);
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &getterEvent =
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
REQUIRE(getterEvent.GetConditions().size() == 0);
REQUIRE(getterEvent.GetActions().size() == 1);
auto &getterAction = getterEvent.GetActions().at(0);
REQUIRE(getterAction.GetType() == "SetReturnNumber");
REQUIRE(getterAction.GetParametersCount() == 1);
REQUIRE(getterAction.GetParameter(0).GetPlainString() ==
"Object.Behavior::PropertyMovementAngle()");
}
{
auto &setter =
behavior.GetEventsFunctions().GetEventsFunction("SetMovementAngle");
REQUIRE(setter.GetFunctionType() ==
gd::EventsFunction::ActionWithOperator);
REQUIRE(setter.GetGetterName() == "MovementAngle");
// These fields are deducted from the getter.
REQUIRE(setter.GetFullName() == "");
REQUIRE(setter.GetGroup() == "");
REQUIRE(setter.GetDescription() == "");
REQUIRE(setter.GetSentence() == "");
// Object and behavior parameters are added automatically.
REQUIRE(setter.GetParameters().size() == 0);
REQUIRE(setter.GetEvents().GetEventsCount() == 1);
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &setterEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
REQUIRE(setterEvent.GetConditions().size() == 0);
REQUIRE(setterEvent.GetActions().size() == 1);
auto &setterAction = setterEvent.GetActions().at(0);
REQUIRE(
setterAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyMovementAngle");
REQUIRE(setterAction.GetParametersCount() == 4);
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "Behavior");
REQUIRE(setterAction.GetParameter(2).GetPlainString() == "=");
REQUIRE(setterAction.GetParameter(3).GetPlainString() ==
"GetArgumentAsNumber(\"Value\")");
}
}
SECTION("Can generate functions for a choice property in a behavior") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("CollisionShape", 0);
property.SetType("Choice")
.SetLabel("Collision shape")
.SetLabel("Dot shape")
.SetDescription("The shape is used for collision.")
.SetGroup("Movement");
property.GetExtraInfo().push_back("Dot shape");
property.GetExtraInfo().push_back("Bounding disk");
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
project, extension, behavior, property, false);
REQUIRE(
behavior.GetEventsFunctions().HasEventsFunctionNamed("CollisionShape"));
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
"SetCollisionShape"));
auto &getter =
behavior.GetEventsFunctions().GetEventsFunction("CollisionShape");
REQUIRE(getter.GetFunctionType() ==
gd::EventsFunction::ExpressionAndCondition);
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
"[\"Dot shape\",\"Bounding disk\"]");
}
SECTION("Can generate functions for a boolean property in a behavior") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property = behavior.GetPropertyDescriptors().InsertNew("Rotate", 0);
property.SetType("Boolean")
.SetLabel("Rotate object")
.SetDescription(
"The rotation follows movements done by this behavior only.")
.SetGroup("Movement");
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
project, extension, behavior, property, false);
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed("Rotate"));
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed("SetRotate"));
{
auto &getter = behavior.GetEventsFunctions().GetEventsFunction("Rotate");
REQUIRE(getter.GetFunctionType() == gd::EventsFunction::Condition);
REQUIRE(getter.GetExpressionType().GetName() == "boolean");
REQUIRE(getter.GetFullName() == "Rotate object");
REQUIRE(getter.GetGroup() ==
"My events based behavior movement configuration");
REQUIRE(getter.GetDescription() ==
"Check if rotate object. The rotation follows movements done by "
"this behavior only.");
REQUIRE(getter.GetSentence() == "_PARAM0_ rotate object");
// Object and behavior parameters are added automatically.
REQUIRE(getter.GetParameters().size() == 0);
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &getterEvent =
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
REQUIRE(getterEvent.GetConditions().size() == 1);
REQUIRE(getterEvent.GetActions().size() == 1);
auto &getterCondition = getterEvent.GetConditions().at(0);
REQUIRE(getterCondition.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::PropertyRotate");
REQUIRE(!getterCondition.IsInverted());
REQUIRE(getterCondition.GetParametersCount() == 2);
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
REQUIRE(getterCondition.GetParameter(1).GetPlainString() == "Behavior");
auto &getterAction = getterEvent.GetActions().at(0);
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
REQUIRE(getterAction.GetParametersCount() == 1);
REQUIRE(getterAction.GetParameter(0).GetPlainString() == "True");
}
{
auto &setter =
behavior.GetEventsFunctions().GetEventsFunction("SetRotate");
REQUIRE(setter.GetFunctionType() == gd::EventsFunction::Action);
REQUIRE(setter.GetFullName() == "Rotate object");
REQUIRE(setter.GetGroup() ==
"My events based behavior movement configuration");
REQUIRE(setter.GetDescription() ==
"Change if rotate object. The rotation follows movements done by "
"this behavior only.");
REQUIRE(setter.GetSentence() == "_PARAM0_ rotate object: _PARAM2_");
// To generate the value parameter, object and behavior parameters has to
// be declared too.
REQUIRE(setter.GetParameters().size() == 3);
auto &objectParameter = setter.GetParameters().at(0);
REQUIRE(objectParameter.GetName() == "Object");
REQUIRE(objectParameter.GetType() == "object");
auto &behaviorParameter = setter.GetParameters().at(1);
REQUIRE(behaviorParameter.GetName() == "Behavior");
REQUIRE(behaviorParameter.GetType() == "behavior");
REQUIRE(behaviorParameter.GetExtraInfo() ==
"MyEventsExtension::MyEventsBasedBehavior");
auto &valueParameter = setter.GetParameters().at(2);
REQUIRE(valueParameter.GetName() == "Value");
REQUIRE(valueParameter.GetType() == "yesorno");
REQUIRE(setter.GetEvents().GetEventsCount() == 2);
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
REQUIRE(setter.GetEvents().GetEvent(1).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &setterNoEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
REQUIRE(setterNoEvent.GetConditions().size() == 1);
REQUIRE(setterNoEvent.GetActions().size() == 1);
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(setterNoCondition.IsInverted());
REQUIRE(setterNoCondition.GetParametersCount() == 1);
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterNoAction = setterNoEvent.GetActions().at(0);
REQUIRE(setterNoAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
REQUIRE(setterNoAction.GetParametersCount() == 3);
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "Behavior");
REQUIRE(setterNoAction.GetParameter(2).GetPlainString() == "no");
auto &setterYesEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
REQUIRE(setterYesEvent.GetConditions().size() == 1);
REQUIRE(setterYesEvent.GetActions().size() == 1);
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(!setterYesCondition.IsInverted());
REQUIRE(setterYesCondition.GetParametersCount() == 1);
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterYesAction = setterYesEvent.GetActions().at(0);
REQUIRE(setterYesAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::SetPropertyRotate");
REQUIRE(setterYesAction.GetParametersCount() == 3);
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "Behavior");
REQUIRE(setterYesAction.GetParameter(2).GetPlainString() == "yes");
}
}
SECTION("Can generate functions for a number property in an object") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &object = CreateObject(extension);
auto &property =
object.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number")
.SetLabel("Movement angle")
.SetDescription("The angle of the trajectory direction.")
.SetGroup("Movement");
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
project, extension, object, property);
REQUIRE(
object.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
REQUIRE(
object.GetEventsFunctions().HasEventsFunctionNamed("SetMovementAngle"));
{
auto &getter =
object.GetEventsFunctions().GetEventsFunction("MovementAngle");
REQUIRE(getter.GetFunctionType() ==
gd::EventsFunction::ExpressionAndCondition);
REQUIRE(getter.GetExpressionType().GetName() == "expression");
REQUIRE(getter.GetFullName() == "Movement angle");
REQUIRE(getter.GetGroup() ==
"My events based object movement configuration");
REQUIRE(getter.GetDescription() ==
"the movement angle of the object. The "
"angle of the trajectory direction.");
REQUIRE(getter.GetSentence() == "the movement angle");
// Object parameter is added automatically.
REQUIRE(getter.GetParameters().size() == 0);
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &getterEvent =
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
REQUIRE(getterEvent.GetConditions().size() == 0);
REQUIRE(getterEvent.GetActions().size() == 1);
auto &getterAction = getterEvent.GetActions().at(0);
REQUIRE(getterAction.GetType() == "SetReturnNumber");
REQUIRE(getterAction.GetParametersCount() == 1);
REQUIRE(getterAction.GetParameter(0).GetPlainString() ==
"Object.PropertyMovementAngle()");
}
{
auto &setter =
object.GetEventsFunctions().GetEventsFunction("SetMovementAngle");
REQUIRE(setter.GetFunctionType() ==
gd::EventsFunction::ActionWithOperator);
REQUIRE(setter.GetGetterName() == "MovementAngle");
// These fields are deducted from the getter.
REQUIRE(setter.GetFullName() == "");
REQUIRE(setter.GetGroup() == "");
REQUIRE(setter.GetDescription() == "");
REQUIRE(setter.GetSentence() == "");
// Object parameter is added automatically.
REQUIRE(setter.GetParameters().size() == 0);
REQUIRE(setter.GetEvents().GetEventsCount() == 1);
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &setterEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
REQUIRE(setterEvent.GetConditions().size() == 0);
REQUIRE(setterEvent.GetActions().size() == 1);
auto &setterAction = setterEvent.GetActions().at(0);
REQUIRE(
setterAction.GetType() ==
"MyEventsExtension::MyEventsBasedObject::SetPropertyMovementAngle");
REQUIRE(setterAction.GetParametersCount() == 3);
REQUIRE(setterAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterAction.GetParameter(1).GetPlainString() == "=");
REQUIRE(setterAction.GetParameter(2).GetPlainString() ==
"GetArgumentAsNumber(\"Value\")");
}
}
SECTION("Can generate functions for a choice property in an object") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &object = CreateObject(extension);
auto &property =
object.GetPropertyDescriptors().InsertNew("CollisionShape", 0);
property.SetType("Choice")
.SetLabel("Collision shape")
.SetLabel("Dot shape")
.SetDescription("The shape is used for collision.")
.SetGroup("Movement");
property.GetExtraInfo().push_back("Dot shape");
property.GetExtraInfo().push_back("Bounding disk");
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
project, extension, object, property);
REQUIRE(
object.GetEventsFunctions().HasEventsFunctionNamed("CollisionShape"));
REQUIRE(object.GetEventsFunctions().HasEventsFunctionNamed(
"SetCollisionShape"));
auto &getter =
object.GetEventsFunctions().GetEventsFunction("CollisionShape");
REQUIRE(getter.GetFunctionType() ==
gd::EventsFunction::ExpressionAndCondition);
REQUIRE(getter.GetExpressionType().GetName() == "stringWithSelector");
REQUIRE(getter.GetExpressionType().GetExtraInfo() ==
"[\"Dot shape\",\"Bounding disk\"]");
}
SECTION("Can generate functions for a boolean property in an object") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &object = CreateObject(extension);
auto &property = object.GetPropertyDescriptors().InsertNew("Rotate", 0);
property.SetType("Boolean")
.SetLabel("Rotate object")
.SetDescription("The rotation follows movements done by this object.")
.SetGroup("Movement");
gd::PropertyFunctionGenerator::GenerateObjectGetterAndSetter(
project, extension, object, property);
REQUIRE(object.GetEventsFunctions().HasEventsFunctionNamed("Rotate"));
REQUIRE(object.GetEventsFunctions().HasEventsFunctionNamed("SetRotate"));
{
auto &getter = object.GetEventsFunctions().GetEventsFunction("Rotate");
REQUIRE(getter.GetFunctionType() == gd::EventsFunction::Condition);
REQUIRE(getter.GetExpressionType().GetName() == "boolean");
REQUIRE(getter.GetFullName() == "Rotate object");
REQUIRE(getter.GetGroup() ==
"My events based object movement configuration");
REQUIRE(getter.GetDescription() ==
"Check if rotate object. The rotation follows movements done by "
"this object.");
REQUIRE(getter.GetSentence() == "_PARAM0_ rotate object");
// The Object parameter is added automatically.
REQUIRE(getter.GetParameters().size() == 0);
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &getterEvent =
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
REQUIRE(getterEvent.GetConditions().size() == 1);
REQUIRE(getterEvent.GetActions().size() == 1);
auto &getterCondition = getterEvent.GetConditions().at(0);
REQUIRE(getterCondition.GetType() ==
"MyEventsExtension::MyEventsBasedObject::PropertyRotate");
REQUIRE(!getterCondition.IsInverted());
REQUIRE(getterCondition.GetParametersCount() == 1);
REQUIRE(getterCondition.GetParameter(0).GetPlainString() == "Object");
auto &getterAction = getterEvent.GetActions().at(0);
REQUIRE(getterAction.GetType() == "SetReturnBoolean");
REQUIRE(getterAction.GetParametersCount() == 1);
REQUIRE(getterAction.GetParameter(0).GetPlainString() == "True");
}
{
auto &setter = object.GetEventsFunctions().GetEventsFunction("SetRotate");
REQUIRE(setter.GetFunctionType() == gd::EventsFunction::Action);
REQUIRE(setter.GetFullName() == "Rotate object");
REQUIRE(setter.GetGroup() ==
"My events based object movement configuration");
REQUIRE(setter.GetDescription() ==
"Change if rotate object. The rotation follows movements done by "
"this object.");
REQUIRE(setter.GetSentence() == "_PARAM0_ rotate object: _PARAM1_");
// To generate the value parameter, the object parameter has to
// be declared too.
REQUIRE(setter.GetParameters().size() == 2);
auto &objectParameter = setter.GetParameters().at(0);
REQUIRE(objectParameter.GetName() == "Object");
REQUIRE(objectParameter.GetType() == "object");
REQUIRE(objectParameter.GetExtraInfo() ==
"MyEventsExtension::MyEventsBasedObject");
auto &valueParameter = setter.GetParameters().at(1);
REQUIRE(valueParameter.GetName() == "Value");
REQUIRE(valueParameter.GetType() == "yesorno");
REQUIRE(setter.GetEvents().GetEventsCount() == 2);
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
REQUIRE(setter.GetEvents().GetEvent(1).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &setterNoEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
REQUIRE(setterNoEvent.GetConditions().size() == 1);
REQUIRE(setterNoEvent.GetActions().size() == 1);
auto &setterNoCondition = setterNoEvent.GetConditions().at(0);
REQUIRE(setterNoCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(setterNoCondition.IsInverted());
REQUIRE(setterNoCondition.GetParametersCount() == 1);
REQUIRE(setterNoCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterNoAction = setterNoEvent.GetActions().at(0);
REQUIRE(setterNoAction.GetType() ==
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
REQUIRE(setterNoAction.GetParametersCount() == 2);
REQUIRE(setterNoAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterNoAction.GetParameter(1).GetPlainString() == "no");
auto &setterYesEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(1));
REQUIRE(setterYesEvent.GetConditions().size() == 1);
REQUIRE(setterYesEvent.GetActions().size() == 1);
auto &setterYesCondition = setterYesEvent.GetConditions().at(0);
REQUIRE(setterYesCondition.GetType() == "GetArgumentAsBoolean");
REQUIRE(!setterYesCondition.IsInverted());
REQUIRE(setterYesCondition.GetParametersCount() == 1);
REQUIRE(setterYesCondition.GetParameter(0).GetPlainString() ==
"\"Value\"");
auto &setterYesAction = setterYesEvent.GetActions().at(0);
REQUIRE(setterYesAction.GetType() ==
"MyEventsExtension::MyEventsBasedObject::SetPropertyRotate");
REQUIRE(setterYesAction.GetParametersCount() == 2);
REQUIRE(setterYesAction.GetParameter(0).GetPlainString() == "Object");
REQUIRE(setterYesAction.GetParameter(1).GetPlainString() == "yes");
}
}
SECTION("Can generate functions for a shared property") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetSharedPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number")
.SetLabel("Movement angle")
.SetDescription("The angle of the trajectory direction.")
.SetGroup("Movement");
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
project, extension, behavior, property, true);
REQUIRE(
behavior.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
"SetMovementAngle"));
{
auto &getter =
behavior.GetEventsFunctions().GetEventsFunction("MovementAngle");
REQUIRE(getter.GetDescription() ==
"the movement angle. The angle of the trajectory direction. "
"While an object is needed, this will apply to all objects using "
"the behavior.");
REQUIRE(getter.GetEvents().GetEventsCount() == 1);
REQUIRE(getter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &getterEvent =
dynamic_cast<gd::StandardEvent &>(getter.GetEvents().GetEvent(0));
REQUIRE(getterEvent.GetConditions().size() == 0);
REQUIRE(getterEvent.GetActions().size() == 1);
auto &getterAction = getterEvent.GetActions().at(0);
REQUIRE(getterAction.GetType() == "SetReturnNumber");
REQUIRE(getterAction.GetParametersCount() == 1);
REQUIRE(getterAction.GetParameter(0).GetPlainString() ==
"Object.Behavior::SharedPropertyMovementAngle()");
}
{
auto &setter =
behavior.GetEventsFunctions().GetEventsFunction("SetMovementAngle");
REQUIRE(setter.GetEvents().GetEventsCount() == 1);
REQUIRE(setter.GetEvents().GetEvent(0).GetType() ==
"BuiltinCommonInstructions::Standard");
auto &setterEvent =
dynamic_cast<gd::StandardEvent &>(setter.GetEvents().GetEvent(0));
REQUIRE(setterEvent.GetConditions().size() == 0);
REQUIRE(setterEvent.GetActions().size() == 1);
auto &setterAction = setterEvent.GetActions().at(0);
REQUIRE(setterAction.GetType() ==
"MyEventsExtension::MyEventsBasedBehavior::"
"SetSharedPropertyMovementAngle");
}
}
SECTION("Allow functions generation when there is no setter") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number")
.SetLabel("Movement angle")
.SetDescription("The angle of the trajectory direction.")
.SetGroup("Movement");
REQUIRE(gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
behavior, property));
}
SECTION("Forbid functions generation when a getter exists") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number")
.SetLabel("Movement angle")
.SetDescription("The angle of the trajectory direction.")
.SetGroup("Movement");
behavior.GetEventsFunctions().InsertNewEventsFunction("MovementAngle", 0);
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
behavior, property));
}
SECTION("Forbid functions generation when a setter exists") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number")
.SetLabel("Movement angle")
.SetDescription("The angle of the trajectory direction.")
.SetGroup("Movement");
behavior.GetEventsFunctions().InsertNewEventsFunction("SetMovementAngle",
0);
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
behavior, property));
}
SECTION("Forbid functions generation when both setter and getter exist") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number")
.SetLabel("Movement angle")
.SetDescription("The angle of the trajectory direction.")
.SetGroup("Movement");
behavior.GetEventsFunctions().InsertNewEventsFunction("MovementAngle", 0);
behavior.GetEventsFunctions().InsertNewEventsFunction("SetMovementAngle",
0);
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
behavior, property));
}
SECTION("Forbid functions generation for required behavior properties") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Behavior")
.SetLabel("Pathfinding behavior")
.SetDescription("A required behavior.")
.SetGroup("Movement")
.GetExtraInfo()
.push_back("PlatformBehavior::PlatformerObjectBehavior");
REQUIRE(!gd::PropertyFunctionGenerator::CanGenerateGetterAndSetter(
behavior, property));
}
SECTION("Can generate functions when only the property name is filled") {
gd::Platform platform;
gd::Project project;
SetupProjectWithDummyPlatform(project, platform);
auto &extension =
project.InsertNewEventsFunctionsExtension("MyEventsExtension", 0);
auto &behavior = CreateBehavior(extension);
auto &property =
behavior.GetPropertyDescriptors().InsertNew("MovementAngle", 0);
property.SetType("Number");
gd::PropertyFunctionGenerator::GenerateBehaviorGetterAndSetter(
project, extension, behavior, property, false);
REQUIRE(
behavior.GetEventsFunctions().HasEventsFunctionNamed("MovementAngle"));
REQUIRE(behavior.GetEventsFunctions().HasEventsFunctionNamed(
"SetMovementAngle"));
auto &getter =
behavior.GetEventsFunctions().GetEventsFunction("MovementAngle");
REQUIRE(getter.GetFunctionType() ==
gd::EventsFunction::ExpressionAndCondition);
REQUIRE(getter.GetExpressionType().GetName() == "expression");
REQUIRE(getter.GetFullName() == "MovementAngle");
REQUIRE(getter.GetGroup() == "My events based behavior configuration");
REQUIRE(getter.GetDescription() == "the movementAngle of the object.");
REQUIRE(getter.GetSentence() == "the movementAngle");
}
}

View File

@@ -19,15 +19,77 @@ TEST_CASE("ResourcesRenamer", "[common]") {
gd::ResourcesRenamer resourcesRenamer(renamings);
gd::Project project;
// Add "classic", plain resources.
gd::ImageResource resource1;
resource1.SetName("Resource1");
project.GetResourcesManager().AddResource(resource1);
gd::ImageResource resource2;
resource2.SetName("Resource2");
project.GetResourcesManager().AddResource(resource2);
// Add usage of some resources.
project.GetPlatformSpecificAssets().Set(
"android", "some-icon", "Resource1");
project.GetPlatformSpecificAssets().Set(
"android", "some-other-icon", "Resource2");
project.ExposeResources(resourcesRenamer);
// Check that resources were renamed were used.
REQUIRE(project.GetPlatformSpecificAssets().Get("android", "some-icon") ==
"RenamedResource1");
REQUIRE(project.GetPlatformSpecificAssets().Get(
"android", "some-other-icon") == "Resource2");
}
SECTION("It renames embedded resources") {
std::map<gd::String, gd::String> renamings = {
{"Resource1", "RenamedResource1"}};
gd::ResourcesRenamer resourcesRenamer(renamings);
gd::Project project;
// Add "classic", plain resources.
gd::ImageResource resource1;
resource1.SetName("Resource1");
project.GetResourcesManager().AddResource(resource1);
gd::ImageResource resource2;
resource2.SetName("Resource2");
project.GetResourcesManager().AddResource(resource2);
// Add a resource containing a mapping to other resources.
gd::JsonResource jsonResourceWithEmbeddeds;
jsonResourceWithEmbeddeds.SetName("Resource3");
jsonResourceWithEmbeddeds.SetMetadata(
"{ \"embeddedResourcesMapping\": {\"some-resource-name\": "
"\"Resource1\", \"some-other-resource-name\": \"Resource2\"} }");
project.GetResourcesManager().AddResource(jsonResourceWithEmbeddeds);
// Add usage of some resources.
project.GetPlatformSpecificAssets().Set(
"android", "some-icon", "Resource1");
project.GetPlatformSpecificAssets().Set(
"android", "some-other-icon", "Resource2");
project.ExposeResources(resourcesRenamer);
// TODO: This should not be necessary, but for now not all resources support embeddeds,
// so we must call it manually:
gd::String resource3Name = "Resource3";
resourcesRenamer.ExposeEmbeddeds(resource3Name);
// Check that resources were renamed were used.
REQUIRE(project.GetPlatformSpecificAssets().Get("android", "some-icon") ==
"RenamedResource1");
REQUIRE(project.GetPlatformSpecificAssets().Get(
"android", "some-other-icon") == "Resource2");
// Check that the names were also updated in the embedded resources mapping.
REQUIRE(project.GetResourcesManager().HasResource("Resource3") == true);
REQUIRE(
project.GetResourcesManager().GetResource("Resource3").GetMetadata() ==
"{\"embeddedResourcesMapping\":{\"some-resource-name\":"
"\"RenamedResource1\",\"some-other-resource-name\":\"Resource2\"}}");
}
}

View File

@@ -85,7 +85,7 @@ TEST_CASE("SerializerElement", "[common]") {
SerializerElement element;
// A single line is saved as a string.
element.SetMultilineStringValue("test", false);
element.SetMultilineStringValue("test");
REQUIRE(element.GetMultilineStringValue() == "test");
REQUIRE(element.GetStringValue() == "test");
@@ -94,12 +94,12 @@ TEST_CASE("SerializerElement", "[common]") {
REQUIRE(element.GetMultilineStringValue() == "test of\nsomething\nsaved as a string");
// A multi lines string is saved as an array.
element.SetMultilineStringValue("test\nwith\nmultiple lines.", false);
element.SetMultilineStringValue("test\nwith\nmultiple lines.");
REQUIRE(element.ConsideredAsArray() == true);
REQUIRE(element.GetChildrenCount() == 3);
REQUIRE(element.GetMultilineStringValue() == "test\nwith\nmultiple lines.");
element.SetMultilineStringValue("test\n\nwith\n\nmultiple lines.\n", false);
element.SetMultilineStringValue("test\n\nwith\n\nmultiple lines.\n");
REQUIRE(element.ConsideredAsArray() == true);
REQUIRE(element.GetChildrenCount() == 6);
REQUIRE(element.GetMultilineStringValue() == "test\n\nwith\n\nmultiple lines.\n");

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -19,6 +19,8 @@
import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'
*/
const stringifyOptions = (options) => '["' + options.join('","') + '"]';
module.exports = {
createExtension: function (
_ /*: (string) => string */,
@@ -34,9 +36,10 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/objects/bbtext')
.setCategory('User interface');
extension.addInstructionOrExpressionGroupMetadata(_("BBCode Text Object"))
.setIcon("JsPlatform/Extensions/bbcode32.png");
.setCategory('Text');
extension
.addInstructionOrExpressionGroupMetadata(_('BBCode Text Object'))
.setIcon('JsPlatform/Extensions/bbcode32.png');
var objectBBText = new gd.ObjectJsImplementation();
// $FlowExpectedError
@@ -171,7 +174,7 @@ module.exports = {
.addIncludeFile(
'Extensions/BBText/pixi-multistyle-text/dist/pixi-multistyle-text.umd.js'
)
.setCategoryFullName(_('User interface'));
.setCategoryFullName(_('Text'));
/**
* Utility function to add both a setter and a getter to a property from a list.
@@ -195,7 +198,10 @@ module.exports = {
.addParameter('object', objectName, objectName, false)
.getCodeExtraInformation()
.setFunctionName(`get${property.functionName}`);
} else if (parameterType === 'string') {
} else if (
parameterType === 'string' ||
parameterType === 'stringWithSelector'
) {
gdObject
.addStrExpression(
`Get${property.functionName}`,
@@ -210,13 +216,24 @@ module.exports = {
}
// Add the action
if (parameterType === 'number' || parameterType === 'string') {
const expressionType =
parameterType === 'number' ? 'expression' : 'string';
if (
parameterType === 'number' ||
parameterType === 'string' ||
parameterType === 'stringWithSelector'
) {
const parameterOptions =
gd.ParameterOptions.makeNewOptions().setDescription(
property.paramLabel
);
if (property.options) {
parameterOptions.setTypeExtraInfo(
stringifyOptions(property.options)
);
}
gdObject
.addAction(
`Set${property.functionName}`,
property.paramLabel,
property.instructionLabel,
property.actionDescription,
property.actionSentence,
'',
@@ -224,7 +241,7 @@ module.exports = {
property.iconPath
)
.addParameter('object', objectName, objectName, false)
.useStandardOperatorParameters(parameterType)
.useStandardOperatorParameters(parameterType, parameterOptions)
.getCodeExtraInformation()
.setFunctionName(`set${property.functionName}`)
.setGetter(`get${property.functionName}`);
@@ -232,7 +249,7 @@ module.exports = {
gdObject
.addAction(
`Set${property.functionName}`,
property.paramLabel,
property.instructionLabel,
property.actionDescription,
property.actionSentence,
'',
@@ -243,9 +260,7 @@ module.exports = {
.addParameter(
parameterType,
property.paramLabel,
property.options
? '["' + property.options.join('", "') + '"]'
: '',
'', // There should not be options for the property if it's not a stringWithSelector
false
)
.getCodeExtraInformation()
@@ -254,13 +269,24 @@ module.exports = {
}
// Add condition
if (parameterType === 'string' || parameterType === 'number') {
const propExpressionType =
parameterType === 'string' ? 'string' : 'expression';
if (
parameterType === 'string' ||
parameterType === 'number' ||
parameterType === 'stringWithSelector'
) {
const parameterOptions =
gd.ParameterOptions.makeNewOptions().setDescription(
property.paramLabel
);
if (property.options) {
parameterOptions.setTypeExtraInfo(
stringifyOptions(property.options)
);
}
gdObject
.addCondition(
`Is${property.functionName}`,
property.paramLabel,
property.instructionLabel,
property.conditionDescription,
property.conditionSentence,
'',
@@ -268,14 +294,17 @@ module.exports = {
property.iconPath
)
.addParameter('object', objectName, objectName, false)
.useStandardRelationalOperatorParameters(parameterType)
.useStandardRelationalOperatorParameters(
parameterType,
parameterOptions
)
.getCodeExtraInformation()
.setFunctionName(`get${property.functionName}`);
} else if (parameterType === 'yesorno') {
gdObject
.addCondition(
`Is${property.functionName}`,
property.paramLabel,
property.instructionLabel,
property.conditionDescription,
property.conditionSentence,
'',
@@ -294,7 +323,8 @@ module.exports = {
functionName: 'BBText',
iconPath: 'res/actions/text24_black.png',
type: 'string',
paramLabel: _('BBCode text'),
instructionLabel: _('BBCode text'),
paramLabel: _('Text'),
conditionDescription: _('Compare the value of the BBCode text.'),
conditionSentence: _('the BBCode text'),
actionDescription: _('Set BBCode text'),
@@ -306,7 +336,8 @@ module.exports = {
functionName: 'Color',
iconPath: 'res/actions/color24.png',
type: 'color',
paramLabel: _('Color'),
instructionLabel: _('Color'),
paramLabel: _('Color (R;G;B)'),
conditionDescription: '', // No conditions for a "color" property
conditionSentence: '', // No conditions for a "color" property
actionDescription: _('Set base color'),
@@ -318,7 +349,8 @@ module.exports = {
functionName: 'Opacity',
iconPath: 'res/actions/opacity24.png',
type: 'number',
paramLabel: _('Opacity'),
instructionLabel: _('Opacity'),
paramLabel: _('Opacity (0-255)'),
conditionDescription: _(
'Compare the value of the base opacity of the text.'
),
@@ -332,6 +364,7 @@ module.exports = {
functionName: 'FontSize',
iconPath: 'res/actions/characterSize24.png',
type: 'number',
instructionLabel: _('Font size'),
paramLabel: _('Font size'),
conditionDescription: _('Compare the base font size of the text.'),
conditionSentence: _('the base font size'),
@@ -344,6 +377,7 @@ module.exports = {
functionName: 'FontFamily',
iconPath: 'res/actions/font24.png',
type: 'string',
instructionLabel: _('Font family'),
paramLabel: _('Font family'),
conditionDescription: _('Compare the value of font family'),
conditionSentence: _('the base font family'),
@@ -356,6 +390,7 @@ module.exports = {
functionName: 'Alignment',
iconPath: 'res/actions/textAlign24.png',
type: 'stringWithSelector',
instructionLabel: _('Alignment'),
paramLabel: _('Alignment'),
options: ['left', 'right', 'center'],
conditionDescription: _('Check the current text alignment.'),
@@ -369,6 +404,7 @@ module.exports = {
functionName: 'WordWrap',
iconPath: 'res/actions/scaleWidth24_black.png',
type: 'boolean',
instructionLabel: _('Word wrap'),
paramLabel: _('Word wrap'),
conditionDescription: _('Check if word wrap is enabled.'),
conditionSentence: _('Word wrap is enabled'),
@@ -381,6 +417,7 @@ module.exports = {
functionName: 'WrappingWidth',
iconPath: 'res/actions/scaleWidth24_black.png',
type: 'number',
instructionLabel: _('Wrapping width'),
paramLabel: _('Wrapping width'),
conditionDescription: _(
'Compare the width, in pixels, after which the text is wrapped on next line.'
@@ -510,8 +547,7 @@ module.exports = {
* This is called to update the PIXI object on the scene editor
*/
RenderedBBTextInstance.prototype.update = function () {
const properties = this._associatedObjectConfiguration
.getProperties();
const properties = this._associatedObjectConfiguration.getProperties();
const rawText = properties.get('text').getValue();
if (rawText !== this._pixiObject.text) {

View File

@@ -36,9 +36,10 @@ module.exports = {
'Open source (MIT License)'
)
.setExtensionHelpPath('/objects/bitmap_text')
.setCategory('User interface');
extension.addInstructionOrExpressionGroupMetadata(_("Bitmap Text"))
.setIcon("JsPlatform/Extensions/bitmapfont32.png");
.setCategory('Text');
extension
.addInstructionOrExpressionGroupMetadata(_('Bitmap Text'))
.setIcon('JsPlatform/Extensions/bitmapfont32.png');
const bitmapTextObject = new gd.ObjectJsImplementation();
// $FlowExpectedError
@@ -91,7 +92,7 @@ module.exports = {
.setType('resource')
.addExtraInfo('bitmapFont') //fnt or xml files
.setLabel(_('Bitmap Font'))
.setGroup(_("Font"));
.setGroup(_('Font'));
objectProperties
.getOrCreate('textureAtlasResourceName')
@@ -99,7 +100,7 @@ module.exports = {
.setType('resource')
.addExtraInfo('image')
.setLabel(_('Bitmap atlas image'))
.setGroup(_("Font"));
.setGroup(_('Font'));
objectProperties
.getOrCreate('scale')
@@ -113,7 +114,7 @@ module.exports = {
.setValue(objectContent.tint)
.setType('color')
.setLabel(_('Font tint'))
.setGroup(_("Font"));
.setGroup(_('Font'));
objectProperties
.getOrCreate('wordWrap')
@@ -174,7 +175,7 @@ module.exports = {
.addIncludeFile(
'Extensions/BitmapText/bitmaptextruntimeobject-pixi-renderer.js'
)
.setCategoryFullName(_('User interface'));
.setCategoryFullName(_('Text'));
object
.addExpressionAndConditionAndAction(
@@ -187,7 +188,7 @@ module.exports = {
'res/conditions/text24_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('string')
.useStandardParameters('string', gd.ParameterOptions.makeNewOptions())
.setFunctionName('setText')
.setGetter('getText');
@@ -202,7 +203,12 @@ module.exports = {
'res/conditions/opacity24.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('number')
.useStandardParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Opacity (0-255)')
)
)
.setFunctionName('setOpacity')
.setGetter('getOpacity');
@@ -217,7 +223,7 @@ module.exports = {
'res/conditions/characterSize24.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('number')
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
.setFunctionName('getFontSize');
object
@@ -231,7 +237,12 @@ module.exports = {
'res/actions/scale24_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('number')
.useStandardParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Scale (1 by default)')
)
)
.setFunctionName('setScale')
.setGetter('getScale');
@@ -246,7 +257,7 @@ module.exports = {
'res/conditions/font24.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('string')
.useStandardParameters('string', gd.ParameterOptions.makeNewOptions())
.setFunctionName('getFontName');
object
@@ -304,7 +315,12 @@ module.exports = {
'res/actions/textAlign24.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('string')
.useStandardParameters(
'string',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Alignment ("left", "right" or "center")')
)
)
.setFunctionName('getAlignment');
object
@@ -367,7 +383,7 @@ module.exports = {
'res/actions/scaleWidth24_black.png'
)
.addParameter('object', _('Bitmap text'), 'BitmapTextObject', false)
.useStandardParameters('number')
.useStandardParameters('number', gd.ParameterOptions.makeNewOptions())
.setFunctionName('setWrappingWidth')
.setGetter('getWrappingWidth');
@@ -637,8 +653,7 @@ module.exports = {
// This is called to update the PIXI object on the scene editor
RenderedBitmapTextInstance.prototype.update = function () {
const properties = this._associatedObjectConfiguration
.getProperties();
const properties = this._associatedObjectConfiguration.getProperties();
// Update the rendered text properties (note: Pixi is only
// applying changes if there were changed).

View File

@@ -25,6 +25,7 @@ DestroyOutsideBehavior::GetProperties(
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("extraBorder", 0)))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetLabel(_("Margin before deleting the object, in pixels"));
return properties;

View File

@@ -45,7 +45,8 @@ void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/destroyoutsideicon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "DestroyOutside")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetFunctionName("GetExtraBorder");
@@ -59,7 +60,8 @@ void DeclareDestroyOutsideBehaviorExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/destroyoutsideicon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "DestroyOutside")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetFunctionName("SetExtraBorder")
.SetGetter("GetExtraBorder");

View File

@@ -28,7 +28,7 @@ module.exports = {
extension
.setExtensionInformation(
'DialogueTree',
_('Dialogue Tree (experimental)'),
_('Dialogue Tree'),
'Handle dialogue trees, made using Yarn Spinner. Useful to make complex dialogues with multiple choices. The Yarn Spinner editor is embedded in GDevelop so you can edit your dialogues without leaving GDevelop.',
'Todor Imreorov',
'Open source (MIT License)'
@@ -36,7 +36,7 @@ module.exports = {
.setExtensionHelpPath('/all-features/dialogue-tree')
.setCategory('Game mechanic');
extension
.addInstructionOrExpressionGroupMetadata(_('Dialogue Tree (experimental)'))
.addInstructionOrExpressionGroupMetadata(_('Dialogue Tree'))
.setIcon('JsPlatform/Extensions/yarn32.png');
extension

View File

@@ -57,35 +57,18 @@ namespace gdjs {
}
const inputManager = instanceContainer.getGame().getInputManager();
//Try mouse
const mouseDraggableManager = DraggableManager.getMouseManager(
instanceContainer
);
if (
inputManager.isMouseButtonPressed(0) &&
!mouseDraggableManager.isDragging(this)
) {
if (mouseDraggableManager.tryAndTakeDragging(instanceContainer, this)) {
this._draggedByDraggableManager = mouseDraggableManager;
return true;
const touchIds = inputManager.getStartedTouchIdentifiers();
for (let i = 0; i < touchIds.length; ++i) {
const touchDraggableManager = DraggableManager.getTouchManager(
instanceContainer,
touchIds[i]
);
if (touchDraggableManager.isDragging(this)) {
continue;
}
} else {
//Try touches
const touchIds = inputManager.getStartedTouchIdentifiers();
for (let i = 0; i < touchIds.length; ++i) {
const touchDraggableManager = DraggableManager.getTouchManager(
instanceContainer,
touchIds[i]
);
if (touchDraggableManager.isDragging(this)) {
continue;
}
if (
touchDraggableManager.tryAndTakeDragging(instanceContainer, this)
) {
this._draggedByDraggableManager = touchDraggableManager;
return true;
}
if (touchDraggableManager.tryAndTakeDragging(instanceContainer, this)) {
this._draggedByDraggableManager = touchDraggableManager;
return true;
}
}
return false;
@@ -121,14 +104,6 @@ namespace gdjs {
}
doStepPostEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
const mouseDraggableManager = DraggableManager.getMouseManager(
instanceContainer
);
mouseDraggableManager.leftPressedLastFrame = instanceContainer
.getGame()
.getInputManager()
.isMouseButtonPressed(0);
this._justDropped = false;
}
@@ -144,7 +119,8 @@ namespace gdjs {
/**
* Handle the dragging
*/
abstract class DraggableManager {
class DraggableManager {
private _touchId: integer;
/**
* The object has left its original position.
* When true, the search for the best object to drag has ended.
@@ -157,24 +133,11 @@ namespace gdjs {
protected _xOffset: number = 0;
protected _yOffset: number = 0;
constructor(instanceContainer: gdjs.RuntimeInstanceContainer) {}
/**
* Get the platforms manager of an instance container.
*/
static getMouseManager(
instanceContainer: gdjs.RuntimeInstanceContainer
): MouseDraggableManager {
// @ts-ignore
if (!instanceContainer.mouseDraggableManager) {
//Create the shared manager if necessary.
// @ts-ignore
instanceContainer.mouseDraggableManager = new MouseDraggableManager(
instanceContainer
);
}
// @ts-ignore
return instanceContainer.mouseDraggableManager;
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
touchId: integer
) {
this._touchId = touchId;
}
/**
@@ -196,7 +159,7 @@ namespace gdjs {
// @ts-ignore
instanceContainer.touchDraggableManagers[
touchId
] = new TouchDraggableManager(instanceContainer, touchId);
] = new DraggableManager(instanceContainer, touchId);
}
// @ts-ignore
return instanceContainer.touchDraggableManagers[touchId];
@@ -263,75 +226,6 @@ namespace gdjs {
this._draggableBehavior = null;
}
abstract isDragging(
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean;
abstract shouldEndDrag(
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean;
abstract getPosition(
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): FloatPoint;
}
/**
* Handle the dragging by mouse
*/
class MouseDraggableManager extends DraggableManager {
/** Used to only start dragging when clicking. */
leftPressedLastFrame = false;
constructor(instanceContainer: gdjs.RuntimeInstanceContainer) {
super(instanceContainer);
}
isDragging(draggableRuntimeBehavior: DraggableRuntimeBehavior): boolean {
return this.leftPressedLastFrame || this._draggingSomething;
}
getPosition(
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): FloatPoint {
const workingPoint: FloatPoint = gdjs.staticArray(
MouseDraggableManager.prototype.getPosition
) as FloatPoint;
const inputManager = instanceContainer.getGame().getInputManager();
return instanceContainer
.getLayer(draggableRuntimeBehavior.owner.getLayer())
.convertCoords(
inputManager.getMouseX(),
inputManager.getMouseY(),
0,
workingPoint
);
}
shouldEndDrag(
instanceContainer: gdjs.RuntimeInstanceContainer,
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean {
const inputManager = instanceContainer.getGame().getInputManager();
return !inputManager.isMouseButtonPressed(0);
}
}
/**
* Handle the dragging by touch
*/
class TouchDraggableManager extends DraggableManager {
private _touchId: integer;
constructor(
instanceContainer: gdjs.RuntimeInstanceContainer,
touchId: integer
) {
super(instanceContainer);
this._touchId = touchId;
}
isDragging(draggableRuntimeBehavior: DraggableRuntimeBehavior): boolean {
return this._draggingSomething;
}
@@ -341,7 +235,7 @@ namespace gdjs {
draggableRuntimeBehavior: DraggableRuntimeBehavior
): FloatPoint {
const workingPoint: FloatPoint = gdjs.staticArray(
TouchDraggableManager.prototype.getPosition
DraggableManager.prototype.getPosition
) as FloatPoint;
const inputManager = instanceContainer.getGame().getInputManager();
return instanceContainer
@@ -359,9 +253,7 @@ namespace gdjs {
draggableRuntimeBehavior: DraggableRuntimeBehavior
): boolean {
const inputManager = instanceContainer.getGame().getInputManager();
return (
inputManager.getAllTouchIdentifiers().indexOf(this._touchId) === -1
);
return inputManager.hasTouchEnded(this._touchId);
}
}

View File

@@ -1,11 +1,6 @@
// @ts-check
describe('gdjs.DraggableRuntimeBehavior', function () {
var runtimeGame = new gdjs.RuntimeGame({
variables: [],
resources: { resources: [] },
// @ts-ignore
properties: { windowWidth: 800, windowHeight: 600 },
});
const runtimeGame = gdjs.getPixiRuntimeGame();
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [
@@ -66,17 +61,21 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Drag'n'drop
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(450, 500);
runtimeGame
.getInputManager()
.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(750, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame
.getInputManager()
.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
@@ -84,6 +83,7 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Mouse move without dragging
runtimeGame.getInputManager().onMouseMove(600, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
@@ -94,12 +94,15 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
.getInputManager()
.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(850, 700);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame
.getInputManager()
.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
expect(object.getX()).to.be(850);
expect(object.getY()).to.be(700);
@@ -111,17 +114,21 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Dragged point is in the bounding box but not in hitbox
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(450, 500);
runtimeGame
.getInputManager()
.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(750, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame
.getInputManager()
.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
@@ -135,34 +142,42 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Dragged point is in the bounding box but not in hitbox
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(450, 500);
runtimeGame
.getInputManager()
.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(750, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame
.getInputManager()
.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
expect(object2.getX()).to.be(450);
expect(object2.getY()).to.be(500);
// Dragged point is in the bounding box and in hitbox
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(455, 505);
runtimeGame
.getInputManager()
.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(855, 705);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame
.getInputManager()
.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
expect(object2.getX()).to.be(850);
expect(object2.getY()).to.be(700);
@@ -185,17 +200,21 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Drag'n'drop
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(450, 500);
runtimeGame
.getInputManager()
.onMouseButtonPressed(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onMouseMove(750, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame
.getInputManager()
.onMouseButtonReleased(gdjs.InputManager.MOUSE_LEFT_BUTTON);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
if (firstInFront) {
// The 1st object moved
@@ -220,6 +239,7 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Drag'n'drop
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(1, 10, 20);
runtimeGame.getInputManager().onTouchStart(0, 450, 500);
runtimeScene.renderAndStep(1000 / 60);
@@ -237,22 +257,25 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Move another unrelated touch
runtimeGame.getInputManager().onTouchMove(1, 750, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchMove(1, 850, 700);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
expect(object.getX()).to.be(750);
expect(object.getY()).to.be(600);
// Start drag'n'drop with another touch
runtimeGame.getInputManager().onTouchEnd(1);
runtimeGame.getInputManager().onFrameEnded();
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(1, 750, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchMove(1, 850, 700);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onTouchEnd(1);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchEnd(1);
expect(object.getX()).to.be(850);
expect(object.getY()).to.be(700);
@@ -264,12 +287,12 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Dragged point is in the bounding box but not in hitbox
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(0, 450, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchMove(0, 750, 600);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchEnd(0);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
@@ -286,6 +309,7 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Dragged point is in the bounding box but not in hitbox
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(0, 450, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
@@ -301,6 +325,7 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Dragged point is in the bounding box but not in hitbox
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(0, 455, 505);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
@@ -323,6 +348,7 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Drag'n'drop
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(2, 450, 500);
runtimeGame.getInputManager().onTouchStart(1, 650, 600);
runtimeScene.renderAndStep(1000 / 60);
@@ -361,6 +387,7 @@ describe('gdjs.DraggableRuntimeBehavior', function () {
// Drag'n'drop
runtimeGame.getInputManager().touchSimulateMouse(false);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.getInputManager().onFrameEnded();
runtimeGame.getInputManager().onTouchStart(1, 10, 20);
runtimeGame.getInputManager().onTouchStart(0, 450, 500);
runtimeScene.renderAndStep(1000 / 60);

View File

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

View File

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

View File

@@ -2037,7 +2037,7 @@ module.exports = {
_('Update a document in Database'),
_('Updates a variable on the database.'),
_(
'Update varable _PARAM0_ with _PARAM1_ (store result state in _PARAM2_)'
'Update variable _PARAM0_ with _PARAM1_ (store result state in _PARAM2_)'
),
_('Realtime Database'),
'JsPlatform/Extensions/firebase.png',

View File

@@ -1,17 +1,3 @@
/**
* A firebase configuaration of a project made only for those tests.
*/
const firebaseConfig = {
apiKey: 'AIzaSyBwPnGpfEBXDjwQrWfU0wqgp4m9qEt7YM8',
authDomain: 'gdtest-e11a5.firebaseapp.com',
databaseURL: 'https://gdtest-e11a5.firebaseio.com',
projectId: 'gdtest-e11a5',
storageBucket: 'gdtest-e11a5.appspot.com',
messagingSenderId: '254035412678',
appId: '1:254035412678:web:2ddd6b83019b7f259b79c7',
measurementId: 'G-4REML26L59',
};
/**
* Turns a callback variable into a promise.
* @param {(callbackVariable: {setString: (result: "ok" | string) => void}, result: gdjs.Variable) => any} executor
@@ -38,6 +24,20 @@ const variable = new gdjs.Variable().fromJSObject({
it: ['is', true],
});
/**
* A firebase configuration of a project made only for those tests.
*/
const firebaseConfig = {
apiKey: 'AIzaSyBwPnGpfEBXDjwQrWfU0wqgp4m9qEt7YM8',
authDomain: 'gdtest-e11a5.firebaseapp.com',
databaseURL: 'https://gdtest-e11a5.firebaseio.com',
projectId: 'gdtest-e11a5',
storageBucket: 'gdtest-e11a5.appspot.com',
messagingSenderId: '254035412678',
appId: '1:254035412678:web:2ddd6b83019b7f259b79c7',
measurementId: 'G-4REML26L59',
};
// The tests require an internet connection, as a real Firebase instance is used.
const describeIfOnline = navigator.onLine ? describe : describe.skip;
describeIfOnline('Firebase extension end-to-end tests', function () {
@@ -48,8 +48,8 @@ describeIfOnline('Firebase extension end-to-end tests', function () {
.toString()
.replace('.', '-')}-${Date.now()}`;
before(function setupFirebase() {
gdjs.evtTools.firebaseTools._setupFirebase({
before(async function setupFirebase() {
await gdjs.evtTools.firebaseTools._setupFirebase({
getGame: () => ({
getExtensionProperty: () => JSON.stringify(firebaseConfig),
}),

View File

@@ -64,7 +64,8 @@ void DeclareInventoryExtension(gd::PlatformExtension& extension) {
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Inventory name"))
.AddParameter("string", _("Item name"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("InventoryTools::Count");
extension

View File

@@ -1,10 +1,6 @@
describe('Inventory', function () {
it('Inventories can be serialized then unserialized with no data loss', () => {
var runtimeGame = new gdjs.RuntimeGame({
variables: [],
properties: { windowWidth: 800, windowHeight: 600 },
resources: { resources: [] },
});
const runtimeGame = gdjs.getPixiRuntimeGame();
var runtimeScene = new gdjs.RuntimeScene(runtimeGame);
gdjs.evtTools.inventory.add(runtimeScene, 'MyInventory', 'sword');

View File

@@ -28,14 +28,14 @@ module.exports = {
extension
.setExtensionInformation(
'Leaderboards',
_('Leaderboards (experimental)'),
_('Leaderboards'),
_('Allow your game to send scores to your leaderboards.'),
'Florian Rival',
'Open source (MIT License)'
)
.setExtensionHelpPath('/all-features/leaderboards')
.setCategory('Players')
.addInstructionOrExpressionGroupMetadata(_('Leaderboards (experimental)'))
.addInstructionOrExpressionGroupMetadata(_('Leaderboards'))
.setIcon('JsPlatform/Extensions/leaderboard.svg');
extension
@@ -154,6 +154,21 @@ module.exports = {
.setIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.isSaving');
extension
.addCondition(
'HasPlayerJustClosedLeaderboardView',
_('Closed by player'),
_('Check if the player has just closed the leaderboard view.'),
_('Player has just closed the leaderboard view'),
_('Display leaderboard'),
'JsPlatform/Extensions/leaderboard.svg',
'JsPlatform/Extensions/leaderboard.svg'
)
.setHelpPath('/all-features/leaderboards')
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName('gdjs.evtTools.leaderboards.hasPlayerJustClosedLeaderboardView');
extension
.addStrExpression(
'LastSaveError',

View File

@@ -5,6 +5,19 @@ namespace gdjs {
const logger = new gdjs.Logger('Leaderboards');
export namespace evtTools {
export namespace leaderboards {
let _hasPlayerJustClosedLeaderboardView = false;
gdjs.registerRuntimeScenePostEventsCallback(() => {
// Set it back to false for the next frame.
_hasPlayerJustClosedLeaderboardView = false;
});
/**
* Returns true if the player has just closed the leaderboard view.
*/
export const hasPlayerJustClosedLeaderboardView = () =>
_hasPlayerJustClosedLeaderboardView;
const computeDigest = (payload: string): string => {
const shaObj = new jsSHA('SHA-256', 'TEXT', { encoding: 'UTF8' });
shaObj.update(payload);
@@ -521,6 +534,7 @@ namespace gdjs {
) {
switch (event.data) {
case 'closeLeaderboardView':
_hasPlayerJustClosedLeaderboardView = true;
closeLeaderboardView(runtimeScene);
break;
case 'leaderboardViewLoaded':
@@ -672,7 +686,7 @@ namespace gdjs {
const isDev = runtimeScene
.getGame()
.isUsingGDevelopDevelopmentEnvironment();
const targetUrl = `https://liluo.io/games/${gameId}/leaderboard/${leaderboardId}?inGameEmbedded=true${
const targetUrl = `https://gd.games/games/${gameId}/leaderboard/${leaderboardId}?inGameEmbedded=true${
isDev ? '&dev=true' : ''
}`;
checkLeaderboardAvailability(targetUrl).then(

View File

@@ -56,13 +56,7 @@ const addLightObstacle = (runtimeScene, width, height) => {
describe('gdjs.LightRuntimeObject', function () {
PIXI.settings.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT = false;
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
resources: {
resources: [],
},
properties: { windowWidth: 800, windowHeight: 600 },
});
const runtimeGame = gdjs.getPixiRuntimeGame();
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{ name: '', visibility: true, effects: [] }],
@@ -96,13 +90,7 @@ describe('gdjs.LightRuntimeObject', function () {
describe('Light with obstacles around it', function () {
PIXI.settings.FAIL_IF_MAJOR_PERFORMANCE_CAVEAT = false;
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
resources: {
resources: [],
},
properties: { windowWidth: 800, windowHeight: 600 },
});
const runtimeGame = gdjs.getPixiRuntimeGame();
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [{ name: '', visibility: true, effects: [] }],

View File

@@ -6,12 +6,7 @@ describe('gdjs.LinksManager', function () {
object3Names,
eventsFunctionContext
) => {
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
// @ts-ignore - missing properties.
properties: { windowWidth: 800, windowHeight: 600 },
resources: { resources: [] },
});
const runtimeGame = gdjs.getPixiRuntimeGame();
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [

View File

@@ -28,7 +28,7 @@ module.exports = {
extension
.setExtensionInformation(
'P2P',
_('P2P (experimental)'),
_('P2P'),
'Allow game instances to communicate remotely using messages sent via WebRTC (P2P).',
'Arthur Pacaud (arthuro555)',
'MIT'
@@ -36,7 +36,7 @@ module.exports = {
.setExtensionHelpPath('/all-features/p2p')
.setCategory('Network');
extension
.addInstructionOrExpressionGroupMetadata(_('P2P (experimental)'))
.addInstructionOrExpressionGroupMetadata(_('P2P'))
.setIcon('JsPlatform/Extensions/p2picon.svg');
extension

View File

@@ -24,7 +24,9 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"Victor Levasseur and Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects/panel_sprite");
extension.AddInstructionOrExpressionGroupMetadata(_("Panel Sprite (9-patch) Object"))
extension
.AddInstructionOrExpressionGroupMetadata(
_("Panel Sprite (9-patch) Object"))
.SetIcon("CppPlatform/Extensions/PanelSpriteIcon.png");
gd::ObjectMetadata& obj =
@@ -48,7 +50,10 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"res/conditions/opacity.png")
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity to compare to (0-255)")));
obj.AddAction(
"SetOpacity",
@@ -61,7 +66,10 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"res/actions/opacity.png")
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity (0-255)")));
obj.AddExpression("Opacity",
_("Opacity"),
@@ -91,7 +99,8 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetWidth")
.SetGetter("GetWidth");
@@ -104,7 +113,8 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("GetWidth");
obj.AddAction("Height",
@@ -116,7 +126,8 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetHeight")
.SetGetter("GetHeight");
@@ -129,7 +140,8 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetHeight")
.SetGetter("GetHeight");
@@ -143,7 +155,10 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
.SetHidden() // Deprecated
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle (in degrees)")))
.SetFunctionName("SetAngle")
.SetGetter("GetAngle");
@@ -157,7 +172,10 @@ void DeclarePanelSpriteObjectExtension(gd::PlatformExtension& extension) {
.SetHidden() // Deprecated
.AddParameter("object", _("Object"), "PanelSprite")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle to compare to (in degrees)")))
.SetFunctionName("SetAngle")
.SetGetter("GetAngle");

View File

@@ -54,7 +54,8 @@ void PanelSpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
element.SetAttribute("tiled", tiled);
}
void PanelSpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {
void PanelSpriteObject::ExposeResources(
gd::ArbitraryResourceWorker& worker) {
worker.ExposeImage(textureName);
}
#endif

View File

@@ -8,12 +8,13 @@ This project is released under the MIT License.
#ifndef PANELSPRITEOBJECT_H
#define PANELSPRITEOBJECT_H
#include <memory>
#include "GDCore/Project/Object.h"
namespace gd {
class ObjectConfiguration;
class InitialInstance;
class Project;
}
} // namespace gd
/**
* PanelSprite Object
@@ -23,37 +24,36 @@ class GD_EXTENSION_API PanelSpriteObject : public gd::ObjectConfiguration {
PanelSpriteObject();
virtual ~PanelSpriteObject();
virtual std::unique_ptr<gd::ObjectConfiguration> Clone() const {
return std::unique_ptr<gd::ObjectConfiguration>(new PanelSpriteObject(*this));
return std::unique_ptr<gd::ObjectConfiguration>(
new PanelSpriteObject(*this));
}
#if defined(GD_IDE_ONLY)
virtual void ExposeResources(gd::ArbitraryResourceWorker &worker);
#endif
float GetWidth() const { return width; };
float GetHeight() const { return height; };
double GetWidth() const { return width; };
double GetHeight() const { return height; };
void SetWidth(float newWidth) {
void SetWidth(double newWidth) {
width = newWidth >= (leftMargin + rightMargin) ? newWidth
: (leftMargin + rightMargin);
};
void SetHeight(float newHeight) {
void SetHeight(double newHeight) {
height = newHeight >= (topMargin + bottomMargin)
? newHeight
: (topMargin + bottomMargin);
};
float GetLeftMargin() const { return leftMargin; };
void SetLeftMargin(float newMargin) { leftMargin = newMargin; };
double GetLeftMargin() const { return leftMargin; };
void SetLeftMargin(double newMargin) { leftMargin = newMargin; };
float GetTopMargin() const { return topMargin; };
void SetTopMargin(float newMargin) { topMargin = newMargin; };
double GetTopMargin() const { return topMargin; };
void SetTopMargin(double newMargin) { topMargin = newMargin; };
float GetRightMargin() const { return rightMargin; };
void SetRightMargin(float newMargin) { rightMargin = newMargin; };
double GetRightMargin() const { return rightMargin; };
void SetRightMargin(double newMargin) { rightMargin = newMargin; };
float GetBottomMargin() const { return bottomMargin; };
void SetBottomMargin(float newMargin) { bottomMargin = newMargin; };
double GetBottomMargin() const { return bottomMargin; };
void SetBottomMargin(double newMargin) { bottomMargin = newMargin; };
bool IsTiled() const { return tiled; };
void SetTiled(bool enable = true) { tiled = enable; };
@@ -72,13 +72,13 @@ class GD_EXTENSION_API PanelSpriteObject : public gd::ObjectConfiguration {
virtual void DoSerializeTo(gd::SerializerElement &element) const;
#endif
float width;
float height;
double width;
double height;
float leftMargin;
float topMargin;
float rightMargin;
float bottomMargin;
double leftMargin;
double topMargin;
double rightMargin;
double bottomMargin;
bool tiled;
};

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