Compare commits

...

150 Commits

Author SHA1 Message Date
Florian Rival
50d7bec375 Bump newIDE version 2021-10-25 15:30:31 +01:00
Clément Pasteau
0c85e9bf30 Prevent sending session hits if the session is not correctly created 2021-10-25 15:58:30 +02:00
github-actions[bot]
08c41ece71 Update translations (#3197) 2021-10-25 14:27:17 +01:00
Aurélien Vivet
bd9fffba3f Remove unused test games from GDevelop 4 (#3192)
Don't show in changelog
2021-10-24 19:22:31 +01:00
github-actions[bot]
413caf6f62 Update translations (#3182) 2021-10-22 22:15:43 +01:00
Aurélien Vivet
530d0baffe Remove beta term from the docs (#3187)
Don't show in changelog
2021-10-22 22:13:14 +01:00
Aurélien Vivet
e78d2c6962 Add automation to automatically close stale issues (#3184)
Only show in developer changelog
2021-10-22 11:26:31 +01:00
Arthur Pacaud
bc606ed1be Add a console to the games debugger (#2770)
* When launching the Debugger to inspect a game, open the Console to see internal messages sent by the game, JavaScript code or the game engine.
* This is an advanced feature that is useful to find issues in your game or to see if your game is displaying any internal error.
2021-10-21 19:47:28 +01:00
Clément Pasteau
c705f89de8 Feature/external layout options (#3178)
Improve scene selection and help text for an external layout
2021-10-21 14:18:44 +02:00
github-actions[bot]
3b73b5eb6d Update translations 2021-10-21 12:40:29 +01:00
D8H
107410f0a4 Improve typing and simplify implementation of Linked Objects' getObjectsLinkedWith function (#3180)
Only show in developer changelog
2021-10-21 09:42:34 +01:00
D8H
b7b95d5e09 Add new tests for the platformer engine to prepare for the upcoming changes (#3176)
Only show in developer changelog
2021-10-20 15:40:01 +02:00
AlexandreS
a470e9b86c Fixes an issue with ghost instances of behaviors (light obstacle and pathfinder obstacle) 2021-10-20 10:45:01 +02:00
Clément Pasteau
cf5c8ae631 Improve Expression autocomplete for functions 2021-10-18 13:22:01 +02:00
AlexandreS
8f8ac2fd1e Show index of current focused result in Event Sheet 2021-10-15 09:34:48 +02:00
Clément Pasteau
cdac70425e Prevent debugger server being launched twice, causing a crash
Do not show in changelog
2021-10-14 16:58:46 +02:00
AlexandreS
378f0a48ad Add possibility to search in events sentences
* Better highlight of search results
* Remove highlights when closing the search panel
2021-10-14 15:52:30 +02:00
Clément Pasteau
e653639366 Improve Expression autocomplete (#3167)
Improve Expression Autocomplete to be more intuitive
2021-10-14 15:08:18 +02:00
Florian Rival
e105d4c9f6 Disable history when publishing the web-app to GitHub pages
Don't show in changelog
2021-10-11 16:43:33 +01:00
Florian Rival
5b80bed305 Fix crash happening when modifying "dead" instances after removing a layer and instances that were on it
Fix #3164
2021-10-11 16:39:35 +01:00
AlexandreS
a4ac323e63 Only show the operators that can be actually used in actions/conditions for strings (#3156)
* For strings/texts, only = and ≠ can be used for comparisons, and "set to"/"add to" for modifications.
2021-10-08 17:14:02 +01:00
Clément Pasteau
bc23d6a084 Fix effects being applied multiple times on objects when creating and destroying a lot of them (#3149)
* Effects from destroyed objects could be cleaned incorrectly and applied to new objects, creating glitches on newly created objects.
2021-10-08 16:14:23 +01:00
Florian Rival
2c24359fba Skip CI for Pull Request automatically open to update translations
We can always remove this tag before merging. This is to avoid doubling the usage of Travis/Semaphore CIs at every commit on master.

Don't show in changelog
2021-10-08 11:48:32 +01:00
Clément Pasteau
a6b01fc01d Add conditions for mouse key pressed from text 2021-10-08 12:15:35 +02:00
github-actions[bot]
44b81f52ea Update translations (#3154)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2021-10-07 23:06:41 +01:00
Florian Rival
cfdf13538e Automate update of translations (#3153)
* Automatically download and build latest translations from Crowdin at each commit on master, opening a PR with the changes (if any).
2021-10-07 22:58:50 +01:00
Florian Rival
7ee38a50bf Fix translations
Launched npm run compile-translations *after* launching npm run extract-all-translations, so that the English .po file was up-to-date to avoid missing translations in English language.

Don't show in changelog
2021-10-07 19:28:01 +01:00
Florian Rival
e2b8620b83 Fix translations
Don't show in changelog
2021-10-07 17:18:57 +01:00
AlexandreS
7ed8660edc Fix translations - Don't show in changelog 2021-10-07 18:10:18 +02:00
AlexandreS
75cc70368c Bump newIDE version and update translations 2021-10-07 16:38:19 +02:00
AlexandreS
0d3dfe5cf4 Display another user's profile when clicking their badge 2021-10-07 15:57:49 +02:00
Clément Pasteau
e7aa75bcd7 Add possibility to change one's email with confirmation 2021-10-07 13:28:44 +02:00
Clément Pasteau
c5ad127e83 Fix opening up the parameters dialog for object or behaviors expressions having no parameters 2021-10-07 12:28:27 +02:00
Clément Pasteau
acfdebfc0f Prevent calling a user update on every authState change
This fixes a race condition where the fetchUser would be called too early, causing a conflict with the signup function while creating the user in the database.

Do not show in changelog
2021-10-06 12:15:56 +02:00
Leo_Red
d3f8b410b0 Fix wording of "empty game" to "empty project" for consistency (#3136) 2021-10-06 09:04:53 +01:00
Florian Rival
4b7d67ce97 Fix very long object names overflowing or messing up some dialogs in the editor 2021-10-05 23:46:08 +01:00
Florian Rival
46a81ef4be Fix icons aligment and text ellipsis for long resource names in resources selector 2021-10-05 23:46:08 +01:00
Florian Rival
fe2812b8e8 Update caching by service worker of libGD.js/wasm
Don't show in changelog
2021-10-05 23:46:08 +01:00
Clément Pasteau
042cf49b3b Allow user to verify their email (#3132)
Allow users to verify their email
2021-10-05 18:23:29 +02:00
Florian Rival
7cf334ad1c Fix Edit My Profile and Logout buttons not working anymore
This was because of a stale "state" used by React. Fix by using the functional version of setState.

Also fix some Flow types that are not stricts.

Don't show in changelog
2021-10-04 17:47:10 +01:00
AlexandreS
f999bee387 Fix loss of user login between IDE refreshes 2021-10-04 17:09:43 +02:00
AlexandreS
0627d4b865 Show user's bio on My Profile window 2021-10-04 16:12:22 +02:00
Clément Pasteau
92e6a5e67f Improve user autocomplete (#3129)
Prevent saving projects and extensions with non-existing authors
2021-10-04 11:44:40 +02:00
Aurélien Vivet
d980400c2b Add "FontSize" expression for Text objects (#2974) 2021-10-03 15:50:30 +01:00
MechanicalPen
e235694fac Fix conditions comparing Dialogue Tree variables to work even if the dialogue is not running (#3127) 2021-10-03 12:07:33 +01:00
AlexandreS
cdf00d10f1 Give possibility to enter one's bio 2021-10-01 17:07:40 +02:00
Clément Pasteau
218520b836 Update translations (#3124) 2021-10-01 15:56:10 +01:00
Clément Pasteau
3ce71813ba Bump newIDE version (#3122) 2021-10-01 14:03:39 +01:00
Clément Pasteau
90300f895c Validate the username format in the create & edit forms 2021-10-01 14:56:14 +02:00
Florian Rival
9c8aa57fb6 Fix alignment of a background text in profile dialog
Don't show in changelog
2021-10-01 13:50:03 +01:00
Clément Pasteau
84876a1dff Display contributions (examples & extensions) on the user profile (#3110)
Display contributions (examples & extensions) on the user profile
2021-10-01 13:27:03 +02:00
Florian Rival
19ef8742f0 Extract translation sources and upload them to Crowdin at each commit on master (#3114)
* Extract but without upload for other branches

Don't show in changelog
2021-10-01 11:25:36 +01:00
Clément Pasteau
567efafa70 Display error if username is not valid 2021-10-01 11:41:59 +02:00
AlexandreS
c70685ccc7 Improve changelog extraction
Don't show in changelog
2021-09-30 17:10:15 +02:00
ClementPasteau
ec8daa7d8d Change profile.id calls to firebaseUser.id (#3112)
This ensures we don't prevent an action because the profile is
not fetched yet

Don't show in changelog
2021-09-30 12:32:43 +01:00
Florian Rival
0d817f4dae Fix warning
Don't show in changelog
2021-09-30 10:44:14 +01:00
AlexandreS
9dbbaada01 Update translations 2021-09-30 10:10:37 +01:00
AlexandreSi
342a6dc56f Bump newIDE version 2021-09-30 09:24:17 +01:00
Florian Rival
baae910fe8 Remove useless postfixing of the libGD.js/wasm files
Don't show in changelog
2021-09-30 09:06:38 +01:00
Florian Rival
2c6d30b28e Fix warning
Don't show in changelog
2021-09-29 22:49:35 +01:00
AlexandreS
9321f0ec7c Do not open expression parameters dialog if no parameters to configure 2021-09-29 18:23:46 +02:00
AlexandreS
e463f352b7 Add several UI improvements on the IDE 2021-09-29 18:16:47 +02:00
AlexandreS
5e3430aea5 Don't show in changelog - Remove unused #ifdef 2021-09-29 16:26:03 +02:00
AlexandreS
2d899d7c52 Add possibility to start and stop particle emitter 2021-09-29 09:25:03 +02:00
Florian Rival
0b933a569e Fix Bitmap Text objects crashing the editor if the font was renamed in resources 2021-09-24 20:24:06 +01:00
Florian Rival
4904e7e7fb Fix crash at game loading when a resource file was not found 2021-09-24 19:23:55 +01:00
Florian Rival
bfb1b6b15d Fix crash when moving a parameter of a function of an extension (or a custom behavior) after adding it
Fix #3093, fix #2729
2021-09-24 18:12:35 +01:00
ClementPasteau
9364a485cd Fix Folder being set for both Examples and Starters 2021-09-24 17:02:28 +02:00
ClementPasteau
176a2a0b47 Modify calls to Example & Extension with new endpoints
Do not show in changelog
2021-09-24 16:42:28 +02:00
AlexandreS
a10c9362dd Add condition to test if platformer is on a given platform 2021-09-24 14:15:06 +02:00
AlexandreS
3a0f55ee1b Fix windows notifications title 2021-09-24 14:01:54 +02:00
ClementPasteau
0b6bddc5a4 Feature/display authors on examples (#3090)
Display Examples authors on the search list and the details popup
2021-09-24 13:55:18 +02:00
Florian Rival
bf910e0cba Fix Scan for Images/Fonts/Audios in the resources editor wrongly adding resources with files already in other resources
* This could be visible when using the asset store or resources that have been renamed.
2021-09-24 00:09:32 +01:00
Florian Rival
763d8e8175 Fix renaming resources breaking objects or events using it
* Also fix the Bitmap Font field not shown in the parameters of the action to change it.
2021-09-24 00:09:32 +01:00
D8H
135ba2b4df Add expressions for properties of type "color" for custom behaviors (#3086) 2021-09-23 17:39:55 +01:00
ClementPasteau
d4a3722ec8 Fix authorIds being saved in the prop elements of a project (#3084) 2021-09-23 13:01:35 +00:00
ClementPasteau
477e88d4ce Allow entering the authors usernames in the Project properties 2021-09-23 12:46:31 +02:00
AlexandreS
023ed8f7b5 Add possibility to zoom in or out on events sheet 2021-09-23 09:37:33 +02:00
Florian Rival
55020a3d15 Fix the deployed storybook not properly loading libGD.js
Don't show in changelog
2021-09-22 17:24:07 +01:00
Florian Rival
552219e48f Add CI to deploy automatically the Storybook for each commit (#3081)
* Useful to quickly test components without having to fetch and build locally a branch.
* Can optionally be deployed to Chromatic if the GitHub action is launched manually.

Only show in developer changelog
2021-09-22 16:58:47 +01:00
ClementPasteau
4dfac41d81 Improve userAutocomplete help text (#3079) 2021-09-22 17:28:52 +02:00
Florian Rival
33deca92e3 Upgrade to Storybook v6 (#3078)
* Add a dropdown to choose the theme in the stories, useful to quickly check a component with all themes.
* Add support for build-storybook (to build a static version of the Storybook). Will be useful to share the storybook on PRs later or even do visual regression testing.

Test: yarn && yarn start, yarn storybook and yarn build-storybook works
Test: npm i && npm start, npm run storybook and npm run build-storybook works
Test: npm run build in newIDE/app works

Only show in developer changelog
2021-09-22 16:10:34 +01:00
AlexandreS
adc7584981 Fix particle emitter unused parameter friction removing it 2021-09-22 13:13:13 +02:00
ClementPasteau
23d5296a52 Feature/authors extension autocomplete (#3073)
Allow authors to be specified when creating an Extension
2021-09-22 12:57:01 +02:00
AlexandreS
2febbf439f Fix some particle emitter actions and conditions 2021-09-22 10:49:47 +02:00
D8H
169a49a246 Optimize Linked Objects actions/conditions, up to 80% faster on games using it extensively with a lot of objects (#3022) 2021-09-21 22:21:16 +01:00
ClementPasteau
c8c4322ece Feature/display extension username (#3056)
Display Authors on Extensions list and details popup
2021-09-20 09:16:14 +02:00
Florian Rival
349703e287 Add a test checking that groups are working correctly inside functions.
Don't show in changelog
2021-09-19 21:43:35 +01:00
D8H
1326ffd3b6 Fix regression in Draggable behavior (objects could be dragged only vertically or horizontally) (#3068)
Don't show in changelog
2021-09-19 12:42:47 +01:00
Florian Rival
baff4d3cb0 Fix long description fields for parameters shown when changing from one function to another after adding a long description
Fix #3067
2021-09-19 10:09:28 +01:00
D8H
b40e2d3fdf Improve Draggable behavior to drag the frontmost object under the cursor/touch (#3066)
* In previous versions, the order was not guaranteed, which could result in a non intuitive result for the player.
2021-09-19 01:36:49 +01:00
Florian Rival
8e6ba3abce Add autocompletion for effect and effect parameter names in actions and conditions (#3060) 2021-09-19 00:36:39 +01:00
D8H
aaebbe47d5 Improve the Draggable behavior to reduce memory usage. (#3064) 2021-09-19 00:25:10 +01:00
AlexandreS
a51003040c Set the default dimensions of a new collision mask to the dimensions of the sprite 2021-09-16 16:48:08 +02:00
Florian Rival
cfce635419 Add automatic addition of extensions, examples and assets commits in the changelog (#3051)
* Also ensure scripts are type checked.

Don't show in changelog
2021-09-16 14:49:03 +01:00
Florian Rival
3d299c5a14 Add back debug task to launch the editor in Chrome (and debug from VSCode) [skip ci]
Don't show in changelog
2021-09-16 09:48:48 +01:00
AlexandreS
f33196dc85 Fix unexpected custom loading screen image removal when removing unused images 2021-09-15 17:06:25 +02:00
AlexandreS
7b2dc2223c Merge pull request #3045 from 4ian/tween-object-color-parameter-type
Add color picker to Add Object Color Tween action 'To color' parameter
2021-09-14 11:48:01 +02:00
AlexandreSi
b37d05f78c Add color picker to Add Object Color Tween action 'To color' parameter 2021-09-14 11:11:52 +02:00
Florian Rival
dcba0b45a6 Remove an ignored (though innocuous) clang warning 2021-09-13 20:29:24 +02:00
Florian Rival
f2ec46ca1e Enable more warnings from Clang when compiling C++ sources (#3042)
Only show in developer changelog
2021-09-13 20:02:03 +02:00
ClementPasteau
5c33e9e8d0 Allow user to enter their username when registering (#3024)
Allow user to add their username when registering
2021-09-13 18:06:16 +02:00
ClementPasteau
fc23517bae Upgrade Pixi.js to 6.1.2 (#3026) 2021-09-13 17:45:27 +02:00
Florian Rival
24c74af79b Fix effects of objects not always working, depending on layers/object position in the list 2021-09-13 13:35:26 +02:00
Florian Rival
2a19ea5182 Bump newIDE version 2021-09-09 12:30:40 +01:00
Florian Rival
705c7af134 Improve typings in the extract changelog script
Don't show in changelog
2021-09-09 12:25:25 +01:00
Florian Rival
028eebefab Fix the regression when using Linked Objects in behaviors by temporarily removing the optimization (#3023) 2021-09-09 12:23:35 +01:00
Florian Rival
25acb603b4 Bump newIDE version 2021-09-07 19:29:02 +01:00
Florian Rival
27d4ead51e Update translations 2021-09-07 19:22:13 +01:00
Florian Rival
1704d196f9 Add script to easily download artifacts (useful when deploying a new release)
Don't show in changelog
2021-09-07 19:19:04 +01:00
D8H
d40e360b8a Add support for behaviors based on other behaviors ("behavior composition") (#2781)
* This allows [custom behaviors](http://wiki.compilgames.net/doku.php/gdevelop5/behaviors/events-based-behaviors), that you can create in your project or get from extensions, to require the presence of one or multiple other behaviors on an object.
  * This is an advanced feature that is helpful to create behaviors that are based on other. For example, a behavior "Platformer enemy" using the "Platformer object" behavior and adding specific actions, conditions and logic to make an enemy chase the player.
  * If you create a behavior and want to use this, just go to the properties of this behavior and add a new property. Choose the type "Required Behavior" for this property. You can then use this new behavior in the events of the behavior you just edited.
* To use a behavior based on another, you don't need to do anything special! Just add it to your object as usual: any missing behavior will be added to your object, so you can start using it immediately.
2021-09-06 19:51:42 +01:00
ClementPasteau
183a0bd08e Increase shader precision, allowing lights to be displayed correctly on iOS (#3017) 2021-09-06 17:43:45 +01:00
D8H
8780f2f415 Add tests for platformer objects on slope junctions (#3016)
Only show in developer changelog
2021-09-06 10:57:56 +01:00
Aurélien Vivet
5adb3c92ee Add "object" term in timer action for object (#3002)
* Add "object" term in timer action for object

* Change for other actions and conditions
2021-09-03 08:04:18 +00:00
D8H
a54ee812bd Improve performance of conditions of "Linked Objects" (#2995) 2021-08-31 21:29:11 +02:00
Aurélien Vivet
f8db01706d Increase the extension description text field height (#2997)
Don't show in changelog
2021-08-31 13:51:01 +02:00
Florian Rival
d9368921af Clean old examples JSON files (#2996)
Not used anymore (the web-app uses examples from resources.gdevelop-app.com)

Don't show in changelog
2021-08-30 16:17:20 +02:00
Florian Rival
12743f6f7e Prevent instances to have a negative width or height in the instances editor
* Note that this does not affect existing games that would use this incorrect behavior (which can create bugs)
2021-08-30 13:20:41 +02:00
Florian Rival
3d3048906e Fix crash when instances were resized on the scene editor after being set to a size of 0
Fix #2983, fix #2829
2021-08-30 12:16:47 +02:00
Ulises Freitas
413fbc529e Updated URL in credits (#2985)
Don't show in changelog
2021-08-28 16:48:28 +02:00
ClementPasteau
287ebd4244 Allow colors to be used for Behavior properties (#2980) 2021-08-27 15:45:46 +02:00
Florian Rival
f2199c8ab4 Clean unused exports/functions (#2978)
Don't show in changelog
2021-08-27 11:17:01 +02:00
ClementPasteau
64b63d4efa Rework the color fields to allow to enter colors as R;G;B directly in the field (#2972) 2021-08-27 10:34:55 +02:00
ClementPasteau
3820c2613a Allow behaviors to have a "string list" property like functions (#2968) 2021-08-25 10:05:30 +02:00
Arthur Pacaud
c42603bb29 Add multiple contributors to the credits (#2967) 2021-08-25 07:47:13 +02:00
ClementPasteau
b879d3043f Increase Flow hash table to avoid memory limitations (#2966)
Only show in developer changelog
2021-08-24 11:21:32 +02:00
ClementPasteau
8be448fd0e Allow rounding pixels when rendering on a project level (#2965) 2021-08-24 10:44:06 +02:00
Florian Rival
9535fbca0f Fix S3 upload on CircleCI (#2960)
aws cli was not properly installed even with the last fix. Now using the "official" commandline: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-mac.html

Don't show in changelog
2021-08-23 14:03:01 +02:00
Harsimran Singh Virk
6667a0005c Remove deprecated/unmaintained Cocos2d-JS renderer files (#2956)
Only show in developer changelog
2021-08-23 12:27:47 +02:00
ClementPasteau
860faae853 Update newIDE deployment docs (#2900)
Don't show in changelog
2021-08-23 09:57:43 +02:00
Florian Rival
dd47c7f6c4 Fix installation of awscli on macOS on CircleCI for automatic builds (#2955)
Don't show in changelog
2021-08-20 16:42:48 +02:00
Aurélien Vivet
c4f76efbcd Fix some missing translations (#2953) 2021-08-20 16:23:02 +02:00
Florian Rival
56d9dc05f1 Add command to open the extension search in the command palette 2021-08-20 16:15:37 +02:00
Harsimran Singh Virk
599ccb677f Add support for visual effects ("shaders") on objects. (#2901)
* This allows to generate interesting visual effects, which can be controlled by events. For example, you can use an outline on an object to highlight, make the player glow when launching a spell, blur objects, etc...
* A new "effects" tab is now present in the objects editor. From there, you can add visual effects, that were already available for layers, customize them from this editor.
* Actions and conditions are available to manipulate effects and change their parameters during the game.
* Learn more on the wiki: http://wiki.compilgames.net/doku.php/gdevelop5/objects/effects

Co-authored-by: Florian Rival <Florian.Rival@gmail.com>
2021-08-20 15:01:06 +02:00
Florian Rival
b97f716c09 Improve events sheet wording for object boolean variables 2021-08-19 14:58:22 +02:00
Florian Rival
58917aec02 Improve typing of TestRuntimeObject (#2943)
Only show in developer changelog
2021-08-19 10:11:16 +02:00
Florian Rival
fdaba4a6d5 Auto cancel Semaphore builds on newer commits, even when running, for faster tests [skip ci]
Don't show in changelog
2021-08-19 10:01:09 +02:00
Florian Rival
d1f49cd1f7 Update Semaphore links [skip ci] 2021-08-18 15:39:32 +02:00
Florian Rival
71a9a3f1d0 Use Semaphore 2 to run the fast tests for each commit/PR (#2935)
Only show in developer changelog
2021-08-18 12:05:00 +02:00
Arthur Pacaud
9173e704be Move variable event tools to their own file (#2870)
Only show in developer changelog
2021-08-17 21:17:58 +02:00
Florian Rival
1a27f689e0 Remove deprecated/unused/unmaintained GDCpp code (#2930)
* This also includes extensions code.

Only show in developer changelog
2021-08-17 14:34:58 +02:00
Aurélien Vivet
ef198b2c64 Fix missing translations in the main menu bar (#2933) 2021-08-17 14:09:02 +02:00
Arthur Pacaud
d5039b5b51 Prevent variable value to be set to an invalid number ("NaN" ) in the variables editor 2021-08-17 12:19:08 +02:00
Florian Rival
4b19696523 Add missing extensions on the web-app (Screenshot, AdvancedWindow)
Don't show in changelog
2021-08-16 20:43:06 +02:00
Florian Rival
32978c22e8 Fix games crashing when an unknown action/condition was used (could come from a deleted extension) 2021-08-16 19:36:52 +02:00
Florian Rival
1f6f2701ff Fix variable dropdown not updated in the action/condition editor after editing variables 2021-08-16 16:42:43 +02:00
Florian Rival
fbf2340f00 Fix a crash when drag'n'dropping actions/conditions in custom behaviors 2021-08-16 16:37:59 +02:00
Florian Rival
4ff208b39f Allow again to choose the opacity of the grid in the scene editor
* Also fix an issue where a grid with the black color was not persisted properly.

Fix #2922 and fix #2918
2021-08-16 11:33:56 +02:00
Florian Rival
3d0a893c1c Autoclose beta 114 upgrade issue [skip ci] 2021-08-13 15:03:59 +02:00
Clément Pasteau
2581021a57 Ensure the deployment script stops on error 2021-08-13 10:39:23 +02:00
1709 changed files with 38606 additions and 749293 deletions

View File

@@ -12,8 +12,12 @@ jobs:
# System dependencies (for Emscripten and upload)
- run:
name: Install dependencies for Emscripten and AWS S3 upload
command: brew install cmake && brew install awscli
name: Install dependencies for Emscripten
command: brew install cmake
- run:
name: Install dependencies for AWS S3 upload
command: curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg" && sudo installer -pkg AWSCLIV2.pkg -target /
- run:
name: Install Emscripten (for GDevelop.js)
@@ -64,10 +68,10 @@ jobs:
# Upload artifacts (AWS)
- run:
name: Deploy to S3 (specific commit)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
- run:
name: Deploy to S3 (latest)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
build-linux:
# CircleCI docker workers are failing if they don't have enough memory (no swap)

View File

@@ -13,6 +13,5 @@
-fPIC
-I./ExtLibs/SFML/include
-I./Core
-I./GDCpp/.
-I./GDJS/.
-F./ExtLibs/SFML/extlibs/libs-osx/Frameworks

1
.gitattributes vendored
View File

@@ -1,6 +1,5 @@
Core/GDCore/Serialization/rapidjson/rapidjson.h/* linguist-vendored
Core/GDCore/TinyXml/* linguist-vendored
GDCpp/GDCpp/Runtime/TinyXml/* linguist-vendored
Extensions/ParticleSystem/SPARK/* linguist-vendored
Extensions/PhysicsBehavior/Box2D/* linguist-vendored
Extensions/PhysicsBehavior/box2djs/* linguist-vendored

15
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
# Automatically close issues with certain tags indicating that we need more information,
# after some days have passed.
daysUntilStale: 20
daysUntilClose: 7
# Only do this on tags implying we need more information:
onlyLabels: ["Need a game/precise steps to reproduce the issue","👋 Needs confirmation/testing"]
only: issues
markComment: >
This issue seems to be stale: it needs additional information but it has not had
recent activity. It will be closed in 7 days if no further activity occurs. Thank you
for your contributions.

71
.github/workflows/build-storybook.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
# GitHub Action to build the Storybook of the editor and publish it for testing.
#
# Note that only the Storybook is built and GDevelop.js is not rebuilt (for speed concerns),
# so changes in the C++ source could not be reflected if the CI run by Travis-CI
# did not upload a freshly built GDevelop.js.
name: Build Storybook
on:
# Launch on all commits.
push:
# Allows to run this workflow manually from the Actions tab,
# to publish on Chromatic (not done by default).
workflow_dispatch:
jobs:
build-storybook:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
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
- name: Build Storybook
run: npm run build-storybook
working-directory: newIDE/app
# Publish on S3 to allow quick testing of components.
- name: Publish Storybook to S3 bucket (specific commit)
run: aws s3 sync ./build-storybook/ s3://gdevelop-storybook/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/ --delete
working-directory: newIDE/app
- name: Publish Storybook to S3 bucket (latest)
run: aws s3 sync ./build-storybook/ s3://gdevelop-storybook/$(git rev-parse --abbrev-ref HEAD)/latest/ --delete
working-directory: newIDE/app
- name: Log urls to the Storybook
run: |
echo "Find the latest Storybook for this branch on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html"
echo "Find the Storybook for this commit on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html"
# Publish on Chromatic, only when manually launched (too costly to run on every commit).
- name: Publish Storybook to Chromatic
if: github.event_name == 'workflow_dispatch'
uses: chromaui/action@v1
with:
workingDir: newIDE/app
storybookBuildDir: "build-storybook"
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

View File

@@ -0,0 +1,47 @@
# GitHub Action to extract translations and (later) upload them to Crowdin.
name: Extract translations
on:
# Execute for all commits (to ensure translations extraction works)
push:
# Allows to run this workflow manually from the Actions tab.
workflow_dispatch:
jobs:
extract-translations:
runs-on: ubuntu-latest
steps:
- 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') }}
- name: Install gettext
run: sudo apt update && sudo apt install gettext -y
- name: Install newIDE dependencies
run: npm install
working-directory: newIDE/app
- name: Extract translations
run: npm run extract-all-translations
working-directory: newIDE/app
# Only upload on Crowdin for the master branch
- name: Install Crowdin CLI
if: github.ref == 'refs/heads/master'
run: npm i -g @crowdin/cli
- name: Upload translations to Crowdin
run: crowdin upload sources
if: github.ref == 'refs/heads/master'
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

View File

@@ -18,3 +18,11 @@ jobs:
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."

View File

@@ -0,0 +1,73 @@
# GitHub Action to update translations by downloading them from Crowdin,
# and open a Pull Request with the changes.
name: Update translations
on:
# Execute only on master
push:
branches:
- master
# Allows to run this workflow manually from the Actions tab.
workflow_dispatch:
jobs:
update-translations:
runs-on: ubuntu-latest
steps:
- 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') }}
- name: Install gettext
run: sudo apt update && sudo apt install gettext -y
- name: Install newIDE dependencies
run: npm install
working-directory: newIDE/app
# We need to extract translations first to make sure all the source strings
# are included in the English catalogs. Otherwise, missing source strings
# with parameters (like "My name is {0}.") would be shown as-is when
# the app is built (but not in development - unclear why, LinguiJS issue?).
- name: Extract translations
run: npm run extract-all-translations
working-directory: newIDE/app
# (Build and) download the most recent translations (PO files) from Crowdin.
- name: Install Crowdin CLI
run: npm i -g @crowdin/cli
- name: Download new translations from Crowdin
run: crowdin download
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
# Seems like the three letters code is not handled properly by LinguiJS?
# Do without this language while we find a solution.
- name: Remove catalogs not handled properly by LinguiJS compile command.
run: rm -rf newIDE/app/src/locales/pcm_NG/
- name: Compile translations into .js files that are read by LinguiJS
run: npm run compile-translations
working-directory: newIDE/app
- name: Create a Pull Request with the changes
uses: peter-evans/create-pull-request@v3.10.1
with:
commit-message: Update translations [skip ci]
branch: chore/update-translations
delete-branch: true
title: '[Auto PR] Update translations'
body: |
This updates the translations by downloading them from Crowdin and compiling them for usage by the app.
Please double check the values in `newIDE/app/src/locales/LocalesMetadata.js` to ensure the changes are sensible.

2
.gitignore vendored
View File

@@ -1,4 +1,3 @@
/Core/GDCore/Tools/VersionPriv.h
/docs
/docs-wiki
/ExtLibs/SFML
@@ -16,7 +15,6 @@
*.bc
/Binaries/Output
*.autosave
!/GDCpp/scripts/bcp.exe
!/scripts/libgettextlib-0-17.dll
!/scripts/libgettextsrc-0-17.dll
!/xgettext.exe

106
.semaphore/semaphore.yml Normal file
View File

@@ -0,0 +1,106 @@
version: v1.0
name: Fast tests (not building GDevelop.js - can have false negatives)
agent:
machine:
type: e1-standard-2
os_image: ubuntu2004
auto_cancel:
running:
when: "true"
blocks:
- name: Install
task:
jobs:
- name: Install node_modules and cache them
commands:
- checkout
- node -v
- |-
if ! cache has_key newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json); then
cd newIDE/app
npm i
cd ../..
cache store newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json) newIDE/app/node_modules
fi
- |-
if ! cache has_key GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json); then
cd GDJS
npm i
cd ..
cache store GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json) GDJS/node_modules
fi
- |-
if ! cache has_key GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json); then
cd GDJS/tests
npm i
cd ../..
cache store GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json) GDJS/tests/node_modules
fi
dependencies: []
- name: Type checks
dependencies:
- Install
task:
jobs:
- name: newIDE typing
commands:
- checkout
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd newIDE/app
- npm run postinstall
- npm run flow
- npm run check-script-types
- cd ../..
- name: GDJS typing and documentation generation
commands:
- checkout
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
- cd GDJS
- npm run check-types
- npm run generate-doc
- name: Auto formatting
dependencies:
- Install
task:
jobs:
- name: newIDE auto-formatting
commands:
- checkout
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd newIDE/app
- npm run postinstall
- npm run check-format
- cd ../..
- name: GDJS auto-formatting
commands:
- checkout
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd GDJS
- npm run check-format
- cd ..
- name: Tests
dependencies:
- Install
task:
jobs:
- name: newIDE tests
commands:
- checkout
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd newIDE/app
- npm run postinstall
- npm run analyze-test-coverage
- cd ../..
- name: GDJS tests
commands:
- checkout
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
- cd GDJS
- npm run build
- npm run test
- cd ../..

View File

@@ -1,5 +1,5 @@
# Travis CI configuration to build and run all tests
# (and typing/formatting) for the Core, newIDE, GDJS (and even GDCpp).
# (and typing/formatting) for the Core, newIDE, GDJS.
#
# This builds GDevelop.js and store it on a S3 so it can be used to run
# GDevelop without building it.
@@ -62,7 +62,7 @@ before_install:
install:
#Get the correct version of gcc/g++
- if [ "$CXX" = "g++" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
#Compile the tests only for GDCore and GDCpp
#Compile the tests only for GDCore
- mkdir .build-tests
- cd .build-tests
- cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) ..
@@ -89,12 +89,9 @@ install:
- cd ../..
script:
# GDCore and GDCpp game engine tests:
# GDCore tests:
- cd .build-tests
- Core/GDCore_tests
- GDCpp/GDCpp_tests
- Extensions/PathfindingBehavior/PathfindingBehavior_Runtime_tests
- Extensions/LinkedObjects/LinkedObjects_Runtime_tests
- cd ..
# GDevelop.js tests
- cd GDevelop.js
@@ -105,12 +102,13 @@ script:
- npm test
- npm run flow
- npm run check-format
- npm run check-script-types
- cd ../..
# GDJS tests:
- cd GDJS
- npm run check-format
- cd ..
# GDJS game engine tests, disabled on Travis CI because ChromeHeadless can't be started.
# See them running on Semaphore-CI instead: https://semaphoreci.com/4ian/gd
# See them running on Semaphore-CI instead: https://gdevelop.semaphoreci.com/projects/GDevelop
# - cd GDJS/tests && npm test
# - cd ../..

View File

@@ -1,98 +1,104 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceRoot}",
"${workspaceRoot}/GDCpp",
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"defines": [
"EMSCRIPTEN",
"GD_IDE_ONLY",
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
"GD_API=/* Macro used to export classes on Windows, please ignore */",
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": ["/System/Library/Frameworks", "/Library/Frameworks"],
"compilerPath": "/usr/bin/clang",
"cStandard": "c11",
"cppStandard": "c++17"
},
{
"name": "Linux",
"includePath": [
"${workspaceRoot}",
"${workspaceRoot}/GDCpp",
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"defines": [
"EMSCRIPTEN",
"GD_IDE_ONLY",
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
"GD_API=/* Macro used to export classes on Windows, please ignore */",
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
],
"intelliSenseMode": "clang-x64",
"browse": {
"path": ["/usr/include", "/usr/local/include", "${workspaceRoot}"],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"${workspaceRoot}",
"${workspaceRoot}/GDCpp",
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE",
"EMSCRIPTEN",
"GD_IDE_ONLY",
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
"GD_API=/* Macro used to export classes on Windows, please ignore */",
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": ["${workspaceRoot}"],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 4
}
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceRoot}",
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"defines": [
"EMSCRIPTEN",
"GD_IDE_ONLY",
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
"GD_API=/* Macro used to export classes on Windows, please ignore */",
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1",
"/usr/local/include",
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include",
"/usr/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
],
"compilerPath": "/usr/bin/clang",
"cStandard": "c11",
"cppStandard": "c++17"
},
{
"name": "Linux",
"includePath": [
"${workspaceRoot}",
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"defines": [
"EMSCRIPTEN",
"GD_IDE_ONLY",
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
"GD_API=/* Macro used to export classes on Windows, please ignore */",
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
},
{
"name": "Win32",
"includePath": [
"${workspaceRoot}",
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"${workspaceRoot}"
],
"defines": [
"_DEBUG",
"UNICODE",
"EMSCRIPTEN",
"GD_IDE_ONLY",
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
"GD_API=/* Macro used to export classes on Windows, please ignore */",
"GD_EXTENSION_API=/* Macro used to export classes on Windows, please ignore */"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 4
}

29
.vscode/launch.json vendored
View File

@@ -4,13 +4,36 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "GDevelop.js Jest tests (all)",
"program": "${workspaceFolder}/GDevelop.js/node_modules/.bin/jest",
"args": ["--runInBand"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/GDevelop.js"
},
{
"type": "node",
"request": "launch",
"name": "GDevelop.js Jest tests (current file)",
"program": "${workspaceFolder}/GDevelop.js/node_modules/.bin/jest",
"args": [
"${fileBasenameNoExtension}"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/GDevelop.js"
},
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"name": "Debug with Chrome (web-app, local development server)",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"preLaunchTask": "Start development server"
"webRoot": "${workspaceFolder}"
}
]
}

View File

@@ -108,7 +108,8 @@
"xtree": "cpp",
"xutility": "cpp",
"xlocbuf": "cpp",
"xlocmes": "cpp"
"xlocmes": "cpp",
"xmemory0": "cpp"
},
"files.exclude": {
"Binaries/*build*": true,

2
.vscode/tasks.json vendored
View File

@@ -80,7 +80,7 @@
},
{
"type": "typescript",
"tsconfig": "GDJS/tsconfig.json",
"tsconfig": "tsconfig.json",
"option": "watch",
"problemMatcher": ["$tsc-watch"],
"group": "test",

View File

@@ -1,3 +1,3 @@
This is the directory where native or WebAssembly binaries of the C++ code of GDCore, GDCpp and GDJS are produced.
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.

View File

@@ -14,12 +14,10 @@ macro(gd_set_option var default type docstring)
endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
endmacro()
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library, FALSE to use the already compiled binaries")
gd_set_option(BUILD_GDCPP TRUE BOOL "TRUE to build GDevelop C++ Platform")
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library")
gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform")
gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions")
gd_set_option(BUILD_TESTS FALSE BOOL "TRUE to build the tests")
gd_set_option(FULL_VERSION_NUMBER TRUE BOOL "TRUE to build GDevelop with its full version number (lastest tag + commit hash), FALSE to only use the lastest tag (avoid rebulding many source file when developping)")
# Disable deprecated code
set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.
@@ -49,15 +47,11 @@ IF(APPLE)
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" )
set(CMAKE_BUILD_TYPE Release)
ENDIF()
IF (EMSCRIPTEN)
set(BUILD_GDCPP FALSE CACHE BOOL "" FORCE) #Force disable GDC++ when compiling with emscripten.
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.
@@ -77,6 +71,13 @@ endif()
# 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")
# Make as much warnings considered as errors as possible (only one for now).
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-stack-address")
endif()
@@ -84,7 +85,6 @@ endif()
set(GD_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
#Add all the CMakeLists:
ADD_SUBDIRECTORY(Version)
ADD_SUBDIRECTORY(ExtLibs)
IF(BUILD_CORE)
ADD_SUBDIRECTORY(Core)
@@ -92,10 +92,7 @@ ENDIF()
IF(BUILD_GDJS)
ADD_SUBDIRECTORY(GDJS)
ENDIF()
IF(BUILD_GDCPP)
ADD_SUBDIRECTORY(GDCpp)
ENDIF()
IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/GDevelop.js/CMakeLists.txt" AND EMSCRIPTEN)
IF(EMSCRIPTEN)
ADD_SUBDIRECTORY(GDevelop.js)
ENDIF()
IF(BUILD_EXTENSIONS)

View File

@@ -57,7 +57,6 @@ IF(EMSCRIPTEN)
ELSE()
add_library(GDCore SHARED ${source_files})
ENDIF()
add_dependencies(GDCore GDVersion)
IF(EMSCRIPTEN)
set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
ELSEIF(WIN32)

View File

@@ -14,9 +14,8 @@
*
* \section other Other documentations
*
* GDevelop is architectured around a `Core` (this library), platforms (`GDJS`, `GDCpp`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries.
* GDevelop is architectured around a `Core` (this library), a game engine (`GDJS`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries.
*
* - [Open GDevelop C++ Platform documentation](../GDCpp Documentation/index.html)
* - [Open GDevelop JS Platform documentation](../GDJS Documentation/index.html)
* - <a href="https://github.com/4ian/GDevelop/blob/master/newIDE/README.md">Getting started with the editor</a>
* - <a href="https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md">Getting started with the extensions</a>

View File

@@ -3,14 +3,17 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include <iostream>
#include "EffectsCodeGenerator.h"
#include <iostream>
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Project/Effect.h"
#include "GDCore/Project/Layer.h"
#include "GDCore/Project/EffectsContainer.h"
#include "GDCore/Project/Layer.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
namespace gd {
@@ -33,6 +36,24 @@ void ExposeProjectEffects(
worker(effect);
}
}
for (std::size_t i = 0; i < layout.GetObjectsCount(); i++) {
auto& object = layout.GetObject(i);
auto& effects = object.GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
auto& effect = effects.GetEffect(e);
worker(effect);
}
}
}
// Add global object effects
for (std::size_t s = 0; s < project.GetObjectsCount(); s++) {
auto& effects = project.GetObject(s).GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
auto& effect = effects.GetEffect(e);
worker(effect);
}
}
}

View File

@@ -261,8 +261,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
EventsCodeGenerationContext& context) {
gd::String conditionCode;
gd::InstructionMetadata instrInfos =
const gd::InstructionMetadata& instrInfos =
MetadataProvider::GetConditionMetadata(platform, condition.GetType());
if (MetadataProvider::IsBadInstructionMetadata(instrInfos)) {
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
maxConditionsListsSize =
@@ -299,15 +302,13 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
condition.SetParameter(pNb, gd::Expression(""));
condition.SetType("");
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
condition.SetParameter(pNb, gd::Expression(""));
condition.SetType("");
return "/* Mismatched object type - skipped. */";
}
}
}
@@ -425,6 +426,11 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
outputCode += "{\n";
outputCode += conditionCode;
outputCode += "}";
} else {
// Deprecated way to cancel code generation - but still honor it.
// Can be removed once condition is passed by const reference to
// GenerateConditionCode.
outputCode += "/* Skipped condition (empty type) */";
}
}
@@ -440,8 +446,11 @@ gd::String EventsCodeGenerator::GenerateActionCode(
gd::Instruction& action, EventsCodeGenerationContext& context) {
gd::String actionCode;
gd::InstructionMetadata instrInfos =
const gd::InstructionMetadata& instrInfos =
MetadataProvider::GetActionMetadata(platform, action.GetType());
if (MetadataProvider::IsBadInstructionMetadata(instrInfos)) {
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
@@ -466,15 +475,13 @@ gd::String EventsCodeGenerator::GenerateActionCode(
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
action.SetParameter(pNb, gd::Expression(""));
action.SetType("");
return "/* Unknown object - skipped. */";
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
action.SetParameter(pNb, gd::Expression(""));
action.SetType("");
return "/* Mismatched object type - skipped. */";
}
}
}
@@ -556,7 +563,14 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
gd::String actionCode = GenerateActionCode(actions[aId], context);
outputCode += "{";
if (!actions[aId].GetType().empty()) outputCode += actionCode;
if (actions[aId].GetType().empty()) {
// Deprecated way to cancel code generation - but still honor it.
// Can be removed once action is passed by const reference to
// GenerateActionCode.
outputCode += "/* Skipped action (empty type) */";
} else {
outputCode += actionCode;
}
outputCode += "}";
}
@@ -607,8 +621,14 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
argOutput = GenerateGetBehaviorNameCode(parameter);
} else if (metadata.type == "key") {
argOutput = "\"" + ConvertToString(parameter) + "\"";
} else if (metadata.type == "password" || metadata.type == "musicfile" ||
metadata.type == "soundfile" || metadata.type == "police") {
} else if (metadata.type == "password" || // Deprecated
metadata.type ==
"musicfile" || // Should be renamed "largeAudioResource"
metadata.type ==
"soundfile" || // Should be renamed "audioResource"
metadata.type == "police" || // Should be renamed "fontResource"
metadata.type == "bitmapFontResource" ||
metadata.type == "imageResource") {
argOutput = "\"" + ConvertToString(parameter) + "\"";
} else if (metadata.type == "mouse") {
argOutput = "\"" + ConvertToString(parameter) + "\"";

View File

@@ -462,24 +462,21 @@ class GD_CORE_API EventsCodeGenerator {
* Other standard parameters type that should be implemented by platforms:
* - currentScene: Reference to the current runtime scene.
* - objectList : a map containing lists of objects which are specified by the
object name in another parameter. (C++: std::map <gd::String,
std::vector<RuntimeObject*> *>). Example:
object name in another parameter. Example:
* \code
AddExpression("Count", _("Object count"), _("Count the number of picked
objects"), _("Objects"), "res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.SetFunctionName("PickedObjectsCount").SetIncludeFile("GDCpp/Extensions/Builtin/ObjectTools.h");
.SetFunctionName("getPickedObjectsCount");
* \endcode
* - objectListWithoutPicking : Same as objectList but do not pick object if
they are not already picked.
* - objectPtr : Return a pointer to object specified by the object name in
another parameter ( C++: RuntimeObject* ). Example:
* - objectPtr : Return a reference to the object specified by the object name in
another parameter. Example:
* \code
.AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Target object"))
//The called function will be called with this signature on the C++ platform:
Function(gd::String, RuntimeObject*)
* \endcode
*/
virtual gd::String GenerateParameterCodes(

View File

@@ -16,7 +16,6 @@
#include "GDCore/String.h"
namespace gd {
class EventsList;
class MainFrameWrapper;
class Project;
class Layout;
class EventsCodeGenerator;

View File

@@ -67,13 +67,13 @@ class GD_CORE_API ExpressionParser2 {
}
/**
* Given an object name (or empty if none) and a behavior name (or empty if none),
* return the index of the first parameter that is inside the parenthesis:
* 0, 1 or 2.
*
* For example, in an expression like `Object.MyBehavior::Method("hello")`, the
* parameter "hello" is the second parameter (the first being by convention Object,
* and the second MyBehavior, also by convention).
* Given an object name (or empty if none) and a behavior name (or empty if
* none), return the index of the first parameter that is inside the
* parenthesis: 0, 1 or 2.
*
* For example, in an expression like `Object.MyBehavior::Method("hello")`,
* the parameter "hello" is the second parameter (the first being by
* convention Object, and the second MyBehavior, also by convention).
*/
static size_t WrittenParametersFirstIndex(const gd::String &objectName,
const gd::String &behaviorName) {
@@ -403,9 +403,18 @@ class GD_CORE_API ExpressionParser2 {
const gd::ExpressionMetadata &metadata =
MetadataProvider::GetAnyExpressionMetadata(platform, functionFullName);
// In case we can't find a valid expression, ensure the node has the type
// that is requested by the parent, so we avoid putting "unknown" (which
// would be also correct, but less precise and would prevent completions to
// be shown to the user)
const gd::String returnType =
gd::MetadataProvider::IsBadExpressionMetadata(metadata) == true
? type
: metadata.GetReturnType();
auto parametersNode = Parameters(metadata.parameters);
auto function =
gd::make_unique<FunctionCallNode>(metadata.GetReturnType(),
gd::make_unique<FunctionCallNode>(returnType,
std::move(parametersNode.parameters),
metadata,
functionFullName);
@@ -458,9 +467,18 @@ class GD_CORE_API ExpressionParser2 {
MetadataProvider::GetObjectAnyExpressionMetadata(
platform, objectType, objectFunctionOrBehaviorName);
// In case we can't find a valid expression, ensure the node has the type
// that is requested by the parent, so we avoid putting "unknown" (which
// would be also correct, but less precise and would prevent completions
// to be shown to the user)
const gd::String returnType =
gd::MetadataProvider::IsBadExpressionMetadata(metadata) == true
? type
: metadata.GetReturnType();
auto parametersNode = Parameters(metadata.parameters, objectName);
auto function = gd::make_unique<FunctionCallNode>(
metadata.GetReturnType(),
returnType,
objectName,
std::move(parametersNode.parameters),
metadata,
@@ -520,10 +538,19 @@ class GD_CORE_API ExpressionParser2 {
MetadataProvider::GetBehaviorAnyExpressionMetadata(
platform, behaviorType, functionName);
// In case we can't find a valid expression, ensure the node has the type
// that is requested by the parent, so we avoid putting "unknown" (which
// would be also correct, but less precise and would prevent completions
// to be shown to the user)
const gd::String returnType =
gd::MetadataProvider::IsBadExpressionMetadata(metadata) == true
? type
: metadata.GetReturnType();
auto parametersNode =
Parameters(metadata.parameters, objectName, behaviorName);
auto function = gd::make_unique<FunctionCallNode>(
metadata.GetReturnType(),
returnType,
objectName,
behaviorName,
std::move(parametersNode.parameters),

View File

@@ -43,6 +43,7 @@ struct ExpressionParserLocation {
* \brief A diagnostic that can be attached to a gd::ExpressionNode.
*/
struct ExpressionParserDiagnostic {
virtual ~ExpressionParserDiagnostic() = default;
virtual bool IsError() { return false; }
virtual const gd::String &GetMessage() { return noMessage; }
virtual size_t GetStartPosition() { return 0; }

View File

@@ -7,21 +7,21 @@
#define GDCORE_EXPRESSIONPARSER2NODEWORKER_H
namespace gd {
class ExpressionNode;
class SubExpressionNode;
class OperatorNode;
class UnaryOperatorNode;
class NumberNode;
class TextNode;
class VariableNode;
class VariableAccessorNode;
class VariableBracketAccessorNode;
class IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode;
class IdentifierNode;
class FunctionCallOrObjectFunctionNameOrEmptyNode;
class ObjectFunctionNameNode;
class FunctionCallNode;
class EmptyNode;
struct ExpressionNode;
struct SubExpressionNode;
struct OperatorNode;
struct UnaryOperatorNode;
struct NumberNode;
struct TextNode;
struct VariableNode;
struct VariableAccessorNode;
struct VariableBracketAccessorNode;
struct IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode;
struct IdentifierNode;
struct FunctionCallOrObjectFunctionNameOrEmptyNode;
struct ObjectFunctionNameNode;
struct FunctionCallNode;
struct EmptyNode;
} // namespace gd
namespace gd {
@@ -34,21 +34,21 @@ namespace gd {
* \see gd::ExpressionNode
*/
class GD_CORE_API ExpressionParser2NodeWorker {
friend class ExpressionNode;
friend class SubExpressionNode;
friend class OperatorNode;
friend class UnaryOperatorNode;
friend class NumberNode;
friend class TextNode;
friend class VariableNode;
friend class VariableAccessorNode;
friend class VariableBracketAccessorNode;
friend class IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode;
friend class IdentifierNode;
friend class FunctionCallOrObjectFunctionNameOrEmptyNode;
friend class ObjectFunctionNameNode;
friend class FunctionCallNode;
friend class EmptyNode;
friend struct ExpressionNode;
friend struct SubExpressionNode;
friend struct OperatorNode;
friend struct UnaryOperatorNode;
friend struct NumberNode;
friend struct TextNode;
friend struct VariableNode;
friend struct VariableAccessorNode;
friend struct VariableBracketAccessorNode;
friend struct IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode;
friend struct IdentifierNode;
friend struct FunctionCallOrObjectFunctionNameOrEmptyNode;
friend struct ObjectFunctionNameNode;
friend struct FunctionCallNode;
friend struct EmptyNode;
public:
virtual ~ExpressionParser2NodeWorker();

View File

@@ -18,7 +18,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"Florian Rival",
"Open source (MIT License)");
#if defined(GD_IDE_ONLY)
extension
.AddCondition("Toujours",
_("Always"),
@@ -104,7 +103,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Functions"),
"res/function16.png")
.AddParameter("string", "Parameter name");
#endif
}
} // namespace gd

View File

@@ -32,7 +32,6 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsExternalLayoutsExtension(
gd::PlatformExtension& extension);
static void ImplementsFileExtension(gd::PlatformExtension& extension);
static void ImplementsJoystickExtension(gd::PlatformExtension& extension);
static void ImplementsKeyboardExtension(gd::PlatformExtension& extension);
static void ImplementsMathematicalToolsExtension(
gd::PlatformExtension& extension);

View File

@@ -21,7 +21,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/audio");
#if defined(GD_IDE_ONLY)
extension
.AddAction("PlaySoundCanal",
_("Play a sound on a channel"),
@@ -579,7 +578,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/volume.png")
.AddCodeOnlyParameter("currentScene", "");
#endif
}
} // namespace gd

View File

@@ -25,7 +25,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
gd::ObjectMetadata& obj = extension.AddObject<gd::Object>(
"", _("Base object"), _("Base object"), "res/objeticon24.png");
#if defined(GD_IDE_ONLY)
obj.AddCondition("PosX",
_("X position"),
_("Compare the X position of the object."),
@@ -84,9 +83,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/position.png")
.AddParameter("object", _("Object"))
.AddParameter("operator", _("Modification's sign"))
.AddParameter("operator", _("Modification's sign"), "number")
.AddParameter("expression", _("X position"))
.AddParameter("operator", _("Modification's sign"))
.AddParameter("operator", _("Modification's sign"), "number")
.AddParameter("expression", _("Y position"))
.MarkAsSimple();
@@ -99,9 +98,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/position24.png",
"res/actions/position.png")
.AddParameter("object", _("Object"))
.AddParameter("operator", _("Modification's sign"))
.AddParameter("operator", _("Modification's sign"), "number")
.AddParameter("expression", _("X position"))
.AddParameter("operator", _("Modification's sign"))
.AddParameter("operator", _("Modification's sign"), "number")
.AddParameter("expression", _("Y position"))
.MarkAsSimple();
@@ -344,7 +343,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddAction("SetObjectVariableAsBoolean",
_("Boolean value of an object variable"),
_("Change the boolean value of an object variable."),
_("Set the boolean value of the variable _PARAM1_ of object "
_("Set the boolean value of variable _PARAM1_ of "
"_PARAM0_ to _PARAM2_"),
_("Variables"),
"res/actions/var24.png",
@@ -360,7 +359,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Toggles the boolean value of an object variable.") + "\n" +
_("If it was true, it will become false, and if it was false "
"it will become true."),
_("Toggle the boolean value of the variable _PARAM1_ of object "
_("Toggle the boolean value of variable _PARAM1_ of "
"_PARAM0_"),
_("Variables"),
"res/actions/var24.png",
@@ -795,8 +794,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
obj.AddCondition(
"ObjectTimer",
_("Value of a timer"),
_("Test the elapsed time of a timer."),
_("Value of an object timer"),
_("Test the elapsed time of an object timer."),
_("The timer _PARAM1_ of _PARAM0_ is greater than _PARAM2_ seconds"),
_("Timers"),
"res/conditions/timer24.png",
@@ -806,8 +805,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("expression", _("Time in seconds"));
obj.AddCondition("ObjectTimerPaused",
_("Timer paused"),
_("Test if specified timer is paused."),
_("Object timer paused"),
_("Test if specified object timer is paused."),
_("The timer _PARAM1_ of _PARAM0_ is paused"),
_("Timers"),
"res/conditions/timerPaused24.png",
@@ -817,8 +816,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddAction("ResetObjectTimer",
_("Start (or reset) a timer"),
_("Reset the specified timer, if the timer doesn't exist "
_("Start (or reset) an object timer"),
_("Reset the specified object timer, if the timer doesn't exist "
"it's created and started."),
_("Reset the timer _PARAM1_ of _PARAM0_"),
_("Timers"),
@@ -828,8 +827,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("string", _("Timer's name"));
obj.AddAction("PauseObjectTimer",
_("Pause a timer"),
_("Pause a timer."),
_("Pause an object timer"),
_("Pause an object timer."),
_("Pause timer _PARAM1_ of _PARAM0_"),
_("Timers"),
"res/actions/pauseTimer24.png",
@@ -839,8 +838,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddAction("UnPauseObjectTimer",
_("Unpause a timer"),
_("Unpause a timer."),
_("Unpause an object timer"),
_("Unpause an object timer."),
_("Unpause timer _PARAM1_ of _PARAM0_"),
_("Timers"),
"res/actions/unPauseTimer24.png",
@@ -850,8 +849,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.MarkAsAdvanced();
obj.AddAction("RemoveObjectTimer",
_("Delete a timer"),
_("Delete a timer from memory."),
_("Delete an object timer"),
_("Delete an object timer from memory."),
_("Delete timer _PARAM1_ of _PARAM0_ from memory"),
_("Timers"),
"res/actions/timer24.png",
@@ -1021,9 +1020,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("objectvar", _("Variable"));
obj.AddExpression("ObjectTimerElapsedTime",
_("Timer value"),
_("Value of a timer"),
_("Timers"),
_("Object timer value"),
_("Value of an object timer"),
_("Object timers"),
"res/actions/time.png")
.AddParameter("object", _("Object"))
.AddParameter("string", _("Timer's name"));
@@ -1072,6 +1071,74 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
.AddParameter("expression", _("Target X position"))
.AddParameter("expression", _("Target Y position"));
obj.AddAction("EnableEffect",
_("Enable an object effect"),
_("Enable an effect on the object"),
_("Enable effect _PARAM1_ on _PARAM0_: _PARAM2_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("yesorno", _("Enable?"))
.MarkAsSimple();
obj.AddAction("SetEffectDoubleParameter",
_("Effect parameter (number)"),
_("Change the value of a parameter of an effect.") + "\n" +
_("You can find the parameter names (and change the effect "
"names) in the effects window."),
_("Set _PARAM2_ to _PARAM3_ for effect _PARAM1_ of _PARAM0_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("objectEffectParameterName", _("Parameter name"))
.AddParameter("expression", _("New value"))
.MarkAsSimple();
obj.AddAction("SetEffectStringParameter",
_("Effect parameter (string)"),
_("Change the value (string) of a parameter of an effect.") + "\n" +
_("You can find the parameter names (and change the effect "
"names) in the effects window."),
_("Set _PARAM2_ to _PARAM3_ for effect _PARAM1_ of _PARAM0_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("objectEffectParameterName", _("Parameter name"))
.AddParameter("string", _("New value"))
.MarkAsSimple();
obj.AddAction("SetEffectBooleanParameter",
_("Effect parameter (enable or disable)"),
_("Enable or disable a parameter of an effect.") + "\n" +
_("You can find the parameter names (and change the effect "
"names) in the effects window."),
_("Enable _PARAM2_ for effect _PARAM1_ of _PARAM0_: _PARAM3_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("objectEffectParameterName", _("Parameter name"))
.AddParameter("yesorno", _("Enable?"))
.MarkAsSimple();
obj.AddCondition("IsEffectEnabled",
_("Effect is enabled"),
_("Check if the effect on an object is enabled."),
_("Effect _PARAM1_ of _PARAM0_ is enabled"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("objectEffectName", _("Effect name"))
.MarkAsSimple();
extension
.AddAction("Create",
_("Create an object"),
@@ -1373,7 +1440,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
_("Objects"),
"res/actions/layer.png")
.AddParameter("object", _("Object"));
#endif
}
} // namespace gd

View File

@@ -24,7 +24,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras");
#if defined(GD_IDE_ONLY)
extension
.AddExpressionAndConditionAndAction(
"number",
@@ -342,8 +341,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("string", _("Effect"))
.AddParameter("string", _("Parameter name"))
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("expression", _("New value"))
.MarkAsAdvanced();
@@ -361,8 +360,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("string", _("Effect"))
.AddParameter("string", _("Parameter name"))
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("string", _("New value"))
.MarkAsAdvanced();
@@ -380,8 +379,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("string", _("Effect"))
.AddParameter("string", _("Parameter name"))
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("yesorno", _("Enable this parameter"))
.MarkAsAdvanced();
@@ -396,7 +395,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("string", _("Effect"))
.AddParameter("layerEffectName", _("Effect name"))
.MarkAsAdvanced();
extension
@@ -410,7 +409,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("string", _("Effect"))
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("yesorno", _("Enable"), "", true)
.MarkAsAdvanced();
@@ -567,7 +566,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"));
#endif
}
} // namespace gd

View File

@@ -21,7 +21,6 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/common-conversions");
#if defined(GD_IDE_ONLY)
extension
.AddExpression("ToNumber",
@@ -65,7 +64,6 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Conversion"),
"res/conditions/toujours24.png")
.AddParameter("expression", _("Angle, in radians"));
#endif
}
} // namespace gd

View File

@@ -5,7 +5,6 @@
*/
#include "AllBuiltinExtensions.h"
#include "GDCore/Tools/Localization.h"
#if defined(GD_IDE_ONLY)
#include "GDCore/Events/Builtin/CommentEvent.h"
#include "GDCore/Events/Builtin/ForEachChildVariableEvent.h"
#include "GDCore/Events/Builtin/ForEachEvent.h"
@@ -15,7 +14,6 @@
#include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Events/Builtin/WhileEvent.h"
#include "GDCore/Events/Event.h"
#endif
using namespace std;
namespace gd {
@@ -33,7 +31,6 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/advanced-conditions");
#if defined(GD_IDE_ONLY)
extension
.AddCondition("Or",
_("Or"),
@@ -134,7 +131,6 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
"",
"res/foreach.png",
std::make_shared<gd::GroupEvent>());
#endif
}
} // namespace gd

View File

@@ -21,7 +21,6 @@ BuiltinExtensionsImplementer::ImplementsExternalLayoutsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/interface/scene-editor/external-layouts");
#if defined(GD_IDE_ONLY)
extension
.AddAction("CreateObjectsFromExternalLayout",
_("Create objects from an external layout"),
@@ -37,7 +36,6 @@ BuiltinExtensionsImplementer::ImplementsExternalLayoutsExtension(
.AddParameter("expression", _("Y position of the origin"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
#endif
}
} // namespace gd

View File

@@ -22,7 +22,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/storage");
#if defined(GD_IDE_ONLY)
extension
.AddCondition(
"GroupExists",
@@ -194,7 +193,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
"res/actions/launchFile.png")
.AddParameter("string", _("Command"))
.MarkAsAdvanced();
#endif
}
} // namespace gd

View File

@@ -1,77 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "AllBuiltinExtensions.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsJoystickExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation(
"BuiltinJoystick",
_("Joysticks features"),
"Built-in extension that enables the use of joysticks.",
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
#if defined(GD_IDE_ONLY)
extension
.AddCondition("JoystickButtonDown",
_("A button on a joystick is pressed"),
_("Test if a button on a joystick is pressed."),
_("The button _PARAM2_ of joystick _PARAM1_ is pressed"),
_("Joystick"),
"res/conditions/joystick24.png",
"res/conditions/joystick.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
.AddParameter("expression", _("Button"));
extension
.AddCondition("JoystickAxis",
_("Value of an axis of a joystick"),
_("Test the value of an axis of a joystick."),
_("the value of the axis _PARAM2_ of joystick _PARAM1_"),
_("Joystick"),
"res/conditions/joystick24.png",
"res/conditions/joystick.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
.AddParameter("joyaxis", _("Axis"))
.UseStandardRelationalOperatorParameters("number");
extension
.AddAction(
"GetJoystickAxis",
_("Get the value of the axis of a joystick"),
_("Save the value of the axis of the joystick (from -100 to 100)."),
_("Save in _PARAM3_ the value of axis _PARAM2_ of joystick _PARAM1_"),
_("Joystick"),
"res/actions/joystick24.png",
"res/actions/joystick.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
.AddParameter("joyaxis", _("Axis"))
.AddParameter("scenevar", _("Save the result to the scene variable"))
.SetManipulatedType("number");
extension
.AddExpression("GetJoystickAxis",
_("Joystick axis"),
_("Value of an axis of a joystick"),
_("Joystick"),
"res/conditions/joystick.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
.AddParameter("joyaxis", _("Axis"));
#endif
}
} // namespace gd

View File

@@ -23,11 +23,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/keyboard");
#if defined(GD_IDE_ONLY)
extension
.AddCondition("KeyPressed",
_("Key pressed"),
_("Test if a key is pressed"),
_("Check if a key is pressed"),
_("_PARAM1_ key is pressed"),
_("Keyboard"),
"res/conditions/keyboard24.png",
@@ -38,7 +37,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension
.AddCondition("KeyReleased",
_("Key released"),
_("Test if a key was just released"),
_("Check if a key was just released"),
_("_PARAM1_ key is released"),
_("Keyboard"),
"res/conditions/keyboard24.png",
@@ -49,33 +48,33 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension
.AddCondition("KeyFromTextPressed",
_("Key pressed (text expression)"),
_("Test if a key, retrieved from the result of the "
_("Check if a key, retrieved from the result of the "
"expression, is pressed"),
_("_PARAM1_ key is pressed"),
_("Keyboard"),
"res/conditions/keyboard24.png",
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Expression generating the key to test"))
.AddParameter("string", _("Expression generating the key to check"))
.MarkAsAdvanced();
extension
.AddCondition("KeyFromTextReleased",
_("Key released (text expression)"),
_("Test if a key, retrieved from the result of the "
_("Check if a key, retrieved from the result of the "
"expression, was just released"),
_("_PARAM1_ key is released"),
_("Keyboard"),
"res/conditions/keyboard24.png",
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Expression generating the key to test"))
.AddParameter("string", _("Expression generating the key to check"))
.MarkAsAdvanced();
extension
.AddCondition("AnyKeyPressed",
_("Any key pressed"),
_("Test if any key is pressed"),
_("Check if any key is pressed"),
_("Any key is pressed"),
_("Keyboard"),
"res/conditions/keyboard24.png",
@@ -85,7 +84,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension
.AddCondition("AnyKeyReleased",
_("Any key released"),
_("Test if any key is released"),
_("Check if any key is released"),
_("Any key is released"),
_("Keyboard"),
"res/conditions/keyboard24.png",
@@ -100,7 +99,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
_("Keyboard"),
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "");
#endif
}
} // namespace gd

View File

@@ -19,7 +19,6 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"Florian Rival",
"Open source (MIT License)");
#if defined(GD_IDE_ONLY)
extension
.AddExpression("normalize",
@@ -403,7 +402,6 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance"));
#endif
}
} // namespace gd

View File

@@ -25,7 +25,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/mouse-touch");
#if defined(GD_IDE_ONLY)
extension
.AddCondition(
"IsMouseWheelScrollingUp",
@@ -217,6 +216,39 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddParameter("mouse", _("Button to check"))
.MarkAsSimple();
extension
.AddCondition(
"MouseButtonFromTextPressed",
_("Mouse button pressed or touch held (text expression)"),
_("Check if a mouse button, retrieved from the result of the "
"expression, is pressed."),
_("_PARAM1_ mouse button is pressed"),
_("Mouse and touch"),
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Expression generating the button to check"))
.SetParameterLongDescription(
_("Possible values are Left, Right and Middle."))
.MarkAsAdvanced();
extension
.AddCondition(
"MouseButtonFromTextReleased",
_("Mouse button released (text expression)"),
_("Check if a mouse button, retrieved from the result of the "
"expression, was just released."),
_("_PARAM1_ mouse button is released"),
_("Mouse and touch"),
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string",
_("Expression generating the mouse button to check"))
.SetParameterLongDescription(
_("Possible values are Left, Right and Middle."))
.MarkAsAdvanced();
extension
.AddExpressionAndCondition("number",
"TouchX",
@@ -302,8 +334,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Mouse and touch/Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
#endif
}
} // namespace gd

View File

@@ -21,7 +21,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/network");
#if defined(GD_IDE_ONLY)
extension
.AddAction(
"SendRequest",
@@ -196,7 +195,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
"res/conditions/toujours24.png")
.AddParameter("objectPtr", _("The object with the variable"))
.AddParameter("objectvar", _("The object variable to be stringified"));
#endif
}
} // namespace gd

View File

@@ -20,7 +20,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
#if defined(GD_IDE_ONLY)
extension
.AddExpression("Random",
@@ -196,7 +195,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
"res/conditions/egal.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("expression", _("First expression"))
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("relationalOperator", _("Sign of the test"), "number")
.AddParameter("expression", _("Second expression"))
.MarkAsAdvanced();
@@ -210,10 +209,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
"res/conditions/egal.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("string", _("First string expression"))
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("relationalOperator", _("Sign of the test"), "string")
.AddParameter("string", _("Second string expression"))
.MarkAsAdvanced();
#endif
}
} // namespace gd

View File

@@ -75,11 +75,9 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
SetTimeBetweenFrames(
element.GetDoubleAttribute("timeBetweenFrames", 1, "tempsEntre"));
SetLoop(element.GetBoolAttribute("looping", false, "boucle"));
#if defined(GD_IDE_ONLY)
SetMetadata(element.HasAttribute("metadata") || element.HasChild("metadata")
? element.GetStringAttribute("metadata")
: "");
#endif
const gd::SerializerElement& spritesElement =
element.GetChild("sprites", 0, "Sprites");
@@ -135,7 +133,6 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
}
};
#if defined(GD_IDE_ONLY)
void SavePoint(const Point& point, gd::SerializerElement& element) {
element.SetAttribute("name", point.GetName());
element.SetAttribute("x", point.GetX());
@@ -190,6 +187,5 @@ void Direction::SerializeTo(gd::SerializerElement& element) const {
if (!GetMetadata().empty()) element.SetAttribute("metadata", GetMetadata());
SaveSpritesDirection(sprites, element.AddChild("sprites"));
}
#endif
} // namespace gd

View File

@@ -113,7 +113,6 @@ class GD_CORE_API Direction {
*/
void MoveSprite(std::size_t oldIndex, std::size_t newIndex);
#if defined(GD_IDE_ONLY)
/**
* \brief Set the metadata (any string) associated to the Direction.
* \note Can be used by external editors to store extra information.
@@ -124,20 +123,15 @@ class GD_CORE_API Direction {
* \brief Return the (optional) metadata associated to the Direction.
*/
virtual const gd::String& GetMetadata() const { return metadata; }
#endif
void UnserializeFrom(const gd::SerializerElement& element);
#if defined(GD_IDE_ONLY)
void SerializeTo(gd::SerializerElement& element) const;
#endif
private:
bool loop; ///< true if the animation must loop.
double timeBetweenFrame; ///< The time between each sprite of the animation.
std::vector<Sprite> sprites; ///< The sprites of the direction.
#if defined(GD_IDE_ONLY)
gd::String metadata;
#endif
};
} // namespace gd

View File

@@ -7,7 +7,6 @@
#include <SFML/Graphics/Sprite.hpp>
#include <iostream>
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
#include "GDCore/Project/ImageManager.h"
using namespace std;
@@ -16,11 +15,7 @@ namespace gd {
Point Sprite::badPoint("");
Sprite::Sprite()
:
#if !defined(EMSCRIPTEN)
hasItsOwnImage(false),
#endif
automaticCollisionMask(true),
: automaticCollisionMask(true),
origine("origine"),
centre("centre"),
automaticCentre(true) {
@@ -73,36 +68,10 @@ Point& Sprite::GetPoint(const gd::String& name) {
bool Sprite::SetDefaultCenterPoint(bool enabled) {
automaticCentre = enabled;
#if !defined(EMSCRIPTEN)
if (automaticCentre)
centre.SetXY(sfmlSprite.getLocalBounds().width / 2,
sfmlSprite.getLocalBounds().height / 2);
#endif
return true;
}
std::vector<Polygon2d> Sprite::GetCollisionMask() const {
// TODO(perf): Cache to avoid re-creating a mask at every call
#if !defined(EMSCRIPTEN)
if (automaticCollisionMask) {
std::vector<Polygon2d> mask;
Polygon2d rectangle;
rectangle.vertices.push_back(sf::Vector2f(0, 0));
rectangle.vertices.push_back(
sf::Vector2f(sfmlSprite.getLocalBounds().width, 0));
rectangle.vertices.push_back(sf::Vector2f(
sfmlSprite.getLocalBounds().width, sfmlSprite.getLocalBounds().height));
rectangle.vertices.push_back(
sf::Vector2f(0, sfmlSprite.getLocalBounds().height));
mask.push_back(rectangle);
return mask;
}
#endif
return customCollisionMask;
}
@@ -111,25 +80,4 @@ void Sprite::SetCustomCollisionMask(
customCollisionMask = collisionMask;
}
#if !defined(EMSCRIPTEN)
void Sprite::LoadImage(std::shared_ptr<SFMLTextureWrapper> image_) {
sfmlImage = image_;
sfmlSprite.setTexture(sfmlImage->texture, true);
hasItsOwnImage = false;
if (automaticCentre)
centre.SetXY(sfmlSprite.getLocalBounds().width / 2,
sfmlSprite.getLocalBounds().height / 2);
}
void Sprite::MakeSpriteOwnsItsImage() {
if (!hasItsOwnImage || sfmlImage == std::shared_ptr<SFMLTextureWrapper>()) {
sfmlImage = std::make_shared<SFMLTextureWrapper>(
sfmlImage->texture); // Copy the texture.
sfmlSprite.setTexture(sfmlImage->texture);
hasItsOwnImage = true;
}
}
#endif
} // namespace gd

View File

@@ -11,7 +11,6 @@
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
#include "GDCore/String.h"
class SFMLTextureWrapper;
#undef LoadImage // prevent windows.h to be polluting everything
namespace gd {
@@ -19,9 +18,6 @@ namespace gd {
/**
* \brief Represents a sprite to be displayed on the screen.
*
* A sprite contains a SFML sprite to be displayed, some points,
* and can also have its own texture (rather than a texture from ImageManager).
*
* \see Direction
* \see SpriteObject
* \ingroup SpriteObjectExtension
@@ -163,53 +159,7 @@ class GD_CORE_API Sprite {
*/
bool SetDefaultCenterPoint(bool enabled);
#if !defined(EMSCRIPTEN)
/** \name Sprite runtime management
* Functions used by the C++ game engine.
*/
///@{
/**
* \brief Get the SFML sprite associated with the sprite
*/
inline const sf::Sprite& GetSFMLSprite() const { return sfmlSprite; }
/**
* \brief Get the SFML sprite associated with the sprite
*/
inline sf::Sprite& GetSFMLSprite() { return sfmlSprite; }
/**
* \brief Set the SFML texture of the sprite
*/
void LoadImage(std::shared_ptr<SFMLTextureWrapper> image);
/**
* \brief Get SFML texture used by the sprite
*/
std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture() { return sfmlImage; };
/**
* \brief Get SFML texture used by the sprite
*/
const std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture() const {
return sfmlImage;
};
/**
* \brief Make the sprite, if it uses a texture from ImageManager,
* copy this texture and take ownership of it.
*/
void MakeSpriteOwnsItsImage();
///@}
#endif
private:
#if !defined(EMSCRIPTEN)
sf::Sprite sfmlSprite; ///< Displayed SFML sprite
std::shared_ptr<SFMLTextureWrapper>
sfmlImage; ///< Pointer to the image displayed by the sprite.
bool hasItsOwnImage; ///< True if sfmlImage is only owned by this Sprite.
#endif
gd::String image; ///< Name of the image to be loaded in Image Manager.
bool automaticCollisionMask; ///< True to use the custom collision mask.

View File

@@ -29,7 +29,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Animated object which can be used for most elements of a game"),
"CppPlatform/Extensions/spriteicon.png");
#if defined(GD_IDE_ONLY)
obj.AddAction("Opacity",
_("Change sprite opacity"),
_("Change the opacity of a Sprite. 0 is fully transparent, 255 "
@@ -334,39 +333,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.UseStandardRelationalOperatorParameters("number")
.MarkAsAdvanced();
obj.AddAction("CopyImageOnImageOfSprite",
_("Copy an image on the current one of an object"),
_("Copy an image on the current image of an object.\nNote that "
"the source image must be preferably kept loaded in memory."),
_("Copy image _PARAM2_ on the current of _PARAM0_ at "
"_PARAM3_;_PARAM4_"),
_("Effects"),
"res/copy24.png",
"res/copyicon.png")
.AddParameter("object", _("Object"), "Sprite")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Name of the source image"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter(
"yesorno",
_("Should the copy take in account the source transparency\?"));
obj.AddAction(
"CreateMaskFromColorOnActualImage", // Actual is indeed a mistake :
// Current should have been
// chosen.
_("Make a color of the image of an object transparent"),
_("Make a color of the image of an object transparent."),
_("Make color _PARAM1_ of the current image of _PARAM0_ transparent"),
_("Effects"),
"res/actions/opacity24.png",
"res/actions/opacity.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("color", _("Color to make transparent"));
obj.AddAction("ChangeColor",
_("Tint color"),
_("Change the tint of an object. The default color is white."),
@@ -569,7 +535,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("objectList", _("Object 1"), "Sprite")
.AddParameter("objectList", _("Object 2"), "Sprite")
.AddCodeOnlyParameter("conditionInverted", "");
#endif
}
} // namespace gd

View File

@@ -10,7 +10,6 @@
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
#include "GDCore/Project/ImageManager.h"
#include "GDCore/Project/InitialInstance.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
@@ -18,11 +17,9 @@
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/Localization.h"
#if defined(GD_IDE_ONLY)
#include <SFML/Graphics.hpp>
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#endif
namespace gd {
@@ -82,7 +79,6 @@ void SpriteObject::DoUnserializeFrom(gd::Project& project,
}
}
#if defined(GD_IDE_ONLY)
void SpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
element.SetAttribute("updateIfNotVisible", updateIfNotVisible);
@@ -158,7 +154,6 @@ bool SpriteObject::UpdateInitialInstanceProperty(gd::InitialInstance& position,
return true;
}
#endif
const Animation& SpriteObject::GetAnimation(std::size_t nb) const {
if (nb >= animations.size()) return badAnimation;

View File

@@ -16,7 +16,6 @@ class Object;
class Layout;
class Sprite;
class Animation;
class MainFrameWrapper;
class SerializerElement;
class PropertyDescriptor;
} // namespace gd
@@ -45,7 +44,6 @@ class GD_CORE_API SpriteObject : public gd::Object {
return gd::make_unique<SpriteObject>(*this);
}
#if defined(GD_IDE_ONLY)
void ExposeResources(gd::ArbitraryResourceWorker& worker) override;
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const override;
@@ -61,7 +59,6 @@ class GD_CORE_API SpriteObject : public gd::Object {
const gd::String& value,
gd::Project& project,
gd::Layout& scene) override;
#endif
/** \name Animations
* Methods related to animations management
@@ -124,9 +121,7 @@ class GD_CORE_API SpriteObject : public gd::Object {
private:
void DoUnserializeFrom(gd::Project& project,
const gd::SerializerElement& element) override;
#if defined(GD_IDE_ONLY)
void DoSerializeTo(gd::SerializerElement& element) const override;
#endif
mutable std::vector<Animation> animations;
bool updateIfNotVisible; ///< If set to true, ask the game engine to play

View File

@@ -21,7 +21,6 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
#if defined(GD_IDE_ONLY)
extension.AddStrExpression("NewLine",
_("Insert a new line"),
_("Insert a new line"),
@@ -182,7 +181,6 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Position of the last character in the string to be "
"considered in the search"));
#endif
}
} // namespace gd

View File

@@ -22,7 +22,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/timers");
#if defined(GD_IDE_ONLY)
extension
.AddCondition("Timer",
@@ -206,7 +205,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"[\"hour\", \"min\", \"sec\", \"mon\", \"year\", \"wday\", \"mday\", "
"\"yday\", \"timestamp\"]");
#endif
}
} // namespace gd

View File

@@ -23,7 +23,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/variables");
#if defined(GD_IDE_ONLY)
extension
.AddCondition("VarScene",
_("Value of a scene variable"),
@@ -458,7 +457,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Variables"),
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"));
#endif
}
} // namespace gd

View File

@@ -22,7 +22,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/window");
#if defined(GD_IDE_ONLY)
extension
.AddAction(
"SetFullScreen",
@@ -215,7 +214,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
_("Screen"),
"res/window.png")
.AddCodeOnlyParameter("currentScene", "");
#endif
}
} // namespace gd

View File

@@ -393,4 +393,14 @@ const gd::String& BehaviorMetadata::GetName() const {
return instance->GetTypeName();
}
gd::Behavior& BehaviorMetadata::Get() const {
if (!instance)
gd::LogFatalError(
"Trying to get a behavior from a BehaviorMetadata that has no "
"behavior. This will crash - please double check that the "
"BehaviorMetadata is valid.");
return *instance;
}
} // namespace gd

View File

@@ -240,7 +240,7 @@ class GD_CORE_API BehaviorMetadata {
/**
* \brief Return the associated gd::Behavior, handling behavior contents.
*/
gd::Behavior& Get() const { return *instance; }
gd::Behavior& Get() const;
/**
* \brief Return the associated gd::BehaviorsSharedData, handling behavior

View File

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

View File

@@ -8,6 +8,7 @@
#include <functional>
#include <map>
#include <memory>
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/String.h"
@@ -49,7 +50,8 @@ class GD_CORE_API EffectMetadata {
};
/**
* Set the help path of the effect, relative to the GDevelop documentation root.
* Set the help path of the effect, relative to the GDevelop documentation
* root.
*/
EffectMetadata& SetHelpPath(const gd::String& path) {
helpPath = path;
@@ -66,6 +68,11 @@ 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.
*/
@@ -81,12 +88,14 @@ class GD_CORE_API EffectMetadata {
}
/**
* \brief Get the help path of the effect, relative to the GDevelop documentation root.
* \brief Get the help path of the effect, relative to the GDevelop
* documentation root.
*/
const gd::String& GetHelpPath() const { return helpPath; }
/**
* \brief Get the type of the effect (its internal name, like "BlackAndWhite").
* \brief Get the type of the effect (its internal name, like
* "BlackAndWhite").
*/
const gd::String& GetType() const { return type; }
@@ -107,6 +116,11 @@ class GD_CORE_API EffectMetadata {
return includeFiles;
}
/**
* \brief Check if the effect is marked as not working as an object effect.
*/
bool IsMarkedAsNotWorkingForObjects() const { return isMarkedAsNotWorkingForObjects; };
private:
gd::String extensionNamespace;
gd::String type;
@@ -114,6 +128,7 @@ class GD_CORE_API EffectMetadata {
gd::String fullname;
gd::String description;
std::vector<gd::String> includeFiles;
bool isMarkedAsNotWorkingForObjects;
std::map<gd::String, gd::PropertyDescriptor> properties;
};

View File

@@ -34,7 +34,7 @@ ExpressionMetadata& ExpressionMetadata::SetHidden() {
gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
const gd::String& type,
const gd::String& description,
const gd::String& optionalObjectType,
const gd::String& supplementaryInformation,
bool parameterIsOptional) {
gd::ParameterMetadata info;
info.type = type;
@@ -46,15 +46,15 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
// parameter is an object/behavior type...
(gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
? (optionalObjectType.empty()
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
optionalObjectType //... so prefix it with the extension
supplementaryInformation //... so prefix it with the extension
// namespace.
)
: optionalObjectType; // Otherwise don't change anything
: supplementaryInformation; // Otherwise don't change anything
// TODO: Assert against optionalObjectType === "emsc" (when running with
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
parameters.push_back(info);

View File

@@ -190,7 +190,7 @@ class GD_CORE_API ExpressionMetadata {
gd::ExpressionMetadata& AddParameter(
const gd::String& type,
const gd::String& description,
const gd::String& optionalObjectType = "",
const gd::String& supplementaryInformation = "",
bool parameterIsOptional = false);
/**

View File

@@ -51,7 +51,7 @@ InstructionMetadata::InstructionMetadata(const gd::String& extensionNamespace_,
InstructionMetadata& InstructionMetadata::AddParameter(
const gd::String& type,
const gd::String& description,
const gd::String& optionalObjectType,
const gd::String& supplementaryInformation,
bool parameterIsOptional) {
ParameterMetadata info;
info.type = type;
@@ -63,15 +63,15 @@ InstructionMetadata& InstructionMetadata::AddParameter(
// parameter is an object/behavior type...
(gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
? (optionalObjectType.empty()
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
optionalObjectType //... so prefix it with the extension
supplementaryInformation //... so prefix it with the extension
// namespace.
)
: optionalObjectType; // Otherwise don't change anything
: supplementaryInformation; // Otherwise don't change anything
// TODO: Assert against optionalObjectType === "emsc" (when running with
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
parameters.push_back(info);
@@ -93,7 +93,7 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
const gd::String& type) {
SetManipulatedType(type);
AddParameter("operator", _("Modification's sign"));
AddParameter("operator", _("Modification's sign"), type);
AddParameter(type == "number" ? "expression" : type, _("Value"));
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;
@@ -129,7 +129,7 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
const gd::String& type) {
SetManipulatedType(type);
AddParameter("relationalOperator", _("Sign of the test"));
AddParameter("relationalOperator", _("Sign of the test"), type);
AddParameter(type == "number" ? "expression" : type, _("Value to compare"));
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;

View File

@@ -6,7 +6,6 @@
#ifndef INSTRUCTIONMETADATA_H
#define INSTRUCTIONMETADATA_H
#if defined(GD_IDE_ONLY)
#include <functional>
#include <map>
#include <memory>
@@ -137,8 +136,11 @@ class GD_CORE_API InstructionMetadata {
* will also determine the type of the argument used when calling the function
* in the generated code.
* \param description Description for parameter
* \param optionalObjectType If type is "object", this parameter will describe
* which objects are allowed. If it is empty, all objects are allowed.
* \param supplementaryInformation Additional information that can be used for
* rendering or logic. For example:
* - If type is "object", this argument will describe which objects are allowed.
* If this argument is empty, all objects are allowed.
* - If type is "operator", this argument will be used to display only pertinent operators.
* \param parameterIsOptional true if the parameter must be optional, false
* otherwise.
*
@@ -146,7 +148,7 @@ class GD_CORE_API InstructionMetadata {
*/
InstructionMetadata &AddParameter(const gd::String &type,
const gd::String &label,
const gd::String &optionalObjectType = "",
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false);
/**
@@ -234,14 +236,14 @@ class GD_CORE_API InstructionMetadata {
/**
* \brief Check if the instruction is an object instruction.
*/
bool IsObjectInstruction() {
bool IsObjectInstruction() const {
return isObjectInstruction;
}
/**
* \brief Check if the instruction is a behavior instruction.
*/
bool IsBehaviorInstruction() {
bool IsBehaviorInstruction() const {
return isBehaviorInstruction;
}
@@ -319,7 +321,7 @@ class GD_CORE_API InstructionMetadata {
* "CppPlatform/Extensions/text.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"))
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString").SetIncludeFile("MyExtension/TextObject.h");
*
@@ -452,5 +454,4 @@ class GD_CORE_API InstructionMetadata {
} // namespace gd
#endif
#endif // INSTRUCTIONMETADATA_H

View File

@@ -245,6 +245,10 @@ class GD_CORE_API MetadataProvider {
return &metadata == &badExpressionMetadata;
}
static bool IsBadInstructionMetadata(const gd::InstructionMetadata& metadata) {
return &metadata == &badInstructionMetadata;
}
static bool IsBadBehaviorMetadata(const gd::BehaviorMetadata& metadata) {
return &metadata == &badBehaviorMetadata;
}

View File

@@ -38,19 +38,17 @@ class GD_CORE_API MultipleInstructionMetadata {
MultipleInstructionMetadata &AddParameter(
const gd::String &type,
const gd::String &label,
const gd::String &optionalObjectType = "",
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) {
#if defined(GD_IDE_ONLY)
if (expression)
expression->AddParameter(
type, label, optionalObjectType, parameterIsOptional);
type, label, supplementaryInformation, parameterIsOptional);
if (condition)
condition->AddParameter(
type, label, optionalObjectType, parameterIsOptional);
type, label, supplementaryInformation, parameterIsOptional);
if (action)
action->AddParameter(
type, label, optionalObjectType, parameterIsOptional);
#endif
type, label, supplementaryInformation, parameterIsOptional);
return *this;
}
@@ -59,13 +57,11 @@ class GD_CORE_API MultipleInstructionMetadata {
*/
MultipleInstructionMetadata &AddCodeOnlyParameter(
const gd::String &type, const gd::String &supplementaryInformation) {
#if defined(GD_IDE_ONLY)
if (expression)
expression->AddCodeOnlyParameter(type, supplementaryInformation);
if (condition)
condition->AddCodeOnlyParameter(type, supplementaryInformation);
if (action) action->AddCodeOnlyParameter(type, supplementaryInformation);
#endif
return *this;
}
@@ -73,11 +69,9 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::SetDefaultValue
*/
MultipleInstructionMetadata &SetDefaultValue(const gd::String &defaultValue) {
#if defined(GD_IDE_ONLY)
if (expression) expression->SetDefaultValue(defaultValue);
if (condition) condition->SetDefaultValue(defaultValue);
if (action) action->SetDefaultValue(defaultValue);
#endif
return *this;
};
@@ -86,11 +80,9 @@ class GD_CORE_API MultipleInstructionMetadata {
*/
MultipleInstructionMetadata &SetParameterLongDescription(
const gd::String &longDescription) {
#if defined(GD_IDE_ONLY)
if (expression) expression->SetParameterLongDescription(longDescription);
if (condition) condition->SetParameterLongDescription(longDescription);
if (action) action->SetParameterLongDescription(longDescription);
#endif
return *this;
};
@@ -98,11 +90,9 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::SetHidden
*/
MultipleInstructionMetadata &SetHidden() {
#if defined(GD_IDE_ONLY)
if (expression) expression->SetHidden();
if (condition) condition->SetHidden();
if (action) action->SetHidden();
#endif
return *this;
};
@@ -111,50 +101,40 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::UseStandardRelationalOperatorParameters
*/
MultipleInstructionMetadata &UseStandardParameters(const gd::String &type) {
#if defined(GD_IDE_ONLY)
if (condition) condition->UseStandardRelationalOperatorParameters(type);
if (action) action->UseStandardOperatorParameters(type);
#endif
return *this;
}
MultipleInstructionMetadata &SetFunctionName(const gd::String &functionName) {
#if defined(GD_IDE_ONLY)
if (expression) expression->SetFunctionName(functionName);
if (condition) condition->SetFunctionName(functionName);
if (action) action->GetCodeExtraInformation().SetFunctionName(functionName);
#endif
return *this;
}
MultipleInstructionMetadata &SetGetter(const gd::String &getter) {
#if defined(GD_IDE_ONLY)
if (expression) expression->SetFunctionName(getter);
if (condition) condition->SetFunctionName(getter);
if (action) action->GetCodeExtraInformation().SetGetter(getter);
#endif
return *this;
}
MultipleInstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
#if defined(GD_IDE_ONLY)
if (expression)
expression->GetCodeExtraInformation().SetIncludeFile(includeFile);
if (condition)
condition->GetCodeExtraInformation().SetIncludeFile(includeFile);
if (action) action->GetCodeExtraInformation().SetIncludeFile(includeFile);
#endif
return *this;
}
MultipleInstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
#if defined(GD_IDE_ONLY)
if (expression)
expression->GetCodeExtraInformation().AddIncludeFile(includeFile);
if (condition)
condition->GetCodeExtraInformation().AddIncludeFile(includeFile);
if (action) action->GetCodeExtraInformation().AddIncludeFile(includeFile);
#endif
return *this;
}
@@ -162,10 +142,8 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::MarkAsSimple
*/
MultipleInstructionMetadata &MarkAsSimple() {
#if defined(GD_IDE_ONLY)
if (condition) condition->MarkAsSimple();
if (action) action->MarkAsSimple();
#endif
return *this;
}
@@ -173,10 +151,8 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::MarkAsAdvanced
*/
MultipleInstructionMetadata &MarkAsAdvanced() {
#if defined(GD_IDE_ONLY)
if (condition) condition->MarkAsAdvanced();
if (action) action->MarkAsAdvanced();
#endif
return *this;
}
@@ -184,10 +160,8 @@ class GD_CORE_API MultipleInstructionMetadata {
* \see gd::InstructionMetadata::MarkAsComplex
*/
MultipleInstructionMetadata &MarkAsComplex() {
#if defined(GD_IDE_ONLY)
if (condition) condition->MarkAsComplex();
if (action) action->MarkAsComplex();
#endif
return *this;
}

View File

@@ -302,6 +302,38 @@ ObjectMetadata::AddExpressionAndConditionAndAction(
expression, condition, action);
}
gd::InstructionMetadata& ObjectMetadata::AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName) {
gd::String newNameWithNamespace = extensionNamespace + newActionName;
gd::String copiedNameWithNamespace = extensionNamespace + copiedActionName;
auto copiedAction = actionsInfos.find(copiedNameWithNamespace);
if (copiedAction == actionsInfos.end()) {
gd::LogWarning("Could not find an action with name " +
copiedNameWithNamespace + " to copy.");
} else {
actionsInfos[newNameWithNamespace] = copiedAction->second;
}
return actionsInfos[newNameWithNamespace];
}
gd::InstructionMetadata& ObjectMetadata::AddDuplicatedCondition(
const gd::String& newConditionName, const gd::String& copiedConditionName) {
gd::String newNameWithNamespace = extensionNamespace + newConditionName;
gd::String copiedNameWithNamespace = extensionNamespace + copiedConditionName;
auto copiedCondition = conditionsInfos.find(copiedNameWithNamespace);
if (copiedCondition == conditionsInfos.end()) {
gd::LogWarning("Could not find a condition with name " +
copiedNameWithNamespace + " to copy.");
} else {
conditionsInfos[newNameWithNamespace] = copiedCondition->second;
}
return conditionsInfos[newNameWithNamespace];
}
ObjectMetadata& ObjectMetadata::SetFullName(const gd::String& fullname_) {
#if defined(GD_IDE_ONLY)
fullname = fullname_;

View File

@@ -153,6 +153,25 @@ class GD_CORE_API ObjectMetadata {
const gd::String& group,
const gd::String& icon);
/**
* \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.
*/
gd::InstructionMetadata& AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName);
/**
* \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.
*/
gd::InstructionMetadata& AddDuplicatedCondition(
const gd::String& newConditionName,
const gd::String& copiedConditionName);
/**
* \brief Set the name shown to the user.
*/

View File

@@ -189,6 +189,10 @@ class GD_CORE_API ParameterMetadata {
parameterType == "joyaxis" ||
parameterType == "stringWithSelector" ||
parameterType == "sceneName" ||
parameterType == "layerEffectName" ||
parameterType == "layerEffectParameterName" ||
parameterType == "objectEffectName" ||
parameterType == "objectEffectParameterName" ||
parameterType == "objectPointName" ||
parameterType == "objectAnimationName";
} else if (type == "variable") {

View File

@@ -4,6 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#include "ParameterMetadataTools.h"
#include "GDCore/Events/Expression.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectsContainer.h"
@@ -60,6 +61,24 @@ void ParameterMetadataTools::IterateOverParameters(
std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
const gd::String& lastObjectName)> fn) {
IterateOverParametersWithIndex(
parameters,
parametersMetadata,
[&fn](const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
fn(parameterMetadata, parameterValue, lastObjectName);
});
}
void ParameterMetadataTools::IterateOverParametersWithIndex(
const std::vector<gd::Expression>& parameters,
const std::vector<gd::ParameterMetadata>& parametersMetadata,
std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName)> fn) {
gd::String lastObjectName = "";
for (std::size_t pNb = 0; pNb < parametersMetadata.size(); ++pNb) {
const gd::ParameterMetadata& parameterMetadata = parametersMetadata[pNb];
@@ -70,7 +89,7 @@ void ParameterMetadataTools::IterateOverParameters(
? parameterMetadata.GetDefaultValue()
: parameterValue;
fn(parameterMetadata, parameterValueOrDefault, lastObjectName);
fn(parameterMetadata, parameterValueOrDefault, pNb, lastObjectName);
// Memorize the last object name. By convention, parameters that require
// an object (mainly, "objectvar" and "behavior") should be placed after

View File

@@ -35,6 +35,19 @@ class GD_CORE_API ParameterMetadataTools {
const gd::String& parameterValue,
const gd::String& lastObjectName)> fn);
/**
* Iterate over a list of parameters and their values.
* Callback function is called with the parameter metadata, its value
* and if applicable the name of the object it's linked to.
*/
static void IterateOverParametersWithIndex(
const std::vector<gd::Expression>& parameters,
const std::vector<gd::ParameterMetadata>& parametersMetadata,
std::function<void(const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName)> fn);
/**
* Given a parameter, return, if applicable, the index of the object parameter
* it's linked to.

View File

@@ -529,24 +529,6 @@ class GD_CORE_API PlatformExtension {
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressionsForBehavior(
gd::String autoType);
/**
* Called to inventory resources used by conditions
* (and possibly do work on them, like renaming, etc...)
*
* \see gd::PlatformExtension::ExposeActionsResources
*/
virtual void ExposeConditionsResources(Instruction& condition,
gd::ArbitraryResourceWorker& worker){};
/**
* Called to inventory resources used by actions
* (and possibly do work on them, like renaming, etc...)
*
* \see ArbitraryResourceWorker
*/
virtual void ExposeActionsResources(Instruction& action,
gd::ArbitraryResourceWorker& worker){};
/**
* \brief Get all the properties of the extension. Properties
* are shown in the game properties in the editor, and are exported in the

View File

@@ -0,0 +1,164 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "GDCore/IDE/Events/EventsBehaviorRenamer.h"
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/IDE/Events/ExpressionValidator.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace gd {
/**
* \brief Go through the nodes and rename any reference to an object behavior.
*
* \see gd::ExpressionParser2
*/
class GD_CORE_API ExpressionBehaviorRenamer
: public ExpressionParser2NodeWorker {
public:
ExpressionBehaviorRenamer(const gd::ObjectsContainer& globalObjectsContainer_,
const gd::ObjectsContainer& objectsContainer_,
const gd::String& objectName_,
const gd::String& oldBehaviorName_,
const gd::String& newBehaviorName_)
: hasDoneRenaming(false),
globalObjectsContainer(globalObjectsContainer_),
objectsContainer(objectsContainer_),
objectName(objectName_),
oldBehaviorName(oldBehaviorName_),
newBehaviorName(newBehaviorName_){};
virtual ~ExpressionBehaviorRenamer(){};
bool HasDoneRenaming() const { return hasDoneRenaming; }
protected:
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
node.expression->Visit(*this);
}
void OnVisitOperatorNode(OperatorNode& node) override {
node.leftHandSide->Visit(*this);
node.rightHandSide->Visit(*this);
}
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
node.factor->Visit(*this);
}
void OnVisitNumberNode(NumberNode& node) override {}
void OnVisitTextNode(TextNode& node) override {}
void OnVisitVariableNode(VariableNode& node) override {
if (node.child) node.child->Visit(*this);
}
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
if (node.child) node.child->Visit(*this);
}
void OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode& node) override {
node.expression->Visit(*this);
if (node.child) node.child->Visit(*this);
}
void OnVisitIdentifierNode(IdentifierNode& node) override {}
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
if (!node.behaviorFunctionName.empty()) {
// Behavior function name
if (node.objectName == objectName && node.objectFunctionOrBehaviorName == oldBehaviorName) {
node.objectFunctionOrBehaviorName = newBehaviorName;
hasDoneRenaming = true;
}
}
}
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
if (!node.behaviorName.empty()) {
// Behavior function call
if (node.objectName == objectName && node.behaviorName == oldBehaviorName) {
node.behaviorName = newBehaviorName;
hasDoneRenaming = true;
}
}
for (auto& parameter : node.parameters) {
parameter->Visit(*this);
}
}
void OnVisitEmptyNode(EmptyNode& node) override {}
private:
bool hasDoneRenaming;
const gd::ObjectsContainer& globalObjectsContainer;
const gd::ObjectsContainer& objectsContainer;
const gd::String& objectName; // The object name for which the behavior
// must be replaced.
const gd::String& oldBehaviorName;
const gd::String& newBehaviorName;
};
bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
bool isCondition) {
const auto& metadata = isCondition
? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(),
metadata.GetParameters(),
[&](const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
const gd::String& type = parameterMetadata.type;
if (gd::ParameterMetadata::IsBehavior(type)) {
if (lastObjectName == objectName) {
if (parameterValue == oldBehaviorName) {
instruction.SetParameter(parameterIndex,
gd::Expression(newBehaviorName));
}
}
} else {
gd::ExpressionParser2 parser(
platform, GetGlobalObjectsContainer(), GetObjectsContainer());
auto node =
gd::ParameterMetadata::IsExpression("number", type)
? parser.ParseExpression("number", parameterValue)
: (gd::ParameterMetadata::IsExpression("string", type)
? parser.ParseExpression("string", parameterValue)
: std::unique_ptr<gd::ExpressionNode>());
if (node) {
ExpressionBehaviorRenamer renamer(GetGlobalObjectsContainer(),
GetObjectsContainer(),
objectName,
oldBehaviorName,
newBehaviorName);
node->Visit(renamer);
if (renamer.HasDoneRenaming()) {
instruction.SetParameter(
parameterIndex,
ExpressionParser2NodePrinter::PrintNode(*node));
}
}
}
});
return false;
}
EventsBehaviorRenamer::~EventsBehaviorRenamer() {}
} // namespace gd

View File

@@ -0,0 +1,52 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef EventsBehaviorRenamer_H
#define EventsBehaviorRenamer_H
#include <map>
#include <memory>
#include <vector>
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/String.h"
namespace gd {
class BaseEvent;
class Platform;
class EventsList;
} // namespace gd
namespace gd {
/**
* \brief Replace in expressions and in parameters of actions or conditions, references
* to the name of a behavior of an object by another name.
*
* \ingroup IDE
*/
class GD_CORE_API EventsBehaviorRenamer : public ArbitraryEventsWorkerWithContext {
public:
EventsBehaviorRenamer(const gd::Platform &platform_,
const gd::String& objectName_,
const gd::String& oldBehaviorName_,
const gd::String& newBehaviorName_) :
platform(platform_),
objectName(objectName_),
oldBehaviorName(oldBehaviorName_),
newBehaviorName(newBehaviorName_)
{};
virtual ~EventsBehaviorRenamer();
private:
bool DoVisitInstruction(gd::Instruction &instruction,
bool isCondition) override;
const gd::Platform &platform;
gd::String objectName;
gd::String oldBehaviorName;
gd::String newBehaviorName;
};
} // namespace gd
#endif // EventsBehaviorRenamer_H

View File

@@ -5,23 +5,28 @@
*/
#include "GDCore/IDE/Events/EventsRefactorer.h"
#include <memory>
#include "GDCore/CommonTools.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
#include "GDCore/IDE/Events/ExpressionValidator.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/IDE/Events/ExpressionValidator.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/IDE/Events/InstructionSentenceFormatter.h"
using namespace std;
namespace gd {
const gd::String EventsRefactorer::searchIgnoredCharacters = ";:,#()";
/**
* \brief Go through the nodes and change the given object name to a new one.
*
@@ -31,10 +36,14 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
public:
ExpressionObjectRenamer(const gd::String& objectName_,
const gd::String& objectNewName_)
: hasDoneRenaming(false), objectName(objectName_), objectNewName(objectNewName_){};
: hasDoneRenaming(false),
objectName(objectName_),
objectNewName(objectNewName_){};
virtual ~ExpressionObjectRenamer(){};
static bool Rename(gd::ExpressionNode & node, const gd::String& objectName, const gd::String& objectNewName) {
static bool Rename(gd::ExpressionNode& node,
const gd::String& objectName,
const gd::String& objectNewName) {
if (ExpressionValidator::HasNoErrors(node)) {
ExpressionObjectRenamer renamer(objectName, objectNewName);
node.Visit(renamer);
@@ -72,7 +81,8 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
if (node.child) node.child->Visit(*this);
}
void OnVisitIdentifierNode(IdentifierNode& node) override {
if (gd::ParameterMetadata::IsObject(node.type) && node.identifierName == objectName) {
if (gd::ParameterMetadata::IsObject(node.type) &&
node.identifierName == objectName) {
hasDoneRenaming = true;
node.identifierName = objectNewName;
}
@@ -109,10 +119,11 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
public:
ExpressionObjectFinder(const gd::String& objectName_)
: hasObject(false), objectName(objectName_) {};
: hasObject(false), objectName(objectName_){};
virtual ~ExpressionObjectFinder(){};
static bool CheckIfHasObject(gd::ExpressionNode & node, const gd::String & objectName) {
static bool CheckIfHasObject(gd::ExpressionNode& node,
const gd::String& objectName) {
if (ExpressionValidator::HasNoErrors(node)) {
ExpressionObjectFinder finder(objectName);
node.Visit(finder);
@@ -150,7 +161,8 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
if (node.child) node.child->Visit(*this);
}
void OnVisitIdentifierNode(IdentifierNode& node) override {
if (gd::ParameterMetadata::IsObject(node.type) && node.identifierName == objectName) {
if (gd::ParameterMetadata::IsObject(node.type) &&
node.identifierName == objectName) {
hasObject = true;
}
}
@@ -183,7 +195,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
bool somethingModified = false;
for (std::size_t aId = 0; aId < actions.size(); ++aId) {
gd::InstructionMetadata instrInfos =
const gd::InstructionMetadata& instrInfos =
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Replace object's name in parameters
@@ -194,20 +206,24 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("number", actions[aId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"number", actions[aId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
actions[aId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
actions[aId].SetParameter(
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
}
}
// Replace object's name in text expressions
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("string", actions[aId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"string", actions[aId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
actions[aId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
actions[aId].SetParameter(
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
}
}
}
@@ -236,8 +252,9 @@ bool EventsRefactorer::RenameObjectInConditions(
bool somethingModified = false;
for (std::size_t cId = 0; cId < conditions.size(); ++cId) {
gd::InstructionMetadata instrInfos = MetadataProvider::GetConditionMetadata(
platform, conditions[cId].GetType());
const gd::InstructionMetadata& instrInfos =
MetadataProvider::GetConditionMetadata(platform,
conditions[cId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Replace object's name in parameters
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
@@ -247,20 +264,24 @@ bool EventsRefactorer::RenameObjectInConditions(
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("number", conditions[cId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"number", conditions[cId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
conditions[cId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
conditions[cId].SetParameter(
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
}
}
// Replace object's name in text expressions
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("string", conditions[cId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"string", conditions[cId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
conditions[cId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
conditions[cId].SetParameter(
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
}
}
}
@@ -293,8 +314,8 @@ bool EventsRefactorer::RenameObjectInEventParameters(
expression.GetPlainString() == oldName)
expression = gd::Expression(newName);
// Replace object's name in expressions
else if (ParameterMetadata::IsExpression(
"number", parameterMetadata.GetType())) {
else if (ParameterMetadata::IsExpression("number",
parameterMetadata.GetType())) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("number", expression.GetPlainString());
@@ -303,8 +324,8 @@ bool EventsRefactorer::RenameObjectInEventParameters(
}
}
// Replace object's name in text expressions
else if (ParameterMetadata::IsExpression(
"string", parameterMetadata.GetType())) {
else if (ParameterMetadata::IsExpression("string",
parameterMetadata.GetType())) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("string", expression.GetPlainString());
@@ -337,13 +358,19 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
platform, project, layout, *actionsVectors[j], oldName, newName);
}
vector<pair<gd::Expression*, gd::ParameterMetadata>> expressionsWithMetadata =
events[i].GetAllExpressionsWithMetadata();
vector<pair<gd::Expression*, gd::ParameterMetadata>>
expressionsWithMetadata = events[i].GetAllExpressionsWithMetadata();
for (std::size_t j = 0; j < expressionsWithMetadata.size(); ++j) {
gd::Expression* expression = expressionsWithMetadata[j].first;
gd::ParameterMetadata parameterMetadata = expressionsWithMetadata[j].second;
bool somethingModified = RenameObjectInEventParameters(
platform, project, layout, *expression, parameterMetadata, oldName, newName);
gd::ParameterMetadata parameterMetadata =
expressionsWithMetadata[j].second;
bool somethingModified = RenameObjectInEventParameters(platform,
project,
layout,
*expression,
parameterMetadata,
oldName,
newName);
}
if (events[i].CanHaveSubEvents())
@@ -366,7 +393,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
for (std::size_t aId = 0; aId < actions.size(); ++aId) {
bool deleteMe = false;
gd::InstructionMetadata instrInfos =
const gd::InstructionMetadata& instrInfos =
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Find object's name in parameters
@@ -379,7 +406,8 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("number", actions[aId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"number", actions[aId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
deleteMe = true;
@@ -390,7 +418,8 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("string", actions[aId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"string", actions[aId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
deleteMe = true;
@@ -427,8 +456,9 @@ bool EventsRefactorer::RemoveObjectInConditions(
for (std::size_t cId = 0; cId < conditions.size(); ++cId) {
bool deleteMe = false;
gd::InstructionMetadata instrInfos = MetadataProvider::GetConditionMetadata(
platform, conditions[cId].GetType());
const gd::InstructionMetadata& instrInfos =
MetadataProvider::GetConditionMetadata(platform,
conditions[cId].GetType());
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
// Find object's name in parameters
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
@@ -440,7 +470,8 @@ bool EventsRefactorer::RemoveObjectInConditions(
else if (ParameterMetadata::IsExpression(
"number", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("number", conditions[cId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"number", conditions[cId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
deleteMe = true;
@@ -451,7 +482,8 @@ bool EventsRefactorer::RemoveObjectInConditions(
else if (ParameterMetadata::IsExpression(
"string", instrInfos.parameters[pNb].type)) {
gd::ExpressionParser2 parser(platform, project, layout);
auto node = parser.ParseExpression("string", conditions[cId].GetParameter(pNb).GetPlainString());
auto node = parser.ParseExpression(
"string", conditions[cId].GetParameter(pNb).GetPlainString());
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
deleteMe = true;
@@ -646,16 +678,27 @@ bool EventsRefactorer::ReplaceStringInConditions(
}
vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
const gd::Platform& platform,
gd::EventsList& events,
gd::String search,
bool matchCase,
bool inConditions,
bool inActions,
bool inEventStrings) {
bool inEventStrings,
bool inEventSentences) {
vector<EventsSearchResult> results;
const gd::String& ignored_characters = EventsRefactorer::searchIgnoredCharacters;
search.replace_if(search.begin(),
search.end(),
[ignored_characters](const char &c) {
return ignored_characters.find(c) != gd::String::npos;
},
"");
search = search.LeftTrim().RightTrim();
search.RemoveConsecutiveOccurrences(search.begin(), search.end(), ' ');
for (std::size_t i = 0; i < events.size(); ++i) {
bool eventAddedInResults = false;
@@ -665,7 +708,7 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
for (std::size_t j = 0; j < conditionsVectors.size(); ++j) {
if (!eventAddedInResults &&
SearchStringInConditions(
project, layout, *conditionsVectors[j], search, matchCase)) {
platform, *conditionsVectors[j], search, matchCase, inEventSentences)) {
results.push_back(EventsSearchResult(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
@@ -680,7 +723,7 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
for (std::size_t j = 0; j < actionsVectors.size(); ++j) {
if (!eventAddedInResults &&
SearchStringInActions(
project, layout, *actionsVectors[j], search, matchCase)) {
platform, *actionsVectors[j], search, matchCase, inEventSentences)) {
results.push_back(EventsSearchResult(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
@@ -691,7 +734,7 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
if (inEventStrings) {
if (!eventAddedInResults &&
SearchStringInEvent(project, layout, events[i], search, matchCase)) {
SearchStringInEvent(events[i], search, matchCase)) {
results.push_back(EventsSearchResult(
std::weak_ptr<gd::BaseEvent>(events.GetEventSmartPtr(i)),
&events,
@@ -701,14 +744,14 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
if (events[i].CanHaveSubEvents()) {
vector<EventsSearchResult> subResults =
SearchInEvents(project,
layout,
SearchInEvents(platform,
events[i].GetSubEvents(),
search,
matchCase,
inConditions,
inActions,
inEventStrings);
inEventStrings,
inEventSentences);
std::copy(
subResults.begin(), subResults.end(), std::back_inserter(results));
}
@@ -717,11 +760,12 @@ vector<EventsSearchResult> EventsRefactorer::SearchInEvents(
return results;
}
bool EventsRefactorer::SearchStringInActions(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
gd::InstructionsList& actions,
gd::String search,
bool matchCase) {
bool EventsRefactorer::SearchStringInActions(
const gd::Platform& platform,
gd::InstructionsList& actions,
gd::String search,
bool matchCase,
bool inSentences) {
for (std::size_t aId = 0; aId < actions.size(); ++aId) {
for (std::size_t pNb = 0; pNb < actions[aId].GetParameters().size();
++pNb) {
@@ -736,24 +780,60 @@ bool EventsRefactorer::SearchStringInActions(gd::ObjectsContainer& project,
if (foundPosition != gd::String::npos) return true;
}
if (inSentences && SearchStringInFormattedText(
platform, actions[aId], search, matchCase, false))
return true;
if (!actions[aId].GetSubInstructions().empty() &&
SearchStringInActions(project,
layout,
SearchStringInActions(platform,
actions[aId].GetSubInstructions(),
search,
matchCase))
matchCase,
inSentences))
return true;
}
return false;
}
bool EventsRefactorer::SearchStringInFormattedText(
const gd::Platform& platform,
gd::Instruction& instruction,
gd::String search,
bool matchCase,
bool isCondition) {
const auto& metadata = isCondition
? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
gd::String completeSentence = gd::InstructionSentenceFormatter::Get()->GetFullText(instruction, metadata);
const gd::String& ignored_characters = EventsRefactorer::searchIgnoredCharacters;
completeSentence.replace_if(completeSentence.begin(),
completeSentence.end(),
[ignored_characters](const char &c) {
return ignored_characters.find(c) != gd::String::npos;
},
"");
completeSentence.RemoveConsecutiveOccurrences(
completeSentence.begin(), completeSentence.end(), ' ');
size_t foundPosition = matchCase
? completeSentence.find(search)
: completeSentence.FindCaseInsensitive(search);
return foundPosition != gd::String::npos;
}
bool EventsRefactorer::SearchStringInConditions(
gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
const gd::Platform& platform,
gd::InstructionsList& conditions,
gd::String search,
bool matchCase) {
bool matchCase,
bool inSentences) {
for (std::size_t cId = 0; cId < conditions.size(); ++cId) {
for (std::size_t pNb = 0; pNb < conditions[cId].GetParameters().size();
++pNb) {
@@ -768,23 +848,25 @@ bool EventsRefactorer::SearchStringInConditions(
if (foundPosition != gd::String::npos) return true;
}
if (inSentences && SearchStringInFormattedText(
platform, conditions[cId], search, matchCase, true))
return true;
if (!conditions[cId].GetSubInstructions().empty() &&
SearchStringInConditions(project,
layout,
SearchStringInConditions(platform,
conditions[cId].GetSubInstructions(),
search,
matchCase))
matchCase,
inSentences))
return true;
}
return false;
}
bool EventsRefactorer::SearchStringInEvent(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
gd::BaseEvent& event,
gd::String search,
bool matchCase) {
bool EventsRefactorer::SearchStringInEvent(gd::BaseEvent& event,
gd::String search,
bool matchCase) {
for (gd::String str : event.GetAllSearchableStrings()) {
if (matchCase) {
if (str.find(search) != gd::String::npos) return true;

View File

@@ -41,7 +41,7 @@ class GD_CORE_API EventsSearchResult {
std::size_t positionInList;
bool IsEventsListValid() const { return eventsList != nullptr; }
/**
* \brief Get the events list containing the event pointed by the EventsSearchResult.
* \warning Only call this when IsEventsListValid returns true.
@@ -49,7 +49,7 @@ class GD_CORE_API EventsSearchResult {
const gd::EventsList & GetEventsList() const { return *eventsList; }
std::size_t GetPositionInList() const { return positionInList; }
bool IsEventValid() const { return !event.expired(); }
/**
@@ -72,7 +72,7 @@ class GD_CORE_API EventsSearchResult {
class GD_CORE_API EventsRefactorer {
public:
/**
* Replace all occurences of an object name by another name
* Replace all occurrences of an object name by another name
* ( include : objects in parameters and in math/text expressions of all
* events ).
*/
@@ -98,14 +98,14 @@ class GD_CORE_API EventsRefactorer {
* \return A vector containing EventsSearchResult objects filled with events
* containing the string
*/
static std::vector<EventsSearchResult> SearchInEvents(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
static std::vector<EventsSearchResult> SearchInEvents(const gd::Platform& platform,
gd::EventsList& events,
gd::String search,
bool matchCase,
bool inConditions,
bool inActions,
bool inEventStrings);
bool inEventStrings,
bool inEventSentences);
/**
* Replace all occurrences of a gd::String in events
@@ -123,7 +123,7 @@ class GD_CORE_API EventsRefactorer {
private:
/**
* Replace all occurences of an object name by another name in an action
* Replace all occurrences of an object name by another name in an action
* ( include : objects in parameters and in math/text expressions ).
*
* \return true if something was modified.
@@ -136,7 +136,7 @@ class GD_CORE_API EventsRefactorer {
gd::String newName);
/**
* Replace all occurences of an object name by another name in a condition
* Replace all occurrences of an object name by another name in a condition
* ( include : objects in parameters and in math/text expressions ).
*
* \return true if something was modified.
@@ -185,7 +185,7 @@ class GD_CORE_API EventsRefactorer {
gd::String name);
/**
* Replace all occurences of a gd::String in conditions
* Replace all occurrences of a gd::String in conditions
*
* \return true if something was modified.
*/
@@ -197,7 +197,7 @@ class GD_CORE_API EventsRefactorer {
bool matchCase);
/**
* Replace all occurences of a gd::String in actions
* Replace all occurrences of a gd::String in actions
*
* \return true if something was modified.
*/
@@ -208,21 +208,26 @@ class GD_CORE_API EventsRefactorer {
gd::String newString,
bool matchCase);
static bool SearchStringInActions(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
static bool SearchStringInFormattedText(const gd::Platform& platform,
gd::Instruction& instruction,
gd::String search,
bool matchCase,
bool isCondition);
static bool SearchStringInActions(const gd::Platform& platform,
gd::InstructionsList& actions,
gd::String search,
bool matchCase);
static bool SearchStringInConditions(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
bool matchCase,
bool inSentences);
static bool SearchStringInConditions(const gd::Platform& platform,
gd::InstructionsList& conditions,
gd::String search,
bool matchCase);
static bool SearchStringInEvent(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
gd::BaseEvent& events,
gd::String search,
bool matchCase);
bool matchCase,
bool inSentences);
static bool SearchStringInEvent(gd::BaseEvent& events,
gd::String search,
bool matchCase);
static const gd::String searchIgnoredCharacters;
EventsRefactorer(){};
};

View File

@@ -151,7 +151,7 @@ std::set<gd::String> EventsVariablesFinder::FindArgumentsInInstructions(
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
gd::String lastObjectParameter = "";
gd::InstructionMetadata instrInfos =
const gd::InstructionMetadata& instrInfos =
instructionsAreConditions ? MetadataProvider::GetConditionMetadata(
platform, instructions[aId].GetType())
: MetadataProvider::GetActionMetadata(

View File

@@ -9,12 +9,12 @@
#include <memory>
#include <vector>
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/IDE/Events/ExpressionNodeLocationFinder.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
namespace gd {
class Expression;
@@ -326,10 +326,7 @@ class GD_CORE_API ExpressionCompletionFinder
node.type, "", searchedPosition + 1, searchedPosition + 1));
}
void OnVisitOperatorNode(OperatorNode& node) override {
completions.push_back(ExpressionCompletionDescription::ForObject(
node.type, "", searchedPosition + 1, searchedPosition + 1));
completions.push_back(ExpressionCompletionDescription::ForExpression(
node.type, "", searchedPosition + 1, searchedPosition + 1));
// No completions.
}
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
completions.push_back(ExpressionCompletionDescription::ForObject(
@@ -359,8 +356,9 @@ class GD_CORE_API ExpressionCompletionFinder
}
// Search the parameter metadata index skipping invisible ones.
size_t visibleParameterIndex = 0;
size_t metadataParameterIndex = ExpressionParser2::WrittenParametersFirstIndex(
functionCall->objectName, functionCall->behaviorName);
size_t metadataParameterIndex =
ExpressionParser2::WrittenParametersFirstIndex(
functionCall->objectName, functionCall->behaviorName);
const gd::ParameterMetadata* parameterMetadata = nullptr;
while (metadataParameterIndex <

View File

@@ -4,9 +4,11 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/IDE/Events/ExpressionsParameterMover.h"
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
@@ -134,10 +136,11 @@ class GD_CORE_API ExpressionParameterMover
bool ExpressionsParameterMover::DoVisitInstruction(gd::Instruction& instruction,
bool isCondition) {
auto& metadata = isCondition ? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
const auto& metadata = isCondition
? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
for (std::size_t pNb = 0; pNb < metadata.parameters.size() &&
pNb < instruction.GetParametersCount();

View File

@@ -4,9 +4,11 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/IDE/Events/ExpressionsRenamer.h"
#include <map>
#include <memory>
#include <vector>
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
@@ -145,10 +147,11 @@ class GD_CORE_API ExpressionFunctionRenamer
bool ExpressionsRenamer::DoVisitInstruction(gd::Instruction& instruction,
bool isCondition) {
auto& metadata = isCondition ? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
const auto& metadata = isCondition
? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
for (std::size_t pNb = 0; pNb < metadata.parameters.size() &&
pNb < instruction.GetParametersCount();

View File

@@ -4,7 +4,6 @@
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#include "GDCore/IDE/Events/InstructionSentenceFormatter.h"
#include <algorithm>
#include <iostream>
@@ -90,6 +89,19 @@ InstructionSentenceFormatter::GetAsFormattedText(
return formattedStr;
}
} // namespace gd
gd::String InstructionSentenceFormatter::GetFullText(
const gd::Instruction &instr, const gd::InstructionMetadata &metadata)
{
const std::vector<std::pair<gd::String, gd::TextFormatting> > formattedText =
GetAsFormattedText(instr, metadata);
#endif
gd::String completeSentence = "";
for (std::size_t id = 0; id < formattedText.size(); ++id) {
completeSentence += formattedText.at(id).first;
}
return completeSentence;
}
} // namespace gd

View File

@@ -4,7 +4,6 @@
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef TRANSLATEACTION_H
#define TRANSLATEACTION_H
#include <map>
@@ -39,6 +38,9 @@ class GD_CORE_API InstructionSentenceFormatter {
return (static_cast<InstructionSentenceFormatter *>(_singleton));
}
gd::String GetFullText(const gd::Instruction &instr,
const gd::InstructionMetadata &metadata);
static void DestroySingleton() {
if (NULL != _singleton) {
delete _singleton;
@@ -55,4 +57,3 @@ class GD_CORE_API InstructionSentenceFormatter {
} // namespace gd
#endif // TRANSLATEACTION_H
#endif

View File

@@ -19,12 +19,15 @@ bool InstructionsParameterMover::DoVisitInstruction(
gd::Instruction& instruction, bool isCondition) {
if (instruction.GetType() == instructionType) {
std::vector<gd::Expression> updatedParameters = instruction.GetParameters();
if (oldIndex < updatedParameters.size() ||
newIndex < updatedParameters.size()) {
gd::Expression movedParameter = updatedParameters[oldIndex];
if (oldIndex < updatedParameters.size()) {
gd::Expression movedParameter = updatedParameters.at(oldIndex);
updatedParameters.erase(updatedParameters.begin() + oldIndex);
updatedParameters.insert(updatedParameters.begin() + newIndex,
movedParameter);
if (newIndex < updatedParameters.size()) {
updatedParameters.insert(updatedParameters.begin() + newIndex,
movedParameter);
} else {
updatedParameters.push_back(movedParameter);
}
instruction.SetParameters(updatedParameters);
}
}

View File

@@ -4,16 +4,20 @@
* reserved. This project is released under the MIT License.
*/
#include "EventsFunctionTools.h"
#include "GDCore/Events/Expression.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsFunction.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/Project.h"
#include "GDCore/String.h"
#include "GDCore/Tools/Log.h"
namespace gd {
void EventsFunctionTools::EventsFunctionToObjectsContainer(
void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
gd::Project& project,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
@@ -31,4 +35,41 @@ void EventsFunctionTools::EventsFunctionToObjectsContainer(
outputObjectsContainer.GetObjectGroups() = eventsFunction.GetObjectGroups();
}
void EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
gd::Project& project,
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
gd::ObjectsContainer& outputObjectsContainer) {
// The context is build the same way as free function...
FreeEventsFunctionToObjectsContainer(project,
eventsFunction,
outputGlobalObjectsContainer,
outputObjectsContainer);
// ...and has an "Object" by convention...
if (!outputObjectsContainer.HasObjectNamed("Object")) {
gd::LogWarning("No \"Object\" in a function of an events based behavior: " +
eventsFunction.GetName() +
". This means this function is likely misconfigured (check "
"its parameters).");
return;
}
// ...with behaviors from properties.
gd::Object& thisObject = outputObjectsContainer.GetObject("Object");
for (size_t i = 0;
i < eventsBasedBehavior.GetPropertyDescriptors().GetCount();
i++) {
const NamedPropertyDescriptor& propertyDescriptor =
eventsBasedBehavior.GetPropertyDescriptors().Get(i);
const std::vector<gd::String>& extraInfo =
propertyDescriptor.GetExtraInfo();
if (propertyDescriptor.GetType() == "Behavior" && extraInfo.size() > 0) {
gd::String behaviorName = propertyDescriptor.GetName();
thisObject.AddNewBehavior(project, extraInfo.at(0), behaviorName);
}
}
}
} // namespace gd

View File

@@ -13,6 +13,7 @@ class Project;
class ObjectsContainer;
class ParameterMetadata;
class EventsFunction;
class EventsBasedBehavior;
class Expression;
} // namespace gd
@@ -23,18 +24,33 @@ namespace gd {
class GD_CORE_API EventsFunctionTools {
public:
/**
* \brief Given an events function, initialize the given objects container
* \brief Given a free events function, initialize the given objects container
* with objects described in the events function parameters and in
* the events function groups.
*
* This is useful to create the "context" of a function, before code
* generation for example.
*/
static void EventsFunctionToObjectsContainer(
static void FreeEventsFunctionToObjectsContainer(
gd::Project& project,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
gd::ObjectsContainer& outputObjectsContainer);
/**
* \brief Given a behavior events function, initialize the given objects container
* with objects described in the events function parameters, in
* the events function groups and in the behavior properties (for additional
* required behaviors on the object).
*
* This is useful to create the "context" of a function, before code
* generation for example.
*/
static void BehaviorEventsFunctionToObjectsContainer(
gd::Project& project,
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::EventsFunction& eventsFunction,
gd::ObjectsContainer& outputGlobalObjectsContainer,
gd::ObjectsContainer& outputObjectsContainer);
};
} // namespace gd

View File

@@ -27,50 +27,6 @@ namespace gd {
PlatformLoader::PlatformLoader() {}
void PlatformLoader::LoadAllPlatformsInManager(gd::String dir) {
{
#if defined(WINDOWS)
std::shared_ptr<gd::Platform> platform = LoadPlatformInManager("GDCpp.dll");
#elif defined(LINUX)
std::shared_ptr<gd::Platform> platform =
LoadPlatformInManager("libGDCpp.so");
#elif defined(MACOS)
std::shared_ptr<gd::Platform> platform =
LoadPlatformInManager("libGDCpp.dylib");
#else
#warning Add the appropriate filename here for the C++ Platform!
std::shared_ptr<gd::Platform> platform;
#endif
if (platform)
gd::ExtensionsLoader::LoadAllExtensions("./CppPlatform/Extensions/",
*platform);
}
{
#if defined(WINDOWS)
std::shared_ptr<gd::Platform> platform =
LoadPlatformInManager("./JsPlatform/GDJS.dll");
#elif defined(LINUX)
std::shared_ptr<gd::Platform> platform =
LoadPlatformInManager("./JsPlatform/libGDJS.so");
#elif defined(MACOS)
std::shared_ptr<gd::Platform> platform =
LoadPlatformInManager("./JsPlatform/libGDJS.dylib");
#else
#warning Add the appropriate filename here for the Js Platform!
std::shared_ptr<gd::Platform> platform;
#endif
if (platform)
gd::ExtensionsLoader::LoadAllExtensions("./JsPlatform/Extensions/",
*platform);
if (platform)
gd::ExtensionsLoader::LoadAllExtensions(
"./CppPlatform/Extensions/", *platform, true);
}
gd::ExtensionsLoader::ExtensionsLoadingDone("./CppPlatform/Extensions/");
}
std::shared_ptr<gd::Platform> PlatformLoader::LoadPlatformInManager(
gd::String fullpath) {
std::cout << "Loading platform " << fullpath << "..." << std::endl;

View File

@@ -30,15 +30,6 @@ passing
*/
class GD_CORE_API PlatformLoader {
public:
/**
* Load all the platforms available in a directory.
*
* \param dir The directory where platforms must be searched for.
*
* \todo For now, only GDCpp.dll and GDJS.dll are loaded.
*/
static void LoadAllPlatformsInManager(gd::String dir);
/**
* Load a specific platform.
*

View File

@@ -13,8 +13,11 @@
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/ResourcesManager.h"
@@ -23,8 +26,13 @@ using namespace std;
namespace gd {
void ArbitraryResourceWorker::ExposeImage(gd::String& imageName){
// Nothing to do, the image is a reference to a resource that
// is already exposed.
// Nothing to do by default - each child class can define here the action to
// do.
};
void ArbitraryResourceWorker::ExposeBitmapFont(gd::String& bitmapFontName){
// Nothing to do by default - each child class can define here the action to
// do.
};
void ArbitraryResourceWorker::ExposeAudio(gd::String& audioName) {
@@ -33,12 +41,14 @@ void ArbitraryResourceWorker::ExposeAudio(gd::String& audioName) {
if (resources->HasResource(audioName) &&
resources->GetResource(audioName).GetKind() == "audio") {
// Nothing to do, the audio is a reference to a resource that
// is already exposed.
// Nothing to do, the audio is a reference to a proper resource.
return;
}
}
// For compatibility with older projects (where events were refering to files
// directly), we consider that this resource name is a filename, and so expose
// it as a file.
ExposeFile(audioName);
};
@@ -48,30 +58,17 @@ void ArbitraryResourceWorker::ExposeFont(gd::String& fontName) {
if (resources->HasResource(fontName) &&
resources->GetResource(fontName).GetKind() == "font") {
// Nothing to do, the font is a reference to a resource that
// is already exposed.
// Nothing to do, the font is a reference to a proper resource.
return;
}
}
// For compatibility with older projects (where events were refering to files
// directly), we consider that this resource name is a filename, and so expose
// it as a file.
ExposeFile(fontName);
};
void ArbitraryResourceWorker::ExposeBitmapFont(gd::String& bitmapFontName) {
for (auto resources : GetResources()) {
if (!resources) continue;
if (resources->HasResource(bitmapFontName) &&
resources->GetResource(bitmapFontName).GetKind() == "bitmapFont") {
// Nothing to do, the font is a reference to a resource that
// is already exposed.
return;
}
}
ExposeFile(bitmapFontName);
};
void ArbitraryResourceWorker::ExposeResources(
gd::ResourcesManager* resourcesManager) {
if (!resourcesManager) return;
@@ -95,101 +92,67 @@ void ArbitraryResourceWorker::ExposeResource(gd::Resource& resource) {
ArbitraryResourceWorker::~ArbitraryResourceWorker() {}
/**
* Launch the specified resource worker on every resource referenced in the
* events.
*/
class ResourceWorkerInEventsWorker : public ArbitraryEventsWorker {
public:
ResourceWorkerInEventsWorker(const gd::Project& project_,
gd::ArbitraryResourceWorker& worker_)
: project(project_), worker(worker_){};
virtual ~ResourceWorkerInEventsWorker() {};
private:
bool DoVisitInstruction(gd::Instruction& instruction, bool isCondition) {
const auto& platform = project.GetCurrentPlatform();
const auto& metadata = isCondition
? gd::MetadataProvider::GetConditionMetadata(
platform, instruction.GetType())
: gd::MetadataProvider::GetActionMetadata(
platform, instruction.GetType());
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
instruction.GetParameters(),
metadata.GetParameters(),
[this, &instruction](const gd::ParameterMetadata& parameterMetadata,
const gd::String& parameterValue,
size_t parameterIndex,
const gd::String& lastObjectName) {
if (parameterMetadata.GetType() ==
"police") { // Should be renamed fontResource
gd::String updatedParameterValue = parameterValue;
worker.ExposeFont(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
} else if (parameterMetadata.GetType() == "soundfile" ||
parameterMetadata.GetType() ==
"musicfile") { // Should be renamed audioResource
gd::String updatedParameterValue = parameterValue;
worker.ExposeAudio(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
} else if (parameterMetadata.GetType() == "bitmapFontResource") {
gd::String updatedParameterValue = parameterValue;
worker.ExposeBitmapFont(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
} else if (parameterMetadata.GetType() == "imageResource") {
gd::String updatedParameterValue = parameterValue;
worker.ExposeImage(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
}
});
return false;
};
const gd::Project& project;
gd::ArbitraryResourceWorker& worker;
};
void LaunchResourceWorkerOnEvents(const gd::Project& project,
gd::EventsList& events,
gd::ArbitraryResourceWorker& worker) {
// Get all extensions used
auto allGameExtensions =
project.GetCurrentPlatform().GetAllPlatformExtensions();
for (std::size_t j = 0; j < events.size(); j++) {
vector<gd::InstructionsList*> allActionsVectors =
events[j].GetAllActionsVectors();
for (std::size_t i = 0; i < allActionsVectors.size(); ++i) {
for (std::size_t k = 0; k < allActionsVectors[i]->size(); k++) {
gd::String type = allActionsVectors[i]->Get(k).GetType();
for (std::size_t e = 0; e < allGameExtensions.size(); ++e) {
bool extensionHasAction = false;
const std::map<gd::String, gd::InstructionMetadata>& allActions =
allGameExtensions[e]->GetAllActions();
if (allActions.find(type) != allActions.end())
extensionHasAction = true;
const vector<gd::String>& objects =
allGameExtensions[e]->GetExtensionObjectsTypes();
for (std::size_t o = 0; o < objects.size(); ++o) {
const std::map<gd::String, gd::InstructionMetadata>&
allObjectsActions =
allGameExtensions[e]->GetAllActionsForObject(objects[o]);
if (allObjectsActions.find(type) != allObjectsActions.end())
extensionHasAction = true;
}
const vector<gd::String>& autos =
allGameExtensions[e]->GetBehaviorsTypes();
for (std::size_t a = 0; a < autos.size(); ++a) {
const std::map<gd::String, gd::InstructionMetadata>&
allAutosActions =
allGameExtensions[e]->GetAllActionsForBehavior(autos[a]);
if (allAutosActions.find(type) != allAutosActions.end())
extensionHasAction = true;
}
if (extensionHasAction) {
allGameExtensions[e]->ExposeActionsResources(
allActionsVectors[i]->Get(k), worker);
break;
}
}
}
}
vector<gd::InstructionsList*> allConditionsVector =
events[j].GetAllConditionsVectors();
for (std::size_t i = 0; i < allConditionsVector.size(); ++i) {
for (std::size_t k = 0; k < allConditionsVector[i]->size(); k++) {
gd::String type = allConditionsVector[i]->Get(k).GetType();
for (std::size_t e = 0; e < allGameExtensions.size(); ++e) {
bool extensionHasCondition = false;
const std::map<gd::String, gd::InstructionMetadata>& allConditions =
allGameExtensions[e]->GetAllConditions();
if (allConditions.find(type) != allConditions.end())
extensionHasCondition = true;
const vector<gd::String>& objects =
allGameExtensions[e]->GetExtensionObjectsTypes();
for (std::size_t j = 0; j < objects.size(); ++j) {
const std::map<gd::String, gd::InstructionMetadata>&
allObjectsConditions =
allGameExtensions[e]->GetAllConditionsForObject(objects[j]);
if (allObjectsConditions.find(type) != allObjectsConditions.end())
extensionHasCondition = true;
}
const vector<gd::String>& autos =
allGameExtensions[e]->GetBehaviorsTypes();
for (std::size_t j = 0; j < autos.size(); ++j) {
const std::map<gd::String, gd::InstructionMetadata>&
allAutosConditions =
allGameExtensions[e]->GetAllConditionsForBehavior(autos[j]);
if (allAutosConditions.find(type) != allAutosConditions.end())
extensionHasCondition = true;
}
if (extensionHasCondition)
allGameExtensions[e]->ExposeConditionsResources(
allConditionsVector[i]->Get(k), worker);
}
}
}
if (events[j].CanHaveSubEvents())
LaunchResourceWorkerOnEvents(project, events[j].GetSubEvents(), worker);
}
return;
ResourceWorkerInEventsWorker eventsWorker(project, worker);
eventsWorker.Launch(events);
}
} // namespace gd

View File

@@ -60,19 +60,18 @@ class GD_CORE_API ArbitraryResourceWorker {
/**
* \brief Expose an audio, which is either a reference to an "audio" resource,
* or a filename if no resource with this name exists.
* or a filename if no resource with this name exists (for backward compatibility).
*/
virtual void ExposeAudio(gd::String &audioName);
/**
* \brief Expose a font, which is either a reference to a "font" resource,
* or a filename if no resource with this name exists.
* or a filename if no resource with this name exists (for backward compatibility).
*/
virtual void ExposeFont(gd::String &fontName);
/**
* \brief Expose a bitmap font, which is either a reference to a "bitmapFont" resource,
* or a filename if no resource with this name exists.
* \brief Expose a bitmap font, which is always a reference to a "bitmapFont" resource.
*/
virtual void ExposeBitmapFont(gd::String &bitmapFontName);

View File

@@ -14,25 +14,6 @@ using namespace std;
namespace gd {
bool ProjectResourcesAdder::AddAllMissing(gd::Project& project,
const gd::String& resourceType) {
// Search for resources used in the project
gd::ResourcesInUseHelper resourcesInUse;
project.ExposeResources(resourcesInUse);
ResourcesManager& resourcesManager = project.GetResourcesManager();
for (auto& resourceName : resourcesInUse.GetAll(resourceType)) {
if (!resourcesManager.HasResource(resourceName)) {
std::cout << "Adding missing resource \"" << resourceName
<< "\"to the project." << std::endl;
resourcesManager.AddResource(
resourceName, /*filename=*/resourceName, resourceType);
}
}
return true;
}
std::vector<gd::String> ProjectResourcesAdder::GetAllUseless(
gd::Project& project, const gd::String& resourceType) {
std::vector<gd::String> unusedResources;
@@ -42,15 +23,13 @@ std::vector<gd::String> ProjectResourcesAdder::GetAllUseless(
std::set<gd::String>& usedResources = resourcesInUse.GetAll(resourceType);
// Search all resources not used
std::vector<gd::String> resources =
project.GetResourcesManager().GetAllResourceNames();
const std::vector<std::shared_ptr<Resource>>& resources =
project.GetResourcesManager().GetAllResources();
for (std::size_t i = 0; i < resources.size(); i++) {
if (project.GetResourcesManager().GetResource(resources[i]).GetKind() !=
resourceType)
continue;
if (resources[i]->GetKind() != resourceType) continue;
if (usedResources.find(resources[i]) == usedResources.end())
unusedResources.push_back(resources[i]);
if (usedResources.find(resources[i]->GetName()) == usedResources.end())
unusedResources.push_back(resources[i]->GetName());
}
return unusedResources;

View File

@@ -20,17 +20,6 @@ namespace gd {
*/
class GD_CORE_API ProjectResourcesAdder {
public:
/**
* \brief Update the project so that all missing resources are added, with an
* filename that is equal to the missing resource name.
*
* \param project The project to be updated.
* \param resourceType The type of the resource the be searched
*
* \return true if no error happened
*/
static bool AddAllMissing(gd::Project& project, const gd::String & resourceType);
/**
* \brief Find all resources of the specified kind that are
* not used by the project.

View File

@@ -22,7 +22,7 @@ void ResourcesMergingHelper::ExposeFile(gd::String& resourceFilename) {
resourceFullFilename = gd::AbstractFileSystem::NormalizeSeparator(
resourceFullFilename); // Protect against \ on Linux.
// In the case of absolute filnames that we don't want to preserve, or
// In the case of absolute filenames that we don't want to preserve, or
// in the case of copying files without preserving relative folders, the new
// names will be generated from the filename alone (with collision protection).
auto stripToFilenameOnly = [&]() {

View File

@@ -71,7 +71,7 @@ class GD_CORE_API ResourcesMergingHelper : public ArbitraryResourceWorker {
* Resources merging helper collects all resources filenames and update these
* filenames.
*/
virtual void ExposeFile(gd::String& resource);
virtual void ExposeFile(gd::String& resource) override;
protected:
void SetNewFilename(gd::String oldFilename, gd::String newFilename);

View File

@@ -33,8 +33,9 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
: gd::ArbitraryResourceWorker(), oldToNewNames(oldToNewNames_){};
virtual ~ResourcesRenamer(){};
virtual void ExposeFile(gd::String& resourceName) override {
RenameIfNeeded(resourceName);
virtual void ExposeFile(gd::String& resourceFileName) override{
// Don't do anything: we're renaming resources, not the files they are
// pointing to.
};
virtual void ExposeImage(gd::String& imageResourceName) override {
RenameIfNeeded(imageResourceName);
@@ -45,6 +46,9 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
virtual void ExposeFont(gd::String& fontResourceName) override {
RenameIfNeeded(fontResourceName);
};
virtual void ExposeBitmapFont(gd::String& bitmapFontName) override {
RenameIfNeeded(bitmapFontName);
};
private:
void RenameIfNeeded(gd::String& resourceName) {

View File

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

View File

@@ -0,0 +1,80 @@
/*
* GDevelop Core
* Copyright 2008-2021 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_UNFILLEDREQUIREDBEHAVIORPROPERTYPROBLEM_H
#define GDCORE_UNFILLEDREQUIREDBEHAVIORPROPERTYPROBLEM_H
#include "GDCore/String.h"
namespace gd {
class Project;
class Object;
class BehaviorContent;
} // namespace gd
namespace gd {
/**
* \brief A problem when a required behavior property is not fill correctly.
*/
class GD_CORE_API UnfilledRequiredBehaviorPropertyProblem {
public:
UnfilledRequiredBehaviorPropertyProblem(
const gd::Project& sourceProject_,
gd::Object& sourceObject_,
gd::BehaviorContent& sourceBehaviorContent_,
const gd::String& sourcePropertyName_,
const gd::String& expectedBehaviorTypeName_)
: sourceProject(sourceProject_),
sourceObject(sourceObject_),
sourceBehaviorContent(sourceBehaviorContent_),
sourcePropertyName(sourcePropertyName_),
expectedBehaviorTypeName(expectedBehaviorTypeName_){};
virtual ~UnfilledRequiredBehaviorPropertyProblem();
/**
* \brief Return the project where the problem appears
*/
virtual const gd::Project& GetSourceProject() const { return sourceProject; }
/**
* \brief Return the object where the problem appears.
*/
virtual gd::Object& GetSourceObject() const { return sourceObject; }
/**
* \brief Return the behavior where the problem appears.
*/
virtual gd::BehaviorContent& GetSourceBehaviorContent() const {
return sourceBehaviorContent;
}
/**
* \brief Return the property where the problem appears.
*/
virtual const gd::String& GetSourcePropertyName() const {
return sourcePropertyName;
}
/**
* \brief Return the behavior type name that is expected for the required
* behavior property.
*/
virtual const gd::String& GetExpectedBehaviorTypeName() const {
return expectedBehaviorTypeName;
}
private:
const gd::Project& sourceProject;
gd::Object& sourceObject;
gd::BehaviorContent& sourceBehaviorContent;
const gd::String sourcePropertyName;
const gd::String expectedBehaviorTypeName;
};
} // namespace gd
#endif // GDCORE_UNFILLEDREQUIREDBEHAVIORPROPERTYPROBLEM_H

View File

@@ -5,9 +5,12 @@
*/
#include "WholeProjectRefactorer.h"
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/DependenciesAnalyzer.h"
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
#include "GDCore/IDE/Events/EventsBehaviorRenamer.h"
#include "GDCore/IDE/Events/EventsRefactorer.h"
#include "GDCore/IDE/Events/ExpressionsParameterMover.h"
#include "GDCore/IDE/Events/ExpressionsRenamer.h"
@@ -15,6 +18,9 @@
#include "GDCore/IDE/Events/InstructionsTypeRenamer.h"
#include "GDCore/IDE/EventsFunctionTools.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
#include "GDCore/IDE/UnfilledRequiredBehaviorPropertyProblem.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorContent.h"
#include "GDCore/Project/EventsBasedBehavior.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/ExternalEvents.h"
@@ -51,6 +57,10 @@ gd::String GetBehaviorFullType(const gd::String& extensionName,
namespace gd {
// By convention, the first parameter of an events based behavior method is
// always called "Object".
const gd::String WholeProjectRefactorer::behaviorObjectParameterName = "Object";
void WholeProjectRefactorer::ExposeProjectEvents(
gd::Project& project, gd::ArbitraryEventsWorker& worker) {
// See also gd::Project::ExposeResources for a method that traverse the whole
@@ -115,7 +125,7 @@ void WholeProjectRefactorer::ExposeProjectEvents(
for (auto&& eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
gd::ObjectsContainer globalObjectsAndGroups;
gd::ObjectsContainer objectsAndGroups;
gd::EventsFunctionTools::EventsFunctionToObjectsContainer(
gd::EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
project, *eventsFunction, globalObjectsAndGroups, objectsAndGroups);
worker.Launch(eventsFunction->GetEvents(),
@@ -127,22 +137,31 @@ void WholeProjectRefactorer::ExposeProjectEvents(
for (auto&& eventsBasedBehavior :
eventsFunctionsExtension.GetEventsBasedBehaviors()
.GetInternalVector()) {
auto& behaviorEventsFunctions = eventsBasedBehavior->GetEventsFunctions();
for (auto&& eventsFunction :
behaviorEventsFunctions.GetInternalVector()) {
gd::ObjectsContainer globalObjectsAndGroups;
gd::ObjectsContainer objectsAndGroups;
gd::EventsFunctionTools::EventsFunctionToObjectsContainer(
project, *eventsFunction, globalObjectsAndGroups, objectsAndGroups);
worker.Launch(eventsFunction->GetEvents(),
globalObjectsAndGroups,
objectsAndGroups);
}
ExposeEventsBasedBehaviorEvents(project, *eventsBasedBehavior, worker);
}
}
}
void WholeProjectRefactorer::ExposeEventsBasedBehaviorEvents(
gd::Project& project,
const gd::EventsBasedBehavior& eventsBasedBehavior,
gd::ArbitraryEventsWorkerWithContext& worker) {
auto& behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
gd::ObjectsContainer globalObjectsAndGroups;
gd::ObjectsContainer objectsAndGroups;
gd::EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
project,
eventsBasedBehavior,
*eventsFunction,
globalObjectsAndGroups,
objectsAndGroups);
worker.Launch(
eventsFunction->GetEvents(), globalObjectsAndGroups, objectsAndGroups);
}
}
void WholeProjectRefactorer::ExposeProjectObjects(
gd::Project& project, gd::ArbitraryObjectsWorker& worker) {
worker.Launch(project);
@@ -192,7 +211,7 @@ void WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
parameters[0]
.SetType("object")
.SetName("Object")
.SetName(behaviorObjectParameterName)
.SetDescription("Object")
.SetExtraInfo(eventsBasedBehavior.GetObjectType());
parameters[1]
@@ -219,7 +238,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
};
auto renameBehaviorEventsFunction =
[&project, &eventsFunctionsExtension, &oldName, &newName](
[&project, &oldName, &newName](
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::EventsFunction& eventsFunction) {
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
@@ -242,7 +261,7 @@ void WholeProjectRefactorer::RenameEventsFunctionsExtension(
};
auto renameBehaviorPropertyFunctions =
[&project, &eventsFunctionsExtension, &oldName, &newName](
[&project, &oldName, &newName](
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::NamedPropertyDescriptor& property) {
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
@@ -470,7 +489,7 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
}
}
void WholeProjectRefactorer::RenameBehaviorProperty(
void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
gd::Project& project,
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
const gd::EventsBasedBehavior& eventsBasedBehavior,
@@ -479,41 +498,294 @@ void WholeProjectRefactorer::RenameBehaviorProperty(
auto& properties = eventsBasedBehavior.GetPropertyDescriptors();
if (!properties.Has(oldPropertyName)) return;
// Order is important: we first rename the expressions then the instructions,
// to avoid being unable to fetch the metadata (the types of parameters) of
// instructions after they are renamed.
gd::ExpressionsRenamer expressionRenamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
expressionRenamer.SetReplacedBehaviorExpression(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
EventsBasedBehavior::GetPropertyExpressionName(oldPropertyName),
EventsBasedBehavior::GetPropertyExpressionName(newPropertyName));
ExposeProjectEvents(project, expressionRenamer);
if (properties.Get(oldPropertyName).GetType() == "Behavior") {
// This is a property representing another behavior that must exist on the
// object.
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyActionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyActionName(newPropertyName)));
ExposeProjectEvents(project, actionRenamer);
// This other "required behavior" uses the property name, that is about to
// change, as its name.
// So we must change all reference to this name in the events of the
// behavior functions.
gd::EventsBehaviorRenamer behaviorRenamer(project.GetCurrentPlatform(),
behaviorObjectParameterName,
oldPropertyName,
newPropertyName);
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyConditionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyConditionName(newPropertyName)));
ExposeProjectEvents(project, conditionRenamer);
ExposeEventsBasedBehaviorEvents(
project, eventsBasedBehavior, behaviorRenamer);
} else {
// Properties that represent primitive values will be used through
// their related actions/conditions/expressions. Rename these.
// Order is important: we first rename the expressions then the
// instructions, to avoid being unable to fetch the metadata (the types of
// parameters) of instructions after they are renamed.
gd::ExpressionsRenamer expressionRenamer =
gd::ExpressionsRenamer(project.GetCurrentPlatform());
expressionRenamer.SetReplacedBehaviorExpression(
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName()),
EventsBasedBehavior::GetPropertyExpressionName(oldPropertyName),
EventsBasedBehavior::GetPropertyExpressionName(newPropertyName));
ExposeProjectEvents(project, expressionRenamer);
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyActionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyActionName(newPropertyName)));
ExposeProjectEvents(project, actionRenamer);
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
project,
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyConditionName(oldPropertyName)),
GetBehaviorEventsFunctionFullType(
eventsFunctionsExtension.GetName(),
eventsBasedBehavior.GetName(),
EventsBasedBehavior::GetPropertyConditionName(newPropertyName)));
ExposeProjectEvents(project, conditionRenamer);
}
}
void WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
gd::Project& project,
gd::Object& object,
const gd::String& behaviorType,
const gd::String& behaviorName) {
if (object.AddNewBehavior(project, behaviorType, behaviorName) == nullptr) {
// The behavior type/metadata can't be found.
return;
};
const gd::Platform& platform = project.GetCurrentPlatform();
const gd::BehaviorMetadata& behaviorMetadata =
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
// Should not happen because the behavior was added successfully (so its
// metadata are valid) - but double check anyway and bail out if the
// behavior metadata are invalid.
return;
}
gd::Behavior& behavior = behaviorMetadata.Get();
gd::BehaviorContent& behaviorContent = object.GetBehavior(behaviorName);
for (auto const& keyValue :
behavior.GetProperties(behaviorContent.GetContent())) {
const gd::String& propertyName = keyValue.first;
const gd::PropertyDescriptor& property = keyValue.second;
if (property.GetType().LowerCase() == "behavior") {
const std::vector<gd::String>& extraInfo = property.GetExtraInfo();
if (extraInfo.size() == 0) {
// very unlikely
continue;
}
const gd::String& requiredBehaviorType = extraInfo.at(0);
const auto behaviorContents =
WholeProjectRefactorer::GetBehaviorsWithType(object,
requiredBehaviorType);
const gd::String* defaultBehaviorName = nullptr;
if (behaviorContents.size() == 0) {
const gd::BehaviorMetadata& requiredBehaviorMetadata =
MetadataProvider::GetBehaviorMetadata(platform,
requiredBehaviorType);
const gd::String& requiredBehaviorName =
requiredBehaviorMetadata.GetDefaultName();
WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
project, object, requiredBehaviorType, requiredBehaviorName);
defaultBehaviorName = &requiredBehaviorName;
} else {
defaultBehaviorName = &behaviorContents.at(0);
}
behavior.UpdateProperty(
behaviorContent.GetContent(), propertyName, *defaultBehaviorName);
}
}
}
std::vector<gd::String> WholeProjectRefactorer::GetBehaviorsWithType(
const gd::Object& object, const gd::String& type) {
std::vector<gd::String> behaviors;
for (auto& behaviorName : object.GetAllBehaviorNames()) {
const gd::BehaviorContent& behaviorContent =
object.GetBehavior(behaviorName);
if (behaviorContent.GetTypeName() == type) {
behaviors.push_back(behaviorName);
}
}
return behaviors;
}
std::vector<gd::String> WholeProjectRefactorer::FindDependentBehaviorNames(
const gd::Project& project,
const gd::Object& object,
const gd::String& behaviorName) {
std::unordered_set<gd::String> dependentBehaviorNames;
WholeProjectRefactorer::FindDependentBehaviorNames(
project, object, behaviorName, dependentBehaviorNames);
std::vector<gd::String> results;
results.insert(results.end(),
dependentBehaviorNames.begin(),
dependentBehaviorNames.end());
return results;
}
void WholeProjectRefactorer::FindDependentBehaviorNames(
const gd::Project& project,
const gd::Object& object,
const gd::String& behaviorName,
std::unordered_set<gd::String>& dependentBehaviorNames) {
const gd::Platform& platform = project.GetCurrentPlatform();
for (auto const& objectBehaviorName : object.GetAllBehaviorNames()) {
const gd::BehaviorContent& behaviorContent =
object.GetBehavior(objectBehaviorName);
const auto& behaviorMetadata = MetadataProvider::GetBehaviorMetadata(
platform, behaviorContent.GetTypeName());
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
// Ignore this behavior as it's unknown.
continue;
}
gd::Behavior& behavior = behaviorMetadata.Get();
for (auto const& keyValue :
behavior.GetProperties(behaviorContent.GetContent())) {
const gd::String& propertyName = keyValue.first;
const gd::PropertyDescriptor& property = keyValue.second;
if (property.GetType().LowerCase() == "behavior" &&
property.GetValue() == behaviorName &&
dependentBehaviorNames.find(objectBehaviorName) ==
dependentBehaviorNames.end()) {
dependentBehaviorNames.insert(objectBehaviorName);
WholeProjectRefactorer::FindDependentBehaviorNames(
project, object, objectBehaviorName, dependentBehaviorNames);
}
}
}
};
std::vector<gd::UnfilledRequiredBehaviorPropertyProblem>
WholeProjectRefactorer::FindInvalidRequiredBehaviorProperties(
const gd::Project& project) {
std::vector<gd::UnfilledRequiredBehaviorPropertyProblem>
invalidRequiredBehaviorProperties;
auto findInvalidRequiredBehaviorPropertiesInObjects =
[&project, &invalidRequiredBehaviorProperties](
const std::vector<std::unique_ptr<gd::Object> >& objectsList) {
for (auto& object : objectsList) {
for (auto& behaviorContentKeyValuePair :
object->GetAllBehaviorContents()) {
gd::BehaviorContent& behaviorContent =
*behaviorContentKeyValuePair.second;
const auto& behaviorMetadata =
gd::MetadataProvider::GetBehaviorMetadata(
project.GetCurrentPlatform(),
behaviorContent.GetTypeName());
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
std::cout << "Could not find metadata for behavior with type \""
<< behaviorContent.GetTypeName() << "\"" << std::endl;
continue;
}
const auto& behavior = behaviorMetadata.Get();
for (auto const& keyValue :
behavior.GetProperties(behaviorContent.GetContent())) {
const gd::String& propertyName = keyValue.first;
const gd::PropertyDescriptor& property = keyValue.second;
if (property.GetType().LowerCase() != "behavior") {
continue;
}
const gd::String& requiredBehaviorName = property.GetValue();
const std::vector<gd::String>& extraInfo =
property.GetExtraInfo();
if (extraInfo.size() == 0) {
// very unlikely
continue;
}
const gd::String& requiredBehaviorType = extraInfo.at(0);
if (requiredBehaviorName == "" ||
!object->HasBehaviorNamed(requiredBehaviorName) ||
object->GetBehavior(requiredBehaviorName).GetTypeName() !=
requiredBehaviorType) {
auto problem = UnfilledRequiredBehaviorPropertyProblem(
project,
*object,
behaviorContent,
propertyName,
requiredBehaviorType);
invalidRequiredBehaviorProperties.push_back(problem);
}
}
}
}
};
// Find in global objects
findInvalidRequiredBehaviorPropertiesInObjects(project.GetObjects());
// Find in layout objects.
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
const gd::Layout& layout = project.GetLayout(i);
findInvalidRequiredBehaviorPropertiesInObjects(layout.GetObjects());
}
return invalidRequiredBehaviorProperties;
}
bool WholeProjectRefactorer::FixInvalidRequiredBehaviorProperties(
gd::Project& project) {
const auto& invalidRequiredBehaviorProblems =
FindInvalidRequiredBehaviorProperties(project);
for (const auto& problem : invalidRequiredBehaviorProblems) {
auto& object = problem.GetSourceObject();
auto suggestedBehaviorNames =
GetBehaviorsWithType(object, problem.GetExpectedBehaviorTypeName());
auto& behaviorContent = problem.GetSourceBehaviorContent();
auto& behaviorMetadata = MetadataProvider::GetBehaviorMetadata(
project.GetCurrentPlatform(), behaviorContent.GetTypeName());
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
continue;
}
auto& behavior = behaviorMetadata.Get();
if (suggestedBehaviorNames.empty()) {
// No matching behavior on the object.
// Add required behaviors on the object.
auto& expectedBehaviorMetadata = MetadataProvider::GetBehaviorMetadata(
project.GetCurrentPlatform(), problem.GetExpectedBehaviorTypeName());
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
continue;
}
const gd::String& newBehaviorName =
expectedBehaviorMetadata.GetDefaultName();
AddBehaviorAndRequiredBehaviors(project,
object,
problem.GetExpectedBehaviorTypeName(),
newBehaviorName);
behavior.UpdateProperty(behaviorContent.GetContent(),
problem.GetSourcePropertyName(),
newBehaviorName);
} else {
// There is a matching behavior on the object use it by default.
behavior.UpdateProperty(
behaviorContent.GetContent(),
problem.GetSourcePropertyName(),
// It's unlikely the object has 2 behaviors of the same type.
suggestedBehaviorNames[0]);
}
}
return !invalidRequiredBehaviorProblems.empty();
}
void WholeProjectRefactorer::RenameEventsBasedBehavior(
@@ -533,7 +805,6 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
auto renameBehaviorEventsFunction =
[&project,
&eventsFunctionsExtension,
&eventsBasedBehavior,
&oldBehaviorName,
&newBehaviorName](const gd::EventsFunction& eventsFunction) {
if (eventsFunction.GetFunctionType() == gd::EventsFunction::Action ||
@@ -560,7 +831,6 @@ void WholeProjectRefactorer::RenameEventsBasedBehavior(
auto renameBehaviorProperty = [&project,
&eventsFunctionsExtension,
&eventsBasedBehavior,
&oldBehaviorName,
&newBehaviorName](
const gd::NamedPropertyDescriptor&
@@ -678,6 +948,31 @@ void WholeProjectRefactorer::DoRenameBehavior(
}
};
// Rename behavior in required behavior properties
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
e++) {
auto& eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
for (auto&& eventsBasedBehavior :
eventsFunctionsExtension.GetEventsBasedBehaviors()
.GetInternalVector()) {
for (size_t i = 0;
i < eventsBasedBehavior->GetPropertyDescriptors().GetCount();
i++) {
NamedPropertyDescriptor& propertyDescriptor =
eventsBasedBehavior->GetPropertyDescriptors().Get(i);
std::vector<gd::String>& extraInfo = propertyDescriptor.GetExtraInfo();
if (propertyDescriptor.GetType() == "Behavior" &&
extraInfo.size() > 0) {
const gd::String& requiredBehaviorType = extraInfo[0];
if (requiredBehaviorType == oldBehaviorType) {
extraInfo[0] = newBehaviorType;
}
}
}
}
}
// Rename behavior in global objects
renameBehaviorTypeInObjects(project.GetObjects());

View File

@@ -6,10 +6,13 @@
#ifndef GDCORE_WHOLEPROJECTREFACTORER_H
#define GDCORE_WHOLEPROJECTREFACTORER_H
#include <set>
#include <unordered_set>
#include <vector>
namespace gd {
class Platform;
class Project;
class Layout;
class Object;
class String;
class EventsFunctionsExtension;
class EventsFunction;
@@ -18,6 +21,10 @@ class EventsBasedBehavior;
class ArbitraryEventsWorker;
class ArbitraryObjectsWorker;
class ArbitraryEventsWorkerWithContext;
class Behavior;
class BehaviorContent;
class BehaviorMetadata;
class UnfilledRequiredBehaviorPropertyProblem;
} // namespace gd
namespace gd {
@@ -51,13 +58,24 @@ class GD_CORE_API WholeProjectRefactorer {
gd::ArbitraryEventsWorkerWithContext& worker);
/**
* \brief Call the specified worker on all ObjectContainers of the project (global,
* layouts...)
* \brief Call the specified worker on all events of the events based behavior
*
* This should be the preferred way to traverse all the events of an events
* based behavior
*/
static void ExposeEventsBasedBehaviorEvents(
gd::Project& project,
const gd::EventsBasedBehavior& eventsBasedBehavior,
gd::ArbitraryEventsWorkerWithContext& worker);
/**
* \brief Call the specified worker on all ObjectContainers of the project
* (global, layouts...)
*
* This should be the preferred way to traverse all the objects of a project.
*/
static void ExposeProjectObjects(
gd::Project& project, gd::ArbitraryObjectsWorker& worker);
static void ExposeProjectObjects(gd::Project& project,
gd::ArbitraryObjectsWorker& worker);
/**
* \brief Refactor the project **before** an events function extension is
@@ -140,13 +158,52 @@ class GD_CORE_API WholeProjectRefactorer {
* This is because the property is expected to have its old name for the
* refactoring.
*/
static void RenameBehaviorProperty(
static void RenameEventsBasedBehaviorProperty(
gd::Project& project,
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
const gd::EventsBasedBehavior& eventsBasedBehavior,
const gd::String& oldPropertyName,
const gd::String& newPropertyName);
/**
* \brief Add a behavior to an object and add required behaviors if necessary
* to fill every behavior properties of the added behaviors.
*/
static void AddBehaviorAndRequiredBehaviors(gd::Project& project,
gd::Object& object,
const gd::String& behaviorType,
const gd::String& behaviorName);
/**
* \brief Find every behavior of the object that needs the given behaviors
* directly or indirectly (because of "required behavior" properties).
*/
static std::vector<gd::String> FindDependentBehaviorNames(
const gd::Project& project,
const gd::Object& object,
const gd::String& behaviorName);
/**
* \brief Find the names of the behaviors with the specified type on the object.
*/
static std::vector<gd::String> GetBehaviorsWithType(const gd::Object& object,
const gd::String& type);
/**
* \brief Find in the project objects having behaviors with "behavior" properties that
* don't have a valid value (i.e: pointing to a non existing behavior, or of a wrong type).
*/
static std::vector<gd::UnfilledRequiredBehaviorPropertyProblem>
FindInvalidRequiredBehaviorProperties(const gd::Project& project);
/**
* \brief Fix in the project objects having behaviors with "behavior" properties that
* don't have a valid value (i.e: pointing to a non existing behavior, or of a wrong type),
* by setting a proper behavior, or adding missing behaviors to these objects.
*/
static bool
FixInvalidRequiredBehaviorProperties(gd::Project& project);
/**
* \brief Refactor the project **before** a behavior is renamed.
*
@@ -267,6 +324,14 @@ class GD_CORE_API WholeProjectRefactorer {
const gd::String& oldBehaviorType,
const gd::String& newBehaviorType);
static void FindDependentBehaviorNames(
const gd::Project& project,
const gd::Object& object,
const gd::String& behaviorName,
std::unordered_set<gd::String>& dependentBehaviorNames);
static const gd::String behaviorObjectParameterName;
WholeProjectRefactorer(){};
};

View File

@@ -36,6 +36,7 @@ void EventsFunctionsExtension::Init(const gd::EventsFunctionsExtension& other) {
fullName = other.fullName;
tags = other.tags;
author = other.author;
authorIds = other.authorIds;
previewIconUrl = other.previewIconUrl;
iconUrl = other.iconUrl;
helpPath = other.helpPath;
@@ -55,6 +56,11 @@ void EventsFunctionsExtension::SerializeTo(SerializerElement& element) const {
for (const auto& tag : tags) {
tagsElement.AddChild("").SetStringValue(tag);
}
auto& authorIdsElement = element.AddChild("authorIds");
authorIdsElement.ConsiderAsArray();
for (const auto& authorId : authorIds) {
authorIdsElement.AddChild("").SetStringValue(authorId);
}
element.SetAttribute("author", author);
element.SetAttribute("previewIconUrl", previewIconUrl);
element.SetAttribute("iconUrl", iconUrl);
@@ -99,6 +105,13 @@ void EventsFunctionsExtension::UnserializeFrom(
}
}
authorIds.clear();
auto& authorIdsElement = element.GetChild("authorIds");
authorIdsElement.ConsiderAsArray();
for (std::size_t i = 0; i < authorIdsElement.GetChildrenCount(); ++i) {
authorIds.push_back(authorIdsElement.GetChild(i).GetStringValue());
}
dependencies.clear();
const auto& dependenciesElement = element.GetChild("dependencies");
dependenciesElement.ConsiderAsArray();

View File

@@ -88,6 +88,9 @@ class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
const std::vector<gd::String>& GetTags() const { return tags; };
std::vector<gd::String>& GetTags() { return tags; };
const std::vector<gd::String>& GetAuthorIds() const { return authorIds; };
std::vector<gd::String>& GetAuthorIds() { return authorIds; };
const gd::String& GetAuthor() const { return author; };
EventsFunctionsExtension& SetAuthor(const gd::String& author_) {
author = author_;
@@ -220,6 +223,7 @@ class GD_CORE_API EventsFunctionsExtension : public EventsFunctionsContainer {
gd::String name;
gd::String fullName;
std::vector<gd::String> tags;
std::vector<gd::String> authorIds;
gd::String author;
gd::String previewIconUrl;
gd::String iconUrl;

View File

@@ -52,12 +52,12 @@ class GD_CORE_API ExtensionProperties {
/**
* \brief Serialize the Extension Properties.
*/
virtual void SerializeTo(SerializerElement& element) const;
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the Extension Properties.
*/
virtual void UnserializeFrom(const SerializerElement& element);
void UnserializeFrom(const SerializerElement& element);
///@}
private:

View File

@@ -1,5 +1,5 @@
#if defined(GD_IDE_ONLY)
#include "GDCore/Project/ExternalEvents.h"
#include "ExternalEvents.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Events/Serialization.h"
@@ -48,4 +48,3 @@ void ExternalEvents::UnserializeFrom(gd::Project& project,
}
} // namespace gd
#endif

View File

@@ -3,12 +3,12 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef GDCORE_EXTERNALEVENTS_H
#define GDCORE_EXTERNALEVENTS_H
#include <ctime>
#include <memory>
#include <vector>
#include "GDCore/Events/EventsList.h"
#include "GDCore/String.h"
namespace gd {
@@ -135,4 +135,3 @@ struct ExternalEventsHasName
} // namespace gd
#endif // GDCORE_EXTERNALEVENTS_H
#endif

View File

@@ -5,6 +5,7 @@
*/
#include "GDCore/Project/ExternalLayout.h"
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
#include "GDCore/Project/InitialInstancesContainer.h"
#include "GDCore/Serialization/SerializerElement.h"
@@ -15,19 +16,15 @@ namespace gd {
void ExternalLayout::UnserializeFrom(const SerializerElement& element) {
name = element.GetStringAttribute("name", "", "Name");
instances.UnserializeFrom(element.GetChild("instances", 0, "Instances"));
#if defined(GD_IDE_ONLY)
editorSettings.UnserializeFrom(element.GetChild("editionSettings"));
#endif
associatedLayout = element.GetStringAttribute("associatedLayout");
}
#if defined(GD_IDE_ONLY)
void ExternalLayout::SerializeTo(SerializerElement& element) const {
element.SetAttribute("name", name);
instances.SerializeTo(element.AddChild("instances"));
editorSettings.SerializeTo(element.AddChild("editionSettings"));
element.SetAttribute("associatedLayout", associatedLayout);
}
#endif
} // namespace gd

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