Compare commits

...

247 Commits

Author SHA1 Message Date
Clément Pasteau
ca220d8fe5 Fix copying points & masks when editing sprite too (#5532)
Do not show in changeloc
2023-08-02 16:58:49 +02:00
github-actions[bot]
9971702ec9 Update translations (#5529) 2023-08-02 14:21:57 +02:00
Clément Pasteau
e48f14b753 Bump IDE version to 169 (#5530)
Do not show in changelog
2023-08-02 14:21:20 +02:00
Clément Pasteau
ce046c0b99 Fix setting up points & collision masks according to object animation settings (#5527)
* Adding a new sprite in a new animation will now correctly copy points and collision masks defined in others if "sharing with all animations" is toggled
2023-08-02 14:10:37 +02:00
Florian Rival
e29cb462e1 Add mention to using git for projects in the project properties dialog (#5528) 2023-08-02 14:02:20 +02:00
github-actions[bot]
aee05affd0 Update translations [skip ci] (#5526)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-08-02 12:03:59 +02:00
Clément Pasteau
f95d197634 Fix a bug where renaming project elements wouldn't work when an action is using the default layer (#5524) 2023-08-02 11:27:39 +02:00
github-actions[bot]
075cc5a7aa Update translations [skip ci] (#5513)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-07-31 17:18:10 +02:00
Clément Pasteau
56c2aa0dc6 Fix collision mask when adding new sprites with default, full image mask (#5523) 2023-07-31 17:17:39 +02:00
Clément Pasteau
fa003374ba Fix automatic collision mask on multiple sprites addition (#5521)
And on piskel edition
2023-07-31 11:29:11 +02:00
github-actions[bot]
ca27a946a1 Update translations [skip ci] (#5509)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-07-28 17:57:49 +02:00
Clément Pasteau
2845c403f9 Prevent saving in the same folder as GDevelop's executable (#5510)
* Some users have mentioned their project disappear after a GDevelop's update. This is a safe-guard to avoid projects from being saved in the executable folder, as it gets deleted on every update.
2023-07-28 17:57:22 +02:00
Clément Pasteau
9cc2e2987e Allow navigating to packs and bundles directly from banners (#5512) 2023-07-28 17:07:12 +02:00
Clément Pasteau
b9d6336dc7 Rework the asset store to show bundles and owned packs first (#5504)
* Also slightly improve the size of dialogs on large screens
2023-07-28 10:39:11 +02:00
D8H
c2ad00ed6c No longer show a tooltip when a behavior has no author (#5507)
Don't show in changelog
2023-07-28 08:58:07 +02:00
Clément Pasteau
2d1845f0b8 run actions only on push, not on new tags (#5508)
Do not show in changelog
2023-07-27 16:55:54 +02:00
D8H
b5f0758f4d Add an information button on behaviors (#5505)
* Show authors on hovering
* Open extension details on click
2023-07-27 14:51:41 +02:00
Clément Pasteau
1e2ffe5d15 Allow downloading artefacts from a commit hash (#5506)
Do not show in changelog
2023-07-27 14:20:01 +02:00
github-actions[bot]
c887769c0a Update translations (#5474)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-07-27 14:14:51 +02:00
Clément Pasteau
dc1ac1e094 Bump to 5.2.168 (#5502) 2023-07-27 11:53:24 +02:00
Clément Pasteau
4b1ceeb642 Fix adapting collision mask to new sprites (#5500) 2023-07-27 09:20:31 +02:00
supertree-wook
e5d92fbf43 Upgrade missing cmake (#5450)
Only show in developer changelog
2023-07-26 22:54:40 +02:00
Florian Rival
c323fea5bd Simplify display of leaderboard entries (#5501)
Don't show in the changelog
2023-07-26 22:14:52 +02:00
D8H
32f0fe9051 Fix some typos in the new behavior dialog (#5503) 2023-07-26 22:14:35 +02:00
Clément Pasteau
be74d3efa6 Prevent installing too many assets at a time (#5495)
* Installing more than 100 assets from a pack can cause failures on some low connections
2023-07-25 09:09:23 +02:00
D8H
8969c9af8c Show extensions from the store at the end of the behavior list (#5476) 2023-07-24 17:50:39 +02:00
D8H
15cac278d6 Separate 2D and 3D effects in 2 lists (#5484) 2023-07-24 11:02:06 +02:00
Florian Rival
9e8a15547d Improve leaderboard score handling (#5481)
* Leaderboards will now display the score of the player, if a score was just sent before displaying the leaderboard.
* If the score is being sent, the leaderboard will wait for it to be sent before showing the leaderboard.
* Important change: a player name can now be empty when a score is sent. In this case, the leaderboard will auto-generate a name.
* Leaderboard administration was improved to allow to customise the prefix used to generate automatically player names (when no name is entered by the player). You can also now choose to disallow any custom player name to prevent abuse (in this case, all non-connected player names will be auto-generated)
* Allow to use custom CSS to fully customize the leaderboard - only for business users (reach out if you need this).

Co-authored-by: AlexandreS <32449369+AlexandreSi@users.noreply.github.com>
2023-07-18 16:20:45 +02:00
supertree-wook
ed74a49aa3 Remove unnecessary dependencies in the Editor and GDJS (#5469)
Only show in developer changelog
2023-07-18 14:29:19 +02:00
D8H
6ef5d0c326 Add an action to insert a function parameter (#5483) 2023-07-18 12:29:14 +02:00
AlexandreS
5f871e2643 Fix Safari not being able to open .glb files on iPad/iPhone (#5479) 2023-07-18 09:24:18 +02:00
AlexandreS
4f65fa0d82 Fix: Avoid purchasing twice the same asset pack (#5482) 2023-07-17 17:28:56 +02:00
AlexandreS
4d1d763bd9 Fix keyboard undesired openings on mobile (#5478) 2023-07-13 17:16:37 +02:00
AlexandreS
3286722b6a Enable search and replace in For each object events and Javascript events (#5477) 2023-07-13 17:09:00 +02:00
AlexandreS
656255a662 Bump newIDE version (#5475) 2023-07-12 11:56:23 +02:00
AlexandreS
ea7b7a778e Improve messages visibility in collision masks dialog (#5473)
Don't show in changelog
2023-07-12 10:00:37 +02:00
AlexandreS
9b6de5affd Add possibility to subscribe to a startup plan from the profile (#5472) 2023-07-11 16:31:25 +02:00
Clément Pasteau
0c03659314 Fix Node.js 18 compatibility, upgrade to create-react-app v5 and make mac build universal (#5270)
* only show in developer changelog
2023-07-11 15:03:33 +02:00
github-actions[bot]
6b08c0f033 Update translations [skip ci] (#5466)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-07-11 14:10:20 +02:00
AlexandreS
a1dcf03a5b Fix the editor hanging when opening a scene with hundreds of instances of 3D model objects (#5470) 2023-07-10 17:31:29 +02:00
D8H
556d13c881 Fix the community warning that wasn't showing up in documentation (#5468)
Don't show in changelog
2023-07-09 19:31:28 +02:00
D8H
0d6c42a9bf Filter private actions and conditions from the reference page (#5467)
* Don't show in changelog
2023-07-07 14:09:53 +02:00
D8H
690ce16ab4 Add a listing of actions and conditions in community extension reference pages (#5464) 2023-07-07 10:50:47 +02:00
github-actions[bot]
5f51a5e465 Update translations [skip ci] (#5465)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-07-06 09:51:54 +02:00
AlexandreS
b7521de138 Add startup plan support in user profile components (#5462) 2023-07-05 09:39:40 +02:00
AlexandreS
acea6fc595 Fix SetPosition action that was missing parenthesis creating math errors (#5458) 2023-07-03 12:07:10 +02:00
github-actions[bot]
d8107fe3d5 Update translations [skip ci] (#5457)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-07-03 11:31:55 +02:00
Clément Pasteau
b40b95be99 Remove jimp, use Canvas for image manipulation (#5454)
Do not show in changelog
2023-07-03 11:21:28 +02:00
AlexandreS
6644525dd0 Remove former fix that triggered a bug where values were not persisted after editing expression in event sheet (#5455) 2023-07-03 10:28:43 +02:00
github-actions[bot]
56e66d1c5a Update translations [skip ci] (#5452)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-06-30 15:51:19 +02:00
Clément Pasteau
90d8afb5a0 Calculate Sprite collision masks automatically (#5447)
* Sprites now have an option to calculate their collision mask automatically, based on the first image of their first animation
* The generated collision mask consists of the biggest rectangle possible, encapsulating the image and avoiding transparent pixels
* This option is enabled by default for all new sprites, and can be disabled to create a custom collision mask like before
* When enabled, the mask will adapt automatically when the first image is updated
2023-06-30 15:33:50 +02:00
AlexandreS
d4db61a595 Fix autofocus of searchbar on tablets in landscape (#5451) 2023-06-29 22:40:06 +02:00
D8H
90413b842d Move event-based extension metadata generation from newIDE to GDJS (#5255) 2023-06-29 20:18:51 +02:00
github-actions[bot]
43c788acbf Update translations [skip ci] (#5444)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-06-29 11:29:17 +02:00
supertree-wook
ee22b2e4b1 Upgrade CMake minimum version and improve CMake code (#5446)
Only show in developer changelog
2023-06-28 12:01:05 +02:00
AlexandreS
007d56e946 Display the scene editors more conveniently on mobile (#5441) 2023-06-26 18:07:23 +02:00
AlexandreS
577c4adb14 Fix images selectors not updating on Box 3D editor after an image has been created with Piskel (#5442) 2023-06-26 17:53:23 +02:00
AlexandreS
7f17720ff3 Fix: Do not close popover when releasing text selection click outside of popover (#5443) 2023-06-23 16:51:24 +02:00
github-actions[bot]
288db1c941 Update translations [skip ci] (#5434)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-06-23 16:32:13 +02:00
Florian Rival
2496fc3eef Revert "Add extension to support Steamworks integration of games made with GDevelop (#5401)" (#5438)
This reverts commit 3c43f28966.
2023-06-22 12:58:00 +02:00
AlexandreS
b43d5ec425 Improve copy regarding faces orientation of the 3D box (#5432) 2023-06-22 09:27:06 +02:00
Arthur Pacaud
3c43f28966 Add extension to support Steamworks integration of games made with GDevelop (#5401) 2023-06-22 09:16:20 +02:00
Clément Pasteau
a3f7c5782e Fix creating project properties from template to be set properly (#5436) 2023-06-22 09:14:46 +02:00
AlexandreS
8dec6dfa28 Bump newIDE version (#5433) 2023-06-22 09:13:01 +02:00
D8H
4eb49bdeb2 Use the object type for 3D model assets (#5431)
* Don't show in changelog
2023-06-21 20:14:46 +02:00
Clément Pasteau
813cadbd6e Improve prompt generator to hint on game type for better results (#5430)
Do not show in changelog
2023-06-21 16:04:01 +02:00
github-actions[bot]
58dd2c1a7b Update translations [skip ci] (#5428)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-06-21 15:57:23 +02:00
AlexandreS
104c27ebc8 Improve guided lessons framework (#5426)
- Improve tooltip placement
- Fix z order setting step sometimes blocked
2023-06-21 14:48:39 +02:00
D8H
318099504c Handle 3D models in the asset store (#5427) 2023-06-21 14:46:34 +02:00
supertree-wook
8851be03a3 Fix typos here and there (#5253)
Only show in developer changelog
2023-06-21 12:41:17 +02:00
github-actions[bot]
a9a126ab0d Update translations [skip ci] (#5422)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-06-21 11:20:33 +02:00
AlexandreS
19e46fedc8 Fix scroll on autocompletion displayer on mobile (#5425) 2023-06-21 11:12:07 +02:00
Arthur Pacaud
ff987a0751 Suggest the authenticated user's username by default in inputs showing usernames (#5423) 2023-06-21 08:21:44 +02:00
AlexandreS
0c0ab65b1a Display more info on missing action/condition placeholder (#5415) 2023-06-20 09:43:18 +02:00
AlexandreS
52a5908d7e Rename 3D editor preference to enable 3D editor for everyone (#5421) 2023-06-20 09:37:22 +02:00
github-actions[bot]
49926a89a2 Update translations [skip ci] (#5417)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-06-20 09:25:08 +02:00
D8H
b63b91f33d Fix out-of-limits dragging of animation in sprite editor (#5413)
Also:
- Show duplicated animation name errors directly on the field instead of a popup

---------

Co-authored-by: AlexandreSi <32449369+AlexandreSi@users.noreply.github.com>
2023-06-19 17:13:26 +02:00
supertree-wook
67ea361416 Remove duplicate cache registration code (#5411) 2023-06-16 17:37:58 +02:00
github-actions[bot]
3b9078c6b3 Update translations [skip ci] (#5408)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-06-16 14:12:34 +02:00
D8H
3d9e3f997e Clear 3D animation name errors when they are moved (#5416) 2023-06-16 12:27:40 +02:00
D8H
3c34866faa Fix the dragging of the first 3D animation (#5414)
* Don't show in changelog
2023-06-15 16:42:51 +02:00
AlexandreS
69cd2784c4 Add alert message when changing the 3D rendering in scene editor (#5412)
Do not show in changelog
2023-06-15 09:27:37 +02:00
AlexandreS
5b7e419a41 Improve user experience with users autocomplete (#5410) 2023-06-14 19:03:37 +02:00
AlexandreS
7773460d35 Autodetect webgl support to define 3D instances showing preference (#5409)
Don't show in changelog
2023-06-14 15:30:27 +02:00
AlexandreS
9262266480 Fix wrongly set flag (#5406)
Do not show in changelog
2023-06-14 14:59:42 +02:00
AlexandreS
84f2b4ca68 Bump newIDE version (#5407) 2023-06-14 14:58:38 +02:00
AlexandreS
19ae7a378c Prevent empty Algolia search at app start (#5405)
only show in developer changelog
2023-06-14 14:57:47 +02:00
github-actions[bot]
f9ca330add Update translations [skip ci] (#5403) 2023-06-14 14:10:30 +02:00
D8H
5ef990ac7d Fix 3D model positions in the 2D editor (#5404)
* Don't show in changelog
2023-06-14 11:34:26 +02:00
D8H
8099820729 Fix double dot in descriptions (#5402)
* Don't show in changelog.
2023-06-14 10:20:25 +02:00
github-actions[bot]
df556f20e9 Update translations [skip ci] (#5399)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-06-14 09:37:57 +02:00
Clément Pasteau
2c8f2ab58d New field to create a project from a prompt (#5395)
* New Experimental field in the Create Project Dialog allowing to enter a game description and get a game generated by the AI
2023-06-13 17:15:06 +02:00
D8H
20c3d62c90 Add the support for animations on 3D models (#5302)
- Breaking change: fix 3D models that were mirrored on Y axis.
  - In case some models look upside-down, they can be fixed by adding 180° to the "Rotation around Y axis" property.
- Handle custom origin and center.
2023-06-13 12:42:46 +02:00
github-actions[bot]
0a28981c74 Update translations [skip ci] (#5388)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-06-13 10:19:16 +02:00
D8H
c8bb24475c Use the project name when creating a new project file locally (#5396) 2023-06-12 15:17:41 +02:00
AlexandreS
81bce61783 Introduce Education plan (#5382)
It is now possible to subscribe to an education plan to provide gold subscriptions to a pool of anonymised users.
2023-06-12 10:32:21 +02:00
Florian Rival
71d1b6aa1f Refactor handling of prices of asset packs (#5393)
Don't show in changelog
2023-06-11 20:33:42 +02:00
Clément Pasteau
c41974c24b Update fling game (#5391)
Do not show in changelog
2023-06-09 17:52:08 +02:00
D8H
3bee88c6cd Handle 3D models compressed with Draco (#5390) 2023-06-09 17:49:46 +02:00
D8H
4c874dfb7e Automatically set a default operator when adding a new condition or action (#5389) 2023-06-09 14:59:04 +02:00
D8H
65f499f24e Fix the alert message about 3d objects without any light (#5387)
* Don't show in changelog
2023-06-09 10:30:20 +02:00
github-actions[bot]
3265bf7fb4 Update translations [skip ci] (#5386)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-06-09 10:27:25 +02:00
AlexandreS
5a437dea4e Fix markdown tables rendering (for extension description for instance) (#5384) 2023-06-09 10:00:06 +02:00
github-actions[bot]
19b576e8cc Update translations [skip ci] (#5383)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-06-08 16:07:35 +02:00
Clément Pasteau
67747e458e Add new guided lesson: Create a 3D Box (#5376) 2023-06-08 11:37:29 +02:00
github-actions[bot]
260c2b9c8f Update translations [skip ci] (#5380)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-06-08 10:30:14 +02:00
D8H
255ef1d8ef Add an antialising setting for 3D (#5381) 2023-06-08 09:57:34 +02:00
D8H
53c633c646 Add an hemisphere light effect for 3D layers (#5379) 2023-06-07 17:21:26 +02:00
github-actions[bot]
cec67a91d4 Update translations [skip ci] (#5370)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-06-07 16:59:32 +02:00
Clément Pasteau
4408dfe59d Fix initializing received assets correctly when user is not authenticated (#5374)
* Asset pack web links were not working because of this
2023-06-07 16:59:08 +02:00
Clément Pasteau
c4274d2fc4 Fix default depth of 3D object on scene being correctly initialised (#5378) 2023-06-07 15:13:04 +02:00
Clément Pasteau
b0103f31b7 Fix showing cancel subscription button for legacy plans (#5371) 2023-06-07 10:23:39 +02:00
AlexandreS
18905890d4 Fix dialogue tree loading from scene variable action sentence (#5372) 2023-06-06 19:01:05 +02:00
D8H
6858e0fb59 Render 3D in linear color space, upgrade to Three.js 1.152.0 (#5360)
* 3D model objects will look brighter. Light intensity may need to be reduced.
2023-06-06 12:28:46 +02:00
github-actions[bot]
cf595a7d7d Update translations [skip ci] (#5364)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-06-05 13:42:31 +02:00
Florian Rival
e681d27bb8 Allow to use the 3D editor with a toggle in the preferences 2023-06-03 14:19:00 +02:00
AlexandreS
8941e04390 Fix color 3D model color rendering being darker than the original texture (#5368) 2023-06-02 15:46:27 +02:00
AlexandreS
e186681f39 Display Z coordinate in instance tooltip for instances of 3D objects
- Also fixes some weird behavior around the "Custom size" checkbox in instance properties
2023-06-01 16:12:34 +02:00
Florian Rival
a578fa32e9 Add support for 3D objects in editor (#5357) 2023-06-01 12:17:20 +02:00
supertree-wook
6b40e8309c Fix some extension descriptions in the wiki not having properly formatted lists (#5365) 2023-06-01 11:56:14 +02:00
supertree-wook
5ff51351af Fix typo in description of StrFindLastFrom (#5363) 2023-05-31 09:57:13 +02:00
github-actions[bot]
d66e4e0001 Update translations [skip ci] (#5351)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-05-30 18:02:33 +02:00
Clément Pasteau
2184eaf70b Fix sprite images selection when opening up the options menu (#5359)
* Fix an issue where opening the options menu of a sprite of a non-selected image would not take it into account for the actions.
2023-05-30 11:18:23 +02:00
AlexandreS
29fc0598f6 Start over from the suffix number when generating a new name (#5355) 2023-05-26 11:36:51 +02:00
AlexandreS
a7760e975a Bump newIDE version (#5353) 2023-05-25 16:41:28 +02:00
AlexandreS
e2397cb0a4 Make sure dialogs are displayed full screen on mobiles landscape-oriented (#5350) 2023-05-25 14:54:45 +02:00
Aurélien Vivet
24ff670886 Make more visible the actions and condition to Save and Load the of a game.
- Replace the actions and conditions "Write a value" by "Save a value", and "Read a value" by "Load a value".
2023-05-25 13:39:06 +01:00
github-actions[bot]
d24b7497c9 Update translations [skip ci] (#5341) 2023-05-25 14:29:25 +02:00
supertree-wook
0ecaa342f9 Fix and improve GithHb action to see translations with coverage deltas (#5348) 2023-05-25 12:59:14 +02:00
D8H
141ac87c6e Convert animation list to functional component (#5342)
* Don't show in changelog
2023-05-25 09:35:43 +02:00
Aurélien Vivet
057e6dcfed Fix typos (#5347) 2023-05-24 22:41:49 +02:00
D8H
9c69c90a66 Fix object instance dimension values editor (#5346)
* Also fix default value for the "3D world top" property of directional lights
2023-05-24 21:21:35 +02:00
AlexandreS
4df6ecc654 Fix 3D model object not showing in preview when working on the web or mobile app (#5344) 2023-05-24 20:01:59 +02:00
AlexandreS
c106d05098 Use the native selector to select an object on mobile (#5343)
This should fix issues happening on mobile where the keyboard opens when one wants to select an object from the parameter of an event
2023-05-24 17:26:27 +02:00
Clément Pasteau
f3f426e949 Update icon for mac (#5340)
Don't show in changelog
2023-05-23 16:47:25 +02:00
github-actions[bot]
52d0ed1217 Update translations [skip ci] (#5337) 2023-05-23 16:04:49 +02:00
AlexandreS
511138269d Bump newIDE version (#5339) 2023-05-23 15:46:23 +02:00
AlexandreS
22dda6194c Add QR code when doing a network preview to facilitate accessing the testing url (#5338) 2023-05-23 15:45:20 +02:00
github-actions[bot]
aa2ef39f32 Update translations [skip ci] (#5335)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-05-23 14:23:06 +02:00
Clément Pasteau
a744b88c5c Rework objectGroupsContainer to contain references, avoiding possible wrong memory accesses (#5329)
Do not show in changelog
2023-05-23 14:22:39 +02:00
D8H
2847601fc5 Add an alert when event-functions only call themselves (#5324) 2023-05-23 12:09:56 +02:00
D8H
bfbdf1cd3f Fix outline style when drawing a path with the shape painter (#5336) 2023-05-23 10:33:53 +02:00
Clément Pasteau
ed1694a818 Update GitHub actions (#5279)
Only show in developer changelog

Co-authored-by: supertree-wook <phk09242@supertree.co>
2023-05-23 10:24:52 +02:00
AlexandreS
0ee121c014 Add a few missing things following 3D release (#5328)
- Restore Debug draw action in games with 3D
- Fix inspector not working on 3D objects with Z = 0
- Use magenta box when no model is specified for 3D model objects
- Add missing default names for 2 new 3D objects
2023-05-23 10:21:09 +02:00
D8H
312e96a881 Force the expression mode for parameter fields within an extension (#5318) 2023-05-23 10:00:42 +02:00
D8H
c169c5037a Use instance default size as default custom size (#5334) 2023-05-23 09:41:43 +02:00
github-actions[bot]
a82ae304a0 Update translations [skip ci] (#5310)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-05-23 09:17:53 +02:00
AlexandreS
adb30c5105 Fix default game slug on gd.games not long enough creating confusing errors (#5333) 2023-05-22 17:53:39 +02:00
Clément Pasteau
aad11f2518 Fix object group duplication crashing the app (#5331) 2023-05-22 16:11:15 +02:00
AlexandreS
737d389493 Prevent creating a global group with the same name as a default group and vice versa (#5332) 2023-05-22 16:05:13 +02:00
Clément Pasteau
4b071fbf17 Fix pixi js version (#5330)
Do not show in changelog
2023-05-22 15:48:10 +02:00
AlexandreS
982a0c6e53 Fix Z position tween not working on 3D model objects
Also fixes a missing icon for 3D model resource in the resources tab of the project
2023-05-22 09:55:36 +02:00
AlexandreS
91adaac722 Fix random color used in transparent sprites in 2D+3D rendering (#5314) 2023-05-19 17:39:17 +02:00
Clément Pasteau
138a7c9abe Fix format (#5313)
Don't show in changelog
2023-05-19 14:48:03 +02:00
AlexandreS
c7099d694e Improve build card name editing UX (#5312) 2023-05-19 14:47:38 +02:00
D8H
fde1039707 Fix the isCameraRotatedIn3D condition. (#5311)
Do not show in changelog
2023-05-19 12:13:40 +02:00
D8H
73e087936a Fix mouse and multitouch controls when 3D cameras are rotated (#5309) 2023-05-19 11:37:55 +02:00
AlexandreS
260fd5949e Upgrade posthog-js [skip ci] (#5308)
Only show in developer changelog
2023-05-19 11:29:17 +02:00
github-actions[bot]
a4939181a5 Update translations [skip ci] (#5307)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-05-19 11:12:15 +02:00
AlexandreS
cab56451ff Bump newIDE version (#5306) 2023-05-19 10:12:22 +02:00
github-actions[bot]
7b32bbacd6 Update translations [skip ci] (#5300) 2023-05-19 10:02:01 +02:00
AlexandreS
a15707d655 Use correct reference to layer (#5305)
[skip-ci]
2023-05-19 10:00:58 +02:00
Aurélien Vivet
714a9f1198 Add a condition to check if a scene exists (#5297) 2023-05-19 09:24:15 +02:00
AlexandreS
2a91c54b0e Remove forgotten ref (#5304)
Don't show in changelog
2023-05-18 17:33:31 +02:00
Florian Rival
3272b8eda7 Fix 2D rendering sometimes occluding/cutting semi transparent 3D objects 2023-05-18 16:58:42 +02:00
AlexandreS
cd432a22b6 Fix crash when working with instances in the scene editor (#5303) 2023-05-18 16:28:19 +02:00
AlexandreS
9ac483156e Unsubscribe effects and asynchronous tasks (#5301)
Only show in developer changelog
2023-05-17 17:44:18 +02:00
AlexandreS
d0f39027af Slightly lighten project file when lots of comments are present in the events sheets (#5299) 2023-05-17 16:45:19 +02:00
github-actions[bot]
5d8a59533d Update translations [skip ci] (#5294)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-05-17 14:48:23 +02:00
D8H
243a72008b Fix a key exception in the 3D model object editor (#5298)
* Don't show in changelog
2023-05-17 14:39:10 +02:00
Florian Rival
e56cdac96a Fix 3D rendering after loading a scene (#5296) 2023-05-17 13:12:27 +02:00
AlexandreS
cf374737fc Add support for built-in 3D games (#5285)
* This provides new 3D objects: 3D Box (perfect to create walls, floors, or billboards) and 3D Model (to import objects created in a 3D modeling app).
* 2D and 3D can be mixed in a same game. Each layer of a game can contain 2D objects, 3D objects or a mix of both.
* This allows to build 2D games, 2.5D games and full 3D games: platformers, racing games, FPS, hyper casual games. It's easy to start adding 3D objects to an existing 2D game.
* You can set up a light by adding an ambient light and/or directional light in the effects of a 3D layer. 3D objects can be configured to react to light or ignore it.
* In the future, support for 3D objects will be improved: light objects, animations, etc...
2023-05-16 17:37:49 +02:00
Florian Rival
3d043f5264 Update the GDevelop app icon on web and desktop (#5295) 2023-05-16 16:21:02 +02:00
AlexandreS
032f53e4e3 Bump newIDE version (#5293) 2023-05-16 10:34:20 +02:00
github-actions[bot]
f68ae4b8d8 Update translations [skip ci] (#5282) 2023-05-16 09:37:57 +02:00
Clément Pasteau
fa40381fb4 Fix design of login & register (#5280)
Do not show in changelog
2023-05-15 09:55:44 +02:00
Florian Rival
544b6243ba Add some tooltips in the Events Sheet (#5290) 2023-05-14 21:01:47 +02:00
supertree-wook
0a03cbb89c Add support for mouse "Forward" and "Back" buttons (#5278) 2023-05-13 16:52:30 +02:00
supertree-wook
c00d75f047 Fix typo in comments and message strings (#5287) 2023-05-12 22:20:27 +02:00
Aurélien Vivet
5dce0684f5 Fix typo (#5284)
Do not show in changelog
2023-05-12 17:47:26 +02:00
D8H
cb44999538 Fix extension refresh on a new project. (#5283)
Do not show in changelog
2023-05-12 14:12:36 +02:00
D8H
4a9de2edf3 Fix the tile map scale action (#5281)
* Operators +=, -=, *= and /= were making previews crash.
2023-05-11 18:00:52 +02:00
github-actions[bot]
8c3728f8b7 Update translations [skip ci] (#5274)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-05-10 10:36:09 +02:00
Clément Pasteau
212c58f67c Fix TextInput having extra margins on iOS (#5277) 2023-05-09 10:35:54 +02:00
github-actions[bot]
f5d89c66ea Update translations [skip ci] (#5271)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-05-04 09:22:40 +02:00
supertree-wook
8fb139ff63 Rename the readme and license files to match standard (#5272)
Do not show in changelog
2023-05-04 09:22:12 +02:00
Clément Pasteau
0c0fb5da1c Fix generated .exe not working if the project name contains special characters (#5254) 2023-05-03 11:48:17 +02:00
github-actions[bot]
65a33589c0 Update translations [skip ci] (#5251)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2023-05-02 09:37:54 +02:00
supertree-wook
7ec5a95de8 Improve bug report template on GitHub (#5261)
Do not show in changelog
2023-05-02 09:37:01 +02:00
Aurélien Vivet
26289eec99 Fix typo (#5263)
Don't show in the changelog
2023-05-02 09:36:21 +02:00
Aurélien Vivet
cc0a01bbdb Add an action to focus a text input object (#5268)
* Useful to let the player type something without having them manually clicking/touching the input on the screen.
2023-05-01 21:21:57 +02:00
supertree-wook
a0fb289aaf Update to the new forum URL in some part of the interface (#5264) 2023-04-28 13:13:55 +02:00
D8H
94045aec91 Fix typo in comments and message strings (thanks @st-Wook!) (#5262)
Co-authored-by: supertree-wook <phk09242@supertree.co>
2023-04-28 11:58:51 +02:00
supertree-wook
b70d4c54c1 Improve bug report template on GitHub (#5259)
Only show in developer changelog
2023-04-26 14:24:45 +02:00
Aurélien Vivet
f269b820fc Add 2 expressions for the Tiled Sprite to get X & Y offset of the displayed image. (#5252) 2023-04-25 10:45:59 +02:00
Clément Pasteau
f91bde1fca Limit bio and username size (#5257)
Do not show in changelog
2023-04-25 10:25:55 +02:00
AlexandreS
73ac71dadf Add possibility to open events context menu on iOS devices (#4793) 2023-04-21 16:54:26 +02:00
AlexandreS
52fcf52ecc Prevent loss of focus when editing the value of an object variable in the instance properties panel (#5247) 2023-04-21 13:39:56 +02:00
supertree-wook
55c7c4e8bf Change Bug report issue template to Github Forms (#5250) 2023-04-21 10:35:14 +02:00
github-actions[bot]
d6a15d4090 Update translations [skip ci] (#5241)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-04-21 09:46:29 +02:00
supertree-wook
21a87daf64 Clean markdown files and fix typos (#5248)
Only show in develop changelog
2023-04-20 16:22:46 +02:00
AlexandreS
c712ab3163 fix: Correctly detect project manager open to fix some stall guided lessons (#5246) 2023-04-20 13:34:54 +02:00
AlexandreS
6c27c3dcf8 Improve command palette on mobile (#5249) 2023-04-20 13:34:09 +02:00
AlexandreS
f8de6c2ea9 Fix resource opening on iOS and opening of urls (#5245) 2023-04-19 14:10:20 +02:00
AlexandreS
b2e8c23944 Add text field to search in wiki on home page learn section (#5243) 2023-04-19 12:29:17 +02:00
AlexandreS
bfc6a69d77 Decrease checkbox padding to have the same appearance as small icon buttons (#5242)
Don't show in changelog
2023-04-18 15:42:52 +02:00
D8H
3abf81fda2 Add a grab tool to the collision mask and points editors (#5235)
* It also fixes the Physics2 polygon editor that wasn't refreshed when dragging a vertex.
2023-04-18 12:19:43 +02:00
D8H
4caef9c7e6 Add an special object parameter to handle object creation in extensions (#5239)
* It allows extension users to apply actions to the created objects.
2023-04-18 09:55:19 +02:00
github-actions[bot]
f9edfdef72 Update translations [skip ci] (#5233)
Co-authored-by: Bouh <Bouh@users.noreply.github.com>
2023-04-17 10:13:26 +02:00
DaddyPluM
4e0e4b9184 Rename license.txt to license.md (#4783)
Don't show in the changelog
2023-04-15 16:00:16 +02:00
Clément Pasteau
908926bf73 Allow deleting your account from the profile (#5232) 2023-04-13 17:18:49 +02:00
github-actions[bot]
2ba81cc7d6 Update translations [skip ci] (#5231)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-04-13 14:06:56 +02:00
D8H
e77e1fb840 Allow event extensions to declare variable parameters (#5220) 2023-04-13 13:48:47 +02:00
D8H
f0f47ca2f0 Set collision mask zoom bounds relatively to the default zoom (#5229) 2023-04-13 13:48:10 +02:00
github-actions[bot]
07920fda9f Update translations [skip ci] (#5230)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-04-13 12:20:43 +02:00
D8H
48e4447212 Add a button to report extension issues (#5224) 2023-04-13 12:19:59 +02:00
Clément Pasteau
b69dcafcc6 Improve errors when registering game with translations (#5216) 2023-04-13 12:03:08 +02:00
D8H
89e06b0801 Fix collision mask editor image border size (#5228) 2023-04-13 11:52:36 +02:00
github-actions[bot]
5e1a6eb084 Update translations [skip ci] (#5225)
Co-authored-by: D8H <D8H@users.noreply.github.com>
2023-04-13 10:22:32 +02:00
D8H
f89a48fb2c Allow to lock layers in the editor (#5226) 2023-04-13 10:18:54 +02:00
D8H
ddb65012ce Allow to copy and paste effects from one object or layer to another (#5207) 2023-04-12 10:39:11 +02:00
D8H
bb0fe0ea37 Allow to copy and paste behaviors from one object to another (#5205) 2023-04-12 10:38:27 +02:00
D8H
747cdf0243 Allow drag and drop or copy and paste of properties in the extension editor (#5222) 2023-04-11 18:14:27 +02:00
Clément Pasteau
385ec5e9ca Fix long touch not working on iOS Safari (#5223) 2023-04-11 16:45:16 +02:00
github-actions[bot]
bcbdc35d72 Update translations [skip ci] (#5221)
Co-authored-by: ClementPasteau <ClementPasteau@users.noreply.github.com>
2023-04-11 12:10:17 +02:00
Clément Pasteau
6053369474 Rework multiple fields to have selects (#5208)
* External Layout, Animation, Effect and Effect Parameter
2023-04-11 09:25:41 +02:00
AlexandreS
ed1e0852b5 Check other scenes for conflicts when creating or manipulating global object and groups (#5215) 2023-04-11 09:09:35 +02:00
D8H
23ce46439a Show invalid resources errors in the event sheet (#5218) 2023-04-09 18:50:43 +02:00
github-actions[bot]
d9b35018e7 Update translations [skip ci] (#5200)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-04-07 17:38:03 +02:00
AlexandreS
571ab1313d Recompute full url to include a refreshed token (#5217)
Don't show in changelog
2023-04-07 16:55:23 +02:00
AlexandreS
aff82c4733 Add possibility to close preview window with Cmd/Ctrl + W (#5214)
- The previous announce about making this feature available was wrong
2023-04-07 12:05:59 +02:00
AlexandreS
2d4fc0af07 Update function configuration after toggling async function (#5212)
Don't show in changelog
2023-04-07 11:18:13 +02:00
AlexandreS
7cadf35642 Allow to open or download resources of a cloud project from the Resources editor 2023-04-06 10:17:21 +02:00
D8H
73e1ea5ff1 Fix missing errors when a variable name is used alone in an expression (#5203) 2023-04-05 12:01:43 +02:00
AlexandreS
bc87caf640 Handle cloud project opening errors better (#5202)
Don't show in changelog
2023-04-05 10:28:25 +02:00
Florian Rival
95dfb391c4 Revert Publish icon (#5201)
Don't show in changelog
2023-04-05 08:58:40 +02:00
AlexandreS
4b973c9655 Do not raise error if community link field is empty (#5199)
Don't show in changelog
2023-04-04 18:22:55 +02:00
Clément Pasteau
23f24a3939 Bump to 5.1.160 2023-04-04 16:47:53 +02:00
github-actions[bot]
b3ed22806b Update translations [skip ci] (#5192) 2023-04-04 16:47:02 +02:00
Clément Pasteau
4afefafc76 Fix Fling game tutorial being properly closed and restarted on the saved step (#5198) 2023-04-04 16:28:43 +02:00
Florian Rival
d2a1d8620f Handle management of subscriptions made on another platform (#5196) 2023-04-04 14:33:19 +02:00
AlexandreS
fdfc028a2c Scroll editor tabs when a new tab is activated or opened (#5194) 2023-04-04 10:22:26 +02:00
Peter Anderson
48cd42fee0 Fix Objects Panel button to show correct tooltip (#5195) 2023-04-04 09:21:09 +02:00
Clément Pasteau
b215eff444 Add more customization to the user profile (#5181)
* Community links can now be entered (Twitter, Reddit, Discord, etc...)
* Those links will be displayed on your GDevelop profile as well as your gd.games profile page!
2023-04-03 16:17:21 +02:00
AlexandreS
1bf66a97ae Improve the UI of the alert messages so that they are more noticeable (#5186) 2023-04-03 11:59:43 +02:00
github-actions[bot]
cc6890a495 Update translations [skip ci] (#5182)
Co-authored-by: AlexandreSi <AlexandreSi@users.noreply.github.com>
2023-03-31 14:04:32 +02:00
AlexandreS
418dd834c0 Fix attempt: Check cloud project before sending it to avoid corrupt cloud project (#5183) 2023-03-31 13:45:45 +02:00
932 changed files with 78940 additions and 50545 deletions

View File

@@ -15,7 +15,7 @@ jobs:
# Build the **entire** app for macOS.
build-macos:
macos:
xcode: 12.5.1
xcode: 14.2.0
steps:
- checkout
@@ -64,11 +64,11 @@ jobs:
# Note: Code signing is done using CSC_LINK (see https://www.electron.build/code-signing).
- run:
name: Build GDevelop IDE
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --mac --publish=never
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && CI=false npm run build -- --mac --publish=never
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf "newIDE/electron-app/dist/mac/GDevelop 5.app" && rm -rf "newIDE/electron-app/dist/mac-arm64/GDevelop 5.app"
command: rm -rf "newIDE/electron-app/dist/mac-universal/GDevelop 5.app"
# Upload artifacts (CircleCI)
- store_artifacts:
@@ -101,8 +101,8 @@ jobs:
command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)
@@ -178,8 +178,8 @@ jobs:
command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)

View File

@@ -1,28 +0,0 @@
---
name: "\U0001F41BBug report"
about: Create a bug report about GDevelop or the game engine
title: ''
labels: ''
assignees: ''
---
## Describe the bug
A clear and concise description of what the bug is.
Please double check that the bug is not already reported in the issues list.
## To Reproduce
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
* Please include a link to a game if possible!
* If applicable, add screenshots to help explain your problem.
## Other details
* Include any OS/browser version/smartphone that you're using
* Which version of GDevelop are you using? The desktop app or the web-app?
* Add any other context about the problem here.

71
.github/ISSUE_TEMPLATE/--bug-report.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: 🐛Bug report
description: Create a bug report about GDevelop or the game engine
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
options:
- label: I have searched the [existing issues](https://github.com/4ian/GDevelop/issues)
required: true
- type: textarea
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: |
* Please include a link to a game if possible!
* If applicable, add screenshots to help explain your problem.
placeholder: |
1. Go to '...'
2. Click on '...'
3. Scroll down to '...'
4. See error
validations:
required: true
- type: dropdown
attributes:
label: GDevelop platform
description: Which platform of GDevelop are you using?
multiple: true
options:
- Desktop
- Web
- Mobile
validations:
required: true
- type: input
attributes:
label: GDevelop version
description: |
Which version of GDevelop are you using?
Take a look here: [Editor Home - About GDevelop - "This version of GDevelop is: ~~~"]
placeholder: 5.1.159? 5.1.160?
validations:
required: true
- type: textarea
attributes:
label: Platform info
value: |
<details>
*OS (e.g. Windows, Linux, macOS, Android, iOS)*
>
*OS Version (e.g. Windows 10, macOS 10.15)*
>
*Browser(For Web) (e.g. Chrome, Firefox, Safari)*
>
*Device(For Mobile) (e.g. iPhone 12, Samsung Galaxy S21)*
>
</details>
- type: textarea
attributes:
label: Additional context
description: Add any other context about the problem here.

View File

@@ -9,6 +9,10 @@ name: Build Storybook
on:
# Launch on all commits.
push:
branches:
- "**"
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab,
# to publish on Chromatic (not done by default).
workflow_dispatch:
@@ -17,31 +21,23 @@ jobs:
build-storybook:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 50
- uses: actions/setup-node@v3
with:
node-version: 16
cache: "npm"
cache-dependency-path: "newIDE/app/package-lock.json"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.BUILD_STORYBOOK_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.BUILD_STORYBOOK_AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- uses: actions/checkout@v2
with:
fetch-depth: 50
# Cache npm dependencies to speed up the workflow
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-newIDE-app-node_modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
- name: Install newIDE dependencies
run: npm install
working-directory: newIDE/app

View File

@@ -4,6 +4,10 @@ name: Extract translations
on:
# Execute for all commits (to ensure translations extraction works)
push:
branches:
- "**"
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab.
workflow_dispatch:
@@ -11,20 +15,12 @@ jobs:
extract-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: actions/checkout@v2
# Cache npm dependencies to speed up the workflow
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-newIDE-app-node_modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
cache: "npm"
cache-dependency-path: "newIDE/app/package-lock.json"
- name: Install gettext
run: sudo apt update && sudo apt install gettext -y

View File

@@ -3,41 +3,17 @@ on:
issues:
types: [opened]
jobs:
autoclose:
runs-on: ubuntu-latest
steps:
- name: Autoclose issues about adding a bug without changing the bug report template
uses: arkon/issue-closer-action@v1.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
type: "body"
regex: ".*Scroll down to '\\.\\.\\.\\.'.*"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop.io/), the Discord chat or [read the documentation](https://wiki.gdevelop.io/gdevelop5/start) to learn more about GDevelop. Thanks!"
- name: Autoclose known beta 105 web-app update bug
uses: arkon/issue-closer-action@v1.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
type: "body"
regex: ".*_instance.getRawFloatProperty is not a function.*"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed as this seems to be a known bug. It can be solved by **closing entirely the web-app and opening it again**. This will allow the web-app to auto-update and the problem should be gone."
- name: Autoclose known beta 114 web-app update bug
uses: arkon/issue-closer-action@v1.1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
type: "body"
regex: ".*getAssociatedSettings is not a function.*"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed as this seems to be a known bug. It can be solved by **closing entirely the web-app and opening it again**. This will allow the web-app to auto-update and the problem should be gone."
autocomment:
runs-on: ubuntu-latest
if: contains(github.event.issue.body, 'The node to be removed is not a child of this node')
steps:
- name: Autocomment indications on bug if it looks like #3453
uses: peter-evans/create-or-update-comment@v1
with:
issue-number: ${{ github.event.issue.number }}
body: |
Hi @${{ github.actor }}!
Thank you for taking the time to open an issue.
- name: Autocomment indications on bug if it looks like #3453
uses: peter-evans/create-or-update-comment@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hi @${{ github.actor }}!
Thank you for taking the time to open an issue.
The solved issue #3453 mentioned a similar error, maybe it could help fix this new issue.
token: ${{ secrets.GITHUB_TOKEN }}
The solved issue #3453 mentioned a similar error, maybe it could help fix this new issue.

View File

@@ -1,29 +1,53 @@
name: GDevelop Issues automatic workflow
on:
pull_request:
types: [opened]
types:
- opened
- reopened
- synchronize
jobs:
read-locales-metadata:
if: contains(github.event.pull_request.title, '[Auto PR] Update translations')
if: github.event.pull_request.title == '[Auto PR] Update translations'
runs-on: ubuntu-latest
env:
COMMENT_TITLE: "Translation ratio changes"
steps:
- name: Read and format locales metadata
run: |
LANS=($(git diff HEAD^ HEAD --unified=5 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\s+\"languageName" | sed -E "s/^ *\"languageName\": \"//g" | sed -E "s/\",//g" | sed -E "s/ /_/g"))
ADDS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\+\s*\"translationRatio\"" | sed -E "s/^\+ *\"translationRatio\": //g"))
SUBS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\-\s*\"translationRatio\"" | sed -E "s/^\- *\"translationRatio\": //g"))
touch sumup.txt
for index in ${!ADDS[@]}; do
echo ${LANS[index]} | sed -E "s/_/ /g" >> sumup.txt
DELTA=$(bc <<< "scale=2;(${ADDS[index]}-${SUBS[index]})*100/1")
echo $DELTA % >> sumup.txt
done
- name: Store sumup in outputs
id: sumup
run: echo "::set-output name=sumupFileContent::$(cat sumup.txt)"
- name: Autocomment pull request with sumup
uses: peter-evans/create-or-update-comment@v1
with:
issue-number: ${{ github.event.number }}
body: ${{ steps.sumup.outputs.sumupFileContent}}
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Read and format locales metadata
env:
BASE: ${{ github.event.pull_request.base.sha }}
HEAD: ${{ github.event.pull_request.head.sha }}
run: |
LANS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\s+\"languageName" | sed -E "s/^ *\"languageName\": \"//g" | sed -E "s/\",//g" | sed -E "s/ /_/g"))
ADDS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\+\s*\"translationRatio\"" | sed -E "s/^\+ *\"translationRatio\": //g"))
SUBS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\-\s*\"translationRatio\"" | sed -E "s/^\- *\"translationRatio\": //g"))
touch sumup.md
echo "## $COMMENT_TITLE" >> sumup.md
echo "" >> sumup.md
echo "| Language | Change |" >> sumup.md
echo "| --- | --- |" >> sumup.md
for index in ${!ADDS[@]}; do
DELTA=$(echo "scale=3; (${ADDS[index]} - ${SUBS[index]})*100/1" | bc)
if (( $(echo "$DELTA == 0" | bc -l) )); then
continue
fi
LANGUAGE=${LANS[index]//_/ }
echo "| $LANGUAGE | $(printf "%1.3f" $DELTA) % |" >> sumup.md
done
- name: Find Comment
uses: peter-evans/find-comment@v2
id: fc
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.number }}
body-includes: ${{ env.COMMENT_TITLE }}
- name: Autocomment pull request with sumup
uses: peter-evans/create-or-update-comment@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.number }}
comment-id: ${{ steps.fc.outputs.comment-id }}
edit-mode: replace
body-path: "sumup.md"

View File

@@ -7,6 +7,8 @@ on:
push:
branches:
- master
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab.
workflow_dispatch:
@@ -14,20 +16,12 @@ jobs:
update-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- uses: actions/checkout@v2
# Cache npm dependencies to speed up the workflow
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-newIDE-app-node_modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
cache: "npm"
cache-dependency-path: "newIDE/app/package-lock.json"
- name: Install gettext
run: sudo apt update && sudo apt install gettext -y
@@ -64,7 +58,7 @@ jobs:
working-directory: newIDE/app
- name: Create a Pull Request with the changes
uses: peter-evans/create-pull-request@v3.10.1
uses: peter-evans/create-pull-request@v5
with:
commit-message: Update translations [skip ci]
branch: chore/update-translations

257
.vscode/settings.json vendored
View File

@@ -1,131 +1,134 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.associations": {
"*.idl": "java",
"Fastfile": "ruby",
"iosfwd": "cpp",
"functional": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"algorithm": "cpp",
"random": "cpp",
"__config": "cpp",
"cstddef": "cpp",
"exception": "cpp",
"initializer_list": "cpp",
"new": "cpp",
"stdexcept": "cpp",
"typeinfo": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"complex": "cpp",
"cstdarg": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"streambuf": "cpp",
"hashtable": "cpp",
"tuple": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"__split_buffer": "cpp",
"deque": "cpp",
"iterator": "cpp",
"list": "cpp",
"map": "cpp",
"queue": "cpp",
"regex": "cpp",
"set": "cpp",
"stack": "cpp",
"string": "cpp",
"vector": "cpp",
"iostream": "cpp",
"__functional_03": "cpp",
"__hash_table": "cpp",
"__tree": "cpp",
"bitset": "cpp",
"__bit_reference": "cpp",
"__mutex_base": "cpp",
"fstream": "cpp",
"ios": "cpp",
"__locale": "cpp",
"valarray": "cpp",
"freeglut_spaceball.c": "cpp",
"__tuple": "cpp",
"hash_map": "cpp",
"hash_set": "cpp",
"system_error": "cpp",
"__nullptr": "cpp",
"__functional_base": "cpp",
"__functional_base_03": "cpp",
"chrono": "cpp",
"ratio": "cpp",
"atomic": "cpp",
"locale": "cpp",
"string_view": "cpp",
"__string": "cpp",
"cstring": "cpp",
"iomanip": "cpp",
"cstdint": "cpp",
"forward_list": "cpp",
"mutex": "cpp",
"__hash": "cpp",
"__debug": "cpp",
"__threading_support": "cpp",
"any": "cpp",
"array": "cpp",
"cinttypes": "cpp",
"numeric": "cpp",
"__memory": "cpp",
"__errc": "cpp",
"__node_handle": "cpp",
"bit": "cpp",
"optional": "cpp",
"filesystem": "cpp",
"compare": "cpp",
"concepts": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocinfo": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"xlocbuf": "cpp",
"xlocmes": "cpp",
"xmemory0": "cpp",
"memory_resource": "cpp"
},
"files.exclude": {
"Binaries/*build*": true,
"Binaries/Output": true,
"GDJS/Runtime-dist": true,
"docs": true,
"newIDE/electron-app/dist": true,
"newIDE/app/build": true,
"newIDE/app/resources/GDJS": true,
"newIDE/electron-app/app/www": true
},
// Support for Flowtype (for newIDE):
"javascript.validate.enable": false,
"flow.useNPMPackagedFlow": true,
"files.associations": {
"*.idl": "java",
"Fastfile": "ruby",
"iosfwd": "cpp",
"functional": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"algorithm": "cpp",
"random": "cpp",
"__config": "cpp",
"cstddef": "cpp",
"exception": "cpp",
"initializer_list": "cpp",
"new": "cpp",
"stdexcept": "cpp",
"typeinfo": "cpp",
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"complex": "cpp",
"cstdarg": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"streambuf": "cpp",
"hashtable": "cpp",
"tuple": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"__split_buffer": "cpp",
"deque": "cpp",
"iterator": "cpp",
"list": "cpp",
"map": "cpp",
"queue": "cpp",
"regex": "cpp",
"set": "cpp",
"stack": "cpp",
"string": "cpp",
"vector": "cpp",
"iostream": "cpp",
"__functional_03": "cpp",
"__hash_table": "cpp",
"__tree": "cpp",
"bitset": "cpp",
"__bit_reference": "cpp",
"__mutex_base": "cpp",
"fstream": "cpp",
"ios": "cpp",
"__locale": "cpp",
"valarray": "cpp",
"freeglut_spaceball.c": "cpp",
"__tuple": "cpp",
"hash_map": "cpp",
"hash_set": "cpp",
"system_error": "cpp",
"__nullptr": "cpp",
"__functional_base": "cpp",
"__functional_base_03": "cpp",
"chrono": "cpp",
"ratio": "cpp",
"atomic": "cpp",
"locale": "cpp",
"string_view": "cpp",
"__string": "cpp",
"cstring": "cpp",
"iomanip": "cpp",
"cstdint": "cpp",
"forward_list": "cpp",
"mutex": "cpp",
"__hash": "cpp",
"__debug": "cpp",
"__threading_support": "cpp",
"any": "cpp",
"array": "cpp",
"cinttypes": "cpp",
"numeric": "cpp",
"__memory": "cpp",
"__errc": "cpp",
"__node_handle": "cpp",
"bit": "cpp",
"optional": "cpp",
"filesystem": "cpp",
"compare": "cpp",
"concepts": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocinfo": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"xlocbuf": "cpp",
"xlocmes": "cpp",
"xmemory0": "cpp",
"memory_resource": "cpp",
"__bits": "cpp",
"__verbose_abort": "cpp",
"variant": "cpp"
},
"files.exclude": {
"Binaries/*build*": true,
"Binaries/Output": true,
"GDJS/Runtime-dist": true,
"docs": true,
"newIDE/electron-app/dist": true,
"newIDE/app/build": true,
"newIDE/app/resources/GDJS": true,
"newIDE/electron-app/app/www": true
},
// Support for Flowtype (for newIDE):
"javascript.validate.enable": false,
"flow.useNPMPackagedFlow": true,
// Clang format styling (duplicated in scripts/CMakeClangUtils.txt)
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}"
// Clang format styling (duplicated in scripts/CMakeClangUtils.txt)
"C_Cpp.clang_format_style": "{BasedOnStyle: Google, BinPackParameters: false, BinPackArguments: false}"
}

View File

@@ -1,3 +1,3 @@
This is the directory where native or WebAssembly binaries of the C++ code of GDCore and GDJS are produced.
See GDevelop.js README for the instructions to compile after a change in the C++ source code.
See GDevelop.js README for the instructions to compile after a change in the C++ source code.

View File

@@ -1,100 +1,99 @@
#This is the CMake file used to build GDevelop.
#For more information, see the Readme.md file.
# This is the CMake file used to build GDevelop.
# For more information, see the README.md file.
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0011 NEW)
cmake_minimum_required(VERSION 3.5)
# Add utility functions
include(scripts/CMakeClangUtils.txt) # To add clang-format and clang-tidy support to a target
# Macro for defining an option
macro(gd_set_option var default type docstring)
if(NOT DEFINED ${var})
set(${var} ${default})
endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
if(NOT DEFINED ${var})
set(${var} ${default})
endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
endmacro()
# Set options
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library")
gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform")
gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions")
gd_set_option(BUILD_TESTS TRUE BOOL "TRUE to build the tests")
# Disable deprecated code
set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.
set(NO_GUI TRUE CACHE BOOL "" FORCE) # Force disable old GUI related code.
#Setting up installation directory, for Linux (has to be done before "project" command).
IF(NOT WIN32)
if (NOT APPLE)
gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed")
ELSE()
gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed")
ENDIF()
# Setting up installation directory, for Linux (has to be done before "project" command).
if(NOT WIN32)
if(NOT APPLE)
gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed")
else()
gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed")
endif()
#As we embed SFML, prevent it to be installed system-wide
# As we embed SFML, prevent it to be installed system-wide
set(CMAKE_INSTALL_PREFIX "${GD_INSTALL_PREFIX}/useless")
ENDIF()
endif()
project(GDevelop)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
IF(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS)
SET(CMAKE_SKIP_BUILD_RPATH TRUE) #Avoid errors when packaging for linux.
ENDIF()
IF(APPLE)
if(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS)
set(CMAKE_SKIP_BUILD_RPATH TRUE) # Avoid errors when packaging for linux.
endif()
if(APPLE)
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
set(CMAKE_INSTALL_RPATH ".")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
ENDIF()
#Sanity checks
IF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
message( "CMAKE_BUILD_TYPE is empty, assuming build type is Release" )
add_compile_options(
-D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_
-Wno-potentially-evaluated-expression)
endif()
# Sanity checks
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
message(STATUS "CMAKE_BUILD_TYPE is empty, assuming build type is Release")
set(CMAKE_BUILD_TYPE Release)
ENDIF()
endif()
IF("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
SET(CMAKE_SHARED_LINKER_FLAGS "-s") #Force stripping to avoid errors when packaging for linux.
ENDIF()
if("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_SHARED_LINKER_FLAGS "-s") # Force stripping to avoid errors when packaging for linux.
endif()
#Activate C++11
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support (with GNU extensions). Please use a different C++ compiler.")
endif()
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Mark some warnings as errors
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Activate as much warnings as possible to avoid errors like
# uninitialized variables or other hard to debug bugs.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder-ctor -Wno-reorder -Wno-pessimizing-move -Wno-unused-variable -Wno-unused-private-field")
add_compile_options(
-Wall
-Wno-unknown-warning-option
-Wno-reorder-ctor
-Wno-reorder
-Wno-pessimizing-move
-Wno-unused-variable
-Wno-unused-private-field
# Make as much warnings considered as errors as possible (only one for now).
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-stack-address")
# Make as much warnings considered as errors as possible (only one for now).
-Werror=return-stack-address)
endif()
#Define common directories:
# Define common directories:
set(GD_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
#Add all the CMakeLists:
ADD_SUBDIRECTORY(ExtLibs)
IF(BUILD_CORE)
ADD_SUBDIRECTORY(Core)
ENDIF()
IF(BUILD_GDJS)
ADD_SUBDIRECTORY(GDJS)
ENDIF()
IF(EMSCRIPTEN)
ADD_SUBDIRECTORY(GDevelop.js)
ENDIF()
IF(BUILD_EXTENSIONS)
ADD_SUBDIRECTORY(Extensions)
ENDIF()
# Add all the CMakeLists:
add_subdirectory(ExtLibs)
if(BUILD_CORE)
add_subdirectory(Core)
endif()
if(BUILD_GDJS)
add_subdirectory(GDJS)
endif()
if(EMSCRIPTEN)
add_subdirectory(GDevelop.js)
endif()
if(BUILD_EXTENSIONS)
add_subdirectory(Extensions)
endif()

View File

@@ -1,83 +1,98 @@
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
cmake_minimum_required(VERSION 3.5)
project(GDCore)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) #Force use response file: useful for Ninja build system on Windows.
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) # Force use response file: useful for Ninja build system on Windows.
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
#Define common directories:
# Define common directories:
set(GDCORE_include_dir ${GD_base_dir}/Core PARENT_SCOPE)
set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME} PARENT_SCOPE)
#Dependencies on external libraries:
###
# Dependencies on external libraries:
#
#Defines
###
add_definitions( -DGD_IDE_ONLY )
IF (EMSCRIPTEN)
add_definitions( -DEMSCRIPTEN )
ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
add_definitions( -DDEBUG )
ELSE()
add_definitions( -DRELEASE )
ENDIF()
# Defines
#
add_definitions(-DGD_IDE_ONLY)
if(EMSCRIPTEN)
add_definitions(-DEMSCRIPTEN)
endif()
if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
add_definitions(-DDEBUG)
else()
add_definitions(-DRELEASE)
endif()
IF(WIN32)
add_definitions( -DWINDOWS )
add_definitions( "-DGD_CORE_API=__declspec(dllexport)" )
add_definitions( -D__GNUWIN32__ )
ELSE()
IF(APPLE)
add_definitions( -DMACOS )
ELSE()
add_definitions( -DLINUX )
ENDIF()
add_definitions( -DGD_API= )
add_definitions( -DGD_CORE_API= )
ENDIF(WIN32)
if(WIN32)
add_definitions(-DWINDOWS)
add_definitions("-DGD_CORE_API=__declspec(dllexport)")
add_definitions(-D__GNUWIN32__)
else()
if(APPLE)
add_definitions(-DMACOS)
else()
add_definitions(-DLINUX)
endif()
add_definitions(-DGD_API=)
add_definitions(-DGD_CORE_API=)
endif()
#The target
###
# The target
#
include_directories(.)
file(GLOB_RECURSE source_files GDCore/*)
file(
GLOB_RECURSE
source_files
GDCore/*)
file(GLOB_RECURSE formatted_source_files tests/* GDCore/Events/* GDCore/Extensions/* GDCore/IDE/* GDCore/Project/* GDCore/Serialization/* GDCore/Tools/*)
list(REMOVE_ITEM formatted_source_files "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.h" "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs_dialogs_bitmaps.cpp")
file(
GLOB_RECURSE
formatted_source_files
tests/*
GDCore/Events/*
GDCore/Extensions/*
GDCore/IDE/*
GDCore/Project/*
GDCore/Serialization/*
GDCore/Tools/*)
list(
REMOVE_ITEM
formatted_source_files
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.h"
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs_dialogs_bitmaps.cpp")
gd_add_clang_utils(GDCore "${formatted_source_files}")
IF(EMSCRIPTEN)
if(EMSCRIPTEN)
# Emscripten treats all libraries as static libraries
add_library(GDCore STATIC ${source_files})
ELSE()
else()
add_library(GDCore SHARED ${source_files})
ENDIF()
IF(EMSCRIPTEN)
endif()
if(EMSCRIPTEN)
set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
ELSEIF(WIN32)
elseif(WIN32)
set_target_properties(GDCore PROPERTIES PREFIX "")
ELSE()
else()
set_target_properties(GDCore PROPERTIES PREFIX "lib")
ENDIF()
endif()
set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
set(ARCHIVE_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
set(RUNTIME_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
#Tests
###
# Tests
#
if(BUILD_TESTS)
file(
GLOB_RECURSE
test_source_files
tests/*
)
GLOB_RECURSE
test_source_files
tests/*)
add_executable(GDCore_tests ${test_source_files})
set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) #Allow finding dependencies directly from build path on Mac OS X.
set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) # Allow finding dependencies directly from build path on Mac OS X.
target_link_libraries(GDCore_tests GDCore)
target_link_libraries(GDCore_tests ${CMAKE_DL_LIBS})
endif()

View File

@@ -38,7 +38,7 @@ void CommentEvent::SerializeTo(SerializerElement &element) const {
.SetAttribute("textB", textB);
element.AddChild("comment").SetValue(com1);
element.AddChild("comment2").SetValue(com2);
if (!com2.empty()) element.AddChild("comment2").SetValue(com2);
}
void CommentEvent::UnserializeFrom(gd::Project &project,
@@ -53,7 +53,9 @@ void CommentEvent::UnserializeFrom(gd::Project &project,
textB = colorElement.GetIntAttribute("textB");
com1 = element.GetChild("comment", 0, "Com1").GetValue().GetString();
com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
if (element.HasChild("comment2")) {
com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
}
}
} // namespace gd

View File

@@ -15,7 +15,7 @@ using namespace std;
namespace gd {
ForEachEvent::ForEachEvent()
: BaseEvent(), objectsToPick(""), objectsToPickSelected(false) {}
: BaseEvent(), objectsToPick("") {}
vector<gd::InstructionsList*> ForEachEvent::GetAllConditionsVectors() {
vector<gd::InstructionsList*> allConditions;

View File

@@ -6,6 +6,8 @@
#ifndef FOREACHEVENT_H
#define FOREACHEVENT_H
#include <vector>
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
namespace gd {
@@ -62,13 +64,17 @@ class GD_CORE_API ForEachEvent : public gd::BaseEvent {
virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element);
std::vector<gd::Expression*> GetAllObjectExpressions() {
std::vector<gd::Expression*> allObjectExpressions;
allObjectExpressions.push_back(&objectsToPick);
return allObjectExpressions;
}
private:
gd::Expression objectsToPick;
gd::InstructionsList conditions;
gd::InstructionsList actions;
gd::EventsList events;
bool objectsToPickSelected;
};
} // namespace gd

View File

@@ -267,11 +267,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
AddIncludeFiles(instrInfos.GetIncludeFiles());
maxConditionsListsSize =
std::max(maxConditionsListsSize, condition.GetSubInstructions().size());
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
if (instrInfos.HasCustomCodeGenerator()) {
context.EnterCustomCondition();
conditionCode += instrInfos.codeExtraInformation.customCodeGenerator(
condition, *this, context);
@@ -289,7 +289,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
condition.SetParameters(parameters);
}
// Verify that there are no mismatchs between object type in parameters.
// Verify that there are no mismatches between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter =
@@ -459,9 +459,9 @@ gd::String EventsCodeGenerator::GenerateActionCode(
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
AddIncludeFiles(instrInfos.GetIncludeFiles());
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
if (instrInfos.HasCustomCodeGenerator()) {
return instrInfos.codeExtraInformation.customCodeGenerator(
action, *this, context);
}
@@ -481,7 +481,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
action.SetParameters(parameters);
}
// Verify that there are no mismatchs between object type in parameters.
// Verify that there are no mismatches between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
@@ -727,6 +727,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
metadata.GetType() == "tilemapResource" ||
metadata.GetType() == "tilesetResource" ||
metadata.GetType() == "videoResource" ||
metadata.GetType() == "model3DResource" ||
// Deprecated, old parameter names:
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
@@ -1018,15 +1019,15 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
bool conditionInverted,
gd::EventsCodeGenerationContext& context) {
// Generate call
gd::String predicat;
gd::String predicate;
if (instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string") {
predicat = GenerateRelationalOperatorCall(
predicate = GenerateRelationalOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName);
} else {
predicat = instrInfos.codeExtraInformation.functionCallName + "(" +
predicate = instrInfos.codeExtraInformation.functionCallName + "(" +
GenerateArgumentsList(arguments, 0) + ")";
}
@@ -1039,10 +1040,10 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
conditionAlreadyTakeCareOfInversion = true;
}
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
predicat = GenerateNegatedPredicat(predicat);
predicate = GenerateNegatedPredicate(predicate);
// Generate condition code
return returnBoolean + " = " + predicat + ";\n";
return returnBoolean + " = " + predicate + ";\n";
}
gd::String EventsCodeGenerator::GenerateObjectCondition(
@@ -1064,18 +1065,18 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
instrInfos.codeExtraInformation.functionCallName;
// Create call
gd::String predicat;
gd::String predicate;
if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) {
predicat = GenerateRelationalOperatorCall(
predicate = GenerateRelationalOperatorCall(
instrInfos, arguments, objectFunctionCallNamePart, 1);
} else {
predicat = objectFunctionCallNamePart + "(" +
predicate = objectFunctionCallNamePart + "(" +
GenerateArgumentsList(arguments, 1) + ")";
}
if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
return "For each picked object \"" + objectName + "\", check " + predicat +
return "For each picked object \"" + objectName + "\", check " + predicate +
".\n";
}
@@ -1089,16 +1090,16 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
bool conditionInverted,
gd::EventsCodeGenerationContext& context) {
// Create call
gd::String predicat;
gd::String predicate;
if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) {
predicat = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
predicate = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
} else {
predicat = "(" + GenerateArgumentsList(arguments, 2) + ")";
predicate = "(" + GenerateArgumentsList(arguments, 2) + ")";
}
if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate);
return "For each picked object \"" + objectName + "\", check " + predicat +
return "For each picked object \"" + objectName + "\", check " + predicate +
" for behavior \"" + behaviorName + "\".\n";
}
@@ -1238,7 +1239,7 @@ size_t EventsCodeGenerator::GenerateSingleUsageUniqueIdFor(
<< std::endl;
}
// Base the unique id on the adress in memory so that the same instruction
// Base the unique id on the address in memory so that the same instruction
// in memory will get the same id across different code generations.
size_t uniqueId = (size_t)instruction;

View File

@@ -507,7 +507,7 @@ class GD_CORE_API EventsCodeGenerator {
* - string : %Text expression -> string
* - layer, color, file, stringWithSelector : Same as string
* - relationalOperator : Used to make a comparison between the function
resturn value and value of the parameter preceding the relationOperator
return value and value of the parameter preceding the relationOperator
parameter -> string
* - operator : Used to update a value using a setter and a getter -> string
* - key, mouse, objectvar, scenevar, globalvar, password, musicfile,
@@ -668,13 +668,13 @@ class GD_CORE_API EventsCodeGenerator {
};
/**
* \brief Must negate a predicat.
* \brief Must negate a predicate.
*
* The default implementation generates C-style code : It wraps the predicat
* The default implementation generates C-style code : It wraps the predicate
* inside parenthesis and add a !.
*/
virtual gd::String GenerateNegatedPredicat(const gd::String& predicat) const {
return "!(" + predicat + ")";
virtual gd::String GenerateNegatedPredicate(const gd::String& predicate) const {
return "!(" + predicate + ")";
};
virtual gd::String GenerateFreeCondition(
@@ -785,7 +785,7 @@ class GD_CORE_API EventsCodeGenerator {
const gd::Project* project; ///< The project being used.
const gd::Layout* scene; ///< The scene being generated.
bool errorOccurred; ///< Must be set to true if an error occured.
bool errorOccurred; ///< Must be set to true if an error occurred.
bool compilationForRuntime; ///< Is set to true if the code generation is
///< made for runtime only.

View File

@@ -170,7 +170,7 @@ void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
}
else {
// This is for function names that are put in IdentifierNode
// because the type is needed to tell them appart from variables.
// because the type is needed to tell them apart from variables.
output += GenerateDefaultValue(type);
}
}
@@ -216,10 +216,10 @@ gd::String ExpressionCodeGenerator::GenerateFreeFunctionCode(
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) {
codeGenerator.AddIncludeFiles(
expressionMetadata.codeExtraInformation.GetIncludeFiles());
expressionMetadata.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
if (expressionMetadata.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}
@@ -242,10 +242,10 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles(
expressionMetadata.codeExtraInformation.GetIncludeFiles());
expressionMetadata.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
if (expressionMetadata.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}
@@ -300,10 +300,10 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles(
expressionMetadata.codeExtraInformation.GetIncludeFiles());
expressionMetadata.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
if (expressionMetadata.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}

View File

@@ -282,6 +282,14 @@ class GD_CORE_API BaseEvent {
*/
bool IsFolded() const { return folded; }
/**
* \brief Return a list of all objects linked to the event.
*/
virtual std::vector<gd::Expression*> GetAllObjectExpressions() {
std::vector<gd::Expression*> allObjectExpressions;
return allObjectExpressions;
}
///@}
std::weak_ptr<gd::BaseEvent>

View File

@@ -66,6 +66,11 @@ class GD_CORE_API ReadOnlyEventVisitor {
* Note that VisitEvent is also called with this event.
*/
virtual void VisitLinkEvent(const gd::LinkEvent& linkEvent) = 0;
/**
* @brief Abort the iteration on the events.
*/
virtual void StopAnyEventIteration() = 0;
};
}

View File

@@ -5,6 +5,7 @@
*/
#include "EventsList.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Tools/Log.h"
@@ -100,9 +101,8 @@ bool EventsList::Contains(const gd::BaseEvent& eventToSearch,
}
bool EventsList::MoveEventToAnotherEventsList(const gd::BaseEvent& eventToMove,
gd::EventsList& newEventsList,
std::size_t newPosition) {
gd::EventsList& newEventsList,
std::size_t newPosition) {
for (std::size_t i = 0; i < GetEventsCount(); ++i) {
if (events[i].get() == &eventToMove) {
std::shared_ptr<BaseEvent> event = events[i];

View File

@@ -17,7 +17,7 @@ const gd::String& EventsCodeNameMangler::GetMangledObjectsListName(
return it->second;
}
gd::String partiallyMangledName = originalObjectName;
gd::String partiallyMangledName = GetMangledNameWithForbiddenUnderscore(originalObjectName);
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -43,7 +43,15 @@ const gd::String& EventsCodeNameMangler::GetExternalEventsFunctionMangledName(
return it->second;
}
gd::String partiallyMangledName = externalEventsName;
gd::String partiallyMangledName = GetMangledNameWithForbiddenUnderscore(externalEventsName);
mangledExternalEventsNames[externalEventsName] = "GDExternalEvents" + partiallyMangledName;
return mangledExternalEventsNames[externalEventsName];
}
gd::String EventsCodeNameMangler::GetMangledNameWithForbiddenUnderscore(
const gd::String &name) {
gd::String partiallyMangledName = name;
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -57,11 +65,30 @@ const gd::String& EventsCodeNameMangler::GetExternalEventsFunctionMangledName(
partiallyMangledName.replace(i, 1, "_" + gd::String::From(unallowedChar));
}
}
mangledExternalEventsNames[externalEventsName] = "GDExternalEvents" + partiallyMangledName;
return mangledExternalEventsNames[externalEventsName];
return partiallyMangledName;
}
gd::String EventsCodeNameMangler::GetMangledName(
const gd::String &name) {
gd::String partiallyMangledName = name;
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
for (size_t i = 0; i < partiallyMangledName.size();
++i) // Replace all unallowed letter by an underscore and the ascii
// number of the letter
{
if (allowedCharacters.find_first_of(
std::u32string(1, partiallyMangledName[i])) == gd::String::npos) {
char32_t unallowedChar = partiallyMangledName[i];
partiallyMangledName.replace(i, 1, "_" + gd::String::From(unallowedChar));
}
}
return partiallyMangledName;
}
const gd::String& ManObjListName(const gd::String &objectName) {
return EventsCodeNameMangler::Get()->GetMangledObjectsListName(objectName);
}

View File

@@ -36,6 +36,8 @@ class GD_CORE_API EventsCodeNameMangler {
const gd::String &GetExternalEventsFunctionMangledName(
const gd::String &externalEventsName);
static gd::String GetMangledName(const gd::String &name);
static EventsCodeNameMangler *Get();
static void DestroySingleton();
@@ -44,6 +46,9 @@ class GD_CORE_API EventsCodeNameMangler {
virtual ~EventsCodeNameMangler(){};
static EventsCodeNameMangler *_singleton;
// This method is inlined to avoid to copy the returned string.
static inline gd::String GetMangledNameWithForbiddenUnderscore(const gd::String &name);
std::unordered_map<gd::String, gd::String>
mangledObjectNames; ///< Memoized results of mangling for objects
std::unordered_map<gd::String, gd::String>

View File

@@ -33,7 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("expression", "The number to be returned")
.AddParameter("expression", _("The number to be returned"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -48,7 +48,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("string", "The text to be returned")
.AddParameter("string", _("The text to be returned"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -62,7 +62,37 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("trueorfalse", "Should the condition be true or false?")
.AddParameter("trueorfalse", _("Should the condition be true or false?"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
.AddAction("CopyArgumentToVariable",
_("Copy function parameter to variable"),
_("Copy a function parameter (also called \"argument\") to a variable. "
"The parameter type must be a variable."),
_("Copy the parameter _PARAM0_ into the variable _PARAM1_"),
"",
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
.AddAction("CopyVariableToArgument",
_("Copy variable to function parameter"),
_("Copy a variable to function parameter (also called \"argument\"). "
"The parameter type must be a variable."),
_("Copy the variable _PARAM1_ into the parameter _PARAM0_"),
"",
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -77,7 +107,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"",
"res/function32.png",
"res/function32.png")
.AddParameter("functionParameterName", "Parameter name")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -88,7 +118,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Get function parameter (also called \"argument\") value."),
"",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.SetRelevantForFunctionEventsOnly();
extension
@@ -98,7 +128,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Get function parameter (also called \"argument\") text."),
"",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.SetRelevantForFunctionEventsOnly();
extension
@@ -110,7 +140,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
@@ -124,7 +154,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", "Parameter name")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();

View File

@@ -1588,7 +1588,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"Raycast",
_("Raycast"),
_("Sends a ray from the given source position and angle, "
"intersecting the closest object.\nThe instersected "
"intersecting the closest object.\nThe intersected "
"object will become the only one taken into account.\nIf "
"the condition is inverted, the object to be intersected "
"will be the farthest one within the ray radius."),
@@ -1619,7 +1619,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"RaycastToPosition",
_("Raycast to position"),
_("Sends a ray from the given source position to the final point, "
"intersecting the closest object.\nThe instersected "
"intersecting the closest object.\nThe intersected "
"object will become the only one taken into account.\nIf "
"the condition is inverted, the object to be intersected "
"will be the farthest one within the ray radius."),

View File

@@ -69,12 +69,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension
.AddAction(
"EcrireFichierExp",
_("Write a value"),
_("Write the result of the expression in the stored data, in the "
_("Save a value"),
_("Save the result of the expression in the stored data, in the "
"specified element.\nSpecify the structure leading to the "
"element using / (example : Root/Level/Current)\nSpaces are "
"forbidden in element names."),
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
@@ -85,12 +85,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension
.AddAction(
"EcrireFichierTxt",
_("Write a text"),
_("Write the text in the specified storage, in the specified "
_("Save a text"),
_("Save the text in the specified storage, in the specified "
"element.\nSpecify "
"the structure leading to the element using / (example : "
"Root/Level/Current)\nSpaces are forbidden in element names."),
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
@@ -101,13 +101,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension
.AddAction(
"LireFichierExp",
_("Read a value"),
_("Read the value saved in the specified element and store it in a "
_("Load a value"),
_("Load the value saved in the specified element and store it in a "
"scene "
"variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."),
_("Read _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
_("Load _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
@@ -119,13 +119,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension
.AddAction(
"LireFichierTxt",
_("Read a text"),
_("Read the text saved in the specified element and store it in a "
_("Load a text"),
_("Load the text saved in the specified element and store it in a "
"scene "
"variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."),
_("Read _PARAM1_ from storage _PARAM0_ and store as text in "
_("Load _PARAM1_ from storage _PARAM0_ and store as text in "
"_PARAM3_"),
"",
"res/actions/fichier24.png",

View File

@@ -48,7 +48,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
.AddParameter("string", "Content type", "", true)
.SetParameterLongDescription(
"If empty, \"application/x-www-form-urlencoded\" will be used.")
.AddParameter("scenevar", "Reponse scene variable", "", true)
.AddParameter("scenevar", "Response scene variable", "", true)
.SetParameterLongDescription(
"The response of the server will be stored, as a string, in this "
"variable. If the server returns *JSON*, you may want to use the "

View File

@@ -54,6 +54,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.AddCodeOnlyParameter("currentScene", "")
.MarkAsSimple();
extension
.AddCondition("DoesSceneExist",
_("Does scene exist"),
_("Check if scene exists."),
_("Scene _PARAM1_ exists"),
"",
"res/actions/texte.png",
"res/actions/texte.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Name of the scene to check"))
.MarkAsSimple();
extension
.AddAction("Scene",
_("Change the scene"),

View File

@@ -110,11 +110,11 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
.GetBoolAttribute("automatic", true));
if (spriteElement.HasChild("CustomCollisionMask"))
sprite.SetCollisionMaskAutomatic(
sprite.SetFullImageCollisionMask(
!spriteElement.GetChild("CustomCollisionMask")
.GetBoolAttribute("custom", false));
else
sprite.SetCollisionMaskAutomatic(
sprite.SetFullImageCollisionMask(
!spriteElement.GetBoolAttribute("hasCustomCollisionMask", false));
std::vector<Polygon2d> mask;
@@ -173,7 +173,7 @@ void SaveSpritesDirection(const vector<Sprite>& sprites,
.SetAttribute("automatic", sprites[i].IsDefaultCenterPoint());
spriteElement.SetAttribute("hasCustomCollisionMask",
!sprites[i].IsCollisionMaskAutomatic());
!sprites[i].IsFullImageCollisionMask());
gd::SerializerElement& collisionMaskElement =
spriteElement.AddChild("customCollisionMask");

View File

@@ -4,7 +4,9 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include <iostream>
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
using namespace std;
@@ -14,11 +16,10 @@ namespace gd {
Point Sprite::badPoint("");
Sprite::Sprite()
: automaticCollisionMask(true),
: fullImageCollisionMask(false),
origine("origine"),
centre("centre"),
automaticCentre(true) {
}
automaticCentre(true) {}
Sprite::~Sprite(){};

View File

@@ -7,6 +7,7 @@
#ifndef SPRITE_H
#define SPRITE_H
#include <memory>
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
#include "GDCore/String.h"
@@ -43,7 +44,7 @@ class GD_CORE_API Sprite {
/**
* \brief Get the collision mask (custom or automatically generated owing to
* IsCollisionMaskAutomatic())
* IsFullImageCollisionMask())
*
* \warning If the image has not been loaded ( using LoadImage ) and the
* collision mask is set as automatic, the returned mask won't be correct.
@@ -66,7 +67,7 @@ class GD_CORE_API Sprite {
/**
* \brief Set the custom collision mask.
* Call then `SetCollisionMaskAutomatic(false)` to use it.
* Call then `SetFullImageCollisionMask(false)` to use it.
*/
void SetCustomCollisionMask(const std::vector<Polygon2d>& collisionMask);
@@ -74,15 +75,15 @@ class GD_CORE_API Sprite {
* \brief Return true if the collision mask is a bounding box, false if a
* custom collision mask is used.
*/
inline bool IsCollisionMaskAutomatic() const {
return automaticCollisionMask;
inline bool IsFullImageCollisionMask() const {
return fullImageCollisionMask;
}
/**
* \brief Un/set use of the custom collision mask.
*/
inline void SetCollisionMaskAutomatic(bool enabled) {
automaticCollisionMask = enabled;
inline void SetFullImageCollisionMask(bool enabled) {
fullImageCollisionMask = enabled;
};
/**
@@ -161,9 +162,9 @@ class GD_CORE_API Sprite {
private:
gd::String image; ///< Name of the image to be loaded in Image Manager.
bool automaticCollisionMask; ///< True to use the custom collision mask.
///< Otherwise, a basic bounding box is returned
///< by GetCollisionMask()
bool fullImageCollisionMask; ///< True to use a bounding box wrapping the
///< whole image as collision mask. If false,
///< custom collision mask is used.
std::vector<Polygon2d> customCollisionMask; ///< Custom collision mask
std::vector<Point> points; ///< List of the points used by the sprite

View File

@@ -287,7 +287,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
obj.AddCondition("AnimationName",
_("Current animation name"),
_("Check the animation by played by the object."),
_("Check the animation played by the object."),
_("The animation of _PARAM0_ is _PARAM1_"),
_("Animations and images"),
"res/conditions/animation24.png",

View File

@@ -25,13 +25,16 @@ namespace gd {
Animation SpriteObject::badAnimation;
SpriteObject::SpriteObject() : updateIfNotVisible(false) {}
SpriteObject::SpriteObject()
: updateIfNotVisible(false), adaptCollisionMaskAutomatically(true) {}
SpriteObject::~SpriteObject(){};
void SpriteObject::DoUnserializeFrom(gd::Project& project,
const gd::SerializerElement& element) {
updateIfNotVisible = element.GetBoolAttribute("updateIfNotVisible", true);
adaptCollisionMaskAutomatically =
element.GetBoolAttribute("adaptCollisionMaskAutomatically", false);
RemoveAllAnimations();
const gd::SerializerElement& animationsElement =
@@ -80,6 +83,8 @@ void SpriteObject::DoUnserializeFrom(gd::Project& project,
void SpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
element.SetAttribute("updateIfNotVisible", updateIfNotVisible);
element.SetAttribute("adaptCollisionMaskAutomatically",
adaptCollisionMaskAutomatically);
// Animations
gd::SerializerElement& animationsElement = element.AddChild("animations");

View File

@@ -47,8 +47,7 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
void ExposeResources(gd::ArbitraryResourceWorker& worker) override;
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const override;
bool UpdateProperty(const gd::String& name,
const gd::String& value) override;
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
std::map<gd::String, gd::PropertyDescriptor> GetInitialInstanceProperties(
const gd::InitialInstance& position,
@@ -118,14 +117,30 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
const std::vector<Animation>& GetAllAnimations() const { return animations; }
/**
* \brief Set if the object animation should be played even if the object is hidden
* or far from the camera.
* @brief Check if the collision mask adapts automatically to the animation.
*/
void SetUpdateIfNotVisible(bool updateIfNotVisible_) { updateIfNotVisible = updateIfNotVisible_; }
bool AdaptCollisionMaskAutomatically() const {
return adaptCollisionMaskAutomatically;
}
/**
* \brief Check if the object animation should be played even if the object is hidden
* or far from the camera (false by default).
* @brief Set if the collision mask adapts automatically to the animation.
*/
void SetAdaptCollisionMaskAutomatically(bool enable) {
adaptCollisionMaskAutomatically = enable;
}
/**
* \brief Set if the object animation should be played even if the object is
* hidden or far from the camera.
*/
void SetUpdateIfNotVisible(bool updateIfNotVisible_) {
updateIfNotVisible = updateIfNotVisible_;
}
/**
* \brief Check if the object animation should be played even if the object
* is hidden or far from the camera (false by default).
*/
bool GetUpdateIfNotVisible() const { return updateIfNotVisible; }
///@}
@@ -137,11 +152,15 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
mutable std::vector<Animation> animations;
bool updateIfNotVisible; ///< If set to true, ask the game engine to play
///< object animation even if hidden or far from the
///< screen.
///< object animation even if hidden or far from
///< the screen.
static Animation badAnimation; //< Bad animation when an out of bound
// animation is requested.
static Animation badAnimation; //< Bad animation when an out of bound
// animation is requested.
bool adaptCollisionMaskAutomatically; ///< If set to true, the collision
///< mask will be automatically
///< adapted to the animation of the
///< object.
};
} // namespace gd

View File

@@ -126,8 +126,8 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
extension
.AddExpression(
"StrFindLast",
_("Search the last occurence in a text"),
_("Search the last occurence in a string (return the position of "
_("Search the last occurrence in a text"),
_("Search the last occurrence in a string (return the position of "
"the result, from the beginning of the string, or -1 if not "
"found)"),
"",
@@ -169,10 +169,10 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
extension
.AddExpression(
"StrFindLastFrom",
_("Search the last occurence in a text, starting from a position"),
_("Search in a text the last occurence, starting from a position "
_("Search the last occurrence in a text, starting from a position"),
_("Search in a text the last occurrence, starting from a position "
"(return "
" the position of the result, from the beginning of the string, or "
"the position of the result, from the beginning of the string, or "
"-1 if not found)"),
"",
"res/conditions/toujours24_black.png")

View File

@@ -0,0 +1,135 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include "GDCore/Events/Instruction.h"
#include "GDCore/String.h"
#include "ParameterMetadata.h"
#include "ParameterOptions.h"
namespace gd {
class Project;
class Layout;
class EventsCodeGenerator;
class EventsCodeGenerationContext;
class SerializerElement;
} // namespace gd
namespace gd {
/**
* \brief Describe user-friendly information about an expression or an
* instruction (action or condition), its parameters and the function name as
* well as other information for code generation.
*
* \ingroup Events
*/
class GD_CORE_API AbstractFunctionMetadata {
public:
AbstractFunctionMetadata(){};
virtual ~AbstractFunctionMetadata(){};
/**
* \see gd::InstructionMetadata::AddParameter
*/
virtual AbstractFunctionMetadata &
AddParameter(const gd::String &type, const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) = 0;
/**
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
virtual AbstractFunctionMetadata &
AddCodeOnlyParameter(const gd::String &type,
const gd::String &supplementaryInformation) = 0;
/**
* \see gd::InstructionMetadata::SetDefaultValue
*/
virtual AbstractFunctionMetadata &
SetDefaultValue(const gd::String &defaultValue) = 0;
/**
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
virtual AbstractFunctionMetadata &
SetParameterExtraInfo(const gd::String &defaultValue) = 0;
/**
* \see gd::InstructionMetadata::SetParameterLongDescription
*/
virtual AbstractFunctionMetadata &
SetParameterLongDescription(const gd::String &longDescription) = 0;
/**
* \see gd::InstructionMetadata::SetHidden
*/
virtual AbstractFunctionMetadata &SetHidden() = 0;
/**
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
virtual AbstractFunctionMetadata &SetPrivate() = 0;
/**
* Set that the instruction can be used in layouts or external events.
*/
virtual AbstractFunctionMetadata &SetRelevantForLayoutEventsOnly() = 0;
/**
* Set that the instruction can be used in function events.
*/
virtual AbstractFunctionMetadata &SetRelevantForFunctionEventsOnly() = 0;
/**
* Set that the instruction can be used in asynchronous function events.
*/
virtual AbstractFunctionMetadata &
SetRelevantForAsynchronousFunctionEventsOnly() = 0;
/**
* Set that the instruction can be used in custom object events.
*/
virtual AbstractFunctionMetadata &SetRelevantForCustomObjectEventsOnly() = 0;
/**
* \brief Set the function that should be called when generating the source
* code from events.
* \param functionName the name of the function to call
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
virtual AbstractFunctionMetadata &
SetFunctionName(const gd::String &functionName) = 0;
/**
* \brief Erase any existing include file and add the specified include.
*/
virtual AbstractFunctionMetadata &
SetIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Add a file to the already existing include files.
*/
virtual AbstractFunctionMetadata &
AddIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Get the files that must be included to use the instruction.
*/
virtual const std::vector<gd::String> &GetIncludeFiles() const = 0;
private:
};
} // namespace gd

View File

@@ -3,8 +3,10 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef BEHAVIORMETADATA_H
#define BEHAVIORMETADATA_H
#pragma once
#include "InstructionOrExpressionContainerMetadata.h"
#include <map>
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
@@ -25,7 +27,7 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API BehaviorMetadata {
class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMetadata {
public:
BehaviorMetadata(
const gd::String& extensionNamespace,
@@ -67,7 +69,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the behavior.
@@ -80,7 +82,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new condition as being part of the behavior.
@@ -91,7 +93,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the behavior.
@@ -102,7 +104,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the extension.
*/
@@ -110,7 +112,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new string expression as being part of the extension.
@@ -119,7 +121,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new expression and condition as being part of the
@@ -134,7 +136,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Declare a new expression, condition and action as being part of the
@@ -151,7 +153,7 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Create a new action which is the duplicate of the specified one.
@@ -160,7 +162,7 @@ class GD_CORE_API BehaviorMetadata {
* one.
*/
gd::InstructionMetadata& AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName);
const gd::String& newActionName, const gd::String& copiedActionName) override;
/**
* \brief Create a new condition which is the duplicate of the specified one.
@@ -170,7 +172,7 @@ class GD_CORE_API BehaviorMetadata {
*/
gd::InstructionMetadata& AddDuplicatedCondition(
const gd::String& newConditionName,
const gd::String& copiedConditionName);
const gd::String& copiedConditionName) override;
/**
* \brief Create a new expression which is the duplicate of the specified one.
@@ -193,9 +195,9 @@ class GD_CORE_API BehaviorMetadata {
const gd::String& newExpressionName,
const gd::String& copiedExpressionName);
BehaviorMetadata& SetFullName(const gd::String& fullname_);
BehaviorMetadata& SetFullName(const gd::String& fullname_) override;
BehaviorMetadata& SetDefaultName(const gd::String& defaultName_);
BehaviorMetadata& SetDescription(const gd::String& description_);
BehaviorMetadata& SetDescription(const gd::String& description_) override;
BehaviorMetadata& SetGroup(const gd::String& group_);
/**
@@ -203,12 +205,12 @@ class GD_CORE_API BehaviorMetadata {
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the behavior.
*/
BehaviorMetadata& SetIncludeFile(const gd::String& includeFile);
BehaviorMetadata& SetIncludeFile(const gd::String& includeFile) override;
/**
* \brief Add a file to the already existing include files.
*/
BehaviorMetadata& AddIncludeFile(const gd::String& includeFile);
BehaviorMetadata& AddIncludeFile(const gd::String& includeFile) override;
/**
* \brief Add a file to the already existing required files.
@@ -221,7 +223,7 @@ class GD_CORE_API BehaviorMetadata {
* Get the help path of the behavior, relative to the GDevelop documentation
* root.
*/
const gd::String& GetHelpPath() const { return helpPath; }
const gd::String& GetHelpPath() const override { return helpPath; }
/**
* Set the help path of the behavior, relative to the GDevelop documentation
@@ -230,17 +232,17 @@ class GD_CORE_API BehaviorMetadata {
* The behavior instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
BehaviorMetadata& SetHelpPath(const gd::String& path) {
BehaviorMetadata& SetHelpPath(const gd::String& path) override {
helpPath = path;
return *this;
}
const gd::String& GetName() const;
const gd::String& GetFullName() const { return fullname; }
const gd::String& GetName() const override;
const gd::String& GetFullName() const override { return fullname; }
const gd::String& GetDefaultName() const { return defaultName; }
const gd::String& GetDescription() const { return description; }
const gd::String& GetDescription() const override { return description; }
const gd::String& GetGroup() const { return group; }
const gd::String& GetIconFilename() const { return iconFilename; }
const gd::String& GetIconFilename() const override { return iconFilename; }
/**
* \brief Set the type of the object that this behavior can be used on.
@@ -293,22 +295,22 @@ class GD_CORE_API BehaviorMetadata {
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() { return actionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() override { return actionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() { return conditionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() override { return conditionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() { return expressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() override { return expressionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() { return strExpressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() override { return strExpressionsInfos; };
std::map<gd::String, gd::InstructionMetadata> conditionsInfos;
std::map<gd::String, gd::InstructionMetadata> actionsInfos;
@@ -337,5 +339,3 @@ class GD_CORE_API BehaviorMetadata {
};
} // namespace gd
#endif // BEHAVIORMETADATA_H

View File

@@ -62,7 +62,7 @@ class GD_CORE_API DependencyMetadata {
};
/**
* \brief Sets the type of dependecy (what will be used to install it)
* \brief Sets the type of dependency (what will be used to install it)
*
* This can either be "npm" or "cordova" for now.
*/

View File

@@ -7,9 +7,6 @@
namespace gd {
EffectMetadata::EffectMetadata(const gd::String& type_)
: type(type_), isMarkedAsNotWorkingForObjects(false) {}
EffectMetadata& EffectMetadata::SetIncludeFile(const gd::String& includeFile) {
includeFiles.clear();
includeFiles.push_back(includeFile);
@@ -23,9 +20,4 @@ EffectMetadata& EffectMetadata::AddIncludeFile(const gd::String& includeFile) {
return *this;
}
EffectMetadata& EffectMetadata::MarkAsNotWorkingForObjects() {
isMarkedAsNotWorkingForObjects = true;
return *this;
}
} // namespace gd

View File

@@ -3,8 +3,8 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef EFFECTMETADATA_H
#define EFFECTMETADATA_H
#pragma once
#include <functional>
#include <map>
#include <memory>
@@ -25,21 +25,25 @@ class GD_CORE_API EffectMetadata {
/**
* \brief Construct an effect metadata, with the given type
*/
EffectMetadata(const gd::String& type_);
EffectMetadata(const gd::String &type_)
: type(type_), isMarkedAsNotWorkingForObjects(false),
isMarkedAsOnlyWorkingFor2D(false), isMarkedAsOnlyWorkingFor3D(false),
isMarkedAsUnique(false) {}
/**
* \brief Default constructor, only used for initializing `badEffectMetadata`.
*/
EffectMetadata() {}
/**
* \brief Default constructor, only used for initializing
* `badEffectMetadata`.
*/
EffectMetadata() {}
virtual ~EffectMetadata(){};
virtual ~EffectMetadata(){};
/**
* \brief Set the name shown to the user.
*/
EffectMetadata& SetFullName(const gd::String& fullname_) {
fullname = fullname_;
return *this;
/**
* \brief Set the name shown to the user.
*/
EffectMetadata &SetFullName(const gd::String &fullname_) {
fullname = fullname_;
return *this;
};
/**
@@ -69,11 +73,6 @@ class GD_CORE_API EffectMetadata {
*/
EffectMetadata& AddIncludeFile(const gd::String& includeFile);
/**
* \brief Mark the effect as not working as an object effect.
*/
EffectMetadata& MarkAsNotWorkingForObjects();
/**
* \brief Return a reference to the properties of this effect.
*/
@@ -117,10 +116,65 @@ class GD_CORE_API EffectMetadata {
return includeFiles;
}
/**
* \brief Mark the effect as not working as an object effect.
*/
EffectMetadata& MarkAsNotWorkingForObjects() {
isMarkedAsNotWorkingForObjects = true;
return *this;
}
/**
* \brief Mark the effect as only working for the 2D renderer.
*/
EffectMetadata& MarkAsOnlyWorkingFor2D() {
isMarkedAsOnlyWorkingFor2D = true;
return *this;
}
/**
* \brief Mark the effect as only working for the 3D renderer.
*/
EffectMetadata& MarkAsOnlyWorkingFor3D() {
isMarkedAsOnlyWorkingFor3D = true;
return *this;
}
/**
* \brief Mark the effect as only addable once.
*/
EffectMetadata& MarkAsUnique() {
isMarkedAsUnique = true;
return *this;
}
/**
* \brief Check if the effect is marked as not working as an object effect.
*/
bool IsMarkedAsNotWorkingForObjects() const { return isMarkedAsNotWorkingForObjects; };
bool IsMarkedAsNotWorkingForObjects() const {
return isMarkedAsNotWorkingForObjects;
};
/**
* \brief Check if the effect is marked as only working for the 2D renderer.
*/
bool IsMarkedAsOnlyWorkingFor2D() const {
return isMarkedAsOnlyWorkingFor2D;
};
/**
* \brief Check if the effect is marked as only working for the 3D renderer.
*/
bool IsMarkedAsOnlyWorkingFor3D() const {
return isMarkedAsOnlyWorkingFor3D;
};
/**
* \brief Check if the effect can only be added once.
*/
bool IsMarkedAsUnique() const {
return isMarkedAsUnique;
};
private:
gd::String extensionNamespace;
@@ -130,8 +184,10 @@ class GD_CORE_API EffectMetadata {
gd::String description;
std::vector<gd::String> includeFiles;
bool isMarkedAsNotWorkingForObjects;
bool isMarkedAsOnlyWorkingFor2D;
bool isMarkedAsOnlyWorkingFor3D;
bool isMarkedAsUnique;
std::map<gd::String, gd::PropertyDescriptor> properties;
};
} // namespace gd
#endif // EFFECTMETADATA_H

View File

@@ -3,9 +3,10 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef EXPRESSIONMETADATA_H
#define EXPRESSIONMETADATA_H
#if defined(GD_IDE_ONLY)
#pragma once
#include "AbstractFunctionMetadata.h"
#include <functional>
#include <memory>
@@ -17,7 +18,6 @@ class Layout;
}
namespace gd {
/**
* \brief Information about how generate code for an expression
*/
@@ -27,79 +27,7 @@ class ExpressionCodeGenerationInformation {
: staticFunction(false), hasCustomCodeGenerator(false){};
virtual ~ExpressionCodeGenerationInformation(){};
/**
* \brief Set the function name which will be used when generating the code.
* \param functionName the name of the function to call
*/
ExpressionCodeGenerationInformation& SetFunctionName(
const gd::String& functionName) {
functionCallName = functionName;
return *this;
}
/**
* \brief Set that the function is static
*/
ExpressionCodeGenerationInformation& SetStatic() {
staticFunction = true;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionCodeGenerationInformation& SetIncludeFile(
const gd::String& includeFile) {
includeFiles.clear();
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionCodeGenerationInformation& AddIncludeFile(
const gd::String& includeFile) {
if (std::find(includeFiles.begin(), includeFiles.end(), includeFile) ==
includeFiles.end())
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return includeFiles;
};
/**
* \brief Set that the function must be generated using a custom code
* generator.
*/
ExpressionCodeGenerationInformation& SetCustomCodeGenerator(
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
codeGenerator) {
hasCustomCodeGenerator = true;
customCodeGenerator = codeGenerator;
return *this;
}
ExpressionCodeGenerationInformation& RemoveCustomCodeGenerator() {
hasCustomCodeGenerator = false;
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
emptyFunction;
customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return hasCustomCodeGenerator; }
// TODO Move these attributes to ExpressionMetadata.
bool staticFunction;
gd::String functionCallName;
bool hasCustomCodeGenerator;
@@ -107,8 +35,6 @@ class ExpressionCodeGenerationInformation {
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
customCodeGenerator;
private:
std::vector<gd::String> includeFiles;
};
@@ -118,7 +44,7 @@ class ExpressionCodeGenerationInformation {
*
* \ingroup Events
*/
class GD_CORE_API ExpressionMetadata {
class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
public:
/**
* Construct a new expression metadata.
@@ -144,7 +70,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* \brief Set the expression as not shown in the IDE.
*/
ExpressionMetadata& SetHidden();
ExpressionMetadata& SetHidden() override;
/**
* \brief Set the group of the instruction in the IDE.
@@ -179,7 +105,7 @@ class GD_CORE_API ExpressionMetadata {
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
ExpressionMetadata& SetPrivate() {
ExpressionMetadata& SetPrivate() override {
isPrivate = true;
return *this;
}
@@ -216,7 +142,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in layouts or external events.
*/
ExpressionMetadata &SetRelevantForLayoutEventsOnly() {
ExpressionMetadata &SetRelevantForLayoutEventsOnly() override {
relevantContext = "Layout";
return *this;
}
@@ -224,7 +150,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in function events.
*/
ExpressionMetadata &SetRelevantForFunctionEventsOnly() {
ExpressionMetadata &SetRelevantForFunctionEventsOnly() override {
relevantContext = "Function";
return *this;
}
@@ -232,7 +158,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in asynchronous function events.
*/
ExpressionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
ExpressionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
relevantContext = "AsynchronousFunction";
return *this;
}
@@ -240,7 +166,7 @@ class GD_CORE_API ExpressionMetadata {
/**
* Set that the instruction can be used in custom object events.
*/
ExpressionMetadata &SetRelevantForCustomObjectEventsOnly() {
ExpressionMetadata &SetRelevantForCustomObjectEventsOnly() override {
relevantContext = "Object";
return *this;
}
@@ -248,17 +174,17 @@ class GD_CORE_API ExpressionMetadata {
/**
* \see gd::InstructionMetadata::AddParameter
*/
gd::ExpressionMetadata& AddParameter(
const gd::String& type,
const gd::String& description,
const gd::String& supplementaryInformation = "",
bool parameterIsOptional = false);
gd::ExpressionMetadata &
AddParameter(const gd::String &type, const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) override;
/**
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
gd::ExpressionMetadata& AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation);
gd::ExpressionMetadata &
AddCodeOnlyParameter(const gd::String &type,
const gd::String &supplementaryInformation) override;
/**
* Set the default value used in editor (or if an optional parameter is empty
@@ -266,8 +192,9 @@ class GD_CORE_API ExpressionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata& SetDefaultValue(gd::String defaultValue_) {
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
ExpressionMetadata &SetDefaultValue(const gd::String &defaultValue) override {
if (!parameters.empty())
parameters.back().SetDefaultValue(defaultValue);
return *this;
};
@@ -277,7 +204,8 @@ class GD_CORE_API ExpressionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata& SetParameterLongDescription(gd::String longDescription) {
ExpressionMetadata &
SetParameterLongDescription(const gd::String &longDescription) override {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
@@ -290,7 +218,8 @@ class GD_CORE_API ExpressionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
ExpressionMetadata &SetParameterExtraInfo(
const gd::String &extraInfo) override {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
}
@@ -312,50 +241,6 @@ class GD_CORE_API ExpressionMetadata {
return requiredBaseObjectCapability;
};
/**
* \brief Set the function that should be called when generating the source
* code from events.
* \param functionName the name of the function to call
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
ExpressionCodeGenerationInformation& SetFunctionName(
const gd::String& functionName) {
return codeExtraInformation.SetFunctionName(functionName);
}
/**
* \brief Return the structure containing the information about code
* generation for the expression.
*/
ExpressionCodeGenerationInformation& GetCodeExtraInformation() {
return codeExtraInformation;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
}
ExpressionCodeGenerationInformation codeExtraInformation;
bool IsShown() const { return shown; }
const gd::String& GetReturnType() const { return returnType; }
const gd::String& GetFullName() const { return fullname; }
@@ -375,6 +260,99 @@ class GD_CORE_API ExpressionMetadata {
std::vector<gd::ParameterMetadata> parameters;
/**
* \brief Set the function name which will be used when generating the code.
* \param functionName the name of the function to call
*/
ExpressionMetadata& SetFunctionName(
const gd::String& functionName) override {
codeExtraInformation.functionCallName = functionName;
return *this;
}
/**
* \brief Return the name of the function which will be called in the generated code.
*/
const gd::String &GetFunctionName() {
return codeExtraInformation.functionCallName;
}
/**
* \brief Set that the function is static
*/
ExpressionMetadata& SetStatic() {
codeExtraInformation.staticFunction = true;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionMetadata& SetIncludeFile(
const gd::String& includeFile) override {
codeExtraInformation.includeFiles.clear();
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata& AddIncludeFile(
const gd::String& includeFile) override {
if (std::find(codeExtraInformation.includeFiles.begin(), codeExtraInformation.includeFiles.end(), includeFile) ==
codeExtraInformation.includeFiles.end())
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const override {
return codeExtraInformation.includeFiles;
};
/**
* \brief Set that the function must be generated using a custom code
* generator.
*/
ExpressionMetadata& SetCustomCodeGenerator(
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
codeGenerator) {
codeExtraInformation.hasCustomCodeGenerator = true;
codeExtraInformation.customCodeGenerator = codeGenerator;
return *this;
}
ExpressionMetadata& RemoveCustomCodeGenerator() {
codeExtraInformation.hasCustomCodeGenerator = false;
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
emptyFunction;
codeExtraInformation.customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return codeExtraInformation.hasCustomCodeGenerator; }
/**
* \brief Return the structure containing the information about code
* generation for the expression.
*
* \deprecated
*/
ExpressionMetadata& GetCodeExtraInformation() {
return *this;
}
ExpressionCodeGenerationInformation codeExtraInformation;
private:
gd::String returnType;
gd::String fullname;
@@ -391,6 +369,3 @@ class GD_CORE_API ExpressionMetadata {
};
} // namespace gd
#endif
#endif // EXPRESSIONMETADATA_H

View File

@@ -4,8 +4,10 @@
* reserved. This project is released under the MIT License.
*/
#ifndef INSTRUCTIONMETADATA_H
#define INSTRUCTIONMETADATA_H
#pragma once
#include "AbstractFunctionMetadata.h"
#include <algorithm>
#include <functional>
#include <map>
@@ -33,7 +35,7 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API InstructionMetadata {
class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
public:
/**
* Construct a new instruction metadata.
@@ -96,7 +98,7 @@ class GD_CORE_API InstructionMetadata {
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
InstructionMetadata &SetPrivate() {
InstructionMetadata &SetPrivate() override {
isPrivate = true;
return *this;
}
@@ -133,7 +135,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in layouts or external events.
*/
InstructionMetadata &SetRelevantForLayoutEventsOnly() {
InstructionMetadata &SetRelevantForLayoutEventsOnly() override {
relevantContext = "Layout";
return *this;
}
@@ -141,7 +143,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in function events.
*/
InstructionMetadata &SetRelevantForFunctionEventsOnly() {
InstructionMetadata &SetRelevantForFunctionEventsOnly() override {
relevantContext = "Function";
return *this;
}
@@ -149,7 +151,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in asynchronous function events.
*/
InstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
InstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
relevantContext = "AsynchronousFunction";
return *this;
}
@@ -157,7 +159,7 @@ class GD_CORE_API InstructionMetadata {
/**
* Set that the instruction can be used in custom object events.
*/
InstructionMetadata &SetRelevantForCustomObjectEventsOnly() {
InstructionMetadata &SetRelevantForCustomObjectEventsOnly() override {
relevantContext = "Object";
return *this;
}
@@ -192,7 +194,7 @@ class GD_CORE_API InstructionMetadata {
*
* Used mainly when an instruction is deprecated.
*/
InstructionMetadata &SetHidden() {
InstructionMetadata &SetHidden() override {
hidden = true;
return *this;
}
@@ -231,7 +233,7 @@ class GD_CORE_API InstructionMetadata {
const gd::String &type,
const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false);
bool parameterIsOptional = false) override;
/**
* \brief Add a parameter not displayed in editor.
@@ -245,7 +247,7 @@ class GD_CORE_API InstructionMetadata {
* \see EventsCodeGenerator::GenerateParametersCodes
*/
InstructionMetadata &AddCodeOnlyParameter(
const gd::String &type, const gd::String &supplementaryInformation);
const gd::String &type, const gd::String &supplementaryInformation) override;
/**
* \brief Set the default value used in editor (or if an optional parameter is
@@ -253,7 +255,7 @@ class GD_CORE_API InstructionMetadata {
*
* \see AddParameter
*/
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) {
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) override {
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
return *this;
};
@@ -265,7 +267,7 @@ class GD_CORE_API InstructionMetadata {
* \see AddParameter
*/
InstructionMetadata &SetParameterLongDescription(
const gd::String &longDescription) {
const gd::String &longDescription) override {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
@@ -278,7 +280,7 @@ class GD_CORE_API InstructionMetadata {
*
* \see AddParameter
*/
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) override {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
}
@@ -382,128 +384,13 @@ class GD_CORE_API InstructionMetadata {
/**
* \brief Defines information about how generate the code for an instruction
*/
class ExtraInformation {
class ExtraInformation {
public:
enum AccessType { Reference, MutatorAndOrAccessor, Mutators };
ExtraInformation() : accessType(Reference), hasCustomCodeGenerator(false){};
virtual ~ExtraInformation(){};
/**
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
*/
ExtraInformation &SetFunctionName(const gd::String &functionName_) {
functionCallName = functionName_;
return *this;
}
/**
* Set the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*
* \param functionName the name of the function doing asynchronous work to
* call.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName_) {
asyncFunctionCallName = functionName_;
return *this;
}
/**
* Declare if the instruction being declared is somewhat manipulating in a
* standard way.
*/
ExtraInformation &SetManipulatedType(const gd::String &type_) {
type = type_;
return *this;
}
/**
* If InstructionMetadata::ExtraInformation::SetManipulatedType was called
* with "number" or "string", this function will tell the code generator the
* name of the getter function used to retrieve the data value.
*
* Usage example:
* \code
* obj.AddAction("String",
* _("Change the string"),
* _("Change the string of a text"),
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString");
*
* DECLARE_END_OBJECT_ACTION()
* \endcode
*/
ExtraInformation &SetGetter(const gd::String &getter) {
optionalAssociatedInstruction = getter;
accessType = MutatorAndOrAccessor;
return *this;
}
ExtraInformation &SetMutators(
const std::map<gd::String, gd::String> &mutators) {
optionalMutators = mutators;
accessType = Mutators;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExtraInformation &SetIncludeFile(const gd::String &includeFile) {
includeFiles.clear();
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExtraInformation &AddIncludeFile(const gd::String &includeFile) {
if (std::find(includeFiles.begin(), includeFiles.end(), includeFile) ==
includeFiles.end())
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
return includeFiles;
};
ExtraInformation &SetCustomCodeGenerator(
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
codeGenerator) {
hasCustomCodeGenerator = true;
customCodeGenerator = codeGenerator;
return *this;
}
ExtraInformation &RemoveCustomCodeGenerator() {
hasCustomCodeGenerator = false;
std::function<gd::String(Instruction & instruction,
gd::EventsCodeGenerator & codeGenerator,
gd::EventsCodeGenerationContext & context)>
emptyFunction;
customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return hasCustomCodeGenerator; }
// TODO Move these attributes to InstructionMetadata.
gd::String functionCallName;
gd::String asyncFunctionCallName;
gd::String type;
@@ -512,75 +399,156 @@ class GD_CORE_API InstructionMetadata {
std::map<gd::String, gd::String> optionalMutators;
bool hasCustomCodeGenerator;
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
customCodeGenerator;
private:
std::vector<gd::String> includeFiles;
};
ExtraInformation codeExtraInformation; ///< Information about how generate
///< code for the instruction
/**
* \brief Return the structure containing the information about code
* generation for the instruction.
*/
ExtraInformation &GetCodeExtraInformation() { return codeExtraInformation; }
/**
* \brief Declare if the instruction being declared is somewhat manipulating
* in a standard way. \param type "number" or "string" \note Shortcut for
* `codeExtraInformation.SetManipulatedType(type)`.
*/
ExtraInformation &SetManipulatedType(const gd::String &type_) {
return codeExtraInformation.SetManipulatedType(type_);
}
/**
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
ExtraInformation &SetFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetFunctionName(functionName);
InstructionMetadata &SetFunctionName(const gd::String &functionName_) override {
codeExtraInformation.functionCallName = functionName_;
return *this;
}
/**
* Set the name of the function, doing asynchronous work, which will be called
* in the generated code. This function should return an asynchronous task
* (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
* 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`.
* call.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetAsyncFunctionName(functionName);
InstructionMetadata &SetAsyncFunctionName(const gd::String &functionName_) {
codeExtraInformation.asyncFunctionCallName = functionName_;
return *this;
}
/**
* Return the name of the function which will be called in the generated code.
*/
const gd::String &GetFunctionName() {
return codeExtraInformation.functionCallName;
}
/**
* Return 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).
*/
const gd::String &GetAsyncFunctionName() {
return codeExtraInformation.asyncFunctionCallName;
}
/**
* \brief Declare if the instruction being declared is somewhat manipulating
* in a standard way.
*
* \param type "number" or "string"
*/
InstructionMetadata &SetManipulatedType(const gd::String &type_) {
codeExtraInformation.type = type_;
return *this;
}
/**
* If InstructionMetadata::ExtraInformation::SetManipulatedType was called
* with "number" or "string", this function will tell the code generator the
* name of the getter function used to retrieve the data value.
*
* Usage example:
* \code
* obj.AddAction("String",
* _("Change the string"),
* _("Change the string of a text"),
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString");
*
* DECLARE_END_OBJECT_ACTION()
* \endcode
*/
InstructionMetadata &SetGetter(const gd::String &getter) {
codeExtraInformation.optionalAssociatedInstruction = getter;
codeExtraInformation.accessType = codeExtraInformation.MutatorAndOrAccessor;
return *this;
}
InstructionMetadata &SetMutators(
const std::map<gd::String, gd::String> &mutators) {
codeExtraInformation.optionalMutators = mutators;
codeExtraInformation.accessType = codeExtraInformation.Mutators;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) override {
codeExtraInformation.includeFiles.clear();
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) override {
if (std::find(codeExtraInformation.includeFiles.begin(), codeExtraInformation.includeFiles.end(), includeFile) ==
codeExtraInformation.includeFiles.end())
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
const std::vector<gd::String> &GetIncludeFiles() const override {
return codeExtraInformation.includeFiles;
};
InstructionMetadata &SetCustomCodeGenerator(
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
codeGenerator) {
codeExtraInformation.hasCustomCodeGenerator = true;
codeExtraInformation.customCodeGenerator = codeGenerator;
return *this;
}
InstructionMetadata &RemoveCustomCodeGenerator() {
codeExtraInformation.hasCustomCodeGenerator = false;
std::function<gd::String(Instruction & instruction,
gd::EventsCodeGenerator & codeGenerator,
gd::EventsCodeGenerationContext & context)>
emptyFunction;
codeExtraInformation.customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return codeExtraInformation.hasCustomCodeGenerator; }
/**
* \brief Return the structure containing the information about code
* generation for the instruction.
*
* \deprecated
*/
InstructionMetadata &GetCodeExtraInformation() { return *this; }
std::vector<ParameterMetadata> parameters;
private:
@@ -604,5 +572,3 @@ class GD_CORE_API InstructionMetadata {
};
} // namespace gd
#endif // INSTRUCTIONMETADATA_H

View File

@@ -0,0 +1,201 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <map>
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h"
namespace gd {
class Behavior;
class BehaviorsSharedData;
class MultipleInstructionMetadata;
class InstructionMetadata;
class ExpressionMetadata;
} // namespace gd
namespace gd {
/**
* \brief Contains user-friendly information about instructions and expressions
* (usually for a behavior or an object).
*
* \ingroup Events
*/
class GD_CORE_API InstructionOrExpressionContainerMetadata {
public:
InstructionOrExpressionContainerMetadata(){};
virtual ~InstructionOrExpressionContainerMetadata(){};
/**
* Declare a new condition as being part of the behavior or object.
* \deprecated Prefer using `AddScopedCondition`, to properly namespace
* the condition.
*/
virtual gd::InstructionMetadata &
AddCondition(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the behavior or object.
* \deprecated Prefer using `AddScopedAction`, to properly namespace
* the action.
*/
virtual gd::InstructionMetadata &
AddAction(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new condition as being part of the behavior or object.
*/
virtual gd::InstructionMetadata &
AddScopedCondition(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_,
const gd::String &sentence_, const gd::String &group_,
const gd::String &icon_, const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the behavior or object.
*/
virtual gd::InstructionMetadata &
AddScopedAction(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the extension.
*/
virtual gd::ExpressionMetadata &
AddExpression(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &group_,
const gd::String &smallicon_) = 0;
/**
* Declare a new string expression as being part of the extension.
*/
virtual gd::ExpressionMetadata &
AddStrExpression(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &group_,
const gd::String &smallicon_) = 0;
/**
* \brief Declare a new expression and condition as being part of the
* behavior.
* \note It's recommended to use this function to avoid declaring twice a
* similar expression/condition.
*/
virtual gd::MultipleInstructionMetadata AddExpressionAndCondition(
const gd::String &type, const gd::String &name,
const gd::String &fullname, const gd::String &description,
const gd::String &sentenceName, const gd::String &group,
const gd::String &icon) = 0;
/**
* \brief Declare a new expression, condition and action as being part of the
* behavior.
* \note The action name is prefixed by "Set" (and the namespace, as the
* condition).
* \note It's recommended to use this function to avoid declaring 3 times a
* similar expression/condition/action.
*/
virtual gd::MultipleInstructionMetadata AddExpressionAndConditionAndAction(
const gd::String &type, const gd::String &name,
const gd::String &fullname, const gd::String &description,
const gd::String &sentenceName, const gd::String &group,
const gd::String &icon) = 0;
/**
* \brief Create a new action which is the duplicate of the specified one.
*
* Useful for handling a deprecated action that is just a "copy" of the new
* one.
*/
virtual gd::InstructionMetadata &
AddDuplicatedAction(const gd::String &newActionName,
const gd::String &copiedActionName) = 0;
/**
* \brief Create a new condition which is the duplicate of the specified one.
*
* Useful for handling a deprecated condition that is just a "copy" of the new
* one.
*/
virtual gd::InstructionMetadata &
AddDuplicatedCondition(const gd::String &newConditionName,
const gd::String &copiedConditionName) = 0;
virtual InstructionOrExpressionContainerMetadata &
SetFullName(const gd::String &fullname_) = 0;
virtual InstructionOrExpressionContainerMetadata &
SetDescription(const gd::String &description_) = 0;
/**
* \brief Erase any existing include file and add the specified include.
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the behavior.
*/
virtual InstructionOrExpressionContainerMetadata &
SetIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Add a file to the already existing include files.
*/
virtual InstructionOrExpressionContainerMetadata &
AddIncludeFile(const gd::String &includeFile) = 0;
/**
* Get the help path of the behavior, relative to the GDevelop documentation
* root.
*/
virtual const gd::String &GetHelpPath() const = 0;
/**
* Set the help path of the behavior, relative to the GDevelop documentation
* root.
*
* The behavior instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
virtual InstructionOrExpressionContainerMetadata &
SetHelpPath(const gd::String &path) = 0;
virtual const gd::String &GetName() const = 0;
virtual const gd::String &GetFullName() const = 0;
virtual const gd::String &GetDescription() const = 0;
virtual const gd::String &GetIconFilename() const = 0;
/**
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
virtual std::map<gd::String, gd::InstructionMetadata> &GetAllActions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::InstructionMetadata> &GetAllConditions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::ExpressionMetadata> &GetAllExpressions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::ExpressionMetadata> &
GetAllStrExpressions() = 0;
private:
};
} // namespace gd

View File

@@ -135,11 +135,11 @@ MetadataProvider::GetExtensionAndConditionMetadata(const gd::Platform& platform,
const auto& objects = extension->GetExtensionObjectsTypes();
for (const gd::String& extObjectType : objects) {
const auto& allObjetsConditions =
const auto& allObjectsConditions =
extension->GetAllConditionsForObject(extObjectType);
if (allObjetsConditions.find(conditionType) != allObjetsConditions.end())
if (allObjectsConditions.find(conditionType) != allObjectsConditions.end())
return ExtensionAndMetadata<InstructionMetadata>(
*extension, allObjetsConditions.find(conditionType)->second);
*extension, allObjectsConditions.find(conditionType)->second);
}
const auto& autos = extension->GetBehaviorsTypes();

View File

@@ -1,12 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "MultipleInstructionMetadata.h"
#include "InstructionMetadata.h"
namespace gd {
} // namespace gd

View File

@@ -3,8 +3,8 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef MULTIPLEINSTRUCTIONSMETADATA_H
#define MULTIPLEINSTRUCTIONSMETADATA_H
#pragma once
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h"
@@ -21,7 +21,7 @@ namespace gd {
*
* \ingroup PlatformDefinition
*/
class GD_CORE_API MultipleInstructionMetadata {
class GD_CORE_API MultipleInstructionMetadata : public AbstractFunctionMetadata {
public:
static MultipleInstructionMetadata WithExpressionAndCondition(
gd::ExpressionMetadata &expression, gd::InstructionMetadata &condition) {
@@ -45,7 +45,7 @@ class GD_CORE_API MultipleInstructionMetadata {
const gd::String &type,
const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) {
bool parameterIsOptional = false) override {
if (expression)
expression->AddParameter(
type, label, supplementaryInformation, parameterIsOptional);
@@ -62,7 +62,7 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
MultipleInstructionMetadata &AddCodeOnlyParameter(
const gd::String &type, const gd::String &supplementaryInformation) {
const gd::String &type, const gd::String &supplementaryInformation) override {
if (expression)
expression->AddCodeOnlyParameter(type, supplementaryInformation);
if (condition)
@@ -74,7 +74,7 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \see gd::InstructionMetadata::SetDefaultValue
*/
MultipleInstructionMetadata &SetDefaultValue(const gd::String &defaultValue) {
MultipleInstructionMetadata &SetDefaultValue(const gd::String &defaultValue) override {
if (expression) expression->SetDefaultValue(defaultValue);
if (condition) condition->SetDefaultValue(defaultValue);
if (action) action->SetDefaultValue(defaultValue);
@@ -85,7 +85,7 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
MultipleInstructionMetadata &SetParameterExtraInfo(
const gd::String &defaultValue) {
const gd::String &defaultValue) override {
if (expression) expression->SetParameterExtraInfo(defaultValue);
if (condition) condition->SetParameterExtraInfo(defaultValue);
if (action) action->SetParameterExtraInfo(defaultValue);
@@ -96,7 +96,7 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::SetParameterLongDescription
*/
MultipleInstructionMetadata &SetParameterLongDescription(
const gd::String &longDescription) {
const gd::String &longDescription) override {
if (expression) expression->SetParameterLongDescription(longDescription);
if (condition) condition->SetParameterLongDescription(longDescription);
if (action) action->SetParameterLongDescription(longDescription);
@@ -106,7 +106,7 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \see gd::InstructionMetadata::SetHidden
*/
MultipleInstructionMetadata &SetHidden() {
MultipleInstructionMetadata &SetHidden() override {
if (expression) expression->SetHidden();
if (condition) condition->SetHidden();
if (action) action->SetHidden();
@@ -136,47 +136,47 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
}
MultipleInstructionMetadata &SetFunctionName(const gd::String &functionName) {
MultipleInstructionMetadata &SetFunctionName(const gd::String &functionName) override {
if (expression) expression->SetFunctionName(functionName);
if (condition) condition->SetFunctionName(functionName);
if (action) action->GetCodeExtraInformation().SetFunctionName(functionName);
if (action) action->SetFunctionName(functionName);
return *this;
}
MultipleInstructionMetadata &SetGetter(const gd::String &getter) {
if (expression) expression->SetFunctionName(getter);
if (condition) condition->SetFunctionName(getter);
if (action) action->GetCodeExtraInformation().SetGetter(getter);
if (action) action->SetGetter(getter);
return *this;
}
MultipleInstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
MultipleInstructionMetadata &SetIncludeFile(const gd::String &includeFile) override {
if (expression)
expression->GetCodeExtraInformation().SetIncludeFile(includeFile);
expression->SetIncludeFile(includeFile);
if (condition)
condition->GetCodeExtraInformation().SetIncludeFile(includeFile);
if (action) action->GetCodeExtraInformation().SetIncludeFile(includeFile);
condition->SetIncludeFile(includeFile);
if (action) action->SetIncludeFile(includeFile);
return *this;
}
MultipleInstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
MultipleInstructionMetadata &AddIncludeFile(const gd::String &includeFile) override {
if (expression)
expression->GetCodeExtraInformation().AddIncludeFile(includeFile);
if (condition)
condition->GetCodeExtraInformation().AddIncludeFile(includeFile);
if (action) action->GetCodeExtraInformation().AddIncludeFile(includeFile);
condition->AddIncludeFile(includeFile);
if (action) action->AddIncludeFile(includeFile);
return *this;
}
/**
* \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 override {
if (expression)
return expression->GetCodeExtraInformation().GetIncludeFiles();
if (condition)
return condition->GetCodeExtraInformation().GetIncludeFiles();
if (action) return action->GetCodeExtraInformation().GetIncludeFiles();
return condition->GetIncludeFiles();
if (action) return action->GetIncludeFiles();
// It can't actually happen.
throw std::logic_error("no instruction metadata");
}
@@ -184,7 +184,7 @@ class GD_CORE_API MultipleInstructionMetadata {
/**
* \see gd::InstructionMetadata::SetPrivate
*/
MultipleInstructionMetadata &SetPrivate() {
MultipleInstructionMetadata &SetPrivate() override {
if (expression) expression->SetPrivate();
if (condition) condition->SetPrivate();
if (action) action->SetPrivate();
@@ -218,6 +218,42 @@ class GD_CORE_API MultipleInstructionMetadata {
return *this;
}
/**
* Set that the instruction can be used in layouts or external events.
*/
MultipleInstructionMetadata &SetRelevantForLayoutEventsOnly() override {
if (condition) condition->SetRelevantForLayoutEventsOnly();
if (action) action->SetRelevantForLayoutEventsOnly();
return *this;
}
/**
* Set that the instruction can be used in function events.
*/
MultipleInstructionMetadata &SetRelevantForFunctionEventsOnly() override {
if (condition) condition->SetRelevantForFunctionEventsOnly();
if (action) action->SetRelevantForFunctionEventsOnly();
return *this;
}
/**
* Set that the instruction can be used in asynchronous function events.
*/
MultipleInstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
if (condition) condition->SetRelevantForAsynchronousFunctionEventsOnly();
if (action) action->SetRelevantForAsynchronousFunctionEventsOnly();
return *this;
}
/**
* Set that the instruction can be used in custom object events.
*/
MultipleInstructionMetadata &SetRelevantForCustomObjectEventsOnly() override {
if (condition) condition->SetRelevantForCustomObjectEventsOnly();
if (action) action->SetRelevantForCustomObjectEventsOnly();
return *this;
}
/**
* \brief Don't use, only here to fulfill Emscripten bindings requirements.
*/
@@ -242,5 +278,3 @@ class GD_CORE_API MultipleInstructionMetadata {
};
} // namespace gd
#endif // MULTIPLEINSTRUCTIONSMETADATA_H

View File

@@ -3,8 +3,10 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef OBJECTMETADATA_H
#define OBJECTMETADATA_H
#pragma once
#include "InstructionOrExpressionContainerMetadata.h"
#include <functional>
#include <map>
#include <set>
@@ -32,7 +34,7 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API ObjectMetadata {
class GD_CORE_API ObjectMetadata : public InstructionOrExpressionContainerMetadata {
public:
/**
* \brief Construct an object metadata, using a "blueprint" object that will
@@ -57,7 +59,7 @@ class GD_CORE_API ObjectMetadata {
/**
* \brief Construct an object metadata, with a function that will be called
* to instanciate a new object.
* to instantiate a new object.
*/
ObjectMetadata(const gd::String& extensionNamespace_,
const gd::String& name_,
@@ -79,7 +81,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new action as being part of the extension.
@@ -92,7 +94,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new condition as being part of the object.
@@ -103,7 +105,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* Declare a new action as being part of the object.
@@ -114,7 +116,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new expression as being part of the extension.
@@ -123,7 +125,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new string expression as being part of the extension.
*/
@@ -131,7 +133,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_);
const gd::String& smallicon_) override;
/**
* \brief Declare a new expression and condition as being part of the
@@ -146,7 +148,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Declare a new expression, condition and action as being part of the
@@ -163,7 +165,7 @@ class GD_CORE_API ObjectMetadata {
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon);
const gd::String& icon) override;
/**
* \brief Create a new action which is the duplicate of the specified one.
@@ -172,7 +174,7 @@ class GD_CORE_API ObjectMetadata {
* one.
*/
gd::InstructionMetadata& AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName);
const gd::String& newActionName, const gd::String& copiedActionName) override;
/**
* \brief Create a new condition which is the duplicate of the specified one.
@@ -182,23 +184,23 @@ class GD_CORE_API ObjectMetadata {
*/
gd::InstructionMetadata& AddDuplicatedCondition(
const gd::String& newConditionName,
const gd::String& copiedConditionName);
const gd::String& copiedConditionName) override;
/**
* \brief Set the name shown to the user.
*/
ObjectMetadata& SetFullName(const gd::String& fullname_);
ObjectMetadata& SetFullName(const gd::String& fullname_) override;
/**
* \brief Set the description shown to the user.
*/
ObjectMetadata& SetDescription(const gd::String& description_);
ObjectMetadata& SetDescription(const gd::String& description_) override;
/**
* \brief Get the help path of the object, relative to the GDevelop
* documentation root.
*/
const gd::String& GetHelpPath() const { return helpPath; }
const gd::String& GetHelpPath() const override { return helpPath; }
/**
* \brief Set the help path of the object, relative to the GDevelop
@@ -207,7 +209,7 @@ class GD_CORE_API ObjectMetadata {
* The object instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
ObjectMetadata& SetHelpPath(const gd::String& path) {
ObjectMetadata& SetHelpPath(const gd::String& path) override {
helpPath = path;
return *this;
}
@@ -224,7 +226,7 @@ class GD_CORE_API ObjectMetadata {
/**
* \brief The "capabilities" that are offered by the base object that are
* *not* supported by this object, and should be hidden in the editor
* inferface.
* interface.
*/
const std::set<gd::String>& GetUnsupportedBaseObjectCapabilities() const {
return unsupportedBaseObjectCapabilities;
@@ -232,7 +234,7 @@ class GD_CORE_API ObjectMetadata {
/**
* \brief Add a "capability" that is offered by the base object that is *not*
* supported by this object, and should be hidden in the editor inferface.
* supported by this object, and should be hidden in the editor interface.
*/
ObjectMetadata& AddUnsupportedBaseObjectCapability(
const gd::String& capability) {
@@ -242,18 +244,18 @@ class GD_CORE_API ObjectMetadata {
/**
* \brief Check if a "capability" that is offered by the base object is *not*
* supported by this object, and should be hidden in the editor inferface.
* supported by this object, and should be hidden in the editor interface.
*/
bool IsUnsupportedBaseObjectCapability(const gd::String& capability) const {
return unsupportedBaseObjectCapabilities.find(capability) != unsupportedBaseObjectCapabilities.end();
}
const gd::String& GetName() const { return name; }
const gd::String& GetFullName() const { return fullname; }
const gd::String& GetName() const override { return name; }
const gd::String& GetFullName() const override { return fullname; }
const gd::String& GetCategoryFullName() const { return categoryFullName; }
const gd::String& GetHelpUrl() const { return helpUrl; }
const gd::String& GetDescription() const { return description; }
const gd::String& GetIconFilename() const { return iconFilename; }
const gd::String& GetDescription() const override { return description; }
const gd::String& GetIconFilename() const override { return iconFilename; }
/**
* \brief Set the URL pointing to the help page about this object
@@ -267,33 +269,33 @@ class GD_CORE_API ObjectMetadata {
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the object.
*/
ObjectMetadata& SetIncludeFile(const gd::String& includeFile);
ObjectMetadata& SetIncludeFile(const gd::String& includeFile) override;
/**
* \brief Add a file to the already existing include files.
*/
ObjectMetadata& AddIncludeFile(const gd::String& includeFile);
ObjectMetadata& AddIncludeFile(const gd::String& includeFile) override;
/**
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() { return actionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() override { return actionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() { return conditionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() override { return conditionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() { return expressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() override { return expressionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() { return strExpressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() override { return strExpressionsInfos; };
/**
* \brief Set the object to be hidden in the IDE.
@@ -341,4 +343,3 @@ class GD_CORE_API ObjectMetadata {
};
} // namespace gd
#endif // OBJECTMETADATA_H

View File

@@ -209,10 +209,10 @@ class GD_CORE_API ParameterMetadata {
* \brief Return the expression type from the parameter type.
* Declinations of "number" and "string" types (like "forceMultiplier" or
* "sceneName") are replaced by "number" and "string".
* \deprecated Use gd::ValueTypeMetadata instead.
* \deprecated Use gd::ValueTypeMetadata or gd::GetExpressionPrimitiveValueType instead.
*/
static const gd::String &GetExpressionValueType(const gd::String &parameterType) {
return gd::ValueTypeMetadata::GetPrimitiveValueType(parameterType);
return gd::ValueTypeMetadata::GetExpressionPrimitiveValueType(parameterType);
}
/** \name Serialization

View File

@@ -35,17 +35,40 @@ void ValueTypeMetadata::UnserializeFrom(const SerializerElement& element) {
const gd::String ValueTypeMetadata::numberType = "number";
const gd::String ValueTypeMetadata::stringType = "string";
const gd::String ValueTypeMetadata::variableType = "variable";
const gd::String ValueTypeMetadata::booleanType = "boolean";
const gd::String &ValueTypeMetadata::GetPrimitiveValueType(const gd::String &parameterType) {
if (parameterType == "number" || gd::ValueTypeMetadata::IsTypeExpression("number", parameterType)) {
const gd::String &ValueTypeMetadata::GetExpressionPrimitiveValueType(
const gd::String &parameterType) {
if (parameterType == "number" ||
gd::ValueTypeMetadata::IsTypeExpression("number", parameterType)) {
return ValueTypeMetadata::numberType;
}
if (parameterType == "string" || gd::ValueTypeMetadata::IsTypeExpression("string", parameterType)) {
if (parameterType == "string" ||
gd::ValueTypeMetadata::IsTypeExpression("string", parameterType)) {
return ValueTypeMetadata::stringType;
}
return parameterType;
}
const gd::String &
ValueTypeMetadata::GetPrimitiveValueType(const gd::String &parameterType) {
if (parameterType == "variable" ||
gd::ValueTypeMetadata::IsTypeExpression("variable", parameterType)) {
return ValueTypeMetadata::variableType;
}
if (parameterType == "boolean" || parameterType == "yesorno" ||
parameterType == "trueorfalse") {
return ValueTypeMetadata::booleanType;
}
// These 2 types are not strings from the code generator point of view,
// but it is for event-based extensions.
if (parameterType == "key" || parameterType == "mouse") {
return ValueTypeMetadata::stringType;
}
return GetExpressionPrimitiveValueType(parameterType);
}
const gd::String ValueTypeMetadata::numberValueType = "number";
const gd::String ValueTypeMetadata::booleanValueType = "boolean";
const gd::String ValueTypeMetadata::colorValueType = "color";

View File

@@ -178,6 +178,16 @@ class GD_CORE_API ValueTypeMetadata {
} else if (type == "variable") {
return parameterType == "objectvar" || parameterType == "globalvar" ||
parameterType == "scenevar";
} else if (type == "resource") {
return parameterType == "fontResource" ||
parameterType == "soundfile" ||
parameterType == "musicfile" ||
parameterType == "bitmapFontResource" ||
parameterType == "imageResource" ||
parameterType == "jsonResource" ||
parameterType == "tilemapResource" ||
parameterType == "tilesetResource" ||
parameterType == "model3DResource";
}
return false;
}
@@ -186,10 +196,23 @@ class GD_CORE_API ValueTypeMetadata {
* \brief Return the expression type from the parameter type.
* Declinations of "number" and "string" types (like "forceMultiplier" or
* "sceneName") are replaced by "number" and "string".
*
* \note It only maps string and number types.
*/
static const gd::String &GetExpressionPrimitiveValueType(const gd::String &parameterType);
/**
* \brief Return the primitive type from the parameter type.
* Declinations of "number" and "string" types (like "forceMultiplier" or
* "sceneName") are replaced by "number" and "string".
*
* \note It also maps variable and boolean types.
*/
static const gd::String &GetPrimitiveValueType(const gd::String &parameterType);
static const gd::String numberType;
static const gd::String stringType;
static const gd::String variableType;
static const gd::String booleanType;
/**
* \brief Return the ValueTypeMetadata name for a property type.

View File

@@ -653,7 +653,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllActions().begin();
it != GetAllActions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllActions().erase(it++);
} else
++it;
@@ -663,7 +663,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllConditions().begin();
it != GetAllConditions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllConditions().erase(it++);
} else
++it;
@@ -673,7 +673,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllExpressions().begin();
it != GetAllExpressions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllExpressions().erase(it++);
} else
++it;
@@ -683,7 +683,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
GetAllStrExpressions().begin();
it != GetAllStrExpressions().end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
GetAllStrExpressions().erase(it++);
} else
++it;
@@ -699,7 +699,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.actionsInfos.begin();
it != obj.actionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.actionsInfos.erase(it++);
} else
++it;
@@ -709,7 +709,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.conditionsInfos.begin();
it != obj.conditionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.conditionsInfos.erase(it++);
} else
++it;
@@ -719,7 +719,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.expressionsInfos.begin();
it != obj.expressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.expressionsInfos.erase(it++);
} else
++it;
@@ -729,7 +729,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.strExpressionsInfos.begin();
it != obj.strExpressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.strExpressionsInfos.erase(it++);
} else
++it;
@@ -746,7 +746,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.actionsInfos.begin();
it != obj.actionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.actionsInfos.erase(it++);
} else
++it;
@@ -756,7 +756,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.conditionsInfos.begin();
it != obj.conditionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.conditionsInfos.erase(it++);
} else
++it;
@@ -766,7 +766,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.expressionsInfos.begin();
it != obj.expressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.expressionsInfos.erase(it++);
} else
++it;
@@ -776,7 +776,7 @@ void PlatformExtension::StripUnimplementedInstructionsAndExpressions() {
obj.strExpressionsInfos.begin();
it != obj.strExpressionsInfos.end();) {
if (it->second.codeExtraInformation.functionCallName.empty() &&
!it->second.codeExtraInformation.HasCustomCodeGenerator()) {
!it->second.HasCustomCodeGenerator()) {
obj.strExpressionsInfos.erase(it++);
} else
++it;

View File

@@ -42,7 +42,7 @@ class GD_CORE_API DependenciesAnalyzer {
*
* You can also call then
* DependenciesAnalyzer::ExternalEventsCanBeCompiledForAScene to check if the
* external events can be compiled separatly and called by a scene. \see
* external events can be compiled separately and called by a scene. \see
* DependenciesAnalyzer::ExternalEventsCanBeCompiledForAScene
*/
DependenciesAnalyzer(const gd::Project& project_,

View File

@@ -84,6 +84,9 @@ void ReadOnlyArbitraryEventsWorker::VisitEventList(const gd::EventsList& events)
DoVisitEventList(events);
for (std::size_t i = 0; i < events.size(); ++i) {
if (shouldStopIteration) {
break;
}
events[i].AcceptVisitor(*this);
if (events[i].CanHaveSubEvents()) {
@@ -98,11 +101,17 @@ void ReadOnlyArbitraryEventsWorker::VisitEvent(const gd::BaseEvent& event) {
const vector<const gd::InstructionsList*> conditionsVectors =
event.GetAllConditionsVectors();
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
if (shouldStopIteration) {
break;
}
VisitInstructionList(*conditionsVectors[j], true);
}
const vector<const gd::InstructionsList*> actionsVectors = event.GetAllActionsVectors();
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
if (shouldStopIteration) {
break;
}
VisitInstructionList(*actionsVectors[j], false);
}
}
@@ -116,6 +125,9 @@ void ReadOnlyArbitraryEventsWorker::VisitInstructionList(
DoVisitInstructionList(instructions, areConditions);
for (std::size_t i = 0; i < instructions.size(); ++i) {
if (shouldStopIteration) {
break;
}
VisitInstruction(instructions[i], areConditions);
if (!instructions[i].GetSubInstructions().empty()) {
VisitInstructionList(instructions[i].GetSubInstructions(),
@@ -129,6 +141,10 @@ void ReadOnlyArbitraryEventsWorker::VisitInstruction(const gd::Instruction& inst
DoVisitInstruction(instruction, isCondition);
}
void ReadOnlyArbitraryEventsWorker::StopAnyEventIteration() {
shouldStopIteration = true;
}
ReadOnlyArbitraryEventsWorkerWithContext::~ReadOnlyArbitraryEventsWorkerWithContext() {}
} // namespace gd

View File

@@ -144,7 +144,7 @@ class GD_CORE_API ArbitraryEventsWorkerWithContext
*/
class GD_CORE_API ReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
public:
ReadOnlyArbitraryEventsWorker(){};
ReadOnlyArbitraryEventsWorker() : shouldStopIteration(false) {};
virtual ~ReadOnlyArbitraryEventsWorker();
/**
@@ -152,6 +152,9 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
*/
void Launch(const gd::EventsList& events) { VisitEventList(events); };
protected:
void StopAnyEventIteration() override;
private:
void VisitEventList(const gd::EventsList& events);
void VisitEvent(const gd::BaseEvent& event) override;
@@ -188,6 +191,8 @@ class GD_CORE_API ReadOnlyArbitraryEventsWorker : private ReadOnlyEventVisitor {
*/
virtual void DoVisitInstruction(const gd::Instruction& instruction,
bool isCondition) {};
bool shouldStopIteration;
};
/**

View File

@@ -0,0 +1,175 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "EventsFunctionSelfCallChecker.h"
#include "GDCore/Events/Expression.h"
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsBasedObject.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace gd {
/**
* \brief Check the type of the first condition or action.
*/
class GD_CORE_API FirstInstructionTypeChecker
: public ReadOnlyArbitraryEventsWorker {
public:
FirstInstructionTypeChecker(const gd::String &eventFunctionType_,
const bool isEventFunctionCondition_)
: eventFunctionType(eventFunctionType_),
isEventFunctionCondition(isEventFunctionCondition_),
isOnlyCallingItself(false){};
virtual ~FirstInstructionTypeChecker(){};
void DoVisitInstruction(const gd::Instruction &instruction,
bool isCondition) override {
if (isCondition == isEventFunctionCondition) {
isOnlyCallingItself = instruction.GetType() == eventFunctionType;
StopAnyEventIteration();
}
};
bool isOnlyCallingItself;
private:
gd::String eventFunctionType;
bool isEventFunctionCondition;
};
/**
* \brief Check the type of the first condition or action.
*/
class GD_CORE_API FirstActionExpressionTypeChecker
: public ReadOnlyArbitraryEventsWorker,
ExpressionParser2NodeWorker {
public:
FirstActionExpressionTypeChecker(const gd::Platform &platform_,
const gd::String &eventFunctionType_)
: platform(platform_), eventFunctionType(eventFunctionType_),
isOnlyCallingItself(false){};
virtual ~FirstActionExpressionTypeChecker(){};
void DoVisitInstruction(const gd::Instruction &instruction,
bool isCondition) override {
// Typically, it should be a "return" action.
if (!isCondition) {
gd::String lastObjectParameter = "";
const gd::InstructionMetadata &instrInfos =
MetadataProvider::GetActionMetadata(platform, instruction.GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].GetType()) ||
ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].GetType())) {
auto node = instruction.GetParameter(pNb).GetRootNode();
node->Visit(*this);
}
}
StopAnyEventIteration();
}
}
// Only check expressions that directly calls a function.
void OnVisitFunctionCallNode(FunctionCallNode &node) override {
isOnlyCallingItself |= node.functionName == eventFunctionType;
}
// Handle extra parenthesis.
void OnVisitSubExpressionNode(SubExpressionNode &node) override {
node.expression->Visit(*this);
}
void OnVisitOperatorNode(OperatorNode &node) override {}
// Handle sign that could have been forgotten
void OnVisitUnaryOperatorNode(UnaryOperatorNode &node) override {
node.factor->Visit(*this);
}
void OnVisitNumberNode(NumberNode &node) override {}
void OnVisitTextNode(TextNode &node) override {}
void OnVisitVariableNode(VariableNode &node) override {}
void OnVisitVariableAccessorNode(VariableAccessorNode &node) override {}
void OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode &node) override {}
void OnVisitIdentifierNode(IdentifierNode &node) override {}
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode &node) override {}
void OnVisitEmptyNode(EmptyNode &node) override {}
bool isOnlyCallingItself;
private:
const gd::Platform &platform;
gd::String eventFunctionType;
};
bool EventsFunctionSelfCallChecker::IsOnlyCallingItself(
const gd::Project &project, const gd::String &functionFullType,
const gd::EventsFunction &eventsFunction) {
bool isOnlyCallingItself = false;
if (eventsFunction.IsExpression()) {
FirstActionExpressionTypeChecker eventWorker(project.GetCurrentPlatform(),
functionFullType);
eventWorker.Launch(eventsFunction.GetEvents());
isOnlyCallingItself = eventWorker.isOnlyCallingItself;
} else {
FirstInstructionTypeChecker eventWorker(functionFullType,
!eventsFunction.IsAction());
eventWorker.Launch(eventsFunction.GetEvents());
isOnlyCallingItself = eventWorker.isOnlyCallingItself;
}
return isOnlyCallingItself;
}
bool EventsFunctionSelfCallChecker::IsFreeFunctionOnlyCallingItself(
const gd::Project &project,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsFunction &eventsFunction) {
return IsOnlyCallingItself(
project,
PlatformExtension::GetEventsFunctionFullType(
eventsFunctionsExtension.GetName(), eventsFunction.GetName()),
eventsFunction);
}
bool EventsFunctionSelfCallChecker::IsBehaviorFunctionOnlyCallingItself(
const gd::Project &project,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::EventsFunction &eventsFunction) {
return IsOnlyCallingItself(
project,
PlatformExtension::GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(), eventsBasedBehavior.GetName(),
eventsFunction.GetName()),
eventsFunction);
}
bool EventsFunctionSelfCallChecker::IsObjectFunctionOnlyCallingItself(
const gd::Project &project,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsBasedObject &eventsBasedObject,
const gd::EventsFunction &eventsFunction) {
return IsOnlyCallingItself(project,
PlatformExtension::GetObjectEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedObject.GetName(),
eventsFunction.GetName()),
eventsFunction);
}
} // namespace gd

View File

@@ -0,0 +1,64 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/String.h"
#include <vector>
namespace gd {
class Project;
class EventsFunctionsExtension;
class EventsFunctionsContainer;
class EventsFunction;
class EventsBasedBehavior;
class EventsBasedObject;
} // namespace gd
namespace gd {
/**
* \brief Check if functions are only calling themselves.
*
* It allows to detect mistakes when implementing functions for compatibility
* after a function renaming.
* Infinite loops can happens when the legacy function call itself instead of
* the new function.
*
* \note Only the first instruction or the expressions of the first action is
* checked.
*/
class GD_CORE_API EventsFunctionSelfCallChecker {
public:
/**
* \brief Check if a free function is only calling itself.
*/
static bool IsFreeFunctionOnlyCallingItself(
const gd::Project &project,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsFunction &eventsFunction);
/**
* \brief Check if a behavior function is only calling itself.
*/
static bool IsBehaviorFunctionOnlyCallingItself(
const gd::Project &project,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::EventsFunction &eventsFunction);
/**
* \brief Check if an object function is only calling itself.
*/
static bool IsObjectFunctionOnlyCallingItself(
const gd::Project &project,
const gd::EventsFunctionsExtension &eventsFunctionsExtension,
const gd::EventsBasedObject &eventsBasedObject,
const gd::EventsFunction &eventsFunction);
private:
static bool IsOnlyCallingItself(const gd::Project &project,
const gd::String &functionFullType,
const gd::EventsFunction &eventsFunction);
};
} // namespace gd

View File

@@ -555,6 +555,22 @@ void EventsRefactorer::RemoveObjectInEvents(const gd::Platform& platform,
}
}
gd::String ReplaceAllOccurrencesCaseInsensitive(gd::String context,
const gd::String& from,
const gd::String& to) {
size_t lookHere = 0;
size_t foundHere;
size_t fromSize = from.size();
size_t toSize = to.size();
while ((foundHere = context.FindCaseInsensitive(from, lookHere)) !=
gd::String::npos) {
context.replace(foundHere, fromSize, to);
lookHere = foundHere + toSize;
}
return context;
}
std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
@@ -570,6 +586,32 @@ std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
for (std::size_t i = 0; i < events.size(); ++i) {
bool eventModified = false;
std::vector<gd::Expression*> allObjectExpressions =
events[i].GetAllObjectExpressions();
for (std::size_t j = 0; j < allObjectExpressions.size(); ++j) {
gd::String newExpressionPlainString =
matchCase ? allObjectExpressions[j]->GetPlainString().FindAndReplace(
toReplace, newString, true)
: ReplaceAllOccurrencesCaseInsensitive(
allObjectExpressions[j]->GetPlainString(),
toReplace,
newString);
if (newExpressionPlainString !=
allObjectExpressions[j]->GetPlainString()) {
*allObjectExpressions[j] = gd::Expression(newExpressionPlainString);
if (!eventModified) {
modifiedEvents.push_back(EventsSearchResult(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventModified = true;
}
}
}
if (inConditions) {
vector<gd::InstructionsList*> conditionsVectors =
events[i].GetAllConditionsVectors();
@@ -642,22 +684,6 @@ std::vector<EventsSearchResult> EventsRefactorer::ReplaceStringInEvents(
return modifiedEvents;
}
gd::String ReplaceAllOccurencesCaseUnsensitive(gd::String context,
gd::String from,
const gd::String& to) {
size_t lookHere = 0;
size_t foundHere;
size_t fromSize = from.size();
size_t toSize = to.size();
while ((foundHere = context.FindCaseInsensitive(from, lookHere)) !=
gd::String::npos) {
context.replace(foundHere, fromSize, to);
lookHere = foundHere + toSize;
}
return context;
}
bool EventsRefactorer::ReplaceStringInActions(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
gd::InstructionsList& actions,
@@ -673,7 +699,7 @@ bool EventsRefactorer::ReplaceStringInActions(gd::ObjectsContainer& project,
matchCase
? actions[aId].GetParameter(pNb).GetPlainString().FindAndReplace(
toReplace, newString, true)
: ReplaceAllOccurencesCaseUnsensitive(
: ReplaceAllOccurrencesCaseInsensitive(
actions[aId].GetParameter(pNb).GetPlainString(),
toReplace,
newString);
@@ -713,7 +739,7 @@ bool EventsRefactorer::ReplaceStringInConditions(
.GetParameter(pNb)
.GetPlainString()
.FindAndReplace(toReplace, newString, true)
: ReplaceAllOccurencesCaseUnsensitive(
: ReplaceAllOccurrencesCaseInsensitive(
conditions[cId].GetParameter(pNb).GetPlainString(),
toReplace,
newString);
@@ -749,7 +775,7 @@ bool EventsRefactorer::ReplaceStringInEventSearchableStrings(
for (std::size_t sNb = 0; sNb < stringEvent.size(); ++sNb) {
gd::String newStringEvent =
matchCase ? stringEvent[sNb].FindAndReplace(toReplace, newString, true)
: ReplaceAllOccurencesCaseUnsensitive(
: ReplaceAllOccurrencesCaseInsensitive(
stringEvent[sNb], toReplace, newString);
newEventStrings.push_back(newStringEvent);
}
@@ -789,6 +815,24 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
for (std::size_t i = 0; i < events.size(); ++i) {
bool eventAddedInResults = false;
std::vector<gd::Expression*> allObjectExpressions =
events[i].GetAllObjectExpressions();
for (std::size_t j = 0; j < allObjectExpressions.size(); ++j) {
size_t foundPosition =
matchCase
? allObjectExpressions[j]->GetPlainString().find(search)
: allObjectExpressions[j]->GetPlainString().FindCaseInsensitive(
search);
if (foundPosition != gd::String::npos && !eventAddedInResults) {
results.push_back(EventsSearchResult(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventAddedInResults = true;
}
}
if (inConditions) {
vector<gd::InstructionsList*> conditionsVectors =
events[i].GetAllConditionsVectors();
@@ -803,6 +847,7 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventAddedInResults = true;
}
}
}
@@ -820,6 +865,7 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
i));
eventAddedInResults = true;
}
}
}

View File

@@ -159,12 +159,29 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
void OnVisitNumberNode(NumberNode& node) override {
ReportAnyError(node);
childType = Type::Number;
CheckType(parentType, childType, node.location);
if (parentType == Type::String) {
RaiseTypeError(
_("You entered a number, but a text was expected (in quotes)."),
node.location);
} else if (parentType != Type::Number &&
parentType != Type::NumberOrString) {
RaiseTypeError(_("You entered a number, but this type was expected:") +
" " + TypeToString(parentType),
node.location);
}
}
void OnVisitTextNode(TextNode& node) override {
ReportAnyError(node);
childType = Type::String;
CheckType(parentType, childType, node.location);
if (parentType == Type::Number) {
RaiseTypeError(_("You entered a text, but a number was expected."),
node.location);
} else if (parentType != Type::String &&
parentType != Type::NumberOrString) {
RaiseTypeError(_("You entered a text, but this type was expected:") +
" " + TypeToString(parentType),
node.location);
}
}
void OnVisitVariableNode(VariableNode& node) override {
ReportAnyError(node);
@@ -172,7 +189,21 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
node.child->Visit(*this);
}
childType = Type::Variable;
CheckType(parentType, childType, node.location);
if (parentType == Type::String) {
RaiseTypeError(_("Variables must be surrounded by VariableString()."),
node.location);
} else if (parentType == Type::Number) {
RaiseTypeError(_("Variables must be surrounded by Variable()."),
node.location);
} else if (parentType == Type::NumberOrString) {
RaiseTypeError(
_("Variables must be surrounded by Variable() or VariableString()."),
node.location);
} else if (parentType != Type::Variable) {
RaiseTypeError(_("You entered a variable, but this type was expected:") +
" " + TypeToString(parentType),
node.location);
}
}
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
ReportAnyError(node);
@@ -284,32 +315,6 @@ class GD_CORE_API ExpressionValidator : public ExpressionParser2NodeWorker {
RaiseError("invalid_operator", message, location);
}
void CheckType(Type expect, Type actual, const ExpressionParserLocation &location) {
if (actual == Type::String) {
if (expect == Type::Number) {
RaiseTypeError(_("You entered a text, but a number was expected."),
location);
}
else if (expect != Type::String && expect != Type::NumberOrString) {
RaiseTypeError(
_("You entered a text, but this type was expected:") + " " + TypeToString(expect),
location);
}
}
else if (actual == Type::Number) {
if (expect == Type::String) {
RaiseTypeError(
_("You entered a number, but a text was expected (in quotes)."),
location);
}
else if (expect != Type::Number && expect != Type::NumberOrString) {
RaiseTypeError(
_("You entered a number, but this type was expected:") + " " + TypeToString(expect),
location);
}
}
}
static Type StringToType(const gd::String &type);
static const gd::String &TypeToString(Type type);
static const gd::String unknownTypeString;

View File

@@ -87,11 +87,22 @@ protected:
std::unique_ptr<gd::ExpressionNode> &parameterNode,
size_t parameterIndex, const gd::String &lastObjectName) {
if (parameterMetadata.GetType() == "layer") {
// Remove quotes, it won't match if it's not a literal anyway.
lastLayerName = expressionPlainString.substr(
parameterNode->location.GetStartPosition() + 1,
parameterNode->location.GetEndPosition() -
parameterNode->location.GetStartPosition() - 2);
if (parameterNode->location.GetEndPosition() -
parameterNode->location.GetStartPosition() <
2) {
// This is either the base layer or an invalid layer name.
// Keep it as is.
lastLayerName = expressionPlainString.substr(
parameterNode->location.GetStartPosition(),
parameterNode->location.GetEndPosition() -
parameterNode->location.GetStartPosition());
} else {
// Remove quotes, so it can be compared to the layer name.
lastLayerName = expressionPlainString.substr(
parameterNode->location.GetStartPosition() + 1,
parameterNode->location.GetEndPosition() -
parameterNode->location.GetStartPosition() - 2);
}
}
if (parameterMetadata.GetType() == parameterType) {
auto parameterExpressionPlainString = expressionPlainString.substr(
@@ -143,9 +154,15 @@ bool ProjectElementRenamer::DoVisitInstruction(gd::Instruction &instruction,
const gd::Expression &parameterValue, size_t parameterIndex,
const gd::String &lastObjectName) {
if (parameterMetadata.GetType() == "layer") {
// Remove quotes, it won't match if it's not a literal anyway.
lastLayerName = parameterValue.GetPlainString().substr(
1, parameterValue.GetPlainString().length() - 2);
if (parameterValue.GetPlainString().length() < 2) {
// This is either the base layer or an invalid layer name.
// Keep it as is.
lastLayerName = parameterValue.GetPlainString();
} else {
// Remove quotes, so it can be compared to the layer name.
lastLayerName = parameterValue.GetPlainString().substr(
1, parameterValue.GetPlainString().length() - 2);
}
}
if (parameterMetadata.GetType() == parameterType &&
@@ -165,7 +182,6 @@ bool ProjectElementRenamer::DoVisitInstruction(gd::Instruction &instruction,
node->Visit(finder);
if (finder.GetOccurrences().size() > 0) {
gd::String newNameWithQuotes = "\"" + newName + "\"";
gd::String oldParameterValue = parameterValue.GetPlainString();
gd::String newParameterValue;

View File

@@ -82,7 +82,7 @@ bool UsedExtensionsFinder::DoVisitInstruction(gd::Instruction& instruction,
// Expressions scanner
// Ignore litterals nodes
// Ignore literals nodes
void UsedExtensionsFinder::OnVisitNumberNode(NumberNode& node){};
void UsedExtensionsFinder::OnVisitTextNode(TextNode& node){};

View File

@@ -144,7 +144,7 @@ void ExtensionsLoader::LoadExtension(const gd::String &fullpath,
bool forgiving) {
if (platform.GetExtensionCreateFunctionName().empty()) {
cout << "Unable to load extension " << fullpath << ":" << endl;
cout << "The plaftorm does not support extensions creation." << endl;
cout << "The platform does not support extensions creation." << endl;
return;
}

View File

@@ -35,7 +35,7 @@ class GD_CORE_API ExtensionsLoader {
* \param platform The platform the extensions belongs to.
* \param forgiving If set to true, files will try to be opened, but a failure
* when searching for the platform creation function symbol won't be logged as
* an error. (All other errors are still reparted as usual).
* an error. (All other errors are still reported as usual).
*
* \note Extensions files must have extensions *.xgd(w|l|m)(e),
* w for Windows, l for Linux, m for Mac, e for Edittime extensions.
@@ -51,7 +51,7 @@ class GD_CORE_API ExtensionsLoader {
* \param platform The platform the extension belongs to.
* \param forgiving If set to true, files will try to be opened, but a failure
* when searching for the platform creation function symbol won't be logged as
* an error. (All other errors are still reparted as usual).
* an error. (All other errors are still reported as usual).
*/
static void LoadExtension(const gd::String& fullpath,
gd::Platform& platform,

View File

@@ -45,6 +45,11 @@ void ArbitraryResourceWorker::ExposeTileset(gd::String& tilesetName){
// do.
};
void ArbitraryResourceWorker::ExposeModel3D(gd::String& resourceName){
// Nothing to do by default - each child class can define here the action to
// do.
};
void ArbitraryResourceWorker::ExposeVideo(gd::String& videoName){
// Nothing to do by default - each child class can define here the action to
// do.
@@ -66,7 +71,7 @@ void ArbitraryResourceWorker::ExposeAudio(gd::String& audioName) {
}
}
// For compatibility with older projects (where events were refering to files
// For compatibility with older projects (where events were referring to files
// directly), we consider that this resource name is a filename, and so expose
// it as a file.
ExposeFile(audioName);
@@ -83,7 +88,7 @@ void ArbitraryResourceWorker::ExposeFont(gd::String& fontName) {
}
}
// For compatibility with older projects (where events were refering to files
// For compatibility with older projects (where events were referring to files
// directly), we consider that this resource name is a filename, and so expose
// it as a file.
ExposeFile(fontName);
@@ -146,6 +151,8 @@ void ArbitraryResourceWorker::ExposeEmbeddeds(gd::String& resourceName) {
ExposeTileset(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "video") {
ExposeVideo(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "model3D") {
ExposeModel3D(potentiallyUpdatedTargetResourceName);
}
if (potentiallyUpdatedTargetResourceName != targetResourceName) {
@@ -233,6 +240,10 @@ class ResourceWorkerInEventsWorker : public ArbitraryEventsWorker {
gd::String updatedParameterValue = parameterValue;
worker.ExposeTileset(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
} else if (parameterMetadata.GetType() == "model3DResource") {
gd::String updatedParameterValue = parameterValue;
worker.ExposeModel3D(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
}
});

View File

@@ -85,6 +85,11 @@ class GD_CORE_API ArbitraryResourceWorker {
*/
virtual void ExposeTileset(gd::String &tilesetName);
/**
* \brief Expose a 3D model, which is always a reference to a "model3D" resource.
*/
virtual void ExposeModel3D(gd::String &resourceName);
/**
* \brief Expose a video, which is always a reference to a "video" resource.
*/

View File

@@ -29,7 +29,7 @@ bool ProjectResourcesCopier::CopyAllResourcesTo(
originalProject.ExposeResources(absolutePathChecker);
auto projectDirectory = fs.DirNameFrom(originalProject.GetProjectFile());
std::cout << "Copying all ressources from " << projectDirectory << " to "
std::cout << "Copying all resources from " << projectDirectory << " to "
<< destinationDirectory << "..." << std::endl;
// Get the resources to be copied

View File

@@ -44,6 +44,7 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
std::set<gd::String>& GetAllTilesets() { return GetAll("tileset"); };
std::set<gd::String>& GetAllVideos() { return GetAll("video"); };
std::set<gd::String>& GetAllBitmapFonts() { return GetAll("bitmapFont"); };
std::set<gd::String>& GetAll3DModels() { return GetAll("model3D"); };
std::set<gd::String>& GetAll(const gd::String& resourceType) {
if (resourceType == "image") return allImages;
if (resourceType == "audio") return allAudios;
@@ -53,6 +54,7 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
if (resourceType == "tileset") return allTilesets;
if (resourceType == "video") return allVideos;
if (resourceType == "bitmapFont") return allBitmapFonts;
if (resourceType == "model3D") return allModel3Ds;
return emptyResources;
};
@@ -84,6 +86,9 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
virtual void ExposeBitmapFont(gd::String& bitmapFontResourceName) override {
allBitmapFonts.insert(bitmapFontResourceName);
};
virtual void ExposeModel3D(gd::String& resourceName) override {
allModel3Ds.insert(resourceName);
};
protected:
std::set<gd::String> allImages;
@@ -94,6 +99,7 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
std::set<gd::String> allTilesets;
std::set<gd::String> allVideos;
std::set<gd::String> allBitmapFonts;
std::set<gd::String> allModel3Ds;
std::set<gd::String> emptyResources;
};

View File

@@ -59,6 +59,9 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
virtual void ExposeBitmapFont(gd::String& bitmapFontName) override {
RenameIfNeeded(bitmapFontName);
};
virtual void ExposeModel3D(gd::String& resourceName) override {
RenameIfNeeded(resourceName);
};
private:
void RenameIfNeeded(gd::String& resourceName) {

View File

@@ -16,7 +16,7 @@ class EventsBasedObject;
class AbstractEventsBasedEntity;
class PropertyDescriptor;
class NamedPropertyDescriptor;
} // namespace gd
} // namespace gd
namespace gd {
@@ -24,22 +24,24 @@ namespace gd {
* \brief Generate a getter and a setter functions for properties.
*/
class GD_CORE_API PropertyFunctionGenerator {
public:
public:
/**
* \brief Generate a getter and a setter for the given behavior property.
*/
static void GenerateBehaviorGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::Project &project,
gd::EventsFunctionsExtension &extension,
gd::EventsBasedBehavior &eventsBasedBehavior,
const gd::NamedPropertyDescriptor &property, bool isSharedProperties);
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 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);
@@ -50,23 +52,26 @@ public:
static void GenerateConditionSkeleton(gd::Project &project,
gd::EventsFunction &eventFunction);
~PropertyFunctionGenerator();
~PropertyFunctionGenerator(){};
private:
private:
static void GenerateGetterAndSetter(
gd::Project &project, gd::EventsFunctionsExtension &extension,
gd::Project &project,
gd::EventsFunctionsExtension &extension,
gd::AbstractEventsBasedEntity &eventsBasedEntity,
const gd::NamedPropertyDescriptor &property, const gd::String &objectType,
bool isBehavior, bool isSharedProperties);
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);
static gd::String GetStringifiedExtraInfo(
const gd::PropertyDescriptor &property);
PropertyFunctionGenerator();
};
} // namespace gd
} // namespace gd
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H
#endif // GDCORE_PROPERTYFUNCTIONGENERATOR_H

File diff suppressed because it is too large Load Diff

View File

@@ -212,6 +212,13 @@ class GD_CORE_API WholeProjectRefactorer {
gd::Object& object,
const gd::String& behaviorType,
const gd::String& behaviorName);
/**
* \brief Add required behaviors if necessary to fill every behavior
* properties of the given behaviors.
*/
static void AddRequiredBehaviorsFor(gd::Project& project,
gd::Object& object,
const gd::String& behaviorName);
/**
* \brief Find every behavior of the object that needs the given behaviors

View File

@@ -153,6 +153,8 @@ void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& wor
worker.ExposeTileset(newPropertyValue);
} else if (resourceType == "bitmapFont") {
worker.ExposeBitmapFont(newPropertyValue);
} else if (resourceType == "model3D") {
worker.ExposeModel3D(newPropertyValue);
}
if (newPropertyValue != oldPropertyValue) {

View File

@@ -64,7 +64,7 @@ class GD_CORE_API EffectsContainer {
std::size_t GetEffectPosition(const gd::String& name) const;
/**
* Return the number of effecst.
* Return the number of effects.
*/
std::size_t GetEffectsCount() const;

View File

@@ -77,7 +77,7 @@ class GD_CORE_API EventsBasedBehavior: public AbstractEventsBasedEntity {
* \brief Check if the behavior is private - it can't be used outside of its
* extension.
*/
bool IsPrivate() { return isPrivate; }
bool IsPrivate() const { return isPrivate; }
/**
* \brief Set that the behavior is private - it can't be used outside of its

View File

@@ -201,7 +201,7 @@ class GD_CORE_API EventsFunction {
/**
* \brief Returns true if the function is private.
*/
bool IsPrivate() { return isPrivate; }
bool IsPrivate() const { return isPrivate; }
/**
* \brief Sets the privateness of the function.
@@ -217,7 +217,7 @@ class GD_CORE_API EventsFunction {
bool IsAsync() const { return isAsync; }
/**
* \brief Sets the asycronity of the function.
* \brief Sets the asynchronicity of the function.
*/
EventsFunction& SetAsync(bool _isAsync) {
isAsync = _isAsync;

View File

@@ -207,6 +207,13 @@ class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
return dependencies;
};
/**
* \brief Returns the list of dependencies.
*/
const std::vector<gd::DependencyMetadata>& GetAllDependencies() const {
return dependencies;
};
///@}
/** \name Serialization

View File

@@ -9,9 +9,9 @@
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/UUID/UUID.h"
#include "GDCore/Project/PropertyDescriptor.h"
namespace gd {
@@ -21,12 +21,17 @@ InitialInstance::InitialInstance()
: objectName(""),
x(0),
y(0),
z(0),
angle(0),
rotationX(0),
rotationY(0),
zOrder(0),
layer(""),
personalizedSize(false),
customSize(false),
customDepth(false),
width(0),
height(0),
depth(0),
locked(false),
sealed(false),
persistentUuid(UUID::MakeUuid4()) {}
@@ -35,11 +40,20 @@ void InitialInstance::UnserializeFrom(const SerializerElement& element) {
SetObjectName(element.GetStringAttribute("name", "", "nom"));
SetX(element.GetDoubleAttribute("x"));
SetY(element.GetDoubleAttribute("y"));
SetZ(element.GetDoubleAttribute("z", 0));
SetAngle(element.GetDoubleAttribute("angle"));
SetRotationX(element.GetDoubleAttribute("rotationX", 0));
SetRotationY(element.GetDoubleAttribute("rotationY", 0));
SetHasCustomSize(
element.GetBoolAttribute("customSize", false, "personalizedSize"));
SetCustomWidth(element.GetDoubleAttribute("width"));
SetCustomHeight(element.GetDoubleAttribute("height"));
if (element.HasChild("depth") || element.HasAttribute("depth")) {
SetHasCustomDepth(true);
SetCustomDepth(element.GetDoubleAttribute("depth"));
} else {
SetHasCustomDepth(false);
}
SetZOrder(element.GetIntAttribute("zOrder", 0, "plan"));
SetLayer(element.GetStringAttribute("layer"));
SetLocked(element.GetBoolAttribute("locked", false));
@@ -53,9 +67,26 @@ void InitialInstance::UnserializeFrom(const SerializerElement& element) {
element.GetChild("numberProperties", 0, "floatInfos");
numberPropertiesElement.ConsiderAsArrayOf("property", "Info");
for (std::size_t j = 0; j < numberPropertiesElement.GetChildrenCount(); ++j) {
gd::String name = numberPropertiesElement.GetChild(j).GetStringAttribute("name");
double value = numberPropertiesElement.GetChild(j).GetDoubleAttribute("value");
numberProperties[name] = value;
gd::String name =
numberPropertiesElement.GetChild(j).GetStringAttribute("name");
double value =
numberPropertiesElement.GetChild(j).GetDoubleAttribute("value");
// Compatibility with GD <= 5.1.164
if (name == "z") {
SetZ(value);
} else if (name == "rotationX") {
SetRotationX(value);
} else if (name == "rotationY") {
SetRotationY(value);
} else if (name == "depth") {
SetHasCustomDepth(true);
SetCustomDepth(value);
}
// end of compatibility code
else {
numberProperties[name] = value;
}
}
stringProperties.clear();
@@ -77,21 +108,26 @@ void InitialInstance::SerializeTo(SerializerElement& element) const {
element.SetAttribute("name", GetObjectName());
element.SetAttribute("x", GetX());
element.SetAttribute("y", GetY());
if (GetZ() != 0) element.SetAttribute("z", GetZ());
element.SetAttribute("zOrder", GetZOrder());
element.SetAttribute("layer", GetLayer());
element.SetAttribute("angle", GetAngle());
if (GetRotationX() != 0) element.SetAttribute("rotationX", GetRotationX());
if (GetRotationY() != 0) element.SetAttribute("rotationY", GetRotationY());
element.SetAttribute("customSize", HasCustomSize());
element.SetAttribute("width", GetCustomWidth());
element.SetAttribute("height", GetCustomHeight());
if (HasCustomDepth()) element.SetAttribute("depth", GetCustomDepth());
if (IsLocked()) element.SetAttribute("locked", IsLocked());
if (IsSealed()) element.SetAttribute("sealed", IsSealed());
if (persistentUuid.empty()) persistentUuid = UUID::MakeUuid4();
element.SetStringAttribute("persistentUuid", persistentUuid);
SerializerElement& numberPropertiesElement = element.AddChild("numberProperties");
SerializerElement& numberPropertiesElement =
element.AddChild("numberProperties");
numberPropertiesElement.ConsiderAsArrayOf("property");
for (const auto& property: numberProperties) {
for (const auto& property : numberProperties) {
numberPropertiesElement.AddChild("property")
.SetAttribute("name", property.first)
.SetAttribute("value", property.second);
@@ -99,7 +135,7 @@ void InitialInstance::SerializeTo(SerializerElement& element) const {
SerializerElement& stringPropElement = element.AddChild("stringProperties");
stringPropElement.ConsiderAsArrayOf("property");
for (const auto& property: stringProperties) {
for (const auto& property : stringProperties) {
stringPropElement.AddChild("property")
.SetAttribute("name", property.first)
.SetAttribute("value", property.second);
@@ -117,10 +153,12 @@ std::map<gd::String, gd::PropertyDescriptor>
InitialInstance::GetCustomProperties(gd::Project& project, gd::Layout& layout) {
// Find an object
if (layout.HasObjectNamed(GetObjectName()))
return layout.GetObject(GetObjectName()).GetConfiguration()
return layout.GetObject(GetObjectName())
.GetConfiguration()
.GetInitialInstanceProperties(*this, project, layout);
else if (project.HasObjectNamed(GetObjectName()))
return project.GetObject(GetObjectName()).GetConfiguration()
return project.GetObject(GetObjectName())
.GetConfiguration()
.GetInitialInstanceProperties(*this, project, layout);
std::map<gd::String, gd::PropertyDescriptor> nothing;
@@ -132,10 +170,12 @@ bool InitialInstance::UpdateCustomProperty(const gd::String& name,
gd::Project& project,
gd::Layout& layout) {
if (layout.HasObjectNamed(GetObjectName()))
return layout.GetObject(GetObjectName()).GetConfiguration()
return layout.GetObject(GetObjectName())
.GetConfiguration()
.UpdateInitialInstanceProperty(*this, name, value, project, layout);
else if (project.HasObjectNamed(GetObjectName()))
return project.GetObject(GetObjectName()).GetConfiguration()
return project.GetObject(GetObjectName())
.GetConfiguration()
.UpdateInitialInstanceProperty(*this, name, value, project, layout);
return false;
@@ -154,7 +194,8 @@ const gd::String& InitialInstance::GetRawStringProperty(
return it != stringProperties.end() ? it->second : *badStringProperyValue;
}
void InitialInstance::SetRawDoubleProperty(const gd::String& name, double value) {
void InitialInstance::SetRawDoubleProperty(const gd::String& name,
double value) {
numberProperties[name] = value;
}

View File

@@ -73,22 +73,52 @@ class GD_CORE_API InitialInstance {
void SetY(double y_) { y = y_; }
/**
* \brief Get the rotation of the instance, in radians.
* \brief Get the Z position of the instance
*/
double GetZ() const { return z; }
/**
* \brief Set the Z position of the instance
*/
void SetZ(double z_) { z = z_; }
/**
* \brief Get the rotation of the instance on Z axis, in radians.
*/
double GetAngle() const { return angle; }
/**
* \brief Set the rotation of the instance, in radians.
* \brief Set the rotation of the instance on Z axis, in radians.
*/
void SetAngle(double angle_) { angle = angle_; }
/**
* \brief Get the Z order of the instance.
* \brief Get the rotation of the instance on X axis, in radians.
*/
double GetRotationX() const { return rotationX; }
/**
* \brief Set the rotation of the instance on X axis, in radians.
*/
void SetRotationX(double rotationX_) { rotationX = rotationX_; }
/**
* \brief Get the rotation of the instance on Y axis, in radians.
*/
double GetRotationY() const { return rotationY; }
/**
* \brief Set the rotation of the instance on Y axis, in radians.
*/
void SetRotationY(double rotationY_) { rotationY = rotationY_; }
/**
* \brief Get the Z order of the instance (for a 2D object).
*/
int GetZOrder() const { return zOrder; }
/**
* \brief Set the Z order of the instance.
* \brief Set the Z order of the instance (for a 2D object).
*/
void SetZOrder(int zOrder_) { zOrder = zOrder_; }
@@ -103,29 +133,51 @@ class GD_CORE_API InitialInstance {
void SetLayer(const gd::String& layer_) { layer = layer_; }
/**
* \brief Return true if the instance has a size which is different from its
* object default size.
* \brief Return true if the instance has a width/height which is different from its
* object default width/height. This is independent from `HasCustomDepth`.
*
* \see gd::Object
*/
bool HasCustomSize() const { return personalizedSize; }
bool HasCustomSize() const { return customSize; }
/**
* \brief Set whether the instance has a size which is different from its
* object default size or not.
* \brief Return true if the instance has a depth which is different from its
* object default depth. This is independent from `HasCustomSize`.
*
* \param hasCustomSize true if the size is different from the object's
* default size. \see gd::Object
* \see gd::Object
*/
bool HasCustomDepth() const { return customDepth; }
/**
* \brief Set whether the instance has a width/height which is different from its
* object default width/height or not.
* This is independent from `SetHasCustomDepth`.
*
* \see gd::Object
*/
void SetHasCustomSize(bool hasCustomSize_) {
personalizedSize = hasCustomSize_;
customSize = hasCustomSize_;
}
/**
* \brief Set whether the instance has a depth which is different from its
* object default depth or not.
* This is independent from `SetHasCustomSize`.
*
* \param hasCustomSize true if the depth is different from the object's
* default depth.
* \see gd::Object
*/
void SetHasCustomDepth(bool hasCustomDepth_) {
customDepth = hasCustomDepth_;
}
double GetCustomWidth() const { return width; }
void SetCustomWidth(double width_) { width = width_; }
double GetCustomHeight() const { return height; }
void SetCustomHeight(double height_) { height = height_; }
double GetCustomDepth() const { return depth; }
void SetCustomDepth(double depth_) { depth = depth_; }
/**
* \brief Return true if the instance is locked and cannot be moved in the
@@ -193,7 +245,6 @@ class GD_CORE_API InitialInstance {
* \see gd::Object
*/
///@{
#if defined(GD_IDE_ONLY)
/**
* \brief Return a map containing the properties names (as keys) and their
* values.
@@ -213,7 +264,6 @@ class GD_CORE_API InitialInstance {
const gd::String& value,
gd::Project& project,
gd::Layout& layout);
#endif
/**
* \brief Get the value of a double property stored in the instance.
@@ -274,14 +324,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
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 x; ///< Instance X position
double y; ///< Instance Y position
double z; ///< Instance Z position (for a 3D object)
double angle; ///< Instance angle on Z axis
double rotationX; ///< Instance angle on X axis (for a 3D object)
double rotationY; ///< Instance angle on Y axis (for a 3D object)
int zOrder; ///< Instance Z order (for a 2D object)
gd::String layer; ///< Instance layer
bool customSize; ///< True if object has a custom width and height
bool customDepth; ///< True if object has a custom depth
double width; ///< Instance custom width
double height; ///< Instance custom height
double depth; ///< Instance custom depth
gd::VariablesContainer initialVariables; ///< Instance specific variables
bool locked; ///< True if the instance is locked
bool sealed; ///< True if the instance is sealed

View File

@@ -68,14 +68,14 @@ gd::InitialInstance& InitialInstancesContainer::InsertNewInitialInstance() {
}
void InitialInstancesContainer::RemoveInstanceIf(
std::function<bool(const gd::InitialInstance&)> predicat) {
std::function<bool(const gd::InitialInstance&)> predicate) {
// Note that we can't use eraseremove idiom here because remove_if would
// move the instances, and the container must guarantee that
// iterators/pointers to instances always remain valid.
for (std::list<gd::InitialInstance>::iterator it = initialInstances.begin(),
end = initialInstances.end();
it != end;) {
if (predicat(*it))
if (predicate(*it))
it = initialInstances.erase(it);
else
++it;

View File

@@ -178,7 +178,7 @@ class GD_CORE_API InitialInstancesContainer {
private:
void RemoveInstanceIf(
std::function<bool(const gd::InitialInstance &)> predicat);
std::function<bool(const gd::InitialInstance &)> predicate);
std::list<gd::InitialInstance> initialInstances;

View File

@@ -14,7 +14,17 @@ namespace gd {
Camera Layer::badCamera;
Layer::Layer()
: isVisible(true), isLightingLayer(false), followBaseLayerCamera(false) {}
: renderingType(""),
isVisible(true),
isLocked(false),
isLightingLayer(false),
followBaseLayerCamera(false),
camera3DNearPlaneDistance(0.1),
camera3DFarPlaneDistance(10000),
camera3DFieldOfView(45),
ambientLightColorR(200),
ambientLightColorG(200),
ambientLightColorB(200) {}
/**
* Change cameras count, automatically adding/removing them.
@@ -26,15 +36,21 @@ void Layer::SetCameraCount(std::size_t n) {
cameras.erase(cameras.begin() + cameras.size() - 1);
}
#if defined(GD_IDE_ONLY)
void Layer::SerializeTo(SerializerElement& element) const {
element.SetAttribute("name", GetName());
element.SetAttribute("renderingType", GetRenderingType());
element.SetAttribute("visibility", GetVisibility());
element.SetAttribute("isLocked", IsLocked());
element.SetAttribute("isLightingLayer", IsLightingLayer());
element.SetAttribute("followBaseLayerCamera", IsFollowingBaseLayerCamera());
element.SetAttribute("ambientLightColorR", (int)GetAmbientLightColorRed());
element.SetAttribute("ambientLightColorG", (int)GetAmbientLightColorGreen());
element.SetAttribute("ambientLightColorB", (int)GetAmbientLightColorBlue());
element.SetAttribute("camera3DNearPlaneDistance",
GetCamera3DNearPlaneDistance());
element.SetAttribute("camera3DFarPlaneDistance",
GetCamera3DFarPlaneDistance());
element.SetAttribute("camera3DFieldOfView", GetCamera3DFieldOfView());
SerializerElement& camerasElement = element.AddChild("cameras");
camerasElement.ConsiderAsArrayOf("camera");
@@ -55,20 +71,27 @@ void Layer::SerializeTo(SerializerElement& element) const {
SerializerElement& effectsElement = element.AddChild("effects");
effectsContainer.SerializeTo(effectsElement);
}
#endif
/**
* \brief Unserialize the layer.
*/
void Layer::UnserializeFrom(const SerializerElement& element) {
SetName(element.GetStringAttribute("name", "", "Name"));
SetRenderingType(element.GetStringAttribute("renderingType", ""));
SetVisibility(element.GetBoolAttribute("visibility", true, "Visibility"));
SetLocked(element.GetBoolAttribute("isLocked", false));
SetLightingLayer(element.GetBoolAttribute("isLightingLayer", false));
SetFollowBaseLayerCamera(
element.GetBoolAttribute("followBaseLayerCamera", false));
SetAmbientLightColor(element.GetIntAttribute("ambientLightColorR", 200),
element.GetIntAttribute("ambientLightColorG", 200),
element.GetIntAttribute("ambientLightColorB", 200));
SetCamera3DNearPlaneDistance(element.GetDoubleAttribute(
"camera3DNearPlaneDistance", 0.1, "threeDNearPlaneDistance"));
SetCamera3DFarPlaneDistance(element.GetDoubleAttribute(
"camera3DFarPlaneDistance", 10000, "threeDFarPlaneDistance"));
SetCamera3DFieldOfView(element.GetDoubleAttribute(
"camera3DFieldOfView", 45, "threeDFieldOfView"));
cameras.clear();
SerializerElement& camerasElement = element.GetChild("cameras");
@@ -80,24 +103,22 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
camera.SetUseDefaultSize(
cameraElement.GetBoolAttribute("defaultSize", true));
camera.SetSize(cameraElement.GetDoubleAttribute("width"),
cameraElement.GetDoubleAttribute("height"));
cameraElement.GetDoubleAttribute("height"));
camera.SetUseDefaultViewport(
cameraElement.GetBoolAttribute("defaultViewport", true));
camera.SetViewport(
cameraElement.GetDoubleAttribute("viewportLeft"),
cameraElement.GetDoubleAttribute("viewportTop"),
cameraElement.GetDoubleAttribute("viewportRight"),
cameraElement.GetDoubleAttribute(
"viewportBottom"));
camera.SetViewport(cameraElement.GetDoubleAttribute("viewportLeft"),
cameraElement.GetDoubleAttribute("viewportTop"),
cameraElement.GetDoubleAttribute("viewportRight"),
cameraElement.GetDoubleAttribute("viewportBottom"));
cameras.push_back(camera);
}
if (camerasElement.GetChildrenCount() > 50) {
// Highly unlikely that we want as many cameras, as they were not even exposed in
// the editor nor used in the game engine. Must be because of a bug in the editor that
// duplicated cameras when cancelling changes on a layer.
// Reset to one camera.
// Highly unlikely that we want as many cameras, as they were not even
// exposed in the editor nor used in the game engine. Must be because of a
// bug in the editor that duplicated cameras when cancelling changes on a
// layer. Reset to one camera.
SetCameraCount(1);
}
@@ -105,9 +126,7 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
effectsContainer.UnserializeFrom(effectsElement);
}
gd::EffectsContainer& Layer::GetEffects() {
return effectsContainer;
}
gd::EffectsContainer& Layer::GetEffects() { return effectsContainer; }
const gd::EffectsContainer& Layer::GetEffects() const {
return effectsContainer;

View File

@@ -47,6 +47,11 @@ class GD_CORE_API Layer {
*/
const gd::String& GetName() const { return name; }
const gd::String& GetRenderingType() const { return renderingType; }
void SetRenderingType(const gd::String& renderingType_) {
renderingType = renderingType_;
}
/**
* \brief Change if layer is displayed or not
*/
@@ -58,7 +63,17 @@ class GD_CORE_API Layer {
bool GetVisibility() const { return isVisible; }
/**
* \brief Set if the layer is a lightining layer or not.
* \brief Change if layer can be modified or not.
*/
void SetLocked(bool isLocked_) { isLocked = isLocked_; }
/**
* \brief Return true if layer can't be modified.
*/
bool IsLocked() const { return isLocked; }
/**
* \brief Set if the layer is a lighting layer or not.
*/
void SetLightingLayer(bool isLightingLayer_) {
isLightingLayer = isLightingLayer_;
@@ -81,6 +96,25 @@ class GD_CORE_API Layer {
*/
bool IsFollowingBaseLayerCamera() const { return followBaseLayerCamera; }
/** \name 3D
*/
///@{
double GetCamera3DNearPlaneDistance() const {
return camera3DNearPlaneDistance;
}
void SetCamera3DNearPlaneDistance(double distance) {
camera3DNearPlaneDistance = distance;
}
double GetCamera3DFarPlaneDistance() const {
return camera3DFarPlaneDistance;
}
void SetCamera3DFarPlaneDistance(double distance) {
camera3DFarPlaneDistance = distance;
}
double GetCamera3DFieldOfView() const { return camera3DFieldOfView; }
void SetCamera3DFieldOfView(double angle) { camera3DFieldOfView = angle; }
///@}
/** \name Cameras
*/
///@{
@@ -164,12 +198,10 @@ class GD_CORE_API Layer {
const EffectsContainer& GetEffects() const;
///@}
#if defined(GD_IDE_ONLY)
/**
* \brief Serialize layer.
*/
void SerializeTo(SerializerElement& element) const;
#endif
/**
* \brief Unserialize the layer.
@@ -177,16 +209,22 @@ class GD_CORE_API Layer {
void UnserializeFrom(const SerializerElement& element);
private:
gd::String name; ///< The name of the layer
bool isVisible; ///< True if the layer is visible
gd::String name; ///< The name of the layer
gd::String renderingType; ///< The rendering type: "" (empty), "2d", "3d" or
///< "2d+3d".
bool isVisible; ///< True if the layer is visible
bool isLocked; ///< True if the layer is locked
bool isLightingLayer; ///< True if the layer is used to display lights and
///< renders an ambient light.
bool followBaseLayerCamera; ///< True if the layer automatically follows the
///< base layer
unsigned int ambientLightColorR; ///< Ambient light color Red component
unsigned int ambientLightColorG; ///< Ambient light color Green component
unsigned int ambientLightColorB; ///< Ambient light color Blue component
std::vector<gd::Camera> cameras; ///< The camera displayed by the layer
double camera3DNearPlaneDistance; ///< 3D camera frustum near plan distance
double camera3DFarPlaneDistance; ///< 3D camera frustum far plan distance
double camera3DFieldOfView; ///< 3D camera field of view (fov) in degrees
unsigned int ambientLightColorR; ///< Ambient light color Red component
unsigned int ambientLightColorG; ///< Ambient light color Green component
unsigned int ambientLightColorB; ///< Ambient light color Blue component
std::vector<gd::Camera> cameras; ///< The camera displayed by the layer
gd::EffectsContainer effectsContainer; ///< The effects applied to the layer.
static gd::Camera badCamera;

View File

@@ -5,17 +5,17 @@
*/
#ifndef GDCORE_OBJECT_H
#define GDCORE_OBJECT_H
#include "GDCore/Vector2.h"
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/ObjectConfiguration.h"
#include "GDCore/Project/EffectsContainer.h"
#include "GDCore/Project/ObjectConfiguration.h"
#include "GDCore/Project/VariablesContainer.h"
#include "GDCore/String.h"
#include "GDCore/Tools/MakeUnique.h"
#include "GDCore/Vector2.h"
namespace gd {
class PropertyDescriptor;
@@ -45,7 +45,7 @@ class GD_CORE_API Object {
/**
* Create a new object with the name passed as argument.
*
*
* Object takes the ownership of the configuration.
*/
Object(const gd::String& name,
@@ -104,7 +104,9 @@ class GD_CORE_API Object {
/** \brief Change the asset store id of the object.
*/
void SetAssetStoreId(const gd::String& assetStoreId_) { assetStoreId = assetStoreId_; };
void SetAssetStoreId(const gd::String& assetStoreId_) {
assetStoreId = assetStoreId_;
};
/** \brief Return the asset store id of the object.
*/
@@ -112,15 +114,11 @@ class GD_CORE_API Object {
/** \brief Change the type of the object.
*/
void SetType(const gd::String& type_) {
configuration->SetType(type_);
}
void SetType(const gd::String& type_) { configuration->SetType(type_); }
/** \brief Return the type of the object.
*/
const gd::String& GetType() const {
return configuration->GetType();
}
const gd::String& GetType() const { return configuration->GetType(); }
/** \brief Change the tags of the object.
*/
@@ -129,6 +127,10 @@ class GD_CORE_API Object {
/** \brief Return the tags of the object.
*/
const gd::String& GetTags() const { return tags; }
/** \brief Shortcut to check if the object is a 3D object.
*/
bool Is3DObject() const { return configuration->Is3DObject(); }
///@}
/** \name Behaviors management
@@ -224,12 +226,12 @@ class GD_CORE_API Object {
* effects.
*/
gd::EffectsContainer& GetEffects() { return effectsContainer; }
///@}
///@}
/** \name Serialization
* Members functions related to serialization of the object
*/
///@{
/** \name Serialization
* Members functions related to serialization of the object
*/
///@{
/**
* \brief Serialize the object.
* \see DoSerializeTo
@@ -244,8 +246,9 @@ class GD_CORE_API Object {
///@}
protected:
gd::String name; ///< The full name of the object
gd::String assetStoreId; ///< The ID of the asset if the object comes from the store.
gd::String name; ///< The full name of the object
gd::String assetStoreId; ///< The ID of the asset if the object comes from
///< the store.
std::unique_ptr<gd::ObjectConfiguration> configuration;
std::map<gd::String, std::unique_ptr<gd::Behavior>>
behaviors; ///< Contains all behaviors and their properties for the
@@ -260,7 +263,7 @@ class GD_CORE_API Object {
/**
* Initialize object using another object. Used by copy-ctor and assign-op.
* Don't forget to update me if members were changed!
*
*
* It's needed because there is no default copy for a map of unique_ptr like
* behaviors and it must be a deep copy.
*/
@@ -283,14 +286,4 @@ struct ObjectHasName : public std::binary_function<std::unique_ptr<gd::Object>,
} // namespace gd
/**
* An object list is a vector containing (smart) pointers to objects.
*/
using ObjList = std::vector<std::unique_ptr<gd::Object>>;
/**
* Objects are usually managed thanks to (smart) pointers.
*/
using ObjSPtr = std::unique_ptr<gd::Object>;
#endif // GDCORE_OBJECT_H

View File

@@ -20,7 +20,7 @@ namespace gd {
ObjectConfiguration::~ObjectConfiguration() {}
ObjectConfiguration::ObjectConfiguration() {}
ObjectConfiguration::ObjectConfiguration(): is3DObject(false) {}
std::map<gd::String, gd::PropertyDescriptor> ObjectConfiguration::GetProperties() const {
std::map<gd::String, gd::PropertyDescriptor> nothing;

View File

@@ -61,12 +61,22 @@ class GD_CORE_API ObjectConfiguration {
/** \brief Change the type of the object.
*/
void SetType(const gd::String& type_) { type = type_; }
void SetType(const gd::String& type_) {
type = type_;
// For now, as a shortcut, consider only the objects from the built-in 3D extension
// to be 3D object.
is3DObject = type.find("Scene3D::") == 0;
}
/** \brief Return the type of the object.
*/
const gd::String& GetType() const { return type; }
/** \brief Shortcut to check if the object is a 3D object.
*/
bool Is3DObject() const { return is3DObject; }
/** \name Object properties
* Reading and updating object configuration properties
*/
@@ -170,6 +180,7 @@ class GD_CORE_API ObjectConfiguration {
protected:
gd::String type; ///< Which type of object is represented by this
///< configuration.
bool is3DObject;
/**
* \brief Derived object configuration can redefine this method to load

View File

@@ -5,8 +5,10 @@
*/
#include "ObjectGroup.h"
#include <algorithm>
#include <vector>
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
@@ -41,8 +43,9 @@ void ObjectGroup::SerializeTo(SerializerElement& element) const {
SerializerElement& objectsElement = element.AddChild("objects");
objectsElement.ConsiderAsArrayOf("object");
for (auto& name : GetAllObjectsNames())
for (auto& name : GetAllObjectsNames()) {
objectsElement.AddChild("object").SetAttribute("name", name);
}
}
void ObjectGroup::UnserializeFrom(const SerializerElement& element) {

View File

@@ -8,7 +8,9 @@
#define GDCORE_OBJECTGROUP_H
#include <utility>
#include <vector>
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
}

View File

@@ -4,79 +4,113 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Project/ObjectGroupsContainer.h"
#include "ObjectGroupsContainer.h"
#include <memory>
#include "GDCore/Project/ObjectGroup.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
#include "GDCore/Tools/MakeUnique.h"
namespace gd {
gd::ObjectGroup ObjectGroupsContainer::badGroup;
ObjectGroup ObjectGroupsContainer::badGroup;
ObjectGroupsContainer::ObjectGroupsContainer() {}
ObjectGroupsContainer::ObjectGroupsContainer(
const ObjectGroupsContainer& other) {
Init(other);
}
ObjectGroupsContainer& ObjectGroupsContainer::operator=(
const ObjectGroupsContainer& other) {
if (this != &other) Init(other);
return *this;
}
void ObjectGroupsContainer::Init(const ObjectGroupsContainer& other) {
objectGroups.clear();
for (auto& it : other.objectGroups) {
objectGroups.push_back(gd::make_unique<gd::ObjectGroup>(*it));
}
}
void ObjectGroupsContainer::SerializeTo(SerializerElement& element) const {
element.ConsiderAsArrayOf("group");
for (std::size_t i = 0; i < objectGroups.size(); ++i) {
objectGroups[i]->SerializeTo(element.AddChild("group"));
}
}
void ObjectGroupsContainer::UnserializeFrom(const SerializerElement& element) {
objectGroups.clear();
element.ConsiderAsArrayOf("group", "Groupe");
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
const SerializerElement& groupElement = element.GetChild(i);
gd::ObjectGroup& objectGroup =
InsertNew(element.GetStringAttribute("name", "", "nom"), -1);
objectGroup.UnserializeFrom(groupElement);
}
}
bool ObjectGroupsContainer::Has(const gd::String& name) const {
auto i = std::find_if(
objectGroups.begin(),
objectGroups.end(),
[&name](const ObjectGroup& group) { return group.GetName() == name; });
auto i = std::find_if(objectGroups.begin(),
objectGroups.end(),
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
return group->GetName() == name;
});
return (i != objectGroups.end());
}
ObjectGroup& ObjectGroupsContainer::Get(std::size_t index) {
if (index < objectGroups.size()) return objectGroups[index];
if (index < objectGroups.size()) return *objectGroups[index];
return badGroup;
}
const ObjectGroup& ObjectGroupsContainer::Get(std::size_t index) const {
if (index < objectGroups.size()) return objectGroups[index];
if (index < objectGroups.size()) return *objectGroups[index];
return badGroup;
}
ObjectGroup& ObjectGroupsContainer::Get(const gd::String& name) {
auto i = std::find_if(
objectGroups.begin(),
objectGroups.end(),
[&name](const ObjectGroup& group) { return group.GetName() == name; });
if (i != objectGroups.end()) return *i;
auto i = std::find_if(objectGroups.begin(),
objectGroups.end(),
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
return group->GetName() == name;
});
if (i != objectGroups.end()) return **i;
return badGroup;
}
const ObjectGroup& ObjectGroupsContainer::Get(const gd::String& name) const {
auto i = std::find_if(
objectGroups.begin(),
objectGroups.end(),
[&name](const ObjectGroup& group) { return group.GetName() == name; });
if (i != objectGroups.end()) return *i;
auto i = std::find_if(objectGroups.begin(),
objectGroups.end(),
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
return group->GetName() == name;
});
if (i != objectGroups.end()) return **i;
return badGroup;
}
ObjectGroup& ObjectGroupsContainer::Insert(const gd::ObjectGroup& group,
std::size_t position) {
if (position < objectGroups.size()) {
objectGroups.insert(objectGroups.begin() + position, group);
return objectGroups[position];
} else {
objectGroups.push_back(group);
return objectGroups.back();
}
}
#if defined(GD_IDE_ONLY)
void ObjectGroupsContainer::Remove(const gd::String& name) {
objectGroups.erase(std::remove_if(objectGroups.begin(),
objectGroups.end(),
[&name](const ObjectGroup& group) {
return group.GetName() == name;
}),
objectGroups.end());
objectGroups.erase(
std::remove_if(objectGroups.begin(),
objectGroups.end(),
[&name](const std::unique_ptr<gd::ObjectGroup>& group) {
return group->GetName() == name;
}),
objectGroups.end());
}
std::size_t ObjectGroupsContainer::GetPosition(const gd::String& name) const {
for (std::size_t i = 0; i < objectGroups.size(); ++i) {
if (objectGroups[i].GetName() == name) return i;
if (objectGroups[i]->GetName() == name) return i;
}
return gd::String::npos;
@@ -84,21 +118,36 @@ std::size_t ObjectGroupsContainer::GetPosition(const gd::String& name) const {
ObjectGroup& ObjectGroupsContainer::InsertNew(const gd::String& name,
std::size_t position) {
ObjectGroup newGroup;
newGroup.SetName(name);
return Insert(newGroup, position);
gd::ObjectGroup& newlyInsertedGroup = *(*(objectGroups.insert(
position < objectGroups.size() ? objectGroups.begin() + position
: objectGroups.end(),
gd::make_unique<gd::ObjectGroup>())));
newlyInsertedGroup.SetName(name);
return newlyInsertedGroup;
}
ObjectGroup& ObjectGroupsContainer::Insert(const gd::ObjectGroup& group,
std::size_t position) {
gd::ObjectGroup& newlyInsertedGroup = *(*(objectGroups.insert(
position < objectGroups.size() ? objectGroups.begin() + position
: objectGroups.end(),
gd::make_unique<gd::ObjectGroup>(group))));
return newlyInsertedGroup;
}
bool ObjectGroupsContainer::Rename(const gd::String& oldName,
const gd::String& newName) {
if (Has(newName)) return false;
auto i = std::find_if(objectGroups.begin(),
objectGroups.end(),
[&oldName](const ObjectGroup& group) {
return group.GetName() == oldName;
});
if (i != objectGroups.end()) i->SetName(newName);
auto i =
std::find_if(objectGroups.begin(),
objectGroups.end(),
[&oldName](const std::unique_ptr<gd::ObjectGroup>& group) {
return group->GetName() == oldName;
});
if (i != objectGroups.end()) {
(*i)->SetName(newName);
}
return true;
}
@@ -107,30 +156,10 @@ void ObjectGroupsContainer::Move(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= objectGroups.size() || newIndex >= objectGroups.size())
return;
auto group = objectGroups[oldIndex];
std::unique_ptr<gd::ObjectGroup> objectGroup =
std::move(objectGroups[oldIndex]);
objectGroups.erase(objectGroups.begin() + oldIndex);
Insert(group, newIndex);
}
#endif
void ObjectGroupsContainer::SerializeTo(SerializerElement& element) const {
element.ConsiderAsArrayOf("group");
for (auto& group : objectGroups) {
SerializerElement& groupElement = element.AddChild("group");
group.SerializeTo(groupElement);
}
}
void ObjectGroupsContainer::UnserializeFrom(const SerializerElement& element) {
objectGroups.clear();
element.ConsiderAsArrayOf("group", "Groupe");
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
SerializerElement& groupElement = element.GetChild(i);
gd::ObjectGroup objectGroup;
objectGroup.UnserializeFrom(groupElement);
objectGroups.push_back(objectGroup);
}
objectGroups.insert(objectGroups.begin() + newIndex, std::move(objectGroup));
}
} // namespace gd

View File

@@ -6,8 +6,10 @@
#ifndef GDCORE_OBJECTGROUPSCONTAINER_H
#define GDCORE_OBJECTGROUPSCONTAINER_H
#include <vector>
#include <algorithm>
#include <memory>
#include <vector>
#include "GDCore/Project/ObjectGroup.h"
#include "GDCore/String.h"
namespace gd {
@@ -26,8 +28,10 @@ namespace gd {
*/
class GD_CORE_API ObjectGroupsContainer {
public:
ObjectGroupsContainer(){};
ObjectGroupsContainer();
ObjectGroupsContainer(const ObjectGroupsContainer&);
virtual ~ObjectGroupsContainer(){};
ObjectGroupsContainer& operator=(const ObjectGroupsContainer& rhs);
/**
* \brief Return true if the specified group is in the container
@@ -171,8 +175,14 @@ class GD_CORE_API ObjectGroupsContainer {
const ObjectGroup& at(size_t index) const { return Get(index); };
///@}
/**
* Initialize from another object groups container. Used by copy-ctor and
* assign-op. Don't forget to update me if members were changed!
*/
void Init(const gd::ObjectGroupsContainer& other);
private:
std::vector<ObjectGroup> objectGroups;
std::vector<std::unique_ptr<gd::ObjectGroup>> objectGroups;
static ObjectGroup badGroup;
};

View File

@@ -4,7 +4,9 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Project/ObjectsContainer.h"
#include <algorithm>
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
@@ -16,14 +18,12 @@ ObjectsContainer::ObjectsContainer() {}
ObjectsContainer::~ObjectsContainer() {}
#if defined(GD_IDE_ONLY)
void ObjectsContainer::SerializeObjectsTo(SerializerElement& element) const {
element.ConsiderAsArrayOf("object");
for (std::size_t j = 0; j < initialObjects.size(); j++) {
initialObjects[j]->SerializeTo(element.AddChild("object"));
}
}
#endif
void ObjectsContainer::UnserializeObjectsFrom(
gd::Project& project, const SerializerElement& element) {
@@ -75,7 +75,6 @@ std::size_t ObjectsContainer::GetObjectPosition(const gd::String& name) const {
std::size_t ObjectsContainer::GetObjectsCount() const {
return initialObjects.size();
}
#if defined(GD_IDE_ONLY)
gd::Object& ObjectsContainer::InsertNewObject(const gd::Project& project,
const gd::String& objectType,
const gd::String& name,
@@ -87,7 +86,6 @@ gd::Object& ObjectsContainer::InsertNewObject(const gd::Project& project,
return newlyCreatedObject;
}
#endif
gd::Object& ObjectsContainer::InsertObject(const gd::Object& object,
std::size_t position) {
@@ -119,7 +117,7 @@ void ObjectsContainer::MoveObject(std::size_t oldIndex, std::size_t newIndex) {
}
void ObjectsContainer::RemoveObject(const gd::String& name) {
std::vector<std::unique_ptr<gd::Object> >::iterator objectIt =
std::vector<std::unique_ptr<gd::Object>>::iterator objectIt =
find_if(initialObjects.begin(),
initialObjects.end(),
bind2nd(ObjectHasName(), name));
@@ -132,7 +130,7 @@ void ObjectsContainer::MoveObjectToAnotherContainer(
const gd::String& name,
gd::ObjectsContainer& newContainer,
std::size_t newPosition) {
std::vector<std::unique_ptr<gd::Object> >::iterator objectIt =
std::vector<std::unique_ptr<gd::Object>>::iterator objectIt =
find_if(initialObjects.begin(),
initialObjects.end(),
bind2nd(ObjectHasName(), name));

View File

@@ -65,6 +65,8 @@ Project::Project()
pixelsRounding(false),
adaptGameResolutionAtRuntime(true),
sizeOnStartupMode("adaptWidth"),
antialiasingMode("MSAA"),
isAntialisingEnabledOnMobile(false),
projectUuid(""),
useDeprecatedZeroAsDefaultZOrder(false),
useExternalSourceFiles(false),
@@ -81,24 +83,23 @@ Project::~Project() {}
void Project::ResetProjectUuid() { projectUuid = UUID::MakeUuid4(); }
std::unique_ptr<gd::Object> Project::CreateObject(
const gd::String& type,
const gd::String& name) const {
return gd::make_unique<Object>(name, type, CreateObjectConfiguration(type));
const gd::String& type, const gd::String& name) const {
return gd::make_unique<Object>(name, type, CreateObjectConfiguration(type));
}
std::unique_ptr<gd::ObjectConfiguration> Project::CreateObjectConfiguration(
const gd::String& type) const {
const gd::String& type) const {
if (Project::HasEventsBasedObject(type)) {
return gd::make_unique<CustomObjectConfiguration>(*this, type);
}
else {
} else {
// Create a base object if the type can't be found in the platform.
return currentPlatform->CreateObjectConfiguration(type);
}
}
bool Project::HasEventsBasedObject(const gd::String& type) const {
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
if (separatorIndex == std::string::npos) {
return false;
}
@@ -106,59 +107,67 @@ bool Project::HasEventsBasedObject(const gd::String& type) const {
if (!Project::HasEventsFunctionsExtensionNamed(extensionName)) {
return false;
}
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
gd::String objectTypeName = type.substr(separatorIndex + 2);
return extension.GetEventsBasedObjects().Has(objectTypeName);
}
gd::EventsBasedObject& Project::GetEventsBasedObject(const gd::String& type) {
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
gd::String extensionName = type.substr(0, separatorIndex);
gd::String objectTypeName = type.substr(separatorIndex + 2);
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
return extension.GetEventsBasedObjects().Get(objectTypeName);
}
const gd::EventsBasedObject& Project::GetEventsBasedObject(const gd::String& type) const {
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
const gd::EventsBasedObject& Project::GetEventsBasedObject(
const gd::String& type) const {
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
gd::String extensionName = type.substr(0, separatorIndex);
gd::String objectTypeName = type.substr(separatorIndex + 2);
const auto &extension = Project::GetEventsFunctionsExtension(extensionName);
const auto& extension = Project::GetEventsFunctionsExtension(extensionName);
return extension.GetEventsBasedObjects().Get(objectTypeName);
}
bool Project::HasEventsBasedBehavior(const gd::String& type) const {
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
if (separatorIndex == std::string::npos) {
return false;
}
gd::String extensionName = type.substr(0, separatorIndex);
if (!Project::HasEventsFunctionsExtensionNamed(extensionName)) {
return false;
}
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
return extension.GetEventsBasedBehaviors().Has(behaviorTypeName);
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
if (separatorIndex == std::string::npos) {
return false;
}
gd::String extensionName = type.substr(0, separatorIndex);
if (!Project::HasEventsFunctionsExtensionNamed(extensionName)) {
return false;
}
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
return extension.GetEventsBasedBehaviors().Has(behaviorTypeName);
}
gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(const gd::String& type) {
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
gd::String extensionName = type.substr(0, separatorIndex);
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(
const gd::String& type) {
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
gd::String extensionName = type.substr(0, separatorIndex);
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
}
const gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(const gd::String& type) const {
const auto separatorIndex = type.find(PlatformExtension::GetNamespaceSeparator());
gd::String extensionName = type.substr(0, separatorIndex);
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
const gd::EventsBasedBehavior& Project::GetEventsBasedBehavior(
const gd::String& type) const {
const auto separatorIndex =
type.find(PlatformExtension::GetNamespaceSeparator());
gd::String extensionName = type.substr(0, separatorIndex);
gd::String behaviorTypeName = type.substr(separatorIndex + 2);
auto &extension = Project::GetEventsFunctionsExtension(extensionName);
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
auto& extension = Project::GetEventsFunctionsExtension(extensionName);
return extension.GetEventsBasedBehaviors().Get(behaviorTypeName);
}
std::shared_ptr<gd::BaseEvent> Project::CreateEvent(
@@ -378,7 +387,7 @@ void Project::MoveExternalLayout(std::size_t oldIndex, std::size_t newIndex) {
};
void Project::MoveEventsFunctionsExtension(std::size_t oldIndex,
std::size_t newIndex) {
std::size_t newIndex) {
if (oldIndex >= eventsFunctionsExtensions.size() ||
newIndex >= eventsFunctionsExtensions.size())
return;
@@ -621,6 +630,8 @@ void Project::UnserializeFrom(const SerializerElement& element) {
SetAdaptGameResolutionAtRuntime(
propElement.GetBoolAttribute("adaptGameResolutionAtRuntime", false));
SetSizeOnStartupMode(propElement.GetStringAttribute("sizeOnStartupMode", ""));
SetAntialiasingMode(propElement.GetStringAttribute("antialiasingMode", "MSAA"));
SetAntialisingEnabledOnMobile(propElement.GetBoolAttribute("antialisingEnabledOnMobile", false));
SetProjectUuid(propElement.GetStringAttribute("projectUuid", ""));
SetAuthor(propElement.GetChild("author", 0, "Auteur").GetValue().GetString());
SetPackageName(propElement.GetStringAttribute("packageName"));
@@ -875,6 +886,8 @@ void Project::SerializeTo(SerializerElement& element) const {
propElement.SetAttribute("adaptGameResolutionAtRuntime",
adaptGameResolutionAtRuntime);
propElement.SetAttribute("sizeOnStartupMode", sizeOnStartupMode);
propElement.SetAttribute("antialiasingMode", antialiasingMode);
propElement.SetAttribute("antialisingEnabledOnMobile", isAntialisingEnabledOnMobile);
propElement.SetAttribute("projectUuid", projectUuid);
propElement.SetAttribute("folderProject", folderProject);
propElement.SetAttribute("packageName", packageName);
@@ -1005,7 +1018,7 @@ void Project::ExposeResources(gd::ArbitraryResourceWorker& worker) {
// Add layouts resources
for (std::size_t s = 0; s < GetLayoutsCount(); s++) {
for (std::size_t j = 0; j < GetLayout(s).GetObjectsCount();
++j) { // Add objects resources
++j) { // Add objects resources
GetLayout(s).GetObject(j).GetConfiguration().ExposeResources(worker);
}
@@ -1106,6 +1119,8 @@ void Project::Init(const gd::Project& game) {
pixelsRounding = game.pixelsRounding;
adaptGameResolutionAtRuntime = game.adaptGameResolutionAtRuntime;
sizeOnStartupMode = game.sizeOnStartupMode;
antialiasingMode = game.antialiasingMode;
isAntialisingEnabledOnMobile = game.isAntialisingEnabledOnMobile;
projectUuid = game.projectUuid;
useDeprecatedZeroAsDefaultZOrder = game.useDeprecatedZeroAsDefaultZOrder;

View File

@@ -383,6 +383,26 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
void SetPixelsRounding(bool enable) { pixelsRounding = enable; }
/**
* Return the antialiasing mode used by the game ("none" or "MSAA").
*/
const gd::String& GetAntialiasingMode() const { return antialiasingMode; }
/**
* Set the antialiasing mode used by the game ("none" or "MSAA").
*/
void SetAntialiasingMode(const gd::String& antialiasingMode_) { antialiasingMode = antialiasingMode_; }
/**
* Return true if antialising is enabled on mobiles.
*/
bool IsAntialisingEnabledOnMobile() const { return isAntialisingEnabledOnMobile; }
/**
* Set whether antialising is enabled on mobiles or not.
*/
void SetAntialisingEnabledOnMobile(bool enable) { isAntialisingEnabledOnMobile = enable; }
/**
* \brief Return if the project should set 0 as Z-order for objects created
* from events (which is deprecated) - instead of the highest Z order that was
@@ -1040,6 +1060,8 @@ class GD_CORE_API Project : public ObjectsContainer {
gd::String
sizeOnStartupMode; ///< How to adapt the game size to the screen. Can be
///< "adaptWidth", "adaptHeight" or empty
gd::String antialiasingMode;
bool isAntialisingEnabledOnMobile;
gd::String projectUuid; ///< UUID useful to identify the game in online
///< services or database that would require it.
bool useDeprecatedZeroAsDefaultZOrder; ///< If true, objects created from

View File

@@ -91,6 +91,8 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
return std::make_shared<TilesetResource>();
else if (kind == "bitmapFont")
return std::make_shared<BitmapFontResource>();
else if (kind == "model3D")
return std::make_shared<Model3DResource>();
std::cout << "Bad resource created (type: " << kind << ")" << std::endl;
return std::make_shared<Resource>();
@@ -736,6 +738,20 @@ void BitmapFontResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("file", GetFile());
}
void Model3DResource::SetFile(const gd::String& newFile) {
file = NormalizePathSeparator(newFile);
}
void Model3DResource::UnserializeFrom(const SerializerElement& element) {
SetUserAdded(element.GetBoolAttribute("userAdded"));
SetFile(element.GetStringAttribute("file"));
}
void Model3DResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute("file", GetFile());
}
ResourceFolder::ResourceFolder(const ResourceFolder& other) { Init(other); }
ResourceFolder& ResourceFolder::operator=(const ResourceFolder& other) {

View File

@@ -142,7 +142,7 @@ class GD_CORE_API Resource {
virtual void SerializeTo(SerializerElement& element) const {};
/**
* \brief Unserialize the objectt.
* \brief Unserialize the object.
*/
virtual void UnserializeFrom(const SerializerElement& element){};
@@ -195,7 +195,7 @@ class GD_CORE_API ImageResource : public Resource {
void SerializeTo(SerializerElement& element) const override;
/**
* \brief Unserialize the objectt.
* \brief Unserialize the object.
*/
void UnserializeFrom(const SerializerElement& element) override;
@@ -481,6 +481,32 @@ class GD_CORE_API BitmapFontResource : public Resource {
gd::String file;
};
/**
* \brief Describe a 3D model file used by a project.
*
* \see Resource
* \ingroup ResourcesManagement
*/
class GD_CORE_API Model3DResource : public Resource {
public:
Model3DResource() : Resource() { SetKind("model3D"); };
virtual ~Model3DResource(){};
virtual Model3DResource* Clone() const override {
return new Model3DResource(*this);
}
virtual const gd::String& GetFile() const override { return file; };
virtual void SetFile(const gd::String& newFile) override;
virtual bool UseFile() const override { return true; }
void SerializeTo(SerializerElement& element) const override;
void UnserializeFrom(const SerializerElement& element) override;
private:
gd::String file;
};
/**
* \brief Inventory all resources used by a project
*
@@ -637,7 +663,7 @@ class GD_CORE_API ResourcesManager {
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the objectt.
* \brief Unserialize the object.
*/
void UnserializeFrom(const SerializerElement& element);
@@ -714,7 +740,7 @@ class GD_CORE_API ResourceFolder {
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the objectt.
* \brief Unserialize the object.
*/
void UnserializeFrom(const SerializerElement& element,
gd::ResourcesManager& parentManager);

View File

@@ -2280,7 +2280,7 @@ public:
//!@name Handling parse errors
//!@{
//! Whether a parse error has occured in the last parsing.
//! Whether a parse error has occurred in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); }
//! Get the \ref ParseErrorCode of last parsing.

View File

@@ -527,7 +527,7 @@ public:
return Parse<kParseDefaultFlags>(is, handler);
}
//! Whether a parse error has occured in the last parsing.
//! Whether a parse error has occurred in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); }
//! Get the \ref ParseErrorCode of last parsing.

View File

@@ -686,6 +686,16 @@ String GD_CORE_API operator+(const char *lhs, const String &rhs)
return str;
}
const String& GD_CORE_API operator||(const String& lhs, const String &rhs)
{
return lhs.empty() ? rhs : lhs;
}
String GD_CORE_API operator||(String lhs, const char *rhs)
{
return lhs.empty() ? rhs : lhs;
}
bool GD_CORE_API operator==( const String &lhs, const String &rhs )
{
return (lhs.compare(rhs) == 0);

View File

@@ -584,32 +584,32 @@ public:
String substr( size_type start = 0, size_type length = npos ) const;
/**
* \return the position of the first occurence of **search** starting from **pos**.
* \return the position of the first occurrence of **search** starting from **pos**.
*/
size_type find( const String &search, size_type pos = 0 ) const;
/**
* \return the position of the first occurence of **search** starting from **pos**.
* \return the position of the first occurrence of **search** starting from **pos**.
*/
size_type find( const char *search, size_type pos = 0 ) const;
/**
* \return the position of the first occurence of **search** starting from **pos**.
* \return the position of the first occurrence of **search** starting from **pos**.
*/
size_type find( const value_type search, size_type pos = 0 ) const;
/**
* \return the position of the last occurence of **search** starting before **pos**.
* \return the position of the last occurrence of **search** starting before **pos**.
*/
size_type rfind( const String &search, size_type pos = npos ) const;
/**
* \return the position of the last occurence of **search** starting before **pos**.
* \return the position of the last occurrence of **search** starting before **pos**.
*/
size_type rfind( const char *search, size_type pos = npos ) const;
/**
* \return the position of the last occurence of **search** starting before **pos**.
* \return the position of the last occurrence of **search** starting before **pos**.
*/
size_type rfind( const value_type &search, size_type pos = npos ) const;
@@ -658,7 +658,7 @@ public:
/**
* \brief Do a case-insensitive search
* \return the position of the first occurence of **search** starting from **pos**.
* \return the position of the first occurrence of **search** starting from **pos**.
*
* \note This method isn't very efficient as it is linear on the string size times the
* search string size
@@ -699,6 +699,10 @@ String GD_CORE_API operator+(String lhs, const char *rhs);
*/
String GD_CORE_API operator+(const char *lhs, const String &rhs);
const String& GD_CORE_API operator||(const String &lhs, const String &rhs);
String GD_CORE_API operator||(String lhs, const char *rhs);
/**
* \}
*/

View File

@@ -577,7 +577,7 @@ public:
#endif
/** Add a new node related to this. Adds a child past the LastChild.
Returns a pointer to the new object or NULL if an error occured.
Returns a pointer to the new object or NULL if an error occurred.
*/
TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
@@ -594,17 +594,17 @@ public:
TiXmlNode* LinkEndChild( TiXmlNode* addThis );
/** Add a new node related to this. Adds a child before the specified child.
Returns a pointer to the new object or NULL if an error occured.
Returns a pointer to the new object or NULL if an error occurred.
*/
TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
/** Add a new node related to this. Adds a child after the specified child.
Returns a pointer to the new object or NULL if an error occured.
Returns a pointer to the new object or NULL if an error occurred.
*/
TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
/** Replace a child of this node.
Returns a pointer to the new object or NULL if an error occured.
Returns a pointer to the new object or NULL if an error occurred.
*/
TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
@@ -1471,7 +1471,7 @@ public:
@sa SetTabSize, Row, Column
*/
int ErrorRow() const { return errorLocation.row+1; }
int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occurred. See ErrorRow()
/** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
to report the correct values for row and column. It does not change the output

View File

@@ -99,7 +99,7 @@ Everything in GDevelop.js is meant to create a "bridge" allowing us to run and u
### I want all the gory details about GDevelop.js 🧐
All the required C++ files are imported into this huge list: https://github.com/4ian/GDevelop/blob/master/GDevelop.js/Bindings/Wrapper.cpp#L1-L79. C++ compilation is done with a "build system" called CMake, which is using [this file](https://github.com/4ian/GDevelop/blob/master/GDevelop.js/CMakeLists.txt#L82-L101) to see what to compile.
All the required C++ files are imported into this huge list: <https://github.com/4ian/GDevelop/blob/master/GDevelop.js/Bindings/Wrapper.cpp#L1-L79>. C++ compilation is done with a "build system" called CMake, which is using [this file](https://github.com/4ian/GDevelop/blob/master/GDevelop.js/CMakeLists.txt#L82-L101) to see what to compile.
> In an ideal world, there would be something to do this automatically, so the GDevelop.js folder would not even exist 😉
> If you're interested and want to know more about GDevelop.js bridging between C++ and JavaScript, look at [this talk from GDevelop original author](https://www.youtube.com/watch?v=6La7jSCnYyk).

View File

@@ -12,16 +12,16 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
External libraries used by GDevelop Core

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