Compare commits

...

133 Commits

Author SHA1 Message Date
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
Clément Pasteau
e4fc065dc1 Bump newIDE Version 2021-08-12 17:27:30 +02:00
Florian Rival
d1f4d26e49 Fix color of grids in scene editor not properly persisted
* Also make the update real time (any change in the settings are shown directly in the editor)

Don't show the rest in the changelog:

* Add various Flow typings where missing (SetupGridDialog and various InstancesEditor files)
* Serialize the settings into a generic "EditorSetting" (so that the Project is agnostic of any editor related stuff)
* Rename uiSettings/options/LayoutEditorCanvasOptions to InstancesEditorSettings
  * Handle everything inside the IDE (so that the Project remains agnostic of any editor related stuff)

Note that in the future, this kind of EditorSetting that is stored inside the project could be moved to its own structure (living outside of the project file).
2021-08-12 17:05:32 +02:00
ClementPasteau
a1b840a4fa Add Release Ladder action to Platformer Object Behavior (#2892)
Allow a Platformer Object to simulate a "Release Ladder" action
2021-08-12 15:54:19 +02:00
Florian Rival
465629b688 Add a way to set the "extra info" of a parameter without automatic namespace addition for objects/behaviors
Don't show in changelog
2021-08-12 10:28:01 +02:00
ClementPasteau
38758c62c6 Improve Actions and Conditions search allowing typing mistakes (fuzzy) (#2891) 2021-08-11 17:40:20 +02:00
Aurélien Vivet
26f6e95e46 Show previews of image resources properly pixelated when smoothing is deactivated (#2882) 2021-08-09 17:09:58 +02:00
Aurélien Vivet
34abf8290e Bump newIDE version (#2880) 2021-08-07 14:33:54 +02:00
Aurélien Vivet
52677f5512 Show pixel art assets in the asset store as pixelated and larger (#2838) 2021-08-05 20:27:47 +02:00
ClementPasteau
df2b51bb1b Increase the NewIDE tests jest timeout (#2878)
Don't show in changelog
2021-08-05 15:12:52 +02:00
ClementPasteau
6b0ff984f2 Fix Panel Sprite initial opacity not being correctly applied (#2873)
Fix Panel Sprite initial opacity not being correctly applied
2021-08-05 14:25:43 +02:00
D8H
f4512242e4 Add an action to clear the shapes of a Shape Painter object on demand (#2868) 2021-08-04 13:10:29 +02:00
D8H
8beabbadef Add an action to forbid to jump again while in the air to the Platformer behavior. (#2872)
* This is useful if you want to allow to jump again in the air for a bit of time, and then forbid to jump again later (for example, to implement a "Coyote Time" feature to your player character)
2021-08-04 12:29:38 +02:00
Todor Imreorov
9491a8ed45 Fix buttons to save/load/change the file in Piskel sometimes not displayed properly (#2844) 2021-08-04 11:29:35 +02:00
D8H
f945dfd987 Fix an error log when the new instruction dialog opens (#2869)
Don't show in changelog
2021-08-04 09:35:04 +02:00
Florian Rival
ff42591354 Increase the GDJS tests Karma timeout (#2861)
Semaphore CI tests were sometimes timing out, notably the ones involving PixiJS and real resources to load.

Don't show in changelog
2021-08-03 16:20:35 +02:00
D8H
21fb93c66a Improve TypeScript types for the Shape Painter object (#2860)
Only show in developer changelog
2021-08-03 16:17:11 +02:00
Arthur Pacaud
068fbe653a Add new lines between functions back in TS files (#2859)
Only show in developer changelog
2021-08-03 14:35:07 +02:00
Florian Rival
80891dcc59 Fix readme link
[skip ci]
Don't show in changelog
2021-08-02 19:57:24 +02:00
ClementPasteau
34155d65f1 Fix color picker not shown for the action setting the color of a light object (#2857) 2021-08-02 19:01:16 +02:00
Florian Rival
18f22470ca Fix wrong icon shown intermittently in the extensions store 2021-08-01 20:22:24 +02:00
Florian Rival
92a8ebc58b Fix extra scrollbar on small screens when selecting an object or an action/condition in the events sheet 2021-08-01 19:11:29 +02:00
Florian Rival
565384e270 Fix unability to scroll when a lot of parameters were shown for an action or a condition 2021-08-01 19:11:29 +02:00
Florian Rival
8335b2edf9 Add continuous delivery: automatic macOS and Windows builds (#2854)
* This automatically builds the signed macOS app, the Windows exe and AppX, the Linux AppImage.
* This is only for master and any "experimental-build/xxx" branches.
* Only Travis CI and Semaphore CI are running tests, for all branches.
2021-07-31 18:12:19 +02:00
Aurélien Vivet
12c77d0455 Add thumbnails in the resources list (#2842) 2021-07-27 15:59:06 +02:00
Florian Rival
13b62a06eb Add option to allow building Android App Bundles that can be uploaded if you already published APKs with Play App Signing enabled for your game
* If you already opted in for "Play App Signing" in the Play Developer Console and published some APKs like this, you need to enable the new "Old upload key" option, in the Signing Option, before *each* packaging for Android.
* Read this [page to learn more](http://wiki.compilgames.net/doku.php/gdevelop5/publishing/android_and_ios/play-store/upgrading-from-apk-to-aab#done_you_can_now_upload_your_aab) and have step by step details of what to do to update your game.
* If you publish a new game with Android App Bundles, there is nothing to do!
2021-07-22 15:09:58 +01:00
Florian Rival
d27119d8ea Remove deprecated examples upload script from web-app deployment
Don't show in changelog
2021-07-21 17:25:40 +01:00
Florian Rival
dd3ff554d5 Upgrade AppVeyor CI to Node.js 14 (#2826)
[ci skip] [skip ci]
2021-07-20 23:36:56 +01:00
Florian Rival
287a17b634 Add a maximum size for the GDevelop logo so that it's not too big on large resolutions 2021-07-20 18:13:42 +01:00
1635 changed files with 45905 additions and 728268 deletions

View File

@@ -1,9 +1,79 @@
# CircleCI 2.0 configuration file to build GDevelop app running
# on the Electron runtime (newIDE/electron-app).
# CircleCI configuration to build GDevelop app running
# on the Electron runtime (newIDE/electron-app) for macOS and Linux.
# For Windows, see the appveyor.yml file.
version: 2
version: 2.1
jobs:
build:
build-macos:
macos:
xcode: 12.5.1
steps:
- checkout
# System dependencies (for Emscripten and upload)
- run:
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)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# GDevelop.js dependencies
- restore_cache:
keys:
- gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
# fallback to using the latest cache if no exact match is found
- gd-macos-nodejs-dependencies---
- run:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && npm install && cd ..
# Build GDevelop.js (and run tests to ensure it works)
- run:
name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
# GDevelop IDE dependencies (after building GDevelop.js to avoid downloading a pre-built version)
- run:
name: Install GDevelop IDE dependencies
command: cd newIDE/app && npm install && cd ../electron-app && npm install
- save_cache:
paths:
- newIDE/electron-app/node_modules
- newIDE/app/node_modules
- GDevelop.js/node_modules
key: gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
# Note: Code signing is done using CSC_LINK (see https://www.electron.build/code-signing).
- run:
name: Build GDevelop IDE
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --mac --publish=never
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf "newIDE/electron-app/dist/mac/GDevelop 5.app"
# Upload artifacts (CircleCI)
- store_artifacts:
path: newIDE/electron-app/dist
# Upload artifacts (AWS)
- run:
name: Deploy to S3 (specific commit)
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: 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)
resource_class: xlarge
docker:
@@ -23,10 +93,6 @@ jobs:
name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
- run:
name: Install Wine for Electron builder
command: sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt install wine32
- run:
name: Install system dependencies for Electron builder
command: sudo apt install icnsutils && sudo apt install graphicsmagick && sudo apt install rsync
@@ -34,15 +100,15 @@ jobs:
# GDevelop.js dependencies
- restore_cache:
keys:
- gd-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
- gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
# fallback to using the latest cache if no exact match is found
- gd-nodejs-dependencies---
- gd-linux-nodejs-dependencies---
- run:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && sudo npm install -g grunt-cli && npm install && cd ..
command: cd GDevelop.js && npm install && cd ..
# Build GDevelop.js
# Build GDevelop.js (and run tests to ensure it works)
- run:
name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
@@ -57,16 +123,16 @@ jobs:
- newIDE/electron-app/node_modules
- newIDE/app/node_modules
- GDevelop.js/node_modules
key: gd-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}
key: gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
- run:
name: Build GDevelop IDE
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --mac zip --win --linux tar.gz --publish=never
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --linux AppImage --publish=never
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf newIDE/electron-app/dist/linux-unpacked && rm -rf newIDE/electron-app/dist/win-unpacked && rm -rf newIDE/electron-app/dist/mac
command: rm -rf newIDE/electron-app/dist/linux-unpacked
# Upload artifacts (CircleCI)
- store_artifacts:
@@ -79,3 +145,20 @@ jobs:
- run:
name: Deploy to S3 (latest)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
workflows:
builds:
jobs:
- build-macos:
filters:
branches:
only:
- master
- /experimental-build.*/
- build-linux:
filters:
branches:
only:
- master
- /experimental-build.*/

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

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."

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,3 +1,12 @@
# Travis CI configuration to build and run all tests
# (and typing/formatting) for the Core, newIDE, GDJS.
#
# This builds GDevelop.js and store it on a S3 so it can be used to run
# GDevelop without building it.
#
# See also Semaphore CI for quick tests (not building GDevelop.js, so
# faster but not always reliable).
language: cpp
sudo: false
compiler:
@@ -53,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) ..
@@ -80,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
@@ -96,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,

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

@@ -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."),
@@ -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,7 +23,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/keyboard");
#if defined(GD_IDE_ONLY)
extension
.AddCondition("KeyPressed",
_("Key pressed"),
@@ -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",
@@ -303,7 +302,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"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",
@@ -213,7 +212,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.AddParameter("relationalOperator", _("Sign of the test"))
.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

@@ -275,6 +275,76 @@ BehaviorMetadata::AddExpressionAndConditionAndAction(
expression, condition, action);
}
#if defined(GD_IDE_ONLY)
gd::InstructionMetadata& BehaviorMetadata::AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName) {
gd::String newNameWithNamespace = extensionNamespace + newActionName;
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& BehaviorMetadata::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];
}
gd::ExpressionMetadata& BehaviorMetadata::AddDuplicatedExpression(
const gd::String& newExpressionName,
const gd::String& copiedExpressionName) {
gd::String newNameWithNamespace = extensionNamespace + newExpressionName;
gd::String copiedNameWithNamespace =
extensionNamespace + copiedExpressionName;
auto copiedExpression = expressionsInfos.find(copiedNameWithNamespace);
if (copiedExpression == expressionsInfos.end()) {
gd::LogWarning("Could not find an expression with name " +
copiedNameWithNamespace + " to copy.");
} else {
expressionsInfos[newNameWithNamespace] = copiedExpression->second;
}
return expressionsInfos[newNameWithNamespace];
}
gd::ExpressionMetadata& BehaviorMetadata::AddDuplicatedStrExpression(
const gd::String& newExpressionName,
const gd::String& copiedExpressionName) {
gd::String newNameWithNamespace = extensionNamespace + newExpressionName;
gd::String copiedNameWithNamespace =
extensionNamespace + copiedExpressionName;
auto copiedExpression = strExpressionsInfos.find(copiedNameWithNamespace);
if (copiedExpression == strExpressionsInfos.end()) {
gd::LogWarning("Could not find a string expression with name " +
copiedNameWithNamespace + " to copy.");
} else {
strExpressionsInfos[newNameWithNamespace] = copiedExpression->second;
}
return strExpressionsInfos[newNameWithNamespace];
}
#endif
BehaviorMetadata& BehaviorMetadata::SetFullName(const gd::String& fullname_) {
#if defined(GD_IDE_ONLY)
fullname = fullname_;
@@ -323,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

@@ -138,6 +138,46 @@ class GD_CORE_API BehaviorMetadata {
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 Create a new expression which is the duplicate of the specified one.
*
* Useful for handling a deprecated expression that is just a "copy" of the
* new one.
*/
gd::ExpressionMetadata& AddDuplicatedExpression(
const gd::String& newExpressionName,
const gd::String& copiedExpressionName);
/**
* \brief Create a new string expression which is the duplicate of the
* specified one.
*
* Useful for handling a deprecated string expression that is just a "copy" of
* the new one.
*/
gd::ExpressionMetadata& AddDuplicatedStrExpression(
const gd::String& newExpressionName,
const gd::String& copiedExpressionName);
BehaviorMetadata& SetFullName(const gd::String& fullname_);
BehaviorMetadata& SetDefaultName(const gd::String& defaultName_);
BehaviorMetadata& SetDescription(const gd::String& description_);
@@ -200,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

@@ -187,6 +187,19 @@ class GD_CORE_API InstructionMetadata {
return *this;
};
/**
* \brief Set the additional information, used for some parameters
* with special type (for example, it can contains the type of object accepted
* by the parameter), for the last added parameter.
*
* \see AddParameter
*/
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty())
parameters.back().SetExtraInfo(extraInfo);
return *this;
};
/**
* \brief Add the default parameters for an instruction manipulating the
* specified type ("string", "number") with the default operators.
@@ -221,14 +234,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;
}

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

@@ -68,14 +68,14 @@ class GD_CORE_API ParameterMetadata {
/**
* \brief Return an optional additional information, used for some parameters
* with special type (For example, it can contains the type of object accepted
* with special type (for example, it can contains the type of object accepted
* by the parameter).
*/
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
/**
* \brief Set an optional additional information, used for some parameters
* with special type (For example, it can contains the type of object accepted
* with special type (for example, it can contains the type of object accepted
* by the parameter).
*/
ParameterMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
@@ -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,25 @@
/*
* GDevelop Core
* 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)
#include "GDCore/CommonTools.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "EditorSettings.h"
namespace gd {
EditorSettings::EditorSettings() {}
void EditorSettings::SerializeTo(SerializerElement& element) const {
element = content;
}
void EditorSettings::UnserializeFrom(
const SerializerElement& element) {
content = element;
}
} // namespace gd
#endif

View File

@@ -0,0 +1,46 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef SCENECANVASSETTINGS_H
#define SCENECANVASSETTINGS_H
#include "GDCore/String.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
/**
* \brief Container for arbitrary serialized data to be used by the editor
* to store settings.
*
* \see Scene
*/
class GD_CORE_API EditorSettings {
public:
EditorSettings();
virtual ~EditorSettings(){};
/** \name Serialization
*/
///@{
/**
* \brief Serialize the settings.
*/
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the settings.
*/
void UnserializeFrom(const SerializerElement& element);
///@}
private:
gd::SerializerElement content; ///< Arbitrary content, depending on the editor.
};
} // namespace gd
#endif // SCENECANVASSETTINGS_H
#endif

View File

@@ -1,59 +0,0 @@
/*
* GDevelop Core
* 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)
#include "LayoutEditorCanvasOptions.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Serialization/SerializerElement.h"
namespace gd {
LayoutEditorCanvasOptions::LayoutEditorCanvasOptions()
: grid(false),
snap(true),
gridWidth(32),
gridHeight(32),
gridOffsetX(0),
gridOffsetY(0),
gridType("rectangular"),
gridR(158),
gridG(180),
gridB(255),
zoomFactor(1),
windowMask(false) {}
void LayoutEditorCanvasOptions::SerializeTo(SerializerElement& element) const {
element.SetAttribute("grid", grid);
element.SetAttribute("snap", snap);
element.SetAttribute("gridWidth", gridWidth);
element.SetAttribute("gridHeight", gridHeight);
element.SetAttribute("gridOffsetX", gridOffsetX);
element.SetAttribute("gridOffsetY", gridOffsetY);
element.SetAttribute("gridType", gridType);
element.SetAttribute("gridR", gridR);
element.SetAttribute("gridG", gridG);
element.SetAttribute("gridB", gridB);
element.SetAttribute("zoomFactor", zoomFactor);
element.SetAttribute("windowMask", windowMask);
}
void LayoutEditorCanvasOptions::UnserializeFrom(
const SerializerElement& element) {
grid = element.GetBoolAttribute("grid");
snap = element.GetBoolAttribute("snap");
windowMask = element.GetBoolAttribute("windowMask");
gridWidth = element.GetDoubleAttribute("gridWidth", 32);
gridHeight = element.GetDoubleAttribute("gridHeight", 32);
gridOffsetX = element.GetDoubleAttribute("gridOffsetX", 0);
gridOffsetY = element.GetDoubleAttribute("gridOffsetY", 0);
gridType = element.GetStringAttribute("gridType", "rectangular");
gridR = element.GetIntAttribute("gridR", 158);
gridG = element.GetIntAttribute("gridG", 180);
gridB = element.GetIntAttribute("gridB", 255);
zoomFactor = element.GetDoubleAttribute("zoomFactor", 1.0);
}
} // namespace gd
#endif

View File

@@ -1,58 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#if defined(GD_IDE_ONLY)
#ifndef SCENECANVASSETTINGS_H
#define SCENECANVASSETTINGS_H
#include "GDCore/String.h"
namespace gd {
class SerializerElement;
}
namespace gd {
/**
* \brief Tool class used to store settings of a LayoutEditorCanvas.
*
* \see Scene
*/
class GD_CORE_API LayoutEditorCanvasOptions {
public:
LayoutEditorCanvasOptions();
virtual ~LayoutEditorCanvasOptions(){};
/** \name Serialization
*/
///@{
/**
* \brief Serialize instances container.
*/
void SerializeTo(SerializerElement& element) const;
/**
* \brief Unserialize the instances container.
*/
void UnserializeFrom(const SerializerElement& element);
///@}
bool grid; ///< True if grid activated in editor
bool snap; ///< True if snap to grid activated in editor
double gridWidth; ///< Grid width in editor
double gridHeight; ///< Grid height in editor
double gridOffsetX; ///< Grid X offset
double gridOffsetY; ///< Grid Y offset
gd::String gridType; ///< Grid type: rectangular or isometric
int gridR; ///< Grid red color in editor
int gridG; ///< Grid green color in editor
int gridB; ///< Grid blue color in editor
double zoomFactor; ///< Stores the zoom factor
bool windowMask; ///< True if window mask displayed in editor
};
} // namespace gd
#endif // SCENECANVASSETTINGS_H
#endif

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,17 +5,19 @@
*/
#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"
using namespace std;
@@ -31,10 +33,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 +78,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 +116,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 +158,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 +192,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 +203,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 +249,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 +261,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 +311,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 +321,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 +355,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 +390,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 +403,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 +415,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 +453,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 +467,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 +479,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;
@@ -781,10 +810,10 @@ bool EventsRefactorer::SearchStringInConditions(
}
bool EventsRefactorer::SearchStringInEvent(gd::ObjectsContainer& project,
gd::ObjectsContainer& layout,
gd::BaseEvent& event,
gd::String search,
bool matchCase) {
gd::ObjectsContainer& layout,
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

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

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

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

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

View File

@@ -13,7 +13,7 @@ namespace gd {
class SerializerElement;
}
#if defined(GD_IDE_ONLY)
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
#endif
namespace gd {
@@ -58,15 +58,15 @@ class GD_CORE_API ExternalLayout {
/**
* \brief Get the user settings for the IDE.
*/
const gd::LayoutEditorCanvasOptions& GetAssociatedSettings() const {
return editionSettings;
const gd::EditorSettings& GetAssociatedEditorSettings() const {
return editorSettings;
}
/**
* \brief Get the user settings for the IDE.
*/
gd::LayoutEditorCanvasOptions& GetAssociatedSettings() {
return editionSettings;
gd::EditorSettings& GetAssociatedEditorSettings() {
return editorSettings;
}
#endif
@@ -100,7 +100,7 @@ class GD_CORE_API ExternalLayout {
gd::String name;
gd::InitialInstancesContainer instances;
#if defined(GD_IDE_ONLY)
gd::LayoutEditorCanvasOptions editionSettings;
gd::EditorSettings editorSettings;
#endif
gd::String associatedLayout;
};

View File

@@ -1,213 +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 "GDCore/Project/ImageManager.h"
#include <SFML/OpenGL.hpp>
#include "GDCore/Project/ResourcesLoader.h"
#include "GDCore/Project/ResourcesManager.h"
#include "GDCore/Tools/InvalidImage.h"
#if !defined(ANDROID) && !defined(MACOS)
#include <GL/glu.h>
#endif
#undef LoadImage // thx windows.h
namespace gd {
ImageManager::ImageManager() : resourcesManager(NULL) {
#if !defined(EMSCRIPTEN)
badTexture = std::make_shared<SFMLTextureWrapper>();
badTexture->texture.loadFromMemory(gd::InvalidImageData,
sizeof(gd::InvalidImageData));
badTexture->texture.setSmooth(false);
badTexture->image = badTexture->texture.copyToImage();
#endif
}
std::shared_ptr<SFMLTextureWrapper> ImageManager::GetSFMLTexture(
const gd::String& name) const {
if (!resourcesManager) {
std::cout << "ImageManager has no ResourcesManager associated with.";
return badTexture;
}
if (alreadyLoadedImages.find(name) != alreadyLoadedImages.end() &&
!alreadyLoadedImages.find(name)->second.expired())
return alreadyLoadedImages.find(name)->second.lock();
std::cout << "ImageManager: Loading " << name << ".";
// Load only an image when necessary
try {
ImageResource& image =
dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
auto texture = std::make_shared<SFMLTextureWrapper>();
ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), texture->image);
texture->texture.loadFromImage(texture->image);
texture->texture.setSmooth(image.smooth);
alreadyLoadedImages[name] = texture;
#if defined(GD_IDE_ONLY)
if (preventUnloading)
unloadingPreventer.push_back(
texture); // If unload prevention is activated, add the image to the
// list dedicated to prevent images from being unloaded.
#endif
return texture;
} catch (...) {
}
std::cout << " Resource not found." << std::endl;
return badTexture;
}
bool ImageManager::HasLoadedSFMLTexture(const gd::String& name) const {
if (alreadyLoadedImages.find(name) != alreadyLoadedImages.end() &&
!alreadyLoadedImages.find(name)->second.expired())
return true;
return false;
}
void ImageManager::SetSFMLTextureAsPermanentlyLoaded(
const gd::String& name,
std::shared_ptr<SFMLTextureWrapper>& texture) const {
if (alreadyLoadedImages.find(name) == alreadyLoadedImages.end() ||
alreadyLoadedImages.find(name)->second.expired())
alreadyLoadedImages[name] = texture;
if (permanentlyLoadedImages.find(name) == permanentlyLoadedImages.end())
permanentlyLoadedImages[name] = texture;
}
void ImageManager::ReloadImage(const gd::String& name) const {
if (!resourcesManager) {
std::cout << "ImageManager has no ResourcesManager associated with.";
return;
}
// Verify if image is in memory. If not, it will be automatically reloaded
// when necessary.
if (alreadyLoadedImages.find(name) == alreadyLoadedImages.end() ||
alreadyLoadedImages.find(name)->second.expired())
return;
// Image still in memory, get it and update it.
std::shared_ptr<SFMLTextureWrapper> oldTexture =
alreadyLoadedImages.find(name)->second.lock();
try {
ImageResource& image =
dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
std::cout << "ImageManager: Reload " << name << std::endl;
ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), oldTexture->image);
oldTexture->texture.loadFromImage(oldTexture->image);
oldTexture->texture.setSmooth(image.smooth);
return;
} catch (...) { /*The ressource is not an image*/
}
// Image not present anymore in image list.
std::cout << "ImageManager: " << name << " is not available anymore."
<< std::endl;
*oldTexture = *badTexture;
}
std::shared_ptr<OpenGLTextureWrapper> ImageManager::GetOpenGLTexture(
const gd::String& name) const {
if (alreadyLoadedOpenGLTextures.find(name) !=
alreadyLoadedOpenGLTextures.end() &&
!alreadyLoadedOpenGLTextures.find(name)->second.expired())
return alreadyLoadedOpenGLTextures.find(name)->second.lock();
std::cout << "Load OpenGL Texture" << name << std::endl;
std::shared_ptr<OpenGLTextureWrapper> texture =
std::make_shared<OpenGLTextureWrapper>(GetSFMLTexture(name));
alreadyLoadedOpenGLTextures[name] = texture;
return texture;
}
void ImageManager::LoadPermanentImages() {
if (!resourcesManager) {
std::cout << "ImageManager has no ResourcesManager associated with.";
return;
}
// Create a new list of permanently loaded images but do not delete now the
// old list so as not to unload images that could be still present.
std::map<gd::String, std::shared_ptr<SFMLTextureWrapper> >
newPermanentlyLoadedImages;
std::vector<gd::String> resources = resourcesManager->GetAllResourceNames();
for (std::size_t i = 0; i < resources.size(); i++) {
try {
ImageResource& image = dynamic_cast<ImageResource&>(
resourcesManager->GetResource(resources[i]));
if (image.alwaysLoaded)
newPermanentlyLoadedImages[image.GetName()] =
GetSFMLTexture(image.GetName());
} catch (...) { /*The resource is not an image, we don't care about it.*/
}
}
permanentlyLoadedImages = newPermanentlyLoadedImages;
}
#if defined(GD_IDE_ONLY)
void ImageManager::PreventImagesUnloading() {
preventUnloading = true;
for (auto it = alreadyLoadedImages.begin(); it != alreadyLoadedImages.end();
++it) {
std::shared_ptr<SFMLTextureWrapper> image = (it->second).lock();
if (image != std::shared_ptr<SFMLTextureWrapper>())
unloadingPreventer.push_back(image);
}
}
void ImageManager::EnableImagesUnloading() {
preventUnloading = false;
unloadingPreventer
.clear(); // Images which are not used anymore will thus be destroyed (As
// no shared pointer will be pointing to them).
}
#endif
} // namespace gd
SFMLTextureWrapper::SFMLTextureWrapper(const sf::Texture& texture_)
: texture(texture_), image(texture.copyToImage()) {}
SFMLTextureWrapper::SFMLTextureWrapper() {}
SFMLTextureWrapper::~SFMLTextureWrapper() {}
OpenGLTextureWrapper::OpenGLTextureWrapper(
std::shared_ptr<SFMLTextureWrapper> sfmlTexture_) {
sfmlTexture = sfmlTexture_;
#if !defined(ANDROID) // TODO: OpenGL
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sfmlTexture->image.getSize().x,
// sfmlTexture->image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
// sfmlTexture->image.getPixelsPtr()); glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
#endif
}
OpenGLTextureWrapper::~OpenGLTextureWrapper() {
#if !defined(ANDROID) // TODO: OpenGL
glDeleteTextures(1, &texture);
#endif
};

View File

@@ -1,185 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef ImageManager_H
#define ImageManager_H
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/System.hpp>
#include <iostream>
#include <memory>
#include <vector>
#include "GDCore/String.h"
namespace gd {
class ResourcesManager;
}
class OpenGLTextureWrapper;
class SFMLTextureWrapper;
#undef LoadImage // thx windows.h
namespace gd {
/**
* \brief Manage images for the IDE as well as at runtime for GD C++ Platform,
* providing an easy way to get SFML images or OpenGL textures.
*
* Image manager is used by objects to obtain their images from the image name.
*
* Images are loaded dynamically when necessary, and are unloaded if there is no
* more shared_ptr pointing on an image.
*
* You should in particular be interested by gd::ImageManager::GetOpenGLTexture
* and gd::ImageManager::GetSFMLTexture.
*
* \see SFMLTextureWrapper
* \see OpenGLTextureWrapper
*
* \ingroup ResourcesManagement
*/
class GD_CORE_API ImageManager {
public:
ImageManager();
virtual ~ImageManager(){};
/**
* \brief Get a shared pointer to an OpenGL texture. The shared pointer must
* be kept alive as long as the texture is used.
*/
std::shared_ptr<OpenGLTextureWrapper> GetOpenGLTexture(
const gd::String& name) const;
/**
* \brief Get a shared pointer to a SFML texture. The shared pointer must be
* kept alive as long as the texture is used.
*
* For example, if the texture is used in an object, you should store the
* shared pointer in a member to make sure the texture is available as long as
* the object is alive.
*/
std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture(
const gd::String& name) const;
/**
* \brief Set the gd::ResourcesManager used by the ImageManager.
*/
void SetResourcesManager(gd::ResourcesManager* resourcesManager_) {
resourcesManager = resourcesManager_;
}
/**
* \brief Load all images of the project which are flagged as alwaysLoaded.
* \see ImageResource
*/
void LoadPermanentImages();
/**
* \brief Check if a SFML texture with the specified name is available and
* loaded in memory. \return true if the texture called \a name if available
* and loaded in memory.
*/
bool HasLoadedSFMLTexture(const gd::String& name) const;
/**
* \brief Add the SFMLTextureWrapper to loaded images ( so that it can be
* accessed thanks to ImageManager::GetSFMLTexture ) with the specified name
* and mark it as permanently loaded ( so that is is unloaded only when the
* layout is unloaded ).
*/
void SetSFMLTextureAsPermanentlyLoaded(
const gd::String& name,
std::shared_ptr<SFMLTextureWrapper>& texture) const;
/**
* \brief Reload a single image from the game resources
*/
void ReloadImage(const gd::String& name) const;
#if defined(GD_IDE_ONLY)
/**
* \brief When called, images won't be unloaded from memory until
* EnableImagesUnloading is called. Can be used when reloading a layout so as
* to prevent images from being unloaded and then immediately reloaded.
*/
void PreventImagesUnloading();
/**
* \brief Enable again unused images to be unloaded from memory.
*/
void EnableImagesUnloading();
#endif
private:
mutable std::map<gd::String, std::weak_ptr<SFMLTextureWrapper> >
alreadyLoadedImages; ///< Reference all images loaded in memory.
mutable std::map<gd::String, std::shared_ptr<SFMLTextureWrapper> >
permanentlyLoadedImages; ///< Contains (smart) pointers to images which
///< should stay loaded even if they are not
///< (currently) used.
#if defined(GD_IDE_ONLY)
/** This list is filled, when PreventImagesUnloading is called, with images
* already loaded in memory ( and any image loaded after the call to
* PreventImagesUnloading ). It will thus prevent these images from being
* unloaded. This list is destroyed when EnableImagesUnloading is called.
*
* \see PreventImagesUnloading
* \see EnableImagesUnloading
*/
mutable std::vector<std::shared_ptr<SFMLTextureWrapper> > unloadingPreventer;
bool preventUnloading; ///< True if no images must be currently unloaded.
#endif
mutable std::map<gd::String, std::weak_ptr<OpenGLTextureWrapper> >
alreadyLoadedOpenGLTextures; ///< Reference all OpenGL textures loaded in
///< memory.
mutable std::shared_ptr<SFMLTextureWrapper> badTexture;
mutable std::shared_ptr<OpenGLTextureWrapper> badOpenGLTexture;
gd::ResourcesManager* resourcesManager;
};
} // namespace gd
/**
* \brief Class wrapping an SFML texture.
*
* \see gd::ImageManager
* \ingroup ResourcesManagement
*/
class GD_CORE_API SFMLTextureWrapper {
public:
SFMLTextureWrapper(const sf::Texture& texture);
SFMLTextureWrapper();
~SFMLTextureWrapper();
sf::Texture texture;
sf::Image image; ///< Associated sfml image, used for pixel perfect collision
///< for example. If you update the image, call
///< LoadFromImage on texture to update it also.
};
/**
* \brief Class wrapping an OpenGL texture.
*
* \see gd::ImageManager
* \ingroup ResourcesManagement
*/
class GD_CORE_API OpenGLTextureWrapper {
public:
OpenGLTextureWrapper(std::shared_ptr<SFMLTextureWrapper> sfmlTexture_);
OpenGLTextureWrapper() : texture(0){};
~OpenGLTextureWrapper();
inline GLuint GetOpenGLTexture() const { return texture; }
private:
std::shared_ptr<SFMLTextureWrapper> sfmlTexture;
GLuint texture;
};
#endif // ImageManager_H

View File

@@ -272,7 +272,7 @@ void Layout::SerializeTo(SerializerElement& element) const {
disableInputWhenNotFocused);
#if defined(GD_IDE_ONLY)
GetAssociatedSettings().SerializeTo(element.AddChild("uiSettings"));
editorSettings.SerializeTo(element.AddChild("uiSettings"));
#endif
GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
@@ -333,7 +333,7 @@ void Layout::UnserializeFrom(gd::Project& project,
element.GetBoolAttribute("disableInputWhenNotFocused");
#if defined(GD_IDE_ONLY)
associatedSettings.UnserializeFrom(
editorSettings.UnserializeFrom(
element.GetChild("uiSettings", 0, "UISettings"));
GetObjectGroups().UnserializeFrom(
@@ -412,7 +412,7 @@ void Layout::Init(const Layout& other) {
#if defined(GD_IDE_ONLY)
events = other.events;
associatedSettings = other.associatedSettings;
editorSettings = other.editorSettings;
objectGroups = other.objectGroups;
profiler = other.profiler;

View File

@@ -18,7 +18,7 @@
#include "GDCore/Project/VariablesContainer.h"
#include "GDCore/String.h"
#if defined(GD_IDE_ONLY)
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
#endif
namespace gd {
class BaseEvent;
@@ -291,18 +291,18 @@ class GD_CORE_API Layout : public ObjectsContainer {
#if defined(GD_IDE_ONLY)
/**
* Return the settings associated to the layout.
* \see gd::LayoutEditorCanvasOptions
* \see gd::EditorSettings
*/
const gd::LayoutEditorCanvasOptions& GetAssociatedSettings() const {
return associatedSettings;
const gd::EditorSettings& GetAssociatedEditorSettings() const {
return editorSettings;
}
/**
* Return the settings associated to the layout.
* \see gd::LayoutEditorCanvasOptions
* \see gd::EditorSettings
*/
gd::LayoutEditorCanvasOptions& GetAssociatedSettings() {
return associatedSettings;
gd::EditorSettings& GetAssociatedEditorSettings() {
return editorSettings;
}
#endif
@@ -436,7 +436,7 @@ class GD_CORE_API Layout : public ObjectsContainer {
///< specified behavior shared data.
#if defined(GD_IDE_ONLY)
EventsList events; ///< Scene events
gd::LayoutEditorCanvasOptions associatedSettings;
gd::EditorSettings editorSettings;
#endif
// TODO: GD C++ Platform specific code below

View File

@@ -50,6 +50,10 @@ class GD_CORE_API LoadingScreen {
return backgroundImageResourceName;
};
gd::String& GetBackgroundImageResourceName() {
return backgroundImageResourceName;
};
LoadingScreen& SetBackgroundImageResourceName(const gd::String& value) {
backgroundImageResourceName = value;
return *this;

View File

@@ -70,12 +70,6 @@ class GD_CORE_API NamedPropertyDescriptor : public PropertyDescriptor {
virtual void UnserializeValuesFrom(const SerializerElement& element);
///@}
/**
* Return a PropertyDescriptor from this NamedPropertyDescriptor,
* slicing the name.
*/
PropertyDescriptor ToPropertyDescriptor() { return PropertyDescriptor(*this); }
private:
gd::String name; ///< The name of the property.
};

View File

@@ -87,7 +87,6 @@ class GD_CORE_API ObjectsContainer {
*/
std::size_t GetObjectsCount() const;
#if defined(GD_IDE_ONLY)
/**
* \brief Add a new empty object of type \a objectType called \a name at the
* specified position in the list.<br>
@@ -99,7 +98,6 @@ class GD_CORE_API ObjectsContainer {
const gd::String& objectType,
const gd::String& name,
std::size_t position);
#endif
/**
* \brief Add a new object to the list
@@ -176,7 +174,6 @@ class GD_CORE_API ObjectsContainer {
*/
///@{
#if defined(GD_IDE_ONLY)
/**
* \brief Return a reference to the project's objects groups.
*/
@@ -186,7 +183,6 @@ class GD_CORE_API ObjectsContainer {
* \brief Return a const reference to the project's objects groups.
*/
const ObjectGroupsContainer& GetObjectGroups() const { return objectGroups; }
#endif
///@}

View File

@@ -26,7 +26,6 @@
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/Project/ExternalEvents.h"
#include "GDCore/Project/ExternalLayout.h"
#include "GDCore/Project/ImageManager.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/ObjectGroupsContainer.h"
@@ -50,41 +49,27 @@ using namespace std;
namespace gd {
Project::Project()
:
#if defined(GD_IDE_ONLY)
name(_("Project")),
: name(_("Project")),
version("1.0.0"),
packageName("com.example.gamename"),
orientation("landscape"),
folderProject(false),
#endif
windowWidth(800),
windowHeight(600),
maxFPS(60),
minFPS(20),
verticalSync(false),
scaleMode("linear"),
pixelsRounding(false),
adaptGameResolutionAtRuntime(true),
sizeOnStartupMode("adaptWidth"),
projectUuid(""),
useDeprecatedZeroAsDefaultZOrder(false),
imageManager(std::make_shared<ImageManager>())
#if defined(GD_IDE_ONLY)
,
useExternalSourceFiles(false),
currentPlatform(NULL),
gdMajorVersion(gd::VersionWrapper::Major()),
gdMinorVersion(gd::VersionWrapper::Minor()),
gdBuildVersion(gd::VersionWrapper::Build()),
dirty(false)
#endif
{
imageManager->SetResourcesManager(&resourcesManager);
#if !defined(GD_IDE_ONLY)
platforms.push_back(&CppPlatform::Get());
#endif
}
gdBuildVersion(gd::VersionWrapper::Build()) {}
Project::~Project() {}
@@ -109,7 +94,6 @@ std::unique_ptr<gd::Object> Project::CreateObject(
return nullptr;
}
#if defined(GD_IDE_ONLY)
std::shared_ptr<gd::BaseEvent> Project::CreateEvent(
const gd::String& type, const gd::String& platformName) {
for (std::size_t i = 0; i < platforms.size(); ++i) {
@@ -168,7 +152,6 @@ bool Project::RemovePlatform(const gd::String& platformName) {
return false;
}
#endif
bool Project::HasLayoutNamed(const gd::String& name) const {
return (find_if(scenes.begin(),
@@ -195,13 +178,11 @@ std::size_t Project::GetLayoutPosition(const gd::String& name) const {
}
std::size_t Project::GetLayoutsCount() const { return scenes.size(); }
#if defined(GD_IDE_ONLY)
void Project::SwapLayouts(std::size_t first, std::size_t second) {
if (first >= scenes.size() || second >= scenes.size()) return;
std::iter_swap(scenes.begin() + first, scenes.begin() + second);
}
#endif
gd::Layout& Project::InsertNewLayout(const gd::String& name,
std::size_t position) {
@@ -210,9 +191,7 @@ gd::Layout& Project::InsertNewLayout(const gd::String& name,
new Layout())));
newlyInsertedLayout.SetName(name);
#if defined(GD_IDE_ONLY)
newlyInsertedLayout.UpdateBehaviorsSharedData(*this);
#endif
return newlyInsertedLayout;
}
@@ -223,9 +202,7 @@ gd::Layout& Project::InsertLayout(const gd::Layout& layout,
position < scenes.size() ? scenes.begin() + position : scenes.end(),
new Layout(layout))));
#if defined(GD_IDE_ONLY)
newlyInsertedLayout.UpdateBehaviorsSharedData(*this);
#endif
return newlyInsertedLayout;
}
@@ -238,7 +215,6 @@ void Project::RemoveLayout(const gd::String& name) {
scenes.erase(scene);
}
#if defined(GD_IDE_ONLY)
bool Project::HasExternalEventsNamed(const gd::String& name) const {
return (find_if(externalEvents.begin(),
externalEvents.end(),
@@ -318,7 +294,6 @@ void Project::SwapExternalLayouts(std::size_t first, std::size_t second) {
std::iter_swap(externalLayouts.begin() + first,
externalLayouts.begin() + second);
}
#endif
bool Project::HasExternalLayoutNamed(const gd::String& name) const {
return (find_if(externalLayouts.begin(),
externalLayouts.end(),
@@ -384,7 +359,6 @@ void Project::RemoveExternalLayout(const gd::String& name) {
externalLayouts.erase(externalLayout);
}
#if defined(GD_IDE_ONLY)
void Project::SwapEventsFunctionsExtensions(std::size_t first,
std::size_t second) {
if (first >= eventsFunctionsExtensions.size() ||
@@ -483,11 +457,8 @@ void Project::RemoveEventsFunctionsExtension(const gd::String& name) {
void Project::ClearEventsFunctionsExtensions() {
eventsFunctionsExtensions.clear();
}
#endif
void Project::UnserializeFrom(const SerializerElement& element) {
// Checking version
#if defined(GD_IDE_ONLY)
const SerializerElement& gdVersionElement =
element.GetChild("gdVersion", 0, "GDVersion");
gdMajorVersion =
@@ -520,7 +491,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
"available.");
}
}
#endif
const SerializerElement& propElement =
element.GetChild("properties", 0, "Info");
@@ -536,11 +506,11 @@ void Project::UnserializeFrom(const SerializerElement& element) {
SetVerticalSyncActivatedByDefault(
propElement.GetChild("verticalSync").GetValue().GetBool());
SetScaleMode(propElement.GetStringAttribute("scaleMode", "linear"));
SetPixelsRounding(propElement.GetBoolAttribute("pixelsRounding", false));
SetAdaptGameResolutionAtRuntime(
propElement.GetBoolAttribute("adaptGameResolutionAtRuntime", false));
SetSizeOnStartupMode(propElement.GetStringAttribute("sizeOnStartupMode", ""));
SetProjectUuid(propElement.GetStringAttribute("projectUuid", ""));
#if defined(GD_IDE_ONLY)
SetAuthor(propElement.GetChild("author", 0, "Auteur").GetValue().GetString());
SetPackageName(propElement.GetStringAttribute("packageName"));
SetOrientation(propElement.GetStringAttribute("orientation", "default"));
@@ -558,6 +528,13 @@ void Project::UnserializeFrom(const SerializerElement& element) {
useExternalSourceFiles =
propElement.GetBoolAttribute("useExternalSourceFiles");
authorIds.clear();
auto& authorIdsElement = propElement.GetChild("authorIds");
authorIdsElement.ConsiderAsArray();
for (std::size_t i = 0; i < authorIdsElement.GetChildrenCount(); ++i) {
authorIds.push_back(authorIdsElement.GetChild(i).GetStringValue());
}
// Compatibility with GD <= 5.0.0-beta101
if (VersionWrapper::IsOlderOrEqual(
gdMajorVersion, gdMinorVersion, gdBuildVersion, 0, 4, 0, 98, 0) &&
@@ -589,9 +566,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
}
// end of compatibility code
#endif
#if defined(GD_IDE_ONLY)
currentPlatform = NULL;
gd::String currentPlatformName =
propElement.GetChild("currentPlatform").GetValue().GetString();
@@ -641,12 +615,9 @@ void Project::UnserializeFrom(const SerializerElement& element) {
if (currentPlatform == NULL && !platforms.empty())
currentPlatform = platforms.back();
#endif
#if defined(GD_IDE_ONLY)
GetObjectGroups().UnserializeFrom(
element.GetChild("objectsGroups", 0, "ObjectGroups"));
#endif
resourcesManager.UnserializeFrom(
element.GetChild("resources", 0, "Resources"));
UnserializeObjectsFrom(*this, element.GetChild("objects", 0, "Objects"));
@@ -664,7 +635,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
layout.UnserializeFrom(*this, layoutElement);
}
#if defined(GD_IDE_ONLY)
externalEvents.clear();
const SerializerElement& externalEventsElement =
element.GetChild("externalEvents", 0, "ExternalEvents");
@@ -696,7 +666,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
newEventsFunctionsExtension.UnserializeFrom(
*this, eventsFunctionsExtensionElement);
}
#endif
externalLayouts.clear();
const SerializerElement& externalLayoutsElement =
@@ -711,7 +680,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
newExternalLayout.UnserializeFrom(externalLayoutElement);
}
#if defined(GD_IDE_ONLY)
externalSourceFiles.clear();
const SerializerElement& externalSourceFilesElement =
element.GetChild("externalSourceFiles", 0, "ExternalSourceFiles");
@@ -724,10 +692,8 @@ void Project::UnserializeFrom(const SerializerElement& element) {
gd::SourceFile& newSourceFile = InsertNewSourceFile("", "");
newSourceFile.UnserializeFrom(sourceFileElement);
}
#endif
}
#if defined(GD_IDE_ONLY)
void Project::SerializeTo(SerializerElement& element) const {
SerializerElement& versionElement = element.AddChild("gdVersion");
versionElement.SetAttribute("major", gd::VersionWrapper::Major());
@@ -748,6 +714,7 @@ void Project::SerializeTo(SerializerElement& element) const {
propElement.AddChild("verticalSync")
.SetValue(IsVerticalSynchronizationEnabledByDefault());
propElement.SetAttribute("scaleMode", scaleMode);
propElement.SetAttribute("pixelsRounding", pixelsRounding);
propElement.SetAttribute("adaptGameResolutionAtRuntime",
adaptGameResolutionAtRuntime);
propElement.SetAttribute("sizeOnStartupMode", sizeOnStartupMode);
@@ -760,6 +727,12 @@ void Project::SerializeTo(SerializerElement& element) const {
loadingScreen.SerializeTo(propElement.AddChild("loadingScreen"));
propElement.SetAttribute("useExternalSourceFiles", useExternalSourceFiles);
auto& authorIdsElement = propElement.AddChild("authorIds");
authorIdsElement.ConsiderAsArray();
for (const auto& authorId : authorIds) {
authorIdsElement.AddChild("").SetStringValue(authorId);
}
// Compatibility with GD <= 5.0.0-beta101
if (useDeprecatedZeroAsDefaultZOrder) {
propElement.SetAttribute("useDeprecatedZeroAsDefaultZOrder", true);
@@ -823,10 +796,6 @@ void Project::SerializeTo(SerializerElement& element) const {
for (std::size_t i = 0; i < externalSourceFiles.size(); ++i)
externalSourceFiles[i]->SerializeTo(
externalSourceFilesElement.AddChild("sourceFile"));
#if defined(GD_IDE_ONLY)
dirty = false;
#endif
}
bool Project::ValidateName(const gd::String& name) {
@@ -874,6 +843,10 @@ void Project::ExposeResources(gd::ArbitraryResourceWorker& worker) {
for (std::size_t j = 0; j < GetObjectsCount(); ++j) {
GetObject(j).ExposeResources(worker);
}
// Add loading screen background image if present
if (loadingScreen.GetBackgroundImageResourceName() != "")
worker.ExposeImage(loadingScreen.GetBackgroundImageResourceName());
}
bool Project::HasSourceFile(gd::String name, gd::String language) const {
@@ -924,7 +897,6 @@ gd::SourceFile& Project::InsertNewSourceFile(const gd::String& name,
return newlyInsertedSourceFile;
}
#endif
Project::Project(const Project& other) { Init(other); }
@@ -943,13 +915,14 @@ void Project::Init(const gd::Project& game) {
minFPS = game.minFPS;
verticalSync = game.verticalSync;
scaleMode = game.scaleMode;
pixelsRounding = game.pixelsRounding;
adaptGameResolutionAtRuntime = game.adaptGameResolutionAtRuntime;
sizeOnStartupMode = game.sizeOnStartupMode;
projectUuid = game.projectUuid;
useDeprecatedZeroAsDefaultZOrder = game.useDeprecatedZeroAsDefaultZOrder;
#if defined(GD_IDE_ONLY)
author = game.author;
authorIds = game.authorIds;
packageName = game.packageName;
orientation = game.orientation;
folderProject = game.folderProject;
@@ -965,36 +938,26 @@ void Project::Init(const gd::Project& game) {
gdBuildVersion = game.gdBuildVersion;
currentPlatform = game.currentPlatform;
#endif
platforms = game.platforms;
resourcesManager = game.resourcesManager;
imageManager = std::make_shared<ImageManager>(*game.imageManager);
imageManager->SetResourcesManager(&resourcesManager);
initialObjects = gd::Clone(game.initialObjects);
scenes = gd::Clone(game.scenes);
#if defined(GD_IDE_ONLY)
externalEvents = gd::Clone(game.externalEvents);
#endif
externalLayouts = gd::Clone(game.externalLayouts);
#if defined(GD_IDE_ONLY)
eventsFunctionsExtensions = gd::Clone(game.eventsFunctionsExtensions);
useExternalSourceFiles = game.useExternalSourceFiles;
externalSourceFiles = gd::Clone(game.externalSourceFiles);
#endif
variables = game.GetVariables();
#if defined(GD_IDE_ONLY)
projectFile = game.GetProjectFile();
imagesChanged = game.imagesChanged;
#endif
}
} // namespace gd

View File

@@ -28,7 +28,6 @@ class Object;
class VariablesContainer;
class ArbitraryResourceWorker;
class SourceFile;
class ImageManager;
class Behavior;
class BehaviorsSharedData;
class BaseEvent;
@@ -78,7 +77,6 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
const gd::String& GetVersion() const { return version; }
#if defined(GD_IDE_ONLY)
/**
* \brief Change the author of the project.
*/
@@ -89,6 +87,16 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
const gd::String& GetAuthor() const { return author; }
/**
* \brief Get the author ids of the project.
*/
const std::vector<gd::String>& GetAuthorIds() const { return authorIds; };
/**
* \brief Get the author ids of the project, to modify them (non-const).
*/
std::vector<gd::String>& GetAuthorIds() { return authorIds; };
/**
* \brief Change project package name.
*/
@@ -179,7 +187,6 @@ class GD_CORE_API Project : public ObjectsContainer {
* \brief Return a reference to loading screen setup for the project
*/
const gd::LoadingScreen& GetLoadingScreen() const { return loadingScreen; }
#endif
/**
* Change game's main window default width.
@@ -277,6 +284,16 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
void SetScaleMode(const gd::String& scaleMode_) { scaleMode = scaleMode_; }
/**
* Return true if pixels rounding option is enabled.
*/
bool GetPixelsRounding() const { return pixelsRounding; }
/**
* Set pixels rounding option to true or false.
*/
void SetPixelsRounding(bool enable) { pixelsRounding = enable; }
/**
* \brief Return if the project should set 0 as Z-order for objects created
* from events (which is deprecated) - instead of the highest Z order that was
@@ -313,7 +330,6 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
void ResetProjectUuid();
#if defined(GD_IDE_ONLY)
/**
* \brief Get the properties set by extensions.
*
@@ -364,7 +380,6 @@ class GD_CORE_API Project : public ObjectsContainer {
* current platform won't be changed.
*/
void SetCurrentPlatform(const gd::String& platformName);
#endif
///@}
@@ -390,7 +405,6 @@ class GD_CORE_API Project : public ObjectsContainer {
const gd::String& name,
const gd::String& platformName = "");
#if defined(GD_IDE_ONLY)
/**
* Create an event of the given type.
*
@@ -406,7 +420,6 @@ class GD_CORE_API Project : public ObjectsContainer {
std::shared_ptr<gd::BaseEvent> CreateEvent(
const gd::String& type, const gd::String& platformName = "");
///@}
#endif
/** \name Layouts management
* Members functions related to layout management.
@@ -444,14 +457,12 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::size_t GetLayoutPosition(const gd::String& name) const;
#if defined(GD_IDE_ONLY)
/**
* \brief Swap the specified layouts.
*
* Do nothing if indexes are not correct.
*/
void SwapLayouts(std::size_t first, std::size_t second);
#endif
/**
* \brief Return the number of layouts.
@@ -490,7 +501,6 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
void UnserializeFrom(const SerializerElement& element);
#if defined(GD_IDE_ONLY)
/**
* \brief Serialize the project.
*
@@ -498,19 +508,6 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
void SerializeTo(SerializerElement& element) const;
/**
* \brief Return true if the project is marked as being modified (The IDE or
* application using the project should ask to save the project if the project
* is closed).
*/
bool IsDirty() { return dirty; }
/**
* \brief Mark the project as being modified (The IDE or application
* using the project should ask to save the project if the project is closed).
*/
void SetDirty(bool enable = true) { dirty = enable; }
/**
* Get the major version of GDevelop used to save the project.
*/
@@ -525,13 +522,11 @@ class GD_CORE_API Project : public ObjectsContainer {
* Get the minor version of GDevelop used to save the project.
*/
unsigned int GetLastSaveGDBuildVersion() { return gdBuildVersion; };
#endif
/** \name External events management
* Members functions related to external events management.
*/
///@{
#if defined(GD_IDE_ONLY)
/** \name External events management
* Members functions related to external events management.
*/
///@{
/**
* Return true if external events called "name" exists.
*/
@@ -599,7 +594,6 @@ class GD_CORE_API Project : public ObjectsContainer {
* \brief Delete external events named "name".
*/
void RemoveExternalEvents(const gd::String& name);
#endif
///@}
/** \name External layout management
@@ -640,14 +634,12 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
std::size_t GetExternalLayoutPosition(const gd::String& name) const;
#if defined(GD_IDE_ONLY)
/**
* \brief Swap the specified external layouts.
*
* Do nothing if indexes are not correct.
*/
void SwapExternalLayouts(std::size_t first, std::size_t second);
#endif
/**
* Return the number of external layout.
@@ -691,12 +683,11 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
const gd::String& GetFirstLayout() { return firstLayout; }
///@}
///@}
/** \name Events functions extensions management
*/
///@{
#if defined(GD_IDE_ONLY)
/** \name Events functions extensions management
*/
///@{
/**
* \brief Check if events functions extension called "name" exists.
*/
@@ -771,7 +762,6 @@ class GD_CORE_API Project : public ObjectsContainer {
* \brief Remove all the events functions extensions.
*/
void ClearEventsFunctionsExtensions();
#endif
///@}
/** \name Resources management
@@ -792,28 +782,6 @@ class GD_CORE_API Project : public ObjectsContainer {
*/
ResourcesManager& GetResourcesManager() { return resourcesManager; }
/**
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
* textures for the IDE ( or at runtime for the GD C++ Platform ).
*/
const std::shared_ptr<gd::ImageManager>& GetImageManager() const {
return imageManager;
}
/**
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
* textures for the IDE ( or at runtime for the GD C++ Platform ).
*/
std::shared_ptr<gd::ImageManager>& GetImageManager() { return imageManager; }
/**
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
* textures for the IDE ( or at runtime for the GD C++ Platform ).
*/
void SetImageManager(std::shared_ptr<gd::ImageManager> imageManager_) {
imageManager = imageManager_;
}
/**
* \brief Called ( e.g. during compilation ) so as to inventory internal
* resources, sometimes update their filename or any other work or resources.
@@ -856,13 +824,12 @@ class GD_CORE_API Project : public ObjectsContainer {
* behavior, events function name, etc...).
*/
static bool ValidateName(const gd::String& name);
///@}
///@}
/** \name External source files
* To manage external C++ or Javascript source files used by the game
*/
///@{
#if defined(GD_IDE_ONLY)
/** \name External source files
* To manage external C++ or Javascript source files used by the game
*/
///@{
/**
* \brief Return true if the game activated the use of external source files.
*/
@@ -907,14 +874,7 @@ class GD_CORE_API Project : public ObjectsContainer {
gd::SourceFile& InsertNewSourceFile(const gd::String& name,
const gd::String& language,
std::size_t position = -1);
#endif
///@}
// TODO: Put this in private part
#if defined(GD_IDE_ONLY)
std::vector<gd::String> imagesChanged; ///< Images that have been changed and
///< which have to be reloaded
#endif
///@}
private:
/**
@@ -932,6 +892,8 @@ class GD_CORE_API Project : public ObjectsContainer {
///< are below this number )
bool verticalSync; ///< If true, must activate vertical synchronization.
gd::String scaleMode;
bool pixelsRounding; ///< If true, the rendering should stop pixel
///< interpolation of rendered objects.
bool adaptGameResolutionAtRuntime; ///< Should the game resolution be adapted
///< to the window size at runtime
gd::String
@@ -948,26 +910,22 @@ class GD_CORE_API Project : public ObjectsContainer {
gd::VariablesContainer variables; ///< Initial global variables
std::vector<std::unique_ptr<gd::ExternalLayout> >
externalLayouts; ///< List of all externals layouts
#if defined(GD_IDE_ONLY)
std::vector<std::unique_ptr<gd::EventsFunctionsExtension> >
eventsFunctionsExtensions;
#endif
gd::ResourcesManager
resourcesManager; ///< Contains all resources used by the project
std::shared_ptr<gd::ImageManager>
imageManager; ///< Image manager is accessed thanks to a (smart) ptr as
///< it can be shared with GD C++ Platform projects.
std::vector<gd::Platform*>
platforms; ///< Pointers to the platforms this project supports.
gd::String firstLayout;
#if defined(GD_IDE_ONLY)
bool useExternalSourceFiles; ///< True if game used external source files.
std::vector<std::unique_ptr<gd::SourceFile> >
externalSourceFiles; ///< List of external source files used.
gd::String author; ///< Game author name
gd::String packageName; ///< Game package name
gd::String orientation; ///< Lock game orientation (on mobile devices).
///< "default", "landscape" or "portrait".
gd::String author; ///< Game author name, for publishing purpose.
std::vector<gd::String>
authorIds; ///< Game author ids, from GDevelop users DB.
gd::String packageName; ///< Game package name
gd::String orientation; ///< Lock game orientation (on mobile devices).
///< "default", "landscape" or "portrait".
bool
folderProject; ///< True if folder project, false if single file project.
gd::String
@@ -987,8 +945,6 @@ class GD_CORE_API Project : public ObjectsContainer {
///< time the project was saved.
mutable unsigned int gdBuildVersion; ///< The GD build version used the last
///< time the project was saved.
mutable bool dirty; ///< True to flag the project as being modified.
#endif
};
} // namespace gd

View File

@@ -76,6 +76,14 @@ class GD_CORE_API PropertyDescriptor {
return *this;
}
/**
* \brief Set and replace the additional information for the property.
*/
PropertyDescriptor& SetExtraInfo(const std::vector<gd::String>& info) {
extraInformation = info;
return *this;
}
/**
* \brief Add an information about the property.
* \note The information are arbitrary and are interpreted by the class
@@ -92,9 +100,14 @@ class GD_CORE_API PropertyDescriptor {
const gd::String& GetType() const { return type; }
const gd::String& GetLabel() const { return label; }
const gd::String& GetDescription() const { return description; }
const std::vector<gd::String>& GetExtraInfo() const {
return extraInformation;
}
std::vector<gd::String>& GetExtraInfo() {
return extraInformation;
}
/**
* \brief Set if the property should be shown or hidden in the editor.

View File

@@ -1,108 +0,0 @@
#include "GDCore/Project/ResourcesLoader.h"
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <cstring>
#include <fstream>
#include <iostream>
#include <utility>
#include "GDCore/String.h"
#include "GDCore/Tools/FileStream.h"
#undef LoadImage // Undef a macro from windows.h
using namespace std;
namespace gd {
ResourcesLoader *ResourcesLoader::_singleton = NULL;
void ResourcesLoader::LoadSFMLImage(const gd::String &filename,
sf::Image &image) {
gd::SFMLFileStream stream;
if (!stream.open(filename) || !image.loadFromStream(stream))
cout << "Failed to load a SFML image: " << filename << endl;
}
sf::Texture ResourcesLoader::LoadSFMLTexture(const gd::String &filename) {
sf::Texture texture;
LoadSFMLTexture(filename, texture);
return texture;
}
void ResourcesLoader::LoadSFMLTexture(const gd::String &filename,
sf::Texture &texture) {
gd::SFMLFileStream stream;
if (!stream.open(filename) || !texture.loadFromStream(stream))
cout << "Failed to load a SFML texture: " << filename << endl;
}
std::pair<sf::Font *, StreamHolder *> ResourcesLoader::LoadFont(
const gd::String &filename) {
sf::Font *font = new sf::Font();
StreamHolder *streamHolder = new StreamHolder();
if (!streamHolder->stream.open(filename) ||
!font->loadFromStream(streamHolder->stream)) {
cout << "Failed to load a font from a file: " << filename << endl;
delete font;
delete streamHolder;
return std::make_pair((sf::Font *)nullptr, (StreamHolder *)nullptr);
}
return std::make_pair(font, streamHolder);
}
sf::SoundBuffer ResourcesLoader::LoadSoundBuffer(const gd::String &filename) {
sf::SoundBuffer sbuffer;
gd::SFMLFileStream stream;
if (!stream.open(filename) || !sbuffer.loadFromStream(stream))
cout << "Failed to load a sound buffer: " << filename << endl;
return sbuffer;
}
gd::String ResourcesLoader::LoadPlainText(const gd::String &filename) {
gd::String text;
gd::FileStream file(filename, ios::in);
if (!file.fail()) {
std::string ligne;
while (getline(file, ligne)) text += gd::String::FromUTF8(ligne) + "\n";
file.close();
} else
cout << "Failed to read a file: " << filename << endl;
return text;
}
/**
* Load a binary text file
*/
char *ResourcesLoader::LoadBinaryFile(const gd::String &filename) {
gd::FileStream file(filename, ios::in | ios::binary | ios::ate);
if (file.is_open()) {
iostream::pos_type size = file.tellg();
char *memblock = new char[size];
file.seekg(0, ios::beg);
file.read(memblock, size);
file.close();
return memblock;
}
cout << "Binary file " << filename << " can't be loaded into memory " << endl;
return NULL;
}
long int ResourcesLoader::GetBinaryFileSize(const gd::String &filename) {
gd::FileStream file(filename, ios::in | ios::binary | ios::ate);
if (file.is_open()) {
return file.tellg();
}
std::cout << "Binary file " << filename << " cannot be read. " << std::endl;
return 0;
}
} // namespace gd

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