Compare commits

..

152 Commits

Author SHA1 Message Date
AlexandreSi
01f7524e52 Add timeout to make sure temporary selected instances are up to date with last selection rectangle change 2022-12-22 16:58:57 +01:00
AlexandreSi
1becef95f6 Add throttle on temporary instances selection computation 2022-12-22 15:32:52 +01:00
AlexandreSi
cbe9040b77 Improve computations efficiency 2022-12-22 15:08:00 +01:00
AlexandreSi
e061c5f3c7 When selecting multiple instances, dynamically show instances that will be (un)selected 2022-12-22 10:55:16 +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
github-actions[bot]
e539fdb0e9 Update translations (#4536)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-14 11:22:27 +01:00
Clément Pasteau
2a9193e4c2 Hide warning if backdrop behavior is set to cancel (#4543)
Do not show in changelog
2022-11-14 11:13:35 +01:00
github-actions[bot]
cf8361be0c Update translations (#4534)
Do not show in changelog
2022-11-10 15:57:05 +01:00
Clément Pasteau
2ba5f03e67 Fix animation preview not taking full space (#4535)
Do not show in changelog
2022-11-10 15:53:14 +01:00
Clément Pasteau
d9435eda5a Bump version to 5.1.150 (#4530) 2022-11-10 13:28:04 +01:00
github-actions[bot]
bc807acf8a Update translations [skip ci] (#4512)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2022-11-10 13:27:52 +01:00
Clément Pasteau
194b60aa72 Rework Dialogs and tabs design (#4520)
* Overall redesign or the dialogs to display a title and more margins, helping buttons be more discernable from the content + cross at the top to close them easily.
* Redesign of the tabs to be more intuitive.
2022-11-10 12:59:54 +01:00
D8H
02bbdfecd4 Allow event-based behaviors to declare scene properties (#4464) 2022-11-10 11:43:16 +01:00
D8H
bf19ec5a68 [PathFinding] Improve pathfinding with a property to smooth the path. (#4515) 2022-11-10 11:40:07 +01:00
Florian Rival
59094110ca Serialize JS code events and extension descriptions as arrays of strings to make collaboration/reviews easier (#4468)
Only show in developer changelog
2022-11-09 18:39:23 +01:00
D8H
a35ead0ab2 Panel sprite objects now respect the resource smoothing option (#4526) 2022-11-09 15:21:31 +01:00
Clément Pasteau
669c10c462 Slightly improve animation preview zoom for the image to fit the canvas (#4527) 2022-11-09 14:16:57 +01:00
Clément Pasteau
2859f2a3b6 Improve Selection of resources in parameters (#4524)
* A button is now available to pick a file
* When there is only 1 external editor like Piskel, the button is made more visible
2022-11-09 10:41:35 +01:00
1675 changed files with 38170 additions and 98683 deletions

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

@@ -146,69 +146,83 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddAction("ModVolumeSoundCanal",
_("Volume of the sound on a channel"),
_("This action modifies the volume of the sound on the "
"specified channel. The volume is between 0 and 100."),
"specified channel."),
_("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"),
"res/actions/sonVolume24.png",
"res/actions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced();
extension
.AddAction("ModVolumeMusicCanal",
_("Volume of the music on a channel"),
_("This action modifies the volume of the music on the "
"specified channel. The volume is between 0 and 100."),
"specified channel."),
_("the volume of the music on channel _PARAM1_"),
_("Music on channels"),
"res/actions/musicVolume24.png",
"res/actions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced();
extension
.AddAction("ModGlobalVolume",
_("Game global volume"),
_("This action modifies the global volume of the game. The "
"volume is between 0 and 100."),
_("This action modifies the global volume of the game."),
_("the global sound level"),
"",
"res/actions/volume24.png",
"res/actions/volume.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsSimple();
extension
.AddAction("ModPitchSoundChannel",
_("Pitch of the sound of a channel"),
_("This action modifies the pitch (speed) of the sound on a "
"channel.\n1 is the default pitch."),
"channel."),
_("the pitch of the sound on channel _PARAM1_"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced();
extension
.AddAction("ModPitchMusicChannel",
_("Pitch of the music on a channel"),
_("This action modifies the pitch of the music on the "
"specified channel. 1 is the default pitch"),
"specified channel."),
_("the pitch of the music on channel _PARAM1_"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced();
extension
@@ -222,7 +236,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced();
extension
@@ -236,7 +253,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced();
extension
@@ -448,15 +468,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddCondition(
"SoundCanalVolume",
_("Volume of the sound on a channel"),
_("Test the volume of the sound on the specified channel. The volume "
"is between 0 and 100."),
_("Test the volume of the sound on the specified channel."),
_("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"),
"res/conditions/sonVolume24.png",
"res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced();
extension
@@ -471,7 +493,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced();
extension
@@ -484,7 +509,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/volume24.png",
"res/conditions/volume.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")));
extension
.AddCondition(
@@ -498,22 +526,27 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced();
extension
.AddCondition(
"MusicChannelPitch",
_("Pitch of the music on a channel"),
_("Test the pitch (speed) of the music on a specified channel. 1 is "
"the default pitch."),
_("Test the pitch (speed) of the music on a specified channel."),
_("the pitch of the music on channel _PARAM1_"),
_("Music on channels"),
"res/conditions/musicVolume24.png",
"res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced();
extension
@@ -527,7 +560,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced();
extension
@@ -541,7 +577,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced();
extension

View File

@@ -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"),
@@ -407,7 +415,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions());
obj.AddAction("ModVarObjetTxt",
_("Text of an object variable"),
@@ -419,7 +428,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardOperatorParameters("string");
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions());
obj.AddAction("SetObjectVariableAsBoolean",
_("Boolean value of an object variable"),
@@ -516,7 +526,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 +541,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/planicon.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("Layer",
@@ -585,7 +599,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/vitesse.png")
.AddParameter("object", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddCondition("AngleOfDisplacement",
@@ -613,7 +628,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions());
obj.AddCondition("VarObjetTxt",
_("Text of an object variable"),
@@ -625,7 +641,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("object", _("Object"))
.AddParameter("objectvar", _("Variable"))
.UseStandardRelationalOperatorParameters("string");
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions());
obj.AddCondition("ObjectVariableAsBoolean",
_("Boolean value of an object variable"),
@@ -1423,34 +1440,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 +1581,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

@@ -37,7 +37,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 +69,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 +104,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 +120,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 +137,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 +154,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 +171,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 +188,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 +201,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)
@@ -542,7 +542,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Time scale (1 by default)")))
.MarkAsAdvanced();
extension
@@ -572,7 +575,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

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

@@ -160,7 +160,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -180,7 +180,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -276,7 +276,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
@@ -292,7 +292,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)

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

@@ -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
@@ -155,7 +158,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"",
"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

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

View File

@@ -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,28 +171,23 @@ 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");
}
/**
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
* \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

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

@@ -0,0 +1,301 @@
/*
* 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/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);
}
} // namespace gd

View File

@@ -0,0 +1,65 @@
/*
* 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 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);
~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
@@ -252,7 +218,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 +261,7 @@ void WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
.SetType("behavior")
.SetName("Behavior")
.SetDescription("Behavior")
.SetExtraInfo(GetBehaviorFullType(eventsFunctionsExtension.GetName(),
.SetExtraInfo(gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()));
}
}
@@ -315,7 +281,7 @@ void WholeProjectRefactorer::EnsureObjectEventsFunctionsProperParameters(
.SetType("object")
.SetName(parentObjectParameterName)
.SetDescription("Object")
.SetExtraInfo(GetObjectFullType(eventsFunctionsExtension.GetName(),
.SetExtraInfo(gd::PlatformExtension::GetObjectFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName()));
}
}
@@ -330,8 +296,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 +310,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 +326,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 +341,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(
@@ -391,6 +357,43 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
// extension name
};
auto renameBehaviorSharedPropertyFunctions =
[&project, &oldName, &newName](
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::NamedPropertyDescriptor& property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
oldName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyActionName(
property.GetName())),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
newName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyActionName(
property.GetName())));
ExposeProjectEvents(project, actionRenamer);
gd::InstructionsTypeRenamer conditionRenamer =
gd::InstructionsTypeRenamer(
project,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
oldName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyConditionName(
property.GetName())),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
newName,
eventsBasedBehavior.GetName(),
gd::EventsBasedBehavior::GetSharedPropertyConditionName(
property.GetName())));
ExposeProjectEvents(project, conditionRenamer);
// Nothing to do for expressions, expressions are not including the
// extension name
};
auto renameObjectEventsFunction =
[&project, &oldName, &newName](
const gd::EventsBasedObject& eventsBasedObject,
@@ -401,10 +404,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);
@@ -417,12 +420,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(
@@ -432,12 +435,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(
@@ -488,13 +491,19 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
}
// Behavior properties
for (auto&& eventsBasedBehavior :
for (auto &&eventsBasedBehavior :
eventsFunctionsExtension.GetEventsBasedBehaviors().GetInternalVector()) {
auto& behaviorProperties = eventsBasedBehavior->GetPropertyDescriptors();
for (auto&& propertyDescriptor : behaviorProperties.GetInternalVector()) {
for (auto &&propertyDescriptor :
eventsBasedBehavior->GetPropertyDescriptors().GetInternalVector()) {
renameBehaviorPropertyFunctions(*eventsBasedBehavior,
*propertyDescriptor);
}
for (auto &&propertyDescriptor :
eventsBasedBehavior->GetSharedPropertyDescriptors()
.GetInternalVector()) {
renameBehaviorSharedPropertyFunctions(*eventsBasedBehavior,
*propertyDescriptor);
}
}
// Object instructions
@@ -523,8 +532,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
@@ -532,8 +541,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()));
}
}
@@ -550,9 +559,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) {
@@ -585,7 +594,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);
@@ -594,10 +603,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);
@@ -629,7 +638,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);
@@ -638,10 +647,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);
@@ -668,7 +677,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()) {
@@ -703,7 +712,7 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
eventsFunctions.GetEventsFunction(functionName);
const gd::String& eventsFunctionType =
GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
functionName);
@@ -711,7 +720,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,
@@ -743,7 +752,7 @@ void WholeProjectRefactorer::MoveObjectEventsFunctionParameter(
eventsFunctions.GetEventsFunction(functionName);
const gd::String& eventsFunctionType =
GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
gd::PlatformExtension::GetObjectEventsFunctionFullType(eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
functionName);
@@ -751,7 +760,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,
@@ -803,7 +812,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));
@@ -811,11 +820,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)));
@@ -823,11 +832,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)));
@@ -835,6 +844,72 @@ void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
}
}
void WholeProjectRefactorer::RenameEventsBasedBehaviorSharedProperty(
gd::Project& project,
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::String& oldPropertyName,
const gd::String& newPropertyName) {
auto& properties = eventsBasedBehavior.GetPropertyDescriptors();
if (!properties.Has(oldPropertyName)) return;
if (properties.Get(oldPropertyName).GetType() == "Behavior") {
// This is a property representing another behavior that must exist on the
// object.
// This other "required behavior" uses the property name, that is about to
// change, as its name.
// So we must change all reference to this name in the events of the
// behavior functions.
gd::EventsBehaviorRenamer behaviorRenamer(project.GetCurrentPlatform(),
behaviorObjectParameterName,
oldPropertyName,
newPropertyName);
ExposeEventsBasedBehaviorEvents(
project, eventsBasedBehavior, behaviorRenamer);
} else {
// Properties that represent primitive values will be used through
// their related actions/conditions/expressions. Rename these.
// Order is important: we first rename the expressions then the
// instructions, to avoid being unable to fetch the metadata (the types of
// parameters) of instructions after they are renamed.
gd::ExpressionsRenamer expressionRenamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
expressionRenamer.SetReplacedBehaviorExpression(
gd::PlatformExtension::GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
EventsBasedBehavior::GetSharedPropertyExpressionName(oldPropertyName),
EventsBasedBehavior::GetSharedPropertyExpressionName(newPropertyName));
ExposeProjectEvents(project, expressionRenamer);
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyActionName(oldPropertyName)),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyActionName(newPropertyName)));
ExposeProjectEvents(project, actionRenamer);
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyConditionName(oldPropertyName)),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetSharedPropertyConditionName(newPropertyName)));
ExposeProjectEvents(project, conditionRenamer);
}
}
void WholeProjectRefactorer::RenameEventsBasedObjectProperty(
gd::Project& project,
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
@@ -853,7 +928,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));
@@ -861,11 +936,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)));
@@ -873,11 +948,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)));
@@ -1114,11 +1189,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()));
@@ -1134,11 +1209,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())));
@@ -1146,11 +1221,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())));
@@ -1160,6 +1235,40 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
// the behavior
};
auto renameBehaviorSharedProperty = [&project,
&eventsFunctionsExtension,
&oldBehaviorName,
&newBehaviorName](
const gd::NamedPropertyDescriptor&
property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldBehaviorName,
EventsBasedBehavior::GetSharedPropertyActionName(property.GetName())),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newBehaviorName,
EventsBasedBehavior::GetSharedPropertyActionName(property.GetName())));
ExposeProjectEvents(project, actionRenamer);
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
oldBehaviorName,
EventsBasedBehavior::GetSharedPropertyConditionName(property.GetName())),
gd::PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
newBehaviorName,
EventsBasedBehavior::GetSharedPropertyConditionName(property.GetName())));
ExposeProjectEvents(project, conditionRenamer);
// Nothing to do for expression, expressions are not including the name of
// the behavior
};
// Order is important: we first rename the expressions then the instructions,
// to avoid being unable to fetch the metadata (the types of parameters) of
// instructions after they are renamed.
@@ -1180,15 +1289,17 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
}
// Behavior properties
auto& properties = eventsBasedBehavior.GetPropertyDescriptors();
for (auto&& property : properties.GetInternalVector()) {
for (auto&& property : eventsBasedBehavior.GetPropertyDescriptors().GetInternalVector()) {
renameBehaviorProperty(*property);
}
for (auto&& property : eventsBasedBehavior.GetSharedPropertyDescriptors().GetInternalVector()) {
renameBehaviorSharedProperty(*property);
}
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(
@@ -1217,11 +1328,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()));
@@ -1237,11 +1348,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())));
@@ -1249,11 +1360,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())));
@@ -1290,8 +1401,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

@@ -207,6 +207,21 @@ class GD_CORE_API WholeProjectRefactorer {
const gd::String& oldPropertyName,
const gd::String& newPropertyName);
/**
* \brief Refactor the project **before** a shared property of a behavior is
* renamed.
*
* \warning Do the renaming of the specified shared property after calling
* this. This is because the shared property is expected to have its old name
* for the refactoring.
*/
static void RenameEventsBasedBehaviorSharedProperty(
gd::Project& project,
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::String& oldPropertyName,
const gd::String& newPropertyName);
/**
* \brief Refactor the project **before** a property of an object is
* renamed.

View File

@@ -13,7 +13,8 @@ namespace gd {
/**
* \brief Base class used to represents a behavior that can be applied to an
* object. It stores the content (i.e: the properties) of a behavior of an object.
* object. It stores the content (i.e: the properties) of a behavior of an object
* and forward the properties related functions to Javascript with Emscripten.
*
* \see gd::BehaviorsSharedData
* \see gd::Object

View File

@@ -11,6 +11,7 @@
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/Serializer.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Project/CustomConfigurationHelper.h"
#include <map>
@@ -21,52 +22,26 @@ CustomBehavior *CustomBehavior::Clone() const {
return clone;
}
void CustomBehavior::InitializeContent(gd::SerializerElement &behaviorContent) {
if (!project.HasEventsBasedBehavior(GetTypeName())) {
return;
}
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
gd::CustomConfigurationHelper::InitializeContent(properties, behaviorContent);
}
std::map<gd::String, gd::PropertyDescriptor> CustomBehavior::GetProperties(
const gd::SerializerElement &behaviorContent) const {
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
if (!project.HasEventsBasedBehavior(GetTypeName())) {
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
return behaviorProperties;
}
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
for (auto &property : properties.GetInternalVector()) {
const auto &propertyName = property->GetName();
const auto &propertyType = property->GetType();
// TODO Move this into a PropertyDescriptor copy method.
auto &newProperty = behaviorProperties[propertyName]
.SetType(property->GetType())
.SetDescription(property->GetDescription())
.SetGroup(property->GetGroup())
.SetLabel(property->GetLabel())
.SetValue(property->GetValue())
.SetHidden(property->IsHidden());
for (auto &extraInfo : property->GetExtraInfo()) {
newProperty.AddExtraInfo(extraInfo);
}
if (behaviorContent.HasChild(propertyName)) {
if (propertyType == "String" || propertyType == "Choice" ||
propertyType == "Color" || propertyType == "Behavior") {
newProperty.SetValue(
behaviorContent.GetChild(propertyName).GetStringValue());
} else if (propertyType == "Number") {
newProperty.SetValue(gd::String::From(
behaviorContent.GetChild(propertyName).GetDoubleValue()));
} else if (propertyType == "Boolean") {
newProperty.SetValue(
behaviorContent.GetChild(propertyName).GetBoolValue() ? "true"
: "false");
}
} else {
// No value was serialized for this property. `newProperty`
// will have the default value coming from `enumeratedProperty`.
}
}
return behaviorProperties;
return gd::CustomConfigurationHelper::GetProperties(properties, behaviorContent);
}
bool CustomBehavior::UpdateProperty(gd::SerializerElement &behaviorContent,
@@ -77,43 +52,10 @@ bool CustomBehavior::UpdateProperty(gd::SerializerElement &behaviorContent,
}
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
if (!properties.Has(propertyName)) {
return false;
}
const auto &property = properties.Get(propertyName);
auto &element = behaviorContent.AddChild(propertyName);
const gd::String &propertyType = property.GetType();
if (propertyType == "String" || propertyType == "Choice" ||
propertyType == "Color" || propertyType == "Behavior") {
element.SetStringValue(newValue);
} else if (propertyType == "Number") {
element.SetDoubleValue(newValue.To<double>());
} else if (propertyType == "Boolean") {
element.SetBoolValue(newValue == "1");
}
return true;
}
void CustomBehavior::InitializeContent(gd::SerializerElement &behaviorContent) {
if (!project.HasEventsBasedBehavior(GetTypeName())) {
return;
}
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
const auto &properties = eventsBasedBehavior.GetPropertyDescriptors();
for (auto &&property : properties.GetInternalVector()) {
auto &element = behaviorContent.AddChild(property->GetName());
auto propertyType = property->GetType();
if (propertyType == "String" || propertyType == "Choice" ||
propertyType == "Color" || propertyType == "Behavior") {
element.SetStringValue(property->GetValue());
} else if (propertyType == "Number") {
element.SetDoubleValue(property->GetValue().To<double>());
} else if (propertyType == "Boolean") {
element.SetBoolValue(property->GetValue() == "true");
}
}
return gd::CustomConfigurationHelper::UpdateProperty(
properties,
behaviorContent,
propertyName,
newValue);
}

View File

@@ -17,8 +17,7 @@ using namespace gd;
namespace gd {
/**
* \brief A gd::Behavior that stores its content in JSON and forward the
* properties related functions to Javascript with Emscripten.
* \brief A gd::Behavior that stores its content in JSON.
*/
class CustomBehavior : public gd::Behavior {
public:
@@ -34,13 +33,11 @@ public:
using Behavior::UpdateProperty;
protected:
virtual std::map<gd::String, gd::PropertyDescriptor>
std::map<gd::String, gd::PropertyDescriptor>
GetProperties(const gd::SerializerElement &behaviorContent) const override;
virtual bool UpdateProperty(gd::SerializerElement &behaviorContent,
const gd::String &name,
const gd::String &value) override;
virtual void
InitializeContent(gd::SerializerElement &behaviorContent) override;
bool UpdateProperty(gd::SerializerElement &behaviorContent,
const gd::String &name, const gd::String &value) override;
void InitializeContent(gd::SerializerElement &behaviorContent) override;
private:
const Project &project; ///< The project is used to get the

View File

@@ -0,0 +1,61 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "CustomBehaviorsSharedData.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/Serializer.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Project/CustomConfigurationHelper.h"
#include <map>
using namespace gd;
CustomBehaviorsSharedData *CustomBehaviorsSharedData::Clone() const {
CustomBehaviorsSharedData *clone = new CustomBehaviorsSharedData(*this);
return clone;
}
void CustomBehaviorsSharedData::InitializeContent(gd::SerializerElement &behaviorContent) {
if (!project.HasEventsBasedBehavior(GetTypeName())) {
return;
}
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
const auto &properties = eventsBasedBehavior.GetSharedPropertyDescriptors();
gd::CustomConfigurationHelper::InitializeContent(properties, behaviorContent);
}
std::map<gd::String, gd::PropertyDescriptor> CustomBehaviorsSharedData::GetProperties(
const gd::SerializerElement &behaviorContent) const {
if (!project.HasEventsBasedBehavior(GetTypeName())) {
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
return behaviorProperties;
}
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
const auto &properties = eventsBasedBehavior.GetSharedPropertyDescriptors();
return gd::CustomConfigurationHelper::GetProperties(properties, behaviorContent);
}
bool CustomBehaviorsSharedData::UpdateProperty(gd::SerializerElement &behaviorContent,
const gd::String &propertyName,
const gd::String &newValue) {
if (!project.HasEventsBasedBehavior(GetTypeName())) {
return false;
}
const auto &eventsBasedBehavior = project.GetEventsBasedBehavior(GetTypeName());
const auto &properties = eventsBasedBehavior.GetSharedPropertyDescriptors();
return gd::CustomConfigurationHelper::UpdateProperty(
properties,
behaviorContent,
propertyName,
newValue);
}

View File

@@ -0,0 +1,46 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_CUSTOMBEHAVIORSSHAREDDATA_H
#define GDCORE_CUSTOMBEHAVIORSSHAREDDATA_H
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/Serializer.h"
#include "GDCore/Serialization/SerializerElement.h"
using namespace gd;
namespace gd {
/**
* \brief A gd::BehaviorsSharedData that stores its content in JSON.
*/
class CustomBehaviorsSharedData : public gd::BehaviorsSharedData {
public:
CustomBehaviorsSharedData(const gd::String &name, const Project &project_,
const gd::String &fullType)
: BehaviorsSharedData(name, fullType), project(project_) {}
CustomBehaviorsSharedData *Clone() const override;
using BehaviorsSharedData::GetProperties;
using BehaviorsSharedData::InitializeContent;
using BehaviorsSharedData::UpdateProperty;
protected:
std::map<gd::String, gd::PropertyDescriptor>
GetProperties(const gd::SerializerElement &behaviorContent) const override;
bool UpdateProperty(gd::SerializerElement &behaviorContent,
const gd::String &name, const gd::String &value) override;
void InitializeContent(gd::SerializerElement &behaviorContent) override;
private:
const Project &project; ///< The project is used to get the
///< EventBasedBehavior from the fullType.
};
} // namespace gd
#endif // GDCORE_CUSTOMBEHAVIORSSHAREDDATA_H

View File

@@ -0,0 +1,104 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "CustomConfigurationHelper.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/Serializer.h"
#include "GDCore/Serialization/SerializerElement.h"
#include <map>
using namespace gd;
void CustomConfigurationHelper::InitializeContent(
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
gd::SerializerElement &configurationContent) {
for (auto &&property : properties.GetInternalVector()) {
auto &element = configurationContent.AddChild(property->GetName());
auto propertyType = property->GetType();
if (propertyType == "String" || propertyType == "Choice" ||
propertyType == "Color" || propertyType == "Behavior") {
element.SetStringValue(property->GetValue());
} else if (propertyType == "Number") {
element.SetDoubleValue(property->GetValue().To<double>());
} else if (propertyType == "Boolean") {
element.SetBoolValue(property->GetValue() == "true");
}
}
}
std::map<gd::String, gd::PropertyDescriptor> CustomConfigurationHelper::GetProperties(
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
const gd::SerializerElement &configurationContent) {
auto behaviorProperties = std::map<gd::String, gd::PropertyDescriptor>();
for (auto &property : properties.GetInternalVector()) {
const auto &propertyName = property->GetName();
const auto &propertyType = property->GetType();
// TODO Move this into a PropertyDescriptor copy method.
auto &newProperty = behaviorProperties[propertyName]
.SetType(property->GetType())
.SetDescription(property->GetDescription())
.SetGroup(property->GetGroup())
.SetLabel(property->GetLabel())
.SetValue(property->GetValue())
.SetHidden(property->IsHidden());
for (auto &extraInfo : property->GetExtraInfo()) {
newProperty.AddExtraInfo(extraInfo);
}
if (configurationContent.HasChild(propertyName)) {
if (propertyType == "String" || propertyType == "Choice" ||
propertyType == "Color" || propertyType == "Behavior") {
newProperty.SetValue(
configurationContent.GetChild(propertyName).GetStringValue());
} else if (propertyType == "Number") {
newProperty.SetValue(gd::String::From(
configurationContent.GetChild(propertyName).GetDoubleValue()));
} else if (propertyType == "Boolean") {
newProperty.SetValue(
configurationContent.GetChild(propertyName).GetBoolValue() ? "true"
: "false");
}
} else {
// No value was serialized for this property. `newProperty`
// will have the default value coming from `enumeratedProperty`.
}
}
return behaviorProperties;
}
bool CustomConfigurationHelper::UpdateProperty(
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
gd::SerializerElement &configurationContent,
const gd::String &propertyName,
const gd::String &newValue) {
if (!properties.Has(propertyName)) {
return false;
}
const auto &property = properties.Get(propertyName);
auto &element = configurationContent.AddChild(propertyName);
const gd::String &propertyType = property.GetType();
if (propertyType == "String" || propertyType == "Choice" ||
propertyType == "Color" || propertyType == "Behavior") {
element.SetStringValue(newValue);
} else if (propertyType == "Number") {
element.SetDoubleValue(newValue.To<double>());
} else if (propertyType == "Boolean") {
element.SetBoolValue(newValue == "1");
}
return true;
}

View File

@@ -0,0 +1,43 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_CUSTOMCONFIGURATIONHELPER_H
#define GDCORE_CUSTOMCONFIGURATIONHELPER_H
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/Serializer.h"
#include "GDCore/Serialization/SerializerElement.h"
using namespace gd;
namespace gd {
/**
* \brief Helper functions that gd::CustomBehavior and gd::CustomBehaviorsSharedData use to
* store their content in JSON.
*/
class CustomConfigurationHelper {
public:
CustomConfigurationHelper() {}
static void InitializeContent(
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
gd::SerializerElement &behaviorContent);
static std::map<gd::String, gd::PropertyDescriptor> GetProperties(
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
const gd::SerializerElement &behaviorContent);
static bool UpdateProperty(
const gd::SerializableWithNameList<gd::NamedPropertyDescriptor> &properties,
gd::SerializerElement &behaviorContent,
const gd::String &name,
const gd::String &value);
};
} // namespace gd
#endif // GDCORE_CUSTOMCONFIGURATIONHELPER_H

View File

@@ -12,6 +12,7 @@
#include "GDCore/Serialization/Serializer.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/Log.h"
#include "GDCore/Project/CustomConfigurationHelper.h"
using namespace gd;
@@ -67,50 +68,7 @@ std::map<gd::String, gd::PropertyDescriptor> CustomObjectConfiguration::GetPrope
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
const auto &properties = eventsBasedObject.GetPropertyDescriptors();
for (auto &property : properties.GetInternalVector()) {
const auto &propertyName = property->GetName();
const auto &propertyType = property->GetType();
// TODO Move this into a PropertyDescriptor copy method.
auto &newProperty = objectProperties[propertyName]
.SetType(property->GetType())
.SetDescription(property->GetDescription())
.SetGroup(property->GetGroup())
.SetLabel(property->GetLabel())
.SetValue(property->GetValue())
.SetHidden(property->IsHidden());
for (auto &extraInfo : property->GetExtraInfo()) {
newProperty.AddExtraInfo(extraInfo);
}
if (objectContent.HasChild(propertyName)) {
if (
propertyType == "String" ||
propertyType == "Choice" ||
propertyType == "Color"
) {
newProperty.SetValue(
objectContent.GetChild(propertyName).GetStringValue()
);
} else if (propertyType == "Number") {
newProperty.SetValue(
gd::String::From(objectContent.GetChild(propertyName).GetDoubleValue())
);
} else if (propertyType == "Boolean") {
newProperty.SetValue(
objectContent.GetChild(propertyName).GetBoolValue()
? "true"
: "false"
);
}
} else {
// No value was serialized for this property. `newProperty`
// will have the default value coming from `enumeratedProperty`.
}
}
return objectProperties;
return gd::CustomConfigurationHelper::GetProperties(properties, objectContent);
}
bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
@@ -120,27 +78,12 @@ bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
}
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
const auto &properties = eventsBasedObject.GetPropertyDescriptors();
if (!properties.Has(propertyName)) {
return false;
}
const auto &property = properties.Get(propertyName);
auto &element = objectContent.AddChild(propertyName);
const gd::String &propertyType = property.GetType();
if (
propertyType == "String" ||
propertyType == "Choice" ||
propertyType == "Color"
) {
element.SetStringValue(newValue);
} else if (propertyType == "Number") {
element.SetDoubleValue(newValue.To<double>());
} else if (propertyType == "Boolean") {
element.SetBoolValue(newValue == "1");
}
return true;
return gd::CustomConfigurationHelper::UpdateProperty(
properties,
objectContent,
propertyName,
newValue);
}
std::map<gd::String, gd::PropertyDescriptor>

View File

@@ -21,6 +21,8 @@ void EventsBasedBehavior::SerializeTo(SerializerElement& element) const {
if (isPrivate) {
element.SetBoolAttribute("private", isPrivate);
}
sharedPropertyDescriptors.SerializeElementsTo(
"propertyDescriptor", element.AddChild("sharedPropertyDescriptors"));
}
void EventsBasedBehavior::UnserializeFrom(gd::Project& project,
@@ -28,6 +30,8 @@ void EventsBasedBehavior::UnserializeFrom(gd::Project& project,
AbstractEventsBasedEntity::UnserializeFrom(project, element);
objectType = element.GetStringAttribute("objectType");
isPrivate = element.GetBoolAttribute("private");
sharedPropertyDescriptors.UnserializeElementsFrom(
"propertyDescriptor", element.GetChild("sharedPropertyDescriptors"));
}
} // namespace gd

View File

@@ -88,6 +88,43 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
return *this;
}
/**
* \brief Return a reference to the list of shared properties.
*/
SerializableWithNameList<NamedPropertyDescriptor>& GetSharedPropertyDescriptors() {
return sharedPropertyDescriptors;
}
/**
* \brief Return a const reference to the list of shared properties.
*/
const SerializableWithNameList<NamedPropertyDescriptor>& GetSharedPropertyDescriptors()
const {
return sharedPropertyDescriptors;
}
/**
* \brief Get the name of the action to change a shared property.
*/
static gd::String GetSharedPropertyActionName(const gd::String &propertyName) {
return "SetSharedProperty" + propertyName;
};
/**
* \brief Get the name of the condition to compare a shared property.
*/
static gd::String GetSharedPropertyConditionName(const gd::String &propertyName) {
return "SharedProperty" + propertyName;
};
/**
* \brief Get the name of the expression to get a shared property.
*/
static gd::String
GetSharedPropertyExpressionName(const gd::String &propertyName) {
return "SharedProperty" + propertyName;
};
void SerializeTo(SerializerElement& element) const override;
void UnserializeFrom(gd::Project& project,
@@ -96,6 +133,7 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
private:
gd::String objectType;
bool isPrivate = false;
SerializableWithNameList<NamedPropertyDescriptor> sharedPropertyDescriptors;
};
} // namespace gd

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,

View File

@@ -54,7 +54,7 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element) const {
element.SetAttribute("version", version);
element.SetAttribute("extensionNamespace", extensionNamespace);
element.SetAttribute("shortDescription", shortDescription);
element.SetAttribute("description", description);
element.AddChild("description").SetMultilineStringValue(description);
element.SetAttribute("name", name);
element.SetAttribute("fullName", fullName);
element.SetAttribute("category", category);
@@ -100,7 +100,7 @@ void EventsFunctionsExtension::UnserializeExtensionDeclarationFrom(
version = element.GetStringAttribute("version");
extensionNamespace = element.GetStringAttribute("extensionNamespace");
shortDescription = element.GetStringAttribute("shortDescription");
description = element.GetStringAttribute("description");
description = element.GetChild("description").GetMultilineStringValue();
name = element.GetStringAttribute("name");
fullName = element.GetStringAttribute("fullName");
category = element.GetStringAttribute("category");

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

@@ -17,6 +17,7 @@
#include "GDCore/IDE/SceneNameMangler.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/CustomBehaviorsSharedData.h"
#include "GDCore/Project/InitialInstance.h"
#include "GDCore/Project/Layer.h"
#include "GDCore/Project/Object.h"
@@ -26,6 +27,7 @@
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
#include "GDCore/Tools/PolymorphicClone.h"
#include "GDCore/Tools/Log.h"
using namespace std;
@@ -240,11 +242,11 @@ void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
}
}
std::unique_ptr<gd::BehaviorsSharedData> Layout::CreateBehaviorsSharedData(gd::Project& project, const gd::String& name, const gd::String& behaviorsType) {
std::unique_ptr<gd::BehaviorsSharedData> Layout::CreateBehaviorsSharedData(
gd::Project& project, const gd::String& name, const gd::String& behaviorsType) {
if (project.HasEventsBasedBehavior(behaviorsType)) {
// Events based behaviors don't have shared data yet.
auto sharedData =
gd::make_unique<gd::BehaviorsSharedData>(name, behaviorsType);
gd::make_unique<gd::CustomBehaviorsSharedData>(name, project, behaviorsType);
sharedData->InitializeContent();
return std::move(sharedData);
}
@@ -253,7 +255,14 @@ std::unique_ptr<gd::BehaviorsSharedData> Layout::CreateBehaviorsSharedData(gd::P
project.GetCurrentPlatform(),
behaviorsType);
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
return nullptr;
gd::LogWarning("Tried to create a behavior shared data with an unknown type: " +
behaviorsType + " on object " + GetName() + "!");
// It's probably an events-based behavior that was removed.
// Create a custom behavior shared data to preserve the properties values.
auto sharedData =
gd::make_unique<gd::CustomBehaviorsSharedData>(name, project, behaviorsType);
sharedData->InitializeContent();
return std::move(sharedData);
}
gd::BehaviorsSharedData* behaviorsSharedDataBluePrint =

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

@@ -114,7 +114,7 @@ gd::Behavior* Object::AddNewBehavior(const gd::Project& project,
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
gd::LogWarning("Tried to create a behavior with an unknown type: " + type
+ " on object " + GetName() + "!");
// It's probably an events-based object that was removed.
// It's probably an events-based behavior that was removed.
// Create a custom behavior to preserve the properties values.
return initializeAndAdd(
gd::make_unique<CustomBehavior>(name, project, type));

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;

View File

@@ -165,7 +165,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_) {
@@ -458,7 +458,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 +467,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 +525,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 +633,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 +712,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 +806,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.
*

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

@@ -208,8 +208,7 @@ SerializerElement& SerializerElement::GetChild(
for (size_t i = 0; i < children.size(); ++i) {
if (children[i].second == std::shared_ptr<SerializerElement>()) continue;
if (children[i].first == name ||
(isArray && children[i].first.empty()) ||
if (children[i].first == name || (isArray && children[i].first.empty()) ||
(!deprecatedName.empty() && children[i].first == deprecatedName)) {
if (index == currentIndex)
return *children[i].second;
@@ -242,8 +241,7 @@ std::size_t SerializerElement::GetChildrenCount(
for (size_t i = 0; i < children.size(); ++i) {
if (children[i].second == std::shared_ptr<SerializerElement>()) continue;
if (children[i].first == name ||
(isArray && children[i].first.empty()) ||
if (children[i].first == name || (isArray && children[i].first.empty()) ||
(!deprecatedName.empty() && children[i].first == deprecatedName))
currentIndex++;
}
@@ -291,4 +289,31 @@ void SerializerElement::Init(const gd::SerializerElement& other) {
deprecatedArrayOf = other.deprecatedArrayOf;
}
void SerializerElement::SetMultilineStringValue(const gd::String& value) {
if (value.find('\n') == gd::String::npos) {
SetStringValue(value);
return;
}
std::vector<gd::String> lines = value.Split('\n');
children.clear();
ConsiderAsArrayOf("");
for (const auto& line : lines) {
AddChild("").SetStringValue(line);
}
}
gd::String SerializerElement::GetMultilineStringValue() {
if (!ConsideredAsArray()) {
return GetValue().GetString();
}
gd::String value;
for (const auto& child : children) {
if (!value.empty()) value += "\n";
value += child.second->GetStringValue();
}
return value;
}
} // namespace gd

View File

@@ -10,6 +10,7 @@
#include <memory>
#include <string>
#include <vector>
#include "GDCore/Serialization/SerializerValue.h"
#include "GDCore/String.h"
@@ -177,6 +178,18 @@ class GD_CORE_API SerializerElement {
* \brief Return true if no value was set for the element.
*/
bool IsValueUndefined() const { return valueUndefined; }
/**
* \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);
/**
* \brief Read the value, either represented as a string or as an array of strings,
* into a string.
*/
gd::String GetMultilineStringValue();
///@}
/** \name Attributes
@@ -440,7 +453,7 @@ class GD_CORE_API SerializerElement {
* Initialize element using another element. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed!
*/
void Init(const gd::SerializerElement& other);
void Init(const gd::SerializerElement &other);
bool valueUndefined; ///< If true, the element does not have a value.
SerializerValue elementValue;

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

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

@@ -81,6 +81,30 @@ TEST_CASE("SerializerElement", "[common]") {
REQUIRE(element.GetChild(2).GetDoubleValue() == 45.6);
}
SECTION("Multiline strings") {
SerializerElement element;
// A single line is saved as a string.
element.SetMultilineStringValue("test");
REQUIRE(element.GetMultilineStringValue() == "test");
REQUIRE(element.GetStringValue() == "test");
// A string can be read.
element.SetStringValue("test of\nsomething\nsaved as a string");
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.");
REQUIRE(element.ConsideredAsArray() == true);
REQUIRE(element.GetChildrenCount() == 3);
REQUIRE(element.GetMultilineStringValue() == "test\nwith\nmultiple lines.");
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");
}
SECTION("(Deprecated) attributes") {
SerializerElement element;
element.AddChild("child1").SetStringValue("value123");

View File

@@ -80,6 +80,9 @@ enum TestEvent {
BehaviorPropertyAction,
BehaviorPropertyCondition,
BehaviorPropertyExpression,
BehaviorSharedPropertyAction,
BehaviorSharedPropertyCondition,
BehaviorSharedPropertyExpression,
BehaviorExpression,
IllNamedBehaviorExpression,
NoParameterBehaviorExpression,
@@ -338,6 +341,52 @@ const void SetupEvents(gd::EventsList &eventList) {
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != BehaviorSharedPropertyAction) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" action
{
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType(
"MyEventsExtension::MyEventsBasedBehavior::" +
gd::EventsBasedBehavior::GetSharedPropertyActionName("MyProperty"));
event.GetActions().Insert(instruction);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != BehaviorSharedPropertyCondition) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" condition
{
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType(
"MyEventsExtension::MyEventsBasedBehavior::" +
gd::EventsBasedBehavior::GetSharedPropertyConditionName("MyProperty"));
event.GetConditions().Insert(instruction);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != BehaviorSharedPropertyExpression) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
// Create an event in the layout using "MyProperty" expression
{
gd::StandardEvent event;
gd::Instruction instruction;
instruction.SetType("MyExtension::DoSomething");
instruction.SetParametersCount(1);
instruction.SetParameter(
0, gd::Expression("ObjectWithMyBehavior.MyBehavior::" +
gd::EventsBasedBehavior::GetSharedPropertyExpressionName(
"MyProperty") +
"()"));
event.GetActions().Insert(instruction);
eventList.InsertEvent(event);
}
if (eventList.GetEventsCount() != BehaviorExpression) {
throw std::logic_error("Invalid events setup: " + std::to_string(eventList.GetEventsCount()));
}
@@ -811,6 +860,11 @@ SetupProjectWithEventsFunctionExtension(gd::Project &project) {
eventsBasedBehavior.GetPropertyDescriptors()
.InsertNew("MyProperty", 0)
.SetType("Number");
// The same name is used for the shared property to ensure there is no name
// collision.
eventsBasedBehavior.GetSharedPropertyDescriptors()
.InsertNew("MyProperty", 0)
.SetType("Number");
}
// Add a events based object
@@ -1432,6 +1486,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
eventsList->GetEvent(BehaviorPropertyAction)) ==
"MyRenamedExtension::MyEventsBasedBehavior::"
"SetPropertyMyProperty");
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(BehaviorSharedPropertyAction)) ==
"MyRenamedExtension::MyEventsBasedBehavior::"
"SetSharedPropertyMyProperty");
// Check events-based behavior methods have *not* been renamed in
// expressions
@@ -1746,6 +1804,10 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
eventsList->GetEvent(BehaviorPropertyAction)) ==
"MyEventsExtension::MyRenamedEventsBasedBehavior::"
"SetPropertyMyProperty");
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(BehaviorSharedPropertyAction)) ==
"MyEventsExtension::MyRenamedEventsBasedBehavior::"
"SetSharedPropertyMyProperty");
// Check events-based behavior methods have *not* been renamed in
// expressions
@@ -2327,8 +2389,7 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
}
}
SECTION(
"(Events based behavior) property renamed (not a required behavior)") {
SECTION("(Events based behavior) property renamed (not a required behavior)") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
@@ -2356,6 +2417,67 @@ TEST_CASE("WholeProjectRefactorer", "[common]") {
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorPropertyExpression)) ==
"ObjectWithMyBehavior.MyBehavior::PropertyMyRenamedProperty()");
// Ensure that the shared property was NOT renamed.
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(BehaviorSharedPropertyAction)) ==
"MyEventsExtension::MyEventsBasedBehavior::"
"SetSharedPropertyMyProperty");
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(BehaviorSharedPropertyCondition)) ==
"MyEventsExtension::MyEventsBasedBehavior::"
"SharedPropertyMyProperty");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorSharedPropertyExpression)) ==
"ObjectWithMyBehavior.MyBehavior::SharedPropertyMyProperty()");
}
}
SECTION("(Events based behavior) shared property renamed") {
gd::Project project;
gd::Platform platform;
SetupProjectWithDummyPlatform(project, platform);
auto &eventsExtension = SetupProjectWithEventsFunctionExtension(project);
auto &eventsBasedBehavior =
eventsExtension.GetEventsBasedBehaviors().Get("MyEventsBasedBehavior");
gd::WholeProjectRefactorer::RenameEventsBasedBehaviorSharedProperty(
project, eventsExtension, eventsBasedBehavior, "MyProperty",
"MyRenamedProperty");
for (auto *eventsList : GetEventsLists(project)) {
// Check if events-based behaviors shared property has been renamed in
// instructions
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(BehaviorSharedPropertyAction)) ==
"MyEventsExtension::MyEventsBasedBehavior::"
"SetSharedPropertyMyRenamedProperty");
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(BehaviorSharedPropertyCondition)) ==
"MyEventsExtension::MyEventsBasedBehavior::"
"SharedPropertyMyRenamedProperty");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorSharedPropertyExpression)) ==
"ObjectWithMyBehavior.MyBehavior::SharedPropertyMyRenamedProperty()");
// Ensure that the property was NOT renamed.
REQUIRE(GetEventFirstActionType(
eventsList->GetEvent(BehaviorPropertyAction)) ==
"MyEventsExtension::MyEventsBasedBehavior::"
"SetPropertyMyProperty");
REQUIRE(GetEventFirstConditionType(
eventsList->GetEvent(BehaviorPropertyCondition)) ==
"MyEventsExtension::MyEventsBasedBehavior::"
"PropertyMyProperty");
REQUIRE(GetEventFirstActionFirstParameterString(
eventsList->GetEvent(BehaviorPropertyExpression)) ==
"ObjectWithMyBehavior.MyBehavior::PropertyMyProperty()");
}
}

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 */,
@@ -35,8 +37,9 @@ module.exports = {
)
.setExtensionHelpPath('/objects/bbtext')
.setCategory('User interface');
extension.addInstructionOrExpressionGroupMetadata(_("BBCode Text Object"))
.setIcon("JsPlatform/Extensions/bbcode32.png");
extension
.addInstructionOrExpressionGroupMetadata(_('BBCode Text Object'))
.setIcon('JsPlatform/Extensions/bbcode32.png');
var objectBBText = new gd.ObjectJsImplementation();
// $FlowExpectedError
@@ -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

@@ -187,7 +187,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 +202,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 +222,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 +236,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 +256,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 +314,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 +382,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');

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

@@ -15,9 +15,9 @@ namespace gdjs {
this._textToSet = behaviorData.property1;
// You can also access to the shared data:
const sharedData = instanceContainer
.getScene()
.getInitialSharedDataForBehavior(behaviorData.name);
const sharedData = instanceContainer.getInitialSharedDataForBehavior(
behaviorData.name
);
this._textToSet = (sharedData as any).sharedProperty1;
// You can also run arbitrary code at the creation of the behavior:

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

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

@@ -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,38 @@ 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 +74,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;
};

View File

@@ -33,27 +33,24 @@ namespace gdjs {
const StretchedSprite = !tiled ? PIXI.Sprite : PIXI.TilingSprite;
this._spritesContainer = new PIXI.Container();
this._wrapperContainer = new PIXI.Container();
// @ts-ignore
this._centerSprite = new StretchedSprite(new PIXI.Texture(texture));
this._centerSprite = new StretchedSprite(
new PIXI.Texture(texture.baseTexture)
);
this._borderSprites = [
// @ts-ignore
new StretchedSprite(new PIXI.Texture(texture)),
//Right
// Right
new StretchedSprite(new PIXI.Texture(texture.baseTexture)),
// Top-Right
new PIXI.Sprite(texture),
//Top-Right
// @ts-ignore
new StretchedSprite(new PIXI.Texture(texture)),
//Top
// Top
new StretchedSprite(new PIXI.Texture(texture.baseTexture)),
// Top-Left
new PIXI.Sprite(texture),
//Top-Left
// @ts-ignore
new StretchedSprite(new PIXI.Texture(texture)),
//Left
// Left
new StretchedSprite(new PIXI.Texture(texture.baseTexture)),
// Bottom-Left
new PIXI.Sprite(texture),
//Bottom-Left
// @ts-ignore
new StretchedSprite(new PIXI.Texture(texture)),
//Bottom
// Bottom
new StretchedSprite(new PIXI.Texture(texture.baseTexture)),
new PIXI.Sprite(texture),
];
@@ -77,11 +74,19 @@ namespace gdjs {
ensureUpToDate() {
if (this._spritesContainer.visible && this._wasRendered) {
// Cache the rendered sprites as a bitmap to speed up rendering when
// lots of panel sprites are on the scene.
// Sadly, because of this, we need a wrapper container to workaround
// a PixiJS issue with alpha (see updateOpacity).
this._spritesContainer.cacheAsBitmap = true;
// PIXI uses PIXI.SCALE_MODES.LINEAR for the cached image:
// this._spritesContainer._cacheData.sprite._texture.baseTexture.scaleMode
// There seems to be no way to configure this so the optimization is disabled.
if (
this._centerSprite.texture.baseTexture.scaleMode !==
PIXI.SCALE_MODES.NEAREST
) {
// Cache the rendered sprites as a bitmap to speed up rendering when
// lots of panel sprites are on the scene.
// Sadly, because of this, we need a wrapper container to workaround
// a PixiJS issue with alpha (see updateOpacity).
this._spritesContainer.cacheAsBitmap = true;
}
}
this._wasRendered = true;
}
@@ -193,14 +198,10 @@ namespace gdjs {
instanceContainer: gdjs.RuntimeInstanceContainer
): void {
const obj = this._object;
// @ts-ignore
const texture = instanceContainer
.getGame()
.getImageManager()
.getPIXITexture(textureName) as PIXI.BaseTexture<
PIXI.Resource,
PIXI.IAutoDetectOptions
>;
.getPIXITexture(textureName).baseTexture;
this._textureWidth = texture.width;
this._textureHeight = texture.height;

View File

@@ -5,10 +5,9 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#include "Extension.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Tools/Localization.h"
#include "Extension.h"
#include "ParticleEmitterObject.h"
/**
@@ -23,7 +22,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddAction("EmitterForceMax",
_("Emission maximal force"),
@@ -33,7 +33,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddAction("EmitterAngle",
_("Emission angle"),
@@ -43,7 +44,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle (in degrees)")));
obj.AddCondition("EmitterAngle",
_("Emission angle"),
@@ -53,7 +57,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle to compare to (in degrees)")));
obj.AddAction("EmitterAngleA",
_("Emission angle 1"),
@@ -63,8 +70,9 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number")
.SetHidden(); // Angle A is not used.
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden(); // Angle A is not used.
obj.AddCondition("EmitterAngleA",
_("Emission angle 1"),
@@ -74,8 +82,9 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number")
.SetHidden(); // Angle A is not used.
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetHidden(); // Angle A is not used.
obj.AddAction("EmitterAngleB",
_("Emission angle 2"),
@@ -85,8 +94,9 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number")
.SetHidden(); // Angle B is the same as cone spray angle
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetHidden(); // Angle B is the same as cone spray angle
obj.AddCondition("EmitterAngleB",
_("Emission angle 2"),
@@ -96,8 +106,9 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number")
.SetHidden(); // Angle B is the same as cone spray angle
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetHidden(); // Angle B is the same as cone spray angle
obj.AddAction(
"ConeSprayAngle",
@@ -108,7 +119,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle (in degrees)")));
obj.AddCondition("ConeSprayAngle",
_("Angle of the spray cone"),
@@ -118,7 +132,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle to compare to (in degrees)")));
obj.AddAction("ZoneRadius",
_("Creation radius"),
@@ -129,7 +146,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition("ZoneRadius",
_("Creation radius"),
@@ -139,19 +157,23 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction(
"ParticleLifeTimeMin",
_("Minimum lifetime"),
_("Modify particles minimum lifetime.Particles have to be recreated "
_("Modify particles minimum lifetime. Particles have to be recreated "
"in order to take changes in account."),
_("the minimum lifetime of particles"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Duration (in seconds)")));
obj.AddCondition(
"ParticleLifeTimeMin",
@@ -162,7 +184,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Duration to compare to (in seconds)")));
obj.AddAction(
"ParticleLifeTimeMax",
@@ -174,7 +199,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Duration (in seconds)")));
obj.AddCondition(
"ParticleLifeTimeMax",
@@ -185,7 +213,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Duration to compare to (in seconds)")));
obj.AddAction("ParticleGravityX",
_("Gravity value on X axis"),
@@ -195,7 +226,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition(
"ParticleGravityX",
@@ -206,7 +238,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction("ParticleGravityY",
_("Gravity value on Y axis"),
@@ -216,7 +249,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition(
"ParticleGravityY",
@@ -227,7 +261,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction("ParticleGravityAngle",
_("Gravity angle"),
@@ -237,7 +272,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle (in degrees)")));
obj.AddCondition("ParticleGravityAngle",
_("Gravity angle"),
@@ -247,7 +285,10 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle to compare to (in degrees)")));
obj.AddAction("ParticleGravityLength",
_("Gravity"),
@@ -257,7 +298,8 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition("ParticleGravityLength",
_("Gravity"),
@@ -267,11 +309,13 @@ void ExtensionSubDeclaration1(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction("StartEmission",
_("Start emission"),
_("Refill tank (if not infinite) and start emission of the particles."),
_("Refill tank (if not infinite) and start emission of the "
"particles."),
_("Start emission of _PARAM0_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",

View File

@@ -5,11 +5,10 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#include "Extension.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "Extension.h"
#include "ParticleEmitterObject.h"
/**
@@ -36,137 +35,161 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("color", _("End color"));
obj.AddAction(
"ParticleRed1",
_("Start color red component"),
_("Modify the start color red component."),
_("the start color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddAction("ParticleRed1",
_("Start color red component"),
_("Modify the start color red component."),
_("the start color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleRed1",
_("Start color red component"),
_("Compare the start color red component."),
_("the start color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleRed1",
_("Start color red component"),
_("Compare the start color red component."),
_("the start color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddAction(
"ParticleRed2",
_("End color red component"),
_("Modify the end color red component."),
_("the end color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddAction("ParticleRed2",
_("End color red component"),
_("Modify the end color red component."),
_("the end color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleRed2",
_("End color red component"),
_("Compare the end color red component."),
_("the end color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleRed2",
_("End color red component"),
_("Compare the end color red component."),
_("the end color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddAction(
"ParticleBlue1",
_("Start color blue component"),
_("Modify the start color blue component."),
_("the start color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddAction("ParticleBlue1",
_("Start color blue component"),
_("Modify the start color blue component."),
_("the start color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleBlue1",
_("Start color blue component"),
_("Compare the start color blue component."),
_("the start color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleBlue1",
_("Start color blue component"),
_("Compare the start color blue component."),
_("the start color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddAction(
"ParticleBlue2",
_("End color blue component"),
_("Modify the end color blue component."),
_("the end color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddAction("ParticleBlue2",
_("End color blue component"),
_("Modify the end color blue component."),
_("the end color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleBlue2",
_("End color blue component"),
_("Compare the end color blue component."),
_("the end color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleBlue2",
_("End color blue component"),
_("Compare the end color blue component."),
_("the end color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddAction(
"ParticleGreen1",
_("Start color green component"),
_("Modify the start color green component."),
_("the start color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddAction("ParticleGreen1",
_("Start color green component"),
_("Modify the start color green component."),
_("the start color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleGreen1",
_("Start color green component"),
_("Compare the start color green component."),
_("the start color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleGreen1",
_("Start color green component"),
_("Compare the start color green component."),
_("the start color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddAction(
"ParticleGreen2",
_("End color green component"),
_("Modify the end color green component."),
_("the end color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddAction("ParticleGreen2",
_("End color green component"),
_("Modify the end color green component."),
_("the end color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleGreen2",
_("End color green component"),
_("Compare the end color green component."),
_("the end color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleGreen2",
_("End color green component"),
_("Compare the end color green component."),
_("the end color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddAction("ParticleSize1",
_("Start size"),
@@ -176,7 +199,8 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition("ParticleSize1",
_("Start size"),
@@ -186,7 +210,8 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction("ParticleSize2",
_("End size"),
@@ -196,7 +221,8 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition("ParticleSize2",
_("End size"),
@@ -206,7 +232,8 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction("ParticleAlpha1",
_("Start opacity"),
@@ -216,18 +243,23 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleAlpha1",
_("Start opacity"),
_("Compare the start opacity of particles."),
_("the start opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleAlpha1",
_("Start opacity"),
_("Compare the start opacity of particles."),
_("the start opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddAction("ParticleAlpha2",
_("End opacity"),
@@ -237,18 +269,23 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value (0-255)")));
obj.AddCondition(
"ParticleAlpha2",
_("End opacity"),
_("Compare the end opacity of particles."),
_("the end opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("ParticleAlpha2",
_("End opacity"),
_("Compare the end opacity of particles."),
_("the end opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Value to compare to (0-255)")));
obj.AddCondition("NoMoreParticles",
_("No more particles"),
@@ -261,58 +298,63 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.AddParameter("object", _("Object"), "ParticleEmitter");
obj.AddExpressionAndConditionAndAction(
"number",
"ParticleRotationMinSpeed",
_("Particle rotation min speed"),
_("the minimum rotation speed of the particles"),
_("the particles minimum rotation speed"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
"number",
"ParticleRotationMinSpeed",
_("Particle rotation min speed"),
_("the minimum rotation speed of the particles"),
_("the particles minimum rotation speed"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardParameters("number")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angular speed (in degrees per second)")))
.MarkAsAdvanced()
.SetFunctionName("setParticleRotationMinSpeed")
.SetGetter("getParticleRotationMinSpeed");
obj.AddExpressionAndConditionAndAction(
"number",
"ParticleRotationMaxSpeed",
_("Particle rotation max speed"),
_("the maximum rotation speed of the particles"),
_("the particles maximum rotation speed"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
"number",
"ParticleRotationMaxSpeed",
_("Particle rotation max speed"),
_("the maximum rotation speed of the particles"),
_("the particles maximum rotation speed"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardParameters("number")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angular speed (in degrees per second)")))
.MarkAsAdvanced()
.SetFunctionName("setParticleRotationMaxSpeed")
.SetGetter("getParticleRotationMaxSpeed");
obj.AddExpressionAndConditionAndAction(
"number",
"MaxParticlesCount",
_("Number of displayed particles"),
_("the maximum number of displayed particles"),
_("the maximum number of displayed particles"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
"number",
"MaxParticlesCount",
_("Number of displayed particles"),
_("the maximum number of displayed particles"),
_("the maximum number of displayed particles"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardParameters("number")
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("setMaxParticlesCount")
.SetGetter("getMaxParticlesCount");
obj.AddExpressionAndConditionAndAction(
"boolean",
"AdditiveRendering",
_("Activate particles additive rendering"),
_("the particles additive rendering is activated"),
_("displaying particles with additive rendering activated"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
"boolean",
"AdditiveRendering",
_("Activate particles additive rendering"),
_("the particles additive rendering is activated"),
_("displaying particles with additive rendering activated"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardParameters("boolean")
.UseStandardParameters("boolean", gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetFunctionName("setAdditiveRendering")
.SetGetter("getAdditiveRendering");
}

View File

@@ -34,19 +34,20 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition(
"RendererParam1",
_("Rendering first parameter"),
_("Test the first parameter of rendering (Size/Length)."),
_("the 1st rendering parameter"),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("RendererParam1",
_("Rendering first parameter"),
_("Test the first parameter of rendering (Size/Length)."),
_("the 1st rendering parameter"),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction("RendererParam2",
_("Rendering second parameter"),
@@ -58,18 +59,19 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddCondition(
"RendererParam2",
_("Rendering second parameter"),
_("Test the second parameter of rendering (Size/Length)."),
_("the 2nd rendering parameter"),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("RendererParam2",
_("Rendering second parameter"),
_("Test the second parameter of rendering (Size/Length)."),
_("the 2nd rendering parameter"),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions());
obj.AddAction("Tank",
_("Capacity"),
@@ -79,8 +81,9 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.SetHidden() // DEPRECATED - Use SetTank instead
.UseStandardOperatorParameters("number");
.SetHidden() // DEPRECATED - Use SetTank instead
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddAction("SetTank",
_("Capacity"),
@@ -90,7 +93,9 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(_("Capacity")));
obj.AddCondition("Tank",
_("Capacity"),
@@ -100,7 +105,10 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Capacity to compare to")));
obj.AddAction("Flow",
_("Flow"),
@@ -110,8 +118,9 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.SetHidden() // DEPRECATED - Use SetFlow instead
.UseStandardOperatorParameters("number");
.SetHidden() // DEPRECATED - Use SetFlow instead
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions());
obj.AddAction("SetFlow",
_("Flow"),
@@ -121,7 +130,10 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Flow (in particles per second)")));
obj.AddCondition("Flow",
_("Flow"),
@@ -131,7 +143,10 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("number");
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Flow to compare to (in particles per second)")));
obj.AddAction("Texture",
_("Particle image (using an expression)"),
@@ -154,16 +169,16 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("imageResource", _("Image file (or image resource name)"));
obj.AddCondition(
"Texture",
_("Image"),
_("Test the name of the image displayed by particles."),
_("the image displayed by particles"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
obj.AddCondition("Texture",
_("Image"),
_("Test the name of the image displayed by particles."),
_("the image displayed by particles"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.UseStandardRelationalOperatorParameters("string");
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions());
obj.AddStrExpression("Texture",
_("Particles image"),
@@ -177,7 +192,7 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
_("Particles number"),
_("Particles"),
"CppPlatform/Extensions/particleSystemicon16.png")
.SetHidden() // DEPRECATED - Use CurrentParticleCount instead
.SetHidden() // DEPRECATED - Use CurrentParticleCount instead
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("CurrentParticleCount",

View File

@@ -5,16 +5,15 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#include "GDCore/Tools/Localization.h"
#include "ParticleEmitterObject.h"
#include "GDCore/CommonTools.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/Project/InitialInstance.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "ParticleEmitterObject.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
@@ -178,53 +177,49 @@ void ParticleEmitterObject::ExposeResources(
SetParticleTexture(texture);
}
void ParticleEmitterBase::SetTank(float newValue) {
tank = newValue;
}
void ParticleEmitterBase::SetFlow(float newValue) {
flow = newValue;
}
void ParticleEmitterBase::SetEmitterForceMin(float newValue) {
void ParticleEmitterBase::SetTank(double newValue) { tank = newValue; }
void ParticleEmitterBase::SetFlow(double newValue) { flow = newValue; }
void ParticleEmitterBase::SetEmitterForceMin(double newValue) {
emitterForceMin = newValue;
}
void ParticleEmitterBase::SetEmitterForceMax(float newValue) {
void ParticleEmitterBase::SetEmitterForceMax(double newValue) {
emitterForceMax = newValue;
}
void ParticleEmitterBase::SetParticleGravityX(float newValue) {
void ParticleEmitterBase::SetParticleGravityX(double newValue) {
particleGravityX = newValue;
}
void ParticleEmitterBase::SetParticleGravityY(float newValue) {
void ParticleEmitterBase::SetParticleGravityY(double newValue) {
particleGravityY = newValue;
}
void ParticleEmitterBase::SetEmitterAngleA(float newValue) {
void ParticleEmitterBase::SetEmitterAngleA(double newValue) {
emitterAngleA = newValue;
}
void ParticleEmitterBase::SetEmitterAngleB(float newValue) {
void ParticleEmitterBase::SetEmitterAngleB(double newValue) {
emitterAngleB = newValue;
}
void ParticleEmitterBase::SetZoneRadius(float newValue) {
void ParticleEmitterBase::SetZoneRadius(double newValue) {
zoneRadius = newValue;
}
void ParticleEmitterBase::SetParticleGravityAngle(float newAngleInDegree) {
float length = sqrt(GetParticleGravityY() * GetParticleGravityY() +
GetParticleGravityX() * GetParticleGravityX());
void ParticleEmitterBase::SetParticleGravityAngle(double newAngleInDegree) {
double length = sqrt(GetParticleGravityY() * GetParticleGravityY() +
GetParticleGravityX() * GetParticleGravityX());
SetParticleGravityX(cos(newAngleInDegree / 180.0f * 3.14159f) * length);
SetParticleGravityY(sin(newAngleInDegree / 180.0f * 3.14159f) * length);
}
void ParticleEmitterBase::SetParticleGravityLength(float length) {
float angle = atan2(GetParticleGravityY(), GetParticleGravityX());
void ParticleEmitterBase::SetParticleGravityLength(double length) {
double angle = atan2(GetParticleGravityY(), GetParticleGravityX());
SetParticleGravityX(cos(angle) * length);
SetParticleGravityY(sin(angle) * length);
}
float ParticleEmitterBase::GetParticleGravityAngle() const {
double ParticleEmitterBase::GetParticleGravityAngle() const {
return atan2(GetParticleGravityY(), GetParticleGravityX()) * 180.0f /
3.14159f;
}
float ParticleEmitterBase::GetParticleGravityLength() const {
double ParticleEmitterBase::GetParticleGravityLength() const {
return sqrt(GetParticleGravityY() * GetParticleGravityY() +
GetParticleGravityX() * GetParticleGravityX());
}

View File

@@ -12,7 +12,7 @@ This project is released under the MIT License.
namespace gd {
class InitialInstance;
class Project;
}
} // namespace gd
/**
* \brief Base class containing the parameters of an emitter as well as the
@@ -22,95 +22,69 @@ class GD_EXTENSION_API ParticleEmitterBase {
public:
ParticleEmitterBase();
virtual ~ParticleEmitterBase();
ParticleEmitterBase(const ParticleEmitterBase& other) {
Init(other);
};
ParticleEmitterBase(const ParticleEmitterBase& other) { Init(other); };
ParticleEmitterBase& operator=(const ParticleEmitterBase& other) {
if (&other != this) Init(other);
return *this;
}
void SetParticleTexture(const gd::String & imageName) {
void SetParticleTexture(const gd::String& imageName) {
textureParticleName = imageName;
};
const gd::String & GetParticleTexture() const { return textureParticleName; };
const gd::String& GetParticleTexture() const { return textureParticleName; };
void SetRendererParam1(float newValue) { rendererParam1 = newValue; };
void SetRendererParam2(float newValue) { rendererParam2 = newValue; };
void SetTank(float newValue);
void SetFlow(float newValue);
void SetEmitterForceMin(float newValue);
void SetEmitterForceMax(float newValue);
void SetEmitterAngleA(float newValue);
void SetEmitterAngleB(float newValue);
void SetConeSprayAngle(float newValue) { SetEmitterAngleB(newValue); };
void SetZoneRadius(float newValue);
void SetParticleGravityX(float newValue);
void SetParticleGravityY(float newValue);
void SetParticleGravityAngle(float newAngleInDegree);
void SetParticleGravityLength(float newLength);
void SetRendererParam1(double newValue) { rendererParam1 = newValue; };
void SetRendererParam2(double newValue) { rendererParam2 = newValue; };
void SetTank(double newValue);
void SetFlow(double newValue);
void SetEmitterForceMin(double newValue);
void SetEmitterForceMax(double newValue);
void SetEmitterAngleA(double newValue);
void SetEmitterAngleB(double newValue);
void SetConeSprayAngle(double newValue) { SetEmitterAngleB(newValue); };
void SetZoneRadius(double newValue);
void SetParticleGravityX(double newValue);
void SetParticleGravityY(double newValue);
void SetParticleGravityAngle(double newAngleInDegree);
void SetParticleGravityLength(double newLength);
void SetParticleColor1(const gd::String& color);
void SetParticleColor2(const gd::String& color);
void SetParticleRed1(float newValue) {
particleRed1 = newValue;
};
void SetParticleRed2(float newValue) {
particleRed2 = newValue;
};
void SetParticleGreen1(float newValue) {
particleGreen1 = newValue;
};
void SetParticleGreen2(float newValue) {
particleGreen2 = newValue;
};
void SetParticleBlue1(float newValue) {
particleBlue1 = newValue;
};
void SetParticleBlue2(float newValue) {
particleBlue2 = newValue;
};
void SetParticleAlpha1(float newValue) {
particleAlpha1 = newValue;
};
void SetParticleAlpha2(float newValue) {
particleAlpha2 = newValue;
};
void SetParticleSize1(float newValue) {
particleSize1 = newValue;
};
void SetParticleSize2(float newValue) {
particleSize2 = newValue;
};
void SetParticleAngle1(float newValue) {
particleAngle1 = newValue;
};
void SetParticleAngle2(float newValue) {
particleAngle2 = newValue;
};
void SetParticleAlphaRandomness1(float newValue) {
void SetParticleRed1(double newValue) { particleRed1 = newValue; };
void SetParticleRed2(double newValue) { particleRed2 = newValue; };
void SetParticleGreen1(double newValue) { particleGreen1 = newValue; };
void SetParticleGreen2(double newValue) { particleGreen2 = newValue; };
void SetParticleBlue1(double newValue) { particleBlue1 = newValue; };
void SetParticleBlue2(double newValue) { particleBlue2 = newValue; };
void SetParticleAlpha1(double newValue) { particleAlpha1 = newValue; };
void SetParticleAlpha2(double newValue) { particleAlpha2 = newValue; };
void SetParticleSize1(double newValue) { particleSize1 = newValue; };
void SetParticleSize2(double newValue) { particleSize2 = newValue; };
void SetParticleAngle1(double newValue) { particleAngle1 = newValue; };
void SetParticleAngle2(double newValue) { particleAngle2 = newValue; };
void SetParticleAlphaRandomness1(double newValue) {
particleAlphaRandomness1 = newValue;
};
void SetParticleAlphaRandomness2(float newValue) {
void SetParticleAlphaRandomness2(double newValue) {
particleAlphaRandomness2 = newValue;
};
void SetParticleSizeRandomness1(float newValue) {
void SetParticleSizeRandomness1(double newValue) {
particleSizeRandomness1 = newValue;
};
void SetParticleSizeRandomness2(float newValue) {
void SetParticleSizeRandomness2(double newValue) {
particleSizeRandomness2 = newValue;
};
void SetParticleAngleRandomness1(float newValue) {
void SetParticleAngleRandomness1(double newValue) {
particleAngleRandomness1 = newValue;
};
void SetParticleAngleRandomness2(float newValue) {
void SetParticleAngleRandomness2(double newValue) {
particleAngleRandomness2 = newValue;
};
void SetParticleLifeTimeMin(float newValue) {
void SetParticleLifeTimeMin(double newValue) {
particleLifeTimeMin = newValue;
};
void SetParticleLifeTimeMax(float newValue) {
void SetParticleLifeTimeMax(double newValue) {
particleLifeTimeMax = newValue;
};
void SetMaxParticleNb(std::size_t newValue) { maxParticleNb = newValue; };
@@ -118,50 +92,49 @@ class GD_EXTENSION_API ParticleEmitterBase {
destroyWhenNoParticles = enable;
};
float GetRendererParam1() const { return rendererParam1; };
float GetRendererParam2() const { return rendererParam2; };
float GetTank() const { return tank; };
float GetFlow() const { return flow; };
float GetEmitterForceMin() const { return emitterForceMin; };
float GetEmitterForceMax() const { return emitterForceMax; };
float GetEmitterAngleA() const { return emitterAngleA; };
float GetEmitterAngleB() const { return emitterAngleB; };
float GetConeSprayAngle() const { return GetEmitterAngleB(); };
float GetZoneRadius() const { return zoneRadius; };
float GetParticleGravityX() const { return particleGravityX; };
float GetParticleGravityY() const { return particleGravityY; };
float GetParticleGravityAngle() const;
float GetParticleGravityLength() const;
float GetParticleLifeTimeMin() const { return particleLifeTimeMin; };
float GetParticleLifeTimeMax() const { return particleLifeTimeMax; };
double GetRendererParam1() const { return rendererParam1; };
double GetRendererParam2() const { return rendererParam2; };
double GetTank() const { return tank; };
double GetFlow() const { return flow; };
double GetEmitterForceMin() const { return emitterForceMin; };
double GetEmitterForceMax() const { return emitterForceMax; };
double GetEmitterAngleA() const { return emitterAngleA; };
double GetEmitterAngleB() const { return emitterAngleB; };
double GetConeSprayAngle() const { return GetEmitterAngleB(); };
double GetZoneRadius() const { return zoneRadius; };
double GetParticleGravityX() const { return particleGravityX; };
double GetParticleGravityY() const { return particleGravityY; };
double GetParticleGravityAngle() const;
double GetParticleGravityLength() const;
double GetParticleLifeTimeMin() const { return particleLifeTimeMin; };
double GetParticleLifeTimeMax() const { return particleLifeTimeMax; };
std::size_t GetMaxParticleNb() const { return maxParticleNb; };
bool GetDestroyWhenNoParticles() const { return destroyWhenNoParticles; };
float GetParticleRed1() const { return particleRed1; };
float GetParticleRed2() const { return particleRed2; };
float GetParticleGreen1() const { return particleGreen1; };
float GetParticleGreen2() const { return particleGreen2; };
float GetParticleBlue1() const { return particleBlue1; };
float GetParticleBlue2() const { return particleBlue2; };
float GetParticleAlpha1() const { return particleAlpha1; };
float GetParticleAlpha2() const { return particleAlpha2; };
float GetParticleSize1() const { return particleSize1; };
float GetParticleSize2() const { return particleSize2; };
float GetParticleAngle1() const { return particleAngle1; };
float GetParticleAngle2() const { return particleAngle2; };
float GetParticleAlphaRandomness1() const {
double GetParticleRed1() const { return particleRed1; };
double GetParticleRed2() const { return particleRed2; };
double GetParticleGreen1() const { return particleGreen1; };
double GetParticleGreen2() const { return particleGreen2; };
double GetParticleBlue1() const { return particleBlue1; };
double GetParticleBlue2() const { return particleBlue2; };
double GetParticleAlpha1() const { return particleAlpha1; };
double GetParticleAlpha2() const { return particleAlpha2; };
double GetParticleSize1() const { return particleSize1; };
double GetParticleSize2() const { return particleSize2; };
double GetParticleAngle1() const { return particleAngle1; };
double GetParticleAngle2() const { return particleAngle2; };
double GetParticleAlphaRandomness1() const {
return particleAlphaRandomness1;
};
float GetParticleAlphaRandomness2() const {
double GetParticleAlphaRandomness2() const {
return particleAlphaRandomness2;
};
float GetParticleSizeRandomness1() const { return particleSizeRandomness1; };
float GetParticleSizeRandomness2() const { return particleSizeRandomness2; };
float GetParticleAngleRandomness1() const {
double GetParticleSizeRandomness1() const { return particleSizeRandomness1; };
double GetParticleSizeRandomness2() const { return particleSizeRandomness2; };
double GetParticleAngleRandomness1() const {
return particleAngleRandomness1;
};
float GetParticleAngleRandomness2() const {
double GetParticleAngleRandomness2() const {
return particleAngleRandomness2;
};
@@ -184,23 +157,23 @@ class GD_EXTENSION_API ParticleEmitterBase {
gd::String textureParticleName;
RendererType rendererType;
float rendererParam1;
float rendererParam2;
double rendererParam1;
double rendererParam2;
bool additive;
float tank;
float flow;
float emitterForceMin;
float emitterForceMax;
float emitterAngleA;
float emitterAngleB;
float zoneRadius;
float particleGravityX, particleGravityY;
float particleLifeTimeMin, particleLifeTimeMax;
float particleRed1, particleRed2, particleGreen1, particleGreen2,
double tank;
double flow;
double emitterForceMin;
double emitterForceMax;
double emitterAngleA;
double emitterAngleB;
double zoneRadius;
double particleGravityX, particleGravityY;
double particleLifeTimeMin, particleLifeTimeMax;
double particleRed1, particleRed2, particleGreen1, particleGreen2,
particleBlue1, particleBlue2, particleAlpha1, particleAlpha2;
float particleSize1, particleSize2, particleAngle1, particleAngle2;
float particleAlphaRandomness1, particleAlphaRandomness2;
float particleSizeRandomness1, particleSizeRandomness2,
double particleSize1, particleSize2, particleAngle1, particleAngle2;
double particleAlphaRandomness1, particleAlphaRandomness2;
double particleSizeRandomness1, particleSizeRandomness2,
particleAngleRandomness1, particleAngleRandomness2;
std::size_t maxParticleNb;
bool destroyWhenNoParticles; ///< If set to true, the object will removed

View File

@@ -5,10 +5,10 @@ Copyright (c) 2010-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Tools/Localization.h"
#include "PathfindingBehavior.h"
#include "PathfindingObstacleBehavior.h"
@@ -89,7 +89,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetCellWidth")
.SetGetter("GetCellWidth");
@@ -103,7 +104,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("GetCellWidth");
aut.AddAction("CellHeight",
@@ -116,7 +118,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetCellHeight")
.SetGetter("GetCellHeight");
@@ -130,7 +133,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("GetCellHeight");
aut.AddAction("Acceleration",
@@ -143,7 +147,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetAcceleration")
.SetGetter("GetAcceleration");
@@ -157,7 +162,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("GetAcceleration");
aut.AddAction("MaxSpeed",
@@ -170,7 +176,10 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max speed (in pixels per second)")))
.SetFunctionName("SetMaxSpeed")
.SetGetter("GetMaxSpeed");
@@ -184,7 +193,10 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max speed to compare to (in pixels per second)")))
.SetFunctionName("GetMaxSpeed");
aut.AddAction("Speed",
@@ -197,7 +209,10 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed (in pixels per second)")))
.SetFunctionName("SetSpeed")
.SetGetter("GetSpeed");
@@ -211,17 +226,21 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed to compare to (in pixels per second)")))
.SetFunctionName("GetSpeed");
aut.AddScopedCondition("MovementAngleIsAround",
_("Angle of movement on its path"),
_("Compare the angle of movement of an object on its path."),
_("Angle of movement of _PARAM0_ is _PARAM2_ (tolerance"
": _PARAM3_ degrees)"),
_("Movement on the path"),
"CppPlatform/Extensions/AStaricon24.png",
"CppPlatform/Extensions/AStaricon16.png")
aut.AddScopedCondition(
"MovementAngleIsAround",
_("Angle of movement on its path"),
_("Compare the angle of movement of an object on its path."),
_("Angle of movement of _PARAM0_ is _PARAM2_ (tolerance"
": _PARAM3_ degrees)"),
_("Movement on the path"),
"CppPlatform/Extensions/AStaricon24.png",
"CppPlatform/Extensions/AStaricon16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
@@ -238,7 +257,10 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max angular speed (in degrees per second)")))
.SetFunctionName("SetAngularMaxSpeed")
.SetGetter("GetAngularMaxSpeed");
@@ -253,7 +275,10 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max angular speed to compare to (in degrees per second)")))
.SetFunctionName("GetAngularMaxSpeed");
aut.AddAction(
@@ -267,7 +292,10 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle (in degrees)")))
.SetFunctionName("SetAngleOffset")
.SetGetter("GetAngleOffset");
@@ -281,7 +309,10 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Angle to compare to (in degrees)")))
.SetFunctionName("GetAngleOffset");
aut.AddAction(
@@ -296,7 +327,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetExtraBorder")
.SetGetter("GetExtraBorder");
@@ -311,7 +343,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("GetExtraBorder");
aut.AddAction(
@@ -548,7 +581,7 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/AStaricon24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardParameters("number");
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions());
aut.AddExpressionAndConditionAndAction("number",
"GridOffsetY",
@@ -559,7 +592,7 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/AStaricon24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingBehavior")
.UseStandardParameters("number");
.UseStandardParameters("number", gd::ParameterOptions::MakeNewOptions());
}
{
@@ -584,7 +617,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingObstacleBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetCost")
.SetGetter("GetCost");
@@ -598,7 +632,8 @@ void DeclarePathfindingBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PathfindingObstacleBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("GetCost");
aut.AddAction("SetImpassable",

View File

@@ -27,7 +27,10 @@ class PathfindingBehaviorJsExtension : public gd::PlatformExtension {
"Extensions/PathfindingBehavior/pathfindingruntimebehavior.js")
.AddIncludeFile(
"Extensions/PathfindingBehavior/"
"pathfindingobstacleruntimebehavior.js");
"pathfindingobstacleruntimebehavior.js")
.AddIncludeFile(
"Extensions/PathfindingBehavior/"
"PathTools.js");
{
std::map<gd::String, gd::InstructionMetadata>& autActions =

View File

@@ -0,0 +1,163 @@
namespace gdjs {
export namespace pathfinding {
/**
* Simplify a path according to an allowed gap.
*
* The simplified path vertices are the same instances as the one in
* the source. They must be cloned to make them truly independent from each
* other.
*
* @param sourceVertices The path to simplify.
* @param maxGap The maximum distance the edge of the contour may deviate
* from the source geometry.
* @param simplifiedVertices The simplified path.
* @param workingVertices It avoids allocations.
*/
export const simplifyPath = (
sourceVertices: FloatPoint[],
maxGap: float,
simplifiedVertices: FloatPoint[] = [],
workingVertices: FloatPoint[] = []
): FloatPoint[] => {
if (sourceVertices.length <= 2) {
simplifiedVertices.length = 0;
simplifiedVertices.push.apply(simplifiedVertices, sourceVertices);
return simplifiedVertices;
}
const maxGapSq = maxGap * maxGap;
// We start with only one rope part.
// Stretch a rope between the start and the end of the path.
let previousStepVertices: FloatPoint[] = workingVertices;
previousStepVertices.length = 0;
previousStepVertices.push(sourceVertices[0]);
previousStepVertices.push(sourceVertices[sourceVertices.length - 1]);
do {
simplifiedVertices.length = 0;
simplifiedVertices.push(previousStepVertices[0]);
// For each part of the rope...
let sourceIndex = 0;
for (
let previousStepVerticesIndex = 0;
previousStepVerticesIndex + 1 < previousStepVertices.length;
previousStepVerticesIndex++
) {
const startVertex = previousStepVertices[previousStepVerticesIndex];
const endVertex = previousStepVertices[previousStepVerticesIndex + 1];
const startX = startVertex[0];
const startY = startVertex[1];
const endX = endVertex[0];
const endY = endVertex[1];
// Search the furthest vertex from the rope part.
let maxDeviationSq = maxGapSq;
let maxDeviationVertex: FloatPoint | null = null;
// The first and last vertices of the rope part are not checked.
for (
sourceIndex++;
sourceVertices[sourceIndex] !== endVertex;
sourceIndex++
) {
const sourceVertex = sourceVertices[sourceIndex];
const deviationSq = gdjs.pathfinding.getPointSegmentDistanceSq(
sourceVertex[0],
sourceVertex[1],
startX,
startY,
endX,
endY
);
if (deviationSq > maxDeviationSq) {
maxDeviationSq = deviationSq;
maxDeviationVertex = sourceVertex;
}
}
// Add the furthest vertex to the rope.
// The current rope part is split in 2 for the next step.
if (maxDeviationVertex) {
simplifiedVertices.push(maxDeviationVertex);
}
simplifiedVertices.push(endVertex);
}
const swapVertices = previousStepVertices;
previousStepVertices = simplifiedVertices;
simplifiedVertices = swapVertices;
} while (
// Stop when no new vertex were added.
// It means that the maxGap constraint is fulfilled.
// Otherwise, iterate over the full path once more.
simplifiedVertices.length !== previousStepVertices.length
);
return simplifiedVertices;
};
/**
* Returns the distance squared from the point to the line segment.
*
* Behavior is undefined if the the closest distance is outside the
* line segment.
*
* @param px The X position of point (px, py).
* @param py The Y position of point (px, py)
* @param ax The X position of the line segment's vertex A.
* @param ay The Y position of the line segment's vertex A.
* @param bx The X position of the line segment's vertex B.
* @param by The Y position of the line segment's vertex B.
* @return The distance squared from the point (px, py) to line segment AB.
*/
export const getPointSegmentDistanceSq = (
px: float,
py: float,
ax: float,
ay: float,
bx: float,
by: float
): float => {
// This implementation is strongly inspired from CritterAI class "Geometry".
//
// Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
//
// The goal of the algorithm is to find the point on line segment AB
// that is closest to P and then calculate the distance between P
// and that point.
const deltaABx = bx - ax;
const deltaABy = by - ay;
const deltaAPx = px - ax;
const deltaAPy = py - ay;
const segmentABLengthSq = deltaABx * deltaABx + deltaABy * deltaABy;
if (segmentABLengthSq === 0) {
// AB is not a line segment. So just return
// distanceSq from P to A
return deltaAPx * deltaAPx + deltaAPy * deltaAPy;
}
const u = (deltaAPx * deltaABx + deltaAPy * deltaABy) / segmentABLengthSq;
if (u < 0) {
// Closest point on line AB is outside outside segment AB and
// closer to A. So return distanceSq from P to A.
return deltaAPx * deltaAPx + deltaAPy * deltaAPy;
} else if (u > 1) {
// Closest point on line AB is outside segment AB and closer to B.
// So return distanceSq from P to B.
return (px - bx) * (px - bx) + (py - by) * (py - by);
}
// Closest point on lineAB is inside segment AB. So find the exact
// point on AB and calculate the distanceSq from it to P.
// The calculation in parenthesis is the location of the point on
// the line segment.
const deltaX = ax + u * deltaABx - px;
const deltaY = ay + u * deltaABy - py;
return deltaX * deltaX + deltaY * deltaY;
};
}
}

View File

@@ -24,39 +24,92 @@ void PathfindingBehavior::InitializeContent(
behaviorContent.SetAttribute("gridOffsetX", 0);
behaviorContent.SetAttribute("gridOffsetY", 0);
behaviorContent.SetAttribute("extraBorder", 0);
behaviorContent.SetAttribute("smoothingMaxCellGap", 1);
}
#if defined(GD_IDE_ONLY)
std::map<gd::String, gd::PropertyDescriptor> PathfindingBehavior::GetProperties(
const gd::SerializerElement& behaviorContent) const {
const gd::SerializerElement &behaviorContent) const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[_("Allows diagonals")]
properties["AllowDiagonals"]
.SetLabel(_("Allows diagonals"))
.SetValue(behaviorContent.GetBoolAttribute("allowDiagonals") ? "true"
: "false")
.SetGroup(_("Path smoothing"))
.SetType("Boolean");
properties[_("Acceleration")].SetValue(
properties["Acceleration"]
.SetLabel(_("Acceleration"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelAcceleration()).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("acceleration")));
properties[_("Max. speed")].SetValue(
properties["MaxSpeed"]
.SetLabel(_("Max. speed"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelSpeed()).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("maxSpeed")));
properties[_("Rotate speed")].SetGroup(_("Rotation")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("angularMaxSpeed")));
properties[_("Rotate object")].SetGroup(_("Rotation"))
properties["AngularMaxSpeed"]
.SetLabel(_("Rotation speed"))
.SetGroup(_("Rotation"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetAngularSpeed())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("angularMaxSpeed")));
properties["RotateObject"]
.SetLabel(_("Rotate object"))
.SetGroup(_("Rotation"))
.SetValue(behaviorContent.GetBoolAttribute("rotateObject") ? "true"
: "false")
.SetType("Boolean");
properties[_("Angle offset")].SetGroup(_("Rotation")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("angleOffset")));
properties[_("Virtual cell width")].SetGroup(_("Virtual Grid")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("cellWidth", 0)));
properties[_("Virtual cell height")].SetGroup(_("Virtual Grid")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("cellHeight", 0)));
properties[_("Virtual grid X offset")].SetGroup(_("Virtual Grid")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("gridOffsetX", 0)));
properties[_("Virtual grid Y offset")].SetGroup(_("Virtual Grid")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("gridOffsetY", 0)));
properties[_("Extra border size")].SetGroup(_("Collision")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("extraBorder")));
properties["AngleOffset"]
.SetLabel(_("Angle offset"))
.SetGroup(_("Rotation"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetDegreeAngle())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("angleOffset")));
properties["CellWidth"]
.SetLabel(_("Virtual cell width"))
.SetGroup(_("Virtual Grid"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("cellWidth", 0)));
properties["CellHeight"]
.SetLabel(_("Virtual cell height"))
.SetGroup(_("Virtual Grid"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("cellHeight", 0)));
properties["GridOffsetX"]
.SetLabel(_("Virtual grid X offset"))
.SetGroup(_("Virtual Grid"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("gridOffsetX", 0)));
properties["GridOffsetY"]
.SetLabel(_("Virtual grid Y offset"))
.SetGroup(_("Virtual Grid"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("gridOffsetY", 0)));
properties["ExtraBorder"]
.SetDescription(_("Extra border size"))
.SetGroup(_("Collision"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("extraBorder")));
properties["SmoothingMaxCellGap"]
.SetLabel(_("Smoothing max cell gap"))
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("smoothingMaxCellGap")))
.SetGroup(_("Path smoothing"))
.SetDescription(_("It's recommended to leave a max gap of 1 cell. "
"Setting it to 0 disable the smoothing."));
return properties;
}
@@ -64,37 +117,39 @@ std::map<gd::String, gd::PropertyDescriptor> PathfindingBehavior::GetProperties(
bool PathfindingBehavior::UpdateProperty(gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value) {
if (name == _("Allows diagonals")) {
if (name == "AllowDiagonals") {
behaviorContent.SetAttribute("allowDiagonals", (value != "0"));
return true;
}
if (name == _("Rotate object")) {
if (name == "RotateObject") {
behaviorContent.SetAttribute("rotateObject", (value != "0"));
return true;
}
if (name == _("Extra border size")) {
if (name == "ExtraBorder") {
behaviorContent.SetAttribute("extraBorder", value.To<float>());
return true;
}
if (value.To<float>() < 0) return false;
if (name == _("Acceleration"))
if (name == "Acceleration")
behaviorContent.SetAttribute("acceleration", value.To<float>());
else if (name == _("Max. speed"))
else if (name == "MaxSpeed")
behaviorContent.SetAttribute("maxSpeed", value.To<float>());
else if (name == _("Rotate speed"))
else if (name == "AngularMaxSpeed")
behaviorContent.SetAttribute("angularMaxSpeed", value.To<float>());
else if (name == _("Angle offset"))
else if (name == "AngleOffset")
behaviorContent.SetAttribute("angleOffset", value.To<float>());
else if (name == _("Virtual cell width"))
else if (name == "CellWidth")
behaviorContent.SetAttribute("cellWidth", value.To<float>());
else if (name == _("Virtual cell height"))
else if (name == "CellHeight")
behaviorContent.SetAttribute("cellHeight", value.To<float>());
else if (name == _("Virtual grid X offset"))
else if (name == "GridOffsetX")
behaviorContent.SetAttribute("gridOffsetX", value.To<float>());
else if (name == _("Virtual grid Y offset"))
else if (name == "GridOffsetY")
behaviorContent.SetAttribute("gridOffsetY", value.To<float>());
else if (name == "SmoothingMaxCellGap")
behaviorContent.SetAttribute("smoothingMaxCellGap", value.To<float>());
else
return false;

View File

@@ -20,12 +20,14 @@ std::map<gd::String, gd::PropertyDescriptor>
PathfindingObstacleBehavior::GetProperties(
const gd::SerializerElement& behaviorContent) const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[_("Impassable obstacle")]
properties["Impassable"]
.SetLabel(_("Impassable obstacle"))
.SetValue(behaviorContent.GetBoolAttribute("impassable") ? "true"
: "false")
.SetType("Boolean");
properties[_("Cost (if not impassable)")].SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("cost")));
properties["Cost"]
.SetLabel(_("Cost (if not impassable)"))
.SetValue(gd::String::From(behaviorContent.GetDoubleAttribute("cost")));
return properties;
}
@@ -34,14 +36,14 @@ bool PathfindingObstacleBehavior::UpdateProperty(
gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value) {
if (name == _("Impassable obstacle")) {
if (name == "Impassable") {
behaviorContent.SetAttribute("impassable", (value != "0"));
return true;
}
if (value.To<float>() < 0) return false;
if (name == _("Cost (if not impassable)"))
if (name == "Cost")
behaviorContent.SetAttribute("cost", value.To<float>());
else
return false;

View File

@@ -8,6 +8,7 @@ This project is released under the MIT License.
#ifndef PATHFINDINGOBSTACLEBEHAVIOR_H
#define PATHFINDINGOBSTACLEBEHAVIOR_H
#include <map>
#include "GDCore/Project/Behavior.h"
namespace gd {
class SerializerElement;
@@ -28,13 +29,11 @@ class GD_EXTENSION_API PathfindingObstacleBehavior : public gd::Behavior {
return new PathfindingObstacleBehavior(*this);
}
#if defined(GD_IDE_ONLY)
virtual std::map<gd::String, gd::PropertyDescriptor> GetProperties(
const gd::SerializerElement& behaviorContent) const override;
virtual bool UpdateProperty(gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value) override;
#endif
virtual void InitializeContent(
gd::SerializerElement& behaviorContent) override;

View File

@@ -10,6 +10,10 @@ namespace gdjs {
*/
export class PathfindingRuntimeBehavior extends gdjs.RuntimeBehavior {
_path: Array<FloatPoint> = [];
/** Used by the path simplification algorithm */
static _smoothingResultVertices: Array<FloatPoint> = [];
/** Used by the path simplification algorithm */
static _smoothingWorkingVertices: Array<FloatPoint> = [];
//Behavior configuration:
_allowDiagonals: boolean;
@@ -23,6 +27,7 @@ namespace gdjs {
_gridOffsetX: float;
_gridOffsetY: float;
_extraBorder: float;
_smoothingMaxCellGap: float;
//Attributes used for traveling on the path:
_pathFound: boolean = false;
@@ -60,6 +65,7 @@ namespace gdjs {
this._gridOffsetX = behaviorData.gridOffsetX || 0;
this._gridOffsetY = behaviorData.gridOffsetY || 0;
this._extraBorder = behaviorData.extraBorder;
this._smoothingMaxCellGap = behaviorData.smoothingMaxCellGap || 0;
this._manager = gdjs.PathfindingObstaclesManager.getManager(
instanceContainer
);
@@ -102,6 +108,12 @@ namespace gdjs {
if (oldBehaviorData.extraBorder !== newBehaviorData.extraBorder) {
this.setExtraBorder(newBehaviorData.extraBorder);
}
if (
oldBehaviorData.smoothingMaxCellGap !==
newBehaviorData.smoothingMaxCellGap
) {
this._smoothingMaxCellGap = newBehaviorData.smoothingMaxCellGap;
}
return true;
}
@@ -377,6 +389,20 @@ namespace gdjs {
this._path.reverse();
this._path[0][0] = owner.getX();
this._path[0][1] = owner.getY();
if (this._allowDiagonals && this._smoothingMaxCellGap > 0) {
gdjs.pathfinding.simplifyPath(
this._path,
this._smoothingMaxCellGap *
Math.min(this._cellWidth, this._cellHeight),
gdjs.PathfindingRuntimeBehavior._smoothingResultVertices,
gdjs.PathfindingRuntimeBehavior._smoothingWorkingVertices
);
let swapArray = this._path;
this._path = gdjs.PathfindingRuntimeBehavior._smoothingResultVertices;
gdjs.PathfindingRuntimeBehavior._smoothingResultVertices = swapArray;
}
this._enterSegment(0);
this._pathFound = true;
return;

View File

@@ -0,0 +1,239 @@
// @ts-check
describe('gdjs.PathfindingRuntimeBehavior', function () {
const epsilon = 1 / (2 << 16);
// tests cases where every collisionMethod has the same behavior.
let doCommonPathFindingTests = (collisionMethod) => {
const pathFindingName = 'auto1';
const createScene = (framePerSecond = 60) => {
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
// @ts-ignore - missing properties.
properties: { windowWidth: 800, windowHeight: 600 },
resources: { resources: [] },
});
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [
{
name: '',
visibility: true,
effects: [],
cameras: [],
ambientLightColorR: 0,
ambientLightColorG: 0,
ambientLightColorB: 0,
isLightingLayer: false,
followBaseLayerCamera: true,
},
],
variables: [],
r: 0,
v: 0,
b: 0,
mangledName: 'Scene1',
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
behaviorsSharedData: [],
objects: [],
instances: [],
});
setFramePerSecond(runtimeScene, framePerSecond);
return runtimeScene;
};
const setFramePerSecond = (runtimeScene, framePerSecond) => {
runtimeScene._timeManager.getElapsedTime = function () {
return 1000 / framePerSecond;
};
};
const addPlayer = (runtimeScene, allowDiagonals) => {
const player = new gdjs.RuntimeObject(runtimeScene, {
name: 'player',
type: '',
behaviors: [
{
type: 'PathfindingBehavior::PathfindingBehavior',
name: 'auto1',
// @ts-ignore - properties are not typed
allowDiagonals: allowDiagonals,
acceleration: 400,
maxSpeed: 200,
angularMaxSpeed: 180,
rotateObject: false,
angleOffset: 0,
cellWidth: 20,
cellHeight: 20,
extraBorder: 0,
collisionMethod: true,
},
],
effects: [],
});
player.getWidth = function () {
return 90;
};
player.getHeight = function () {
return 90;
};
runtimeScene.addObject(player);
return player;
};
const addObstacle = (runtimeScene) => {
const obstacle = new gdjs.RuntimeObject(runtimeScene, {
name: 'obstacle',
type: '',
behaviors: [
{
type: 'PathfindingBehavior::PathfindingObstacleBehavior',
// @ts-ignore - properties are not typed
impassable: true,
cost: 2,
},
],
effects: [],
});
obstacle.getWidth = function () {
return 100;
};
obstacle.getHeight = function () {
return 100;
};
runtimeScene.addObject(obstacle);
return obstacle;
};
const getPathLength = (player) => {
/** @type gdjs.PathfindingRuntimeBehavior */
const behavior = player.getBehavior(pathFindingName);
if (behavior.getNodeCount() < 2) {
return 0;
}
let pathLength = 0;
let previousNodeX = behavior.getNodeX(0);
let previousNodeY = behavior.getNodeY(0);
for (let index = 1; index < behavior.getNodeCount(); index++) {
const nodeX = behavior.getNodeX(index);
const nodeY = behavior.getNodeY(index);
pathLength += Math.hypot(nodeX - previousNodeX, nodeY - previousNodeY);
previousNodeX = nodeX;
previousNodeY = nodeY;
}
return pathLength;
};
describe(`(allowDiagonals: true)`, function () {
let runtimeScene;
let player;
beforeEach(function () {
runtimeScene = createScene();
const allowDiagonals = true;
player = addPlayer(runtimeScene, allowDiagonals);
});
[20, 30, 60, 120].forEach((framePerSecond) => {
describe(`(${framePerSecond} fps)`, function () {
it('can move on the path at the right speed', function () {
setFramePerSecond(runtimeScene, framePerSecond);
const obstacle = addObstacle(runtimeScene);
obstacle.setPosition(600, 300);
// To ensure obstacles are registered.
runtimeScene.renderAndStep(1000 / framePerSecond);
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(getPathLength(player)).to.be.above(720 - 480 + 50);
// Move on the path and stop before the last 1/10 of second.
for (let i = 0; i < (framePerSecond * 17) / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(false);
}
// The position is the same no matter the frame rate.
expect(player.getX()).to.be(720);
expect(player.getY()).to.be.within(
288.5786437626905 - epsilon,
288.5786437626905 + epsilon
);
// Let 1/10 of second pass,
// because the calculus interval is not the same for each case.
for (let i = 0; i < framePerSecond / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
}
// The destination is reached for every frame rate within 1/10 of second.
expect(player.getX()).to.be(720);
expect(player.getY()).to.be(300);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(true);
});
});
});
});
describe(`(allowDiagonals: false)`, function () {
let runtimeScene;
let player;
beforeEach(function () {
runtimeScene = createScene();
const allowDiagonals = false;
player = addPlayer(runtimeScene, allowDiagonals);
});
[20, 30, 60, 120].forEach((framePerSecond) => {
describe(`(${framePerSecond} fps)`, function () {
it('can move on the path at the right speed', function () {
setFramePerSecond(runtimeScene, framePerSecond);
const obstacle = addObstacle(runtimeScene);
obstacle.setPosition(600, 300);
// To ensure obstacles are registered.
runtimeScene.renderAndStep(1000 / framePerSecond);
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(getPathLength(player)).to.be.above(720 - 480 + 100);
// Move on the path and stop before the last 1/10 of second.
for (let i = 0; i < (framePerSecond * 20) / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(false);
}
expect(player.getX()).to.be(710);
expect(player.getY()).to.be.within(300 - epsilon, 300 + epsilon);
// Let 1/10 of second pass,
// because the calculus interval is not the same for each case.
for (let i = 0; i < (framePerSecond * 1) / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
}
// The destination is reached for every frame rate within 1/10 of second.
expect(player.getX()).to.be(720);
expect(player.getY()).to.be(300);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(true);
});
});
});
});
};
['Legacy'].forEach((collisionMethod) => {
describe(`(collisionMethod: ${collisionMethod}, `, function () {
doCommonPathFindingTests(collisionMethod);
});
});
});

View File

@@ -0,0 +1,115 @@
// @ts-check
describe('gdjs.pathfinding', function () {
it('can give back an empty path', function () {
expect(gdjs.pathfinding.simplifyPath([], 1)).to.eql([]);
});
it('can give back a path with only 1 vertex', function () {
expect(gdjs.pathfinding.simplifyPath([[2, 4]], 1)).to.eql([[2, 4]]);
});
it('can give back a path with only 2 vertex', function () {
expect(
gdjs.pathfinding.simplifyPath(
[
[2, 4],
[8, 1],
],
1
)
).to.eql([
[2, 4],
[8, 1],
]);
});
it('can give back a path with 3 vertex', function () {
expect(
gdjs.pathfinding.simplifyPath(
[
[2, 4],
[8, 1],
[16, 32],
],
1
)
).to.eql([
[2, 4],
[8, 1],
[16, 32],
]);
});
it('can simplify a line of vertices', function () {
expect(
gdjs.pathfinding.simplifyPath(
[
[2, 4],
[2, 5],
[2, 9],
[2, 9.5],
],
1
)
).to.eql([
[2, 4],
[2, 9.5],
]);
});
it('can simplify a line of vertices with some tangential noise', function () {
expect(
gdjs.pathfinding.simplifyPath(
[
[2, 4],
[2.5, 5],
[1.1, 9],
[2, 9.5],
],
1
)
).to.eql([
[2, 4],
[2, 9.5],
]);
});
it('can simplify an aliased oblique line', function () {
expect(
gdjs.pathfinding.simplifyPath(
[
[2, 4],
[3, 4],
[4, 3],
[5, 3],
[6, 3],
[7, 2],
[8, 2],
],
1
)
).to.eql([
[2, 4],
[8, 2],
]);
});
it('can preserve a bend', function () {
expect(
gdjs.pathfinding.simplifyPath(
[
[2, 4],
[2.5, 5],
[2, 9],
[3, 9.9],
[5, 9],
],
1
)
).to.eql([
[2, 4],
[2, 9],
[5, 9],
]);
});
});

View File

@@ -1,8 +1,11 @@
// @ts-check
describe('gdjs.PathfindingRuntimeBehavior', function () {
const epsilon = 1 / (2 << 16);
// tests cases where every collisionMethod has the same behavior.
let doCommonPathFindingTests = (collisionMethod, allowDiagonals) => {
let doCommonPathFindingTests = (
collisionMethod,
allowDiagonals,
smoothingMaxCellGap
) => {
const pathFindingName = 'auto1';
const createScene = (framePerSecond = 60) => {
@@ -67,6 +70,7 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
cellWidth: 20,
cellHeight: 20,
extraBorder: 0,
smoothingMaxCellGap: smoothingMaxCellGap,
collisionMethod: collisionMethod,
},
],
@@ -106,6 +110,25 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
return obstacle;
};
const getPathLength = (player) => {
/** @type gdjs.PathfindingRuntimeBehavior */
const behavior = player.getBehavior(pathFindingName);
if (behavior.getNodeCount() < 2) {
return 0;
}
let pathLength = 0;
let previousNodeX = behavior.getNodeX(0);
let previousNodeY = behavior.getNodeY(0);
for (let index = 1; index < behavior.getNodeCount(); index++) {
const nodeX = behavior.getNodeX(index);
const nodeY = behavior.getNodeY(index);
pathLength += Math.hypot(nodeX - previousNodeX, nodeY - previousNodeY);
previousNodeX = nodeX;
previousNodeY = nodeY;
}
return pathLength;
};
let runtimeScene;
let player;
beforeEach(function () {
@@ -117,7 +140,7 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(player.getBehavior(pathFindingName).getNodeCount()).to.be(13);
expect(getPathLength(player)).to.be(720 - 480);
});
it('can find a path without any obstacle in the way', function () {
@@ -130,7 +153,7 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(player.getBehavior(pathFindingName).getNodeCount()).to.be(13);
expect(getPathLength(player)).to.be(720 - 480);
});
it("mustn't find a path to the obstacle inside", function () {
@@ -155,101 +178,9 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(player.getBehavior(pathFindingName).getNodeCount()).to.be.above(
13
);
expect(getPathLength(player)).to.be.above(720 - 480 + 50);
});
if (allowDiagonals) {
[20, 30, 60, 120].forEach((framePerSecond) => {
describe(`(${framePerSecond} fps)`, function () {
it('can move on the path at the right speed', function () {
setFramePerSecond(runtimeScene, framePerSecond);
const obstacle = addObstacle(runtimeScene);
obstacle.setPosition(600, 300);
// To ensure obstacles are registered.
runtimeScene.renderAndStep(1000 / framePerSecond);
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(
player.getBehavior(pathFindingName).getNodeCount()
).to.be.above(13);
// Move on the path and stop before the last 1/10 of second.
for (let i = 0; i < (framePerSecond * 17) / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(false);
}
// The position is the same no matter the frame rate.
expect(player.getX()).to.be(720);
expect(player.getY()).to.be.within(
288.5786437626905 - epsilon,
288.5786437626905 + epsilon
);
// Let 1/10 of second pass,
// because the calculus interval is not the same for each case.
for (let i = 0; i < framePerSecond / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
}
// The destination is reached for every frame rate within 1/10 of second.
expect(player.getX()).to.be(720);
expect(player.getY()).to.be(300);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(true);
});
});
});
} else {
[20, 30, 60, 120].forEach((framePerSecond) => {
describe(`(${framePerSecond} fps)`, function () {
it('can move on the path at the right speed', function () {
setFramePerSecond(runtimeScene, framePerSecond);
const obstacle = addObstacle(runtimeScene);
obstacle.setPosition(600, 300);
// To ensure obstacles are registered.
runtimeScene.renderAndStep(1000 / framePerSecond);
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(
player.getBehavior(pathFindingName).getNodeCount()
).to.be.above(13);
// Move on the path and stop before the last 1/10 of second.
for (let i = 0; i < (framePerSecond * 20) / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(false);
}
expect(player.getX()).to.be(710);
expect(player.getY()).to.be.within(300 - epsilon, 300 + epsilon);
// Let 1/10 of second pass,
// because the calculus interval is not the same for each case.
for (let i = 0; i < (framePerSecond * 1) / 10; i++) {
runtimeScene.renderAndStep(1000 / framePerSecond);
}
// The destination is reached for every frame rate within 1/10 of second.
expect(player.getX()).to.be(720);
expect(player.getY()).to.be(300);
expect(
player.getBehavior(pathFindingName).destinationReached()
).to.be(true);
});
});
});
}
it('can find a path between 2 obstacles', function () {
const obstacleTop = addObstacle(runtimeScene);
const obstacleBottom = addObstacle(runtimeScene);
@@ -262,7 +193,7 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
player.setPosition(480, 300);
player.getBehavior(pathFindingName).moveTo(runtimeScene, 720, 300);
expect(player.getBehavior(pathFindingName).pathFound()).to.be(true);
expect(player.getBehavior(pathFindingName).getNodeCount()).to.be(13);
expect(getPathLength(player)).to.be(720 - 480);
});
it("mustn't find a path to a closed room", function () {
@@ -288,7 +219,15 @@ describe('gdjs.PathfindingRuntimeBehavior', function () {
describe(`(collisionMethod: ${collisionMethod}, `, function () {
[false, true].forEach((allowDiagonals) => {
describe(`(allowDiagonals: ${allowDiagonals})`, function () {
doCommonPathFindingTests(collisionMethod, allowDiagonals);
[0, 1].forEach((smoothingMaxCellGap) => {
describe(`(smoothingMaxCellGap: ${smoothingMaxCellGap})`, function () {
doCommonPathFindingTests(
collisionMethod,
allowDiagonals,
smoothingMaxCellGap
);
});
});
});
});
});

View File

@@ -1,6 +1,8 @@
// @ts-check
describe('gdjs.PathfindingRuntimeBehavior', function () {
// limit tests cases on the legacy collision methods.
// Note that the legacy collision mode is still the only mode that exists
// because the new one were never merged.
let doLegacyPathFindingTests = (
cellSize,
objectCenteredOnCells,

View File

@@ -200,6 +200,7 @@ module.exports = {
.toString(10)
)
.setType('Number')
.setMeasurementUnit(gd.MeasurementUnit.getPixel())
.setLabel('Shape Dimension A');
behaviorProperties
.getOrCreate('shapeDimensionB')
@@ -210,6 +211,7 @@ module.exports = {
.toString(10)
)
.setType('Number')
.setMeasurementUnit(gd.MeasurementUnit.getPixel())
.setLabel('Shape Dimension B');
behaviorProperties
.getOrCreate('shapeOffsetX')
@@ -217,6 +219,7 @@ module.exports = {
behaviorContent.getChild('shapeOffsetX').getDoubleValue().toString(10)
)
.setType('Number')
.setMeasurementUnit(gd.MeasurementUnit.getPixel())
.setLabel('Shape Offset X');
behaviorProperties
.getOrCreate('shapeOffsetY')
@@ -224,6 +227,7 @@ module.exports = {
behaviorContent.getChild('shapeOffsetY').getDoubleValue().toString(10)
)
.setType('Number')
.setMeasurementUnit(gd.MeasurementUnit.getPixel())
.setLabel('Shape Offset Y');
behaviorProperties
.getOrCreate('polygonOrigin')
@@ -373,13 +377,15 @@ module.exports = {
.setValue(
sharedContent.getChild('gravityX').getDoubleValue().toString(10)
)
.setType('Number');
.setType('Number')
.setMeasurementUnit(gd.MeasurementUnit.getNewton());
sharedProperties
.getOrCreate('gravityY')
.setValue(
sharedContent.getChild('gravityY').getDoubleValue().toString(10)
)
.setType('Number');
.setType('Number')
.setMeasurementUnit(gd.MeasurementUnit.getNewton());
sharedProperties
.getOrCreate('scaleX')
.setValue(
@@ -435,7 +441,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Gravity to compare to (in pixels per second per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('getGravityX');
@@ -464,7 +475,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Gravity to compare to (in pixels per second per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('getGravityY');
@@ -514,7 +530,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Time scale to compare to (1 by default)')
)
)
.getCodeExtraInformation()
.setFunctionName('getTimeScale');
@@ -535,7 +556,7 @@ module.exports = {
)
.addParameter('objectList', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Value'))
.addParameter('expression', _('Time scale (1 by default)'))
.getCodeExtraInformation()
.setIncludeFile('Extensions/Physics2Behavior/physics2tools.js')
.setFunctionName('gdjs.physics2.setTimeScale');
@@ -782,7 +803,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Scale (1 by default)')
)
)
.getCodeExtraInformation()
.setFunctionName('setShapeScale')
.setGetter('getShapeScale');
@@ -799,7 +825,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('getDensity');
@@ -817,7 +846,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setDensity')
.setGetter('getDensity');
@@ -847,7 +879,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('getFriction');
@@ -865,7 +900,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setFriction')
.setGetter('getFriction');
@@ -895,7 +933,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('getRestitution');
@@ -913,7 +954,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setRestitution')
.setGetter('getRestitution');
@@ -943,7 +987,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('getLinearDamping');
@@ -961,7 +1008,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setLinearDamping')
.setGetter('getLinearDamping');
@@ -991,7 +1041,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('getAngularDamping');
@@ -1009,7 +1062,10 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setAngularDamping')
.setGetter('getAngularDamping');
@@ -1039,7 +1095,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Scale to compare to (1 by default)')
)
)
.getCodeExtraInformation()
.setFunctionName('getGravityScale');
@@ -1057,7 +1118,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Scale (1 by default)')
)
)
.getCodeExtraInformation()
.setFunctionName('setGravityScale')
.setGetter('getGravityScale');
@@ -1161,7 +1227,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Speed to compare to (in pixels per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('getLinearVelocityX');
@@ -1177,7 +1248,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Speed (in pixels per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('setLinearVelocityX')
.setGetter('getLinearVelocityX');
@@ -1207,7 +1283,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Speed to compare to (in pixels per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('getLinearVelocityY');
@@ -1223,7 +1304,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Speed (in pixels per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('setLinearVelocityY')
.setGetter('getLinearVelocityY');
@@ -1253,7 +1339,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Speed to compare to (in pixels per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('getLinearVelocityLength');
@@ -1282,7 +1373,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angular speed to compare to (in degrees per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('getAngularVelocity');
@@ -1298,7 +1394,12 @@ module.exports = {
)
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions().setDescription(
_('Angular speed (in degrees per second)')
)
)
.getCodeExtraInformation()
.setFunctionName('setAngularVelocity')
.setGetter('getAngularVelocity');
@@ -1487,7 +1588,7 @@ module.exports = {
.getCodeExtraInformation()
.setFunctionName('applyAngularImpulse');
aut
aut
.addExpression(
'Mass',
_('Mass'),
@@ -1641,7 +1742,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('getJointReactionForce');
@@ -1672,7 +1776,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardRelationalOperatorParameters('number')
.useStandardRelationalOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('getJointReactionTorque');
@@ -1776,7 +1883,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setDistanceJointLength')
.setGetter('getDistanceJointLength');
@@ -1808,7 +1918,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setDistanceJointFrequency')
.setGetter('getDistanceJointFrequency');
@@ -1840,7 +1953,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setDistanceJointDampingRatio')
.setGetter('getDistanceJointDampingRatio');
@@ -2135,7 +2251,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setRevoluteJointMotorSpeed')
.setGetter('getRevoluteJointMotorSpeed');
@@ -2167,7 +2286,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setRevoluteJointMaxMotorTorque')
.setGetter('getRevoluteJointMaxMotorTorque');
@@ -2447,7 +2569,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setPrismaticJointMotorSpeed')
.setGetter('getPrismaticJointMotorSpeed');
@@ -2479,7 +2604,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setPrismaticJointMaxMotorForce')
.setGetter('getPrismaticJointMaxMotorForce');
@@ -2749,7 +2877,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setGearJointRatio')
.setGetter('getGearJointRatio');
@@ -2876,7 +3007,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setMouseJointMaxForce')
.setGetter('getMouseJointMaxForce');
@@ -2908,7 +3042,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setMouseJointFrequency')
.setGetter('getMouseJointFrequency');
@@ -2940,7 +3077,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setMouseJointDampingRatio')
.setGetter('getMouseJointDampingRatio');
@@ -3109,7 +3249,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setWheelJointMotorSpeed')
.setGetter('getWheelJointMotorSpeed');
@@ -3141,7 +3284,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setWheelJointMaxMotorTorque')
.setGetter('getWheelJointMaxMotorTorque');
@@ -3187,7 +3333,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setWheelJointFrequency')
.setGetter('getWheelJointFrequency');
@@ -3219,7 +3368,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setWheelJointDampingRatio')
.setGetter('getWheelJointDampingRatio');
@@ -3315,7 +3467,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setWeldJointFrequency')
.setGetter('getWeldJointFrequency');
@@ -3347,7 +3502,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setWeldJointDampingRatio')
.setGetter('getWeldJointDampingRatio');
@@ -3422,7 +3580,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setRopeJointMaxLength')
.setGetter('getRopeJointMaxLength');
@@ -3490,7 +3651,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setFrictionJointMaxForce')
.setGetter('getFrictionJointMaxForce');
@@ -3522,7 +3686,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setFrictionJointMaxTorque')
.setGetter('getFrictionJointMaxTorque');
@@ -3639,7 +3806,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setMotorJointAngularOffset')
.setGetter('getMotorJointAngularOffset');
@@ -3671,7 +3841,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setMotorJointMaxForce')
.setGetter('getMotorJointMaxForce');
@@ -3703,7 +3876,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setMotorJointMaxTorque')
.setGetter('getMotorJointMaxTorque');
@@ -3735,7 +3911,10 @@ module.exports = {
.addParameter('object', _('Object'), '', false)
.addParameter('behavior', _('Behavior'), 'Physics2Behavior')
.addParameter('expression', _('Joint ID'))
.useStandardOperatorParameters('number')
.useStandardOperatorParameters(
'number',
gd.ParameterOptions.makeNewOptions()
)
.getCodeExtraInformation()
.setFunctionName('setMotorJointCorrectionFactor')
.setGetter('getMotorJointCorrectionFactor');
@@ -3761,7 +3940,7 @@ module.exports = {
_('Collision'),
_('Check if two objects collide.'),
_('_PARAM0_ is colliding with _PARAM2_'),
'',
'',
'res/physics32.png',
'res/physics32.png'
)

View File

@@ -825,8 +825,12 @@ namespace gdjs {
}
doStepPreEvents(instanceContainer: gdjs.RuntimeInstanceContainer) {
// Step the world if not done this frame yet
if (!this._sharedData.stepped) {
// Step the world if not done this frame yet.
// Don't step at the first frame to allow events to handle overlapping objects.
if (
!this._sharedData.stepped &&
!instanceContainer.getScene().getTimeManager().isFirstFrame()
) {
// Reset started and ended contacts array for all physics instances.
this._sharedData.resetStartedAndEndedCollisions();
this._sharedData.updateBodiesFromObjects();

View File

@@ -64,7 +64,7 @@ describe('Physics2RuntimeBehavior', () => {
resources: { resources: [] },
properties: { windowWidth: 1000, windowHeight: 1000 },
});
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
const runtimeScene = new gdjs.TestRuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [
{
@@ -236,6 +236,39 @@ describe('Physics2RuntimeBehavior', () => {
expect(behavior.getRestitution()).to.be(0.5);
});
it('should not resolve collision before the 1st frame events', () => {
const fps = 60;
runtimeScene._timeManager.getElapsedTime = function () {
return (1 / fps) * 1000;
};
// Create objects in contact
const {
object: object1,
behavior: object1Behavior,
} = createObjectWithPhysicsBehavior(runtimeScene, {
bodyType: 'Dynamic',
});
object1.setPosition(10, 0);
const {
object: object2,
behavior: object2Behavior,
} = createObjectWithPhysicsBehavior(runtimeScene, {
bodyType: 'Static',
restitution: 0,
});
object2.setPosition(20, 0);
// First frame
runtimeScene.renderAndStep(1000 / fps);
// The object has not moved.
expect(object1.getX()).to.be(10);
expect(object1.getY()).to.be(0);
expect(object2.getX()).to.be(20);
expect(object2.getY()).to.be(0);
});
it('should clear contacts when deactivating the physics2 behavior', () => {
const fps = 60;
runtimeGame.setGameResolutionSize(1000, 1000);
@@ -243,6 +276,9 @@ describe('Physics2RuntimeBehavior', () => {
return (1 / fps) * 1000;
};
// The behavior doesn't call Box2D step at the 1st frame.
runtimeScene.renderAndStep(1000 / fps);
// Create objects not in contact
const {
object: object1,
@@ -271,11 +307,10 @@ describe('Physics2RuntimeBehavior', () => {
).to.be(true);
// Put objects in contact and assert collision started during the frame
runtimeScene.setEventsFunction(() => {
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
object1.setPosition(10, 0);
object2.setPosition(20, 0);
});
runtimeScene.renderAndStep(1000 / fps);
// After post event, collision should be present
assertCollision(object1, object2, {
@@ -284,9 +319,6 @@ describe('Physics2RuntimeBehavior', () => {
stopped: false,
});
// Reset scene events
runtimeScene.setEventsFunction(() => {});
// Deactivate physics behavior and test that collisions are cleared.
object1.activateBehavior('Physics2', false);
assertCollision(object1, object2, {
@@ -424,33 +456,28 @@ describe('Physics2RuntimeBehavior', () => {
movingObjectBehavior.setLinearVelocityY(40000);
let hasBounced = false;
let stepIndex = 0;
runtimeScene.setEventsFunction(() => {
if (movingObjectBehavior.getLinearVelocityY() > 0) {
// If the moving object has a positive velocity, it hasn't bounced
// on the static object
assertCollision(movingObject, staticObject, {
started: false,
collision: false,
stopped: false,
});
} else {
hasBounced = true;
expect(movingObject.getY() < staticObject.getY()).to.be(true);
assertCollision(movingObject, staticObject, {
started: true,
collision: true,
stopped: true,
});
}
});
while (stepIndex < 10 && !hasBounced) {
runtimeScene.renderAndStep(1000 / fps);
stepIndex++;
for (let stepIndex = 0; stepIndex < 10 && !hasBounced; stepIndex++) {
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
if (movingObjectBehavior.getLinearVelocityY() > 0) {
// If the moving object has a positive velocity, it hasn't bounced
// on the static object
assertCollision(movingObject, staticObject, {
started: false,
collision: false,
stopped: false,
});
} else {
hasBounced = true;
expect(movingObject.getY() < staticObject.getY()).to.be(true);
assertCollision(movingObject, staticObject, {
started: true,
collision: true,
stopped: true,
});
}
});
}
runtimeScene.setEventsFunction(() => {});
runtimeScene.renderAndStep(1000 / fps);
assertCollision(movingObject, staticObject, {
started: false,
@@ -486,32 +513,31 @@ describe('Physics2RuntimeBehavior', () => {
movingObjectBehavior.setLinearVelocityY(40000);
let hasBegunBouncing = false;
let stepIndex = 0;
runtimeScene.setEventsFunction(() => {
if (movingObjectBehavior.getLinearVelocityY() > 0) {
// If the moving object has a positive velocity, it hasn't bounced
// on the static object
assertCollision(movingObject, staticObject, {
started: false,
collision: false,
stopped: false,
});
} else {
hasBegunBouncing = true;
// At first frame, collision should have only started
expect(movingObject.getY() < staticObject.getY()).to.be(true);
assertCollision(movingObject, staticObject, {
started: true,
collision: true,
stopped: false,
});
}
});
while (stepIndex < 10 && !hasBegunBouncing) {
runtimeScene.renderAndStep(1000 / fps);
stepIndex++;
for (
let stepIndex = 0;
stepIndex < 10 && !hasBegunBouncing;
stepIndex++
) {
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
if (movingObjectBehavior.getLinearVelocityY() > 0) {
// If the moving object has a positive velocity, it hasn't bounced
// on the static object
assertCollision(movingObject, staticObject, {
started: false,
collision: false,
stopped: false,
});
} else {
hasBegunBouncing = true;
// At first frame, collision should have only started
expect(movingObject.getY() < staticObject.getY()).to.be(true);
assertCollision(movingObject, staticObject, {
started: true,
collision: true,
stopped: false,
});
}
});
}
if (!hasBegunBouncing) {
@@ -522,8 +548,7 @@ describe('Physics2RuntimeBehavior', () => {
// At next frame, end of collision should be detected
let hasFinishedBouncing = false;
runtimeScene.setEventsFunction(() => {
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
hasFinishedBouncing = true;
assertCollision(movingObject, staticObject, {
started: false,
@@ -532,8 +557,6 @@ describe('Physics2RuntimeBehavior', () => {
});
});
runtimeScene.renderAndStep(1000 / fps);
if (!hasFinishedBouncing) {
throw new Error('End of contact was not detected, nothing was tested.');
}
@@ -546,6 +569,9 @@ describe('Physics2RuntimeBehavior', () => {
return (1 / fps) * 1000;
};
// The behavior doesn't call Box2D step at the 1st frame.
runtimeScene.renderAndStep(1000 / fps);
const {
behavior: movingObjectBehavior,
object: movingObject,
@@ -567,7 +593,7 @@ describe('Physics2RuntimeBehavior', () => {
stopped: false,
});
runtimeScene.setEventsFunction(() => {
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
// Manually call onContactEnd and onContactBegin methods to simulate
// a loss of contact followed by a contact beginning during the preEvent.
movingObject
@@ -584,7 +610,6 @@ describe('Physics2RuntimeBehavior', () => {
stopped: false,
});
});
runtimeScene.renderAndStep(1000 / fps);
});
it('should not detect a new contact if the contact ended and jittered.', () => {
@@ -594,6 +619,9 @@ describe('Physics2RuntimeBehavior', () => {
return (1 / fps) * 1000;
};
// The behavior doesn't call Box2D step at the 1st frame.
runtimeScene.renderAndStep(1000 / fps);
const {
behavior: movingObjectBehavior,
object: movingObject,
@@ -615,7 +643,7 @@ describe('Physics2RuntimeBehavior', () => {
stopped: false,
});
runtimeScene.setEventsFunction(() => {
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
// Manually call onContactEnd and onContactBegin methods to simulate
// a loss of contact followed by a contact beginning and another loss
// of contact during the event.
@@ -637,7 +665,6 @@ describe('Physics2RuntimeBehavior', () => {
stopped: true,
});
});
runtimeScene.renderAndStep(1000 / fps);
});
it('it should end collision on resize (body updated in pre-event).', () => {
@@ -647,6 +674,9 @@ describe('Physics2RuntimeBehavior', () => {
return (1 / fps) * 1000;
};
// The behavior doesn't call Box2D step at the 1st frame.
runtimeScene.renderAndStep(1000 / fps);
const {
behavior: movingObjectBehavior,
object: movingObject,
@@ -668,18 +698,15 @@ describe('Physics2RuntimeBehavior', () => {
});
// Resize.
runtimeScene.setEventsFunction(() => {
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
movingObject.setCustomWidthAndHeight(5, 5);
});
runtimeScene.renderAndStep(1000 / fps);
assertCollision(movingObject, staticObject, {
started: false,
collision: true,
stopped: false,
});
runtimeScene.setEventsFunction(() => {});
runtimeScene.renderAndStep(1000 / fps);
assertCollision(movingObject, staticObject, {
started: false,
@@ -695,6 +722,9 @@ describe('Physics2RuntimeBehavior', () => {
return (1 / fps) * 1000;
};
// The behavior doesn't call Box2D step at the 1st frame.
runtimeScene.renderAndStep(1000 / fps);
const {
behavior: movingObjectBehavior,
object: movingObject,
@@ -716,13 +746,11 @@ describe('Physics2RuntimeBehavior', () => {
stopped: false,
});
// Destroy (postEvent operation).
runtimeScene.setEventsFunction(() => {
// Destroy (handled by postEvent).
runtimeScene.renderAndStepWithEventsFunction(1000 / fps, () => {
movingObject.deleteFromScene(runtimeScene);
});
runtimeScene.renderAndStep(1000 / fps);
// Collision should be reset on destroyed object and
// added to contactsEndedThisFrame array of the other object.
assertCollision(movingObject, staticObject, {

View File

@@ -337,7 +337,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetLinearVelocityX");
@@ -351,7 +352,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetLinearVelocityY");
@@ -364,7 +366,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetLinearVelocity");
@@ -390,7 +393,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetAngularVelocity");
@@ -403,7 +407,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetLinearDamping");
@@ -445,7 +450,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetAngularDamping");
@@ -516,7 +522,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetPolygonScaleX");
@@ -530,7 +537,8 @@ void DeclarePhysicsBehaviorExtension(gd::PlatformExtension& extension) {
"res/physics16.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PhysicsBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("GetPolygonScaleY");

View File

@@ -5,11 +5,10 @@ Copyright (c) 2014-2016 Florian Rival (Florian.Rival@gmail.com)
This project is released under the MIT License.
*/
#include "PlatformBehavior.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Tools/Localization.h"
#include "PlatformBehavior.h"
#include "PlatformerObjectBehavior.h"
void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
@@ -134,61 +133,71 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
aut.AddCondition("Gravity",
_("Gravity"),
_("Compare the gravity applied on the object (in pixels "
"per second per second)."),
_("Compare the gravity applied on the object."),
_("the gravity"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Gravity to compare to (in pixels per "
"second per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetGravity");
aut.AddAction("Gravity",
_("Gravity"),
_("Change the gravity applied on an object (in pixels per "
"second per second)."),
_("Change the gravity applied on an object."),
_("the gravity"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Gravity (in pixels per "
"second per second)")))
.MarkAsAdvanced()
.SetFunctionName("SetGravity")
.SetGetter("GetGravity");
aut.AddCondition(
"MaxFallingSpeed",
_("Maximum falling speed"),
_("Compare the maximum falling speed of the object (in pixels per "
"second)."),
_("the maximum falling speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddCondition("MaxFallingSpeed",
_("Maximum falling speed"),
_("Compare the maximum falling speed of the object."),
_("the maximum falling speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max speed to compare to (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetMaxFallingSpeed");
aut.AddAction(
"MaxFallingSpeed",
_("Maximum falling speed"),
_("Change the maximum falling speed of an object (in pixels per "
"second)."),
_("the maximum falling speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddAction("MaxFallingSpeed",
_("Maximum falling speed"),
_("Change the maximum falling speed of an object."),
_("the maximum falling speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.AddParameter("yesorno", _("If jumping, try to preserve the current speed in the air"))
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max speed (in pixels per second)")))
.AddParameter(
"yesorno",
_("If jumping, try to preserve the current speed in the air"))
.MarkAsAdvanced()
.SetFunctionName("SetMaxFallingSpeed")
.SetGetter("GetMaxFallingSpeed");
@@ -203,145 +212,170 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed to compare to (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetLadderClimbingSpeed");
aut.AddAction("LadderClimbingSpeed",
_("Ladder climbing speed"),
_("Change the ladder climbing speed (in pixels per "
"second)."),
_("Change the ladder climbing speed."),
_("the ladder climbing speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("SetLadderClimbingSpeed")
.SetGetter("GetLadderClimbingSpeed");
aut.AddCondition("Acceleration",
_("Acceleration"),
_("Compare the horizontal acceleration of the object (in pixels per "
"second per second)."),
_("Compare the horizontal acceleration of the object."),
_("the horizontal acceleration"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Acceleration to compare to (in pixels per "
"second per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetAcceleration");
aut.AddAction("Acceleration",
_("Acceleration"),
_("Change the horizontal acceleration of an object (in pixels per "
"second per second)."),
_("Change the horizontal acceleration of an object."),
_("the horizontal acceleration"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Acceleration (in pixels per "
"second per second)")))
.MarkAsAdvanced()
.SetFunctionName("SetAcceleration")
.SetGetter("GetAcceleration");
aut.AddCondition("Deceleration",
_("Deceleration"),
_("Compare the horizontal deceleration of the object (in pixels per "
"second per second)."),
_("Compare the horizontal deceleration of the object."),
_("the horizontal deceleration"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Deceleration to compare to (in pixels per "
"second per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetDeceleration");
aut.AddAction("Deceleration",
_("Deceleration"),
_("Change the horizontal deceleration of an object (in pixels per "
"second per second)."),
_("Change the horizontal deceleration of an object."),
_("the horizontal deceleration"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Deceleration (in pixels per "
"second per second)")))
.MarkAsAdvanced()
.SetFunctionName("SetDeceleration")
.SetGetter("GetDeceleration");
aut.AddCondition(
"MaxSpeed",
_("Maximum horizontal speed"),
_("Compare the maximum horizontal speed of the object (in pixels per second)."),
_("the maximum horizontal speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddCondition("MaxSpeed",
_("Maximum horizontal speed"),
_("Compare the maximum horizontal speed of the object."),
_("the maximum horizontal speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max speed to compare to (in pixels per second)")))
.SetFunctionName("GetMaxSpeed");
aut.AddAction(
"MaxSpeed",
_("Maximum horizontal speed"),
_("Change the maximum horizontal speed of an object (in pixels per second)."),
_("the maximum horizontal speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddAction("MaxSpeed",
_("Maximum horizontal speed"),
_("Change the maximum horizontal speed of an object."),
_("the maximum horizontal speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Max speed (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("SetMaxSpeed")
.SetGetter("GetMaxSpeed");
aut.AddCondition(
"JumpSpeed",
_("Jump speed"),
_("Compare the jump speed of the object (in pixels per second)."
"Its value is always positive."),
_("the jump speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddCondition("JumpSpeed",
_("Jump speed"),
_("Compare the jump speed of the object."
"Its value is always positive."),
_("the jump speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed to compare to (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetJumpSpeed");
aut.AddAction(
"JumpSpeed",
_("Jump speed"),
_("Change the jump speed of an object (in pixels per second). "
"Its value is always positive."),
_("the jump speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddAction("JumpSpeed",
_("Jump speed"),
_("Change the jump speed of an object. "
"Its value is always positive."),
_("the jump speed"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed (in pixels per second)")))
.SetFunctionName("SetJumpSpeed")
.SetGetter("GetJumpSpeed");
aut.AddCondition(
"JumpSustainTime",
_("Jump sustain time"),
_("Compare the jump sustain time of the object (in seconds)."
_("Compare the jump sustain time of the object."
"This is the time during which keeping the jump button held "
"allow the initial jump speed to be maintained."),
_("the jump sustain time"),
@@ -350,21 +384,28 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Duration to compare to (in seconds)")))
.MarkAsAdvanced();
aut.AddAction("JumpSustainTime",
_("Jump sustain time"),
_("Change the jump sustain time of an object (in seconds). "
"This is the time during which keeping the jump button held "
"allow the initial jump speed to be maintained."),
_("the jump sustain time"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddAction(
"JumpSustainTime",
_("Jump sustain time"),
_("Change the jump sustain time of an object."
"This is the time during which keeping the jump button held "
"allow the initial jump speed to be maintained."),
_("the jump sustain time"),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number");
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Duration (in seconds)")));
aut.AddAction(
"SetCanJump",
@@ -400,7 +441,8 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
"AbortJump",
_("Abort jump"),
_("Abort the current jump and stop the object vertically. "
"This action doesn't have any effect when the character is not jumping."),
"This action doesn't have any effect when the character is not "
"jumping."),
_("Abort the current jump of _PARAM0_"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
@@ -589,11 +631,28 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
.MarkAsSimple()
.SetFunctionName("canGrabPlatforms");
aut.AddCondition("CurrentFallSpeed",
_("Current falling speed"),
_("Compare the current falling speed of the object. Its "
"value is always positive."),
_("the current falling speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed to compare to (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetCurrentFallSpeed");
aut.AddScopedAction(
"SetCurrentFallSpeed",
_("Current falling speed"),
_("Change the current falling speed of the object (in pixels per "
"second). This action doesn't have any effect when the character "
_("Change the current falling speed of the object. This action "
"doesn't have any effect when the character "
"is not falling or is in the first phase of a jump."),
_("the current falling speed"),
_(""),
@@ -601,85 +660,70 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed (in pixels per second)")))
.MarkAsAdvanced();
aut.AddCondition(
"CurrentFallSpeed",
_("Current falling speed"),
_("Compare the current falling speed of the object (in pixels per "
"second). Its value is always positive."),
_("the current falling speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddCondition("CurrentJumpSpeed",
_("Current jump speed"),
_("Compare the current jump speed of the object. Its "
"value is always positive."),
_("the current jump speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.MarkAsAdvanced()
.SetFunctionName("GetCurrentFallSpeed");
aut.AddCondition(
"CurrentJumpSpeed",
_("Current jump speed"),
_("Compare the current jump speed of the object (in pixels per "
"second). Its value is always positive."),
_("the current jump speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed to compare to (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetCurrentJumpSpeed");
aut.AddScopedAction("SetCurrentSpeed",
_("Current horizontal speed"),
_("Change the current horizontal speed of the object "
"(in pixels per second). The object moves to the left "
"with negative values and to the right with positive ones"),
_("the current horizontal speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddScopedAction(
"SetCurrentSpeed",
_("Current horizontal speed"),
_("Change the current horizontal speed of the object. The object "
"moves to the left with negative values and to the right with "
"positive ones"),
_("the current horizontal speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed (in pixels per second)")))
.MarkAsAdvanced();
aut.AddScopedAction("FollowCurrentPlatform",
_("Follow the floor"),
_("Move the object to follow the platform it's currently"
"on if any. This action allows to avoid the 1-frame "
"delay induced by the automatic following."),
_("Move _PARAM0_ to follow the floor"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddCondition(
"CurrentSpeed",
_("Current horizontal speed"),
_("Compare the current horizontal speed of the object. The object "
"moves to the left "
"with negative values and to the right with positive ones"),
_("the current horizontal speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.MarkAsAdvanced();
aut.AddCondition("CurrentSpeed",
_("Current horizontal speed"),
_("Compare the current horizontal speed of the object "
"(in pixels per second). The object moves to the left "
"with negative values and to the right with positive ones"),
_("the current horizontal speed"),
_(""),
"CppPlatform/Extensions/platformerobjecticon.png",
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed to compare to (in pixels per second)")))
.MarkAsAdvanced()
.SetFunctionName("GetCurrentSpeed");
aut.AddExpression("Gravity",
_("Gravity"),
_("Return the gravity applied on the object "
"(in pixels per second per second)."),
"(in pixels per second per second)."),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
@@ -709,7 +753,7 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
aut.AddExpression("Acceleration",
_("Acceleration"),
_("Return the horizontal acceleration of the object "
"(in pixels per second per second)."),
"(in pixels per second per second)."),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
@@ -719,7 +763,7 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
aut.AddExpression("Deceleration",
_("Deceleration"),
_("Return the horizontal deceleration of the object "
"(in pixels per second per second)."),
"(in pixels per second per second)."),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
@@ -736,12 +780,13 @@ void DeclarePlatformBehaviorExtension(gd::PlatformExtension& extension) {
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.SetFunctionName("GetMaxSpeed");
aut.AddExpression("JumpSpeed",
_("Jump speed"),
_("Return the jump speed of the object "
"(in pixels per second). Its value is always positive."),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png")
aut.AddExpression(
"JumpSpeed",
_("Jump speed"),
_("Return the jump speed of the object "
"(in pixels per second). Its value is always positive."),
_("Options"),
"CppPlatform/Extensions/platformerobjecticon.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "PlatformerObjectBehavior")
.SetFunctionName("GetJumpSpeed");

View File

@@ -131,14 +131,10 @@ class PlatformBehaviorJsExtension : public gd::PlatformExtension {
"getCurrentJumpSpeed");
autExpressions["CurrentJumpSpeed"].SetFunctionName("getCurrentJumpSpeed");
autActions["PlatformBehavior::SetCanJump"].SetFunctionName("setCanJump");
autActions["PlatformBehavior::PlatformerObjectBehavior::SetCanNotAirJump"]
.SetFunctionName("setCanNotAirJump");
autActions["PlatformBehavior::PlatformerObjectBehavior::AbortJump"]
.SetFunctionName("abortJump");
autActions
["PlatformBehavior::PlatformerObjectBehavior::FollowCurrentPlatform"]
.SetFunctionName("followCurrentPlatformIfAny");
autConditions["PlatformBehavior::CanJump"].SetFunctionName("canJump");
autActions["PlatformBehavior::PlatformerObjectBehavior::SetCanNotAirJump"].SetFunctionName("setCanNotAirJump");
autActions["PlatformBehavior::PlatformerObjectBehavior::AbortJump"].SetFunctionName("abortJump");
autConditions["PlatformBehavior::CanJump"].SetFunctionName(
"canJump");
autActions["PlatformBehavior::SimulateLeftKey"].SetFunctionName(
"simulateLeftKey");
autActions["PlatformBehavior::SimulateRightKey"].SetFunctionName(

View File

@@ -36,18 +36,24 @@ std::map<gd::String, gd::PropertyDescriptor> PlatformBehavior::GetProperties(
else if (platformType == "Jumpthru")
platformTypeStr = _("Jumpthru platform");
properties[_("Type")]
properties["PlatformType"]
.SetLabel(_("Type"))
.SetValue(platformTypeStr)
.SetType("Choice")
.AddExtraInfo(_("Platform"))
.AddExtraInfo(_("Jumpthru platform"))
.AddExtraInfo(_("Ladder"));
properties[_("Ledges can be grabbed")].SetGroup(_("Ledge"))
properties["CanBeGrabbed"]
.SetLabel(_("Ledges can be grabbed"))
.SetGroup(_("Ledge"))
.SetValue(behaviorContent.GetBoolAttribute("canBeGrabbed", true)
? "true"
: "false")
.SetType("Boolean");
properties[_("Grab offset on Y axis")].SetGroup(_("Ledge")).SetValue(
properties["YGrabOffset"]
.SetLabel(_("Grab offset on Y axis"))
.SetGroup(_("Ledge"))
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("yGrabOffset")));
return properties;
@@ -56,16 +62,16 @@ std::map<gd::String, gd::PropertyDescriptor> PlatformBehavior::GetProperties(
bool PlatformBehavior::UpdateProperty(gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value) {
if (name == _("Ledges can be grabbed"))
if (name == "CanBeGrabbed")
behaviorContent.SetAttribute("canBeGrabbed", (value == "1"));
else if (name == _("Type")) {
else if (name == "PlatformType") {
if (value == _("Jumpthru platform"))
behaviorContent.SetAttribute("platformType", "Jumpthru");
else if (value == _("Ladder"))
behaviorContent.SetAttribute("platformType", "Ladder");
else
behaviorContent.SetAttribute("platformType", "NormalPlatform");
} else if (name == _("Grab offset on Y axis"))
} else if (name == "YGrabOffset")
behaviorContent.SetAttribute("yGrabOffset", value.To<double>());
else
return false;

View File

@@ -13,6 +13,7 @@ This project is released under the MIT License.
#include "GDCore/CommonTools.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/MeasurementUnit.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/Localization.h"
@@ -44,60 +45,109 @@ PlatformerObjectBehavior::GetProperties(
const gd::SerializerElement& behaviorContent) const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[_("Gravity")].SetGroup(_("Jump")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("gravity")));
properties[_("Jump speed")].SetGroup(_("Jump")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("jumpSpeed")));
properties["jumpSustainTime"]
properties["Gravity"]
.SetLabel(_("Gravity"))
.SetGroup(_("Jump"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelAcceleration())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("gravity")));
properties["JumpSpeed"]
.SetLabel(_("Jump speed"))
.SetGroup(_("Jump"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelSpeed())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("jumpSpeed")));
properties["JumpSustainTime"]
.SetLabel(_("Jump sustain time"))
.SetGroup(_("Jump"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetSecond())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("jumpSustainTime", 0)))
.SetLabel(_("Jump sustain time"))
.SetDescription(
_("Maximum time (in seconds) during which the jump strength is "
"sustained if the jump key is held - allowing variable height "
"jumps."));
properties[_("Max. falling speed")].SetGroup(_("Jump")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("maxFallingSpeed")));
properties[_("Ladder climbing speed")]
properties["MaxFallingSpeed"]
.SetLabel(_("Max. falling speed"))
.SetGroup(_("Jump"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelSpeed())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("maxFallingSpeed")));
properties["LadderClimbingSpeed"]
.SetLabel(_("Ladder climbing speed"))
.SetGroup(_("Ladder"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelSpeed())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("ladderClimbingSpeed", 150)));
properties[_("Acceleration")].SetGroup(_("Walk")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("acceleration")));
properties[_("Deceleration")].SetGroup(_("Walk")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("deceleration")));
properties[_("Max. speed")].SetGroup(_("Walk")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("maxSpeed")));
properties[_("Default controls")]
properties["Acceleration"]
.SetLabel(_("Acceleration"))
.SetGroup(_("Walk"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelAcceleration())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("acceleration")));
properties["Deceleration"]
.SetLabel(_("Deceleration"))
.SetGroup(_("Walk"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelAcceleration())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("deceleration")));
properties["MaxSpeed"]
.SetLabel(_("Max. speed"))
.SetGroup(_("Walk"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixelSpeed())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("maxSpeed")));
properties["IgnoreDefaultControls"]
.SetLabel(_("Default controls"))
.SetValue(behaviorContent.GetBoolAttribute("ignoreDefaultControls")
? "false"
: "true")
.SetType("Boolean");
properties[_("Slope max. angle")].SetGroup(_("Walk")).SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("slopeMaxAngle")));
properties[_("Can grab platform ledges")]
properties["SlopeMaxAngle"]
.SetLabel(_("Slope max. angle"))
.SetGroup(_("Walk"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetDegreeAngle())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("slopeMaxAngle")));
properties["CanGrabPlatforms"]
.SetLabel(_("Can grab platform ledges"))
.SetGroup(_("Ledge"))
.SetValue(behaviorContent.GetBoolAttribute("canGrabPlatforms", false)
? "true"
: "false")
.SetType("Boolean");
properties[_("Automatically grab platform ledges without having to move "
"horizontally")]
properties["CanGrabWithoutMoving"]
.SetLabel(_("Automatically grab platform ledges without having to move "
"horizontally"))
.SetGroup(_("Ledge"))
.SetValue(behaviorContent.GetBoolAttribute("canGrabWithoutMoving", false)
? "true"
: "false")
.SetType("Boolean");
properties[_("Grab offset on Y axis")]
properties["YGrabOffset"]
.SetLabel(_("Grab offset on Y axis"))
.SetGroup(_("Ledge"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetValue(
gd::String::From(behaviorContent.GetDoubleAttribute("yGrabOffset")));
properties[_("Grab tolerance on X axis")]
properties["XGrabTolerance"]
.SetLabel(_("Grab tolerance on X axis"))
.SetGroup(_("Ledge"))
.SetType("Number")
.SetMeasurementUnit(gd::MeasurementUnit::GetPixel())
.SetValue(gd::String::From(
behaviorContent.GetDoubleAttribute("xGrabTolerance", 10)));
properties["useLegacyTrajectory"]
properties["UseLegacyTrajectory"]
.SetLabel(_("Use frame rate dependent trajectories (deprecated, it's "
"recommended to leave this unchecked)"))
.SetGroup(_("Deprecated options (advanced)"))
@@ -105,7 +155,8 @@ PlatformerObjectBehavior::GetProperties(
? "true"
: "false")
.SetType("Boolean");
properties[_("Can go down from jumpthru platforms")]
properties["CanGoDownFromJumpthru"]
.SetLabel(_("Can go down from jumpthru platforms"))
.SetGroup(_("Walk"))
.SetValue(behaviorContent.GetBoolAttribute("canGoDownFromJumpthru", false)
? "true"
@@ -118,44 +169,43 @@ bool PlatformerObjectBehavior::UpdateProperty(
gd::SerializerElement& behaviorContent,
const gd::String& name,
const gd::String& value) {
if (name == _("Default controls"))
if (name == "IgnoreDefaultControls")
behaviorContent.SetAttribute("ignoreDefaultControls", (value == "0"));
else if (name == _("Can grab platform ledges"))
else if (name == "CanGrabPlatforms")
behaviorContent.SetAttribute("canGrabPlatforms", (value == "1"));
else if (name == _("Automatically grab platform ledges without having to "
"move horizontally"))
else if (name == "CanGrabWithoutMoving")
behaviorContent.SetAttribute("canGrabWithoutMoving", (value == "1"));
else if (name == "useLegacyTrajectory")
else if (name == "UseLegacyTrajectory")
behaviorContent.SetAttribute("useLegacyTrajectory", (value == "1"));
else if (name == _("Can go down from jumpthru platforms"))
else if (name == "CanGoDownFromJumpthru")
behaviorContent.SetAttribute("canGoDownFromJumpthru", (value == "1"));
else if (name == _("Grab offset on Y axis"))
else if (name == "YGrabOffset")
behaviorContent.SetAttribute("yGrabOffset", value.To<double>());
else {
if (value.To<double>() < 0) return false;
if (name == _("Gravity"))
if (name == "Gravity")
behaviorContent.SetAttribute("gravity", value.To<double>());
else if (name == _("Max. falling speed"))
else if (name == "MaxFallingSpeed")
behaviorContent.SetAttribute("maxFallingSpeed", value.To<double>());
else if (name == _("Ladder climbing speed"))
else if (name == "LadderClimbingSpeed")
behaviorContent.SetAttribute("ladderClimbingSpeed", value.To<double>());
else if (name == _("Acceleration"))
else if (name == "Acceleration")
behaviorContent.SetAttribute("acceleration", value.To<double>());
else if (name == _("Deceleration"))
else if (name == "Deceleration")
behaviorContent.SetAttribute("deceleration", value.To<double>());
else if (name == _("Max. speed"))
else if (name == "MaxSpeed")
behaviorContent.SetAttribute("maxSpeed", value.To<double>());
else if (name == _("Jump speed"))
else if (name == "JumpSpeed")
behaviorContent.SetAttribute("jumpSpeed", value.To<double>());
else if (name == "jumpSustainTime")
else if (name == "JumpSustainTime")
behaviorContent.SetAttribute("jumpSustainTime", value.To<double>());
else if (name == _("Slope max. angle")) {
else if (name == "SlopeMaxAngle") {
double newMaxAngle = value.To<double>();
if (newMaxAngle < 0 || newMaxAngle >= 90) return false;
behaviorContent.SetAttribute("slopeMaxAngle", newMaxAngle);
} else if (name == _("Grab tolerance on X axis"))
} else if (name == "XGrabTolerance")
behaviorContent.SetAttribute("xGrabTolerance", value.To<double>());
else
return false;

View File

@@ -1592,17 +1592,6 @@ namespace gdjs {
this._currentFallSpeed !== 0
);
}
followCurrentPlatformIfAny(): boolean {
let hasMoved = false;
if (this.isOnFloor()) {
const timeDelta = this.owner.getElapsedTime() / 1000;
const hasMovedX = this._onFloor.followCurrentPlatformOnX(timeDelta);
const hasMovedY = this._onFloor.followCurrentPlatformOnY(timeDelta);
hasMoved = hasMovedX || hasMovedY;
}
return hasMoved;
}
}
/**
@@ -1677,11 +1666,6 @@ namespace gdjs {
}
beforeUpdatingObstacles(timeDelta: float) {
this.followCurrentPlatformOnY(timeDelta);
}
followCurrentPlatformOnY(timeDelta: float): boolean {
let hasMoved = false;
const object = this._behavior.owner;
//Stick the object to the floor if its height has changed.
if (this._oldHeight !== object.getHeight()) {
@@ -1690,7 +1674,6 @@ namespace gdjs {
object.getHeight() +
(object.getY() - object.getDrawableY())
);
hasMoved = true;
}
// Directly follow the floor movement on the Y axis by moving the character.
// For the X axis, we follow the floor movement using `_requestedDeltaX`
@@ -1711,18 +1694,14 @@ namespace gdjs {
// and the platform can go out of the spatial search rectangle
// even though they are next to each other, which means
// that the character will fall.
const floorY = this._floorPlatform!.owner.getY();
const deltaY = floorY - this._floorLastY;
const deltaY = this._floorPlatform!.owner.getY() - this._floorLastY;
if (
deltaY !== 0 &&
Math.abs(deltaY) <=
Math.abs(this._behavior._maxFallingSpeed * timeDelta)
) {
object.setY(object.getY() + deltaY);
this._floorLastY = floorY;
hasMoved = true;
}
return hasMoved;
}
checkTransitionBeforeX() {
@@ -1760,29 +1739,11 @@ namespace gdjs {
beforeMovingX() {
const behavior = this._behavior;
// Shift the object according to the floor movement.
const floorX = this._floorPlatform!.owner.getX();
const deltaX = floorX - this._floorLastX;
behavior._requestedDeltaX += deltaX;
this._floorLastX = floorX;
behavior._requestedDeltaX +=
this._floorPlatform!.owner.getX() - this._floorLastX;
// See `beforeUpdatingObstacles` for the logic for the Y axis.
}
followCurrentPlatformOnX(timeDelta: float): boolean {
let hasMoved = false;
const object = this._behavior.owner;
// Shift the object according to the floor movement.
const floorX = this._floorPlatform!.owner.getX();
const deltaX = floorX - this._floorLastX;
if (deltaX !== 0) {
console.log(deltaX);
object.setX(object.getX() + deltaX);
this._floorLastX = floorX;
hasMoved = true;
}
return hasMoved;
}
checkTransitionBeforeY(timeDelta: float) {
const behavior = this._behavior;
// Go on a ladder

View File

@@ -694,7 +694,7 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isOnFloor()).to.be(true);
expect(object.getY()).to.be.within(140.6297999, 140.6298001);
// The floor following has a 1-frame delay.
// TODO Remove the 1-frame delay
expect(object.getX()).to.be(5);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(6);

View File

@@ -68,7 +68,7 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
runtimeScene.renderAndStepWithEventsFunction(1000 / 60, () => {
platform.setX(platform.getX() + 0.12);
});
// The floor following has a 1-frame delay.
// TODO Remove the 1-frame delay
expect(object.getX()).to.be(0.24);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(0.36);
@@ -258,13 +258,13 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
// The object follow the platform
// The rounding error is probably due to a separate call.
// TODO Try to make it exact or find why
// The floor following has a 1-frame delay.
// TODO Remove the 1-frame delay
expect(object.getY()).to.be.within(
previousPlatformY - object.getHeight() - epsilon,
previousPlatformY - object.getHeight() + epsilon
);
}
// The floor following has a 1-frame delay.
// TODO Remove the 1-frame delay
expect(object.getX()).to.be(0 + 4 * deltaX);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(0 + 5 * deltaX);
@@ -400,13 +400,13 @@ describe('gdjs.PlatformerObjectRuntimeBehavior', function () {
expect(object.getBehavior('auto1').isFalling()).to.be(false);
expect(object.getBehavior('auto1').isMoving()).to.be(false);
// The object must not be inside the platform or it gets stuck
// The floor following has a 1-frame delay.
// TODO Remove the 1-frame delay
expect(object.getY()).to.be.within(
previousPlatformY - object.getHeight() - epsilon,
previousPlatformY - object.getHeight() + epsilon
);
}
// The floor following has a 1-frame delay.
// TODO Remove the 1-frame delay
expect(object.getX()).to.be(0 + 4 * deltaX);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.be(0 + 5 * deltaX);

View File

@@ -480,7 +480,8 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/outlineSize_black.png")
.AddParameter("object", _("Shape Painter object"), "Drawer")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("SetOutlineSize")
.SetGetter("GetOutlineSize");
@@ -493,7 +494,8 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/conditions/outlineSize_black.png")
.AddParameter("object", _("Shape Painter object"), "Drawer")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetFunctionName("GetOutlineSize");
obj.AddExpression("OutlineSize",
@@ -514,7 +516,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/opacity.png")
.AddParameter("object", _("Shape Painter object"), "Drawer")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity (0-255)")))
.SetFunctionName("SetFillOpacity")
.SetGetter("GetFillOpacity");
@@ -527,7 +532,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/conditions/opacity.png")
.AddParameter("object", _("Shape Painter object"), "Drawer")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity to compare to (0-255)")))
.SetFunctionName("GetFillOpacity");
obj.AddExpression("FillOpacity",
@@ -547,7 +555,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/opacity.png")
.AddParameter("object", _("Shape Painter object"), "Drawer")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity (0-255)")))
.SetFunctionName("SetOutlineOpacity")
.SetGetter("GetOutlineOpacity");
@@ -560,7 +571,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/conditions/opacity.png")
.AddParameter("object", _("Shape Painter object"), "Drawer")
.UseStandardRelationalOperatorParameters("number")
.UseStandardRelationalOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity to compare to (0-255)")))
.SetFunctionName("GetOutlineOpacity");
obj.AddExpression("OutlineOpacity",
@@ -605,7 +619,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/scale24_black.png",
"res/actions/scale_black.png")
.AddParameter("object", _("Object"), "Drawer")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddExpressionAndConditionAndAction("number",
@@ -616,7 +633,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
_("Size"),
"res/actions/scaleWidth24_black.png")
.AddParameter("object", _("Object"), "Drawer")
.UseStandardParameters("number")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddExpressionAndConditionAndAction("number",
@@ -627,7 +647,10 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
_("Size"),
"res/actions/scaleHeight24_black.png")
.AddParameter("object", _("Object"), "Drawer")
.UseStandardParameters("number")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
obj.AddAction("FlipX",
@@ -678,7 +701,8 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/scaleWidth24_black.png",
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Drawer")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction("Height",
@@ -689,7 +713,8 @@ void DeclarePrimitiveDrawingExtension(gd::PlatformExtension& extension) {
"res/actions/scaleHeight24_black.png",
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Drawer")
.UseStandardOperatorParameters("number")
.UseStandardOperatorParameters("number",
gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
obj.AddAction(

View File

@@ -108,7 +108,7 @@ void ShapePainterObjectBase::SetFillColor(unsigned int r,
fillColorB = b;
}
void ShapePainterObjectBase::SetFillOpacity(float val) {
void ShapePainterObjectBase::SetFillOpacity(double val) {
if (val > 255)
val = 255;
else if (val < 0)
@@ -128,7 +128,7 @@ void ShapePainterObjectBase::SetOutlineColor(unsigned int r,
outlineColorB = b;
}
void ShapePainterObjectBase::SetOutlineOpacity(float val) {
void ShapePainterObjectBase::SetOutlineOpacity(double val) {
if (val > 255)
val = 255;
else if (val < 0)

View File

@@ -26,11 +26,11 @@ class GD_EXTENSION_API ShapePainterObjectBase {
ShapePainterObjectBase();
virtual ~ShapePainterObjectBase(){};
inline void SetOutlineSize(float size) { outlineSize = size; };
inline float GetOutlineSize() const { return outlineSize; };
inline void SetOutlineSize(double size) { outlineSize = size; };
inline double GetOutlineSize() const { return outlineSize; };
void SetOutlineOpacity(float val);
inline float GetOutlineOpacity() const { return outlineOpacity; };
void SetOutlineOpacity(double val);
inline double GetOutlineOpacity() const { return outlineOpacity; };
void SetOutlineColor(unsigned int r, unsigned int v, unsigned int b);
inline unsigned int GetOutlineColorR() const { return outlineColorR; };
@@ -41,8 +41,8 @@ class GD_EXTENSION_API ShapePainterObjectBase {
*/
void SetOutlineColor(const gd::String& color);
void SetFillOpacity(float val);
inline float GetFillOpacity() const { return fillOpacity; };
void SetFillOpacity(double val);
inline double GetFillOpacity() const { return fillOpacity; };
void SetFillColor(unsigned int r, unsigned int v, unsigned int b);
inline unsigned int GetFillColorR() const { return fillColorR; };

View File

@@ -39,7 +39,9 @@ void DeclareTextEntryObjectExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/textentryicon.png")
.AddParameter("object", _("Object"), "TextEntry")
.UseStandardOperatorParameters("string")
.UseStandardOperatorParameters(
"string",
gd::ParameterOptions::MakeNewOptions().SetDescription(_("Text")))
.SetFunctionName("SetString")
.SetGetter("GetString");
@@ -52,7 +54,9 @@ void DeclareTextEntryObjectExtension(gd::PlatformExtension& extension) {
"CppPlatform/Extensions/textentryicon.png")
.AddParameter("object", _("Object"), "TextEntry")
.UseStandardRelationalOperatorParameters("string")
.UseStandardRelationalOperatorParameters(
"string",
gd::ParameterOptions::MakeNewOptions().SetDescription(_("Text to compare to")))
.SetFunctionName("GetString");
obj.AddAction(

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