Compare commits

...

88 Commits

Author SHA1 Message Date
Fannie Yan
33ddda1070 Remove "Create functions or behavior" from project manager tab (#3953)
* Move "+ Create functions or behavior" button in extension search dialog
2022-05-25 10:37:28 +02:00
Clément Pasteau
029c9c853b Bump version to 135
Do not show in changelog
2022-05-25 09:54:52 +02:00
Clément Pasteau
e38a70ad10 Fix Yarn editor not saving anymore
* Pass down remote to Yarn to fix saving with Electron > 18
2022-05-25 09:43:09 +02:00
AlexandreS
78b48601a1 Fix: Allow use of debugger when not connected to Internet 2022-05-24 17:01:00 +02:00
AlexandreS
e91a794d91 Fix: Prevent runtime from trying to parse js map files to avoid Chrome logging warnings 2022-05-24 13:59:03 +02:00
Florian Rival
6fefd6d36e Fix formatting
Don't show in changelog
2022-05-24 13:45:48 +02:00
Florian Rival
0cf05b71ba Fix various links to docs and update links to new domain
Don't show in changelog
2022-05-24 11:44:55 +02:00
Florian Rival
1ab023e211 Add a comment explaining how to generate latest.yml files if necessary (#3946)
Don't show in changelog
2022-05-23 11:14:20 +02:00
AlexandreS
aa4e9e25bf Bump newIDE version 2022-05-23 11:02:13 +02:00
Clément Pasteau
bc235ef492 Revert publish declaration in package.json for latest.yml generation (#3944)
Do not show in changelog
2022-05-23 10:40:39 +02:00
AlexandreS
eabd1a4f23 Compute object variable suggestions on each object change in the expression builder 2022-05-23 08:58:30 +02:00
Florian Rival
62ef3e729b Speed up the editor development server startup time by 3x (#3941)
* Patch Webpack config to avoid processing the locale message files (translation files)

Only show in developer changelog
2022-05-22 21:24:49 +02:00
Florian Rival
802ee0c03f Upgrade Electron to 18.2 and React dev tools to latest version (#3893)
Only show in developer changelog
2022-05-21 17:00:47 +02:00
Florian Rival
7ef2050de7 Normalise imports to avoid .js suffix (#3938)
Don't show in changelog
2022-05-21 12:54:50 +02:00
AlexandreS
eeea1b99f4 New variables list improvements
* Fix drop down styling on light theme for selected rows
* Make sure the toolbar is fixed on every dialog the dialog is used in
* When adding a variable, scroll to the new row and focus name
* When searching, display children of collections to enable the user path "Search by collection name > Find child of interest > change child value".
  * If one changes a variable name that justifies its display during the search, the row does not disappear as soon as one is done with editing the name
2022-05-20 15:33:09 +02:00
Florian Rival
e75d49ea51 Upgrade to latest React v16 and react-scripts v4 (#3934)
* This enables "Fast Refresh" of React components (hot reloading after a change is made)
* This prepares the codebase for a migration to React v17/v18 later.

Only show in developer changelog
2022-05-20 15:04:23 +02:00
Florian Rival
048674a7d0 Fix ObjectGroupsList story not working
Don't show in changelog
2022-05-20 13:18:23 +02:00
Florian Rival
0502bd1f7a Fix properties of a custom behavior edited in an extension not taking the full width of the dialog 2022-05-20 13:01:53 +02:00
Florian Rival
66b84441ea Fix the GDJS development watcher making the electron renderer process crash when reloading (#3931)
Only show in developer changelog
2022-05-19 21:46:16 +02:00
D8H
d9e27dc4f3 Review change: rename the function (#3926)
Do not show in changelog
2022-05-19 14:20:39 +02:00
D8H
a3c3ffc3bb Fix missing exported extension functions (#3908) 2022-05-19 11:36:39 +02:00
Fannie Yan
dc33b6cc01 Fix typo in Leaderboard sort order (#3925)
Don't show in changelog
2022-05-19 11:16:23 +02:00
github-actions[bot]
4a0c1c5ad2 Update translations [skip ci] (#3891)
Do not show in changelog
2022-05-19 10:14:29 +02:00
AlexandreS
5820c5dd3e Bump newIDE version 2022-05-19 10:13:04 +02:00
D8H
606f5aff1b Fix: resource folder won't open on Windows (#3922)
Don't show in changelogs
2022-05-18 17:56:51 +02:00
AlexandreS
1f42374417 Reorder effects with drag n drop
Effects are applied in order and different orders may give different results, so ordering them is important. You can now do it with drag n drop.
Also, when renaming effects, a few checks are now done in order to prevent unexpected results.
2022-05-18 16:25:11 +02:00
AlexandreS
3356400026 Redesign of the variables editor
* Each row should be easier to read in a glance
* You can now collapse collection variables for a better readability
* Reorder and move of variables is now available with drag n drop
* You can now undo and redo changes
* Paste one or more variables at any level of depth you want
* Search in the names and values of each variables with a filter effect
2022-05-18 15:18:54 +02:00
Clément Pasteau
b811b1e873 Track asset packs opening analytics (#3919) 2022-05-18 14:24:13 +02:00
Florian Rival
e985b11971 Prevent layout shift when opening the asset store
Don't show in changelog
2022-05-16 21:16:48 +02:00
Florian Rival
aefc5e2fed Fix warning
Don't show in changelog
2022-05-16 20:57:43 +02:00
Clément Pasteau
0ccb7c3216 Add an asset pack gallery in the asset store (#3896) 2022-05-16 19:09:07 +02:00
Florian Rival
33c2c9c6cf Make GDevelop.js build happen on branches/Pull Requests (but not from forks) (#3914) 2022-05-16 19:04:44 +02:00
AlexandreS
55a6306f05 Fix range of volume on fade sound/music action
* ⚠️ This action was introduced with a buggy range (0 to 1 instead of 0 to 100). If you happen to use it, please update the range of volume used once the GDevelop new version is installed
2022-05-16 17:00:02 +02:00
AlexandreS
d766e32a18 Fix: Align image frame and full-size collision mask in collision mask editor 2022-05-16 16:47:39 +02:00
AlexandreS
7cdf4e1184 Fix: Prevent users to type a game slug longer than the limit 2022-05-16 16:19:29 +02:00
Fannie Yan
2540bf3c3e Allow user to limit score values saved in leaderboards (#3910)
Add a Dialog in a game's dashboard leaderboard tab allowing users to chose sort direction and limit possible scores for their games.
2022-05-16 16:10:59 +02:00
Florian Rival
6adec363d5 Enable C++ tests by default in CMake
Only show in developer changelog
2022-05-13 17:47:16 +00:00
D8H
91a02d132f Remove the dependency to SFML (#3865)
* This allows to run Core tests more easily.
2022-05-13 13:27:41 +02:00
Florian Rival
67718a364b Fix missing https in wiki links
Don't show in changelog
2022-05-13 12:49:02 +02:00
Florian Rival
e9b600d885 Update links to the new wiki
Don't show in changelog
2022-05-13 12:43:25 +02:00
Florian Rival
696dfcb746 Allow to choose installation directory when installing GDevelop on Windows (#3889)
* Also allow to choose if GDevelop must be installed system-wide or just for the user.
2022-05-13 12:06:33 +02:00
Fannie Yan
437edd1fe7 Make anchor behavior more intuitive (#3892)
* Anchor an edge of an object to set its distance from the window edges. Single anchor will not stretch the object anymore; you will need to set anchors to object's opposite edges for this effect.
* Add a button to switch between legacy and new behavior.
2022-05-13 10:50:40 +02:00
Florian Rival
48599ae9ca Improve consistency of some dialogs
Don't show in changelog
2022-05-12 22:30:57 +02:00
Florian Rival
c288700f2d Fix warnings
Don't show in changelog
2022-05-12 21:55:08 +02:00
Florian Rival
fbfb5dbaa6 Improve design of the alerts/messages and make margins consistent in the app (#3897) 2022-05-12 21:50:18 +02:00
Florian Rival
dfa27df64b Fix parameters of extensions actions/conditions made in the editor not having a default proper name
* This was creating a crash, because of infinite warnings, if clicking on a parameter with an empty name and then clicking on another parameter also having an empty name.

Fix #3888
2022-05-12 15:44:05 +02:00
Florian Rival
1ef404b9a9 Update the preview to create the BrowserWindow from the electron main process (#3890)
Only show in the developer changelog
2022-05-11 16:58:40 +02:00
github-actions[bot]
785dd6f08b Update translations [skip ci] (#3867)
Co-authored-by: fannieyan <fannieyan@users.noreply.github.com>
2022-05-11 10:33:46 +02:00
Fannie Yan
59bc76e144 Add tutorials in app (#3870)
- Added dismissable tutorials in events sheet, variable editors and object variable tab, add object dialog, sprite animations tab, export game for web tab, add new extension dialog.

- Added a tutorial button.
2022-05-10 17:42:45 +02:00
Florian Rival
d873d9747a Display all autocompletions in the expression editor when listing them (#3886)
* The list is not truncated anymore so you can scroll or use the arrow keys to browse all the completions (useful to see everything: objects, expressions, but also the available easing for tweens, etc...)
2022-05-10 13:07:38 +02:00
Florian Rival
a7fe36f351 Fix web-app recent files wrongly containing URLs to examples (#3885) 2022-05-10 09:15:52 +02:00
Florian Rival
252eeb86b1 Upgrade the underlying runtime running the desktop app, and exported desktop games, to Electron 18 (#3806) (#3854)
* This brings improved performance and compatibility for the desktop app with Windows, macOS and Linux.
* In particular, tilemap performance should be greatly improved both in the scene editor, the preview and exported games on Linux.
* This should also improve performance of both the editor and games on macOS when running on Apple Silicon (M1 cpus).
* Thanks to @nilaymajorwar for the ground work on this upgrade.

Only show the rest in developer changelog:

* More work is needed to isolate the Electron "renderer" process from the "main" process (both for the editor and for games), by using `contextBridge` and preload scripts (https://www.electronjs.org/docs/latest/tutorial/process-model). Your help is welcome to progressively do this migration.

Co-authored-by: Nilay Majorwar <nilaymajorwar@gmail.com>
2022-05-08 17:24:49 +02:00
Clément Pasteau
66145ce506 Specify supported languages for the Microsoft Store version (appx) (#3873) 2022-05-07 22:23:49 +02:00
Clément Pasteau
0dd10d2fce Fix history not working well on the Events Sheet
* Fix changes not being detected for history when editing an event Inline
* Fix losing focus when switching tabs
2022-05-06 12:15:31 +02:00
Clément Pasteau
5d35241c4c Fix not setting authors correctly when publishing to Liluo
* Also fix project being correctly saved
* And disabled the fields while publishing
2022-05-06 12:07:53 +02:00
AlexandreS
ba368d9eed Improve points and collision masks editors
- Make coordinates inputs more user friendly
  - Removal of unnecessary decimal places
  - Do not replace empty value with 0 to allow whole value erasing
- Better understanding of which point is which
  - Add possibility to select points in the list so that it is highlighted in the preview (same for hovered points)
  - Allow drag n drop for custom collision mask points
- Open image preview at a zoom factor that is adapted to the sprite size so that one doesn't have to zoom at each opening.
2022-05-06 09:56:06 +02:00
Florian Rival
fbeeb589a2 Fix package-lock.json
Don't show in changelog
2022-05-05 15:04:34 +02:00
Florian Rival
3ec4e3b6dd Add missing metric about desktop or web-app
* Also fix the dev version sending analytics

Don't show in changelog
2022-05-05 12:13:32 +02:00
Florian Rival
11ccaf2ea4 Add Posthog for following app usage analytics
* Fix UUID not reset when a user was logging out
* This should allow to create public dashboard showing various app usage (like popular extensions), with more accurate numbers than using Keen.io
2022-05-05 11:40:38 +02:00
Florian Rival
274d31f563 Update help links for the Time extension
Don't show in changelog
2022-05-04 18:56:40 +02:00
AlexandreS
c37049cd72 Add new settings to leaderboards
* Add parameter to control number of entries to display
* Add possibility to set a default leaderboard, displayed on Liluo game page by default
2022-05-04 10:37:01 +02:00
Florian Rival
7cdc92c776 Introduce the "Wait X seconds" action (#3852)
* This action allow to wait for a few seconds before continuing to run the next actions and sub-events.
* It is perfect to create cut scenes, advanced logic or just run things progressively without relying on timers. In a lot of cases, it's simpler and faster to use this new action.
* The action remember the picked objects: it works like an usual event, but run the actions (and sub-events) a bit later in time. While the action wait, other events continue to run as usual.
* Thanks to @arthuro555 for the ground work and follow up on this new feature.

Only show the rest in developer changelog:

* Add support for asynchronous actions (including for objects).
* Add exhaustive test cases for asynchronous actions. 

Co-authored-by: Arthur Pacaud <arthur.pacaud@hotmail.fr>
2022-05-02 19:44:15 +02:00
Florian Rival
471cd61d82 Add test for "Or" condition with objects
Don't show in changelog
2022-05-02 18:23:56 +02:00
Fannie Yan
afb66f213d Add tutorials in behavior, objects, conditions and actions (#3869)
* Add tutorials in behavior, objects, conditions and actions
2022-05-02 17:49:48 +02:00
Clément Pasteau
8ad70e57cc Encode thumbnail URL before sending it to the GDevelop services
* This prevents a bug where the thumbnail would not work when the filename has non-conventional characters
2022-04-29 15:40:54 +02:00
Arthur Pacaud
d9ea04e059 Allow webp images to be selected for object resources, and webm for videos (#3862)
* These formats are providing better compression than PNG or MP4, but they might not work on older devices - be sure to double check if the devices or browsers of your audience support them.
2022-04-29 11:40:07 +02:00
github-actions[bot]
bb3abdb1fa Update translations [skip ci] (#3831)
Co-authored-by: 4ian <4ian@users.noreply.github.com>
2022-04-28 16:40:10 +02:00
Oxey405
cdddcafa68 Add an action to fade a sound or a music on a channel to a new volume (#3724) 2022-04-28 11:17:46 +02:00
AlexandreS
14175c334e Do not show in changelog - Trim player name when formatting it 2022-04-28 11:02:12 +02:00
D8H
6bd4dff03e Remove variable parameters from SavePlayerScore action (#3860)
Do not show in changelog
2022-04-28 11:01:36 +02:00
Clément Pasteau
ceec39f6a2 Bump version to 5.0.132
Do not show in changelog
2022-04-27 17:59:58 +02:00
AlexandreS
5abf80a0c9 Add possibility to customize leaderboard score column appearance (#3857) 2022-04-27 17:46:15 +02:00
AlexandreS
7f955d8703 Add expressions to specify decimal place where to round, floor and ceil 2022-04-27 16:47:14 +02:00
D8H
781dd42ccb Add analytics for extensions (#3848) 2022-04-26 09:16:01 +02:00
Fannie Yan
e584fa952d Make loader screen cover input fields (#3850)
Don't show in changelog
2022-04-25 09:57:21 +02:00
Florian Rival
5681667dde Add a gitpod.io configuration file (experimental)
* This is useful to edit some part of the codebase on gitpod.io

Only show in developer changelog
2022-04-24 14:29:11 +00:00
Florian Rival
d16f04f4a2 Change AlertMessage design to be flat
Avoid shadows if not really needed.

Don't show in changelog
2022-04-24 14:23:08 +00:00
Aurélien Vivet
e9b464beba Improve wording consistency (#3851) 2022-04-23 16:35:51 +02:00
Florian Rival
7597dbe0d1 Add (new) conditions and expressions to compare the number of instances picked or living on the scene (#3842)
* Add `PickedInstancesCount` and `SceneInstancesCount` expressions, to replace `Count`. These expressions don't do any "picking" of instances, so they are safe to use anywhere without "weird" side effects.
* Equivalent conditions are available for all objects. These conditions allow to check at any point in your events the number of instances living on the scene or picked by actions/conditions.
  * This is useful to check if enough objects are picked by a condition before launching an action. 
  * Because this condition does not change the already picked objects, it's safe to use anywhere without any side effect.

Only show the rest in the developer changelog:
* Allow to read events missing some fields (like `disabled`, `folded`).
* Reduce the useless information stored in project JSON files by not storing the fields if they have their default value.
2022-04-23 16:35:10 +02:00
Clément Pasteau
4777f0a824 Save project after creation on Desktop app 2022-04-22 19:11:34 +02:00
AlexandreS
5b2532f8f3 Remove unused variables
Do not show in changelog
2022-04-21 15:02:41 +02:00
AlexandreS
2c43de5120 Improve objects and groups lists
* Use same drag and drop effect for both lists
* Add possibility to duplicate group
* Add possibility to move multiple objects at once
2022-04-21 14:26:42 +02:00
Florian Rival
124ce1101d Fix leaderboards category icon 2022-04-20 14:27:38 +02:00
AlexandreS
eb3d6c2670 Send events when opening and finalizing events extraction as function
Don't show in changelog
2022-04-20 12:17:09 +02:00
Clément Pasteau
f737fa479f Don't allow picking image URLs that will fail when building the game on the web application
- targeting specifically images with failed CORS
2022-04-19 17:45:48 +02:00
Florian Rival
f93b3bc3b4 Fix crash when an empty effect is added to a layer
Fix #3835
2022-04-19 12:47:20 +02:00
Elairyx
5c6eb2dadb Polish the wording of particle emitter actions, conditions and expressions (#3829) 2022-04-15 16:24:51 +01:00
AlexandreS
3e6ca186f8 Add action to change image for particle emitter using project resources 2022-04-15 15:37:38 +02:00
584 changed files with 50473 additions and 45613 deletions

View File

@@ -2,10 +2,17 @@
# on the Electron runtime (newIDE/electron-app) for macOS and Linux.
# For Windows, see the appveyor.yml file.
# This also builds GDevelop.js and store it on a S3 so it can be used to run
# GDevelop without building it from scratch.
# Note that these CircleCI builds/tests are not launched on Pull Requests from forks,
# to avoid sharing secrets.
version: 2.1
orbs:
aws-cli: circleci/aws-cli@2.0.6
jobs:
# Build the **entire** app for macOS.
build-macos:
macos:
xcode: 12.5.1
@@ -75,6 +82,7 @@ jobs:
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 the **entire** app for Linux.
build-linux:
# CircleCI docker workers are failing if they don't have enough memory (no swap)
resource_class: xlarge
@@ -153,10 +161,67 @@ jobs:
name: Deploy to S3 (latest)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
# Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use).
build-gdevelop_js-wasm-only:
docker:
- image: cimg/node:16.13
working_directory: ~/GDevelop
steps:
- checkout
- aws-cli/setup
# System dependencies (for Emscripten)
- run:
name: Install dependencies for Emscripten
command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- 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:
- gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# fallback to using the latest cache if no exact match is found
- gdevelop.js-linux-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 ..
- save_cache:
paths:
- GDevelop.js/node_modules
key: gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# Upload artifacts (CircleCI)
- store_artifacts:
path: Binaries/embuild/GDevelop.js
# Upload artifacts (AWS)
- run:
name: Deploy to S3 (specific commit)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
- run:
name: Deploy to S3 (latest)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/latest/
workflows:
builds:
jobs:
- build-gdevelop_js-wasm-only
- build-macos:
filters:
branches:

View File

@@ -4,14 +4,14 @@ contact_links:
url: https://discord.gg/rjdYHvj
about: Discuss on the forum or on the Discord to get help creating a game or identifying a bug.
- name: GDevelop Forums
url: https://forum.gdevelop-app.com
url: https://forum.gdevelop.io
about: You can also discuss game creation, new feature requests and bugs on the forum.
- name: GDevelop Roadmap
url: https://trello.com/b/qf0lM7k8/gdevelop-roadmap
about: Look at the roadmap and vote on features that you want to see in GDevelop.
- name: Submit a new game example that you created
url: https://github.com/GDevelopApp/GDevelop-examples/issues/new/choose
about: You can submit a game that you made to be added to examples in the "GDevelop-examples" repository
about: You can submit a game that you made to be added to examples in the "GDevelop-examples" repository
- name: Submit a new game extension that you created
url: https://github.com/4ian/GDevelop-extensions/issues/new/choose
about: You can submit an extension that you made in the "GDevelop-extensions" repository
about: You can submit an extension that you made in the "GDevelop-extensions" repository

View File

@@ -12,7 +12,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
type: "body"
regex: ".*Scroll down to '\\.\\.\\.\\.'.*"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop-app.com/), the Discord chat or [read the documentation](http://wiki.compilgames.net/doku.php/gdevelop5/start) to learn more about GDevelop. Thanks!"
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any steps to reproduce the bug.\n\nGitHub is a place for the technical development of GDevelop itself - you may want to go on the [forum](https://forum.gdevelop.io/), the Discord chat or [read the documentation](https://wiki.gdevelop.io/gdevelop5/start) to learn more about GDevelop. Thanks!"
- name: Autoclose known beta 105 web-app update bug
uses: arkon/issue-closer-action@v1.1
with:

1
.gitignore vendored
View File

@@ -8,6 +8,7 @@
/Binaries/.embuild*
/Binaries/build*
/Binaries/embuild*
/emsdk
*.dll
*.exe
*.a

25
.gitpod.yml Normal file
View File

@@ -0,0 +1,25 @@
# This is a configuration file allowing to quickly set up a development environment
# on GitPod (https://www.gitpod.io/).
# Also check GitHub codespaces if you're interested in working
# on a remote development server.
# This works well for:
# - The editor web-app, including the C++ classes.
# This is not yet adapted for:
# - Working on the game engine or extensions, as they can't be easily tested on the web-app.
# - Working on the desktop app (Electron).
tasks:
- name: Install dependencies for Emscripten and build GDevelop.js
init: |
sudo apt-get update
sudo apt install cmake python-is-python3 python3-distutils -y
git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
cd GDevelop.js
npm install
source ../emsdk/emsdk_env.sh && npm run build -- --dev
cd ..
- name: Install GDevelop IDE dependencies
init: cd newIDE/app && npm install && cd ../electron-app && npm install

View File

@@ -1,9 +1,6 @@
# 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).
@@ -17,18 +14,7 @@ cache:
directories:
- $HOME/.npm
services:
# Virtual Framebuffer 'fake' X server for SFML
- xvfb
addons:
artifacts:
s3_region: "us-east-1"
target_paths:
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/commit/$(git rev-parse HEAD)
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/latest
paths:
- Binaries/embuild/GDevelop.js
apt:
sources:
- ubuntu-toolchain-r-test
@@ -36,20 +22,8 @@ addons:
# Build dependencies:
- cmake
- p7zip-full
# SFML dependencies:
- libopenal-dev
- libjpeg-dev
- libglew-dev
- libudev-dev
- libxrandr-dev
- libsndfile1-dev
- libglu1-mesa-dev
- libfreetype6-dev
before_install:
#Activate X Virtual Framebuffer to allow tests to
#use SFML.
- "export DISPLAY=:99.0"
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
- wget -q -O libstdc++6 http://security.ubuntu.com/ubuntu/pool/main/g/gcc-5/libstdc++6_5.4.0-6ubuntu1~16.04.12_amd64.deb
- sudo dpkg --force-all -i libstdc++6

View File

@@ -7,11 +7,9 @@
"${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": [
@@ -27,7 +25,6 @@
"/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,
@@ -48,7 +45,6 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
@@ -78,7 +74,6 @@
"${workspaceRoot}/GDJS",
"${workspaceRoot}/Extensions",
"${workspaceRoot}/Core",
"${workspaceRoot}/ExtLibs/SFML/include",
"${workspaceRoot}"
],
"defines": [
@@ -101,4 +96,4 @@
}
],
"version": 4
}
}

14
.vscode/launch.json vendored
View File

@@ -15,6 +15,20 @@
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/GDevelop.js"
},
{
"type": "node",
"request": "launch",
"name": "newIDE/app Jest tests (current file)",
"program": "${workspaceFolder}/newIDE/app/node_modules/.bin/react-scripts",
"args": [
"test", "--env=node",
"${fileBasenameNoExtension}"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"cwd": "${workspaceFolder}/newIDE/app"
},
{
"type": "node",
"request": "launch",

View File

@@ -115,7 +115,6 @@
"files.exclude": {
"Binaries/*build*": true,
"Binaries/Output": true,
"ExtLibs/SFML": true,
"GDJS/Runtime-dist": true,
"docs": true,
"newIDE/electron-app/dist": true,

View File

@@ -17,7 +17,7 @@ endmacro()
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(BUILD_TESTS TRUE BOOL "TRUE to build the tests")
# Disable deprecated code
set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.

View File

@@ -14,7 +14,6 @@ set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SY
#Dependencies on external libraries:
###
include_directories(${sfml_include_dir})
#Defines
###
@@ -68,14 +67,6 @@ set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMA
set(ARCHIVE_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
set(RUNTIME_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
#Linker files
###
IF(EMSCRIPTEN)
#Nothing.
ELSE()
target_link_libraries(GDCore ${sfml_LIBRARIES})
ENDIF()
#Tests
###
if(BUILD_TESTS)
@@ -88,5 +79,5 @@ if(BUILD_TESTS)
add_executable(GDCore_tests ${test_source_files})
set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) #Allow finding dependencies directly from build path on Mac OS X.
target_link_libraries(GDCore_tests GDCore)
target_link_libraries(GDCore_tests ${sfml_LIBRARIES})
target_link_libraries(GDCore_tests ${CMAKE_DL_LIBS})
endif()

View File

@@ -13,7 +13,6 @@
#include <string>
#include <vector>
#include "Utf8/utf8.h"
#include <SFML/System/String.hpp>
#ifdef __GNUC__
#define GD_DEPRECATED __attribute__((deprecated))

View File

@@ -0,0 +1,36 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#include "AsyncEvent.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Serialization.h"
#include "GDCore/Serialization/SerializerElement.h"
using namespace std;
namespace gd {
AsyncEvent::AsyncEvent() : BaseEvent() {}
AsyncEvent::~AsyncEvent(){};
vector<const gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() const {
vector<const gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
vector<gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() {
vector<gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
} // namespace gd

View File

@@ -0,0 +1,61 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#ifndef GDCORE_ASYNCEVENT_H
#define GDCORE_ASYNCEVENT_H
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
namespace gd {
class Instruction;
class Project;
} // namespace gd
namespace gd {
/**
* \brief Internal event for asynchronous actions.
* This event gets added internally to the events tree when an
* asynchronous action is used.
*/
class GD_CORE_API AsyncEvent : public gd::BaseEvent {
public:
AsyncEvent();
AsyncEvent(const gd::Instruction &asyncAction_,
const gd::InstructionsList &actions_,
const gd::EventsList &subEvents_)
: asyncAction(asyncAction_), actions(actions_), subEvents(subEvents_) {
SetType("BuiltinAsync::Async");
};
virtual ~AsyncEvent();
virtual gd::AsyncEvent *Clone() const { return new AsyncEvent(*this); }
virtual bool IsExecutable() const { return true; }
virtual bool CanHaveSubEvents() const { return true; }
virtual const gd::EventsList &GetSubEvents() const { return subEvents; };
virtual gd::EventsList &GetSubEvents() { return subEvents; };
const gd::InstructionsList &GetActions() const { return actions; };
gd::InstructionsList &GetActions() { return actions; };
const gd::Instruction &GetInstruction() const { return asyncAction; };
gd::Instruction &GetInstruction() { return asyncAction; };
virtual std::vector<const gd::InstructionsList *>
GetAllActionsVectors() const;
virtual std::vector<gd::InstructionsList *> GetAllActionsVectors();
private:
gd::Instruction asyncAction;
gd::InstructionsList actions;
EventsList subEvents;
};
} // namespace gd
#endif // GDCORE_STANDARDEVENT_H

View File

@@ -63,8 +63,12 @@ void StandardEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
events.Clear();
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
}
} // namespace gd

View File

@@ -4,7 +4,9 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include <set>
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
@@ -14,7 +16,7 @@ using namespace std;
namespace gd {
void EventsCodeGenerationContext::InheritsFrom(
const EventsCodeGenerationContext& parent_) {
EventsCodeGenerationContext& parent_) {
parent = &parent_;
// Objects lists declared by parent became "already declared" in the child
@@ -24,8 +26,8 @@ void EventsCodeGenerationContext::InheritsFrom(
parent_.objectsListsToBeDeclared.end(),
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
std::copy(parent_.objectsListsWithoutPickingToBeDeclared.begin(),
parent_.objectsListsWithoutPickingToBeDeclared.end(),
std::copy(parent_.objectsListsOrEmptyToBeDeclared.begin(),
parent_.objectsListsOrEmptyToBeDeclared.end(),
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
std::copy(parent_.emptyObjectsListsToBeDeclared.begin(),
@@ -33,6 +35,8 @@ void EventsCodeGenerationContext::InheritsFrom(
std::inserter(alreadyDeclaredObjectsLists,
alreadyDeclaredObjectsLists.begin()));
nearestAsyncParent = parent_.IsAsyncCallback() ? &parent_ : parent_.nearestAsyncParent;
asyncDepth = parent_.asyncDepth;
depthOfLastUse = parent_.depthOfLastUse;
customConditionDepth = parent_.customConditionDepth;
contextDepth = parent_.GetContextDepth() + 1;
@@ -42,33 +46,59 @@ void EventsCodeGenerationContext::InheritsFrom(
}
}
void EventsCodeGenerationContext::InheritsAsAsyncCallbackFrom(
EventsCodeGenerationContext& parent_) {
// Increasing the async depth is enough to mark the context as an async callback.
InheritsFrom(parent_);
asyncDepth = parent_.asyncDepth + 1;
}
void EventsCodeGenerationContext::Reuse(
const EventsCodeGenerationContext& parent_) {
EventsCodeGenerationContext& parent_) {
InheritsFrom(parent_);
if (parent_.CanReuse())
contextDepth = parent_.GetContextDepth(); // Keep same context depth
}
void EventsCodeGenerationContext::NotifyAsyncParentsAboutDeclaredObject(const gd::String& objectName) {
gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
for (;
asyncContext != nullptr;
asyncContext = asyncContext->parent->nearestAsyncParent)
asyncContext->allObjectsListToBeDeclaredAcrossChildren.insert(objectName);
}
void EventsCodeGenerationContext::ObjectsListNeeded(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName))
if (!IsToBeDeclared(objectName)) {
objectsListsToBeDeclared.insert(objectName);
if (IsInsideAsync()) {
NotifyAsyncParentsAboutDeclaredObject(objectName);
}
}
depthOfLastUse[objectName] = GetContextDepth();
}
void EventsCodeGenerationContext::ObjectsListWithoutPickingNeeded(
void EventsCodeGenerationContext::ObjectsListNeededOrEmptyIfJustDeclared(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName))
objectsListsWithoutPickingToBeDeclared.insert(objectName);
if (!IsToBeDeclared(objectName)) {
objectsListsOrEmptyToBeDeclared.insert(objectName);
if (IsInsideAsync()) {
NotifyAsyncParentsAboutDeclaredObject(objectName);
}
}
depthOfLastUse[objectName] = GetContextDepth();
}
void EventsCodeGenerationContext::EmptyObjectsListNeeded(
const gd::String& objectName) {
if (!IsToBeDeclared(objectName))
if (!IsToBeDeclared(objectName)) {
emptyObjectsListsToBeDeclared.insert(objectName);
}
depthOfLastUse[objectName] = GetContextDepth();
}
@@ -77,8 +107,8 @@ std::set<gd::String> EventsCodeGenerationContext::GetAllObjectsToBeDeclared()
const {
std::set<gd::String> allObjectListsToBeDeclared(
objectsListsToBeDeclared.begin(), objectsListsToBeDeclared.end());
allObjectListsToBeDeclared.insert(objectsListsWithoutPickingToBeDeclared.begin(),
objectsListsWithoutPickingToBeDeclared.end());
allObjectListsToBeDeclared.insert(objectsListsOrEmptyToBeDeclared.begin(),
objectsListsOrEmptyToBeDeclared.end());
allObjectListsToBeDeclared.insert(emptyObjectsListsToBeDeclared.begin(),
emptyObjectsListsToBeDeclared.end());
@@ -102,4 +132,21 @@ bool EventsCodeGenerationContext::IsSameObjectsList(
otherContext.GetLastDepthObjectListWasNeeded(objectName);
}
bool EventsCodeGenerationContext::ShouldUseAsyncObjectsList(
const gd::String& objectName) const {
if (!IsInsideAsync()) return false;
// Check if the objects list was used after (or in) the nearest async callback context.
const gd::EventsCodeGenerationContext* asyncContext = IsAsyncCallback() ? this : nearestAsyncParent;
if (parent->GetLastDepthObjectListWasNeeded(objectName) >= asyncContext->GetContextDepth()) {
// The object was used in a context after (or in) the nearest async parent context, so we're not getting it from the
// async object lists (it was already gotten from there in this previous context).
return false;
}
// If the objects list is declared in a parent of the nearest async context, it means
// the async context had to use an async objects list to access it.
return asyncContext->ObjectAlreadyDeclaredByParents(objectName);
};
} // namespace gd

View File

@@ -8,6 +8,7 @@
#include <map>
#include <memory>
#include <set>
#include "GDCore/String.h"
namespace gd {
@@ -33,11 +34,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* updated to contain the maximal scope depth reached.
*/
EventsCodeGenerationContext(unsigned int* maxDepthLevel_ = nullptr)
: contextDepth(0),
customConditionDepth(0),
maxDepthLevel(maxDepthLevel_),
parent(NULL),
reuseExplicitlyForbidden(false){};
: maxDepthLevel(maxDepthLevel_){};
virtual ~EventsCodeGenerationContext(){};
/**
@@ -45,7 +42,13 @@ class GD_CORE_API EventsCodeGenerationContext {
* another one. The child will then for example not declare again objects
* already declared by its parent.
*/
void InheritsFrom(const EventsCodeGenerationContext& parent);
void InheritsFrom(EventsCodeGenerationContext& parent);
/**
* Call this method to make an EventsCodeGenerationContext as a "child" of
* another one, but in the context of an async function.
*/
void InheritsAsAsyncCallbackFrom(EventsCodeGenerationContext& parent);
/**
* \brief As InheritsFrom, mark the context as being the child of another one,
@@ -53,7 +56,7 @@ class GD_CORE_API EventsCodeGenerationContext {
*
* Used for example for optimizing the last event of a list.
*/
void Reuse(const EventsCodeGenerationContext& parent);
void Reuse(EventsCodeGenerationContext& parent);
/**
* \brief Forbid any optimization that would reuse and modify the object list
@@ -88,19 +91,19 @@ class GD_CORE_API EventsCodeGenerationContext {
const EventsCodeGenerationContext* GetParentContext() const { return parent; }
/**
* Mark the object has being the object being handled by the instruction
* Mark the object as being the object being handled by the instruction.
*/
void SetCurrentObject(const gd::String& objectName) {
currentObject = objectName;
};
/**
* Set that no particular object is being handled by an instruction
* Set that no particular object is being handled by an instruction.
*/
void SetNoCurrentObject() { currentObject = ""; };
/**
* Get the object being handled by the instruction
* Get the object being handled by the instruction.
*/
const gd::String& GetCurrentObject() const { return currentObject; };
@@ -109,7 +112,7 @@ class GD_CORE_API EventsCodeGenerationContext {
*
* The list will be filled with objects from the scene if it is the first time
* it is requested, unless there is already an object list with this name
* (i.e. `ObjectAlreadyDeclared(objectName)` returns true).
* (i.e. `ObjectAlreadyDeclaredByParents(objectName)` returns true).
*/
void ObjectsListNeeded(const gd::String& objectName);
@@ -121,7 +124,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* from the scene. If there is already an objects list with this name, no new
* list will be declared again.
*/
void ObjectsListWithoutPickingNeeded(const gd::String& objectName);
void ObjectsListNeededOrEmptyIfJustDeclared(const gd::String& objectName);
/**
* Call this when an instruction in the event needs an empty object list,
@@ -134,29 +137,21 @@ class GD_CORE_API EventsCodeGenerationContext {
void EmptyObjectsListNeeded(const gd::String& objectName);
/**
* Return true if an object list has already been declared (or is going to be
* declared).
* Return true if an object list has already been declared by the parent contexts.
*/
bool ObjectAlreadyDeclared(const gd::String& objectName) const {
bool ObjectAlreadyDeclaredByParents(const gd::String& objectName) const {
return (alreadyDeclaredObjectsLists.find(objectName) !=
alreadyDeclaredObjectsLists.end());
};
/**
* \brief Consider that \a objectName is now declared in the context.
*/
void SetObjectDeclared(const gd::String& objectName) {
alreadyDeclaredObjectsLists.insert(objectName);
}
/**
* Return all the objects lists which will be declared by the current context
* ( the non empty as well as the empty objects lists )
* (normal, potentially empty or empty).
*/
std::set<gd::String> GetAllObjectsToBeDeclared() const;
/**
* Return the objects lists which will be declared by the current context
* Return the objects lists which will be declared by the current context.
*/
const std::set<gd::String>& GetObjectsListsToBeDeclared() const {
return objectsListsToBeDeclared;
@@ -166,9 +161,9 @@ class GD_CORE_API EventsCodeGenerationContext {
* Return the objects lists which will be will be declared, without filling
* them with objects from the scene.
*/
const std::set<gd::String>& GetObjectsListsToBeDeclaredWithoutPicking()
const std::set<gd::String>& GetObjectsListsToBeEmptyIfJustDeclared()
const {
return objectsListsWithoutPickingToBeDeclared;
return objectsListsOrEmptyToBeDeclared;
};
/**
@@ -184,7 +179,7 @@ class GD_CORE_API EventsCodeGenerationContext {
* Return the objects lists which are already declared and can be used in the
* current context without declaration.
*/
const std::set<gd::String>& GetObjectsListsAlreadyDeclared() const {
const std::set<gd::String>& GetObjectsListsAlreadyDeclaredByParents() const {
return alreadyDeclaredObjectsLists;
};
@@ -227,22 +222,55 @@ class GD_CORE_API EventsCodeGenerationContext {
*/
size_t GetCurrentConditionDepth() const { return customConditionDepth; }
private:
/**
* \brief Returns the list of all objects declared in this context
* and subcontexts.
* \warning Only works on an async callback's context.
*
* It is to be used by the Async event code generator to know what objects
* lists to backup for the async callback and async callbacks after it.
*/
const std::set<gd::String>& GetAllDeclaredObjectsAcrossChildren() {
return allObjectsListToBeDeclaredAcrossChildren;
};
/**
* Returns true if an object list should be gotten from a backed up
* objects list instead of the parent context. This can happen inside an
* asynchronous callback or a child context of an asynchronous callback (i.e:
* the `asyncDepth` is not 0).
*/
bool ShouldUseAsyncObjectsList(const gd::String& objectName) const;
/**
* Returns true if the code currently being generated is inside an
* asynchronous context (either in an asynchronous callback, or in a children of
* an asynchronous callback).
*/
bool IsInsideAsync() const { return asyncDepth != 0; };
/**
* Returns true if the code currently being generated is an asynchronous
* callback (but not a child of an asynchronous callback).
*/
bool IsAsyncCallback() const { return parent != nullptr && parent->asyncDepth != asyncDepth; }
/**
* \brief Returns true if the given object is already going to be declared
* (either as a traditional objects list, or one without picking, or one
* empty).
*
* in this context (either as a traditional objects list, or an empty one).
*/
bool IsToBeDeclared(const gd::String& objectName) {
return objectsListsToBeDeclared.find(objectName) !=
objectsListsToBeDeclared.end() ||
objectsListsWithoutPickingToBeDeclared.find(objectName) !=
objectsListsWithoutPickingToBeDeclared.end() ||
objectsListsOrEmptyToBeDeclared.find(objectName) !=
objectsListsOrEmptyToBeDeclared.end() ||
emptyObjectsListsToBeDeclared.find(objectName) !=
emptyObjectsListsToBeDeclared.end();
};
private:
void NotifyAsyncParentsAboutDeclaredObject(const gd::String& objectName);
std::set<gd::String>
alreadyDeclaredObjectsLists; ///< Objects lists already needed in a
///< parent context.
@@ -250,7 +278,7 @@ class GD_CORE_API EventsCodeGenerationContext {
objectsListsToBeDeclared; ///< Objects lists that will be declared in
///< this context.
std::set<gd::String>
objectsListsWithoutPickingToBeDeclared; ///< Objects lists that will be
objectsListsOrEmptyToBeDeclared; ///< Objects lists that will be
///< declared in this context,
///< but not filled with scene's
///< objects.
@@ -260,21 +288,40 @@ class GD_CORE_API EventsCodeGenerationContext {
///< but not filled with scene's
///< objects and not filled with any
///< previously existing objects list.
std::set<gd::String>
allObjectsListToBeDeclaredAcrossChildren; ///< This is only to be used by
///< the async callback
///< contexts to know all
///< objects declared across
///< all children, so that the
///< necessary objects can be
///< backed up.
std::map<gd::String, unsigned int>
depthOfLastUse; ///< The context depth when an object was last used.
gd::String
currentObject; ///< The object being used by an action or condition.
unsigned int contextDepth; ///< The depth of the context : 0 for a newly
///< created context, n+1 for any context
///< inheriting from context with depth n.
unsigned int
customConditionDepth; ///< The depth of the conditions being generated.
unsigned int contextDepth = 0; ///< The depth of the context: 0 for a newly
///< created context, n+1 for any context
///< inheriting from context with depth n.
unsigned int customConditionDepth =
0; ///< The depth of the conditions being generated.
unsigned int asyncDepth =
0; ///< If higher than 0, the current context is an asynchronous callback,
///< or a child context of an asynchronous callback:
///< - If the parent's async depth != the current context async depth,
///< then the current context is an asynchronous callback context.
///< - Otherwise, it's a child of an asynchronous callback.
unsigned int* maxDepthLevel; ///< A pointer to a unsigned int updated with
///< the maximum depth reached.
const EventsCodeGenerationContext*
parent; ///< The parent of the current context. Can be NULL.
bool reuseExplicitlyForbidden; ///< If set to true, forbid children context
///< to reuse this one without inheriting.
const EventsCodeGenerationContext* parent =
nullptr; ///< The parent of the current context. Can be NULL.
EventsCodeGenerationContext* nearestAsyncParent =
nullptr; ///< The nearest parent context that is an async callback
///< context.
bool reuseExplicitlyForbidden =
false; ///< If set to true, forbid children contexts
///< to reuse this one without inheriting.
};
} // namespace gd

View File

@@ -450,7 +450,9 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
* Generate code for an action.
*/
gd::String EventsCodeGenerator::GenerateActionCode(
gd::Instruction& action, EventsCodeGenerationContext& context) {
gd::Instruction& action,
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
gd::String actionCode;
const gd::InstructionMetadata& instrInfos =
@@ -518,8 +520,12 @@ gd::String EventsCodeGenerator::GenerateActionCode(
// Prepare arguments and generate the whole action code
vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateObjectAction(
realObjects[i], objInfo, arguments, instrInfos, context);
actionCode += GenerateObjectAction(realObjects[i],
objInfo,
arguments,
instrInfos,
context,
optionalAsyncCallbackName);
context.SetNoCurrentObject();
}
@@ -552,7 +558,8 @@ gd::String EventsCodeGenerator::GenerateActionCode(
autoInfo,
arguments,
instrInfos,
context);
context,
optionalAsyncCallbackName);
context.SetNoCurrentObject();
}
@@ -560,12 +567,72 @@ gd::String EventsCodeGenerator::GenerateActionCode(
} else {
vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateFreeAction(arguments, instrInfos, context);
actionCode +=
GenerateFreeAction(arguments, instrInfos, context, optionalAsyncCallbackName);
}
return actionCode;
}
const EventsCodeGenerator::CallbackDescriptor
EventsCodeGenerator::GenerateCallback(
const gd::String& callbackID,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents) {
gd::EventsCodeGenerationContext callbackContext;
callbackContext.InheritsAsAsyncCallbackFrom(parentContext);
const gd::String callbackFunctionName =
GetCodeNamespaceAccessor() + "asyncCallback" + callbackID;
const gd::String callbackFunctionArguments =
GenerateEventsParameters(callbackContext);
// Generate actions
gd::String actionsCode = GenerateActionsListCode(actions, callbackContext);
// Generate subevents
if (subEvents != nullptr) // Sub events
{
actionsCode += "\n{ //Subevents\n";
actionsCode += GenerateEventsListCode(*subEvents, callbackContext);
actionsCode += "} //End of subevents\n";
}
// Compose the callback function and add outside main
const gd::String actionsDeclarationsCode =
GenerateObjectsDeclarationCode(callbackContext);
const gd::String callbackCode = callbackFunctionName + " = function (" +
GenerateEventsParameters(callbackContext) +
") {\n" + actionsDeclarationsCode +
actionsCode + "}\n";
AddCustomCodeOutsideMain(callbackCode);
std::set<gd::String> requiredObjects;
// Build the list of all objects required by the callback. Any object that has
// already been declared could have gone through previous object picking, so
// if such an object is used by the actions or subevents of this callback, we
// must ask the caller to pass the already existing objects lists through a
// `LongLivedObjectsList` to the callback function.
for (const auto& objectUsedInSubTree :
callbackContext.GetAllDeclaredObjectsAcrossChildren()) {
if (callbackContext.ObjectAlreadyDeclaredByParents(objectUsedInSubTree))
requiredObjects.insert(objectUsedInSubTree);
};
return CallbackDescriptor(
callbackFunctionName, callbackFunctionArguments, requiredObjects);
};
const gd::String EventsCodeGenerator::GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context) {
gd::String parameters = "runtimeScene";
if (!HasProjectAndLayout()) parameters += ", eventsFunctionContext";
if (context.IsInsideAsync()) parameters += ", asyncObjectsList";
return parameters;
};
/**
* Generate actions code.
*/
@@ -743,23 +810,21 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
gd::String declarationsCode;
for (auto object : context.GetObjectsListsToBeDeclared()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclared(object)) {
if (!context.ObjectAlreadyDeclaredByParents(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) +
" = runtimeContext->GetObjectsRawPointers(\"" +
ConvertToString(object) + "\");\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = declareObjectList(object, context);
declarationsCode += objectListDeclaration + "\n";
}
for (auto object : context.GetObjectsListsToBeDeclaredWithoutPicking()) {
for (auto object : context.GetObjectsListsToBeEmptyIfJustDeclared()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclared(object)) {
if (!context.ObjectAlreadyDeclaredByParents(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = declareObjectList(object, context);
@@ -767,10 +832,9 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
}
for (auto object : context.GetObjectsListsToBeDeclaredEmpty()) {
gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclared(object)) {
if (!context.ObjectAlreadyDeclaredByParents(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else
objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n";
@@ -785,7 +849,7 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
* Generate events list code.
*/
gd::String EventsCodeGenerator::GenerateEventsListCode(
gd::EventsList& events, const EventsCodeGenerationContext& parentContext) {
gd::EventsList& events, EventsCodeGenerationContext& parentContext) {
gd::String output;
for (std::size_t eId = 0; eId < events.size(); ++eId) {
// Each event has its own context : Objects picked in an event are totally
@@ -801,6 +865,8 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
// operation.
bool reuseParentContext =
parentContext.CanReuse() && eId == events.size() - 1;
// TODO: avoid creating if useless.
gd::EventsCodeGenerationContext reusedContext;
reusedContext.Reuse(parentContext);
@@ -1015,7 +1081,8 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
gd::String EventsCodeGenerator::GenerateFreeAction(
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context) {
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
// Generate call
gd::String call;
if (instrInfos.codeExtraInformation.type == "number" ||
@@ -1042,6 +1109,11 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
call = instrInfos.codeExtraInformation.functionCallName + "(" +
GenerateArgumentsList(arguments) + ")";
}
if (!optionalAsyncCallbackName.empty())
call = "runtimeScene.getAsyncTasksManager().addTask(" + call + ", " +
optionalAsyncCallbackName + ")";
return call + ";\n";
}
@@ -1050,7 +1122,8 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
const gd::ObjectMetadata& objInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context) {
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
// Create call
gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1077,8 +1150,11 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
call = instrInfos.codeExtraInformation.functionCallName + "(" +
argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ").\n";
argumentsStr + ")" +
(optionalAsyncCallbackName.empty() ? "" : (", then call" + optionalAsyncCallbackName)) +
".\n";
}
}
@@ -1088,7 +1164,8 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
const gd::BehaviorMetadata& autoInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context) {
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
// Create call
gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1114,8 +1191,11 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
call = instrInfos.codeExtraInformation.functionCallName + "(" +
argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ")" + " for behavior \"" + behaviorName + "\".\n";
argumentsStr + ")" + " for behavior \"" + behaviorName + "\"" +
(optionalAsyncCallbackName.empty() ? "" : (", then call" + optionalAsyncCallbackName)) +
".\n";
}
}

View File

@@ -77,7 +77,7 @@ class GD_CORE_API EventsCodeGenerator {
* \return Code
*/
virtual gd::String GenerateEventsListCode(
gd::EventsList& events, const EventsCodeGenerationContext& context);
gd::EventsList& events, EventsCodeGenerationContext& context);
/**
* \brief Generate code for executing a condition list
@@ -155,7 +155,51 @@ class GD_CORE_API EventsCodeGenerator {
* \return Code
*/
gd::String GenerateActionCode(gd::Instruction& action,
EventsCodeGenerationContext& context);
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
struct CallbackDescriptor {
CallbackDescriptor(const gd::String functionName_,
const gd::String argumentsList_,
const std::set<gd::String> requiredObjects_)
: functionName(functionName_),
argumentsList(argumentsList_),
requiredObjects(requiredObjects_){};
/**
* The name by which the function can be invoked.
*/
const gd::String functionName;
/**
* The comma separated list of arguments that the function takes.
*/
const gd::String argumentsList;
/**
* A set of all objects that need to be backed up to be passed to the callback code.
*/
const std::set<gd::String> requiredObjects;
};
/**
* \brief Generates actions and events as a callback.
*
* This is used by asynchronous functions to run the code out of the normal
* events flow.
*
* \returns A set with all objects required by the callback code.
* The caller must take care of backing them up in a LongLivedObjectsList,
* and to pass it to the callback function as the last argument.
*/
virtual const CallbackDescriptor GenerateCallback(
const gd::String& callbackFunctionName,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents = nullptr);
/**
* \brief Generates the parameters list of an event's generated function.
*/
const gd::String GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context);
/**
* \brief Generate code for declaring objects lists.
@@ -462,17 +506,10 @@ 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. Example:
* \code
AddExpression("Count", _("Object count"), _("Count the number of picked
objects"), _("Objects"), "res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.SetFunctionName("getPickedObjectsCount");
* \endcode
* - objectListWithoutPicking : Same as objectList but do not pick object if
object name in another parameter.
* - objectListOrEmptyIfJustDeclared : Same as `objectList` but do not pick object if
they are not already picked.
* - objectPtr : Return a reference to the object specified by the object name in
* - objectPtr: Return a reference to the object specified by the object name in
another parameter. Example:
* \code
.AddParameter("object", _("Object"))
@@ -665,14 +702,16 @@ class GD_CORE_API EventsCodeGenerator {
virtual gd::String GenerateFreeAction(
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context);
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
virtual gd::String GenerateObjectAction(
const gd::String& objectName,
const gd::ObjectMetadata& objInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context);
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
virtual gd::String GenerateBehaviorAction(
const gd::String& objectName,
@@ -680,7 +719,8 @@ class GD_CORE_API EventsCodeGenerator {
const gd::BehaviorMetadata& autoInfo,
const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context);
gd::EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
gd::String GenerateRelationalOperatorCall(
const gd::InstructionMetadata& instrInfos,

View File

@@ -5,8 +5,11 @@
*/
#include "GDCore/Events/Event.h"
#include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
@@ -65,10 +68,40 @@ gd::String BaseEvent::GenerateEventCode(
return "";
}
void BaseEvent::PreprocessAsyncActions(const gd::Platform& platform) {
if (!CanHaveSubEvents()) return;
for (const auto& actionsList : GetAllActionsVectors())
for (std::size_t aId = 0; aId < actionsList->size(); ++aId) {
const auto& action = actionsList->at(aId);
const gd::InstructionMetadata& actionMetadata =
gd::MetadataProvider::GetActionMetadata(platform, action.GetType());
if (actionMetadata.IsAsync()) {
gd::InstructionsList remainingActions;
remainingActions.InsertInstructions(
*actionsList, aId + 1, actionsList->size() - 1);
gd::AsyncEvent asyncEvent(action, remainingActions, GetSubEvents());
// Ensure that the local event no longer has any of the actions/subevent
// after the async function
actionsList->RemoveAfter(aId);
GetSubEvents().Clear();
GetSubEvents().InsertEvent(asyncEvent);
// We just moved all the rest, there's nothing left to do in this event.
return;
}
}
};
void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator,
gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList) {
if (IsDisabled() || !MustBePreprocessed()) return;
if (IsDisabled()) return;
PreprocessAsyncActions(codeGenerator.GetPlatform());
if (!MustBePreprocessed()) return;
try {
if (type.empty()) return;

View File

@@ -10,6 +10,7 @@
#include <iostream>
#include <memory>
#include <vector>
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
@@ -23,7 +24,7 @@ class EventsCodeGenerationContext;
class Platform;
class SerializerElement;
class Instruction;
}
} // namespace gd
namespace gd {
@@ -136,13 +137,15 @@ class GD_CORE_API BaseEvent {
* \note Used to preprocess or search in the expressions of the event.
*/
virtual std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() {
GetAllExpressionsWithMetadata() {
std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> > noExpr;
return noExpr;
};
virtual std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() const {
std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> > noExpr;
virtual std::vector<
std::pair<const gd::Expression*, const gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() const {
std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
noExpr;
return noExpr;
};
@@ -206,6 +209,11 @@ class GD_CORE_API BaseEvent {
gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList);
/**
* A function that turns all async member actions into an Async subevent for code generation.
*/
void PreprocessAsyncActions(const gd::Platform& platform);
/**
* \brief If MustBePreprocessed is redefined to return true, the
* gd::EventMetadata::preprocessing associated to the event will be called to

View File

@@ -5,6 +5,7 @@
*/
#include "InstructionsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Project/Project.h"
#include "Serialization.h"
@@ -31,6 +32,10 @@ void InstructionsList::InsertInstructions(const InstructionsList& list,
}
}
void InstructionsList::RemoveAfter(const size_t position) {
elements.resize(position);
}
void InstructionsList::SerializeTo(SerializerElement& element) const {
EventsListSerialization::SerializeInstructionsTo(*this, element);
}

View File

@@ -6,9 +6,10 @@
#ifndef GDCORE_INSTRUCTIONSLIST_H
#define GDCORE_INSTRUCTIONSLIST_H
#include "GDCore/Tools/SPtrList.h"
#include <memory>
#include <vector>
#include "GDCore/Tools/SPtrList.h"
namespace gd {
class Instruction;
}
@@ -22,11 +23,11 @@ class SerializerElement;
namespace gd {
class InstructionsList : public SPtrList<gd::Instruction> {
public:
void InsertInstructions(const InstructionsList& list,
size_t begin,
size_t end,
size_t position = (size_t)-1);
public:
void InsertInstructions(const InstructionsList &list, size_t begin,
size_t end, size_t position = (size_t)-1);
void RemoveAfter(size_t position);
/** \name Serialization
*/
@@ -35,17 +36,17 @@ class InstructionsList : public SPtrList<gd::Instruction> {
* \brief Serialize the instructions to the specified element
* \see EventsListSerialization
*/
void SerializeTo(gd::SerializerElement& element) const;
void SerializeTo(gd::SerializerElement &element) const;
/**
* \brief Load the instructions from the specified element
* \see EventsListSerialization
*/
void UnserializeFrom(gd::Project& project,
const gd::SerializerElement& element);
void UnserializeFrom(gd::Project &project,
const gd::SerializerElement &element);
///@}
};
} // namespace gd
} // namespace gd
#endif

View File

@@ -218,8 +218,8 @@ void EventsListSerialization::UnserializeEventsFrom(
event = std::make_shared<EmptyEvent>();
}
event->SetDisabled(eventElem.GetBoolAttribute("disabled"));
event->SetFolded(eventElem.GetBoolAttribute("folded"));
event->SetDisabled(eventElem.GetBoolAttribute("disabled", false));
event->SetFolded(eventElem.GetBoolAttribute("folded", false));
list.InsertEvent(event, list.GetEventsCount());
}
@@ -232,8 +232,8 @@ void EventsListSerialization::SerializeEventsTo(const EventsList& list,
const gd::BaseEvent& event = list.GetEvent(j);
SerializerElement& eventElem = events.AddChild("event");
eventElem.SetAttribute("disabled", event.IsDisabled());
eventElem.SetAttribute("folded", event.IsFolded());
if (event.IsDisabled()) eventElem.SetAttribute("disabled", event.IsDisabled());
if (event.IsFolded()) eventElem.SetAttribute("folded", event.IsFolded());
eventElem.AddChild("type").SetValue(event.GetType());
event.SerializeTo(eventElem);

View File

@@ -42,6 +42,7 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsTimeExtension(gd::PlatformExtension& extension);
static void ImplementsVariablesExtension(gd::PlatformExtension& extension);
static void ImplementsWindowExtension(gd::PlatformExtension& extension);
static void ImplementsAsyncExtension(gd::PlatformExtension& extension);
};
} // namespace gd

View File

@@ -0,0 +1,32 @@
/*
* 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/Events/Builtin/AsyncEvent.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
gd::PlatformExtension &extension) {
extension
.SetExtensionInformation(
"BuiltinAsync",
_("Async functions"),
_("Functions that defer the execution of the events after it."),
"Arthur Pacaud (arthuro555)",
"Open source (MIT License)")
.SetCategory("Advanced");
extension.AddEvent("Async",
_("Async event"),
_("Internal event for asynchronous actions"),
"",
"res/eventaddicon.png",
std::make_shared<gd::AsyncEvent>());
}
} // namespace gd

View File

@@ -343,6 +343,34 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsComplex();
extension
.AddAction(
"FadeSoundVolume",
_("Fade the volume of a sound played on a channel."),
_("Fade the volume of a sound played on a channel to the specified volume within the specified duration."),
_("Fade the sound on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddAction(
"FadeMusicVolume",
_("Fade the volume of a music played on a channel."),
_("Fade the volume of a music played on a channel to the specified volume within the specified duration."),
_("Fade the music on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddCondition("MusicPlaying",

View File

@@ -1252,7 +1252,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListWithoutPicking", _("Object to create"))
.AddParameter("objectListOrEmptyIfJustDeclared", _("Object to create"))
.AddParameter("expression", _("X position"))
.AddParameter("expression", _("Y position"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
@@ -1270,7 +1270,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/actions/create24.png",
"res/actions/create24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListWithoutPicking", _("Group of potential objects"))
.AddParameter("objectListOrEmptyIfJustDeclared", _("Group of potential objects"))
.SetParameterLongDescription(
_("Group containing objects that can be created by the action."))
.AddParameter("string", _("Name of the object to create"))
@@ -1418,7 +1418,33 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.UseStandardRelationalOperatorParameters("number")
.MarkAsSimple();
.MarkAsSimple()
.SetHidden();
extension.AddExpressionAndCondition(
"number",
"SceneInstancesCount",
_("Number of object instances on the scene"),
_("the number of instances of the specified objects living on the scene"),
_("the number of _PARAM1_ living on the scene"),
_("Objects"),
"res/conditions/nbObjet24.png")
.AddCodeOnlyParameter("objectsContext", "")
.AddParameter("objectListOrEmptyWithoutPicking", _("Object"))
.UseStandardParameters("number")
.MarkAsSimple();
extension.AddExpressionAndCondition(
"number",
"PickedInstancesCount",
_("Number of object instances currently picked"),
_("the number of instances picked by the previous conditions (or actions)"),
_("the number of _PARAM0_ currently picked"),
_("Objects"),
"res/conditions/nbObjet24.png")
.AddParameter("objectListOrEmptyWithoutPicking", _("Object"))
.UseStandardParameters("number")
.MarkAsSimple();
extension
.AddCondition(
@@ -1526,7 +1552,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
"currently picked in the event"),
"",
"res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"));
.AddParameter("objectList", _("Object"))
.SetHidden(); // Deprecated
obj.AddStrExpression("ObjectName",
_("Object name"),

View File

@@ -229,6 +229,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("ceilTo",
_("Ceil (round up) to a decimal point"),
_("Round number up to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("floor",
_("Floor (round down)"),
@@ -237,6 +246,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("floorTo",
_("Floor (round down) to a decimal point"),
_("Round number down to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("cos",
_("Cosine"),
@@ -295,6 +313,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));
extension
.AddExpression("roundTo",
_("Round to a decimal point"),
_("Round a number to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension
.AddExpression("exp",
_("Exponential"),

View File

@@ -121,7 +121,7 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
polygonElement.GetChild(k);
polygon.vertices.push_back(
sf::Vector2f(verticeElement.GetDoubleAttribute("x"),
gd::Vector2f(verticeElement.GetDoubleAttribute("x"),
verticeElement.GetDoubleAttribute("y")));
}

View File

@@ -4,7 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#include "Polygon2d.h"
#include <SFML/System/Vector2.hpp>
#include "GDCore/Vector2.h"
#include <cmath>
#include <iostream>
@@ -28,7 +28,7 @@ void Polygon2d::Move(float x, float y) {
}
void Polygon2d::ComputeEdges() const {
sf::Vector2f v1, v2;
gd::Vector2f v1, v2;
edges.clear();
for (std::size_t i = 0; i < vertices.size(); i++) {
@@ -62,8 +62,8 @@ bool Polygon2d::IsConvex() const {
return true;
}
sf::Vector2f Polygon2d::ComputeCenter() const {
sf::Vector2f center;
gd::Vector2f Polygon2d::ComputeCenter() const {
gd::Vector2f center;
for (std::size_t i = 0; i < vertices.size(); i++) {
center.x += vertices[i].x;
@@ -77,10 +77,10 @@ sf::Vector2f Polygon2d::ComputeCenter() const {
Polygon2d Polygon2d::CreateRectangle(float width, float height) {
Polygon2d rect;
rect.vertices.push_back(sf::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(sf::Vector2f(+width / 2.0f, -height / 2.0f));
rect.vertices.push_back(sf::Vector2f(+width / 2.0f, +height / 2.0f));
rect.vertices.push_back(sf::Vector2f(-width / 2.0f, +height / 2.0f));
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, +height / 2.0f));
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, +height / 2.0f));
return rect;
}

View File

@@ -5,7 +5,7 @@
*/
#ifndef GDCORE_POLYGON_H
#define GDCORE_POLYGON_H
#include <SFML/System/Vector2.hpp>
#include "GDCore/Vector2.h"
#include <vector>
/**
@@ -22,19 +22,19 @@ class GD_CORE_API Polygon2d {
Polygon2d(){};
virtual ~Polygon2d(){};
std::vector<sf::Vector2f> vertices; ///< The vertices composing the polygon
mutable std::vector<sf::Vector2f>
std::vector<gd::Vector2f> vertices; ///< The vertices composing the polygon
mutable std::vector<gd::Vector2f>
edges; ///< Edges. Can be computed from vertices using ComputeEdges()
/**
* \brief Get the vertices composing the polygon.
*/
std::vector<sf::Vector2f>& GetVertices() { return vertices; }
std::vector<gd::Vector2f>& GetVertices() { return vertices; }
/**
* \brief Get the vertices composing the polygon.
*/
const std::vector<sf::Vector2f>& GetVertices() const { return vertices; }
const std::vector<gd::Vector2f>& GetVertices() const { return vertices; }
/**
* \brief Moves each vertices from the given amount.
@@ -68,7 +68,7 @@ class GD_CORE_API Polygon2d {
/**
* \brief Return the position of the center of the polygon
*/
sf::Vector2f ComputeCenter() const;
gd::Vector2f ComputeCenter() const;
/** \name Tools
* Tool functions

View File

@@ -4,7 +4,6 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include <SFML/Graphics/Sprite.hpp>
#include <iostream>
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"

View File

@@ -6,7 +6,6 @@
#ifndef SPRITE_H
#define SPRITE_H
#include <SFML/Graphics/Sprite.hpp>
#include <memory>
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"

View File

@@ -6,7 +6,6 @@
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
#include <SFML/Graphics.hpp>
#include <algorithm>
#include "GDCore/CommonTools.h"

View File

@@ -20,7 +20,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
"for slow motion effects).",
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/all-features/timers");
.SetExtensionHelpPath("/all-features/timers-and-time");
extension.AddInstructionOrExpressionGroupMetadata(
_("Timers and time")
)
@@ -141,7 +141,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
_("Change time scale"),
_("Change the time scale of the scene."),
_("Set the time scale of the scene to _PARAM1_"),
"",
"res/actions/time24.png",
"res/actions/time.png")
@@ -149,6 +148,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTimeExtension(
.AddParameter("expression",
_("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)"));
extension
.AddAction("Wait",
_("Wait X seconds (experimental)"),
_("Waits a number of seconds before running "
"the next actions (and sub-events)."),
_("Wait _PARAM0_ seconds"),
"",
"res/timer.svg",
"res/timer.svg")
.AddParameter("expression", "Time to wait in seconds")
.SetHelpPath("/all-features/timers-and-time/wait-action")
.SetAsync();
extension
.AddExpression("TimeDelta",
_("Time elapsed since the last frame"),

View File

@@ -8,6 +8,7 @@
#include <functional>
#include <map>
#include <memory>
#include <algorithm>
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/String.h"

View File

@@ -22,6 +22,7 @@ InstructionMetadata::InstructionMetadata()
canHaveSubInstructions(false),
hidden(true),
usageComplexity(5),
isAsync(false),
isPrivate(false),
isObjectInstruction(false),
isBehaviorInstruction(false) {}
@@ -45,6 +46,7 @@ InstructionMetadata::InstructionMetadata(const gd::String& extensionNamespace_,
extensionNamespace(extensionNamespace_),
hidden(false),
usageComplexity(5),
isAsync(false),
isPrivate(false),
isObjectInstruction(false),
isBehaviorInstruction(false) {}

View File

@@ -9,6 +9,7 @@
#include <functional>
#include <map>
#include <memory>
#include <algorithm>
#include "GDCore/Events/Instruction.h"
#include "GDCore/String.h"
@@ -98,6 +99,23 @@ class GD_CORE_API InstructionMetadata {
return *this;
}
/**
* Check if the instruction is asynchronous - it will be running in the
* background, executing the instructions following it before the frame after
* it resolved.
*/
bool IsAsync() const { return isAsync; }
/**
* Set that the instruction is asynchronous - it will be running in the
* background, executing the instructions following it before the frame after
* it resolved.
*/
InstructionMetadata &SetAsync() {
isAsync = true;
return *this;
}
/**
* Notify that the instruction can have sub instructions.
*/
@@ -461,6 +479,7 @@ class GD_CORE_API InstructionMetadata {
int usageComplexity; ///< Evaluate the instruction from 0 (simple&easy to
///< use) to 10 (complex to understand)
bool isPrivate;
bool isAsync;
bool isObjectInstruction;
bool isBehaviorInstruction;
gd::String requiredBaseObjectCapability;

View File

@@ -152,15 +152,16 @@ class GD_CORE_API ParameterMetadata {
}
/**
* \brief Return true if the type of the parameter is "object", "objectPtr" or
* "objectList".
* \brief Return true if the type of the parameter is representing one object
* (or more, i.e: an object group).
*
* \see gd::ParameterMetadata::GetType
*/
static bool IsObject(const gd::String &parameterType) {
return parameterType == "object" || parameterType == "objectPtr" ||
parameterType == "objectList" ||
parameterType == "objectListWithoutPicking";
parameterType == "objectListOrEmptyIfJustDeclared" ||
parameterType == "objectListOrEmptyWithoutPicking";
}
/**

View File

@@ -117,6 +117,16 @@ void EffectsContainer::SwapEffects(std::size_t firstEffectIndex,
effects[secondEffectIndex] = temp;
}
void EffectsContainer::MoveEffect(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= effects.size() || newIndex >= effects.size() ||
newIndex == oldIndex)
return;
auto effect = effects[oldIndex];
effects.erase(effects.begin() + oldIndex);
effects.insert(effects.begin() + newIndex, effect);
}
void EffectsContainer::SerializeTo(SerializerElement& element) const {
element.ConsiderAsArrayOf("effect");
for (std::size_t i = 0; i < GetEffectsCount(); ++i) {

View File

@@ -7,6 +7,7 @@
#define GDCORE_EFFECTS_CONTAINER_H
#include <memory>
#include <vector>
#include <algorithm>
#include "GDCore/String.h"
@@ -89,6 +90,11 @@ class GD_CORE_API EffectsContainer {
*/
void RemoveEffect(const gd::String& name);
/**
* \brief Move the specified effect at a new position in the list.
*/
void MoveEffect(std::size_t oldIndex, std::size_t newIndex);
/**
* Swap the position of two effects.
*/

View File

@@ -5,7 +5,7 @@
*/
#ifndef GDCORE_OBJECT_H
#define GDCORE_OBJECT_H
#include <SFML/System/Vector2.hpp>
#include "GDCore/Vector2.h"
#include <map>
#include <memory>
#include <vector>

View File

@@ -7,6 +7,7 @@
#ifndef GDCORE_OBJECTGROUPSCONTAINER_H
#define GDCORE_OBJECTGROUPSCONTAINER_H
#include <vector>
#include <algorithm>
#include "GDCore/Project/ObjectGroup.h"
#include "GDCore/String.h"
namespace gd {
@@ -77,7 +78,6 @@ class GD_CORE_API ObjectGroupsContainer {
*/
bool IsEmpty() const { return objectGroups.empty(); };
#if defined(GD_IDE_ONLY)
/**
* \brief return the position of the group called "name" in the group list
*/
@@ -107,7 +107,6 @@ class GD_CORE_API ObjectGroupsContainer {
* \brief Move the specified group at a new position in the list.
*/
void Move(std::size_t oldIndex, std::size_t newIndex);
#endif
/**
* \brief Clear all groups of the container.

View File

@@ -9,7 +9,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <SFML/System/Utf.hpp>
#include <cctype>
#include <fstream>
#include <map>

View File

@@ -92,7 +92,7 @@ double Variable::GetValue() const {
return value;
} else if (type == Type::String) {
double retVal = str.empty() ? 0.0 : str.To<double>();
if(std::isnan(retVal)) retVal = 0.0;
if (std::isnan(retVal)) retVal = 0.0;
return retVal;
} else if (type == Type::Boolean) {
return boolVal ? 1.0 : 0.0;
@@ -188,6 +188,15 @@ const Variable& Variable::GetAtIndex(const size_t index) const {
return *childrenArray.at(index);
};
void Variable::MoveChildInArray(const size_t oldIndex, const size_t newIndex) {
if (oldIndex >= childrenArray.size() || newIndex >= childrenArray.size())
return;
std::shared_ptr<gd::Variable> object = std::move(childrenArray[oldIndex]);
childrenArray.erase(childrenArray.begin() + oldIndex);
childrenArray.insert(childrenArray.begin() + newIndex, std::move(object));
}
Variable& Variable::PushNew() { return GetAtIndex(GetChildrenCount()); };
void Variable::RemoveAtIndex(const size_t index) {
@@ -195,8 +204,29 @@ void Variable::RemoveAtIndex(const size_t index) {
childrenArray.erase(childrenArray.begin() + index);
};
bool Variable::InsertAtIndex(const gd::Variable& variable, const size_t index) {
if (type != Type::Array) return false;
auto newVariable = std::make_shared<gd::Variable>(variable);
if (index < childrenArray.size()) {
childrenArray.insert(childrenArray.begin() + index, newVariable);
} else {
childrenArray.push_back(newVariable);
}
return true;
};
bool Variable::InsertChild(const gd::String& name,
const gd::Variable& variable) {
if (type != Type::Structure || HasChild(name)) {
return false;
}
children[name] = std::make_shared<gd::Variable>(variable);
return true;
};
void Variable::SerializeTo(SerializerElement& element) const {
element.SetStringAttribute("type", TypeAsString(GetType()));
if (IsFolded()) element.SetBoolAttribute("folded", true);
if (type == Type::String) {
element.SetStringAttribute("value", GetString());
@@ -234,6 +264,7 @@ void Variable::UnserializeFrom(const SerializerElement& element) {
if (element.HasChild("children", "Children") && IsPrimitive(type))
type = Type::Structure;
// end of compatibility code
SetFolded(element.GetBoolAttribute("folded", false));
if (IsPrimitive(type)) {
if (type == Type::String) {
@@ -305,6 +336,7 @@ void Variable::RemoveRecursively(const gd::Variable& variableToRemove) {
Variable::Variable(const Variable& other)
: value(other.value),
str(other.str),
folded(other.folded),
boolVal(other.boolVal),
type(other.type) {
CopyChildren(other);
@@ -314,6 +346,7 @@ Variable& Variable::operator=(const Variable& other) {
if (this != &other) {
value = other.value;
str = other.str;
folded = other.folded;
boolVal = other.boolVal;
type = other.type;
CopyChildren(other);

View File

@@ -6,10 +6,10 @@
#ifndef GDCORE_VARIABLE_H
#define GDCORE_VARIABLE_H
#include <cmath>
#include <map>
#include <memory>
#include <vector>
#include <cmath>
#include "GDCore/String.h"
namespace gd {
@@ -98,7 +98,7 @@ class GD_CORE_API Variable {
void SetValue(double val) {
value = val;
// NaN values are not supported by GDevelop nor the serializer.
if(std::isnan(value)) value = 0.0;
if (std::isnan(value)) value = 0.0;
type = Type::Number;
}
@@ -185,9 +185,9 @@ class GD_CORE_API Variable {
* \brief Get the count of children that the variable has.
*/
size_t GetChildrenCount() const {
return type == Type::Structure
? children.size()
: type == Type::Array ? childrenArray.size() : 0;
return type == Type::Structure ? children.size()
: type == Type::Array ? childrenArray.size()
: 0;
};
/** \name Structure
@@ -290,12 +290,38 @@ class GD_CORE_API Variable {
*/
void RemoveAtIndex(const size_t index);
/**
* \brief Move child in array.
*/
void MoveChildInArray(const size_t oldIndex, const size_t newIndex);
/**
* \brief Insert child in array.
*/
bool InsertAtIndex(const gd::Variable& variable, const size_t index);
/**
* \brief Insert a child in a structure.
*/
bool InsertChild(const gd::String& name, const gd::Variable& variable);
/**
* \brief Get the vector containing all the children.
*/
const std::vector<std::shared_ptr<Variable>>& GetAllChildrenArray() const {
return childrenArray;
}
/**
* \brief Set if the children must be folded.
*/
void SetFolded(bool fold = true) { folded = fold; }
/**
* \brief True if the children should be folded in the variables editor.
*/
bool IsFolded() const { return folded; }
///@}
///@}
@@ -325,6 +351,7 @@ class GD_CORE_API Variable {
*/
static Type StringAsType(const gd::String& str);
bool folded;
mutable Type type;
mutable gd::String str;
mutable double value;

View File

@@ -4,8 +4,10 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Project/VariablesContainer.h"
#include <algorithm>
#include <iostream>
#include "GDCore/Project/Variable.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/String.h"
@@ -88,7 +90,6 @@ Variable& VariablesContainer::Insert(const gd::String& name,
}
}
#if defined(GD_IDE_ONLY)
void VariablesContainer::Remove(const gd::String& varName) {
variables.erase(
std::remove_if(
@@ -151,13 +152,14 @@ void VariablesContainer::Swap(std::size_t firstVariableIndex,
}
void VariablesContainer::Move(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= variables.size() || newIndex >= variables.size()) return;
if (oldIndex >= variables.size() || newIndex >= variables.size() ||
oldIndex == newIndex)
return;
auto nameAndVariable = variables[oldIndex];
variables.erase(variables.begin() + oldIndex);
variables.insert(variables.begin() + newIndex, nameAndVariable);
}
#endif
void VariablesContainer::SerializeTo(SerializerElement& element) const {
element.ConsiderAsArrayOf("variable");

View File

@@ -77,8 +77,6 @@ bool SerializerElement::GetBoolAttribute(const gd::String& name,
}
}
std::cout << "Bool attribute \"" << name << "\" not found, returning "
<< defaultValue;
return defaultValue;
}

View File

@@ -9,7 +9,6 @@
#include <algorithm>
#include <string.h>
#include <SFML/System/String.hpp>
#include "GDCore/CommonTools.h"
#include "GDCore/Utf8/utf8proc.h"
@@ -28,11 +27,6 @@ String::String(const char *characters) : m_string()
*this = characters;
}
String::String(const sf::String &string) : m_string()
{
*this = string;
}
String::String(const std::u32string &string) : m_string()
{
*this = string;
@@ -44,26 +38,6 @@ String& String::operator=(const char *characters)
return *this;
}
String& String::operator=(const sf::String &string)
{
m_string.clear();
//In theory, an UTF8 character can be up to 6 bytes (even if in the current Unicode standard,
//the last character is 4 bytes long when encoded in UTF8).
//So, reserve the maximum possible size to avoid reallocations.
m_string.reserve( string.getSize() * 6 );
//Push_back all characters inside the string.
for( sf::String::ConstIterator it = string.begin(); it != string.end(); ++it )
{
push_back( *it );
}
m_string.shrink_to_fit();
return *this;
}
String& String::operator=(const std::u32string &string)
{
m_string.clear();
@@ -112,7 +86,7 @@ String::const_iterator String::end() const
String String::FromLocale( const std::string &localizedString )
{
#if defined(WINDOWS)
return FromSfString(sf::String(localizedString)); //Don't need to use the current locale, on Windows, std::locale is always the C locale
return FromUTF8(localizedString); //Don't need to use the current locale, on Windows, std::locale is always the C locale
#elif defined(MACOS)
return FromUTF8(localizedString); //Assume UTF8 is the current locale
#elif defined(EMSCRIPTEN)
@@ -124,7 +98,7 @@ String String::FromLocale( const std::string &localizedString )
std::locale("").name().find("UTF8") != std::string::npos)
return FromUTF8(localizedString); //UTF8 is already the current locale
else
return FromSfString(sf::String(localizedString, std::locale(""))); //Use the current locale (std::locale("")) for conversion
return FromUTF8(localizedString); //Use the current locale (std::locale("")) for conversion
#endif
}
@@ -136,11 +110,6 @@ String String::FromUTF32( const std::u32string &string )
return str;
}
String String::FromSfString( const sf::String &sfString )
{
return String(sfString);
}
String String::FromUTF8( const std::string &utf8Str )
{
String str(utf8Str.c_str());
@@ -164,7 +133,7 @@ String String::FromWide( const std::wstring &wstr )
std::string String::ToLocale() const
{
#if defined(WINDOWS)
return ToSfString().toAnsiString();
return m_string;
#elif defined(MACOS)
return m_string;
#elif defined(EMSCRIPTEN)
@@ -176,7 +145,7 @@ std::string String::ToLocale() const
std::locale("").name().find("UTF8") != std::string::npos)
return m_string; //UTF8 is already the current locale on Linux
else
return ToSfString().toAnsiString(std::locale("")); //Use the current locale for conversion
return m_string; //Use the current locale for conversion
#endif
}
@@ -191,20 +160,6 @@ std::u32string String::ToUTF32() const
return u32str;
}
sf::String String::ToSfString() const
{
sf::String str;
for(const_iterator it = begin(); it != end(); ++it)
str += sf::String(static_cast<sf::Uint32>(*it));
return str;
}
String::operator sf::String() const
{
return ToSfString();
}
std::string String::ToUTF8() const
{
return m_string;

View File

@@ -13,12 +13,9 @@
#include <sstream>
#include <string>
#include <vector>
#include <SFML/System/String.hpp>
#include "GDCore/Utf8/utf8.h"
namespace sf {class String;};
namespace gd
{
@@ -121,11 +118,6 @@ public:
*/
String(const std::u32string &string);
/**
* Constructs a string from an sf::String.
*/
String(const sf::String &string);
/**
* \}
*/
@@ -146,8 +138,6 @@ public:
*/
String& operator=(const char *characters);
String& operator=(const sf::String &string);
String& operator=(const std::u32string &string);
/**
@@ -229,7 +219,6 @@ public:
static String From(T value)
{
static_assert(!std::is_same<T, std::string>::value, "Can't use gd::String::From with std::string.");
static_assert(!std::is_same<T, sf::String>::value, "Can't use gd::String::From with sf::String.");
std::ostringstream oss;
oss << value;
@@ -244,7 +233,6 @@ public:
T To() const
{
static_assert(!std::is_same<T, std::string>::value, "Can't use gd::String::To with std::string.");
static_assert(!std::is_same<T, sf::String>::value, "Can't use gd::String::To with sf::String.");
T value;
std::istringstream oss(m_string);
@@ -274,13 +262,6 @@ public:
*/
static String FromUTF32( const std::u32string &string );
/**
* \return a String created from a sf::String (UTF32).
*
* See \ref Conversions1 for more information.
*/
static String FromSfString( const sf::String &sfString );
/**
* \return a String created an UTF8 encoded std::string.
*/
@@ -312,20 +293,6 @@ public:
*/
std::u32string ToUTF32() const;
/**
* \return a sf::String from the current string.
*
* See \ref Conversions1 for more information.
*/
sf::String ToSfString() const;
/**
* Implicit conversion operator to sf::String.
*
* See \ref Conversions1 for more information.
*/
operator sf::String() const;
/**
* \return a UTF8 encoded std::string from the current string.
*/
@@ -885,7 +852,7 @@ namespace std
* on the string size and so is the operator[]().
*
* \section Conversion Conversions from/to other string types
* The String handles implicit conversion with sf::String (implicit constructor and implicit conversion
* The String handles implicit conversion with std::String (implicit constructor and implicit conversion
* operator).
*
* **However, this is not the case with std::string** as this conversion is not often lossless (mostly on Windows).
@@ -894,16 +861,6 @@ namespace std
* directly use the operator=() or the constructor as they are supporting const char* as argument (it assumes the string
* literal is encoded in UTF8, so you'll need to put the u8 prefix).
*
* \subsection Conversions1 Implicit conversion from/to sf::String
* \code
* //Get a String from sf::String
* sf::String sfmlStr("This is a test ! ");
* gd::String str1(sfmlStr); //Now contains "This is a test ! " encoded in UTF8
*
* //Get a sf::String from String
* sf::String anotherSfmlString = str; //anotherSfmlString now contains "Another test ! "
* \endcode
*
* \subsection Conversions2 Conversion from/to std::string
* \code
* //Get a String from a std::string encoded in the current locale

View File

@@ -1,200 +0,0 @@
#include "GDCore/Tools/FileStream.h"
#if defined(WINDOWS)
#if __GLIBCXX__
#include <ext/stdio_filebuf.h>
#endif
#endif
namespace gd {
namespace {
#if FSTREAM_WINDOWS_MINGW
#define MODE(in_val, out_val, trunc_val, app_val) \
((((mode & std::ios_base::in) != 0) == in_val) && \
(((mode & std::ios_base::out) != 0) == out_val) && \
(((mode & std::ios_base::trunc) != 0) == trunc_val) && \
(((mode & std::ios_base::app) != 0) == app_val))
std::wstring GetStdioMode(std::ios_base::openmode mode) {
std::wstring strMode;
/// Thanks to https://gcc.gnu.org/ml/libstdc++/2007-06/msg00013.html
if (MODE(false, true, false, false))
strMode += L"w";
else if (MODE(false, true, false, true))
strMode += L"a";
else if (MODE(true, true, false, true))
strMode += L"a+";
else if (MODE(false, true, true, false))
strMode += L"w";
else if (MODE(true, false, false, false))
strMode += L"r";
else if (MODE(true, true, false, false))
strMode += L"r+";
else if (MODE(true, true, true, false))
strMode += L"w+";
if ((mode & std::ios_base::binary) != 0) strMode += L"b";
return strMode;
}
#endif
/**
* Open the given file into a filebuf and return it.
* On Windows, return the associated FILE* inside the file argument.
*/
FileStream::InternalBufferType* OpenBuffer(const gd::String& path,
std::ios_base::openmode mode,
FILE** file) {
#if FSTREAM_WINDOWS_MINGW
*file = _wfopen(path.ToWide().c_str(), GetStdioMode(mode).c_str());
if (!(*file)) return nullptr;
return new __gnu_cxx::stdio_filebuf<char>(*file, mode);
#else
auto* filebuffer = new std::filebuf();
return filebuffer->open(path.ToLocale().c_str(), mode);
#endif
}
} // namespace
FileStream::FileStream() : std::iostream(nullptr) {}
FileStream::FileStream(const gd::String& path, std::ios_base::openmode mode)
: std::iostream(nullptr),
m_file(nullptr),
m_buffer(OpenBuffer(path, mode, &m_file)) {
setstate(ios_base::goodbit);
if (m_buffer) {
std::iostream::init(m_buffer.get());
if ((mode & std::ios_base::ate) != 0) seekg(0, end);
} else
setstate(ios_base::badbit);
}
FileStream::~FileStream() {
if (is_open()) close();
}
/*
WILL WORK with GCC>=5 (not 4.9 used on Windows)
FileStream::FileStream(FileStream && other) :
std::iostream(std::move(other)),
m_buffer(std::move(other.m_buffer))
{
}*/
/*FileStream& FileStream::operator=(FileStream && other)
{
std::iostream::operator=(std::move(other));
m_buffer = std::move(other.m_buffer);
}*/
void FileStream::open(const gd::String& path, std::ios_base::openmode mode) {
setstate(ios_base::goodbit);
if (is_open()) {
setstate(ios_base::failbit);
std::cout << "is_open true when trying to open!" << std::endl;
} else {
auto* newBuffer = OpenBuffer(path, mode, &m_file);
if (newBuffer) {
m_buffer.reset(newBuffer);
std::iostream::init(m_buffer.get());
if ((mode & std::ios_base::ate) != 0) seekg(0, end);
} else {
setstate(ios_base::badbit);
}
}
}
bool FileStream::is_open() const {
if (!m_buffer) return false;
return m_buffer->is_open();
}
void FileStream::close() {
#if FSTREAM_WINDOWS_MINGW
if (m_buffer) m_buffer->close();
if (m_file && fclose(m_file) != 0) {
setstate(ios_base::failbit);
}
m_buffer.reset(nullptr);
m_file = nullptr;
#else
if (!m_buffer || m_buffer->close() == nullptr) {
setstate(ios_base::failbit);
} else {
m_buffer.reset(nullptr);
}
#endif
}
/*void FileStream::swap(FileStream & other) //WILL WORK with GCC>=5 (not 4.9
used on Windows)
{
std::iostream::swap(other);
std::swap(m_buffer, other.m_buffer);
}*/
SFMLFileStream::SFMLFileStream() : m_file(nullptr) {}
SFMLFileStream::~SFMLFileStream() {
if (m_file) fclose(m_file);
}
bool SFMLFileStream::open(const gd::String& filename) {
if (m_file) fclose(m_file);
#if FSTREAM_WINDOWS_MINGW
m_file = _wfopen(filename.ToWide().c_str(), L"rb");
#else
m_file = fopen(filename.ToLocale().c_str(), "rb");
#endif
return m_file != NULL;
}
sf::Int64 SFMLFileStream::read(void* data, sf::Int64 size) {
if (m_file)
return fread(data, 1, static_cast<std::size_t>(size), m_file);
else
return -1;
}
sf::Int64 SFMLFileStream::seek(sf::Int64 position) {
if (m_file) {
fseek(m_file, static_cast<std::size_t>(position), SEEK_SET);
return tell();
} else {
return -1;
}
}
sf::Int64 SFMLFileStream::tell() {
if (m_file)
return ftell(m_file);
else
return -1;
}
sf::Int64 SFMLFileStream::getSize() {
if (m_file) {
sf::Int64 position = tell();
fseek(m_file, 0, SEEK_END);
sf::Int64 size = tell();
seek(position);
return size;
} else {
return -1;
}
}
} // namespace gd

View File

@@ -1,82 +0,0 @@
#ifndef GDCORE_FSTREAMTOOLS
#define GDCORE_FSTREAMTOOLS
#include <iostream>
#include <memory>
#include <SFML/System.hpp>
#include "GDCore/String.h"
#if defined(WINDOWS) && __GLIBCXX__
#include <ext/stdio_filebuf.h>
#else
#include <fstream> //for std::filebuf
#endif
namespace gd {
/**
* Similar to std::i/ofstream except that it can open file with
* gd::String paths (useful on Windows where fstream doesn't
* support wide paths).
*/
class GD_CORE_API FileStream : public std::iostream {
public:
#if defined(WINDOWS) && __GLIBCXX__
using InternalBufferType = std::basic_filebuf<char>;
#else
using InternalBufferType = std::filebuf;
#endif
FileStream();
FileStream(const gd::String& path, std::ios_base::openmode mode);
~FileStream();
FileStream(const FileStream& other) = delete;
FileStream(FileStream&& other) = delete; // HACK for GCC 4.9 (Windows)
// FileStream(FileStream && other); WILL WORK with GCC>=5 (not 4.9 used on
// Windows)
FileStream& operator=(const FileStream& other) = delete;
FileStream& operator=(FileStream&& other) =
delete; // HACK for GCC 4.9 (Windows)
// FileStream& operator=(FileStream && other); WILL WORK with GCC>=5 (not 4.9
// used on Windows)
void open(const gd::String& path, std::ios_base::openmode mode);
bool is_open() const;
void close();
// void swap(FileStream & other); //WILL WORK with GCC>=5 (not 4.9 used on
// Windows)
private:
FILE* m_file;
std::unique_ptr<InternalBufferType> m_buffer;
};
class GD_CORE_API SFMLFileStream : public sf::InputStream {
public:
SFMLFileStream();
~SFMLFileStream();
bool open(const gd::String& filename);
virtual sf::Int64 read(void* data, sf::Int64 size);
virtual sf::Int64 seek(sf::Int64 position);
virtual sf::Int64 tell();
virtual sf::Int64 getSize();
private:
FILE* m_file;
};
} // namespace gd
#endif

View File

@@ -1,19 +0,0 @@
#include <SFML/OpenGL.hpp>
#include <cmath>
namespace OpenGLTools {
void GD_CORE_API PerspectiveGL(GLdouble fovY,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar) {
const GLdouble pi = 3.1415926535897932384626433832795;
GLdouble fW, fH;
fH = std::tan(fovY / 360 * pi) * zNear;
fW = fH * aspect;
glFrustum(-fW, fW, -fH, fH, zNear, zFar);
}
} // namespace OpenGLTools

View File

@@ -1,9 +0,0 @@
#include <SFML/OpenGL.hpp>
namespace OpenGLTools {
void GD_CORE_API PerspectiveGL(GLdouble fovY,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar);
}

360
Core/GDCore/Vector2.h Normal file
View File

@@ -0,0 +1,360 @@
// This is adapted from SFML (https://github.com/SFML/SFML).
#ifndef GDCORE_VECTOR2_H
#define GDCORE_VECTOR2_H
namespace gd
{
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
/// \brief Utility template class for manipulating
/// 2-dimensional vectors
///
////////////////////////////////////////////////////////////
template <typename T>
class Vector2
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// Creates a Vector2(0, 0).
///
////////////////////////////////////////////////////////////
inline Vector2() :
x(0),
y(0)
{
}
////////////////////////////////////////////////////////////
/// \brief Construct the vector from its coordinates
///
/// \param X X coordinate
/// \param Y Y coordinate
///
////////////////////////////////////////////////////////////
inline Vector2(T X, T Y) :
x(X),
y(Y)
{
}
////////////////////////////////////////////////////////////
/// \brief Construct the vector from another type of vector
///
/// This constructor doesn't replace the copy constructor,
/// it's called only when U != T.
/// A call to this constructor will fail to compile if U
/// is not convertible to T.
///
/// \param vector Vector to convert
///
////////////////////////////////////////////////////////////
template <typename U>
inline explicit Vector2(const Vector2<U>& vector) :
x(static_cast<T>(vector.x)),
y(static_cast<T>(vector.y))
{
}
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
T x; ///< X coordinate of the vector
T y; ///< Y coordinate of the vector
};
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of unary operator -
///
/// \param right Vector to negate
///
/// \return Memberwise opposite of the vector
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator -(const Vector2<T>& right)
{
return Vector2<T>(-right.x, -right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator +=
///
/// This operator performs a memberwise addition of both vectors,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator +=(Vector2<T>& left, const Vector2<T>& right)
{
left.x += right.x;
left.y += right.y;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator -=
///
/// This operator performs a memberwise subtraction of both vectors,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator -=(Vector2<T>& left, const Vector2<T>& right)
{
left.x -= right.x;
left.y -= right.y;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator +
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Memberwise addition of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator +(const Vector2<T>& left, const Vector2<T>& right)
{
return Vector2<T>(left.x + right.x, left.y + right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator -
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return Memberwise subtraction of both vectors
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator -(const Vector2<T>& left, const Vector2<T>& right)
{
return Vector2<T>(left.x - right.x, left.y - right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator *
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Memberwise multiplication by \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator *(const Vector2<T>& left, T right)
{
return Vector2<T>(left.x * right, left.y * right);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator *
///
/// \param left Left operand (a scalar value)
/// \param right Right operand (a vector)
///
/// \return Memberwise multiplication by \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator *(T left, const Vector2<T>& right)
{
return Vector2<T>(right.x * left, right.y * left);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator *=
///
/// This operator performs a memberwise multiplication by \a right,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator *=(Vector2<T>& left, T right)
{
left.x *= right;
left.y *= right;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator /
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Memberwise division by \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T> operator /(const Vector2<T>& left, T right)
{
return Vector2<T>(left.x / right, left.y / right);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator /=
///
/// This operator performs a memberwise division by \a right,
/// and assigns the result to \a left.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a scalar value)
///
/// \return Reference to \a left
///
////////////////////////////////////////////////////////////
template <typename T>
inline Vector2<T>& operator /=(Vector2<T>& left, T right)
{
left.x /= right;
left.y /= right;
return left;
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator ==
///
/// This operator compares strict equality between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return True if \a left is equal to \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline bool operator ==(const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x == right.x) && (left.y == right.y);
}
////////////////////////////////////////////////////////////
/// \relates Vector2
/// \brief Overload of binary operator !=
///
/// This operator compares strict difference between two vectors.
///
/// \param left Left operand (a vector)
/// \param right Right operand (a vector)
///
/// \return True if \a left is not equal to \a right
///
////////////////////////////////////////////////////////////
template <typename T>
inline bool operator !=(const Vector2<T>& left, const Vector2<T>& right)
{
return (left.x != right.x) || (left.y != right.y);
}
// Define the most common types
typedef Vector2<int> Vector2i;
typedef Vector2<unsigned int> Vector2u;
typedef Vector2<float> Vector2f;
} // namespace gd
#endif // GDCORE_VECTOR2_H
////////////////////////////////////////////////////////////
/// \class gd::Vector2
/// \ingroup CommonProgrammingTools
///
/// gd::Vector2 is a simple class that defines a mathematical
/// vector with two coordinates (x and y). It can be used to
/// represent anything that has two dimensions: a size, a point,
/// a velocity, etc.
///
/// The template parameter T is the type of the coordinates. It
/// can be any type that supports arithmetic operations (+, -, /, *)
/// and comparisons (==, !=), for example int or float.
///
/// You generally don't have to care about the templated form (gd::Vector2<T>),
/// the most common specializations have special typedefs:
/// \li gd::Vector2<float> is gd::Vector2f
/// \li gd::Vector2<int> is gd::Vector2i
/// \li gd::Vector2<unsigned int> is gd::Vector2u
///
/// The gd::Vector2 class has a small and simple interface, its x and y members
/// can be accessed directly (there are no accessors like setX(), getX()) and it
/// contains no mathematical function like dot product, cross product, length, etc.
///
/// Usage example:
/// \code
/// gd::Vector2f v1(16.5f, 24.f);
/// v1.x = 18.2f;
/// float y = v1.y;
///
/// gd::Vector2f v2 = v1 * 5.f;
/// gd::Vector2f v3;
/// v3 = v1 + v2;
///
/// bool different = (v2 != v3);
/// \endcode
///
/// Note: for 3-dimensional vectors, see gd::Vector3.
///
////////////////////////////////////////////////////////////

View File

@@ -31,8 +31,8 @@ Extensions do have the same distinction between the "**IDE**" part and the "**Ru
In GDevelop, developers can associate and manipulate variables in their games. To represent them, we have two things:
- The **editor** `gd::Variable` that is part of the structure of the game, so living in [GDCore in Variable.h](https://docs.gdevelop-app.com/GDCore%20Documentation/classgd_1_1_variable.html). This is what is shown in the editor, saved on disk in the project file.
- The **game engine** variable, called `gdjs.Variable` in GDJS. [Documentation is in the GDJS **game engine**](https://docs.gdevelop-app.com/GDJS%20Runtime%20Documentation/Variable.html). This JavaScript class is what is used during a game.
- The **editor** `gd::Variable` that is part of the structure of the game, so living in [GDCore in Variable.h](https://docs.gdevelop.io/GDCore%20Documentation/classgd_1_1_variable.html). This is what is shown in the editor, saved on disk in the project file.
- The **game engine** variable, called `gdjs.Variable` in GDJS. [Documentation is in the GDJS **game engine**](https://docs.gdevelop.io/GDJS%20Runtime%20Documentation/classes/gdjs.Variable.html). This JavaScript class is what is used during a game.
The editor `gd::Variable` **knows nothing** about the game engine class `gdjs.Variable`. And the `gdjs.Variable` class in the game engine knows almost nothing from `gd::Variable` (apart from how it's written in JSON, to be able to load a game default variables).
@@ -56,10 +56,10 @@ The game engine is in GDJS/Runtime and is all written in TypeScript.
## What about events?
An "**event**" is by default something that [is mostly empty](https://docs.gdevelop-app.com/GDCore%20Documentation/classgd_1_1_base_event.html). In a more traditional programming language, an event can be seen as a scope or block (example: `{ some code here }` in a C style language like JavaScript, Java or C++).
An "**event**" is by default something that [is mostly empty](https://docs.gdevelop.io/GDCore%20Documentation/classgd_1_1_base_event.html). In a more traditional programming language, an event can be seen as a scope or block (example: `{ some code here }` in a C style language like JavaScript, Java or C++).
[Default events are defined](https://github.com/4ian/GDevelop/tree/master/Core/GDCore/Events/Builtin) in GDevelop Core.
In particular, there is StandardEvent, which has conditions and actions. Conditions and actions are both a list of [`gd::Instruction`](https://docs.gdevelop-app.com/GDCore%20Documentation/classgd_1_1_instruction.html). A `gd::Instruction` is either a condition or an action (it depends only on the context where they are used).
In particular, there is StandardEvent, which has conditions and actions. Conditions and actions are both a list of [`gd::Instruction`](https://docs.gdevelop.io/GDCore%20Documentation/classgd_1_1_instruction.html). A `gd::Instruction` is either a condition or an action (it depends only on the context where they are used).
A `gd::Instruction` is "just" a type (the name of the action or condition), and some parameters. You can think of it as a function in a programming language (`add(2, 3)` is calling a function called "add" with parameters "2" and "3"). Conditions have the special thing that they are functions returning true or false (and potentially being used to do a filter on the objects being picked for next conditions and actions).

View File

@@ -6,7 +6,7 @@ GDevelop Core is a portable C++ library, compiled to be used in JavaScript in th
## 1) Getting started 🤓
First, take a look at the _Readme.md_ at the root of the repository and the [developer documentation](https://docs.gdevelop-app.com/).
First, take a look at the _Readme.md_ at the root of the repository and the [developer documentation](https://docs.gdevelop.io/).
## 2) How to contribute 😎

View File

@@ -75,7 +75,11 @@ TEST_CASE("EventsList", "[common][events]") {
size_t endMemory = gd::SystemStats::GetUsedVirtualMemory();
INFO("Memory used: " << endMemory - startMemory << "KB");
REQUIRE(1500 >= endMemory - startMemory);
#if defined(WINDOWS)
REQUIRE(3000 >= endMemory - startMemory);
#else
REQUIRE(1500 >= endMemory - startMemory);
#endif
}
}

View File

@@ -31,7 +31,7 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
gd::EventsCodeGenerationContext c1(&maxDepth);
c1.ObjectsListNeeded("c1.object1");
c1.ObjectsListNeeded("c1.object2");
c1.ObjectsListWithoutPickingNeeded("c1.noPicking1");
c1.ObjectsListNeededOrEmptyIfJustDeclared("c1.noPicking1");
gd::EventsCodeGenerationContext c2;
c2.InheritsFrom(c1);
@@ -47,7 +47,7 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
gd::EventsCodeGenerationContext c5;
c5.InheritsFrom(c2);
c5.ObjectsListWithoutPickingNeeded("c5.noPicking1");
c5.ObjectsListNeededOrEmptyIfJustDeclared("c5.noPicking1");
c5.ObjectsListNeeded("c5.object1");
c5.ObjectsListNeeded("c1.object2");
c5.EmptyObjectsListNeeded("c5.empty1");
@@ -70,36 +70,36 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
}
SECTION("Object list needed") {
REQUIRE(c1.GetObjectsListsAlreadyDeclared() == std::set<gd::String>());
REQUIRE(c1.GetObjectsListsAlreadyDeclaredByParents() == std::set<gd::String>());
REQUIRE(c1.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c1.object1", "c1.object2"}));
REQUIRE(c1.GetObjectsListsToBeDeclaredWithoutPicking() ==
REQUIRE(c1.GetObjectsListsToBeEmptyIfJustDeclared() ==
std::set<gd::String>({"c1.noPicking1"}));
REQUIRE(c1.GetAllObjectsToBeDeclared() ==
std::set<gd::String>({"c1.object1", "c1.object2", "c1.noPicking1"}));
REQUIRE(c2.GetObjectsListsAlreadyDeclared() ==
REQUIRE(c2.GetObjectsListsAlreadyDeclaredByParents() ==
std::set<gd::String>({"c1.object1", "c1.object2", "c1.noPicking1"}));
REQUIRE(c2.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c2.object1"}));
REQUIRE(c2.GetObjectsListsToBeDeclaredWithoutPicking() == std::set<gd::String>());
REQUIRE(c2.GetObjectsListsToBeEmptyIfJustDeclared() == std::set<gd::String>());
REQUIRE(c2.GetAllObjectsToBeDeclared() ==
std::set<gd::String>({"c2.object1"}));
REQUIRE(c3.GetObjectsListsAlreadyDeclared() ==
REQUIRE(c3.GetObjectsListsAlreadyDeclaredByParents() ==
std::set<gd::String>({"c1.object1", "c1.object2", "c1.noPicking1"}));
REQUIRE(c3.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c3.object1", "c1.object2"}));
REQUIRE(c3.GetObjectsListsToBeDeclaredWithoutPicking() == std::set<gd::String>());
REQUIRE(c3.GetObjectsListsToBeEmptyIfJustDeclared() == std::set<gd::String>());
REQUIRE(c3.GetAllObjectsToBeDeclared() ==
std::set<gd::String>({"c3.object1", "c1.object2"}));
REQUIRE(c5.GetObjectsListsAlreadyDeclared() ==
REQUIRE(c5.GetObjectsListsAlreadyDeclaredByParents() ==
std::set<gd::String>(
{"c1.object1", "c1.object2", "c1.noPicking1", "c2.object1"}));
REQUIRE(c5.GetObjectsListsToBeDeclared() ==
std::set<gd::String>({"c5.object1", "c1.object2"}));
REQUIRE(c5.GetObjectsListsToBeDeclaredWithoutPicking() ==
REQUIRE(c5.GetObjectsListsToBeEmptyIfJustDeclared() ==
std::set<gd::String>({"c5.noPicking1"}));
REQUIRE(c5.GetObjectsListsToBeDeclaredEmpty() ==
std::set<gd::String>({"c5.empty1"}));
@@ -107,22 +107,18 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
std::set<gd::String>({"c5.object1", "c5.noPicking1", "c1.object2", "c5.empty1"}));
}
SECTION("ObjectAlreadyDeclared") {
REQUIRE(c1.ObjectAlreadyDeclared("c1.object1") == false);
REQUIRE(c2.ObjectAlreadyDeclared("c1.object1") == true);
REQUIRE(c3.ObjectAlreadyDeclared("c1.object1") == true);
REQUIRE(c4.ObjectAlreadyDeclared("c1.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclared("c1.object1") == true);
SECTION("ObjectAlreadyDeclaredByParents") {
REQUIRE(c1.ObjectAlreadyDeclaredByParents("c1.object1") == false);
REQUIRE(c2.ObjectAlreadyDeclaredByParents("c1.object1") == true);
REQUIRE(c3.ObjectAlreadyDeclaredByParents("c1.object1") == true);
REQUIRE(c4.ObjectAlreadyDeclaredByParents("c1.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclaredByParents("c1.object1") == true);
REQUIRE(c2.ObjectAlreadyDeclared("c2.object1") == false);
REQUIRE(c1.ObjectAlreadyDeclared("c2.object1") == false);
REQUIRE(c3.ObjectAlreadyDeclared("c2.object1") == false);
REQUIRE(c4.ObjectAlreadyDeclared("c2.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclared("c2.object1") == true);
REQUIRE(c3.ObjectAlreadyDeclared("some object") == false);
c3.SetObjectDeclared("some object");
REQUIRE(c3.ObjectAlreadyDeclared("some object") == true);
REQUIRE(c1.ObjectAlreadyDeclaredByParents("c2.object1") == false);
REQUIRE(c2.ObjectAlreadyDeclaredByParents("c2.object1") == false);
REQUIRE(c3.ObjectAlreadyDeclaredByParents("c2.object1") == false);
REQUIRE(c4.ObjectAlreadyDeclaredByParents("c2.object1") == true);
REQUIRE(c5.ObjectAlreadyDeclaredByParents("c2.object1") == true);
}
SECTION("Object list last depth") {
@@ -186,4 +182,87 @@ TEST_CASE("EventsCodeGenerationContext", "[common][events]") {
REQUIRE(c7.IsSameObjectsList("c6.object3", c6) == false);
REQUIRE(c7.IsSameObjectsList("c5.empty1", c5) == false);
}
SECTION("Async") {
gd::EventsCodeGenerationContext c1;
c1.ObjectsListNeeded("c1.object1");
c1.ObjectsListNeeded("c1.object2");
c1.ObjectsListNeededOrEmptyIfJustDeclared("c1.possiblyEmpty1");
c1.EmptyObjectsListNeeded("c1.empty1");
gd::EventsCodeGenerationContext c2;
c2.InheritsAsAsyncCallbackFrom(c1);
c2.ObjectsListNeeded("c2.object1");
c2.ObjectsListNeededOrEmptyIfJustDeclared("c2.possiblyEmpty1");
c2.EmptyObjectsListNeeded("c2.empty1");
c2.ObjectsListNeeded("c1.object1");
gd::EventsCodeGenerationContext c3;
c3.InheritsAsAsyncCallbackFrom(c2);
c3.ObjectsListNeeded("c3.object1");
c3.ObjectsListNeededOrEmptyIfJustDeclared("c3.possiblyEmpty1");
c3.EmptyObjectsListNeeded("c3.empty1");
c3.ObjectsListNeeded("c1.object1");
gd::EventsCodeGenerationContext c4;
c4.InheritsFrom(c3);
c4.ObjectsListNeeded("c4.object1");
c4.ObjectsListNeededOrEmptyIfJustDeclared("c4.possiblyEmpty1");
c4.EmptyObjectsListNeeded("c4.empty1");
c4.ObjectsListNeeded("c1.object1");
c4.ObjectsListNeeded("c1.object2");
gd::EventsCodeGenerationContext c5;
c5.InheritsFrom(c4);
c5.ObjectsListNeeded("c5.object1");
c5.ObjectsListNeededOrEmptyIfJustDeclared("c5.possiblyEmpty1");
c5.EmptyObjectsListNeeded("c5.empty1");
c5.ObjectsListNeeded("c1.object1");
c5.ObjectsListNeeded("c1.object2");
REQUIRE(c1.ShouldUseAsyncObjectsList("c1.object1") == false);
REQUIRE(c1.ShouldUseAsyncObjectsList("c1.possiblyEmpty1") == false);
REQUIRE(c1.ShouldUseAsyncObjectsList("c1.empty1") == false);
// Objects declared in async callback are used traditionally:
REQUIRE(c2.ShouldUseAsyncObjectsList("c2.object1") == false);
REQUIRE(c2.ShouldUseAsyncObjectsList("c2.possiblyEmpty1") == false);
REQUIRE(c2.ShouldUseAsyncObjectsList("c2.empty1") == false);
// Objects declared in c1 are gotten from the async list in c2 and c3
// because these contexts use them and are async.
REQUIRE(c2.ShouldUseAsyncObjectsList("c1.object1") == true);
REQUIRE(c3.ShouldUseAsyncObjectsList("c1.object1") == true);
REQUIRE(c4.ShouldUseAsyncObjectsList("c1.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c1.object1") == false);
// Objects declared in c1 are gotten from the async list in c4
// because c3 is async (but is not using them)
REQUIRE(c4.ShouldUseAsyncObjectsList("c1.object2") == true);
// Objects declared in c1 but gotten from the async list in c4
// is used traditionnally:
REQUIRE(c5.ShouldUseAsyncObjectsList("c1.object2") == false);
// Objects declared in or after c3 are used traditionally:
REQUIRE(c3.ShouldUseAsyncObjectsList("c3.object1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c3.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c3.object1") == false);
REQUIRE(c3.ShouldUseAsyncObjectsList("c3.possiblyEmpty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c3.possiblyEmpty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c3.possiblyEmpty1") == false);
REQUIRE(c3.ShouldUseAsyncObjectsList("c3.empty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c3.empty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c3.empty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c4.object1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c4.possiblyEmpty1") == false);
REQUIRE(c4.ShouldUseAsyncObjectsList("c4.empty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c4.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c4.possiblyEmpty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c4.empty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c5.object1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c5.possiblyEmpty1") == false);
REQUIRE(c5.ShouldUseAsyncObjectsList("c5.empty1") == false);
}
}

View File

@@ -1,90 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
/**
* @file Tests covering FileStream class of GDevelop Core.
*/
#include "GDCore/Tools/FileStream.h"
#include <fstream>
#include <memory>
#include "GDCore/CommonTools.h"
#include "catch.hpp"
TEST_CASE("FileStream", "[common][fstream]") {
// Creating the test file
std::ofstream testFile("FileStreamTest.test");
REQUIRE(testFile.is_open());
testFile << "this is the first line of the test file!\n";
testFile << "the last line!";
testFile.close();
SECTION("Input file") {
gd::FileStream f;
f.open("FileStreamTest.test", std::ios_base::in);
REQUIRE(f.is_open() == true);
REQUIRE(f.tellg() == 0);
std::string lineContent;
REQUIRE(f.eof() == false);
std::getline(f, lineContent);
REQUIRE(lineContent == "this is the first line of the test file!");
REQUIRE(f.eof() == false);
std::getline(f, lineContent);
REQUIRE(lineContent == "the last line!");
REQUIRE(f.eof() == true);
REQUIRE(f.fail() == false);
f.close();
REQUIRE(f.is_open() == false);
REQUIRE(f.fail() == false);
}
SECTION("Output/Input file with special characters in filepath") {
gd::FileStream output("\xEA\x88\xA1.txt", std::ios_base::out);
REQUIRE(output.is_open() == true);
output << "TEST";
output.close();
gd::FileStream input("\xEA\x88\xA1.txt", std::ios_base::in);
REQUIRE(input.is_open() == true);
std::string lineContent;
REQUIRE(input.eof() == false);
std::getline(input, lineContent);
REQUIRE(lineContent == "TEST");
REQUIRE(input.eof() == true);
input.close();
REQUIRE(input.is_open() == false);
REQUIRE(input.fail() == false);
}
SECTION("File opening failure") {
gd::FileStream f("\xE4\x84\xA2",
std::ios_base::in); // A file that doesn't exist
REQUIRE(f.is_open() == false);
REQUIRE(f.fail() ==
true); // As the opening failed, the "fail" flag should be set
f.close();
REQUIRE(f.bad() == true); // As no files are opened, this should set the
// "bad" flag of the stream
}
SECTION("std::ios_base::ate") { // As ate is "emulated", needs testing
gd::FileStream f;
f.open("FileStreamTest.test", std::ios_base::in | std::ios_base::ate);
REQUIRE(f.is_open() == true);
REQUIRE(f.tellg() > 0);
}
}

View File

@@ -7,7 +7,6 @@
* @file Tests covering utf8 features from GDevelop Core.
*/
#include <SFML/System/String.hpp>
#include <exception>
#include <iostream>
#include <string>
@@ -19,10 +18,8 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
SECTION("ctor & conversions") {
gd::String str = u8"UTF8 a été testé !";
sf::String sfStr = str;
std::u32string u32str = str.ToUTF32();
REQUIRE(str == gd::String::FromSfString(sfStr));
REQUIRE(str == gd::String::FromUTF32(u32str));
}
@@ -42,8 +39,10 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
REQUIRE(str.substr(5, 7) == u8"a été t");
REQUIRE(str.substr(5, gd::String::npos) == u8"a été testé !");
REQUIRE_THROWS_AS(str.substr(50, 5), std::out_of_range);
// Windows doesn't seems to like exceptions.
#if !defined(WINDOWS)
REQUIRE_THROWS_AS(str.substr(50, 5), std::out_of_range);
#endif
}
SECTION("insert") {
@@ -51,7 +50,9 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
str.insert(25, u8"vraiment ");
REQUIRE(str == u8"Une fonctionnalité a été vraiment testée !");
REQUIRE_THROWS_AS(str.insert(150, u8"This gonna fail"), std::out_of_range);
#if !defined(WINDOWS)
REQUIRE_THROWS_AS(str.insert(150, u8"This gonna fail"), std::out_of_range);
#endif
}
SECTION("replace") {
@@ -62,8 +63,10 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
REQUIRE(str.replace(11, gd::String::npos, u8"vraiment très testé !") ==
u8"UTF8 a été vraiment très testé !");
REQUIRE_THROWS_AS(str.replace(50, 5, u8"Cela va planter."),
std::out_of_range);
#if !defined(WINDOWS)
REQUIRE_THROWS_AS(str.replace(50, 5, u8"Cela va planter."),
std::out_of_range);
#endif
// Testing the iterator version of replace
gd::String str2 = u8"UTF8 a été testé !";
@@ -94,8 +97,10 @@ TEST_CASE("Utf8 String", "[common][utf8]") {
REQUIRE(str == "UTF8");
}
{
gd::String str = u8"UTF8 a été testé !";
REQUIRE_THROWS_AS(str.erase(100, 5), std::out_of_range);
#if !defined(WINDOWS)
gd::String str = u8"UTF8 a été testé !";
REQUIRE_THROWS_AS(str.erase(100, 5), std::out_of_range);
#endif
}
{
gd::String str = u8"UTF8 a été testé !";

View File

@@ -1,54 +0,0 @@
# Clone SFML from its official directory using Git. Only
# do it if not already cloned to avoid triggering a whole
# recompilation every time CMake is run.
find_package(Git)
if(GIT_FOUND)
if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/SFML/readme.txt")
message( "Cloning SFML in ExtLibs/SFML with Git..." )
execute_process(
COMMAND ${GIT_EXECUTABLE} clone "https://www.github.com/SFML/SFML.git" SFML
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
OUTPUT_QUIET)
message( "Resetting SFML source code to version 2.4.1..." )
execute_process(
COMMAND ${GIT_EXECUTABLE} reset --hard 2.4.1
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/SFML
OUTPUT_QUIET)
message( "Applying the patches..." )
file(GLOB SFML_PATCHES
LIST_DIRECTORIES FALSE
${CMAKE_CURRENT_SOURCE_DIR}/SFML-patches/*.patch)
if(SFML_PATCHES)
list(SORT SFML_PATCHES)
foreach(SFML_PATCH ${SFML_PATCHES})
message( "Applying patch: ${SFML_PATCH}..." )
execute_process(
COMMAND ${GIT_EXECUTABLE} apply ${SFML_PATCH} --ignore-whitespace
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/SFML
OUTPUT_QUIET)
endforeach()
endif()
else()
message( "SFML already downloaded." )
endif()
else()
message( "Git not found, make sure you have SFML >= 2.4 in ExtLibs/SFML and you applied the needed patches (from ExtLibs/SFML-patches)!" )
endif()
#SFML:
IF(NOT EMSCRIPTEN) #Don't build SFML binaries when compiling with emscripten (but keep include files!)
add_subdirectory(SFML)
set(sfml_lib_dir ${CMAKE_BINARY_DIR}/ExtLibs/SFML/lib PARENT_SCOPE)
set(sfml_LIBRARIES sfml-audio sfml-graphics sfml-window sfml-network sfml-system)
IF(WIN32)
set(sfml_LIBRARIES "${sfml_LIBRARIES}" ws2_32 user32 opengl32 glu32 psapi)
ELSEIF(NOT APPLE)
set(sfml_LIBRARIES "${sfml_LIBRARIES}" GLU GL)
ENDIF()
set(sfml_LIBRARIES "${sfml_LIBRARIES}" PARENT_SCOPE)
ENDIF()
set(sfml_include_dir ${CMAKE_CURRENT_SOURCE_DIR}/SFML/include PARENT_SCOPE)

View File

@@ -1,2 +0,0 @@
Uncompress here the external libraries needed: SFML.
Refer to [the documentation](https://docs.gdevelop-app.com/GDCore%20Documentation/setup_dev_env.html) for more information and to get the download links of the libraries.

View File

@@ -1,19 +0,0 @@
diff --git a/extlibs/headers/stb_image/stb_image.h b/extlibs/headers/stb_image/stb_image.h
index c3945c2..5fe1050 100644
--- a/extlibs/headers/stb_image/stb_image.h
+++ b/extlibs/headers/stb_image/stb_image.h
@@ -671,14 +671,9 @@ static int stbi__sse2_available()
static int stbi__sse2_available()
{
-#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later
- // GCC 4.8+ has a nice way to do this
- return __builtin_cpu_supports("sse2");
-#else
// portable way to do this, preferably without using GCC inline ASM?
// just bail for now.
return 0;
-#endif
}
#endif
#endif

View File

@@ -1,29 +0,0 @@
From f55ee73a73398bb77ce9c63ff1a13d8053cb1d18 Mon Sep 17 00:00:00 2001
From: Florian Rival <Florian.Rival@gmail.com>
Date: Tue, 3 Jan 2017 21:15:11 +0100
Subject: [PATCH] Fix crash with SFML embeded in wxWidgets on OS X
---
src/SFML/Window/OSX/SFViewController.mm | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/SFML/Window/OSX/SFViewController.mm b/src/SFML/Window/OSX/SFViewController.mm
index 7d736e3..280ec2b 100644
--- a/src/SFML/Window/OSX/SFViewController.mm
+++ b/src/SFML/Window/OSX/SFViewController.mm
@@ -82,8 +82,12 @@ -(id)initWithView:(NSView *)view
////////////////////////////////////////////////////////
-(void)dealloc
{
+ NSLog(@"SFViewController::dealloc called on %@", self);
[self closeWindow];
+
+ // See https://github.com/SFML/SFML/issues/824
+ [[NSNotificationCenter defaultCenter] removeObserver:m_oglView];
[m_view release];
[m_oglView release];
--
2.7.4 (Apple Git-66)

View File

@@ -1,13 +0,0 @@
diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp
index 9c68d84..2522d88 100644
--- a/include/SFML/Config.hpp
+++ b/include/SFML/Config.hpp
@@ -76,7 +76,7 @@
// Android
#define SFML_SYSTEM_ANDROID
- #elif defined(__linux__)
+ #elif defined(__linux__) || defined(EMSCRIPTEN)
// Linux
#define SFML_SYSTEM_LINUX

View File

@@ -45,6 +45,7 @@ module.exports = {
)
.addParameter('yesorno', _('Focus the window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -61,6 +62,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -79,6 +81,7 @@ module.exports = {
)
.addParameter('yesorno', _('Show window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -95,6 +98,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -113,6 +117,7 @@ module.exports = {
)
.addParameter('yesorno', _('Maximize window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -129,6 +134,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -147,6 +153,7 @@ module.exports = {
)
.addParameter('yesorno', _('Minimize window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -163,6 +170,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -181,6 +189,7 @@ module.exports = {
)
.addParameter('yesorno', _('Enable window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -197,6 +206,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -215,6 +225,7 @@ module.exports = {
)
.addParameter('yesorno', _('Allow resizing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -231,6 +242,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -249,6 +261,7 @@ module.exports = {
)
.addParameter('yesorno', _('Allow moving?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -265,6 +278,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -283,6 +297,7 @@ module.exports = {
)
.addParameter('yesorno', _('Allow maximizing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -299,6 +314,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -317,6 +333,7 @@ module.exports = {
)
.addParameter('yesorno', _('Allow minimizing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -333,6 +350,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -351,6 +369,7 @@ module.exports = {
)
.addParameter('yesorno', _('Allow full-screening?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -367,6 +386,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -385,6 +405,7 @@ module.exports = {
)
.addParameter('yesorno', _('Allow closing?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -401,6 +422,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -442,6 +464,7 @@ module.exports = {
'above the taskbar on Windows. ' +
'This parameter is ignored on linux.'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -458,6 +481,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -478,6 +502,7 @@ module.exports = {
)
.addParameter('yesorno', _('Enable kiosk mode?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -494,6 +519,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -512,6 +538,7 @@ module.exports = {
)
.addParameter('yesorno', _('Enable shadow?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -528,6 +555,7 @@ module.exports = {
'res/actions/window24.png',
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -548,6 +576,7 @@ module.exports = {
)
.addParameter('yesorno', _('Enable content protection?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -566,6 +595,7 @@ module.exports = {
)
.addParameter('yesorno', _('Allow focus?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -584,6 +614,7 @@ module.exports = {
)
.addParameter('yesorno', _('Flash the window?'), '', false)
.setDefaultValue('true')
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -604,6 +635,7 @@ module.exports = {
.setParameterLongDescription(
'A number between 0 (fully transparent) and 1 (fully opaque).'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -622,6 +654,7 @@ module.exports = {
)
.addParameter('expression', _('X position'), '', false)
.addParameter('expression', _('Y position'), '', false)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -636,6 +669,7 @@ module.exports = {
_('Windows, Linux, macOS'),
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -650,6 +684,7 @@ module.exports = {
_('Windows, Linux, macOS'),
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'
@@ -666,6 +701,7 @@ module.exports = {
_('Windows, Linux, macOS'),
'res/actions/window.png'
)
.addCodeOnlyParameter('currentScene', '')
.getCodeExtraInformation()
.setIncludeFile(
'Extensions/AdvancedWindow/electron-advancedwindowtools.js'

View File

@@ -6,16 +6,23 @@ namespace gdjs {
*/
export namespace evtTools {
export namespace advancedWindow {
/**
* The game's BrowserWindow instance (or null on
* non-electron platforms).
*/
let electronBrowserWindow: any = null;
const getElectronBrowserWindow = (runtimeScene: gdjs.RuntimeScene) => {
const electronRemote = runtimeScene
.getGame()
.getRenderer()
.getElectronRemote();
if (electronRemote) {
return electronRemote.getCurrentWindow();
}
if (typeof require === 'function') {
electronBrowserWindow = require('electron').remote.getCurrentWindow();
}
export const focus = function (activate: boolean) {
return null;
};
export const focus = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.focus();
@@ -25,14 +32,21 @@ namespace gdjs {
}
};
export const isFocused = function (): boolean {
export const isFocused = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isFocused();
}
return false;
};
export const show = function (activate: boolean) {
export const show = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.showInactive();
@@ -42,14 +56,21 @@ namespace gdjs {
}
};
export const isVisible = function (): boolean {
export const isVisible = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isVisible();
}
return false;
};
export const maximize = function (activate: boolean) {
export const maximize = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.maximize();
@@ -59,14 +80,21 @@ namespace gdjs {
}
};
export const isMaximized = function (): boolean {
export const isMaximized = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isMaximized();
}
return false;
};
export const minimize = function (activate: boolean) {
export const minimize = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
if (activate) {
electronBrowserWindow.minimize();
@@ -76,98 +104,150 @@ namespace gdjs {
}
};
export const isMinimized = function (): boolean {
export const isMinimized = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isMinimized();
}
return false;
};
export const enable = function (activate: boolean) {
export const enable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setEnabled(activate);
}
};
export const isEnabled = function (): boolean {
export const isEnabled = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isEnabled();
}
return false;
};
export const setResizable = function (activate: boolean) {
export const setResizable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setResizable(activate);
}
};
export const isResizable = function (): boolean {
export const isResizable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isResizable();
}
return false;
};
export const setMovable = function (activate: boolean) {
export const setMovable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setMovable(activate);
}
};
export const isMovable = function (): boolean {
export const isMovable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isMovable();
}
return false;
};
export const setMaximizable = function (activate: boolean) {
export const setMaximizable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setMaximizable(activate);
}
};
export const isMaximizable = function (): boolean {
export const isMaximizable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isMaximizable();
}
return false;
};
export const setMinimizable = function (activate: boolean) {
export const setMinimizable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setMinimizable(activate);
}
};
export const isMinimizable = function (): boolean {
export const isMinimizable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isMinimizable();
}
return false;
};
export const setFullScreenable = function (activate: boolean) {
export const setFullScreenable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setFullScreenable(activate);
}
};
export const isFullScreenable = function (): boolean {
export const isFullScreenable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isFullScreenable();
}
return false;
};
export const setClosable = function (activate: boolean) {
export const setClosable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setClosable(activate);
}
};
export const isClosable = function (): boolean {
export const isClosable = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isClosable();
}
@@ -184,93 +264,142 @@ namespace gdjs {
| 'main-menu'
| 'status'
| 'pop-up-menu'
| 'screen-saver'
| 'screen-saver',
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setAlwaysOnTop(activate, level);
}
};
export const isAlwaysOnTop = function (): boolean {
export const isAlwaysOnTop = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isAlwaysOnTop();
}
return false;
};
export const setPosition = function (x: float, y: float) {
export const setPosition = function (
x: float,
y: float,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
// Convert x and y to (32 bit) integers to avoid Electron errors.
electronBrowserWindow.setPosition(~~x, ~~y);
}
};
export const getPositionX = function (): number {
export const getPositionX = function (
runtimeScene: gdjs.RuntimeScene
): number {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.getPosition()[0];
}
return 0;
};
export const getPositionY = function (): number {
export const getPositionY = function (
runtimeScene: gdjs.RuntimeScene
): number {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.getPosition()[1];
}
return 0;
};
export const setKiosk = function (activate: boolean) {
export const setKiosk = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setKiosk(activate);
}
};
export const isKiosk = function (): boolean {
export const isKiosk = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.isKiosk();
}
return false;
};
export const flash = function (activate: boolean) {
export const flash = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.flashFrame(activate);
}
};
export const setHasShadow = function (activate: boolean) {
export const setHasShadow = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setHasShadow(activate);
}
};
export const hasShadow = function (): boolean {
export const hasShadow = function (
runtimeScene: gdjs.RuntimeScene
): boolean {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.hasShadow();
}
return false;
};
export const setOpacity = function (opacity: float) {
export const setOpacity = function (
opacity: float,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setOpacity(opacity);
}
};
export const getOpacity = function (): number {
export const getOpacity = function (
runtimeScene: gdjs.RuntimeScene
): number {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
return electronBrowserWindow.getOpacity();
}
return 1;
};
export const setContentProtection = function (activate: boolean) {
export const setContentProtection = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setContentProtection(activate);
}
};
export const setFocusable = function (activate: boolean) {
export const setFocusable = function (
activate: boolean,
runtimeScene: gdjs.RuntimeScene
) {
const electronBrowserWindow = getElectronBrowserWindow(runtimeScene);
if (electronBrowserWindow) {
electronBrowserWindow.setFocusable(activate);
}

View File

@@ -5,7 +5,9 @@ Copyright (c) 2016 Victor Levasseur (victorlevasseur52@gmail.com)
This project is released under the MIT License.
*/
#include "AnchorBehavior.h"
#include <map>
#include "GDCore/CommonTools.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/SerializerElement.h"
@@ -20,6 +22,7 @@ void AnchorBehavior::InitializeContent(gd::SerializerElement& content) {
content.SetAttribute("topEdgeAnchor", static_cast<int>(ANCHOR_VERTICAL_NONE));
content.SetAttribute("bottomEdgeAnchor",
static_cast<int>(ANCHOR_VERTICAL_NONE));
content.SetAttribute("useLegacyBottomAndRightAnchors", false);
}
#if defined(GD_IDE_ONLY)
@@ -68,7 +71,7 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("Window left"))
.AddExtraInfo(_("Window right"))
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Use this to anchor the object on X axis."));
.SetDescription(_("Anchor the left edge of the object on X axis."));
properties[_("Right edge anchor")]
.SetValue(GetAnchorAsString(static_cast<HorizontalAnchor>(
@@ -77,7 +80,8 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("No anchor"))
.AddExtraInfo(_("Window left"))
.AddExtraInfo(_("Window right"))
.AddExtraInfo(_("Proportional"));
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Anchor the right edge of the object on X axis."));
properties[_("Top edge anchor")]
.SetValue(GetAnchorAsString(static_cast<VerticalAnchor>(
@@ -87,7 +91,7 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("Window top"))
.AddExtraInfo(_("Window bottom"))
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Use this to anchor the object on Y axis."));
.SetDescription(_("Anchor the top edge of the object on Y axis."));
properties[_("Bottom edge anchor")]
.SetValue(GetAnchorAsString(static_cast<VerticalAnchor>(
@@ -96,7 +100,20 @@ std::map<gd::String, gd::PropertyDescriptor> AnchorBehavior::GetProperties(
.AddExtraInfo(_("No anchor"))
.AddExtraInfo(_("Window top"))
.AddExtraInfo(_("Window bottom"))
.AddExtraInfo(_("Proportional"));
.AddExtraInfo(_("Proportional"))
.SetDescription(_("Anchor the bottom edge of the object on Y axis."));
properties[("useLegacyBottomAndRightAnchors")]
.SetLabel(_(
"Stretch object when anchoring right or bottom ledge (deprecated, "
"it's recommended to let this unchecked and anchor both sides if you "
"want Sprite to stretch instead.)"))
.SetGroup(_("Deprecated options (advanced)"))
.SetValue(behaviorContent.GetBoolAttribute(
"useLegacyBottomAndRightAnchors", true)
? "true"
: "false")
.SetType("Boolean");
return properties;
}
@@ -147,6 +164,9 @@ bool AnchorBehavior::UpdateProperty(gd::SerializerElement& behaviorContent,
behaviorContent.SetAttribute(
"bottomEdgeAnchor",
static_cast<int>(GetVerticalAnchorFromString(value)));
else if (name == "useLegacyBottomAndRightAnchors")
behaviorContent.SetAttribute("useLegacyBottomAndRightAnchors",
(value == "1"));
else
return false;

View File

@@ -15,6 +15,7 @@ namespace gdjs {
_rightEdgeDistance: number = 0;
_topEdgeDistance: number = 0;
_bottomEdgeDistance: number = 0;
_useLegacyBottomAndRightAnchors: boolean = false;
constructor(runtimeScene, behaviorData, owner) {
super(runtimeScene, behaviorData, owner);
@@ -23,6 +24,10 @@ namespace gdjs {
this._rightEdgeAnchor = behaviorData.rightEdgeAnchor;
this._topEdgeAnchor = behaviorData.topEdgeAnchor;
this._bottomEdgeAnchor = behaviorData.bottomEdgeAnchor;
this._useLegacyBottomAndRightAnchors =
behaviorData.useLegacyBottomAndRightAnchors === undefined
? true
: behaviorData.useLegacyBottomAndRightAnchors;
}
updateFromBehaviorData(oldBehaviorData, newBehaviorData): boolean {
@@ -40,6 +45,13 @@ namespace gdjs {
) {
this._bottomEdgeAnchor = newBehaviorData.bottomEdgeAnchor;
}
if (
oldBehaviorData.useLegacyTrajectory !==
newBehaviorData.useLegacyTrajectory
) {
this._useLegacyBottomAndRightAnchors =
newBehaviorData.useLegacyBottomAndRightAnchors;
}
if (
oldBehaviorData.relativeToOriginalWindowSize !==
newBehaviorData.relativeToOriginalWindowSize
@@ -262,28 +274,94 @@ namespace gdjs {
bottomPixel
);
//Move and resize the object according to the anchors
if (
this._rightEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
// Compatibility with GD <= 5.0.133
if (this._useLegacyBottomAndRightAnchors) {
//Move and resize the object according to the anchors
if (
this._rightEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
}
if (
this._bottomEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
}
if (
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
);
}
if (
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
);
}
}
if (
this._bottomEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
}
if (
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
);
}
if (this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
);
// End of compatibility code
else {
// Resize if right and left anchors are set
if (
this._rightEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE &&
this._leftEdgeAnchor !== AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setWidth(bottomRightCoord[0] - topLeftCoord[0]);
this.owner.setX(topLeftCoord[0]);
} else {
if (
this._leftEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
topLeftCoord[0] + this.owner.getX() - this.owner.getDrawableX()
);
}
if (
this._rightEdgeAnchor !==
AnchorRuntimeBehavior.HorizontalAnchor.NONE
) {
this.owner.setX(
bottomRightCoord[0] +
this.owner.getX() -
this.owner.getDrawableX() -
this.owner.getWidth()
);
}
}
// Resize if top and bottom anchors are set
if (
this._bottomEdgeAnchor !==
AnchorRuntimeBehavior.VerticalAnchor.NONE &&
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setHeight(bottomRightCoord[1] - topLeftCoord[1]);
this.owner.setY(topLeftCoord[1]);
} else {
if (
this._topEdgeAnchor !== AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
topLeftCoord[1] + this.owner.getY() - this.owner.getDrawableY()
);
}
if (
this._bottomEdgeAnchor !==
AnchorRuntimeBehavior.VerticalAnchor.NONE
) {
this.owner.setY(
bottomRightCoord[1] +
this.owner.getY() -
this.owner.getDrawableY() -
this.owner.getHeight()
);
}
}
}
}
}

View File

@@ -0,0 +1,204 @@
// @ts-check
describe.only('gdjs.AnchorRuntimeBehavior', function () {
const runtimeGame = new gdjs.RuntimeGame({
variables: [],
resources: { resources: [] },
// @ts-ignore
properties: { windowWidth: 1000, windowHeight: 1000 },
});
const anchorBehaviorName = 'Anchor';
const runtimeScene = new gdjs.RuntimeScene(runtimeGame);
runtimeScene.loadFromScene({
layers: [
{
name: '',
visibility: true,
cameras: [],
effects: [],
ambientLightColorR: 127,
ambientLightColorB: 127,
ambientLightColorG: 127,
isLightingLayer: false,
followBaseLayerCamera: false,
},
],
variables: [],
r: 0,
v: 0,
b: 0,
mangledName: 'Scene1',
name: 'Scene1',
stopSoundsOnStartup: false,
title: '',
behaviorsSharedData: [],
objects: [],
instances: [],
});
function createObject(behaviorProperties) {
const object = new gdjs.TestRuntimeObject(runtimeScene, {
name: 'obj1',
type: '',
behaviors: [
{
name: anchorBehaviorName,
type: 'AnchorBehavior::AnchorBehavior',
// @ts-ignore - properties are not typed
rightEdgeAnchor: 0,
leftEdgeAnchor: 0,
topEdgeAnchor: 0,
bottomEdgeAnchor: 0,
relativeToOriginalWindowSize: true,
useLegacyBottomAndRightAnchors: false,
...behaviorProperties,
},
],
variables: [],
effects: [],
});
object.setCustomWidthAndHeight(10, 10);
runtimeScene.addObject(object);
return object;
}
function getAnchorBehavior(object) {
const behavior = object.getBehavior(anchorBehaviorName);
if (!(behavior instanceof gdjs.AnchorRuntimeBehavior)) {
throw new Error(
'Expected behavior to be an instance of gdjs.AnchorBehavior'
);
}
return behavior;
}
describe('(anchor horizontal edge)', function () {
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window left (fixed)`, function () {
const object = createObject({ [objectEdge]: 1 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['rightEdgeAnchor', 'leftEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window right (fixed)`, function () {
const object = createObject({ [objectEdge]: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(1500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the right and left edge of object (fixed)', function () {
const object = createObject({ leftEdgeAnchor: 1, rightEdgeAnchor: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(1010);
});
it('anchors the left edge of object (proportional)', function () {
const object = createObject({ leftEdgeAnchor: 3 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(1000);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
describe('(anchor vertical edge)', function () {
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window top (fixed)`, function () {
const object = createObject({ [objectEdge]: 1 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getWidth()).to.equal(10);
});
});
['topEdgeAnchor', 'bottomEdgeAnchor'].forEach((objectEdge) => {
it(`anchors the ${objectEdge} edge of object to window bottom (fixed)`, function () {
const object = createObject({ [objectEdge]: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1500);
expect(object.getWidth()).to.equal(10);
});
});
it('anchors the top and bottom edge of object (fixed)', function () {
const object = createObject({ topEdgeAnchor: 1, bottomEdgeAnchor: 2 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(500);
expect(object.getHeight()).to.equal(1010);
});
it('anchors the top edge of object (proportional)', function () {
const object = createObject({ topEdgeAnchor: 3 });
runtimeGame.setGameResolutionSize(1000, 1000);
object.setPosition(500, 500);
runtimeScene.renderAndStep(1000 / 60);
runtimeGame.setGameResolutionSize(2000, 2000);
runtimeScene.renderAndStep(1000 / 60);
expect(object.getX()).to.equal(500);
expect(object.getY()).to.equal(1000);
expect(object.getWidth()).to.equal(10);
});
});
});

View File

@@ -4,7 +4,6 @@
# consist in a few lines containing calls to these functions.
macro(gd_add_extension_includes)
include_directories(${sfml_include_dir})
include_directories(${GDCORE_include_dir})
endmacro()
@@ -81,7 +80,6 @@ function(gd_extension_link_libraries target_name)
#Nothing.
ELSE()
target_link_libraries(${target_name} GDCore)
target_link_libraries(${target_name} ${sfml_LIBRARIES})
ENDIF()
endfunction()

View File

@@ -7,7 +7,7 @@ This project is released under the MIT License.
#ifndef DRAGGABLEBEHAVIOR_H
#define DRAGGABLEBEHAVIOR_H
#include <SFML/System/Vector2.hpp>
#include "GDCore/Vector2.h"
#include <map>
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Object.h"

View File

@@ -307,7 +307,7 @@ module.exports = {
.setLabel(_('Color map texture for the effect'))
.setDescription(
_(
'You can change colors of pixels by modifing a reference color image, containing each colors, called the *Color Map Texture*. To get started, **download** [a default color map texture here](http://wiki.compilgames.net/doku.php/gdevelop5/interface/scene-editor/layer-effects).'
'You can change colors of pixels by modifing a reference color image, containing each colors, called the *Color Map Texture*. To get started, **download** [a default color map texture here](https://wiki.gdevelop.io/gdevelop5/interface/scene-editor/layer-effects).'
)
);
colorMapProperties
@@ -442,7 +442,7 @@ module.exports = {
.setLabel(_('Displacement map texture'))
.setDescription(
_(
'Displacement map texture for the effect. To get started, **download** [a default displacement map texture here](http://wiki.compilgames.net/doku.php/gdevelop5/interface/scene-editor/layer-effects).'
'Displacement map texture for the effect. To get started, **download** [a default displacement map texture here](https://wiki.gdevelop.io/gdevelop5/interface/scene-editor/layer-effects).'
)
);
displacementProperties

View File

@@ -68,7 +68,7 @@ module.exports = {
.setFullName(_('Dummy effect example'))
.setDescription(
_(
'This is an example of an effect ("shader") with an [external link to the wiki](http://wiki.compilgames.net/doku.php/gdevelop5/) and **bold letters**.'
'This is an example of an effect ("shader") with an [external link to the wiki](https://wiki.gdevelop.io/gdevelop5/) and **bold letters**.'
)
)
.addIncludeFile('Extensions/ExampleJsExtension/dummyeffect.js');

View File

@@ -8,22 +8,18 @@ namespace gdjs {
/** Get the Node.js path module, or null if it can't be loaded */
export const _getPath = function () {
if (!gdjs.fileSystem._path) {
// @ts-ignore
gdjs.fileSystem._path =
typeof require !== 'undefined' ? require('path') : null;
if (!_path) {
_path = typeof require !== 'undefined' ? require('path') : null;
}
return gdjs.fileSystem._path;
return _path;
};
/** Get the Node.js fs module, or null if it can't be loaded */
export const _getFs = function () {
if (!gdjs.fileSystem._fs) {
// @ts-ignore
gdjs.fileSystem._fs =
typeof require !== 'undefined' ? require('fs') : null;
if (!_fs) {
_fs = typeof require !== 'undefined' ? require('fs') : null;
}
return gdjs.fileSystem._fs;
return _fs;
};
export const getDirectoryName = function (fileOrFolderPath: string) {
@@ -58,9 +54,10 @@ namespace gdjs {
export const getDesktopPath = function (
runtimeScene: gdjs.RuntimeScene
): string {
const electron = runtimeScene.getGame().getRenderer().getElectron();
if (electron) {
return electron.remote.app.getPath('desktop') || '';
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('desktop') || '';
} else {
return '';
}
@@ -74,9 +71,10 @@ namespace gdjs {
export const getDocumentsPath = function (
runtimeScene: gdjs.RuntimeScene
): string {
const electron = runtimeScene.getGame().getRenderer().getElectron();
if (electron) {
return electron.remote.app.getPath('documents') || '';
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('documents') || '';
} else {
return '';
}
@@ -90,9 +88,10 @@ namespace gdjs {
export const getPicturesPath = function (
runtimeScene: gdjs.RuntimeScene
): string {
const electron = runtimeScene.getGame().getRenderer().getElectron();
if (electron) {
return electron.remote.app.getPath('pictures') || '';
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('pictures') || '';
} else {
return '';
}
@@ -106,9 +105,10 @@ namespace gdjs {
export const getExecutablePath = function (
runtimeScene: gdjs.RuntimeScene
): string {
const electron = runtimeScene.getGame().getRenderer().getElectron();
if (electron) {
return electron.remote.app.getPath('exe') || '';
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('exe') || '';
} else {
return '';
}
@@ -138,9 +138,10 @@ namespace gdjs {
export const getUserdataPath = function (
runtimeScene: gdjs.RuntimeScene
): string {
const electron = runtimeScene.getGame().getRenderer().getElectron();
if (electron) {
return electron.remote.app.getPath('userData') || '';
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('userData') || '';
} else {
return '';
}
@@ -153,9 +154,10 @@ namespace gdjs {
export const getUserHomePath = function (
runtimeScene: gdjs.RuntimeScene
): string {
const electron = runtimeScene.getGame().getRenderer().getElectron();
if (electron) {
return electron.remote.app.getPath('home') || '';
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('home') || '';
} else {
return '';
}
@@ -169,9 +171,10 @@ namespace gdjs {
export const getTempPath = function (
runtimeScene: gdjs.RuntimeScene
): string {
const electron = runtimeScene.getGame().getRenderer().getElectron();
if (electron) {
return electron.remote.app.getPath('temp') || '';
const remote = runtimeScene.getGame().getRenderer().getElectronRemote();
const app = remote ? remote.app : null;
if (app) {
return app.getPath('temp') || '';
} else {
return '';
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1324,7 +1324,7 @@ module.exports = {
true
)
.setParameterLongDescription(
'See the shape of the returned data on [the wiki page](http://wiki.compilgames.net/doku.php/gdevelop5/all-features/firebase/firestore#the_query_result).'
'See the shape of the returned data on [the wiki page](https://wiki.gdevelop.io/gdevelop5/all-features/firebase/firestore#the_query_result).'
)
.addParameter(
'scenevar',

View File

@@ -35,7 +35,7 @@ module.exports = {
)
.setExtensionHelpPath('/all-features/leaderboards')
.setCategory('Leaderboards')
.addInstructionOrExpressionGroupMetadata(_('Leaderboards'))
.addInstructionOrExpressionGroupMetadata(_('Leaderboards (experimental)'))
.setIcon('JsPlatform/Extensions/leaderboard.svg');
extension
@@ -59,20 +59,6 @@ module.exports = {
false
)
.addParameter('string', _('Name to register for the player'), '', false)
.addParameter(
'scenevar',
_('Variable where to store the saved score (optional)'),
'',
true
)
.addParameter(
'scenevar',
_(
'Variable where to store the error message (optional, if an error occurs)'
),
'',
true
)
.setHelpPath('/all-features/leaderboards')
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/sha256.js')

View File

@@ -105,6 +105,8 @@ namespace gdjs {
_loaderContainer.style.width = '100%';
_loaderContainer.style.justifyContent = 'center';
_loaderContainer.style.alignItems = 'center';
_loaderContainer.style.position = 'relative';
_loaderContainer.style.zIndex = '2';
const _loader = document.createElement('img');
_loader.setAttribute('width', '50px');
_loader.setAttribute(
@@ -157,9 +159,7 @@ namespace gdjs {
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
score: float,
playerName: string,
responseVar: gdjs.Variable,
errorVar: gdjs.Variable
playerName: string
) {
let scoreSavingState: ScoreSavingState;
if (_scoreSavingStateByLeaderboard[leaderboardId]) {
@@ -177,7 +177,6 @@ namespace gdjs {
);
const errorCode = 'SAME_AS_PREVIOUS';
scoreSavingState.setError(errorCode);
errorVar.setString(errorCode);
return;
}
@@ -187,7 +186,6 @@ namespace gdjs {
);
const errorCode = 'TOO_FAST';
scoreSavingState.setError(errorCode);
errorVar.setString(errorCode);
return;
}
} else {
@@ -195,8 +193,6 @@ namespace gdjs {
_scoreSavingStateByLeaderboard[leaderboardId] = scoreSavingState;
}
errorVar.setString('');
responseVar.setString('');
scoreSavingState.startSaving(playerName, score);
const baseUrl = 'https://api.gdevelop-app.com/play';
@@ -231,22 +227,18 @@ namespace gdjs {
response.statusText
);
scoreSavingState.setError(errorCode);
errorVar.setString(errorCode);
return;
}
scoreSavingState.closeSaving();
return response.text().then(
(text) => {
responseVar.setString(text);
},
(text) => {},
(error) => {
logger.warn(
'An error occurred when reading response but score has been saved:',
error
);
responseVar.setString('CANNOT_READ_RESPONSE');
}
);
},
@@ -254,7 +246,6 @@ namespace gdjs {
logger.error('Error while submitting a leaderboard score:', error);
const errorCode = 'REQUEST_NOT_SENT';
scoreSavingState.setError(errorCode);
errorVar.setString(errorCode);
}
);
};
@@ -335,6 +326,7 @@ namespace gdjs {
)}`;
}
return rawName
.trim()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/\s/g, '_')

View File

@@ -8,9 +8,9 @@ describe('Leaderboards', () => {
);
});
it('it returns name with underscores instead of whitespaces', () => {
it('it returns name with underscores instead of whitespaces except for leading and trailing ones that are removed', () => {
expect(
gdjs.evtTools.leaderboards.formatPlayerName('My Player Name')
gdjs.evtTools.leaderboards.formatPlayerName('\tMy Player Name ')
).to.be('My_Player_Name');
});

View File

@@ -69,4 +69,5 @@ var t=require("./bufferbuilder").BufferBuilder,e=require("./bufferbuilder").bina
},{"eventemitter3":"JJlS","./util":"BHXf","./logger":"WOs9","./socket":"wJlv","./mediaconnection":"dbHP","./dataconnection":"GBTQ","./enums":"ZRYf","./api":"in7L"}],"iTK6":[function(require,module,exports) {
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("./util"),r=require("./peer");exports.peerjs={Peer:r.Peer,util:e.util},exports.default=r.Peer,window.peerjs=exports.peerjs,window.Peer=r.Peer;
},{"./util":"BHXf","./peer":"Hxpd"}]},{},["iTK6"], null)
//# sourceMappingURL=A_peer.js.map
// Disabled to avoid warnings in Chrome (see https://github.com/4ian/GDevelop/pull/3947)
// //# sourceMappingURL=A_peer.js.map

View File

@@ -5,7 +5,6 @@ Copyright (c) 2012-2016 Victor Levasseur (victorlevasseur01@orange.fr)
This project is released under the MIT License.
*/
#include <SFML/Graphics.hpp>
#include "GDCore/Tools/Localization.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Project/InitialInstance.h"

View File

@@ -16,30 +16,30 @@ This project is released under the MIT License.
*/
void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddAction("ParticleColor1",
_("Initial color"),
_("Modify initial color of particles."),
_("Put initial color of particles of _PARAM0_ to _PARAM1_"),
_("Start color"),
_("Modify start color of particles."),
_("Change particles start color of _PARAM0_ to _PARAM1_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("color", _("Initial color"));
.AddParameter("color", _("Start color"));
obj.AddAction("ParticleColor2",
_("Final color"),
_("Modify final color of particles."),
_("Put final color of particles of _PARAM0_ to _PARAM1_"),
_("End color"),
_("Modify end color of particles."),
_("Change particles end color of _PARAM0_ to _PARAM1_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("color", _("Final color"));
.AddParameter("color", _("End color"));
obj.AddAction(
"ParticleRed1",
_("Red color, parameter 1"),
_("Modify parameter 1 of the red color."),
_("the parameter 1 of red color"),
_("Start color red component"),
_("Modify the start color red component."),
_("the start color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -48,9 +48,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleRed1",
_("Red color, parameter 1"),
_("Test parameter 1 of the red color"),
_("the parameter 1 of red color"),
_("Start color red component"),
_("Compare the start color red component."),
_("the start color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -59,9 +59,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddAction(
"ParticleRed2",
_("Red color, parameter 2"),
_("Modify parameter 2 of the red color"),
_("the parameter 2 of red color"),
_("End color red component"),
_("Modify the end color red component."),
_("the end color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -70,9 +70,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleRed2",
_("Red color, parameter 2"),
_("Test parameter 2 of the red color"),
_("the parameter 2 of red color"),
_("End color red component"),
_("Compare the end color red component."),
_("the end color red component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -81,9 +81,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddAction(
"ParticleBlue1",
_("Blue color, parameter 1"),
_("Modify parameter 1 of blue color"),
_("the parameter 1 of blue color"),
_("Start color blue component"),
_("Modify the start color blue component."),
_("the start color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -92,9 +92,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleBlue1",
_("Blue color, parameter 1"),
_("Test parameter 1 of blue color"),
_("the parameter 1 of blue color"),
_("Start color blue component"),
_("Compare the start color blue component."),
_("the start color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -103,9 +103,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddAction(
"ParticleBlue2",
_("Blue color, parameter 2"),
_("Modify parameter 2 of blue color"),
_("the parameter 2 of blue color"),
_("End color blue component"),
_("Modify the end color blue component."),
_("the end color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -114,9 +114,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleBlue2",
_("Blue color, parameter 2"),
_("Test parameter 2 of blue color"),
_("the parameter 2 of blue color"),
_("End color blue component"),
_("Compare the end color blue component."),
_("the end color blue component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -125,9 +125,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddAction(
"ParticleGreen1",
_("Green color, parameter 1"),
_("Modify parameter 1 of green color"),
_("the parameter 1 of green color"),
_("Start color green component"),
_("Modify the start color green component."),
_("the start color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -136,9 +136,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleGreen1",
_("Green color, parameter 1"),
_("Test parameter 1 of green color"),
_("the parameter 1 of green color"),
_("Start color green component"),
_("Compare the start color green component."),
_("the start color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -147,9 +147,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddAction(
"ParticleGreen2",
_("Green color, parameter 2"),
_("Modify the parameter 2 of the green color"),
_("the parameter 2 of green color"),
_("End color green component"),
_("Modify the end color green component."),
_("the end color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -158,9 +158,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleGreen2",
_("Green color, parameter 2"),
_("Test the parameter 2 of the green color"),
_("the parameter 2 of green color"),
_("End color green component"),
_("Compare the end color green component."),
_("the end color green component"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -168,9 +168,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.UseStandardRelationalOperatorParameters("number");
obj.AddAction("ParticleSize1",
_("Size, parameter 1"),
_("Modify parameter 1 of the size of particles"),
_("the parameter 1 of size"),
_("Start size"),
_("Modify the particle start size."),
_("the start size"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -178,9 +178,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.UseStandardOperatorParameters("number");
obj.AddCondition("ParticleSize1",
_("Size, parameter 1"),
_("Test parameter 1 of the size of particles"),
_("the parameter 1 of the size"),
_("Start size"),
_("Compare the particle start size."),
_("the start size"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -188,9 +188,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.UseStandardRelationalOperatorParameters("number");
obj.AddAction("ParticleSize2",
_("Size, parameter 2"),
_("Modify parameter 2 of the size of particles"),
_("the parameter 2 of size"),
_("End size"),
_("Modify the particle end size."),
_("the end size"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -198,9 +198,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.UseStandardOperatorParameters("number");
obj.AddCondition("ParticleSize2",
_("Size, parameter 2"),
_("Test parameter 2 of the size of particles"),
_("the parameter 2 of the size"),
_("End size"),
_("Compare the particle end size."),
_("the end size"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -210,7 +210,7 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddAction(
"ParticleAngle1",
_("Angle, parameter 1"),
_("Modify parameter 1 of the angle of particles"),
_("Modify parameter 1 of the angle of particles."),
_("the parameter 1 of angle"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
@@ -220,7 +220,7 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition("ParticleAngle1",
_("Angle, parameter 1"),
_("Test parameter 1 of the angle of particles"),
_("Compare parameter 1 of the angle of particles."),
_("the parameter 1 of angle"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
@@ -241,7 +241,7 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition("ParticleAngle2",
_("Angle, parameter 2"),
_("Test parameter 2 of the angle of particles"),
_("Compare parameter 2 of the angle of particles."),
_("the parameter 2 of angle"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
@@ -250,9 +250,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.UseStandardRelationalOperatorParameters("number");
obj.AddAction("ParticleAlpha1",
_("Transparency, parameter 1"),
_("Modify parameter 1 of the transparency of particles"),
_("the parameter 1 of the transparency"),
_("Start opacity"),
_("Modify the start opacity of particles."),
_("the start opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -261,9 +261,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleAlpha1",
_("Transparency, parameter 1"),
_("Test parameter 1 of the transparency of particles"),
_("the parameter 1 of the transparency"),
_("Start opacity"),
_("Compare the start opacity of particles."),
_("the start opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -271,9 +271,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
.UseStandardRelationalOperatorParameters("number");
obj.AddAction("ParticleAlpha2",
_("Transparency, parameter 2"),
_("Modify parameter 2 of the transparency of particles"),
_("the parameter 2 of the transparency"),
_("End opacity"),
_("Modify the end opacity of particles."),
_("the end opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
@@ -282,9 +282,9 @@ void ExtensionSubDeclaration2(gd::ObjectMetadata& obj) {
obj.AddCondition(
"ParticleAlpha2",
_("Transparency, parameter 2"),
_("Test parameter 2 of the transparency of particles"),
_("the parameter 2 of the transparency"),
_("Start opacity"),
_("Compare the end opacity of particles."),
_("the end opacity"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")

View File

@@ -28,7 +28,7 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
obj.AddAction(
"RendererParam1",
_("Rendering first parameter"),
_("Modify first parameter of rendering ( Size/Length ).\nParticles "
_("Modify first parameter of rendering (Size/Length).\nParticles "
"have to be recreated in order to take changes in account."),
_("the rendering 1st parameter"),
_("Setup"),
@@ -40,7 +40,7 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
obj.AddCondition(
"RendererParam1",
_("Rendering first parameter"),
_("Test the first parameter of rendering ( Size/Length )."),
_("Test the first parameter of rendering (Size/Length)."),
_("the 1st rendering parameter"),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon24.png",
@@ -51,7 +51,7 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
obj.AddAction("RendererParam2",
_("Rendering second parameter"),
_("Modify the second parameter of rendering ( Size/Length "
_("Modify the second parameter of rendering (Size/Length"
").\nParticles have to be recreated in order to take changes "
"in account."),
_("the rendering 2nd parameter"),
@@ -64,7 +64,7 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
obj.AddCondition(
"RendererParam2",
_("Rendering second parameter"),
_("Test the second parameter of rendering ( Size/Length )."),
_("Test the second parameter of rendering (Size/Length)."),
_("the 2nd rendering parameter"),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon24.png",
@@ -135,14 +135,25 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
.UseStandardRelationalOperatorParameters("number");
obj.AddAction("Texture",
_("Image"),
_("Change the image of particles ( if displayed )."),
_("Change image (using an expression)"),
_("Change the image of particles (if displayed)."),
_("Change the image of particles of _PARAM0_ to _PARAM1_"),
_("Advanced"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("string", _("Image to use"))
.SetParameterLongDescription("Indicate the name of the resource");
obj.AddAction("SetTextureFromResource",
_("Change image"),
_("Change the image of particles (if displayed)."),
_("Change the image of particles of _PARAM0_ to _PARAM1_"),
_("Common"),
"CppPlatform/Extensions/particleSystemicon24.png",
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter")
.AddParameter("string", _("New image"));
.AddParameter("imageResource", _("Image file (or image resource name)"));
obj.AddCondition(
"Texture",
@@ -157,7 +168,7 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
obj.AddStrExpression("Texture",
_("Particles image"),
_("Name of the image displayed by particles"),
_("Name of the image displayed by particles."),
_("Particles"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
@@ -172,7 +183,7 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
obj.AddExpression("CurrentParticleCount",
_("Particles count"),
_("Number of particles currently displayed"),
_("Number of particles currently displayed."),
_("Particles"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
@@ -193,35 +204,35 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
obj.AddExpression("Tank",
_("Capacity"),
_("Capacity"),
_("Capacity of the particle tank."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("Flow",
_("Flow"),
_("Flow"),
_("Flow of the particles (particles/second)."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterForceMin",
_("Emission minimal force"),
_("Emission minimal force"),
_("The minimal emission force of the particles."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterForceMax",
_("Emission maximal force"),
_("Emission maximal force"),
_("The maximal emission force of the particles."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("EmitterAngle",
_("Emission angle"),
_("Emission angle"),
_("Emission angle of the particles."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
@@ -238,104 +249,104 @@ void ExtensionSubDeclaration3(gd::ObjectMetadata& obj) {
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ZoneRadius",
_("Radius of the emission zone"),
_("Radius of the emission zone"),
_("Radius of emission zone"),
_("The radius of the emission zone."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityX",
_("X Gravity of particles"),
_("X Gravity of particles"),
_("X gravity"),
_("Gravity of particles applied on X-axis."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityY",
_("Y Gravity of particles"),
_("Y Gravity of particles"),
_("Y gravity"),
_("Gravity of particles applied on Y-axis."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityAngle",
_("Gravity angle"),
_("Gravity angle"),
_("Angle of gravity."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGravityLength",
_("Gravity"),
_("Gravity value"),
_("Value of gravity."),
_("Common"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleLifeTimeMin",
_("Minimum lifetime of particles"),
_("Minimum lifetime of particles"),
_("Minimum lifetime of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleLifeTimeMax",
_("Maximum lifetime of particles"),
_("Maximum lifetime of particles"),
_("Maximum lifetime of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleRed1",
_("Parameter 1 of red color"),
_("Parameter 1 of red color"),
_("Start color red component"),
_("The start color red component of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleRed2",
_("Parameter 2 of red color"),
_("Parameter 2 of red color"),
_("End color red component"),
_("The end color red component of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleBlue1",
_("Parameter 1 of blue color"),
_("Parameter 1 of blue color"),
_("Start color blue component"),
_("The start color blue component of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleBlue2",
_("Parameter 2 of blue color"),
_("Parameter 2 of blue color"),
_("End color blue component"),
_("The end color blue component of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGreen1",
_("Parameter 1 of green color"),
_("Parameter 1 of green color"),
_("Start color green component"),
_("The start color green component of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleGreen2",
_("Parameter 2 of green color"),
_("Parameter 2 of green color"),
_("End color green component"),
_("The end color green component of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleAlpha1",
_("Parameter 1 of transparency"),
_("Parameter 1 of transparency"),
_("Start opacity"),
_("Start opacity of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleAlpha2",
_("Parameter 2 of transparency"),
_("Parameter 2 of transparency"),
_("End opacity"),
_("End opacity of the particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleSize1",
_("Parameter 1 of size"),
_("Parameter 1 of size"),
_("Start size"),
_("Start size of particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);
obj.AddExpression("ParticleSize2",
_("Parameter 2 of size"),
_("Parameter 2 of size"),
_("End size"),
_("End size of particles."),
_("Setup"),
"CppPlatform/Extensions/particleSystemicon16.png")
.AddParameter("object", _("Object"), "ParticleEmitter", false);

View File

@@ -169,6 +169,10 @@ class ParticleSystemJsExtension : public gd::PlatformExtension {
actions["ParticleSystem::Flow"].SetFunctionName("setFlow").SetGetter(
"getFlow");
conditions["ParticleSystem::Flow"].SetFunctionName("getFlow");
actions["ParticleSystem::SetTextureFromResource"]
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("setTexture")
.SetGetter("getTexture");
actions["ParticleSystem::Texture"]
.AddCodeOnlyParameter("currentScene", "")
.SetFunctionName("setTexture")

File diff suppressed because one or more lines are too long

View File

@@ -7,7 +7,7 @@ This project is released under the MIT License.
#ifndef PATHFINDINGBEHAVIOR_H
#define PATHFINDINGBEHAVIOR_H
#include <SFML/System/Vector2.hpp>
#include "GDCore/Vector2.h"
#include <vector>
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Object.h"

View File

@@ -33,7 +33,7 @@ void PhysicsBehavior::InitializeContent(
behaviorContent.SetAttribute("polygonWidth", 200);
behaviorContent.SetAttribute("polygonHeight", 200);
std::vector<sf::Vector2f> polygonCoords;
std::vector<gd::Vector2f> polygonCoords;
behaviorContent.SetAttribute(
"coordsList",
PhysicsBehavior::GetStringFromCoordsVector(polygonCoords, '/', ';'));
@@ -128,7 +128,7 @@ bool PhysicsBehavior::UpdateProperty(gd::SerializerElement &behaviorContent,
#endif
gd::String PhysicsBehavior::GetStringFromCoordsVector(
const std::vector<sf::Vector2f> &vec,
const std::vector<gd::Vector2f> &vec,
char32_t coordsSep,
char32_t composantSep) {
gd::String coordsStr;

View File

@@ -13,7 +13,7 @@ This project is released under the MIT License.
#include <vector>
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/Object.h"
#include "SFML/System/Vector2.hpp"
#include "GDCore/Vector2.h"
namespace gd {
class Project;
class SerializerElement;
@@ -43,7 +43,7 @@ class GD_EXTENSION_API PhysicsBehavior : public gd::Behavior {
gd::SerializerElement &behaviorContent) override;
private:
gd::String GetStringFromCoordsVector(const std::vector<sf::Vector2f> &vec,
gd::String GetStringFromCoordsVector(const std::vector<gd::Vector2f> &vec,
char32_t coordsSep,
char32_t composantSep);
enum ShapeType {

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