mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Compare commits
173 Commits
v5.0.0-bet
...
v5.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
![]() |
25acb603b4 | ||
![]() |
27d4ead51e | ||
![]() |
1704d196f9 | ||
![]() |
d40e360b8a | ||
![]() |
183a0bd08e | ||
![]() |
8780f2f415 | ||
![]() |
5adb3c92ee | ||
![]() |
a54ee812bd | ||
![]() |
f8db01706d | ||
![]() |
d9368921af | ||
![]() |
12743f6f7e | ||
![]() |
3d3048906e | ||
![]() |
413fbc529e | ||
![]() |
287ebd4244 | ||
![]() |
f2199c8ab4 | ||
![]() |
64b63d4efa | ||
![]() |
3820c2613a | ||
![]() |
c42603bb29 | ||
![]() |
b879d3043f | ||
![]() |
8be448fd0e | ||
![]() |
9535fbca0f | ||
![]() |
6667a0005c | ||
![]() |
860faae853 | ||
![]() |
dd47c7f6c4 | ||
![]() |
c4f76efbcd | ||
![]() |
56d9dc05f1 | ||
![]() |
599ccb677f | ||
![]() |
b97f716c09 | ||
![]() |
58917aec02 | ||
![]() |
fdaba4a6d5 | ||
![]() |
d1f49cd1f7 | ||
![]() |
71a9a3f1d0 | ||
![]() |
9173e704be | ||
![]() |
1a27f689e0 | ||
![]() |
ef198b2c64 | ||
![]() |
d5039b5b51 | ||
![]() |
4b19696523 | ||
![]() |
32978c22e8 | ||
![]() |
1f6f2701ff | ||
![]() |
fbf2340f00 | ||
![]() |
4ff208b39f | ||
![]() |
3d0a893c1c | ||
![]() |
2581021a57 | ||
![]() |
e4fc065dc1 | ||
![]() |
d1f4d26e49 | ||
![]() |
a1b840a4fa | ||
![]() |
465629b688 | ||
![]() |
38758c62c6 | ||
![]() |
26f6e95e46 | ||
![]() |
34abf8290e | ||
![]() |
52677f5512 | ||
![]() |
df2b51bb1b | ||
![]() |
6b0ff984f2 | ||
![]() |
f4512242e4 | ||
![]() |
8beabbadef | ||
![]() |
9491a8ed45 | ||
![]() |
f945dfd987 | ||
![]() |
ff42591354 | ||
![]() |
21fb93c66a | ||
![]() |
068fbe653a | ||
![]() |
80891dcc59 | ||
![]() |
34155d65f1 | ||
![]() |
18f22470ca | ||
![]() |
92a8ebc58b | ||
![]() |
565384e270 | ||
![]() |
8335b2edf9 | ||
![]() |
12c77d0455 | ||
![]() |
13b62a06eb | ||
![]() |
d27119d8ea | ||
![]() |
dd3ff554d5 | ||
![]() |
287a17b634 | ||
![]() |
7dc477e29e | ||
![]() |
8174bca3b1 | ||
![]() |
7f6388c6f5 | ||
![]() |
da3a099ff2 | ||
![]() |
7b2c7b4a00 | ||
![]() |
f750a356c3 | ||
![]() |
611a72aee1 | ||
![]() |
1b965b65a4 | ||
![]() |
c077628eb4 | ||
![]() |
f1a6da0cb2 | ||
![]() |
df4a780311 | ||
![]() |
8c955cf77a | ||
![]() |
17efae037c | ||
![]() |
f1120238ec | ||
![]() |
5d6a2bb3a0 | ||
![]() |
f3a49ad2cf | ||
![]() |
aac3379f59 | ||
![]() |
49949189cf | ||
![]() |
977daa50fa | ||
![]() |
fd8a7df868 | ||
![]() |
303110ade5 | ||
![]() |
cb15111d03 | ||
![]() |
9db4d603a0 | ||
![]() |
6c7db9a948 | ||
![]() |
6b9a8f14e3 | ||
![]() |
2f3a18046a | ||
![]() |
812ff43905 | ||
![]() |
1a113004be | ||
![]() |
0dd10a7955 | ||
![]() |
00b25461ed | ||
![]() |
9e28068e4f | ||
![]() |
6b231f3eb6 | ||
![]() |
2dd2c85f12 | ||
![]() |
c61faa7e05 | ||
![]() |
1840f6f45a | ||
![]() |
b11eccfa22 | ||
![]() |
9236608502 | ||
![]() |
12a6bc23c3 | ||
![]() |
23c2b84707 | ||
![]() |
adb4f2a6cf | ||
![]() |
aa3ed78eda | ||
![]() |
efb8668077 | ||
![]() |
8d763d4600 | ||
![]() |
0cc1e57450 | ||
![]() |
24c13e1022 | ||
![]() |
965f7aab32 | ||
![]() |
23c1f2423d | ||
![]() |
1d5eb8e529 | ||
![]() |
8968ef34e2 | ||
![]() |
736ba023ff | ||
![]() |
ade075f076 | ||
![]() |
049c36b081 | ||
![]() |
3977e2b6f2 | ||
![]() |
f08f38bc3b | ||
![]() |
127a881416 | ||
![]() |
606143ff36 | ||
![]() |
05a68cb17f | ||
![]() |
280377cc98 | ||
![]() |
3c88c150d5 | ||
![]() |
13471ad40a | ||
![]() |
0d7d574f1b | ||
![]() |
19a10d7dab | ||
![]() |
84e096f85d | ||
![]() |
40f5eb3e23 | ||
![]() |
4948e16dd5 | ||
![]() |
2b38325d96 | ||
![]() |
9a10caeeac | ||
![]() |
a4be56a24b | ||
![]() |
fc8b724e3c | ||
![]() |
7e61419a36 | ||
![]() |
473661b8a2 | ||
![]() |
350fea08bf | ||
![]() |
4f9154549b | ||
![]() |
d9172ded36 | ||
![]() |
aef8271a4e | ||
![]() |
83db8ce272 | ||
![]() |
e26c1470c1 | ||
![]() |
4b382cb191 | ||
![]() |
6c631410f2 | ||
![]() |
516b1d978c | ||
![]() |
822146e5f1 | ||
![]() |
7b3987bae4 | ||
![]() |
506c029690 | ||
![]() |
b28e4e1230 | ||
![]() |
c1edcbfa19 | ||
![]() |
3125956dfc | ||
![]() |
633c7bbd9d | ||
![]() |
df92ea1ac9 | ||
![]() |
3eb571a03a | ||
![]() |
98303f7f50 | ||
![]() |
34dfbbc294 | ||
![]() |
afbb316bd2 | ||
![]() |
b75945869c | ||
![]() |
efb3f55885 | ||
![]() |
82d2a4b5e4 | ||
![]() |
7748f3c48e | ||
![]() |
80ddc9c1b7 | ||
![]() |
5d50c31e55 | ||
![]() |
61a969fdb1 | ||
![]() |
a14b8e8bcd | ||
![]() |
faa37a4fd2 | ||
![]() |
176efafe43 |
@@ -1,9 +1,79 @@
|
||||
# CircleCI 2.0 configuration file to build GDevelop app running
|
||||
# on the Electron runtime (newIDE/electron-app).
|
||||
# CircleCI configuration to build GDevelop app running
|
||||
# on the Electron runtime (newIDE/electron-app) for macOS and Linux.
|
||||
# For Windows, see the appveyor.yml file.
|
||||
|
||||
version: 2
|
||||
version: 2.1
|
||||
jobs:
|
||||
build:
|
||||
build-macos:
|
||||
macos:
|
||||
xcode: 12.5.1
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
# System dependencies (for Emscripten and upload)
|
||||
- run:
|
||||
name: Install dependencies for Emscripten
|
||||
command: brew install cmake
|
||||
|
||||
- run:
|
||||
name: Install dependencies for AWS S3 upload
|
||||
command: curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg" && sudo installer -pkg AWSCLIV2.pkg -target /
|
||||
|
||||
- run:
|
||||
name: Install Emscripten (for GDevelop.js)
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
|
||||
|
||||
# GDevelop.js dependencies
|
||||
- restore_cache:
|
||||
keys:
|
||||
- gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
||||
# fallback to using the latest cache if no exact match is found
|
||||
- gd-macos-nodejs-dependencies---
|
||||
|
||||
- run:
|
||||
name: Install GDevelop.js dependencies and build it
|
||||
command: cd GDevelop.js && npm install && cd ..
|
||||
|
||||
# Build GDevelop.js (and run tests to ensure it works)
|
||||
- run:
|
||||
name: Build GDevelop.js
|
||||
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
|
||||
|
||||
# GDevelop IDE dependencies (after building GDevelop.js to avoid downloading a pre-built version)
|
||||
- run:
|
||||
name: Install GDevelop IDE dependencies
|
||||
command: cd newIDE/app && npm install && cd ../electron-app && npm install
|
||||
|
||||
- save_cache:
|
||||
paths:
|
||||
- newIDE/electron-app/node_modules
|
||||
- newIDE/app/node_modules
|
||||
- GDevelop.js/node_modules
|
||||
key: gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
||||
|
||||
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
|
||||
# Note: Code signing is done using CSC_LINK (see https://www.electron.build/code-signing).
|
||||
- run:
|
||||
name: Build GDevelop IDE
|
||||
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --mac --publish=never
|
||||
|
||||
- run:
|
||||
name: Clean dist folder to keep only installers/binaries.
|
||||
command: rm -rf "newIDE/electron-app/dist/mac/GDevelop 5.app"
|
||||
|
||||
# Upload artifacts (CircleCI)
|
||||
- store_artifacts:
|
||||
path: newIDE/electron-app/dist
|
||||
|
||||
# Upload artifacts (AWS)
|
||||
- run:
|
||||
name: Deploy to S3 (specific commit)
|
||||
command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
|
||||
- run:
|
||||
name: Deploy to S3 (latest)
|
||||
command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
|
||||
|
||||
build-linux:
|
||||
# CircleCI docker workers are failing if they don't have enough memory (no swap)
|
||||
resource_class: xlarge
|
||||
docker:
|
||||
@@ -23,10 +93,6 @@ jobs:
|
||||
name: Install Emscripten (for GDevelop.js)
|
||||
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
|
||||
|
||||
- run:
|
||||
name: Install Wine for Electron builder
|
||||
command: sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt install wine32
|
||||
|
||||
- run:
|
||||
name: Install system dependencies for Electron builder
|
||||
command: sudo apt install icnsutils && sudo apt install graphicsmagick && sudo apt install rsync
|
||||
@@ -34,15 +100,15 @@ jobs:
|
||||
# GDevelop.js dependencies
|
||||
- restore_cache:
|
||||
keys:
|
||||
- gd-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
||||
- gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
||||
# fallback to using the latest cache if no exact match is found
|
||||
- gd-nodejs-dependencies---
|
||||
- gd-linux-nodejs-dependencies---
|
||||
|
||||
- run:
|
||||
name: Install GDevelop.js dependencies and build it
|
||||
command: cd GDevelop.js && sudo npm install -g grunt-cli && npm install && cd ..
|
||||
command: cd GDevelop.js && npm install && cd ..
|
||||
|
||||
# Build GDevelop.js
|
||||
# Build GDevelop.js (and run tests to ensure it works)
|
||||
- run:
|
||||
name: Build GDevelop.js
|
||||
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
|
||||
@@ -57,16 +123,16 @@ jobs:
|
||||
- newIDE/electron-app/node_modules
|
||||
- newIDE/app/node_modules
|
||||
- GDevelop.js/node_modules
|
||||
key: gd-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}
|
||||
key: gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
|
||||
|
||||
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
|
||||
- run:
|
||||
name: Build GDevelop IDE
|
||||
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --mac zip --win --linux tar.gz --publish=never
|
||||
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --linux AppImage --publish=never
|
||||
|
||||
- run:
|
||||
name: Clean dist folder to keep only installers/binaries.
|
||||
command: rm -rf newIDE/electron-app/dist/linux-unpacked && rm -rf newIDE/electron-app/dist/win-unpacked && rm -rf newIDE/electron-app/dist/mac
|
||||
command: rm -rf newIDE/electron-app/dist/linux-unpacked
|
||||
|
||||
# Upload artifacts (CircleCI)
|
||||
- store_artifacts:
|
||||
@@ -79,3 +145,20 @@ jobs:
|
||||
- run:
|
||||
name: Deploy to S3 (latest)
|
||||
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
|
||||
|
||||
|
||||
workflows:
|
||||
builds:
|
||||
jobs:
|
||||
- build-macos:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /experimental-build.*/
|
||||
- build-linux:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /experimental-build.*/
|
||||
|
@@ -13,6 +13,5 @@
|
||||
-fPIC
|
||||
-I./ExtLibs/SFML/include
|
||||
-I./Core
|
||||
-I./GDCpp/.
|
||||
-I./GDJS/.
|
||||
-F./ExtLibs/SFML/extlibs/libs-osx/Frameworks
|
||||
|
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1,6 +1,5 @@
|
||||
Core/GDCore/Serialization/rapidjson/rapidjson.h/* linguist-vendored
|
||||
Core/GDCore/TinyXml/* linguist-vendored
|
||||
GDCpp/GDCpp/Runtime/TinyXml/* linguist-vendored
|
||||
Extensions/ParticleSystem/SPARK/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/Box2D/* linguist-vendored
|
||||
Extensions/PhysicsBehavior/box2djs/* linguist-vendored
|
||||
|
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: GDevelop Discord
|
||||
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
|
||||
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
|
||||
- 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
|
15
.github/workflows/issues.yml
vendored
15
.github/workflows/issues.yml
vendored
@@ -4,13 +4,6 @@ jobs:
|
||||
autoclose:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Autoclose issues about adding a new example without providing anything
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
type: "body"
|
||||
regex: ".*INSERT the link to your game here, or add it as an attachment.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed because it seems that you have not included any example.\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!"
|
||||
- name: Autoclose issues about adding a bug without changing the bug report template
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
@@ -25,3 +18,11 @@ jobs:
|
||||
type: "body"
|
||||
regex: ".*_instance.getRawFloatProperty is not a function.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed as this seems to be a known bug. It can be solved by **closing entirely the web-app and opening it again**. This will allow the web-app to auto-update and the problem should be gone."
|
||||
- name: Autoclose known beta 114 web-app update bug
|
||||
uses: arkon/issue-closer-action@v1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
type: "body"
|
||||
regex: ".*getAssociatedSettings is not a function.*"
|
||||
message: "Hi @${issue.user.login}! 👋 This issue was automatically closed as this seems to be a known bug. It can be solved by **closing entirely the web-app and opening it again**. This will allow the web-app to auto-update and the problem should be gone."
|
||||
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
/Core/GDCore/Tools/VersionPriv.h
|
||||
/docs
|
||||
/docs-wiki
|
||||
/ExtLibs/SFML
|
||||
@@ -16,7 +15,6 @@
|
||||
*.bc
|
||||
/Binaries/Output
|
||||
*.autosave
|
||||
!/GDCpp/scripts/bcp.exe
|
||||
!/scripts/libgettextlib-0-17.dll
|
||||
!/scripts/libgettextsrc-0-17.dll
|
||||
!/xgettext.exe
|
||||
|
105
.semaphore/semaphore.yml
Normal file
105
.semaphore/semaphore.yml
Normal file
@@ -0,0 +1,105 @@
|
||||
version: v1.0
|
||||
name: Fast tests (not building GDevelop.js - can have false negatives)
|
||||
agent:
|
||||
machine:
|
||||
type: e1-standard-2
|
||||
os_image: ubuntu2004
|
||||
auto_cancel:
|
||||
running:
|
||||
when: "true"
|
||||
blocks:
|
||||
- name: Install
|
||||
task:
|
||||
jobs:
|
||||
- name: Install node_modules and cache them
|
||||
commands:
|
||||
- checkout
|
||||
- node -v
|
||||
- |-
|
||||
if ! cache has_key newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json); then
|
||||
cd newIDE/app
|
||||
npm i
|
||||
cd ../..
|
||||
cache store newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json) newIDE/app/node_modules
|
||||
fi
|
||||
- |-
|
||||
if ! cache has_key GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json); then
|
||||
cd GDJS
|
||||
npm i
|
||||
cd ..
|
||||
cache store GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json) GDJS/node_modules
|
||||
fi
|
||||
- |-
|
||||
if ! cache has_key GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json); then
|
||||
cd GDJS/tests
|
||||
npm i
|
||||
cd ../..
|
||||
cache store GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json) GDJS/tests/node_modules
|
||||
fi
|
||||
dependencies: []
|
||||
- name: Type checks
|
||||
dependencies:
|
||||
- Install
|
||||
task:
|
||||
jobs:
|
||||
- name: newIDE typing
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cd newIDE/app
|
||||
- npm run postinstall
|
||||
- npm run flow
|
||||
- cd ../..
|
||||
- name: GDJS typing and documentation generation
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
|
||||
- cd GDJS
|
||||
- npm run check-types
|
||||
- npm run generate-doc
|
||||
- name: Auto formatting
|
||||
dependencies:
|
||||
- Install
|
||||
task:
|
||||
jobs:
|
||||
- name: newIDE auto-formatting
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cd newIDE/app
|
||||
- npm run postinstall
|
||||
- npm run check-format
|
||||
- cd ../..
|
||||
- name: GDJS auto-formatting
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cd GDJS
|
||||
- npm run check-format
|
||||
- cd ..
|
||||
- name: Tests
|
||||
dependencies:
|
||||
- Install
|
||||
task:
|
||||
jobs:
|
||||
- name: newIDE tests
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cd newIDE/app
|
||||
- npm run postinstall
|
||||
- npm run analyze-test-coverage
|
||||
- cd ../..
|
||||
- name: GDJS tests
|
||||
commands:
|
||||
- checkout
|
||||
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
|
||||
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
|
||||
- cd GDJS
|
||||
- npm run build
|
||||
- npm run test
|
||||
- cd ../..
|
19
.travis.yml
19
.travis.yml
@@ -1,7 +1,15 @@
|
||||
# Travis CI configuration to build and run all tests
|
||||
# (and typing/formatting) for the Core, newIDE, GDJS.
|
||||
#
|
||||
# This builds GDevelop.js and store it on a S3 so it can be used to run
|
||||
# GDevelop without building it.
|
||||
#
|
||||
# See also Semaphore CI for quick tests (not building GDevelop.js, so
|
||||
# faster but not always reliable).
|
||||
|
||||
language: cpp
|
||||
sudo: false
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
# Cache .npm folder for faster npm install
|
||||
@@ -54,7 +62,7 @@ before_install:
|
||||
install:
|
||||
#Get the correct version of gcc/g++
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
|
||||
#Compile the tests only for GDCore and GDCpp
|
||||
#Compile the tests only for GDCore
|
||||
- mkdir .build-tests
|
||||
- cd .build-tests
|
||||
- cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) ..
|
||||
@@ -81,12 +89,9 @@ install:
|
||||
- cd ../..
|
||||
|
||||
script:
|
||||
# GDCore and GDCpp game engine tests:
|
||||
# GDCore tests:
|
||||
- cd .build-tests
|
||||
- Core/GDCore_tests
|
||||
- GDCpp/GDCpp_tests
|
||||
- Extensions/PathfindingBehavior/PathfindingBehavior_Runtime_tests
|
||||
- Extensions/LinkedObjects/LinkedObjects_Runtime_tests
|
||||
- cd ..
|
||||
# GDevelop.js tests
|
||||
- cd GDevelop.js
|
||||
@@ -103,6 +108,6 @@ script:
|
||||
- npm run check-format
|
||||
- cd ..
|
||||
# GDJS game engine tests, disabled on Travis CI because ChromeHeadless can't be started.
|
||||
# See them running on Semaphore-CI instead: https://semaphoreci.com/4ian/gd
|
||||
# See them running on Semaphore-CI instead: https://gdevelop.semaphoreci.com/projects/GDevelop
|
||||
# - cd GDJS/tests && npm test
|
||||
# - cd ../..
|
||||
|
129
.vscode/GDevelopExtensions.code-snippets
vendored
Normal file
129
.vscode/GDevelopExtensions.code-snippets
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"Define extension": {
|
||||
"scope": "javascript",
|
||||
"description": "Adds the boilerplate code of a GDevelop extension definition.",
|
||||
"prefix": "gdext",
|
||||
"body": [
|
||||
"// @flow",
|
||||
"/**",
|
||||
" * This is a declaration of an extension for GDevelop 5.",
|
||||
" *",
|
||||
" * ℹ️ Changes in this file are watched and automatically imported if the editor",
|
||||
" * is running. You can also manually run `node import-GDJS-Runtime.js` (in newIDE/app/scripts).",
|
||||
" *",
|
||||
" * The file must be named \"JsExtension.js\", otherwise GDevelop won't load it.",
|
||||
" * ⚠️ If you make a change and the extension is not loaded, open the developer console",
|
||||
" * and search for any errors.",
|
||||
" *",
|
||||
" * More information on https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md",
|
||||
" */",
|
||||
"",
|
||||
"/*::",
|
||||
"// Import types to allow Flow to do static type checking on this file.",
|
||||
"// Extensions declaration are typed using Flow (like the editor), but the files",
|
||||
"// for the game engine are checked with TypeScript annotations.",
|
||||
"import { type ObjectsRenderingService, type ObjectsEditorService } from '../JsExtensionTypes.flow.js'",
|
||||
"*/",
|
||||
"",
|
||||
"module.exports = {",
|
||||
"\tcreateExtension: function (",
|
||||
"\t\t/*: (string) => string */,",
|
||||
"\t\tgd /*: libGDevelop */",
|
||||
"\t) {",
|
||||
"\t\tconst extension = new gd.PlatformExtension();",
|
||||
"\t\textension",
|
||||
"\t\t\t.setExtensionInformation(",
|
||||
"\t\t\t\t'${1:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}}',",
|
||||
"\t\t\t\t_('${2:Extension Name}'),",
|
||||
"\t\t\t\t_(",
|
||||
"\t\t\t\t\t'${3:Extension description}'",
|
||||
"\t\t\t\t),",
|
||||
"\t\t\t\t'${4:Extension author}',",
|
||||
"\t\t\t\t'MIT'",
|
||||
"\t\t\t);",
|
||||
"",
|
||||
"\t\t$0",
|
||||
"",
|
||||
"\t\treturn extension;",
|
||||
"\t},",
|
||||
"\trunExtensionSanityTests: function (",
|
||||
"\t\tgd /*: libGDevelop */,",
|
||||
"\t\textension /*: gdPlatformExtension*/",
|
||||
"\t) {",
|
||||
"\t\treturn [];",
|
||||
"\t},",
|
||||
"};",
|
||||
""
|
||||
]
|
||||
},
|
||||
"Define instruction": {
|
||||
"scope": "javascript",
|
||||
"description": "Define an instruction in a GDevelop extension definition.",
|
||||
"prefix": "gdinstr",
|
||||
"body": [
|
||||
"extension",
|
||||
"\t.add${1|Condition,Action|}(",
|
||||
"\t\t'${2:InstructionInternalName}',",
|
||||
"\t\t_('${3:Instruction full name}'),",
|
||||
"\t\t_(",
|
||||
"\t\t\t'${4:Instruction description}'",
|
||||
"\t\t),",
|
||||
"\t\t_('${5:Event sheet sentence}'),",
|
||||
"\t\t_('${6:Events group}'),",
|
||||
"\t\t'JsPlatform/Extensions/${8:icon}.png',",
|
||||
"\t\t'JsPlatform/Extensions/${8:icon}.png'",
|
||||
"\t)",
|
||||
"\t.getCodeExtraInformation()",
|
||||
"\t.setIncludeFile('Extensions/${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}/${9:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}tools}.js')",
|
||||
"\t.setFunctionName('gdjs.evtTools.${7:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}.}');",
|
||||
"",
|
||||
"$0"
|
||||
]
|
||||
},
|
||||
"Define expression": {
|
||||
"scope": "javascript",
|
||||
"description": "Define an expression in a GDevelop extension definition.",
|
||||
"prefix": "gdexp",
|
||||
"body": [
|
||||
"extension",
|
||||
"\t.add${1|Expression,StrExpression|}(",
|
||||
"\t\t'${2:ExpressionsInternalName}',",
|
||||
"\t\t_('${3:Expression full name}'),",
|
||||
"\t\t_(",
|
||||
"\t\t\t'${4:Expression description}'",
|
||||
"\t\t),",
|
||||
"\t\t_('${5:Events group}'),",
|
||||
"\t\t'JsPlatform/Extensions/${7:icon}.png'",
|
||||
"\t)",
|
||||
"\t.getCodeExtraInformation()",
|
||||
"\t.setIncludeFile('Extensions/${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}/${8:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}tools}.js')",
|
||||
"\t.setFunctionName('gdjs.evtTools.${6:${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/${2:/downcase}/}.}');",
|
||||
"",
|
||||
"$0"
|
||||
]
|
||||
},
|
||||
"Add parameter": {
|
||||
"scope": "javascript",
|
||||
"description": "Define a parameter in a GDevelop extension definition.",
|
||||
"prefix": "gdparam",
|
||||
"body": [
|
||||
".addParameter('${1|string,expression,object,behavior,yesorno,stringWithSelector,scenevar,globalvar,objectvar,objectList,objectListWithoutPicking,color,key,sceneName,file,layer,relationalOperator,operator,trueorfalse,musicfile,soundfile,police,mouse,passwordjoyaxis,camera,objectPtr,forceMultiplier|}', '${2:Parameter description}', '${3:Optional parameter data}', /*parameterIsOptional=*/${4|false,true|})"
|
||||
]
|
||||
},
|
||||
"Add code only parameter": {
|
||||
"scope": "javascript",
|
||||
"description": "Define a parameter in a GDevelop extension definition.",
|
||||
"prefix": "gdcoparam",
|
||||
"body": [
|
||||
".addCodeOnlyParameter('${1|inlineCode,currentScene,objectsContext,eventsFunctionContext,conditionInverted|}', '${2:Inline code (for inlineCode parameter)}')"
|
||||
]
|
||||
},
|
||||
"Add include": {
|
||||
"scope": "javascript",
|
||||
"description": "Define an include file in a GDevelop extension definition.",
|
||||
"prefix": "gdincl",
|
||||
"body": [
|
||||
".addIncludeFile('Extensions/${TM_DIRECTORY/(.*)[\\\\\\/](.*)[\\\\\\/]?$/$2/}/${1:include}.js')"
|
||||
]
|
||||
}
|
||||
}
|
11
.vscode/c_cpp_properties.json
vendored
11
.vscode/c_cpp_properties.json
vendored
@@ -4,7 +4,6 @@
|
||||
"name": "Mac",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
@@ -16,6 +15,7 @@
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"EMSCRIPTEN",
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
@@ -45,7 +45,6 @@
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
@@ -55,6 +54,7 @@
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"EMSCRIPTEN",
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
@@ -75,18 +75,16 @@
|
||||
"name": "Win32",
|
||||
"includePath": [
|
||||
"${workspaceRoot}",
|
||||
"${workspaceRoot}/IDE",
|
||||
"${workspaceRoot}/GDCpp",
|
||||
"${workspaceRoot}/GDJS",
|
||||
"${workspaceRoot}/Extensions",
|
||||
"${workspaceRoot}/Core",
|
||||
"${workspaceRoot}/ExtLibs/SFML/include",
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"defines": [
|
||||
"_DEBUG",
|
||||
"UNICODE",
|
||||
"EMSCRIPTEN",
|
||||
"GD_IDE_ONLY",
|
||||
"GD_CORE_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
"GD_API=/* Macro used to export classes on Windows, please ignore */",
|
||||
@@ -95,7 +93,6 @@
|
||||
"intelliSenseMode": "msvc-x64",
|
||||
"browse": {
|
||||
"path": [
|
||||
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
|
||||
"${workspaceRoot}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true,
|
||||
@@ -104,4 +101,4 @@
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
}
|
14
.vscode/extensions.json
vendored
14
.vscode/extensions.json
vendored
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"xaver.clang-format",
|
||||
"ms-vscode.cpptools",
|
||||
"flowtype.flow-for-vscode"
|
||||
]
|
||||
}
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"xaver.clang-format",
|
||||
"ms-vscode.cpptools",
|
||||
"flowtype.flow-for-vscode"
|
||||
]
|
||||
}
|
||||
|
29
.vscode/launch.json
vendored
29
.vscode/launch.json
vendored
@@ -1,15 +1,16 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"preLaunchTask": "Start development server"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -106,12 +106,16 @@
|
||||
"xstring": "cpp",
|
||||
"xtr1common": "cpp",
|
||||
"xtree": "cpp",
|
||||
"xutility": "cpp"
|
||||
"xutility": "cpp",
|
||||
"xlocbuf": "cpp",
|
||||
"xlocmes": "cpp",
|
||||
"xmemory0": "cpp"
|
||||
},
|
||||
"files.exclude": {
|
||||
"Binaries/*build*": true,
|
||||
"Binaries/Output": true,
|
||||
"ExtLibs/SFML": true,
|
||||
"GDJS/Runtime-dist": true,
|
||||
"docs": true,
|
||||
"newIDE/electron-app/dist": true,
|
||||
"newIDE/app/build": true,
|
||||
|
158
.vscode/tasks.json
vendored
158
.vscode/tasks.json
vendored
@@ -1,66 +1,100 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"path": "newIDE/app/",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"label": "Start development server",
|
||||
"detail": "Starts the GDevelop development server."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"path": "GDevelop.js/",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"label": "Build GDevelop.js",
|
||||
"detail": "Builds GDCore for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "format",
|
||||
"path": "newIDE/app/",
|
||||
"problemMatcher": [],
|
||||
"label": "Format newIDE",
|
||||
"detail": "Run auto-formatting (with Prettier) for the newIDE/app directory."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "newIDE/app/",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"label": "Run newIDE tests",
|
||||
"detail": "Run tests for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "typescript",
|
||||
"tsconfig": "GDJS/tsconfig.json",
|
||||
"option": "watch",
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
],
|
||||
"group": "test",
|
||||
"label": "GDJS TS Check",
|
||||
"detail": "Runs a types check on the GDJS Runtime."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "GDJS/",
|
||||
"group": "test",
|
||||
"problemMatcher": [],
|
||||
"label": "Run GDJS tests",
|
||||
"detail": "Run tests for GDJS."
|
||||
}
|
||||
]
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"path": "newIDE/app/",
|
||||
"group": "build",
|
||||
"label": "Start development server",
|
||||
"detail": "Starts the GDevelop development server.",
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "cra",
|
||||
"fileLocation": ["relative", "${workspaceFolder}/newIDE/app"],
|
||||
"source": "create-react-app",
|
||||
"applyTo": "allDocuments",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^([^\\s].*?)$",
|
||||
"file": 1
|
||||
},
|
||||
{
|
||||
"regexp": "^ Line\\s+(\\d+):\\s+(.*)\\s\\s+(.*)$",
|
||||
"line": 1,
|
||||
"message": 2,
|
||||
"code": 3,
|
||||
"loop": true
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "^(?:Compiled with warnings\\.|Compiled successfully!)$",
|
||||
"endsPattern": "^(?:Search for the keywords to learn more about each warning\\.|Note that the development build is not optimized\\.)$"
|
||||
}
|
||||
}
|
||||
],
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"isBackground": true,
|
||||
"runOptions": { "instanceLimit": 1, "runOn": "folderOpen" }
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"path": "newIDE/electron-app/",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"label": "Start electron app",
|
||||
"detail": "Starts the development local version of GDevelop."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "build",
|
||||
"path": "GDevelop.js/",
|
||||
"group": "build",
|
||||
"problemMatcher": [],
|
||||
"label": "Build GDevelop.js",
|
||||
"detail": "Builds GDCore for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "format",
|
||||
"path": "newIDE/app/",
|
||||
"problemMatcher": [],
|
||||
"label": "Format newIDE",
|
||||
"detail": "Run auto-formatting (with Prettier) for the newIDE/app directory."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "newIDE/app/",
|
||||
"group": {
|
||||
"kind": "test",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"label": "Run newIDE tests",
|
||||
"detail": "Run tests for newIDE."
|
||||
},
|
||||
{
|
||||
"type": "typescript",
|
||||
"tsconfig": "GDJS/tsconfig.json",
|
||||
"option": "watch",
|
||||
"problemMatcher": ["$tsc-watch"],
|
||||
"group": "test",
|
||||
"label": "GDJS TS Check",
|
||||
"detail": "Runs a types check on the GDJS Runtime."
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "test",
|
||||
"path": "GDJS/",
|
||||
"group": "test",
|
||||
"problemMatcher": [],
|
||||
"label": "Run GDJS tests",
|
||||
"detail": "Run tests for GDJS."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -1,3 +1,3 @@
|
||||
This is the directory where native or WebAssembly binaries of the C++ code of GDCore, GDCpp and GDJS are produced.
|
||||
This is the directory where native or WebAssembly binaries of the C++ code of GDCore and GDJS are produced.
|
||||
|
||||
See GDevelop.js README for the instructions to compile after a change in the C++ source code.
|
@@ -14,12 +14,10 @@ macro(gd_set_option var default type docstring)
|
||||
endif()
|
||||
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
|
||||
endmacro()
|
||||
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library, FALSE to use the already compiled binaries")
|
||||
gd_set_option(BUILD_GDCPP TRUE BOOL "TRUE to build GDevelop C++ Platform")
|
||||
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library")
|
||||
gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform")
|
||||
gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions")
|
||||
gd_set_option(BUILD_TESTS FALSE BOOL "TRUE to build the tests")
|
||||
gd_set_option(FULL_VERSION_NUMBER TRUE BOOL "TRUE to build GDevelop with its full version number (lastest tag + commit hash), FALSE to only use the lastest tag (avoid rebulding many source file when developping)")
|
||||
|
||||
# Disable deprecated code
|
||||
set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.
|
||||
@@ -55,9 +53,6 @@ IF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
message( "CMAKE_BUILD_TYPE is empty, assuming build type is Release" )
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
ENDIF()
|
||||
IF (EMSCRIPTEN)
|
||||
set(BUILD_GDCPP FALSE CACHE BOOL "" FORCE) #Force disable GDC++ when compiling with emscripten.
|
||||
ENDIF()
|
||||
|
||||
IF("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "-s") #Force stripping to avoid errors when packaging for linux.
|
||||
@@ -84,7 +79,6 @@ endif()
|
||||
set(GD_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
#Add all the CMakeLists:
|
||||
ADD_SUBDIRECTORY(Version)
|
||||
ADD_SUBDIRECTORY(ExtLibs)
|
||||
IF(BUILD_CORE)
|
||||
ADD_SUBDIRECTORY(Core)
|
||||
@@ -92,10 +86,7 @@ ENDIF()
|
||||
IF(BUILD_GDJS)
|
||||
ADD_SUBDIRECTORY(GDJS)
|
||||
ENDIF()
|
||||
IF(BUILD_GDCPP)
|
||||
ADD_SUBDIRECTORY(GDCpp)
|
||||
ENDIF()
|
||||
IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/GDevelop.js/CMakeLists.txt" AND EMSCRIPTEN)
|
||||
IF(EMSCRIPTEN)
|
||||
ADD_SUBDIRECTORY(GDevelop.js)
|
||||
ENDIF()
|
||||
IF(BUILD_EXTENSIONS)
|
||||
|
@@ -57,7 +57,6 @@ IF(EMSCRIPTEN)
|
||||
ELSE()
|
||||
add_library(GDCore SHARED ${source_files})
|
||||
ENDIF()
|
||||
add_dependencies(GDCore GDVersion)
|
||||
IF(EMSCRIPTEN)
|
||||
set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
|
||||
ELSEIF(WIN32)
|
||||
|
@@ -14,9 +14,8 @@
|
||||
*
|
||||
* \section other Other documentations
|
||||
*
|
||||
* GDevelop is architectured around a `Core` (this library), platforms (`GDJS`, `GDCpp`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries.
|
||||
* GDevelop is architectured around a `Core` (this library), a game engine (`GDJS`) and extensions (`Extensions` folder). The editor (`newIDE` folder) is using all of these libraries.
|
||||
*
|
||||
* - [Open GDevelop C++ Platform documentation](../GDCpp Documentation/index.html)
|
||||
* - [Open GDevelop JS Platform documentation](../GDJS Documentation/index.html)
|
||||
* - <a href="https://github.com/4ian/GDevelop/blob/master/newIDE/README.md">Getting started with the editor</a>
|
||||
* - <a href="https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md">Getting started with the extensions</a>
|
||||
|
@@ -3,13 +3,17 @@
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include <iostream>
|
||||
#include "EffectsCodeGenerator.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "GDCore/Extensions/Metadata/EffectMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/Project/EffectsContainer.h"
|
||||
#include "GDCore/Project/Layer.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
|
||||
namespace gd {
|
||||
@@ -26,13 +30,30 @@ void ExposeProjectEffects(
|
||||
auto& layout = project.GetLayout(s);
|
||||
|
||||
for (std::size_t l = 0; l < layout.GetLayersCount(); ++l) {
|
||||
auto& layer = layout.GetLayer(l);
|
||||
|
||||
for (std::size_t e = 0; e < layer.GetEffectsCount(); ++e) {
|
||||
auto& effect = layer.GetEffect(e);
|
||||
auto& effects = layout.GetLayer(l).GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
|
||||
auto& effect = effects.GetEffect(e);
|
||||
worker(effect);
|
||||
}
|
||||
}
|
||||
|
||||
for (std::size_t i; i < layout.GetObjectsCount(); i++) {
|
||||
auto& object = layout.GetObject(i);
|
||||
auto& effects = object.GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
|
||||
auto& effect = effects.GetEffect(e);
|
||||
worker(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add global object effects
|
||||
for (std::size_t s = 0; s < project.GetObjectsCount(); s++) {
|
||||
auto& effects = project.GetObject(s).GetEffects();
|
||||
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
|
||||
auto& effect = effects.GetEffect(e);
|
||||
worker(effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -261,8 +261,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
EventsCodeGenerationContext& context) {
|
||||
gd::String conditionCode;
|
||||
|
||||
gd::InstructionMetadata instrInfos =
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetConditionMetadata(platform, condition.GetType());
|
||||
if (MetadataProvider::IsBadInstructionMetadata(instrInfos)) {
|
||||
return "/* Unknown instruction - skipped. */";
|
||||
}
|
||||
|
||||
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
|
||||
maxConditionsListsSize =
|
||||
@@ -299,15 +302,13 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
|
||||
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
condition.SetParameter(pNb, gd::Expression(""));
|
||||
condition.SetType("");
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter) !=
|
||||
instrInfos.parameters[pNb].supplementaryInformation) {
|
||||
condition.SetParameter(pNb, gd::Expression(""));
|
||||
condition.SetType("");
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,6 +426,11 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
|
||||
outputCode += "{\n";
|
||||
outputCode += conditionCode;
|
||||
outputCode += "}";
|
||||
} else {
|
||||
// Deprecated way to cancel code generation - but still honor it.
|
||||
// Can be removed once condition is passed by const reference to
|
||||
// GenerateConditionCode.
|
||||
outputCode += "/* Skipped condition (empty type) */";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,8 +446,11 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
gd::Instruction& action, EventsCodeGenerationContext& context) {
|
||||
gd::String actionCode;
|
||||
|
||||
gd::InstructionMetadata instrInfos =
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, action.GetType());
|
||||
if (MetadataProvider::IsBadInstructionMetadata(instrInfos)) {
|
||||
return "/* Unknown instruction - skipped. */";
|
||||
}
|
||||
|
||||
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
|
||||
|
||||
@@ -466,15 +475,13 @@ gd::String EventsCodeGenerator::GenerateActionCode(
|
||||
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
|
||||
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
|
||||
objectInParameter)) {
|
||||
action.SetParameter(pNb, gd::Expression(""));
|
||||
action.SetType("");
|
||||
return "/* Unknown object - skipped. */";
|
||||
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
|
||||
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
|
||||
GetObjectsAndGroups(),
|
||||
objectInParameter) !=
|
||||
instrInfos.parameters[pNb].supplementaryInformation) {
|
||||
action.SetParameter(pNb, gd::Expression(""));
|
||||
action.SetType("");
|
||||
return "/* Mismatched object type - skipped. */";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,7 +563,14 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
|
||||
gd::String actionCode = GenerateActionCode(actions[aId], context);
|
||||
|
||||
outputCode += "{";
|
||||
if (!actions[aId].GetType().empty()) outputCode += actionCode;
|
||||
if (actions[aId].GetType().empty()) {
|
||||
// Deprecated way to cancel code generation - but still honor it.
|
||||
// Can be removed once action is passed by const reference to
|
||||
// GenerateActionCode.
|
||||
outputCode += "/* Skipped action (empty type) */";
|
||||
} else {
|
||||
outputCode += actionCode;
|
||||
}
|
||||
outputCode += "}";
|
||||
}
|
||||
|
||||
|
@@ -462,24 +462,21 @@ class GD_CORE_API EventsCodeGenerator {
|
||||
* Other standard parameters type that should be implemented by platforms:
|
||||
* - currentScene: Reference to the current runtime scene.
|
||||
* - objectList : a map containing lists of objects which are specified by the
|
||||
object name in another parameter. (C++: std::map <gd::String,
|
||||
std::vector<RuntimeObject*> *>). Example:
|
||||
object name in another parameter. Example:
|
||||
* \code
|
||||
AddExpression("Count", _("Object count"), _("Count the number of picked
|
||||
objects"), _("Objects"), "res/conditions/nbObjet.png")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.SetFunctionName("PickedObjectsCount").SetIncludeFile("GDCpp/Extensions/Builtin/ObjectTools.h");
|
||||
.SetFunctionName("getPickedObjectsCount");
|
||||
|
||||
* \endcode
|
||||
* - objectListWithoutPicking : Same as objectList but do not pick object if
|
||||
they are not already picked.
|
||||
* - objectPtr : Return a pointer to object specified by the object name in
|
||||
another parameter ( C++: RuntimeObject* ). Example:
|
||||
* - objectPtr : Return a reference to the object specified by the object name in
|
||||
another parameter. Example:
|
||||
* \code
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectPtr", _("Target object"))
|
||||
//The called function will be called with this signature on the C++ platform:
|
||||
Function(gd::String, RuntimeObject*)
|
||||
* \endcode
|
||||
*/
|
||||
virtual gd::String GenerateParameterCodes(
|
||||
|
@@ -360,8 +360,11 @@ gd::String ExpressionCodeGenerator::GenerateDefaultValue(
|
||||
if (gd::ParameterMetadata::IsObject(type)) {
|
||||
return codeGenerator.GenerateBadObject();
|
||||
}
|
||||
if (gd::ParameterMetadata::IsExpression("string", type)) {
|
||||
return "\"\"";
|
||||
}
|
||||
|
||||
return (type == "string") ? "\"\"" : "0";
|
||||
return "0";
|
||||
}
|
||||
|
||||
void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
|
||||
|
@@ -16,7 +16,6 @@
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class EventsList;
|
||||
class MainFrameWrapper;
|
||||
class Project;
|
||||
class Layout;
|
||||
class EventsCodeGenerator;
|
||||
|
@@ -66,6 +66,22 @@ class GD_CORE_API ExpressionParser2 {
|
||||
return Start(type, objectName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an object name (or empty if none) and a behavior name (or empty if none),
|
||||
* return the index of the first parameter that is inside the parenthesis:
|
||||
* 0, 1 or 2.
|
||||
*
|
||||
* For example, in an expression like `Object.MyBehavior::Method("hello")`, the
|
||||
* parameter "hello" is the second parameter (the first being by convention Object,
|
||||
* and the second MyBehavior, also by convention).
|
||||
*/
|
||||
static size_t WrittenParametersFirstIndex(const gd::String &objectName,
|
||||
const gd::String &behaviorName) {
|
||||
// By convention, object is always the first parameter, and behavior the
|
||||
// second one.
|
||||
return !behaviorName.empty() ? 2 : (!objectName.empty() ? 1 : 0);
|
||||
}
|
||||
|
||||
private:
|
||||
/** \name Grammar
|
||||
* Each method is a part of the grammar.
|
||||
@@ -999,13 +1015,6 @@ class GD_CORE_API ExpressionParser2 {
|
||||
}
|
||||
///@}
|
||||
|
||||
static size_t WrittenParametersFirstIndex(const gd::String &objectName,
|
||||
const gd::String &behaviorName) {
|
||||
// By convention, object is always the first parameter, and behavior the
|
||||
// second one.
|
||||
return !behaviorName.empty() ? 2 : (!objectName.empty() ? 1 : 0);
|
||||
}
|
||||
|
||||
gd::String expression;
|
||||
std::size_t currentPosition;
|
||||
|
||||
|
@@ -32,7 +32,6 @@ class GD_CORE_API BuiltinExtensionsImplementer {
|
||||
static void ImplementsExternalLayoutsExtension(
|
||||
gd::PlatformExtension& extension);
|
||||
static void ImplementsFileExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsJoystickExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsKeyboardExtension(gd::PlatformExtension& extension);
|
||||
static void ImplementsMathematicalToolsExtension(
|
||||
gd::PlatformExtension& extension);
|
||||
|
@@ -206,7 +206,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"all of the forces it has."),
|
||||
_("Add to _PARAM0_ _PARAM3_ force of _PARAM1_ p/s on X axis and "
|
||||
"_PARAM2_ p/s on Y axis"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
|
||||
@@ -222,7 +222,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"using the specified angle and length."),
|
||||
_("Add to _PARAM0_ _PARAM3_ force, angle: _PARAM1_ degrees and "
|
||||
"length: _PARAM2_ pixels"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
|
||||
@@ -238,7 +238,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Add a force to an object to make it move toward a position."),
|
||||
_("Move _PARAM0_ toward _PARAM1_;_PARAM2_ with _PARAM4_ force of _PARAM3_ "
|
||||
"pixels"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force24.png",
|
||||
"res/actions/force.png")
|
||||
|
||||
@@ -251,30 +251,30 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
obj.AddAction(
|
||||
"AddForceTournePos",
|
||||
_("Add a force to move around a position"),
|
||||
_("Add a force to an object to make it rotate around a "
|
||||
"Add a force to move around a position",
|
||||
"Add a force to an object to make it rotate around a "
|
||||
"position.\nNote that the movement is not precise, especially if "
|
||||
"the speed is high.\nTo position an object around a position more "
|
||||
"precisely, use the actions in the category \"Position\"."),
|
||||
_("Rotate _PARAM0_ around _PARAM1_;_PARAM2_ at _PARAM3_ deg/sec and "
|
||||
"_PARAM4_ pixels away"),
|
||||
_("Movement"),
|
||||
"precisely, use the actions in the category \"Position\".",
|
||||
"Rotate _PARAM0_ around _PARAM1_;_PARAM2_ at _PARAM3_ deg/sec and "
|
||||
"_PARAM4_ pixels away",
|
||||
_("Movement using forces"),
|
||||
"res/actions/forceTourne24.png",
|
||||
"res/actions/forceTourne.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("X position of the center"))
|
||||
.AddParameter("expression", _("Y position of the center"))
|
||||
.AddParameter("expression", _("Speed (in Degrees per seconds)"))
|
||||
.AddParameter("expression", _("Distance (in pixels)"))
|
||||
.AddParameter("forceMultiplier", _("Force multiplier"))
|
||||
.AddParameter("expression", "X position of the center")
|
||||
.AddParameter("expression", "Y position of the center")
|
||||
.AddParameter("expression", "Speed (in Degrees per seconds)")
|
||||
.AddParameter("expression", "Distance (in pixels)")
|
||||
.AddParameter("forceMultiplier", "Force multiplier")
|
||||
.SetHidden();
|
||||
|
||||
obj.AddAction("Arreter",
|
||||
_("Stop the object"),
|
||||
_("Stop the object by deleting all of its forces."),
|
||||
_("Stop _PARAM0_ (remove all forces)"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/arreter24.png",
|
||||
"res/actions/arreter.png")
|
||||
|
||||
@@ -344,7 +344,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
obj.AddAction("SetObjectVariableAsBoolean",
|
||||
_("Boolean value of an object variable"),
|
||||
_("Change the boolean value of an object variable."),
|
||||
_("Set the boolean value of the variable _PARAM1_ of object "
|
||||
_("Set the boolean value of variable _PARAM1_ of "
|
||||
"_PARAM0_ to _PARAM2_"),
|
||||
_("Variables"),
|
||||
"res/actions/var24.png",
|
||||
@@ -360,7 +360,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Toggles the boolean value of an object variable.") + "\n" +
|
||||
_("If it was true, it will become false, and if it was false "
|
||||
"it will become true."),
|
||||
_("Toggle the boolean value of the variable _PARAM1_ of object "
|
||||
_("Toggle the boolean value of variable _PARAM1_ of "
|
||||
"_PARAM0_"),
|
||||
_("Variables"),
|
||||
"res/actions/var24.png",
|
||||
@@ -475,9 +475,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("Invisible",
|
||||
_("Invisibility of an object"),
|
||||
_("Check if an object is hidden."),
|
||||
_("_PARAM0_ is hidden"),
|
||||
"Invisibility of an object",
|
||||
"Check if an object is hidden.",
|
||||
"_PARAM0_ is hidden",
|
||||
_("Visibility"),
|
||||
"res/conditions/visibilite24.png",
|
||||
"res/conditions/visibilite.png")
|
||||
@@ -486,10 +486,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetHidden(); // Inverted "Visible" condition does the same thing.
|
||||
|
||||
obj.AddCondition("Arret",
|
||||
_("Object is stopped"),
|
||||
_("Object is stopped (no forces applied on it)"),
|
||||
_("Check if an object is not moving"),
|
||||
_("_PARAM0_ is stopped"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/arret24.png",
|
||||
"res/conditions/arret.png")
|
||||
|
||||
@@ -497,10 +497,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("Vitesse",
|
||||
_("Speed"),
|
||||
_("Speed (from forces)"),
|
||||
_("Compare the overall speed of an object"),
|
||||
_("the overall speed"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/vitesse24.png",
|
||||
"res/conditions/vitesse.png")
|
||||
|
||||
@@ -509,17 +509,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("AngleOfDisplacement",
|
||||
_("Angle of movement"),
|
||||
_("Compare the angle of displacement of an object"),
|
||||
_("Angle of displacement of _PARAM0_ is _PARAM1_ (tolerance "
|
||||
_("Angle of movement (using forces)"),
|
||||
_("Compare the angle of movement of an object according to the forces applied on it."),
|
||||
_("Angle of movement of _PARAM0_ is _PARAM1_ (tolerance"
|
||||
": _PARAM2_ degrees)"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/vitesse24.png",
|
||||
"res/conditions/vitesse.png")
|
||||
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("expression", _("Angle, in degrees"))
|
||||
.AddParameter("expression", _("Tolerance"))
|
||||
.AddParameter("expression", _("Tolerance, in degrees"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition("VarObjet",
|
||||
@@ -560,9 +560,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.SetDefaultValue("true");
|
||||
|
||||
obj.AddCondition("VarObjetDef",
|
||||
_("Variable defined"),
|
||||
_("Check if the variable is defined."),
|
||||
_("Variable _PARAM1 of _PARAM0_ is defined"),
|
||||
"Variable defined",
|
||||
"Check if the variable is defined.",
|
||||
"Variable _PARAM1 of _PARAM0_ is defined",
|
||||
_("Variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
@@ -632,7 +632,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Removes a variable at the specified index of an object array "
|
||||
"variable."),
|
||||
_("Remove variable at index _PARAM2_ from array variable _PARAM1_ of "
|
||||
"object _PARAM0_"),
|
||||
"_PARAM0_"),
|
||||
_("Variables/Collections/Arrays"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
@@ -671,7 +671,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Add a force to move toward an object"),
|
||||
_("Add a force to an object to make it move toward another."),
|
||||
_("Move _PARAM0_ toward _PARAM1_ with _PARAM3_ force of _PARAM2_ pixels"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/forceVers24.png",
|
||||
"res/actions/forceVers.png")
|
||||
|
||||
@@ -690,7 +690,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
"the actions in category \"Position\"."),
|
||||
_("Rotate _PARAM0_ around _PARAM1_ at _PARAM2_ deg/sec and _PARAM3_ "
|
||||
"pixels away"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/forceTourne24.png",
|
||||
"res/actions/forceTourne.png")
|
||||
|
||||
@@ -720,29 +720,29 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
// Deprecated action
|
||||
obj.AddAction("Rebondir",
|
||||
_("Move an object away from another"),
|
||||
_("Move an object away from another, using forces."),
|
||||
_("Move _PARAM0_ away from _PARAM1_ (only _PARAM0_ will move)"),
|
||||
_("Movement"),
|
||||
"Move an object away from another",
|
||||
"Move an object away from another, using forces.",
|
||||
"Move _PARAM0_ away from _PARAM1_ (only _PARAM0_ will move)",
|
||||
_("Movement using forces"),
|
||||
"res/actions/ecarter24.png",
|
||||
"res/actions/ecarter.png")
|
||||
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectList", _("Object 2 (won't move)"));
|
||||
.AddParameter("objectList", "Object 2 (won't move)");
|
||||
|
||||
// Deprecated action
|
||||
obj.AddAction("Ecarter",
|
||||
_("Move an object away from another"),
|
||||
_("Move an object away from another without using forces."),
|
||||
_("Move _PARAM0_ away from _PARAM2_ (only _PARAM0_ will move)"),
|
||||
"Move an object away from another",
|
||||
"Move an object away from another without using forces.",
|
||||
"Move _PARAM0_ away from _PARAM2_ (only _PARAM0_ will move)",
|
||||
_("Position"),
|
||||
"res/actions/ecarter24.png",
|
||||
"res/actions/ecarter.png")
|
||||
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("objectList", _("Object 2 (won't move)"));
|
||||
.AddParameter("objectList", "Object 2 (won't move)");
|
||||
|
||||
obj.AddAction("SeparateFromObjects",
|
||||
_("Separate objects"),
|
||||
@@ -795,8 +795,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
obj.AddCondition(
|
||||
"ObjectTimer",
|
||||
_("Value of a timer"),
|
||||
_("Test the elapsed time of a timer."),
|
||||
_("Value of an object timer"),
|
||||
_("Test the elapsed time of an object timer."),
|
||||
_("The timer _PARAM1_ of _PARAM0_ is greater than _PARAM2_ seconds"),
|
||||
_("Timers"),
|
||||
"res/conditions/timer24.png",
|
||||
@@ -806,8 +806,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("expression", _("Time in seconds"));
|
||||
|
||||
obj.AddCondition("ObjectTimerPaused",
|
||||
_("Timer paused"),
|
||||
_("Test if specified timer is paused."),
|
||||
_("Object timer paused"),
|
||||
_("Test if specified object timer is paused."),
|
||||
_("The timer _PARAM1_ of _PARAM0_ is paused"),
|
||||
_("Timers"),
|
||||
"res/conditions/timerPaused24.png",
|
||||
@@ -817,8 +817,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("ResetObjectTimer",
|
||||
_("Start (or reset) a timer"),
|
||||
_("Reset the specified timer, if the timer doesn't exist "
|
||||
_("Start (or reset) an object timer"),
|
||||
_("Reset the specified object timer, if the timer doesn't exist "
|
||||
"it's created and started."),
|
||||
_("Reset the timer _PARAM1_ of _PARAM0_"),
|
||||
_("Timers"),
|
||||
@@ -828,8 +828,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
|
||||
obj.AddAction("PauseObjectTimer",
|
||||
_("Pause a timer"),
|
||||
_("Pause a timer."),
|
||||
_("Pause an object timer"),
|
||||
_("Pause an object timer."),
|
||||
_("Pause timer _PARAM1_ of _PARAM0_"),
|
||||
_("Timers"),
|
||||
"res/actions/pauseTimer24.png",
|
||||
@@ -839,8 +839,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("UnPauseObjectTimer",
|
||||
_("Unpause a timer"),
|
||||
_("Unpause a timer."),
|
||||
_("Unpause an object timer"),
|
||||
_("Unpause an object timer."),
|
||||
_("Unpause timer _PARAM1_ of _PARAM0_"),
|
||||
_("Timers"),
|
||||
"res/actions/unPauseTimer24.png",
|
||||
@@ -850,8 +850,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("RemoveObjectTimer",
|
||||
_("Delete a timer"),
|
||||
_("Delete a timer from memory."),
|
||||
_("Delete an object timer"),
|
||||
_("Delete an object timer from memory."),
|
||||
_("Delete timer _PARAM1_ of _PARAM0_ from memory"),
|
||||
_("Timers"),
|
||||
"res/actions/timer24.png",
|
||||
@@ -882,37 +882,37 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceX",
|
||||
_("Average X coordinates of forces"),
|
||||
_("Average X coordinates of forces"),
|
||||
_("Movement"),
|
||||
_("X coordinate of the sum of forces"),
|
||||
_("X coordinate of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceY",
|
||||
_("Average Y coordinates of forces"),
|
||||
_("Average Y coordinates of forces"),
|
||||
_("Movement"),
|
||||
_("Y coordinate of the sum of forces"),
|
||||
_("Y coordinate of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceAngle",
|
||||
_("Average angle of the forces"),
|
||||
_("Average angle of the forces"),
|
||||
_("Movement"),
|
||||
_("Angle of the sum of forces"),
|
||||
_("Angle of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("ForceLength",
|
||||
_("Average length of the forces"),
|
||||
_("Average length of the forces"),
|
||||
_("Movement"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"));
|
||||
|
||||
obj.AddExpression("Longueur",
|
||||
_("Average length of the forces"),
|
||||
_("Average length of the forces"),
|
||||
_("Movement"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Length of the sum of forces"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/force.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.SetHidden();
|
||||
@@ -1021,9 +1021,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("objectvar", _("Variable"));
|
||||
|
||||
obj.AddExpression("ObjectTimerElapsedTime",
|
||||
_("Timer value"),
|
||||
_("Value of a timer"),
|
||||
_("Timers"),
|
||||
_("Object timer value"),
|
||||
_("Value of an object timer"),
|
||||
_("Object timers"),
|
||||
"res/actions/time.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Timer's name"));
|
||||
@@ -1072,6 +1072,74 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
.AddParameter("expression", _("Target X position"))
|
||||
.AddParameter("expression", _("Target Y position"));
|
||||
|
||||
obj.AddAction("EnableEffect",
|
||||
_("Enable an object effect"),
|
||||
_("Enable an effect on the object"),
|
||||
_("Enable effect _PARAM1_ on _PARAM0_: _PARAM2_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Effect Name"))
|
||||
.AddParameter("yesorno", _("Enable?"))
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("SetEffectDoubleParameter",
|
||||
_("Effect parameter (number)"),
|
||||
_("Change the value of a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM2_ to _PARAM3_ for effect _PARAM1_ of _PARAM0_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Effect Name"))
|
||||
.AddParameter("string", _("Parameter name"))
|
||||
.AddParameter("expression", _("New value"))
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("SetEffectStringParameter",
|
||||
_("Effect parameter (string)"),
|
||||
_("Change the value (string) of a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Set _PARAM2_ to _PARAM3_ for effect _PARAM1_ of _PARAM0_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Effect Name"))
|
||||
.AddParameter("string", _("Parameter name"))
|
||||
.AddParameter("string", _("New value"))
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("SetEffectBooleanParameter",
|
||||
_("Effect parameter (enable or disable)"),
|
||||
_("Enable or disable a parameter of an effect.") + "\n" +
|
||||
_("You can find the parameter names (and change the effect "
|
||||
"names) in the effects window."),
|
||||
_("Enable _PARAM2_ for effect _PARAM1_ of _PARAM0_: _PARAM3_"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Effect Name"))
|
||||
.AddParameter("string", _("Parameter Name"))
|
||||
.AddParameter("yesorno", _("Enable?"))
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddCondition("IsEffectEnabled",
|
||||
_("Effect is enabled"),
|
||||
_("Check if the effect on an object is enabled."),
|
||||
_("Effect _PARAM1_ of _PARAM0_ is enabled"),
|
||||
_("Effects"),
|
||||
"res/actions/effect24.png",
|
||||
"res/actions/effect.png")
|
||||
.AddParameter("object", _("Object"))
|
||||
.AddParameter("string", _("Effect Name"))
|
||||
.MarkAsSimple();
|
||||
|
||||
extension
|
||||
.AddAction("Create",
|
||||
_("Create an object"),
|
||||
@@ -1149,7 +1217,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
_("Moves all objects according to the forces they have. GDevelop "
|
||||
"calls this action at the end of the events by default."),
|
||||
_("Apply movement to all objects"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/actions/doMove24.png",
|
||||
"res/actions/doMove.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
@@ -1157,16 +1225,16 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsBaseObjectExtension(
|
||||
|
||||
extension
|
||||
.AddCondition("SeDirige",
|
||||
_("An object is moving toward another"),
|
||||
_("An object is moving toward another (using forces)"),
|
||||
_("Check if an object moves toward another.\nThe first "
|
||||
"object must move."),
|
||||
_("_PARAM0_ is moving toward _PARAM1_"),
|
||||
_("Movement"),
|
||||
_("Movement using forces"),
|
||||
"res/conditions/sedirige24.png",
|
||||
"res/conditions/sedirige.png")
|
||||
.AddParameter("objectList", _("Object"))
|
||||
.AddParameter("objectList", _("Object 2"))
|
||||
.AddParameter("expression", _("Angle of tolerance"))
|
||||
.AddParameter("expression", _("Tolerance, in degrees"))
|
||||
.AddCodeOnlyParameter("conditionInverted", "")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
|
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "AllBuiltinExtensions.h"
|
||||
#include "GDCore/Tools/Localization.h"
|
||||
|
||||
using namespace std;
|
||||
namespace gd {
|
||||
|
||||
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsJoystickExtension(
|
||||
gd::PlatformExtension& extension) {
|
||||
extension
|
||||
.SetExtensionInformation(
|
||||
"BuiltinJoystick",
|
||||
_("Joysticks features"),
|
||||
"Built-in extension that enables the use of joysticks.",
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
extension
|
||||
.AddCondition("JoystickButtonDown",
|
||||
_("A button on a joystick is pressed"),
|
||||
_("Test if a button on a joystick is pressed."),
|
||||
_("The button _PARAM2_ of joystick _PARAM1_ is pressed"),
|
||||
_("Joystick"),
|
||||
"res/conditions/joystick24.png",
|
||||
"res/conditions/joystick.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
|
||||
.AddParameter("expression", _("Button"));
|
||||
|
||||
extension
|
||||
.AddCondition("JoystickAxis",
|
||||
_("Value of an axis of a joystick"),
|
||||
_("Test the value of an axis of a joystick."),
|
||||
_("the value of the axis _PARAM2_ of joystick _PARAM1_"),
|
||||
_("Joystick"),
|
||||
"res/conditions/joystick24.png",
|
||||
"res/conditions/joystick.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
|
||||
.AddParameter("joyaxis", _("Axis"))
|
||||
.UseStandardRelationalOperatorParameters("number");
|
||||
|
||||
extension
|
||||
.AddAction(
|
||||
"GetJoystickAxis",
|
||||
_("Get the value of the axis of a joystick"),
|
||||
_("Save the value of the axis of the joystick (from -100 to 100)."),
|
||||
_("Save in _PARAM3_ the value of axis _PARAM2_ of joystick _PARAM1_"),
|
||||
_("Joystick"),
|
||||
"res/actions/joystick24.png",
|
||||
"res/actions/joystick.png")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
|
||||
.AddParameter("joyaxis", _("Axis"))
|
||||
.AddParameter("scenevar", _("Save the result to the scene variable"))
|
||||
.SetManipulatedType("number");
|
||||
|
||||
extension
|
||||
.AddExpression("GetJoystickAxis",
|
||||
_("Joystick axis"),
|
||||
_("Value of an axis of a joystick"),
|
||||
_("Joystick"),
|
||||
"res/conditions/joystick.png")
|
||||
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("expression", _("Joystick number (first joystick: 0)"))
|
||||
.AddParameter("joyaxis", _("Axis"));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -15,7 +15,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
||||
.SetExtensionInformation(
|
||||
"BuiltinNetwork",
|
||||
_("Basic internet features"),
|
||||
_("Features to send web requests, communicate with external \"APIs\" and other network related tasks."),
|
||||
_("Features to send web requests, communicate with external \"APIs\" "
|
||||
"and other network related tasks."),
|
||||
"Florian Rival",
|
||||
"Open source (MIT License)")
|
||||
.SetExtensionHelpPath("/all-features/network");
|
||||
@@ -24,33 +25,33 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
||||
extension
|
||||
.AddAction(
|
||||
"SendRequest",
|
||||
_("Send a request to a web page"),
|
||||
_("Send a request to the specified web page.\n\nPlease note that for "
|
||||
"the web games, the game must be hosted on the same host "
|
||||
"as specified below, except if the server is configured to answer "
|
||||
"to all requests (cross-domain requests)."),
|
||||
_("Send _PARAM3_ request to _PARAM0__PARAM1_ with body: _PARAM2_"),
|
||||
"Send a request to a web page",
|
||||
"Send a request to the specified web page.\n\nPlease note that for "
|
||||
"the web games, the game must be hosted on the same host "
|
||||
"as specified below, except if the server is configured to answer "
|
||||
"to all requests (cross-domain requests).",
|
||||
"Send _PARAM3_ request to _PARAM0__PARAM1_ with body: _PARAM2_",
|
||||
_("Network"),
|
||||
"res/actions/net24.png",
|
||||
"res/actions/net.png")
|
||||
.AddParameter("string", _("Host, with protocol"))
|
||||
.SetParameterLongDescription(_("Example: \"http://example.com/\"."))
|
||||
.AddParameter("string", _("Path"))
|
||||
.AddParameter("string", "Host, with protocol")
|
||||
.SetParameterLongDescription("Example: \"http://example.com/\".")
|
||||
.AddParameter("string", "Path")
|
||||
.SetParameterLongDescription(
|
||||
_("Example: \"/user/123\" or \"/some-page.php\"."))
|
||||
.AddParameter("string", _("Request body content"))
|
||||
.AddParameter("string", _("Method: \"POST\" or \"GET\""), "", true)
|
||||
.SetParameterLongDescription(_("If empty, \"GET\" will be used."))
|
||||
"Example: \"/user/123\" or \"/some-page.php\".")
|
||||
.AddParameter("string", "Request body content")
|
||||
.AddParameter("string", "Method: \"POST\" or \"GET\"", "", true)
|
||||
.SetParameterLongDescription("If empty, \"GET\" will be used.")
|
||||
.SetDefaultValue("\"GET\"")
|
||||
.AddParameter("string", _("Content type"), "", true)
|
||||
.AddParameter("string", "Content type", "", true)
|
||||
.SetParameterLongDescription(
|
||||
_("If empty, \"application/x-www-form-urlencoded\" will be used."))
|
||||
.AddParameter("scenevar", _("Reponse scene variable"), "", true)
|
||||
"If empty, \"application/x-www-form-urlencoded\" will be used.")
|
||||
.AddParameter("scenevar", "Reponse scene variable", "", true)
|
||||
.SetParameterLongDescription(
|
||||
_("The response of the server will be stored, as a string, in this "
|
||||
"variable. If the server returns *JSON*, you may want to use the "
|
||||
"action \"Convert JSON to a scene variable\" afterwards, to "
|
||||
"explore the results with a *structure variable*."))
|
||||
"The response of the server will be stored, as a string, in this "
|
||||
"variable. If the server returns *JSON*, you may want to use the "
|
||||
"action \"Convert JSON to a scene variable\" afterwards, to "
|
||||
"explore the results with a *structure variable*.")
|
||||
.MarkAsComplex()
|
||||
.SetHidden();
|
||||
|
||||
@@ -74,7 +75,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
|
||||
"highly recommended."))
|
||||
.AddParameter("string", _("Request body content"))
|
||||
.AddParameter("stringWithSelector",
|
||||
_("Resize mode"),
|
||||
_("Request method"),
|
||||
"[\"GET\", \"POST\", \"PUT\", \"HEAD\", \"DELETE\", "
|
||||
"\"PATCH\", \"OPTIONS\"]",
|
||||
false)
|
||||
|
@@ -7,7 +7,6 @@
|
||||
#include <SFML/Graphics/Sprite.hpp>
|
||||
#include <iostream>
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -16,11 +15,7 @@ namespace gd {
|
||||
Point Sprite::badPoint("");
|
||||
|
||||
Sprite::Sprite()
|
||||
:
|
||||
#if !defined(EMSCRIPTEN)
|
||||
hasItsOwnImage(false),
|
||||
#endif
|
||||
automaticCollisionMask(true),
|
||||
: automaticCollisionMask(true),
|
||||
origine("origine"),
|
||||
centre("centre"),
|
||||
automaticCentre(true) {
|
||||
@@ -73,36 +68,10 @@ Point& Sprite::GetPoint(const gd::String& name) {
|
||||
|
||||
bool Sprite::SetDefaultCenterPoint(bool enabled) {
|
||||
automaticCentre = enabled;
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
if (automaticCentre)
|
||||
centre.SetXY(sfmlSprite.getLocalBounds().width / 2,
|
||||
sfmlSprite.getLocalBounds().height / 2);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<Polygon2d> Sprite::GetCollisionMask() const {
|
||||
// TODO(perf): Cache to avoid re-creating a mask at every call
|
||||
#if !defined(EMSCRIPTEN)
|
||||
if (automaticCollisionMask) {
|
||||
std::vector<Polygon2d> mask;
|
||||
|
||||
Polygon2d rectangle;
|
||||
rectangle.vertices.push_back(sf::Vector2f(0, 0));
|
||||
rectangle.vertices.push_back(
|
||||
sf::Vector2f(sfmlSprite.getLocalBounds().width, 0));
|
||||
rectangle.vertices.push_back(sf::Vector2f(
|
||||
sfmlSprite.getLocalBounds().width, sfmlSprite.getLocalBounds().height));
|
||||
rectangle.vertices.push_back(
|
||||
sf::Vector2f(0, sfmlSprite.getLocalBounds().height));
|
||||
|
||||
mask.push_back(rectangle);
|
||||
return mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
return customCollisionMask;
|
||||
}
|
||||
|
||||
@@ -111,25 +80,4 @@ void Sprite::SetCustomCollisionMask(
|
||||
customCollisionMask = collisionMask;
|
||||
}
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
void Sprite::LoadImage(std::shared_ptr<SFMLTextureWrapper> image_) {
|
||||
sfmlImage = image_;
|
||||
sfmlSprite.setTexture(sfmlImage->texture, true);
|
||||
hasItsOwnImage = false;
|
||||
|
||||
if (automaticCentre)
|
||||
centre.SetXY(sfmlSprite.getLocalBounds().width / 2,
|
||||
sfmlSprite.getLocalBounds().height / 2);
|
||||
}
|
||||
|
||||
void Sprite::MakeSpriteOwnsItsImage() {
|
||||
if (!hasItsOwnImage || sfmlImage == std::shared_ptr<SFMLTextureWrapper>()) {
|
||||
sfmlImage = std::make_shared<SFMLTextureWrapper>(
|
||||
sfmlImage->texture); // Copy the texture.
|
||||
sfmlSprite.setTexture(sfmlImage->texture);
|
||||
hasItsOwnImage = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -11,7 +11,6 @@
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
|
||||
#include "GDCore/String.h"
|
||||
class SFMLTextureWrapper;
|
||||
#undef LoadImage // prevent windows.h to be polluting everything
|
||||
|
||||
namespace gd {
|
||||
@@ -19,9 +18,6 @@ namespace gd {
|
||||
/**
|
||||
* \brief Represents a sprite to be displayed on the screen.
|
||||
*
|
||||
* A sprite contains a SFML sprite to be displayed, some points,
|
||||
* and can also have its own texture (rather than a texture from ImageManager).
|
||||
*
|
||||
* \see Direction
|
||||
* \see SpriteObject
|
||||
* \ingroup SpriteObjectExtension
|
||||
@@ -163,53 +159,7 @@ class GD_CORE_API Sprite {
|
||||
*/
|
||||
bool SetDefaultCenterPoint(bool enabled);
|
||||
|
||||
#if !defined(EMSCRIPTEN)
|
||||
/** \name Sprite runtime management
|
||||
* Functions used by the C++ game engine.
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Get the SFML sprite associated with the sprite
|
||||
*/
|
||||
inline const sf::Sprite& GetSFMLSprite() const { return sfmlSprite; }
|
||||
|
||||
/**
|
||||
* \brief Get the SFML sprite associated with the sprite
|
||||
*/
|
||||
inline sf::Sprite& GetSFMLSprite() { return sfmlSprite; }
|
||||
|
||||
/**
|
||||
* \brief Set the SFML texture of the sprite
|
||||
*/
|
||||
void LoadImage(std::shared_ptr<SFMLTextureWrapper> image);
|
||||
|
||||
/**
|
||||
* \brief Get SFML texture used by the sprite
|
||||
*/
|
||||
std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture() { return sfmlImage; };
|
||||
|
||||
/**
|
||||
* \brief Get SFML texture used by the sprite
|
||||
*/
|
||||
const std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture() const {
|
||||
return sfmlImage;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Make the sprite, if it uses a texture from ImageManager,
|
||||
* copy this texture and take ownership of it.
|
||||
*/
|
||||
void MakeSpriteOwnsItsImage();
|
||||
///@}
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if !defined(EMSCRIPTEN)
|
||||
sf::Sprite sfmlSprite; ///< Displayed SFML sprite
|
||||
std::shared_ptr<SFMLTextureWrapper>
|
||||
sfmlImage; ///< Pointer to the image displayed by the sprite.
|
||||
bool hasItsOwnImage; ///< True if sfmlImage is only owned by this Sprite.
|
||||
#endif
|
||||
gd::String image; ///< Name of the image to be loaded in Image Manager.
|
||||
|
||||
bool automaticCollisionMask; ///< True to use the custom collision mask.
|
||||
|
@@ -66,7 +66,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/animation.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Animation name"))
|
||||
.AddParameter("objectAnimationName", _("Animation name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction(
|
||||
@@ -133,9 +133,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.MarkAsSimple();
|
||||
|
||||
obj.AddAction("TourneVersPos",
|
||||
_("Rotate an object toward a position"),
|
||||
_("Rotate an object towards a position."),
|
||||
_("Rotate _PARAM0_ towards _PARAM1_;_PARAM2_"),
|
||||
"Rotate an object toward a position",
|
||||
"Rotate an object towards a position.",
|
||||
"Rotate _PARAM0_ towards _PARAM1_;_PARAM2_",
|
||||
_("Direction"),
|
||||
"res/actions/direction24.png",
|
||||
"res/actions/direction.png")
|
||||
@@ -230,7 +230,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/conditions/animation.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Animation name"))
|
||||
.AddParameter("objectAnimationName", _("Animation name"))
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddCondition(
|
||||
@@ -249,7 +249,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
|
||||
obj.AddCondition("Sprite",
|
||||
_("Current frame"),
|
||||
_("Compare the index of the current frame in the animation displayed by the specified object. The first frame in an animation starts at index 0."),
|
||||
_("Compare the index of the current frame in the animation "
|
||||
"displayed by the specified object. The first frame in an "
|
||||
"animation starts at index 0."),
|
||||
_("the animation frame"),
|
||||
_("Animations and images"),
|
||||
"res/conditions/sprite24.png",
|
||||
@@ -332,47 +334,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.UseStandardRelationalOperatorParameters("number")
|
||||
.MarkAsAdvanced();
|
||||
|
||||
obj.AddAction("CopyImageOnImageOfSprite",
|
||||
_("Copy an image on the current one of an object"),
|
||||
_("Copy an image on the current image of an object.\nNote that "
|
||||
"the source image must be preferably kept loaded in memory."),
|
||||
_("Copy image _PARAM2_ on the current of _PARAM0_ at "
|
||||
"_PARAM3_;_PARAM4_"),
|
||||
obj.AddAction("ChangeColor",
|
||||
_("Tint color"),
|
||||
_("Change the tint of an object. The default color is white."),
|
||||
_("Change tint of _PARAM0_ to _PARAM1_"),
|
||||
_("Effects"),
|
||||
"res/copy24.png",
|
||||
"res/copyicon.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.AddParameter("string", _("Name of the source image"))
|
||||
.AddParameter("expression", _("X position"))
|
||||
.AddParameter("expression", _("Y position"))
|
||||
.AddParameter(
|
||||
"yesorno",
|
||||
_("Should the copy take in account the source transparency\?"));
|
||||
|
||||
obj.AddAction(
|
||||
"CreateMaskFromColorOnActualImage", // Actual is indeed a mistake :
|
||||
// Current should have been
|
||||
// chosen.
|
||||
_("Make a color of the image of an object transparent"),
|
||||
_("Make a color of the image of an object transparent."),
|
||||
_("Make color _PARAM1_ of the current image of _PARAM0_ transparent"),
|
||||
_("Effects"),
|
||||
"res/actions/opacity24.png",
|
||||
"res/actions/opacity.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("color", _("Color to make transparent"));
|
||||
|
||||
obj.AddAction(
|
||||
"ChangeColor",
|
||||
_("Tint color"),
|
||||
_("Change the tint of an object. The default color is white."),
|
||||
_("Change tint of _PARAM0_ to _PARAM1_"),
|
||||
_("Effects"),
|
||||
"res/actions/color24.png",
|
||||
"res/actions/color.png")
|
||||
"res/actions/color24.png",
|
||||
"res/actions/color.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("color", _("Tint"));
|
||||
@@ -436,15 +404,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
.AddParameter("object", _("Object"), "Sprite");
|
||||
|
||||
obj.AddAction("TourneVers",
|
||||
_("Rotate an object toward another"),
|
||||
_("Rotate an object towards another."),
|
||||
_("Rotate _PARAM0_ towards _PARAM1_"),
|
||||
"Rotate an object toward another",
|
||||
"Rotate an object towards another.",
|
||||
"Rotate _PARAM0_ towards _PARAM1_",
|
||||
_("Direction"),
|
||||
"res/actions/direction24.png",
|
||||
"res/actions/direction.png")
|
||||
|
||||
.AddParameter("object", _("Object to be rotated"), "Sprite")
|
||||
.AddParameter("objectPtr", _("Rotate toward this object"))
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("objectPtr", "Rotate toward this object")
|
||||
.AddCodeOnlyParameter("currentScene", "")
|
||||
.SetHidden(); // Deprecated
|
||||
|
||||
@@ -455,7 +423,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"), "", true);
|
||||
.AddParameter("objectPointName", _("Name of the point"), "", true);
|
||||
|
||||
obj.AddExpression("Y",
|
||||
_("Y position of a point"),
|
||||
@@ -464,7 +432,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
.SetHidden()
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"), "", true);
|
||||
.AddParameter("objectPointName", _("Name of the point"), "", true);
|
||||
|
||||
obj.AddExpression("PointX",
|
||||
_("X position of a point"),
|
||||
@@ -473,7 +441,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"));
|
||||
.AddParameter("objectPointName", _("Name of the point"));
|
||||
|
||||
obj.AddExpression("PointY",
|
||||
_("Y position of a point"),
|
||||
@@ -482,7 +450,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
|
||||
"res/actions/position.png")
|
||||
|
||||
.AddParameter("object", _("Object"), "Sprite")
|
||||
.AddParameter("string", _("Name of the point"));
|
||||
.AddParameter("objectPointName", _("Name of the point"));
|
||||
|
||||
obj.AddExpression("Direc",
|
||||
_("Direction"),
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
|
||||
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
#include "GDCore/Project/InitialInstance.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
|
@@ -16,7 +16,6 @@ class Object;
|
||||
class Layout;
|
||||
class Sprite;
|
||||
class Animation;
|
||||
class MainFrameWrapper;
|
||||
class SerializerElement;
|
||||
class PropertyDescriptor;
|
||||
} // namespace gd
|
||||
|
@@ -112,9 +112,9 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
||||
|
||||
extension
|
||||
.AddExpression("StrRFind",
|
||||
_("Search in a text from the end"),
|
||||
_("Search in a text from the end (return the position of "
|
||||
"the result or -1 if not found)"),
|
||||
"Search in a text from the end",
|
||||
"Search in a text from the end (return the position of "
|
||||
"the result or -1 if not found)",
|
||||
_("Manipulation of text"),
|
||||
"res/conditions/toujours24.png")
|
||||
|
||||
@@ -152,17 +152,17 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
|
||||
extension
|
||||
.AddExpression(
|
||||
"StrRFindFrom",
|
||||
_("Search in a text from the end, starting from a position"),
|
||||
_("Search in a text from the end, starting from a position (return "
|
||||
"the position of the result or -1 if not found)"),
|
||||
"Search in a text from the end, starting from a position",
|
||||
"Search in a text from the end, starting from a position (return "
|
||||
"the position of the result or -1 if not found)",
|
||||
_("Manipulation of text"),
|
||||
"res/conditions/toujours24.png")
|
||||
|
||||
.AddParameter("string", _("Text"))
|
||||
.AddParameter("string", _("Text to search for"))
|
||||
.AddParameter("expression",
|
||||
_("Position of the last character in the string to be "
|
||||
"considered in the search"))
|
||||
"Position of the last character in the string to be "
|
||||
"considered in the search")
|
||||
.SetHidden(); // Deprecated, see StrFindLastFrom instead.
|
||||
|
||||
extension
|
||||
|
@@ -87,9 +87,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
|
||||
extension
|
||||
.AddCondition("VarSceneDef",
|
||||
_("Test if a scene variable is defined"),
|
||||
_("Test if the scene variable exists."),
|
||||
_("Scene variable _PARAM0_ is defined"),
|
||||
"Test if a scene variable is defined",
|
||||
"Test if the scene variable exists.",
|
||||
"Scene variable _PARAM0_ is defined",
|
||||
_("Variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
@@ -136,9 +136,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
|
||||
extension
|
||||
.AddCondition("VarGlobalDef",
|
||||
_("Test if a global variable is defined"),
|
||||
_("Test if a global variable exists"),
|
||||
_("Global variable _PARAM0_ is defined"),
|
||||
"Test if a global variable is defined",
|
||||
"Test if a global variable exists",
|
||||
"Global variable _PARAM0_ is defined",
|
||||
_("Variables/Global variables"),
|
||||
"res/conditions/var24.png",
|
||||
"res/conditions/var.png")
|
||||
@@ -341,7 +341,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"SceneVariableRemoveAt",
|
||||
_("Remove variable from a scene array (by index)"),
|
||||
_("Removes a variable at the specified index of a scene array variable."),
|
||||
_("Remove variable at index _PARAM1_ from array variable _PARAM0_"),
|
||||
_("Remove variable at index _PARAM1_ from scene array variable _PARAM0_"),
|
||||
_("Variables/Collections/Arrays"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
@@ -367,7 +367,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
|
||||
"GlobalVariableRemoveAt",
|
||||
_("Remove variable from a global array (by index)"),
|
||||
_("Removes a variable at the specified index of a global array variable."),
|
||||
_("Remove variable at index _PARAM1_ from array variable _PARAM0_"),
|
||||
_("Remove variable at index _PARAM1_ from global array variable _PARAM0_"),
|
||||
_("Variables/Global variables/Collections/Arrays"),
|
||||
"res/actions/var24.png",
|
||||
"res/actions/var.png")
|
||||
|
@@ -275,6 +275,76 @@ BehaviorMetadata::AddExpressionAndConditionAndAction(
|
||||
expression, condition, action);
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::InstructionMetadata& BehaviorMetadata::AddDuplicatedAction(
|
||||
const gd::String& newActionName, const gd::String& copiedActionName) {
|
||||
gd::String newNameWithNamespace = extensionNamespace + newActionName;
|
||||
gd::String copiedNameWithNamespace = extensionNamespace + copiedActionName;
|
||||
|
||||
auto copiedAction = actionsInfos.find(copiedNameWithNamespace);
|
||||
if (copiedAction == actionsInfos.end()) {
|
||||
gd::LogWarning("Could not find an action with name " +
|
||||
copiedNameWithNamespace + " to copy.");
|
||||
} else {
|
||||
actionsInfos[newNameWithNamespace] = copiedAction->second;
|
||||
}
|
||||
|
||||
return actionsInfos[newNameWithNamespace];
|
||||
}
|
||||
|
||||
gd::InstructionMetadata& BehaviorMetadata::AddDuplicatedCondition(
|
||||
const gd::String& newConditionName, const gd::String& copiedConditionName) {
|
||||
gd::String newNameWithNamespace = extensionNamespace + newConditionName;
|
||||
gd::String copiedNameWithNamespace = extensionNamespace + copiedConditionName;
|
||||
|
||||
auto copiedCondition = conditionsInfos.find(copiedNameWithNamespace);
|
||||
if (copiedCondition == conditionsInfos.end()) {
|
||||
gd::LogWarning("Could not find a condition with name " +
|
||||
copiedNameWithNamespace + " to copy.");
|
||||
} else {
|
||||
conditionsInfos[newNameWithNamespace] = copiedCondition->second;
|
||||
}
|
||||
|
||||
return conditionsInfos[newNameWithNamespace];
|
||||
}
|
||||
|
||||
gd::ExpressionMetadata& BehaviorMetadata::AddDuplicatedExpression(
|
||||
const gd::String& newExpressionName,
|
||||
const gd::String& copiedExpressionName) {
|
||||
gd::String newNameWithNamespace = extensionNamespace + newExpressionName;
|
||||
gd::String copiedNameWithNamespace =
|
||||
extensionNamespace + copiedExpressionName;
|
||||
|
||||
auto copiedExpression = expressionsInfos.find(copiedNameWithNamespace);
|
||||
if (copiedExpression == expressionsInfos.end()) {
|
||||
gd::LogWarning("Could not find an expression with name " +
|
||||
copiedNameWithNamespace + " to copy.");
|
||||
} else {
|
||||
expressionsInfos[newNameWithNamespace] = copiedExpression->second;
|
||||
}
|
||||
|
||||
return expressionsInfos[newNameWithNamespace];
|
||||
}
|
||||
|
||||
gd::ExpressionMetadata& BehaviorMetadata::AddDuplicatedStrExpression(
|
||||
const gd::String& newExpressionName,
|
||||
const gd::String& copiedExpressionName) {
|
||||
gd::String newNameWithNamespace = extensionNamespace + newExpressionName;
|
||||
gd::String copiedNameWithNamespace =
|
||||
extensionNamespace + copiedExpressionName;
|
||||
|
||||
auto copiedExpression = strExpressionsInfos.find(copiedNameWithNamespace);
|
||||
if (copiedExpression == strExpressionsInfos.end()) {
|
||||
gd::LogWarning("Could not find a string expression with name " +
|
||||
copiedNameWithNamespace + " to copy.");
|
||||
} else {
|
||||
strExpressionsInfos[newNameWithNamespace] = copiedExpression->second;
|
||||
}
|
||||
|
||||
return strExpressionsInfos[newNameWithNamespace];
|
||||
}
|
||||
#endif
|
||||
|
||||
BehaviorMetadata& BehaviorMetadata::SetFullName(const gd::String& fullname_) {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
fullname = fullname_;
|
||||
@@ -323,4 +393,14 @@ const gd::String& BehaviorMetadata::GetName() const {
|
||||
return instance->GetTypeName();
|
||||
}
|
||||
|
||||
gd::Behavior& BehaviorMetadata::Get() const {
|
||||
if (!instance)
|
||||
gd::LogFatalError(
|
||||
"Trying to get a behavior from a BehaviorMetadata that has no "
|
||||
"behavior. This will crash - please double check that the "
|
||||
"BehaviorMetadata is valid.");
|
||||
|
||||
return *instance;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -138,6 +138,46 @@ class GD_CORE_API BehaviorMetadata {
|
||||
const gd::String& group,
|
||||
const gd::String& icon);
|
||||
|
||||
/**
|
||||
* \brief Create a new action which is the duplicate of the specified one.
|
||||
*
|
||||
* Useful for handling a deprecated action that is just a "copy" of the new
|
||||
* one.
|
||||
*/
|
||||
gd::InstructionMetadata& AddDuplicatedAction(
|
||||
const gd::String& newActionName, const gd::String& copiedActionName);
|
||||
|
||||
/**
|
||||
* \brief Create a new condition which is the duplicate of the specified one.
|
||||
*
|
||||
* Useful for handling a deprecated condition that is just a "copy" of the new
|
||||
* one.
|
||||
*/
|
||||
gd::InstructionMetadata& AddDuplicatedCondition(
|
||||
const gd::String& newConditionName,
|
||||
const gd::String& copiedConditionName);
|
||||
|
||||
/**
|
||||
* \brief Create a new expression which is the duplicate of the specified one.
|
||||
*
|
||||
* Useful for handling a deprecated expression that is just a "copy" of the
|
||||
* new one.
|
||||
*/
|
||||
gd::ExpressionMetadata& AddDuplicatedExpression(
|
||||
const gd::String& newExpressionName,
|
||||
const gd::String& copiedExpressionName);
|
||||
|
||||
/**
|
||||
* \brief Create a new string expression which is the duplicate of the
|
||||
* specified one.
|
||||
*
|
||||
* Useful for handling a deprecated string expression that is just a "copy" of
|
||||
* the new one.
|
||||
*/
|
||||
gd::ExpressionMetadata& AddDuplicatedStrExpression(
|
||||
const gd::String& newExpressionName,
|
||||
const gd::String& copiedExpressionName);
|
||||
|
||||
BehaviorMetadata& SetFullName(const gd::String& fullname_);
|
||||
BehaviorMetadata& SetDefaultName(const gd::String& defaultName_);
|
||||
BehaviorMetadata& SetDescription(const gd::String& description_);
|
||||
@@ -200,7 +240,7 @@ class GD_CORE_API BehaviorMetadata {
|
||||
/**
|
||||
* \brief Return the associated gd::Behavior, handling behavior contents.
|
||||
*/
|
||||
gd::Behavior& Get() const { return *instance; }
|
||||
gd::Behavior& Get() const;
|
||||
|
||||
/**
|
||||
* \brief Return the associated gd::BehaviorsSharedData, handling behavior
|
||||
|
@@ -7,7 +7,8 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
EffectMetadata::EffectMetadata(const gd::String& type_) : type(type_) {}
|
||||
EffectMetadata::EffectMetadata(const gd::String& type_)
|
||||
: type(type_), isMarkedAsNotWorkingForObjects(false) {}
|
||||
|
||||
EffectMetadata& EffectMetadata::SetIncludeFile(const gd::String& includeFile) {
|
||||
includeFiles.clear();
|
||||
@@ -22,4 +23,9 @@ EffectMetadata& EffectMetadata::AddIncludeFile(const gd::String& includeFile) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
EffectMetadata& EffectMetadata::MarkAsNotWorkingForObjects() {
|
||||
isMarkedAsNotWorkingForObjects = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "GDCore/Project/PropertyDescriptor.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
@@ -49,7 +50,8 @@ class GD_CORE_API EffectMetadata {
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the help path of the effect, relative to the GDevelop documentation root.
|
||||
* Set the help path of the effect, relative to the GDevelop documentation
|
||||
* root.
|
||||
*/
|
||||
EffectMetadata& SetHelpPath(const gd::String& path) {
|
||||
helpPath = path;
|
||||
@@ -66,6 +68,11 @@ class GD_CORE_API EffectMetadata {
|
||||
*/
|
||||
EffectMetadata& AddIncludeFile(const gd::String& includeFile);
|
||||
|
||||
/**
|
||||
* \brief Mark the effect as not working as an object effect.
|
||||
*/
|
||||
EffectMetadata& MarkAsNotWorkingForObjects();
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the properties of this effect.
|
||||
*/
|
||||
@@ -81,12 +88,14 @@ class GD_CORE_API EffectMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the help path of the effect, relative to the GDevelop documentation root.
|
||||
* \brief Get the help path of the effect, relative to the GDevelop
|
||||
* documentation root.
|
||||
*/
|
||||
const gd::String& GetHelpPath() const { return helpPath; }
|
||||
|
||||
/**
|
||||
* \brief Get the type of the effect (its internal name, like "BlackAndWhite").
|
||||
* \brief Get the type of the effect (its internal name, like
|
||||
* "BlackAndWhite").
|
||||
*/
|
||||
const gd::String& GetType() const { return type; }
|
||||
|
||||
@@ -107,6 +116,11 @@ class GD_CORE_API EffectMetadata {
|
||||
return includeFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the effect is marked as not working as an object effect.
|
||||
*/
|
||||
bool IsMarkedAsNotWorkingForObjects() const { return isMarkedAsNotWorkingForObjects; };
|
||||
|
||||
private:
|
||||
gd::String extensionNamespace;
|
||||
gd::String type;
|
||||
@@ -114,6 +128,7 @@ class GD_CORE_API EffectMetadata {
|
||||
gd::String fullname;
|
||||
gd::String description;
|
||||
std::vector<gd::String> includeFiles;
|
||||
bool isMarkedAsNotWorkingForObjects;
|
||||
std::map<gd::String, gd::PropertyDescriptor> properties;
|
||||
};
|
||||
|
||||
|
@@ -187,6 +187,19 @@ class GD_CORE_API InstructionMetadata {
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Set the additional information, used for some parameters
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter), for the last added parameter.
|
||||
*
|
||||
* \see AddParameter
|
||||
*/
|
||||
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
|
||||
if (!parameters.empty())
|
||||
parameters.back().SetExtraInfo(extraInfo);
|
||||
return *this;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Add the default parameters for an instruction manipulating the
|
||||
* specified type ("string", "number") with the default operators.
|
||||
@@ -221,14 +234,14 @@ class GD_CORE_API InstructionMetadata {
|
||||
/**
|
||||
* \brief Check if the instruction is an object instruction.
|
||||
*/
|
||||
bool IsObjectInstruction() {
|
||||
bool IsObjectInstruction() const {
|
||||
return isObjectInstruction;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the instruction is a behavior instruction.
|
||||
*/
|
||||
bool IsBehaviorInstruction() {
|
||||
bool IsBehaviorInstruction() const {
|
||||
return isBehaviorInstruction;
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
gd::BehaviorMetadata MetadataProvider::badBehaviorInfo;
|
||||
gd::BehaviorMetadata MetadataProvider::badBehaviorMetadata;
|
||||
gd::ObjectMetadata MetadataProvider::badObjectInfo;
|
||||
gd::EffectMetadata MetadataProvider::badEffectMetadata;
|
||||
gd::InstructionMetadata MetadataProvider::badInstructionMetadata;
|
||||
@@ -38,7 +38,7 @@ MetadataProvider::GetExtensionAndBehaviorMetadata(const gd::Platform& platform,
|
||||
}
|
||||
}
|
||||
|
||||
return ExtensionAndMetadata<BehaviorMetadata>(badExtension, badBehaviorInfo);
|
||||
return ExtensionAndMetadata<BehaviorMetadata>(badExtension, badBehaviorMetadata);
|
||||
}
|
||||
|
||||
const BehaviorMetadata& MetadataProvider::GetBehaviorMetadata(
|
||||
|
@@ -245,13 +245,21 @@ class GD_CORE_API MetadataProvider {
|
||||
return &metadata == &badExpressionMetadata;
|
||||
}
|
||||
|
||||
static bool IsBadInstructionMetadata(const gd::InstructionMetadata& metadata) {
|
||||
return &metadata == &badInstructionMetadata;
|
||||
}
|
||||
|
||||
static bool IsBadBehaviorMetadata(const gd::BehaviorMetadata& metadata) {
|
||||
return &metadata == &badBehaviorMetadata;
|
||||
}
|
||||
|
||||
virtual ~MetadataProvider();
|
||||
|
||||
private:
|
||||
MetadataProvider();
|
||||
|
||||
static PlatformExtension badExtension;
|
||||
static BehaviorMetadata badBehaviorInfo;
|
||||
static BehaviorMetadata badBehaviorMetadata;
|
||||
static ObjectMetadata badObjectInfo;
|
||||
static EffectMetadata badEffectMetadata;
|
||||
static gd::InstructionMetadata badInstructionMetadata;
|
||||
|
@@ -68,14 +68,14 @@ class GD_CORE_API ParameterMetadata {
|
||||
|
||||
/**
|
||||
* \brief Return an optional additional information, used for some parameters
|
||||
* with special type (For example, it can contains the type of object accepted
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter).
|
||||
*/
|
||||
const gd::String &GetExtraInfo() const { return supplementaryInformation; }
|
||||
|
||||
/**
|
||||
* \brief Set an optional additional information, used for some parameters
|
||||
* with special type (For example, it can contains the type of object accepted
|
||||
* with special type (for example, it can contains the type of object accepted
|
||||
* by the parameter).
|
||||
*/
|
||||
ParameterMetadata &SetExtraInfo(const gd::String &supplementaryInformation_) {
|
||||
@@ -175,7 +175,8 @@ class GD_CORE_API ParameterMetadata {
|
||||
* \brief Return true if the type of the parameter is an expression of the
|
||||
* given type.
|
||||
* \note If you had a new type of parameter, also add it in the IDE (
|
||||
* see EventsFunctionParametersEditor) and in the EventsCodeGenerator.
|
||||
* see EventsFunctionParametersEditor, ParameterRenderingService
|
||||
* and ExpressionAutocompletion) and in the EventsCodeGenerator.
|
||||
*/
|
||||
static bool IsExpression(const gd::String &type,
|
||||
const gd::String ¶meterType) {
|
||||
@@ -187,7 +188,9 @@ class GD_CORE_API ParameterMetadata {
|
||||
parameterType == "color" || parameterType == "file" ||
|
||||
parameterType == "joyaxis" ||
|
||||
parameterType == "stringWithSelector" ||
|
||||
parameterType == "sceneName";
|
||||
parameterType == "sceneName" ||
|
||||
parameterType == "objectPointName" ||
|
||||
parameterType == "objectAnimationName";
|
||||
} else if (type == "variable") {
|
||||
return parameterType == "objectvar" || parameterType == "globalvar" ||
|
||||
parameterType == "scenevar";
|
||||
|
@@ -4,6 +4,7 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ParameterMetadataTools.h"
|
||||
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
@@ -60,6 +61,24 @@ void ParameterMetadataTools::IterateOverParameters(
|
||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::String& parameterValue,
|
||||
const gd::String& lastObjectName)> fn) {
|
||||
IterateOverParametersWithIndex(
|
||||
parameters,
|
||||
parametersMetadata,
|
||||
[&fn](const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::String& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
fn(parameterMetadata, parameterValue, lastObjectName);
|
||||
});
|
||||
}
|
||||
|
||||
void ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::String& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName)> fn) {
|
||||
gd::String lastObjectName = "";
|
||||
for (std::size_t pNb = 0; pNb < parametersMetadata.size(); ++pNb) {
|
||||
const gd::ParameterMetadata& parameterMetadata = parametersMetadata[pNb];
|
||||
@@ -70,7 +89,7 @@ void ParameterMetadataTools::IterateOverParameters(
|
||||
? parameterMetadata.GetDefaultValue()
|
||||
: parameterValue;
|
||||
|
||||
fn(parameterMetadata, parameterValueOrDefault, lastObjectName);
|
||||
fn(parameterMetadata, parameterValueOrDefault, pNb, lastObjectName);
|
||||
|
||||
// Memorize the last object name. By convention, parameters that require
|
||||
// an object (mainly, "objectvar" and "behavior") should be placed after
|
||||
|
@@ -35,6 +35,19 @@ class GD_CORE_API ParameterMetadataTools {
|
||||
const gd::String& parameterValue,
|
||||
const gd::String& lastObjectName)> fn);
|
||||
|
||||
/**
|
||||
* Iterate over a list of parameters and their values.
|
||||
* Callback function is called with the parameter metadata, its value
|
||||
* and if applicable the name of the object it's linked to.
|
||||
*/
|
||||
static void IterateOverParametersWithIndex(
|
||||
const std::vector<gd::Expression>& parameters,
|
||||
const std::vector<gd::ParameterMetadata>& parametersMetadata,
|
||||
std::function<void(const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::String& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName)> fn);
|
||||
|
||||
/**
|
||||
* Given a parameter, return, if applicable, the index of the object parameter
|
||||
* it's linked to.
|
||||
|
@@ -100,26 +100,6 @@ std::unique_ptr<gd::Object> Platform::CreateObject(
|
||||
return std::unique_ptr<gd::Object>(std::move(object));
|
||||
}
|
||||
|
||||
gd::Behavior* Platform::GetBehavior(const gd::String& behaviorType) const {
|
||||
for (std::size_t i = 0; i < extensionsLoaded.size(); ++i) {
|
||||
gd::Behavior* behavior = extensionsLoaded[i]->GetBehavior(behaviorType);
|
||||
if (behavior) return behavior;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* Platform::GetBehaviorSharedDatas(
|
||||
const gd::String& behaviorType) const {
|
||||
for (std::size_t i = 0; i < extensionsLoaded.size(); ++i) {
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
extensionsLoaded[i]->GetBehaviorSharedDatas(behaviorType);
|
||||
if (behaviorSharedData) return behaviorSharedData;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
std::shared_ptr<gd::BaseEvent> Platform::CreateEvent(
|
||||
const gd::String& eventType) const {
|
||||
|
@@ -126,7 +126,8 @@ class GD_CORE_API Platform {
|
||||
///@}
|
||||
|
||||
/** \name Factory method
|
||||
* Member functions used to create the platforms objects
|
||||
* Member functions used to create the platform objects.
|
||||
* TODO: This could be moved to gd::MetadataProvider.
|
||||
*/
|
||||
///@{
|
||||
|
||||
@@ -136,18 +137,6 @@ class GD_CORE_API Platform {
|
||||
std::unique_ptr<gd::Object> CreateObject(gd::String type,
|
||||
const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Get the class handling the behavior with the given type, or
|
||||
* `nullptr` if no behavior with the given type is found.
|
||||
*/
|
||||
gd::Behavior* GetBehavior(const gd::String& type) const;
|
||||
|
||||
/**
|
||||
* \brief Get the class handling the behavior shared data with the given type,
|
||||
* or `nullptr` if no behavior with the given type is found.
|
||||
*/
|
||||
gd::BehaviorsSharedData* GetBehaviorSharedDatas(const gd::String& type) const;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Create an event of given type
|
||||
@@ -165,11 +154,13 @@ class GD_CORE_API Platform {
|
||||
/**
|
||||
* \brief Called when the IDE is about to shut down: Take this opportunity for
|
||||
* erasing for example any temporary file.
|
||||
* @deprecated This should be removed.
|
||||
*/
|
||||
virtual void OnIDEClosed(){};
|
||||
|
||||
/**
|
||||
* \brief Called when the IDE is initialized and ready to be used.
|
||||
* @deprecated This should be removed.
|
||||
*/
|
||||
virtual void OnIDEInitialized(){};
|
||||
|
||||
|
@@ -512,7 +512,7 @@ PlatformExtension::GetAllStrExpressionsForBehavior(gd::String autoType) {
|
||||
return badExpressionsMetadata;
|
||||
}
|
||||
|
||||
gd::BaseEventSPtr PlatformExtension::CreateEvent(gd::String eventType) const {
|
||||
gd::BaseEventSPtr PlatformExtension::CreateEvent(const gd::String& eventType) const {
|
||||
if (eventsInfos.find(eventType) != eventsInfos.end()) {
|
||||
if (eventsInfos.find(eventType)->second.instance ==
|
||||
std::shared_ptr<BaseEvent>()) {
|
||||
@@ -531,14 +531,14 @@ gd::BaseEventSPtr PlatformExtension::CreateEvent(gd::String eventType) const {
|
||||
#endif
|
||||
|
||||
CreateFunPtr PlatformExtension::GetObjectCreationFunctionPtr(
|
||||
gd::String objectType) const {
|
||||
const gd::String& objectType) const {
|
||||
if (objectsInfos.find(objectType) != objectsInfos.end())
|
||||
return objectsInfos.find(objectType)->second.createFunPtr;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gd::Behavior* PlatformExtension::GetBehavior(gd::String type) const {
|
||||
gd::Behavior* PlatformExtension::GetBehavior(const gd::String& type) const {
|
||||
if (behaviorsInfo.find(type) != behaviorsInfo.end())
|
||||
return &behaviorsInfo.find(type)->second.Get();
|
||||
|
||||
@@ -546,7 +546,7 @@ gd::Behavior* PlatformExtension::GetBehavior(gd::String type) const {
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* PlatformExtension::GetBehaviorSharedDatas(
|
||||
gd::String type) const {
|
||||
const gd::String& type) const {
|
||||
if (behaviorsInfo.find(type) != behaviorsInfo.end() &&
|
||||
behaviorsInfo.find(type)->second.GetSharedDataInstance())
|
||||
return behaviorsInfo.find(type)->second.GetSharedDataInstance();
|
||||
|
@@ -400,7 +400,7 @@ class GD_CORE_API PlatformExtension {
|
||||
* \brief Return a function to create the object if the type is handled by the
|
||||
* extension
|
||||
*/
|
||||
CreateFunPtr GetObjectCreationFunctionPtr(gd::String objectType) const;
|
||||
CreateFunPtr GetObjectCreationFunctionPtr(const gd::String& objectType) const;
|
||||
|
||||
/**
|
||||
* \brief Return a vector containing all the effect types provided by the
|
||||
@@ -413,13 +413,13 @@ class GD_CORE_API PlatformExtension {
|
||||
*
|
||||
* Return an empty pointer if \a eventType is not provided by the extension.
|
||||
*/
|
||||
std::shared_ptr<gd::BaseEvent> CreateEvent(gd::String eventType) const;
|
||||
std::shared_ptr<gd::BaseEvent> CreateEvent(const gd::String& eventType) const;
|
||||
/**
|
||||
* \brief Get the gd::Behavior handling the given behavior type.
|
||||
*
|
||||
* Return nullptr if \a behaviorType is not provided by the extension.
|
||||
*/
|
||||
gd::Behavior* GetBehavior(gd::String behaviorType) const;
|
||||
gd::Behavior* GetBehavior(const gd::String& behaviorType) const;
|
||||
|
||||
/**
|
||||
* \brief Get the gd::BehaviorsSharedData handling the given behavior shared
|
||||
@@ -428,7 +428,7 @@ class GD_CORE_API PlatformExtension {
|
||||
* Return nullptr if \a behaviorType is not provided by the extension.
|
||||
*/
|
||||
gd::BehaviorsSharedData* GetBehaviorSharedDatas(
|
||||
gd::String behaviorType) const;
|
||||
const gd::String& behaviorType) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the ObjectMetadata object associated to \a
|
||||
|
@@ -15,25 +15,18 @@
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/SourceFile.h"
|
||||
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(gd::Project& project_,
|
||||
gd::Layout& layout_)
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(const gd::Project& project_,
|
||||
const gd::Layout& layout_)
|
||||
: project(project_), layout(&layout_), externalEvents(NULL) {
|
||||
parentScenes.push_back(layout->GetName());
|
||||
}
|
||||
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(gd::Project& project_,
|
||||
gd::ExternalEvents& externalEvents_)
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(const gd::Project& project_,
|
||||
const gd::ExternalEvents& externalEvents_)
|
||||
: project(project_), layout(NULL), externalEvents(&externalEvents_) {
|
||||
parentExternalEvents.push_back(externalEvents->GetName());
|
||||
}
|
||||
|
||||
DependenciesAnalyzer::DependenciesAnalyzer(const DependenciesAnalyzer& parent)
|
||||
: parentScenes(parent.parentScenes),
|
||||
parentExternalEvents(parent.parentExternalEvents),
|
||||
project(parent.project),
|
||||
layout(NULL),
|
||||
externalEvents(NULL) {}
|
||||
|
||||
bool DependenciesAnalyzer::Analyze() {
|
||||
if (layout)
|
||||
return Analyze(layout->GetEvents(), true);
|
||||
@@ -47,9 +40,9 @@ bool DependenciesAnalyzer::Analyze() {
|
||||
|
||||
DependenciesAnalyzer::~DependenciesAnalyzer() {}
|
||||
|
||||
bool DependenciesAnalyzer::Analyze(gd::EventsList& events, bool isOnTopLevel) {
|
||||
bool DependenciesAnalyzer::Analyze(const gd::EventsList& events, bool isOnTopLevel) {
|
||||
for (unsigned int i = 0; i < events.size(); ++i) {
|
||||
gd::LinkEvent* linkEvent = dynamic_cast<gd::LinkEvent*>(&events[i]);
|
||||
const gd::LinkEvent* linkEvent = dynamic_cast<const gd::LinkEvent*>(&events[i]);
|
||||
if (linkEvent) {
|
||||
DependenciesAnalyzer analyzer(*this);
|
||||
|
||||
@@ -113,7 +106,7 @@ bool DependenciesAnalyzer::Analyze(gd::EventsList& events, bool isOnTopLevel) {
|
||||
sourceFilesDependencies.insert(dependencies.begin(), dependencies.end());
|
||||
|
||||
const gd::String& associatedSourceFile =
|
||||
events[i].GetAssociatedGDManagedSourceFile(project);
|
||||
events[i].GetAssociatedGDManagedSourceFile(const_cast<gd::Project&>(project));
|
||||
if (!associatedSourceFile.empty())
|
||||
sourceFilesDependencies.insert(associatedSourceFile);
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
/**
|
||||
* \brief Constructor for analyzing the dependencies of a layout
|
||||
*/
|
||||
DependenciesAnalyzer(gd::Project& project_, gd::Layout& layout_);
|
||||
DependenciesAnalyzer(const gd::Project& project_, const gd::Layout& layout_);
|
||||
|
||||
/**
|
||||
* \brief Constructor for analyzing the dependencies of external events.
|
||||
@@ -45,8 +45,8 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
* external events can be compiled separatly and called by a scene. \see
|
||||
* DependenciesAnalyzer::ExternalEventsCanBeCompiledForAScene
|
||||
*/
|
||||
DependenciesAnalyzer(gd::Project& project_,
|
||||
gd::ExternalEvents& externalEvents);
|
||||
DependenciesAnalyzer(const gd::Project& project_,
|
||||
const gd::ExternalEvents& externalEvents);
|
||||
|
||||
virtual ~DependenciesAnalyzer();
|
||||
|
||||
@@ -124,13 +124,7 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
* (they have no parents). \return false if a circular dependency exists, true
|
||||
* otherwise.
|
||||
*/
|
||||
bool Analyze(gd::EventsList& events, bool isOnTopLevel);
|
||||
|
||||
/**
|
||||
* \brief Internal constructor used when analyzing a linked layout/external
|
||||
* events.
|
||||
*/
|
||||
DependenciesAnalyzer(const DependenciesAnalyzer& parent);
|
||||
bool Analyze(const gd::EventsList& events, bool isOnTopLevel);
|
||||
|
||||
void AddParentScene(gd::String parentScene) {
|
||||
parentScenes.push_back(parentScene);
|
||||
@@ -161,9 +155,9 @@ class GD_CORE_API DependenciesAnalyzer {
|
||||
std::vector<gd::String>
|
||||
parentExternalEvents; ///< Used to check for circular dependencies.
|
||||
|
||||
gd::Project& project;
|
||||
gd::Layout* layout;
|
||||
gd::ExternalEvents* externalEvents;
|
||||
const gd::Project& project;
|
||||
const gd::Layout* layout;
|
||||
const gd::ExternalEvents* externalEvents;
|
||||
};
|
||||
|
||||
#endif // DEPENDENCIESANALYZER_H
|
||||
|
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "EditorSettings.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
EditorSettings::EditorSettings() {}
|
||||
|
||||
void EditorSettings::SerializeTo(SerializerElement& element) const {
|
||||
element = content;
|
||||
}
|
||||
|
||||
void EditorSettings::UnserializeFrom(
|
||||
const SerializerElement& element) {
|
||||
content = element;
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
#endif
|
46
Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h
Normal file
46
Core/GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#ifndef SCENECANVASSETTINGS_H
|
||||
#define SCENECANVASSETTINGS_H
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Container for arbitrary serialized data to be used by the editor
|
||||
* to store settings.
|
||||
*
|
||||
* \see Scene
|
||||
*/
|
||||
class GD_CORE_API EditorSettings {
|
||||
public:
|
||||
EditorSettings();
|
||||
virtual ~EditorSettings(){};
|
||||
|
||||
/** \name Serialization
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Serialize the settings.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the settings.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
private:
|
||||
gd::SerializerElement content; ///< Arbitrary content, depending on the editor.
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // SCENECANVASSETTINGS_H
|
||||
#endif
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "LayoutEditorCanvasOptions.h"
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
LayoutEditorCanvasOptions::LayoutEditorCanvasOptions()
|
||||
: grid(false),
|
||||
snap(true),
|
||||
gridWidth(32),
|
||||
gridHeight(32),
|
||||
gridOffsetX(0),
|
||||
gridOffsetY(0),
|
||||
gridType("rectangular"),
|
||||
gridR(158),
|
||||
gridG(180),
|
||||
gridB(255),
|
||||
zoomFactor(1),
|
||||
windowMask(false) {}
|
||||
|
||||
void LayoutEditorCanvasOptions::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("grid", grid);
|
||||
element.SetAttribute("snap", snap);
|
||||
element.SetAttribute("gridWidth", gridWidth);
|
||||
element.SetAttribute("gridHeight", gridHeight);
|
||||
element.SetAttribute("gridOffsetX", gridOffsetX);
|
||||
element.SetAttribute("gridOffsetY", gridOffsetY);
|
||||
element.SetAttribute("gridType", gridType);
|
||||
element.SetAttribute("gridR", gridR);
|
||||
element.SetAttribute("gridG", gridG);
|
||||
element.SetAttribute("gridB", gridB);
|
||||
element.SetAttribute("zoomFactor", zoomFactor);
|
||||
element.SetAttribute("windowMask", windowMask);
|
||||
}
|
||||
|
||||
void LayoutEditorCanvasOptions::UnserializeFrom(
|
||||
const SerializerElement& element) {
|
||||
grid = element.GetBoolAttribute("grid");
|
||||
snap = element.GetBoolAttribute("snap");
|
||||
windowMask = element.GetBoolAttribute("windowMask");
|
||||
gridWidth = element.GetDoubleAttribute("gridWidth", 32);
|
||||
gridHeight = element.GetDoubleAttribute("gridHeight", 32);
|
||||
gridOffsetX = element.GetDoubleAttribute("gridOffsetX", 0);
|
||||
gridOffsetY = element.GetDoubleAttribute("gridOffsetY", 0);
|
||||
gridType = element.GetStringAttribute("gridType", "rectangular");
|
||||
gridR = element.GetIntAttribute("gridR", 158);
|
||||
gridG = element.GetIntAttribute("gridG", 180);
|
||||
gridB = element.GetIntAttribute("gridB", 255);
|
||||
zoomFactor = element.GetDoubleAttribute("zoomFactor", 1.0);
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
#endif
|
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#ifndef SCENECANVASSETTINGS_H
|
||||
#define SCENECANVASSETTINGS_H
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Tool class used to store settings of a LayoutEditorCanvas.
|
||||
*
|
||||
* \see Scene
|
||||
*/
|
||||
class GD_CORE_API LayoutEditorCanvasOptions {
|
||||
public:
|
||||
LayoutEditorCanvasOptions();
|
||||
virtual ~LayoutEditorCanvasOptions(){};
|
||||
|
||||
/** \name Serialization
|
||||
*/
|
||||
///@{
|
||||
|
||||
/**
|
||||
* \brief Serialize instances container.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the instances container.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
bool grid; ///< True if grid activated in editor
|
||||
bool snap; ///< True if snap to grid activated in editor
|
||||
double gridWidth; ///< Grid width in editor
|
||||
double gridHeight; ///< Grid height in editor
|
||||
double gridOffsetX; ///< Grid X offset
|
||||
double gridOffsetY; ///< Grid Y offset
|
||||
gd::String gridType; ///< Grid type: rectangular or isometric
|
||||
int gridR; ///< Grid red color in editor
|
||||
int gridG; ///< Grid green color in editor
|
||||
int gridB; ///< Grid blue color in editor
|
||||
double zoomFactor; ///< Stores the zoom factor
|
||||
bool windowMask; ///< True if window mask displayed in editor
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // SCENECANVASSETTINGS_H
|
||||
#endif
|
164
Core/GDCore/IDE/Events/EventsBehaviorRenamer.cpp
Normal file
164
Core/GDCore/IDE/Events/EventsBehaviorRenamer.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/EventsBehaviorRenamer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Go through the nodes and rename any reference to an object behavior.
|
||||
*
|
||||
* \see gd::ExpressionParser2
|
||||
*/
|
||||
class GD_CORE_API ExpressionBehaviorRenamer
|
||||
: public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionBehaviorRenamer(const gd::ObjectsContainer& globalObjectsContainer_,
|
||||
const gd::ObjectsContainer& objectsContainer_,
|
||||
const gd::String& objectName_,
|
||||
const gd::String& oldBehaviorName_,
|
||||
const gd::String& newBehaviorName_)
|
||||
: hasDoneRenaming(false),
|
||||
globalObjectsContainer(globalObjectsContainer_),
|
||||
objectsContainer(objectsContainer_),
|
||||
objectName(objectName_),
|
||||
oldBehaviorName(oldBehaviorName_),
|
||||
newBehaviorName(newBehaviorName_){};
|
||||
virtual ~ExpressionBehaviorRenamer(){};
|
||||
|
||||
bool HasDoneRenaming() const { return hasDoneRenaming; }
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
node.leftHandSide->Visit(*this);
|
||||
node.rightHandSide->Visit(*this);
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
node.factor->Visit(*this);
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {}
|
||||
void OnVisitTextNode(TextNode& node) override {}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitVariableBracketAccessorNode(
|
||||
VariableBracketAccessorNode& node) override {
|
||||
node.expression->Visit(*this);
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
|
||||
if (!node.behaviorFunctionName.empty()) {
|
||||
// Behavior function name
|
||||
if (node.objectName == objectName && node.objectFunctionOrBehaviorName == oldBehaviorName) {
|
||||
node.objectFunctionOrBehaviorName = newBehaviorName;
|
||||
hasDoneRenaming = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnVisitFunctionCallNode(FunctionCallNode& node) override {
|
||||
if (!node.behaviorName.empty()) {
|
||||
// Behavior function call
|
||||
if (node.objectName == objectName && node.behaviorName == oldBehaviorName) {
|
||||
node.behaviorName = newBehaviorName;
|
||||
hasDoneRenaming = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& parameter : node.parameters) {
|
||||
parameter->Visit(*this);
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {}
|
||||
|
||||
private:
|
||||
bool hasDoneRenaming;
|
||||
const gd::ObjectsContainer& globalObjectsContainer;
|
||||
const gd::ObjectsContainer& objectsContainer;
|
||||
const gd::String& objectName; // The object name for which the behavior
|
||||
// must be replaced.
|
||||
const gd::String& oldBehaviorName;
|
||||
const gd::String& newBehaviorName;
|
||||
};
|
||||
|
||||
bool EventsBehaviorRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
|
||||
gd::ParameterMetadataTools::IterateOverParametersWithIndex(
|
||||
instruction.GetParameters(),
|
||||
metadata.GetParameters(),
|
||||
[&](const gd::ParameterMetadata& parameterMetadata,
|
||||
const gd::String& parameterValue,
|
||||
size_t parameterIndex,
|
||||
const gd::String& lastObjectName) {
|
||||
const gd::String& type = parameterMetadata.type;
|
||||
|
||||
if (gd::ParameterMetadata::IsBehavior(type)) {
|
||||
if (lastObjectName == objectName) {
|
||||
if (parameterValue == oldBehaviorName) {
|
||||
instruction.SetParameter(parameterIndex,
|
||||
gd::Expression(newBehaviorName));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gd::ExpressionParser2 parser(
|
||||
platform, GetGlobalObjectsContainer(), GetObjectsContainer());
|
||||
auto node =
|
||||
gd::ParameterMetadata::IsExpression("number", type)
|
||||
? parser.ParseExpression("number", parameterValue)
|
||||
: (gd::ParameterMetadata::IsExpression("string", type)
|
||||
? parser.ParseExpression("string", parameterValue)
|
||||
: std::unique_ptr<gd::ExpressionNode>());
|
||||
if (node) {
|
||||
ExpressionBehaviorRenamer renamer(GetGlobalObjectsContainer(),
|
||||
GetObjectsContainer(),
|
||||
objectName,
|
||||
oldBehaviorName,
|
||||
newBehaviorName);
|
||||
node->Visit(renamer);
|
||||
|
||||
if (renamer.HasDoneRenaming()) {
|
||||
instruction.SetParameter(
|
||||
parameterIndex,
|
||||
ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
EventsBehaviorRenamer::~EventsBehaviorRenamer() {}
|
||||
|
||||
} // namespace gd
|
52
Core/GDCore/IDE/Events/EventsBehaviorRenamer.h
Normal file
52
Core/GDCore/IDE/Events/EventsBehaviorRenamer.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef EventsBehaviorRenamer_H
|
||||
#define EventsBehaviorRenamer_H
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
class Platform;
|
||||
class EventsList;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Replace in expressions and in parameters of actions or conditions, references
|
||||
* to the name of a behavior of an object by another name.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class GD_CORE_API EventsBehaviorRenamer : public ArbitraryEventsWorkerWithContext {
|
||||
public:
|
||||
EventsBehaviorRenamer(const gd::Platform &platform_,
|
||||
const gd::String& objectName_,
|
||||
const gd::String& oldBehaviorName_,
|
||||
const gd::String& newBehaviorName_) :
|
||||
platform(platform_),
|
||||
objectName(objectName_),
|
||||
oldBehaviorName(oldBehaviorName_),
|
||||
newBehaviorName(newBehaviorName_)
|
||||
{};
|
||||
virtual ~EventsBehaviorRenamer();
|
||||
|
||||
private:
|
||||
bool DoVisitInstruction(gd::Instruction &instruction,
|
||||
bool isCondition) override;
|
||||
|
||||
const gd::Platform &platform;
|
||||
gd::String objectName;
|
||||
gd::String oldBehaviorName;
|
||||
gd::String newBehaviorName;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // EventsBehaviorRenamer_H
|
@@ -5,17 +5,19 @@
|
||||
*/
|
||||
|
||||
#include "GDCore/IDE/Events/EventsRefactorer.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodePrinter.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/IDE/Events/ExpressionValidator.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -31,10 +33,14 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionObjectRenamer(const gd::String& objectName_,
|
||||
const gd::String& objectNewName_)
|
||||
: hasDoneRenaming(false), objectName(objectName_), objectNewName(objectNewName_){};
|
||||
: hasDoneRenaming(false),
|
||||
objectName(objectName_),
|
||||
objectNewName(objectNewName_){};
|
||||
virtual ~ExpressionObjectRenamer(){};
|
||||
|
||||
static bool Rename(gd::ExpressionNode & node, const gd::String& objectName, const gd::String& objectNewName) {
|
||||
static bool Rename(gd::ExpressionNode& node,
|
||||
const gd::String& objectName,
|
||||
const gd::String& objectNewName) {
|
||||
if (ExpressionValidator::HasNoErrors(node)) {
|
||||
ExpressionObjectRenamer renamer(objectName, objectNewName);
|
||||
node.Visit(renamer);
|
||||
@@ -72,7 +78,8 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
if (gd::ParameterMetadata::IsObject(node.type) && node.identifierName == objectName) {
|
||||
if (gd::ParameterMetadata::IsObject(node.type) &&
|
||||
node.identifierName == objectName) {
|
||||
hasDoneRenaming = true;
|
||||
node.identifierName = objectNewName;
|
||||
}
|
||||
@@ -109,10 +116,11 @@ class GD_CORE_API ExpressionObjectRenamer : public ExpressionParser2NodeWorker {
|
||||
class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
public:
|
||||
ExpressionObjectFinder(const gd::String& objectName_)
|
||||
: hasObject(false), objectName(objectName_) {};
|
||||
: hasObject(false), objectName(objectName_){};
|
||||
virtual ~ExpressionObjectFinder(){};
|
||||
|
||||
static bool CheckIfHasObject(gd::ExpressionNode & node, const gd::String & objectName) {
|
||||
static bool CheckIfHasObject(gd::ExpressionNode& node,
|
||||
const gd::String& objectName) {
|
||||
if (ExpressionValidator::HasNoErrors(node)) {
|
||||
ExpressionObjectFinder finder(objectName);
|
||||
node.Visit(finder);
|
||||
@@ -150,7 +158,8 @@ class GD_CORE_API ExpressionObjectFinder : public ExpressionParser2NodeWorker {
|
||||
if (node.child) node.child->Visit(*this);
|
||||
}
|
||||
void OnVisitIdentifierNode(IdentifierNode& node) override {
|
||||
if (gd::ParameterMetadata::IsObject(node.type) && node.identifierName == objectName) {
|
||||
if (gd::ParameterMetadata::IsObject(node.type) &&
|
||||
node.identifierName == objectName) {
|
||||
hasObject = true;
|
||||
}
|
||||
}
|
||||
@@ -183,7 +192,7 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
bool somethingModified = false;
|
||||
|
||||
for (std::size_t aId = 0; aId < actions.size(); ++aId) {
|
||||
gd::InstructionMetadata instrInfos =
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
@@ -194,20 +203,24 @@ bool EventsRefactorer::RenameObjectInActions(const gd::Platform& platform,
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"number", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
actions[aId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
actions[aId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"string", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
actions[aId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
actions[aId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,8 +249,9 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
bool somethingModified = false;
|
||||
|
||||
for (std::size_t cId = 0; cId < conditions.size(); ++cId) {
|
||||
gd::InstructionMetadata instrInfos = MetadataProvider::GetConditionMetadata(
|
||||
platform, conditions[cId].GetType());
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetConditionMetadata(platform,
|
||||
conditions[cId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Replace object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
@@ -247,20 +261,24 @@ bool EventsRefactorer::RenameObjectInConditions(
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"number", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
conditions[cId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
conditions[cId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"string", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectRenamer::Rename(*node, oldName, newName)) {
|
||||
conditions[cId].SetParameter(pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
conditions[cId].SetParameter(
|
||||
pNb, ExpressionParser2NodePrinter::PrintNode(*node));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -293,8 +311,8 @@ bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
expression.GetPlainString() == oldName)
|
||||
expression = gd::Expression(newName);
|
||||
// Replace object's name in expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", parameterMetadata.GetType())) {
|
||||
else if (ParameterMetadata::IsExpression("number",
|
||||
parameterMetadata.GetType())) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", expression.GetPlainString());
|
||||
|
||||
@@ -303,8 +321,8 @@ bool EventsRefactorer::RenameObjectInEventParameters(
|
||||
}
|
||||
}
|
||||
// Replace object's name in text expressions
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", parameterMetadata.GetType())) {
|
||||
else if (ParameterMetadata::IsExpression("string",
|
||||
parameterMetadata.GetType())) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", expression.GetPlainString());
|
||||
|
||||
@@ -337,13 +355,19 @@ void EventsRefactorer::RenameObjectInEvents(const gd::Platform& platform,
|
||||
platform, project, layout, *actionsVectors[j], oldName, newName);
|
||||
}
|
||||
|
||||
vector<pair<gd::Expression*, gd::ParameterMetadata>> expressionsWithMetadata =
|
||||
events[i].GetAllExpressionsWithMetadata();
|
||||
vector<pair<gd::Expression*, gd::ParameterMetadata>>
|
||||
expressionsWithMetadata = events[i].GetAllExpressionsWithMetadata();
|
||||
for (std::size_t j = 0; j < expressionsWithMetadata.size(); ++j) {
|
||||
gd::Expression* expression = expressionsWithMetadata[j].first;
|
||||
gd::ParameterMetadata parameterMetadata = expressionsWithMetadata[j].second;
|
||||
bool somethingModified = RenameObjectInEventParameters(
|
||||
platform, project, layout, *expression, parameterMetadata, oldName, newName);
|
||||
gd::ParameterMetadata parameterMetadata =
|
||||
expressionsWithMetadata[j].second;
|
||||
bool somethingModified = RenameObjectInEventParameters(platform,
|
||||
project,
|
||||
layout,
|
||||
*expression,
|
||||
parameterMetadata,
|
||||
oldName,
|
||||
newName);
|
||||
}
|
||||
|
||||
if (events[i].CanHaveSubEvents())
|
||||
@@ -366,7 +390,7 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
for (std::size_t aId = 0; aId < actions.size(); ++aId) {
|
||||
bool deleteMe = false;
|
||||
|
||||
gd::InstructionMetadata instrInfos =
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetActionMetadata(platform, actions[aId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Find object's name in parameters
|
||||
@@ -379,7 +403,8 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"number", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
@@ -390,7 +415,8 @@ bool EventsRefactorer::RemoveObjectInActions(const gd::Platform& platform,
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"string", actions[aId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
@@ -427,8 +453,9 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
for (std::size_t cId = 0; cId < conditions.size(); ++cId) {
|
||||
bool deleteMe = false;
|
||||
|
||||
gd::InstructionMetadata instrInfos = MetadataProvider::GetConditionMetadata(
|
||||
platform, conditions[cId].GetType());
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
MetadataProvider::GetConditionMetadata(platform,
|
||||
conditions[cId].GetType());
|
||||
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
|
||||
// Find object's name in parameters
|
||||
if (gd::ParameterMetadata::IsObject(instrInfos.parameters[pNb].type) &&
|
||||
@@ -440,7 +467,8 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"number", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("number", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"number", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
@@ -451,7 +479,8 @@ bool EventsRefactorer::RemoveObjectInConditions(
|
||||
else if (ParameterMetadata::IsExpression(
|
||||
"string", instrInfos.parameters[pNb].type)) {
|
||||
gd::ExpressionParser2 parser(platform, project, layout);
|
||||
auto node = parser.ParseExpression("string", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
auto node = parser.ParseExpression(
|
||||
"string", conditions[cId].GetParameter(pNb).GetPlainString());
|
||||
|
||||
if (ExpressionObjectFinder::CheckIfHasObject(*node, name)) {
|
||||
deleteMe = true;
|
||||
@@ -781,10 +810,10 @@ bool EventsRefactorer::SearchStringInConditions(
|
||||
}
|
||||
|
||||
bool EventsRefactorer::SearchStringInEvent(gd::ObjectsContainer& project,
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::BaseEvent& event,
|
||||
gd::String search,
|
||||
bool matchCase) {
|
||||
gd::ObjectsContainer& layout,
|
||||
gd::BaseEvent& event,
|
||||
gd::String search,
|
||||
bool matchCase) {
|
||||
for (gd::String str : event.GetAllSearchableStrings()) {
|
||||
if (matchCase) {
|
||||
if (str.find(search) != gd::String::npos) return true;
|
||||
|
@@ -17,6 +17,8 @@
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -95,11 +97,11 @@ std::set<gd::String> EventsVariablesFinder::FindAllGlobalVariables(
|
||||
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
std::set<gd::String> results2 =
|
||||
FindArgumentsInEvents(platform,
|
||||
project,
|
||||
project.GetLayout(i),
|
||||
project.GetLayout(i).GetEvents(),
|
||||
"globalvar");
|
||||
FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
project,
|
||||
project.GetLayout(i),
|
||||
"globalvar");
|
||||
results.insert(results2.begin(), results2.end());
|
||||
}
|
||||
|
||||
@@ -112,8 +114,8 @@ std::set<gd::String> EventsVariablesFinder::FindAllLayoutVariables(
|
||||
const gd::Layout& layout) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEvents(
|
||||
platform, project, layout, layout.GetEvents(), "scenevar");
|
||||
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
|
||||
platform, project, layout, "scenevar");
|
||||
results.insert(results2.begin(), results2.end());
|
||||
|
||||
return results;
|
||||
@@ -126,12 +128,12 @@ std::set<gd::String> EventsVariablesFinder::FindAllObjectVariables(
|
||||
const gd::Object& object) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEvents(platform,
|
||||
project,
|
||||
layout,
|
||||
layout.GetEvents(),
|
||||
"objectvar",
|
||||
object.GetName());
|
||||
std::set<gd::String> results2 = FindArgumentsInEventsAndDependencies(
|
||||
platform,
|
||||
project,
|
||||
layout,
|
||||
"objectvar",
|
||||
object.GetName());
|
||||
results.insert(results2.begin(), results2.end());
|
||||
|
||||
return results;
|
||||
@@ -149,7 +151,7 @@ std::set<gd::String> EventsVariablesFinder::FindArgumentsInInstructions(
|
||||
|
||||
for (std::size_t aId = 0; aId < instructions.size(); ++aId) {
|
||||
gd::String lastObjectParameter = "";
|
||||
gd::InstructionMetadata instrInfos =
|
||||
const gd::InstructionMetadata& instrInfos =
|
||||
instructionsAreConditions ? MetadataProvider::GetConditionMetadata(
|
||||
platform, instructions[aId].GetType())
|
||||
: MetadataProvider::GetActionMetadata(
|
||||
@@ -203,6 +205,38 @@ std::set<gd::String> EventsVariablesFinder::FindArgumentsInInstructions(
|
||||
return results;
|
||||
}
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEventsAndDependencies(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName) {
|
||||
std::set<gd::String> results;
|
||||
|
||||
std::set<gd::String> results2 = FindArgumentsInEvents(
|
||||
platform, project, layout, layout.GetEvents(), parameterType, objectName);
|
||||
results.insert(results2.begin(), results2.end());
|
||||
|
||||
DependenciesAnalyzer dependenciesAnalyzer = DependenciesAnalyzer(project, layout);
|
||||
dependenciesAnalyzer.Analyze();
|
||||
for (const gd::String& externalEventName : dependenciesAnalyzer.GetExternalEventsDependencies()) {
|
||||
const gd::ExternalEvents& externalEvents = project.GetExternalEvents(externalEventName);
|
||||
|
||||
std::set<gd::String> results3 = FindArgumentsInEvents(
|
||||
platform, project, layout, externalEvents.GetEvents(), parameterType, objectName);
|
||||
results.insert(results3.begin(), results3.end());
|
||||
}
|
||||
for (const gd::String& sceneName : dependenciesAnalyzer.GetScenesDependencies()) {
|
||||
const gd::Layout& dependencyLayout = project.GetLayout(sceneName);
|
||||
|
||||
std::set<gd::String> results3 = FindArgumentsInEvents(
|
||||
platform, project, dependencyLayout, dependencyLayout.GetEvents(), parameterType, objectName);
|
||||
results.insert(results3.begin(), results3.end());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
std::set<gd::String> EventsVariablesFinder::FindArgumentsInEvents(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
|
@@ -24,11 +24,17 @@ namespace gd {
|
||||
* global or object variables.
|
||||
*
|
||||
* \todo Refactor this class using ArbitraryEventsWorker
|
||||
* \todo Rework this class to return the shapes (maybe even types?) of the
|
||||
* variables (in particular for structures and arrays), so we can use this
|
||||
* for better autocompletions in the variables dialogs in the IDE.
|
||||
*
|
||||
* \ingroup IDE
|
||||
*/
|
||||
class EventsVariablesFinder {
|
||||
public:
|
||||
EventsVariablesFinder(){};
|
||||
virtual ~EventsVariablesFinder(){};
|
||||
|
||||
/**
|
||||
* Construct a list containing the name of all global variables used in the
|
||||
* project.
|
||||
@@ -94,10 +100,34 @@ class EventsVariablesFinder {
|
||||
|
||||
/**
|
||||
* Construct a list of the value of the arguments for parameters of type @
|
||||
* parameterType
|
||||
* parameterType. It searchs in events dependencies.
|
||||
*
|
||||
* \param platform The platform of the project
|
||||
* \param project The project used
|
||||
* \param project The layout used
|
||||
* \param layout The layout used
|
||||
* \param events The events to be analyzed
|
||||
* \param parameterType The parameters type to be analyzed
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
* only if the last object parameter is filled with
|
||||
* this value.
|
||||
*
|
||||
* \return A std::set filled with the values used for all parameters of the
|
||||
* specified type
|
||||
*/
|
||||
static std::set<gd::String> FindArgumentsInEventsAndDependencies(
|
||||
const gd::Platform& platform,
|
||||
const gd::Project& project,
|
||||
const gd::Layout& layout,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
/**
|
||||
* Construct a list of the value of the arguments for parameters of type @
|
||||
* parameterType. It doesn't search in events dependencies.
|
||||
*
|
||||
* \param platform The platform of the project
|
||||
* \param project The project used
|
||||
* \param layout The layout used
|
||||
* \param events The events to be analyzed
|
||||
* \param parameterType The parameters type to be analyzed
|
||||
* \param objectName If not empty, parameters will be taken into account
|
||||
@@ -113,10 +143,7 @@ class EventsVariablesFinder {
|
||||
const gd::Layout& layout,
|
||||
const gd::EventsList& events,
|
||||
const gd::String& parameterType,
|
||||
const gd::String& objectName = "");
|
||||
|
||||
EventsVariablesFinder(){};
|
||||
virtual ~EventsVariablesFinder(){};
|
||||
const gd::String& objectName);
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
31
Core/GDCore/IDE/Events/ExpressionCompletionFinder.cpp
Normal file
31
Core/GDCore/IDE/Events/ExpressionCompletionFinder.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "ExpressionCompletionFinder.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
const gd::ParameterMetadata
|
||||
ExpressionCompletionDescription::badParameterMetadata;
|
||||
|
||||
/**
|
||||
* \brief Turn an ExpressionCompletionDescription to a string.
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
ExpressionCompletionDescription const& value) {
|
||||
os << "{ " << value.GetCompletionKind() << ", " << value.GetType() << ", "
|
||||
<< value.GetPrefix() << ", " << value.GetObjectName() << ", "
|
||||
<< value.GetBehaviorName() << ", "
|
||||
<< (value.IsExact() ? "exact" : "non-exact") << ", "
|
||||
<< (value.IsLastParameter() ? "last parameter" : "not last parameter")
|
||||
<< ", "
|
||||
<< (value.HasParameterMetadata()
|
||||
? gd::String::From(&value.GetParameterMetadata())
|
||||
: "no parameter metadata")
|
||||
<< " }";
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -8,10 +8,14 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
|
||||
#include "GDCore/IDE/Events/ExpressionNodeLocationFinder.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
|
||||
namespace gd {
|
||||
class Expression;
|
||||
class ObjectsContainer;
|
||||
@@ -33,19 +37,21 @@ struct ExpressionCompletionDescription {
|
||||
/**
|
||||
* The different kind of completions that can be described.
|
||||
*/
|
||||
enum CompletionKind {
|
||||
Object,
|
||||
Behavior,
|
||||
Expression,
|
||||
Variable,
|
||||
};
|
||||
enum CompletionKind { Object, Behavior, Expression, Variable, Text };
|
||||
|
||||
/**
|
||||
* \brief Create a completion for an object with the given prefix
|
||||
*/
|
||||
static ExpressionCompletionDescription ForObject(const gd::String& type_,
|
||||
const gd::String& prefix_) {
|
||||
return ExpressionCompletionDescription(Object, type_, prefix_);
|
||||
static ExpressionCompletionDescription ForObject(
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_) {
|
||||
return ExpressionCompletionDescription(Object,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,17 +59,58 @@ struct ExpressionCompletionDescription {
|
||||
* the specified object
|
||||
*/
|
||||
static ExpressionCompletionDescription ForBehavior(
|
||||
const gd::String& prefix_, const gd::String& objectName_) {
|
||||
return ExpressionCompletionDescription(Behavior, "", prefix_, objectName_);
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_) {
|
||||
return ExpressionCompletionDescription(Behavior,
|
||||
"",
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create a completion for a variable with the given prefix
|
||||
*/
|
||||
static ExpressionCompletionDescription ForVariable(
|
||||
const gd::String& type_, const gd::String& prefix_) {
|
||||
return ExpressionCompletionDescription(Variable, type_, prefix_);
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_ = "") {
|
||||
return ExpressionCompletionDescription(Variable,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create a completion for a text with the given prefix
|
||||
*/
|
||||
static ExpressionCompletionDescription ForText(
|
||||
const gd::String& type_,
|
||||
const gd::ParameterMetadata& parameterMetadata_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const bool isLastParameter_,
|
||||
const gd::String& objectName_ = "") {
|
||||
auto description =
|
||||
ExpressionCompletionDescription(Text,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_);
|
||||
description.SetIsLastParameter(isLastParameter_);
|
||||
description.SetParameterMetadata(parameterMetadata_);
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Create a completion for an expression (free, object or behavior
|
||||
* expression) with the given prefix
|
||||
@@ -71,10 +118,17 @@ struct ExpressionCompletionDescription {
|
||||
static ExpressionCompletionDescription ForExpression(
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_ = "",
|
||||
const gd::String& behaviorName_ = "") {
|
||||
return ExpressionCompletionDescription(
|
||||
Expression, type_, prefix_, objectName_, behaviorName_);
|
||||
return ExpressionCompletionDescription(Expression,
|
||||
type_,
|
||||
prefix_,
|
||||
replacementStartPosition_,
|
||||
replacementEndPosition_,
|
||||
objectName_,
|
||||
behaviorName_);
|
||||
}
|
||||
|
||||
/** Check if two description of completions are equal */
|
||||
@@ -131,6 +185,56 @@ struct ExpressionCompletionDescription {
|
||||
*/
|
||||
bool IsExact() const { return isExact; }
|
||||
|
||||
/**
|
||||
* \brief Return the first character index of the autocompleted part.
|
||||
*/
|
||||
size_t GetReplacementStartPosition() const {
|
||||
return replacementStartPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the first character index after the autocompleted part.
|
||||
*/
|
||||
size_t GetReplacementEndPosition() const { return replacementEndPosition; }
|
||||
|
||||
/**
|
||||
* \brief Set if the expression is the last child of a function call.
|
||||
*/
|
||||
ExpressionCompletionDescription& SetIsLastParameter(bool isLastParameter_) {
|
||||
isLastParameter = isLastParameter_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the expression is the last child of a function call.
|
||||
*/
|
||||
bool IsLastParameter() const { return isLastParameter; }
|
||||
|
||||
/**
|
||||
* \brief Set the parameter metadata, in the case the completion is about
|
||||
* a parameter of a function call.
|
||||
*/
|
||||
ExpressionCompletionDescription& SetParameterMetadata(
|
||||
const gd::ParameterMetadata& parameterMetadata_) {
|
||||
parameterMetadata = ¶meterMetadata_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the completion is about a parameter of a function call.
|
||||
*/
|
||||
bool HasParameterMetadata() const {
|
||||
return parameterMetadata != &badParameterMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the parameter metadata, if the completion is about a
|
||||
* parameter of a function call. Returns an empty metadata otherwise.
|
||||
*/
|
||||
const gd::ParameterMetadata& GetParameterMetadata() const {
|
||||
return *parameterMetadata;
|
||||
}
|
||||
|
||||
/** Default constructor, only to be used by Emscripten bindings. */
|
||||
ExpressionCompletionDescription() : completionKind(Object){};
|
||||
|
||||
@@ -138,34 +242,40 @@ struct ExpressionCompletionDescription {
|
||||
ExpressionCompletionDescription(CompletionKind completionKind_,
|
||||
const gd::String& type_,
|
||||
const gd::String& prefix_,
|
||||
size_t replacementStartPosition_,
|
||||
size_t replacementEndPosition_,
|
||||
const gd::String& objectName_ = "",
|
||||
const gd::String& behaviorName_ = "")
|
||||
: completionKind(completionKind_),
|
||||
type(type_),
|
||||
prefix(prefix_),
|
||||
replacementStartPosition(replacementStartPosition_),
|
||||
replacementEndPosition(replacementEndPosition_),
|
||||
objectName(objectName_),
|
||||
behaviorName(behaviorName_),
|
||||
isExact(false) {}
|
||||
isExact(false),
|
||||
isLastParameter(false),
|
||||
parameterMetadata(&badParameterMetadata) {}
|
||||
|
||||
CompletionKind completionKind;
|
||||
gd::String type;
|
||||
gd::String prefix;
|
||||
size_t replacementStartPosition;
|
||||
size_t replacementEndPosition;
|
||||
gd::String objectName;
|
||||
gd::String behaviorName;
|
||||
bool isExact;
|
||||
bool isLastParameter;
|
||||
const gd::ParameterMetadata* parameterMetadata;
|
||||
|
||||
static const gd::ParameterMetadata badParameterMetadata;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Turn an ExpressionCompletionDescription to a string.
|
||||
*/
|
||||
std::ostream& operator<<(std::ostream& os,
|
||||
ExpressionCompletionDescription const& value) {
|
||||
os << "{ " << value.GetCompletionKind() << ", " << value.GetType() << ", "
|
||||
<< value.GetPrefix() << ", " << value.GetObjectName() << ", "
|
||||
<< value.GetBehaviorName() << ", "
|
||||
<< (value.IsExact() ? "exact" : "non-exact") << " }";
|
||||
return os;
|
||||
}
|
||||
ExpressionCompletionDescription const& value);
|
||||
|
||||
/**
|
||||
* \brief Returns the list of completion descriptions for an expression node.
|
||||
@@ -182,16 +292,18 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
static std::vector<ExpressionCompletionDescription>
|
||||
GetCompletionDescriptionsFor(gd::ExpressionNode& node,
|
||||
size_t searchedPosition) {
|
||||
gd::ExpressionNode* nodeAtLocation =
|
||||
gd::ExpressionNodeLocationFinder::GetNodeAtPosition(node,
|
||||
searchedPosition);
|
||||
gd::ExpressionNodeLocationFinder finder(searchedPosition);
|
||||
node.Visit(finder);
|
||||
gd::ExpressionNode* nodeAtLocation = finder.GetNode();
|
||||
|
||||
if (nodeAtLocation == nullptr) {
|
||||
std::vector<ExpressionCompletionDescription> emptyCompletions;
|
||||
return emptyCompletions;
|
||||
}
|
||||
|
||||
gd::ExpressionCompletionFinder autocompletionProvider(searchedPosition);
|
||||
gd::ExpressionNode* maybeParentNodeAtLocation = finder.GetParentNode();
|
||||
gd::ExpressionCompletionFinder autocompletionProvider(
|
||||
searchedPosition, maybeParentNodeAtLocation);
|
||||
nodeAtLocation->Visit(autocompletionProvider);
|
||||
return autocompletionProvider.GetCompletionDescriptions();
|
||||
}
|
||||
@@ -208,32 +320,92 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, ""));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, ""));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
}
|
||||
void OnVisitOperatorNode(OperatorNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, ""));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, ""));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
}
|
||||
void OnVisitUnaryOperatorNode(UnaryOperatorNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, ""));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, ""));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, "", searchedPosition + 1, searchedPosition + 1));
|
||||
}
|
||||
void OnVisitNumberNode(NumberNode& node) override {
|
||||
// No completions
|
||||
}
|
||||
|
||||
void OnVisitTextNode(TextNode& node) override {
|
||||
// No completions
|
||||
// Completions are searched in the case the text node is a parameter of a
|
||||
// function call.
|
||||
FunctionCallNode* functionCall =
|
||||
dynamic_cast<FunctionCallNode*>(maybeParentNodeAtLocation);
|
||||
if (functionCall != nullptr) {
|
||||
int parameterIndex = -1;
|
||||
for (int i = 0; i < functionCall->parameters.size(); i++) {
|
||||
if (functionCall->parameters.at(i).get() == &node) {
|
||||
parameterIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (parameterIndex < 0) {
|
||||
return;
|
||||
}
|
||||
// Search the parameter metadata index skipping invisible ones.
|
||||
size_t visibleParameterIndex = 0;
|
||||
size_t metadataParameterIndex = ExpressionParser2::WrittenParametersFirstIndex(
|
||||
functionCall->objectName, functionCall->behaviorName);
|
||||
|
||||
const gd::ParameterMetadata* parameterMetadata = nullptr;
|
||||
while (metadataParameterIndex <
|
||||
functionCall->expressionMetadata.parameters.size()) {
|
||||
if (!functionCall->expressionMetadata.parameters[metadataParameterIndex]
|
||||
.IsCodeOnly()) {
|
||||
if (visibleParameterIndex == parameterIndex) {
|
||||
parameterMetadata = &functionCall->expressionMetadata
|
||||
.parameters[metadataParameterIndex];
|
||||
}
|
||||
visibleParameterIndex++;
|
||||
}
|
||||
metadataParameterIndex++;
|
||||
}
|
||||
const int visibleParameterCount = visibleParameterIndex;
|
||||
if (parameterMetadata == nullptr) {
|
||||
// There are too many parameters in the expression, this text node is
|
||||
// not actually linked to a parameter expected by the function call.
|
||||
return;
|
||||
}
|
||||
|
||||
const gd::String& type = parameterMetadata->GetType();
|
||||
if (type == "string") {
|
||||
// No completions for an arbitrary string.
|
||||
return;
|
||||
}
|
||||
|
||||
bool isLastParameter = parameterIndex == visibleParameterCount - 1;
|
||||
completions.push_back(ExpressionCompletionDescription::ForText(
|
||||
type,
|
||||
*parameterMetadata,
|
||||
node.text,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition(),
|
||||
isLastParameter,
|
||||
functionCall->objectName));
|
||||
}
|
||||
}
|
||||
void OnVisitVariableNode(VariableNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForVariable(node.type, node.name));
|
||||
completions.push_back(ExpressionCompletionDescription::ForVariable(
|
||||
node.type,
|
||||
node.name,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition(),
|
||||
node.objectName));
|
||||
}
|
||||
void OnVisitVariableAccessorNode(VariableAccessorNode& node) override {
|
||||
// No completions
|
||||
@@ -246,13 +418,22 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
if (gd::ParameterMetadata::IsObject(node.type)) {
|
||||
// Only show completions of objects if an object is required
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.identifierName));
|
||||
node.type,
|
||||
node.identifierName,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
} else {
|
||||
// Show completions for expressions and objects otherwise.
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.identifierName));
|
||||
node.type,
|
||||
node.identifierName,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.identifierName));
|
||||
node.type,
|
||||
node.identifierName,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
}
|
||||
}
|
||||
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
|
||||
@@ -262,16 +443,24 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// function name missing)
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else if (IsCaretOn(node.objectNameDotLocation) ||
|
||||
IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.objectFunctionOrBehaviorName, node.objectName));
|
||||
node.objectFunctionOrBehaviorName,
|
||||
node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
|
||||
node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
} else if (IsCaretOn(node.behaviorNameNamespaceSeparatorLocation) ||
|
||||
IsCaretOn(node.behaviorFunctionNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type,
|
||||
node.behaviorFunctionName,
|
||||
node.behaviorFunctionNameLocation.GetStartPosition(),
|
||||
node.behaviorFunctionNameLocation.GetEndPosition(),
|
||||
node.objectName,
|
||||
node.objectFunctionOrBehaviorName));
|
||||
}
|
||||
@@ -279,13 +468,23 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// Object function or behavior name
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else if (IsCaretOn(node.objectNameDotLocation) ||
|
||||
IsCaretOn(node.objectFunctionOrBehaviorNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.objectFunctionOrBehaviorName, node.objectName));
|
||||
node.objectFunctionOrBehaviorName,
|
||||
node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
|
||||
node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.objectFunctionOrBehaviorName, node.objectName));
|
||||
node.type,
|
||||
node.objectFunctionOrBehaviorName,
|
||||
node.objectFunctionOrBehaviorNameLocation.GetStartPosition(),
|
||||
node.objectFunctionOrBehaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -297,24 +496,35 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// Behavior function
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else if (IsCaretOn(node.objectNameDotLocation) ||
|
||||
IsCaretOn(node.behaviorNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.behaviorName, node.objectName));
|
||||
node.behaviorName,
|
||||
node.behaviorNameLocation.GetStartPosition(),
|
||||
node.behaviorNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
} else {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type,
|
||||
node.functionName,
|
||||
node.objectName,
|
||||
node.behaviorName)
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type,
|
||||
node.functionName,
|
||||
node.functionNameLocation.GetStartPosition(),
|
||||
node.functionNameLocation.GetEndPosition(),
|
||||
node.objectName,
|
||||
node.behaviorName)
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
}
|
||||
} else if (!node.objectName.empty()) {
|
||||
// Object function
|
||||
if (IsCaretOn(node.objectNameLocation)) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type, node.objectName));
|
||||
node.type,
|
||||
node.objectName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition()));
|
||||
} else {
|
||||
// Add completions for behaviors, because we could imagine that the user
|
||||
// wants to move from an object function to a behavior function, and so
|
||||
@@ -323,25 +533,41 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
// function).
|
||||
if (!isCaretOnParenthesis) {
|
||||
completions.push_back(ExpressionCompletionDescription::ForBehavior(
|
||||
node.functionName, node.objectName));
|
||||
node.functionName,
|
||||
node.objectNameLocation.GetStartPosition(),
|
||||
node.objectNameLocation.GetEndPosition(),
|
||||
node.objectName));
|
||||
}
|
||||
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.functionName, node.objectName)
|
||||
node.type,
|
||||
node.functionName,
|
||||
node.functionNameLocation.GetStartPosition(),
|
||||
node.functionNameLocation.GetEndPosition(),
|
||||
node.objectName)
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
}
|
||||
} else {
|
||||
// Free function
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type, node.functionName)
|
||||
node.type,
|
||||
node.functionName,
|
||||
node.functionNameLocation.GetStartPosition(),
|
||||
node.functionNameLocation.GetEndPosition())
|
||||
.SetIsExact(isCaretOnParenthesis));
|
||||
}
|
||||
}
|
||||
void OnVisitEmptyNode(EmptyNode& node) override {
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForObject(node.type, node.text));
|
||||
completions.push_back(
|
||||
ExpressionCompletionDescription::ForExpression(node.type, node.text));
|
||||
completions.push_back(ExpressionCompletionDescription::ForObject(
|
||||
node.type,
|
||||
node.text,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
completions.push_back(ExpressionCompletionDescription::ForExpression(
|
||||
node.type,
|
||||
node.text,
|
||||
node.location.GetStartPosition(),
|
||||
node.location.GetEndPosition()));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -354,11 +580,14 @@ class GD_CORE_API ExpressionCompletionFinder
|
||||
(inclusive && searchedPosition <= location.GetEndPosition())));
|
||||
}
|
||||
|
||||
ExpressionCompletionFinder(size_t searchedPosition_)
|
||||
: searchedPosition(searchedPosition_){};
|
||||
ExpressionCompletionFinder(size_t searchedPosition_,
|
||||
gd::ExpressionNode* maybeParentNodeAtLocation_)
|
||||
: searchedPosition(searchedPosition_),
|
||||
maybeParentNodeAtLocation(maybeParentNodeAtLocation_){};
|
||||
|
||||
std::vector<ExpressionCompletionDescription> completions;
|
||||
size_t searchedPosition;
|
||||
gd::ExpressionNode* maybeParentNodeAtLocation;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
|
||||
namespace gd {
|
||||
@@ -46,11 +47,30 @@ class GD_CORE_API ExpressionNodeLocationFinder
|
||||
return finder.GetNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Helper function to find the parent of the deepest node at the search
|
||||
* position, if any.
|
||||
*
|
||||
* \warning Useful for tests. In other cases, prefer using `GetParentNode`.
|
||||
*/
|
||||
static ExpressionNode* GetParentNodeAtPosition(gd::ExpressionNode& node,
|
||||
size_t searchedPosition) {
|
||||
gd::ExpressionNodeLocationFinder finder(searchedPosition);
|
||||
node.Visit(finder);
|
||||
return finder.GetParentNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the deepest node found at the search position, if any.
|
||||
*/
|
||||
ExpressionNode* GetNode() { return foundNode; };
|
||||
|
||||
/**
|
||||
* \brief Return the parent of deepest node found at the search position, if
|
||||
* any.
|
||||
*/
|
||||
ExpressionNode* GetParentNode() { return parentNode; };
|
||||
|
||||
protected:
|
||||
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
|
||||
CheckSearchPositionInNode(node);
|
||||
@@ -110,6 +130,7 @@ class GD_CORE_API ExpressionNodeLocationFinder
|
||||
if (node.location.GetStartPosition() <= searchedPosition &&
|
||||
((!inclusive && searchedPosition < node.location.GetEndPosition()) ||
|
||||
(inclusive && searchedPosition <= node.location.GetEndPosition()))) {
|
||||
parentNode = foundNode;
|
||||
foundNode = &node;
|
||||
return true;
|
||||
}
|
||||
@@ -119,6 +140,7 @@ class GD_CORE_API ExpressionNodeLocationFinder
|
||||
|
||||
size_t searchedPosition;
|
||||
ExpressionNode* foundNode;
|
||||
ExpressionNode* parentNode;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -4,9 +4,11 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/ExpressionsParameterMover.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
@@ -134,10 +136,11 @@ class GD_CORE_API ExpressionParameterMover
|
||||
|
||||
bool ExpressionsParameterMover::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
auto& metadata = isCondition ? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
|
||||
for (std::size_t pNb = 0; pNb < metadata.parameters.size() &&
|
||||
pNb < instruction.GetParametersCount();
|
||||
|
@@ -4,9 +4,11 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/IDE/Events/ExpressionsRenamer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Events/Event.h"
|
||||
#include "GDCore/Events/EventsList.h"
|
||||
#include "GDCore/Events/Parsers/ExpressionParser2.h"
|
||||
@@ -145,10 +147,11 @@ class GD_CORE_API ExpressionFunctionRenamer
|
||||
|
||||
bool ExpressionsRenamer::DoVisitInstruction(gd::Instruction& instruction,
|
||||
bool isCondition) {
|
||||
auto& metadata = isCondition ? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
const auto& metadata = isCondition
|
||||
? gd::MetadataProvider::GetConditionMetadata(
|
||||
platform, instruction.GetType())
|
||||
: gd::MetadataProvider::GetActionMetadata(
|
||||
platform, instruction.GetType());
|
||||
|
||||
for (std::size_t pNb = 0; pNb < metadata.parameters.size() &&
|
||||
pNb < instruction.GetParametersCount();
|
||||
|
@@ -24,24 +24,6 @@ namespace gd {
|
||||
|
||||
InstructionSentenceFormatter *InstructionSentenceFormatter::_singleton = NULL;
|
||||
|
||||
gd::String InstructionSentenceFormatter::Translate(
|
||||
const gd::Instruction &instr, const gd::InstructionMetadata &metadata) {
|
||||
gd::String out = metadata.GetSentence();
|
||||
if (out.empty())
|
||||
out = " "; // Prevent empty sentences that could trigger graphical
|
||||
// glitches.
|
||||
|
||||
// Replace _PARAMx_ placeholders by their values
|
||||
for (std::size_t i = 0; i < metadata.parameters.size(); ++i) {
|
||||
gd::String placeholder = "_PARAM" + gd::String::From(i) + "_";
|
||||
gd::String parameter = instr.GetParameter(i).GetPlainString();
|
||||
out = out.FindAndReplace(placeholder, parameter);
|
||||
}
|
||||
|
||||
out = out.FindAndReplace("\n", " ");
|
||||
return out;
|
||||
}
|
||||
|
||||
std::vector<std::pair<gd::String, gd::TextFormatting> >
|
||||
InstructionSentenceFormatter::GetAsFormattedText(
|
||||
const Instruction &instr, const gd::InstructionMetadata &metadata) {
|
||||
@@ -83,8 +65,7 @@ InstructionSentenceFormatter::GetAsFormattedText(
|
||||
}
|
||||
|
||||
// Add the parameter
|
||||
TextFormatting format =
|
||||
GetFormattingFromType(metadata.parameters[firstParamIndex].type);
|
||||
TextFormatting format;
|
||||
format.userData = firstParamIndex;
|
||||
|
||||
gd::String text = instr.GetParameter(firstParamIndex).GetPlainString();
|
||||
@@ -109,74 +90,6 @@ InstructionSentenceFormatter::GetAsFormattedText(
|
||||
return formattedStr;
|
||||
}
|
||||
|
||||
TextFormatting InstructionSentenceFormatter::GetFormattingFromType(
|
||||
const gd::String &type) {
|
||||
if (gd::ParameterMetadata::IsObject(type)) return typesFormatting["object"];
|
||||
|
||||
return typesFormatting[type];
|
||||
}
|
||||
|
||||
gd::String InstructionSentenceFormatter::LabelFromType(const gd::String &type) {
|
||||
if (type.empty())
|
||||
return "";
|
||||
else if (type == "expression")
|
||||
return _("Expression");
|
||||
else if (gd::ParameterMetadata::IsObject(type))
|
||||
return _("Object");
|
||||
else if (type == "behavior")
|
||||
return _("Behavior");
|
||||
else if (type == "operator")
|
||||
return _("Operator");
|
||||
else if (type == "relationalOperator")
|
||||
return _("Relational operator");
|
||||
else if (type == "file")
|
||||
return _("File");
|
||||
else if (type == "key")
|
||||
return _("Key");
|
||||
else if (type == "mouse")
|
||||
return _("Mouse button");
|
||||
else if (type == "yesorno")
|
||||
return _("Yes or No");
|
||||
else if (type == "police")
|
||||
return _("Font");
|
||||
else if (type == "color")
|
||||
return _("Color");
|
||||
else if (type == "trueorfalse")
|
||||
return _("True or False");
|
||||
else if (type == "string")
|
||||
return _("String");
|
||||
else if (type == "musicfile")
|
||||
return _("Music");
|
||||
else if (type == "soundfile")
|
||||
return _("Sound");
|
||||
else if (type == "password")
|
||||
return _("Password");
|
||||
else if (type == "layer")
|
||||
return _("Layer");
|
||||
else if (type == "joyaxis")
|
||||
return _("Joystick axis");
|
||||
else if (type == "objectvar")
|
||||
return _("Variable of the object");
|
||||
else if (type == "scenevar")
|
||||
return _("Scene variable");
|
||||
else if (type == "globalvar")
|
||||
return _("Global variable");
|
||||
|
||||
return _("Unknown");
|
||||
}
|
||||
|
||||
void InstructionSentenceFormatter::LoadTypesFormattingFromConfig() {
|
||||
// Load default configuration
|
||||
typesFormatting.clear();
|
||||
typesFormatting["expression"].SetColor(27, 143, 1).SetBold();
|
||||
typesFormatting["object"].SetColor(182, 97, 10).SetBold();
|
||||
typesFormatting["behavior"].SetColor(119, 119, 119).SetBold();
|
||||
typesFormatting["operator"].SetColor(55, 131, 211).SetBold();
|
||||
typesFormatting["objectvar"].SetColor(131, 55, 162).SetBold();
|
||||
typesFormatting["scenevar"].SetColor(131, 55, 162).SetBold();
|
||||
typesFormatting["globalvar"].SetColor(131, 55, 162).SetBold();
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
||||
|
@@ -25,39 +25,12 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API InstructionSentenceFormatter {
|
||||
public:
|
||||
/**
|
||||
* \brief Create a sentence from an instruction and its metadata.
|
||||
*
|
||||
* Sentence is provided in the gd::InstructionMetadata passed as parameter.
|
||||
* Parameters placeholders ("_PARAMx_", x being the parameter index) are
|
||||
* replaced by their values stored in the isntruction passed as parameter.
|
||||
*/
|
||||
gd::String Translate(const gd::Instruction &instr,
|
||||
const gd::InstructionMetadata &metadata);
|
||||
|
||||
/**
|
||||
* \brief Create a formatted sentence from an instruction and its metadata.
|
||||
*/
|
||||
std::vector<std::pair<gd::String, gd::TextFormatting> > GetAsFormattedText(
|
||||
const gd::Instruction &instr, const gd::InstructionMetadata &metadata);
|
||||
|
||||
/**
|
||||
* \brief Return the TextFormatting object associated to the \a type.
|
||||
*/
|
||||
TextFormatting GetFormattingFromType(const gd::String &type);
|
||||
|
||||
/**
|
||||
* \brief Return the label of a parameter type
|
||||
*/
|
||||
gd::String LabelFromType(const gd::String &type);
|
||||
|
||||
/**
|
||||
* \brief Load the configuration from the default configuration.
|
||||
*/
|
||||
void LoadTypesFormattingFromConfig();
|
||||
|
||||
std::map<gd::String, gd::TextFormatting> typesFormatting;
|
||||
|
||||
static InstructionSentenceFormatter *Get() {
|
||||
if (NULL == _singleton) {
|
||||
_singleton = new InstructionSentenceFormatter;
|
||||
|
@@ -13,85 +13,20 @@ namespace gd {
|
||||
/**
|
||||
* \brief Represents the style of a text displayed in the events editor.
|
||||
*
|
||||
* Notably used by EventsRenderingHelper to render Instruction.
|
||||
*
|
||||
* \see EventsRenderingHelper
|
||||
* \ingroup IDEDialogsEventsEditor
|
||||
*/
|
||||
class GD_CORE_API TextFormatting {
|
||||
public:
|
||||
TextFormatting()
|
||||
: colorRed(0),
|
||||
colorGreen(0),
|
||||
colorBlue(0),
|
||||
bold(false),
|
||||
italic(false),
|
||||
userData(gd::String::npos) {}
|
||||
TextFormatting() : userData(gd::String::npos) {}
|
||||
~TextFormatting() {}
|
||||
|
||||
/**
|
||||
* \brief Return true if the bold style must be applied.
|
||||
*/
|
||||
bool IsBold() const { return bold; }
|
||||
|
||||
/**
|
||||
* \brief Return true if the italic style must be applied.
|
||||
*/
|
||||
bool IsItalic() const { return italic; }
|
||||
|
||||
/**
|
||||
* \brief Return the red component of the color that must be applied to the
|
||||
* text.
|
||||
*/
|
||||
unsigned int GetColorRed() const { return colorRed; }
|
||||
/**
|
||||
* \brief Return the green component of the color that must be applied to the
|
||||
* text.
|
||||
*/
|
||||
unsigned int GetColorGreen() const { return colorGreen; }
|
||||
/**
|
||||
* \brief Return the blue component of the color that must be applied to the
|
||||
* text.
|
||||
*/
|
||||
unsigned int GetColorBlue() const { return colorBlue; }
|
||||
|
||||
/**
|
||||
* Change the color of the text.
|
||||
*/
|
||||
TextFormatting& SetColor(unsigned int r, unsigned int g, unsigned int b) {
|
||||
colorRed = r;
|
||||
colorGreen = g;
|
||||
colorBlue = b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set if the bold style must be applied.
|
||||
*/
|
||||
TextFormatting& SetBold(bool enable = true) {
|
||||
bold = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set if the italic style must be applied.
|
||||
*/
|
||||
TextFormatting& SetItalic(bool enable = true) {
|
||||
italic = enable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the data (an integer) associated with the text formatting.
|
||||
* Used to store the parameter when rendering instructions.
|
||||
*/
|
||||
size_t GetUserData() const { return userData; }
|
||||
|
||||
unsigned int colorRed;
|
||||
unsigned int colorGreen;
|
||||
unsigned int colorBlue;
|
||||
bool bold;
|
||||
bool italic;
|
||||
size_t userData;
|
||||
};
|
||||
|
||||
|
@@ -4,16 +4,20 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "EventsFunctionTools.h"
|
||||
|
||||
#include "GDCore/Events/Expression.h"
|
||||
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsFunction.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectsContainer.h"
|
||||
#include "GDCore/Project/Project.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/Log.h"
|
||||
|
||||
namespace gd {
|
||||
void EventsFunctionTools::EventsFunctionToObjectsContainer(
|
||||
|
||||
void EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
gd::Project& project,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputGlobalObjectsContainer,
|
||||
@@ -31,4 +35,41 @@ void EventsFunctionTools::EventsFunctionToObjectsContainer(
|
||||
outputObjectsContainer.GetObjectGroups() = eventsFunction.GetObjectGroups();
|
||||
}
|
||||
|
||||
void EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
|
||||
gd::Project& project,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputGlobalObjectsContainer,
|
||||
gd::ObjectsContainer& outputObjectsContainer) {
|
||||
// The context is build the same way as free function...
|
||||
FreeEventsFunctionToObjectsContainer(project,
|
||||
eventsFunction,
|
||||
outputGlobalObjectsContainer,
|
||||
outputObjectsContainer);
|
||||
|
||||
// ...and has an "Object" by convention...
|
||||
if (!outputObjectsContainer.HasObjectNamed("Object")) {
|
||||
gd::LogWarning("No \"Object\" in a function of an events based behavior: " +
|
||||
eventsFunction.GetName() +
|
||||
". This means this function is likely misconfigured (check "
|
||||
"its parameters).");
|
||||
return;
|
||||
}
|
||||
|
||||
// ...with behaviors from properties.
|
||||
gd::Object& thisObject = outputObjectsContainer.GetObject("Object");
|
||||
for (size_t i = 0;
|
||||
i < eventsBasedBehavior.GetPropertyDescriptors().GetCount();
|
||||
i++) {
|
||||
const NamedPropertyDescriptor& propertyDescriptor =
|
||||
eventsBasedBehavior.GetPropertyDescriptors().Get(i);
|
||||
const std::vector<gd::String>& extraInfo =
|
||||
propertyDescriptor.GetExtraInfo();
|
||||
if (propertyDescriptor.GetType() == "Behavior" && extraInfo.size() > 0) {
|
||||
gd::String behaviorName = propertyDescriptor.GetName();
|
||||
thisObject.AddNewBehavior(project, extraInfo.at(0), behaviorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
||||
|
@@ -13,6 +13,7 @@ class Project;
|
||||
class ObjectsContainer;
|
||||
class ParameterMetadata;
|
||||
class EventsFunction;
|
||||
class EventsBasedBehavior;
|
||||
class Expression;
|
||||
} // namespace gd
|
||||
|
||||
@@ -23,18 +24,33 @@ namespace gd {
|
||||
class GD_CORE_API EventsFunctionTools {
|
||||
public:
|
||||
/**
|
||||
* \brief Given an events function, initialize the given objects container
|
||||
* \brief Given a free events function, initialize the given objects container
|
||||
* with objects described in the events function parameters and in
|
||||
* the events function groups.
|
||||
*
|
||||
* This is useful to create the "context" of a function, before code
|
||||
* generation for example.
|
||||
*/
|
||||
static void EventsFunctionToObjectsContainer(
|
||||
static void FreeEventsFunctionToObjectsContainer(
|
||||
gd::Project& project,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputGlobalObjectsContainer,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
/**
|
||||
* \brief Given a behavior events function, initialize the given objects container
|
||||
* with objects described in the events function parameters, in
|
||||
* the events function groups and in the behavior properties (for additional
|
||||
* required behaviors on the object).
|
||||
*
|
||||
* This is useful to create the "context" of a function, before code
|
||||
* generation for example.
|
||||
*/
|
||||
static void BehaviorEventsFunctionToObjectsContainer(
|
||||
gd::Project& project,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::EventsFunction& eventsFunction,
|
||||
gd::ObjectsContainer& outputGlobalObjectsContainer,
|
||||
gd::ObjectsContainer& outputObjectsContainer);
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
|
@@ -14,16 +14,16 @@ namespace gd {
|
||||
* \note Both objects must be kept alive, as this is keeping a pointer to them.
|
||||
*/
|
||||
struct DependencyMetadataAndExtension {
|
||||
DependencyMetadataAndExtension(gd::DependencyMetadata& dependency_,
|
||||
gd::PlatformExtension& extension_)
|
||||
DependencyMetadataAndExtension(gd::DependencyMetadata &dependency_,
|
||||
gd::PlatformExtension &extension_)
|
||||
: dependency(&dependency_), extension(&extension_){};
|
||||
|
||||
gd::DependencyMetadata& GetDependency() const { return *dependency; };
|
||||
gd::PlatformExtension& GetExtension() const { return *extension; };
|
||||
gd::DependencyMetadata &GetDependency() const { return *dependency; };
|
||||
gd::PlatformExtension &GetExtension() const { return *extension; };
|
||||
|
||||
private:
|
||||
gd::DependencyMetadata* dependency;
|
||||
gd::PlatformExtension* extension;
|
||||
gd::DependencyMetadata *dependency;
|
||||
gd::PlatformExtension *extension;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -33,8 +33,8 @@ struct DependencyMetadataAndExtension {
|
||||
class ExportedDependencyResolver {
|
||||
public:
|
||||
/**
|
||||
* \brief Return the list of dependencies to be exported for the given project
|
||||
* and dependency type.
|
||||
* \brief Return the list of dependencies to be exported for the given
|
||||
* project, used extensions list and dependency type.
|
||||
*
|
||||
* Not all dependencies declared by extensions must be exported: some are only
|
||||
* exported when some settings are filled. Then, some others are only exported
|
||||
@@ -42,11 +42,13 @@ class ExportedDependencyResolver {
|
||||
* one level though).
|
||||
*/
|
||||
static std::vector<DependencyMetadataAndExtension> GetDependenciesFor(
|
||||
const gd::Project& project, const gd::String& dependencyType) {
|
||||
const gd::Project &project,
|
||||
std::set<gd::String> usedExtensions,
|
||||
const gd::String &dependencyType) {
|
||||
std::vector<DependencyMetadataAndExtension> dependenciesWithProperType;
|
||||
for (std::shared_ptr<gd::PlatformExtension> extension :
|
||||
project.GetCurrentPlatform().GetAllPlatformExtensions()) {
|
||||
for (gd::DependencyMetadata& dependency :
|
||||
for (const gd::String &extensionName : usedExtensions) {
|
||||
auto extension = project.GetCurrentPlatform().GetExtension(extensionName);
|
||||
for (gd::DependencyMetadata &dependency :
|
||||
extension->GetAllDependencies()) {
|
||||
if (dependency.GetDependencyType() == dependencyType) {
|
||||
DependencyMetadataAndExtension dependencyMetadataAndExtension(
|
||||
@@ -60,7 +62,7 @@ class ExportedDependencyResolver {
|
||||
// and those that don't require extra settings to be filled.
|
||||
std::vector<DependencyMetadataAndExtension> dependenciesWithFilledSettings;
|
||||
for (auto dependencyAndExtension : dependenciesWithProperType) {
|
||||
auto& dependency = dependencyAndExtension.GetDependency();
|
||||
auto &dependency = dependencyAndExtension.GetDependency();
|
||||
auto extraSettingValues = GetExtensionDependencyExtraSettingValues(
|
||||
project, dependencyAndExtension);
|
||||
|
||||
@@ -73,15 +75,15 @@ class ExportedDependencyResolver {
|
||||
// exported (or dependencies that don't require another dependency).
|
||||
std::vector<DependencyMetadataAndExtension> exportedDependencies;
|
||||
for (auto dependencyAndExtension : dependenciesWithFilledSettings) {
|
||||
auto& dependency = dependencyAndExtension.GetDependency();
|
||||
auto& otherDependencyName =
|
||||
auto &dependency = dependencyAndExtension.GetDependency();
|
||||
auto &otherDependencyName =
|
||||
dependency.GetOtherDependencyThatMustBeExported();
|
||||
if (otherDependencyName.empty() ||
|
||||
std::find_if(
|
||||
dependenciesWithFilledSettings.begin(),
|
||||
dependenciesWithFilledSettings.end(),
|
||||
[&otherDependencyName](
|
||||
DependencyMetadataAndExtension& otherDependencyAndExtension) {
|
||||
DependencyMetadataAndExtension &otherDependencyAndExtension) {
|
||||
return otherDependencyAndExtension.GetDependency().GetName() ==
|
||||
otherDependencyName;
|
||||
}) != dependenciesWithFilledSettings.end()) {
|
||||
@@ -98,15 +100,15 @@ class ExportedDependencyResolver {
|
||||
*/
|
||||
static std::map<gd::String, gd::String>
|
||||
GetExtensionDependencyExtraSettingValues(
|
||||
const gd::Project& project,
|
||||
const gd::DependencyMetadataAndExtension& dependencyAndExtension) {
|
||||
const gd::Project &project,
|
||||
const gd::DependencyMetadataAndExtension &dependencyAndExtension) {
|
||||
std::map<gd::String, gd::String> values;
|
||||
auto& dependency = dependencyAndExtension.GetDependency();
|
||||
const gd::String& extensionName =
|
||||
auto &dependency = dependencyAndExtension.GetDependency();
|
||||
const gd::String &extensionName =
|
||||
dependencyAndExtension.GetExtension().GetName();
|
||||
|
||||
for (const auto& extraSetting : dependency.GetAllExtraSettings()) {
|
||||
const gd::String& type = extraSetting.second.GetType();
|
||||
for (const auto &extraSetting : dependency.GetAllExtraSettings()) {
|
||||
const gd::String &type = extraSetting.second.GetType();
|
||||
const gd::String extraSettingValue =
|
||||
type == "ExtensionProperty"
|
||||
? project.GetExtensionProperties().GetValue(
|
||||
|
@@ -27,50 +27,6 @@ namespace gd {
|
||||
|
||||
PlatformLoader::PlatformLoader() {}
|
||||
|
||||
void PlatformLoader::LoadAllPlatformsInManager(gd::String dir) {
|
||||
{
|
||||
#if defined(WINDOWS)
|
||||
std::shared_ptr<gd::Platform> platform = LoadPlatformInManager("GDCpp.dll");
|
||||
#elif defined(LINUX)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("libGDCpp.so");
|
||||
#elif defined(MACOS)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("libGDCpp.dylib");
|
||||
#else
|
||||
#warning Add the appropriate filename here for the C++ Platform!
|
||||
std::shared_ptr<gd::Platform> platform;
|
||||
#endif
|
||||
if (platform)
|
||||
gd::ExtensionsLoader::LoadAllExtensions("./CppPlatform/Extensions/",
|
||||
*platform);
|
||||
}
|
||||
|
||||
{
|
||||
#if defined(WINDOWS)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("./JsPlatform/GDJS.dll");
|
||||
#elif defined(LINUX)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("./JsPlatform/libGDJS.so");
|
||||
#elif defined(MACOS)
|
||||
std::shared_ptr<gd::Platform> platform =
|
||||
LoadPlatformInManager("./JsPlatform/libGDJS.dylib");
|
||||
#else
|
||||
#warning Add the appropriate filename here for the Js Platform!
|
||||
std::shared_ptr<gd::Platform> platform;
|
||||
#endif
|
||||
if (platform)
|
||||
gd::ExtensionsLoader::LoadAllExtensions("./JsPlatform/Extensions/",
|
||||
*platform);
|
||||
if (platform)
|
||||
gd::ExtensionsLoader::LoadAllExtensions(
|
||||
"./CppPlatform/Extensions/", *platform, true);
|
||||
}
|
||||
|
||||
gd::ExtensionsLoader::ExtensionsLoadingDone("./CppPlatform/Extensions/");
|
||||
}
|
||||
|
||||
std::shared_ptr<gd::Platform> PlatformLoader::LoadPlatformInManager(
|
||||
gd::String fullpath) {
|
||||
std::cout << "Loading platform " << fullpath << "..." << std::endl;
|
||||
|
@@ -30,15 +30,6 @@ passing
|
||||
*/
|
||||
class GD_CORE_API PlatformLoader {
|
||||
public:
|
||||
/**
|
||||
* Load all the platforms available in a directory.
|
||||
*
|
||||
* \param dir The directory where platforms must be searched for.
|
||||
*
|
||||
* \todo For now, only GDCpp.dll and GDJS.dll are loaded.
|
||||
*/
|
||||
static void LoadAllPlatformsInManager(gd::String dir);
|
||||
|
||||
/**
|
||||
* Load a specific platform.
|
||||
*
|
||||
|
12
Core/GDCore/IDE/UnfilledRequiredBehaviorPropertyProblem.cpp
Normal file
12
Core/GDCore/IDE/UnfilledRequiredBehaviorPropertyProblem.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2021 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "UnfilledRequiredBehaviorPropertyProblem.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
UnfilledRequiredBehaviorPropertyProblem::~UnfilledRequiredBehaviorPropertyProblem(){};
|
||||
|
||||
} // namespace gd
|
80
Core/GDCore/IDE/UnfilledRequiredBehaviorPropertyProblem.h
Normal file
80
Core/GDCore/IDE/UnfilledRequiredBehaviorPropertyProblem.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2021 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef GDCORE_UNFILLEDREQUIREDBEHAVIORPROPERTYPROBLEM_H
|
||||
#define GDCORE_UNFILLEDREQUIREDBEHAVIORPROPERTYPROBLEM_H
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Project;
|
||||
class Object;
|
||||
class BehaviorContent;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A problem when a required behavior property is not fill correctly.
|
||||
*/
|
||||
class GD_CORE_API UnfilledRequiredBehaviorPropertyProblem {
|
||||
public:
|
||||
UnfilledRequiredBehaviorPropertyProblem(
|
||||
const gd::Project& sourceProject_,
|
||||
gd::Object& sourceObject_,
|
||||
gd::BehaviorContent& sourceBehaviorContent_,
|
||||
const gd::String& sourcePropertyName_,
|
||||
const gd::String& expectedBehaviorTypeName_)
|
||||
: sourceProject(sourceProject_),
|
||||
sourceObject(sourceObject_),
|
||||
sourceBehaviorContent(sourceBehaviorContent_),
|
||||
sourcePropertyName(sourcePropertyName_),
|
||||
expectedBehaviorTypeName(expectedBehaviorTypeName_){};
|
||||
virtual ~UnfilledRequiredBehaviorPropertyProblem();
|
||||
|
||||
/**
|
||||
* \brief Return the project where the problem appears
|
||||
*/
|
||||
virtual const gd::Project& GetSourceProject() const { return sourceProject; }
|
||||
|
||||
/**
|
||||
* \brief Return the object where the problem appears.
|
||||
*/
|
||||
virtual gd::Object& GetSourceObject() const { return sourceObject; }
|
||||
|
||||
/**
|
||||
* \brief Return the behavior where the problem appears.
|
||||
*/
|
||||
virtual gd::BehaviorContent& GetSourceBehaviorContent() const {
|
||||
return sourceBehaviorContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the property where the problem appears.
|
||||
*/
|
||||
virtual const gd::String& GetSourcePropertyName() const {
|
||||
return sourcePropertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return the behavior type name that is expected for the required
|
||||
* behavior property.
|
||||
*/
|
||||
virtual const gd::String& GetExpectedBehaviorTypeName() const {
|
||||
return expectedBehaviorTypeName;
|
||||
}
|
||||
|
||||
private:
|
||||
const gd::Project& sourceProject;
|
||||
gd::Object& sourceObject;
|
||||
gd::BehaviorContent& sourceBehaviorContent;
|
||||
const gd::String sourcePropertyName;
|
||||
|
||||
const gd::String expectedBehaviorTypeName;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
#endif // GDCORE_UNFILLEDREQUIREDBEHAVIORPROPERTYPROBLEM_H
|
@@ -5,9 +5,12 @@
|
||||
*/
|
||||
#include "WholeProjectRefactorer.h"
|
||||
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/PlatformExtension.h"
|
||||
#include "GDCore/IDE/DependenciesAnalyzer.h"
|
||||
#include "GDCore/IDE/Events/ArbitraryEventsWorker.h"
|
||||
#include "GDCore/IDE/Events/EventsBehaviorRenamer.h"
|
||||
#include "GDCore/IDE/Events/EventsRefactorer.h"
|
||||
#include "GDCore/IDE/Events/ExpressionsParameterMover.h"
|
||||
#include "GDCore/IDE/Events/ExpressionsRenamer.h"
|
||||
@@ -15,6 +18,9 @@
|
||||
#include "GDCore/IDE/Events/InstructionsTypeRenamer.h"
|
||||
#include "GDCore/IDE/EventsFunctionTools.h"
|
||||
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
|
||||
#include "GDCore/IDE/UnfilledRequiredBehaviorPropertyProblem.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/BehaviorContent.h"
|
||||
#include "GDCore/Project/EventsBasedBehavior.h"
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
@@ -51,6 +57,10 @@ gd::String GetBehaviorFullType(const gd::String& extensionName,
|
||||
|
||||
namespace gd {
|
||||
|
||||
// By convention, the first parameter of an events based behavior method is
|
||||
// always called "Object".
|
||||
const gd::String WholeProjectRefactorer::behaviorObjectParameterName = "Object";
|
||||
|
||||
void WholeProjectRefactorer::ExposeProjectEvents(
|
||||
gd::Project& project, gd::ArbitraryEventsWorker& worker) {
|
||||
// See also gd::Project::ExposeResources for a method that traverse the whole
|
||||
@@ -115,7 +125,7 @@ void WholeProjectRefactorer::ExposeProjectEvents(
|
||||
for (auto&& eventsFunction : eventsFunctionsExtension.GetInternalVector()) {
|
||||
gd::ObjectsContainer globalObjectsAndGroups;
|
||||
gd::ObjectsContainer objectsAndGroups;
|
||||
gd::EventsFunctionTools::EventsFunctionToObjectsContainer(
|
||||
gd::EventsFunctionTools::FreeEventsFunctionToObjectsContainer(
|
||||
project, *eventsFunction, globalObjectsAndGroups, objectsAndGroups);
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(),
|
||||
@@ -127,22 +137,31 @@ void WholeProjectRefactorer::ExposeProjectEvents(
|
||||
for (auto&& eventsBasedBehavior :
|
||||
eventsFunctionsExtension.GetEventsBasedBehaviors()
|
||||
.GetInternalVector()) {
|
||||
auto& behaviorEventsFunctions = eventsBasedBehavior->GetEventsFunctions();
|
||||
for (auto&& eventsFunction :
|
||||
behaviorEventsFunctions.GetInternalVector()) {
|
||||
gd::ObjectsContainer globalObjectsAndGroups;
|
||||
gd::ObjectsContainer objectsAndGroups;
|
||||
gd::EventsFunctionTools::EventsFunctionToObjectsContainer(
|
||||
project, *eventsFunction, globalObjectsAndGroups, objectsAndGroups);
|
||||
|
||||
worker.Launch(eventsFunction->GetEvents(),
|
||||
globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
}
|
||||
ExposeEventsBasedBehaviorEvents(project, *eventsBasedBehavior, worker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ExposeEventsBasedBehaviorEvents(
|
||||
gd::Project& project,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
gd::ArbitraryEventsWorkerWithContext& worker) {
|
||||
auto& behaviorEventsFunctions = eventsBasedBehavior.GetEventsFunctions();
|
||||
for (auto&& eventsFunction : behaviorEventsFunctions.GetInternalVector()) {
|
||||
gd::ObjectsContainer globalObjectsAndGroups;
|
||||
gd::ObjectsContainer objectsAndGroups;
|
||||
gd::EventsFunctionTools::BehaviorEventsFunctionToObjectsContainer(
|
||||
project,
|
||||
eventsBasedBehavior,
|
||||
*eventsFunction,
|
||||
globalObjectsAndGroups,
|
||||
objectsAndGroups);
|
||||
|
||||
worker.Launch(
|
||||
eventsFunction->GetEvents(), globalObjectsAndGroups, objectsAndGroups);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::ExposeProjectObjects(
|
||||
gd::Project& project, gd::ArbitraryObjectsWorker& worker) {
|
||||
worker.Launch(project);
|
||||
@@ -192,7 +211,7 @@ void WholeProjectRefactorer::EnsureBehaviorEventsFunctionsProperParameters(
|
||||
|
||||
parameters[0]
|
||||
.SetType("object")
|
||||
.SetName("Object")
|
||||
.SetName(behaviorObjectParameterName)
|
||||
.SetDescription("Object")
|
||||
.SetExtraInfo(eventsBasedBehavior.GetObjectType());
|
||||
parameters[1]
|
||||
@@ -470,7 +489,7 @@ void WholeProjectRefactorer::MoveBehaviorEventsFunctionParameter(
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameBehaviorProperty(
|
||||
void WholeProjectRefactorer::RenameEventsBasedBehaviorProperty(
|
||||
gd::Project& project,
|
||||
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
@@ -479,41 +498,294 @@ void WholeProjectRefactorer::RenameBehaviorProperty(
|
||||
auto& properties = eventsBasedBehavior.GetPropertyDescriptors();
|
||||
if (!properties.Has(oldPropertyName)) return;
|
||||
|
||||
// Order is important: we first rename the expressions then the instructions,
|
||||
// to avoid being unable to fetch the metadata (the types of parameters) of
|
||||
// instructions after they are renamed.
|
||||
gd::ExpressionsRenamer expressionRenamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
expressionRenamer.SetReplacedBehaviorExpression(
|
||||
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName()),
|
||||
EventsBasedBehavior::GetPropertyExpressionName(oldPropertyName),
|
||||
EventsBasedBehavior::GetPropertyExpressionName(newPropertyName));
|
||||
ExposeProjectEvents(project, expressionRenamer);
|
||||
if (properties.Get(oldPropertyName).GetType() == "Behavior") {
|
||||
// This is a property representing another behavior that must exist on the
|
||||
// object.
|
||||
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyActionName(oldPropertyName)),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyActionName(newPropertyName)));
|
||||
ExposeProjectEvents(project, actionRenamer);
|
||||
// This other "required behavior" uses the property name, that is about to
|
||||
// change, as its name.
|
||||
// So we must change all reference to this name in the events of the
|
||||
// behavior functions.
|
||||
gd::EventsBehaviorRenamer behaviorRenamer(project.GetCurrentPlatform(),
|
||||
behaviorObjectParameterName,
|
||||
oldPropertyName,
|
||||
newPropertyName);
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyConditionName(oldPropertyName)),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyConditionName(newPropertyName)));
|
||||
ExposeProjectEvents(project, conditionRenamer);
|
||||
ExposeEventsBasedBehaviorEvents(
|
||||
project, eventsBasedBehavior, behaviorRenamer);
|
||||
} else {
|
||||
// Properties that represent primitive values will be used through
|
||||
// their related actions/conditions/expressions. Rename these.
|
||||
|
||||
// Order is important: we first rename the expressions then the
|
||||
// instructions, to avoid being unable to fetch the metadata (the types of
|
||||
// parameters) of instructions after they are renamed.
|
||||
gd::ExpressionsRenamer expressionRenamer =
|
||||
gd::ExpressionsRenamer(project.GetCurrentPlatform());
|
||||
expressionRenamer.SetReplacedBehaviorExpression(
|
||||
GetBehaviorFullType(eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName()),
|
||||
EventsBasedBehavior::GetPropertyExpressionName(oldPropertyName),
|
||||
EventsBasedBehavior::GetPropertyExpressionName(newPropertyName));
|
||||
ExposeProjectEvents(project, expressionRenamer);
|
||||
|
||||
gd::InstructionsTypeRenamer actionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyActionName(oldPropertyName)),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyActionName(newPropertyName)));
|
||||
ExposeProjectEvents(project, actionRenamer);
|
||||
|
||||
gd::InstructionsTypeRenamer conditionRenamer = gd::InstructionsTypeRenamer(
|
||||
project,
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyConditionName(oldPropertyName)),
|
||||
GetBehaviorEventsFunctionFullType(
|
||||
eventsFunctionsExtension.GetName(),
|
||||
eventsBasedBehavior.GetName(),
|
||||
EventsBasedBehavior::GetPropertyConditionName(newPropertyName)));
|
||||
ExposeProjectEvents(project, conditionRenamer);
|
||||
}
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
gd::Project& project,
|
||||
gd::Object& object,
|
||||
const gd::String& behaviorType,
|
||||
const gd::String& behaviorName) {
|
||||
if (object.AddNewBehavior(project, behaviorType, behaviorName) == nullptr) {
|
||||
// The behavior type/metadata can't be found.
|
||||
return;
|
||||
};
|
||||
|
||||
const gd::Platform& platform = project.GetCurrentPlatform();
|
||||
const gd::BehaviorMetadata& behaviorMetadata =
|
||||
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
// Should not happen because the behavior was added successfully (so its
|
||||
// metadata are valid) - but double check anyway and bail out if the
|
||||
// behavior metadata are invalid.
|
||||
return;
|
||||
}
|
||||
|
||||
gd::Behavior& behavior = behaviorMetadata.Get();
|
||||
gd::BehaviorContent& behaviorContent = object.GetBehavior(behaviorName);
|
||||
for (auto const& keyValue :
|
||||
behavior.GetProperties(behaviorContent.GetContent())) {
|
||||
const gd::String& propertyName = keyValue.first;
|
||||
const gd::PropertyDescriptor& property = keyValue.second;
|
||||
if (property.GetType().LowerCase() == "behavior") {
|
||||
const std::vector<gd::String>& extraInfo = property.GetExtraInfo();
|
||||
if (extraInfo.size() == 0) {
|
||||
// very unlikely
|
||||
continue;
|
||||
}
|
||||
const gd::String& requiredBehaviorType = extraInfo.at(0);
|
||||
const auto behaviorContents =
|
||||
WholeProjectRefactorer::GetBehaviorsWithType(object,
|
||||
requiredBehaviorType);
|
||||
const gd::String* defaultBehaviorName = nullptr;
|
||||
if (behaviorContents.size() == 0) {
|
||||
const gd::BehaviorMetadata& requiredBehaviorMetadata =
|
||||
MetadataProvider::GetBehaviorMetadata(platform,
|
||||
requiredBehaviorType);
|
||||
const gd::String& requiredBehaviorName =
|
||||
requiredBehaviorMetadata.GetDefaultName();
|
||||
WholeProjectRefactorer::AddBehaviorAndRequiredBehaviors(
|
||||
project, object, requiredBehaviorType, requiredBehaviorName);
|
||||
defaultBehaviorName = &requiredBehaviorName;
|
||||
} else {
|
||||
defaultBehaviorName = &behaviorContents.at(0);
|
||||
}
|
||||
behavior.UpdateProperty(
|
||||
behaviorContent.GetContent(), propertyName, *defaultBehaviorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<gd::String> WholeProjectRefactorer::GetBehaviorsWithType(
|
||||
const gd::Object& object, const gd::String& type) {
|
||||
std::vector<gd::String> behaviors;
|
||||
for (auto& behaviorName : object.GetAllBehaviorNames()) {
|
||||
const gd::BehaviorContent& behaviorContent =
|
||||
object.GetBehavior(behaviorName);
|
||||
if (behaviorContent.GetTypeName() == type) {
|
||||
behaviors.push_back(behaviorName);
|
||||
}
|
||||
}
|
||||
return behaviors;
|
||||
}
|
||||
|
||||
std::vector<gd::String> WholeProjectRefactorer::FindDependentBehaviorNames(
|
||||
const gd::Project& project,
|
||||
const gd::Object& object,
|
||||
const gd::String& behaviorName) {
|
||||
std::unordered_set<gd::String> dependentBehaviorNames;
|
||||
WholeProjectRefactorer::FindDependentBehaviorNames(
|
||||
project, object, behaviorName, dependentBehaviorNames);
|
||||
std::vector<gd::String> results;
|
||||
results.insert(results.end(),
|
||||
dependentBehaviorNames.begin(),
|
||||
dependentBehaviorNames.end());
|
||||
return results;
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::FindDependentBehaviorNames(
|
||||
const gd::Project& project,
|
||||
const gd::Object& object,
|
||||
const gd::String& behaviorName,
|
||||
std::unordered_set<gd::String>& dependentBehaviorNames) {
|
||||
const gd::Platform& platform = project.GetCurrentPlatform();
|
||||
for (auto const& objectBehaviorName : object.GetAllBehaviorNames()) {
|
||||
const gd::BehaviorContent& behaviorContent =
|
||||
object.GetBehavior(objectBehaviorName);
|
||||
const auto& behaviorMetadata = MetadataProvider::GetBehaviorMetadata(
|
||||
platform, behaviorContent.GetTypeName());
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
// Ignore this behavior as it's unknown.
|
||||
continue;
|
||||
}
|
||||
|
||||
gd::Behavior& behavior = behaviorMetadata.Get();
|
||||
for (auto const& keyValue :
|
||||
behavior.GetProperties(behaviorContent.GetContent())) {
|
||||
const gd::String& propertyName = keyValue.first;
|
||||
const gd::PropertyDescriptor& property = keyValue.second;
|
||||
if (property.GetType().LowerCase() == "behavior" &&
|
||||
property.GetValue() == behaviorName &&
|
||||
dependentBehaviorNames.find(objectBehaviorName) ==
|
||||
dependentBehaviorNames.end()) {
|
||||
dependentBehaviorNames.insert(objectBehaviorName);
|
||||
WholeProjectRefactorer::FindDependentBehaviorNames(
|
||||
project, object, objectBehaviorName, dependentBehaviorNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<gd::UnfilledRequiredBehaviorPropertyProblem>
|
||||
WholeProjectRefactorer::FindInvalidRequiredBehaviorProperties(
|
||||
const gd::Project& project) {
|
||||
std::vector<gd::UnfilledRequiredBehaviorPropertyProblem>
|
||||
invalidRequiredBehaviorProperties;
|
||||
auto findInvalidRequiredBehaviorPropertiesInObjects =
|
||||
[&project, &invalidRequiredBehaviorProperties](
|
||||
const std::vector<std::unique_ptr<gd::Object> >& objectsList) {
|
||||
for (auto& object : objectsList) {
|
||||
for (auto& behaviorContentKeyValuePair :
|
||||
object->GetAllBehaviorContents()) {
|
||||
gd::BehaviorContent& behaviorContent =
|
||||
*behaviorContentKeyValuePair.second;
|
||||
|
||||
const auto& behaviorMetadata =
|
||||
gd::MetadataProvider::GetBehaviorMetadata(
|
||||
project.GetCurrentPlatform(),
|
||||
behaviorContent.GetTypeName());
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
std::cout << "Could not find metadata for behavior with type \""
|
||||
<< behaviorContent.GetTypeName() << "\"" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& behavior = behaviorMetadata.Get();
|
||||
|
||||
for (auto const& keyValue :
|
||||
behavior.GetProperties(behaviorContent.GetContent())) {
|
||||
const gd::String& propertyName = keyValue.first;
|
||||
const gd::PropertyDescriptor& property = keyValue.second;
|
||||
if (property.GetType().LowerCase() != "behavior") {
|
||||
continue;
|
||||
}
|
||||
const gd::String& requiredBehaviorName = property.GetValue();
|
||||
const std::vector<gd::String>& extraInfo =
|
||||
property.GetExtraInfo();
|
||||
if (extraInfo.size() == 0) {
|
||||
// very unlikely
|
||||
continue;
|
||||
}
|
||||
const gd::String& requiredBehaviorType = extraInfo.at(0);
|
||||
|
||||
if (requiredBehaviorName == "" ||
|
||||
!object->HasBehaviorNamed(requiredBehaviorName) ||
|
||||
object->GetBehavior(requiredBehaviorName).GetTypeName() !=
|
||||
requiredBehaviorType) {
|
||||
auto problem = UnfilledRequiredBehaviorPropertyProblem(
|
||||
project,
|
||||
*object,
|
||||
behaviorContent,
|
||||
propertyName,
|
||||
requiredBehaviorType);
|
||||
invalidRequiredBehaviorProperties.push_back(problem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Find in global objects
|
||||
findInvalidRequiredBehaviorPropertiesInObjects(project.GetObjects());
|
||||
|
||||
// Find in layout objects.
|
||||
for (std::size_t i = 0; i < project.GetLayoutsCount(); ++i) {
|
||||
const gd::Layout& layout = project.GetLayout(i);
|
||||
findInvalidRequiredBehaviorPropertiesInObjects(layout.GetObjects());
|
||||
}
|
||||
return invalidRequiredBehaviorProperties;
|
||||
}
|
||||
|
||||
bool WholeProjectRefactorer::FixInvalidRequiredBehaviorProperties(
|
||||
gd::Project& project) {
|
||||
const auto& invalidRequiredBehaviorProblems =
|
||||
FindInvalidRequiredBehaviorProperties(project);
|
||||
for (const auto& problem : invalidRequiredBehaviorProblems) {
|
||||
auto& object = problem.GetSourceObject();
|
||||
auto suggestedBehaviorNames =
|
||||
GetBehaviorsWithType(object, problem.GetExpectedBehaviorTypeName());
|
||||
auto& behaviorContent = problem.GetSourceBehaviorContent();
|
||||
auto& behaviorMetadata = MetadataProvider::GetBehaviorMetadata(
|
||||
project.GetCurrentPlatform(), behaviorContent.GetTypeName());
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& behavior = behaviorMetadata.Get();
|
||||
if (suggestedBehaviorNames.empty()) {
|
||||
// No matching behavior on the object.
|
||||
// Add required behaviors on the object.
|
||||
|
||||
auto& expectedBehaviorMetadata = MetadataProvider::GetBehaviorMetadata(
|
||||
project.GetCurrentPlatform(), problem.GetExpectedBehaviorTypeName());
|
||||
if (MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const gd::String& newBehaviorName =
|
||||
expectedBehaviorMetadata.GetDefaultName();
|
||||
AddBehaviorAndRequiredBehaviors(project,
|
||||
object,
|
||||
problem.GetExpectedBehaviorTypeName(),
|
||||
newBehaviorName);
|
||||
behavior.UpdateProperty(behaviorContent.GetContent(),
|
||||
problem.GetSourcePropertyName(),
|
||||
newBehaviorName);
|
||||
} else {
|
||||
// There is a matching behavior on the object use it by default.
|
||||
behavior.UpdateProperty(
|
||||
behaviorContent.GetContent(),
|
||||
problem.GetSourcePropertyName(),
|
||||
// It's unlikely the object has 2 behaviors of the same type.
|
||||
suggestedBehaviorNames[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return !invalidRequiredBehaviorProblems.empty();
|
||||
}
|
||||
|
||||
void WholeProjectRefactorer::RenameEventsBasedBehavior(
|
||||
@@ -678,6 +950,31 @@ void WholeProjectRefactorer::DoRenameBehavior(
|
||||
}
|
||||
};
|
||||
|
||||
// Rename behavior in required behavior properties
|
||||
for (std::size_t e = 0; e < project.GetEventsFunctionsExtensionsCount();
|
||||
e++) {
|
||||
auto& eventsFunctionsExtension = project.GetEventsFunctionsExtension(e);
|
||||
|
||||
for (auto&& eventsBasedBehavior :
|
||||
eventsFunctionsExtension.GetEventsBasedBehaviors()
|
||||
.GetInternalVector()) {
|
||||
for (size_t i = 0;
|
||||
i < eventsBasedBehavior->GetPropertyDescriptors().GetCount();
|
||||
i++) {
|
||||
NamedPropertyDescriptor& propertyDescriptor =
|
||||
eventsBasedBehavior->GetPropertyDescriptors().Get(i);
|
||||
std::vector<gd::String>& extraInfo = propertyDescriptor.GetExtraInfo();
|
||||
if (propertyDescriptor.GetType() == "Behavior" &&
|
||||
extraInfo.size() > 0) {
|
||||
const gd::String& requiredBehaviorType = extraInfo[0];
|
||||
if (requiredBehaviorType == oldBehaviorType) {
|
||||
extraInfo[0] = newBehaviorType;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rename behavior in global objects
|
||||
renameBehaviorTypeInObjects(project.GetObjects());
|
||||
|
||||
|
@@ -6,10 +6,13 @@
|
||||
#ifndef GDCORE_WHOLEPROJECTREFACTORER_H
|
||||
#define GDCORE_WHOLEPROJECTREFACTORER_H
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
namespace gd {
|
||||
class Platform;
|
||||
class Project;
|
||||
class Layout;
|
||||
class Object;
|
||||
class String;
|
||||
class EventsFunctionsExtension;
|
||||
class EventsFunction;
|
||||
@@ -18,6 +21,10 @@ class EventsBasedBehavior;
|
||||
class ArbitraryEventsWorker;
|
||||
class ArbitraryObjectsWorker;
|
||||
class ArbitraryEventsWorkerWithContext;
|
||||
class Behavior;
|
||||
class BehaviorContent;
|
||||
class BehaviorMetadata;
|
||||
class UnfilledRequiredBehaviorPropertyProblem;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -51,13 +58,24 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
gd::ArbitraryEventsWorkerWithContext& worker);
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all ObjectContainers of the project (global,
|
||||
* layouts...)
|
||||
* \brief Call the specified worker on all events of the events based behavior
|
||||
*
|
||||
* This should be the preferred way to traverse all the events of an events
|
||||
* based behavior
|
||||
*/
|
||||
static void ExposeEventsBasedBehaviorEvents(
|
||||
gd::Project& project,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
gd::ArbitraryEventsWorkerWithContext& worker);
|
||||
|
||||
/**
|
||||
* \brief Call the specified worker on all ObjectContainers of the project
|
||||
* (global, layouts...)
|
||||
*
|
||||
* This should be the preferred way to traverse all the objects of a project.
|
||||
*/
|
||||
static void ExposeProjectObjects(
|
||||
gd::Project& project, gd::ArbitraryObjectsWorker& worker);
|
||||
static void ExposeProjectObjects(gd::Project& project,
|
||||
gd::ArbitraryObjectsWorker& worker);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** an events function extension is
|
||||
@@ -140,13 +158,52 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
* This is because the property is expected to have its old name for the
|
||||
* refactoring.
|
||||
*/
|
||||
static void RenameBehaviorProperty(
|
||||
static void RenameEventsBasedBehaviorProperty(
|
||||
gd::Project& project,
|
||||
const gd::EventsFunctionsExtension& eventsFunctionsExtension,
|
||||
const gd::EventsBasedBehavior& eventsBasedBehavior,
|
||||
const gd::String& oldPropertyName,
|
||||
const gd::String& newPropertyName);
|
||||
|
||||
/**
|
||||
* \brief Add a behavior to an object and add required behaviors if necessary
|
||||
* to fill every behavior properties of the added behaviors.
|
||||
*/
|
||||
static void AddBehaviorAndRequiredBehaviors(gd::Project& project,
|
||||
gd::Object& object,
|
||||
const gd::String& behaviorType,
|
||||
const gd::String& behaviorName);
|
||||
|
||||
/**
|
||||
* \brief Find every behavior of the object that needs the given behaviors
|
||||
* directly or indirectly (because of "required behavior" properties).
|
||||
*/
|
||||
static std::vector<gd::String> FindDependentBehaviorNames(
|
||||
const gd::Project& project,
|
||||
const gd::Object& object,
|
||||
const gd::String& behaviorName);
|
||||
|
||||
/**
|
||||
* \brief Find the names of the behaviors with the specified type on the object.
|
||||
*/
|
||||
static std::vector<gd::String> GetBehaviorsWithType(const gd::Object& object,
|
||||
const gd::String& type);
|
||||
|
||||
/**
|
||||
* \brief Find in the project objects having behaviors with "behavior" properties that
|
||||
* don't have a valid value (i.e: pointing to a non existing behavior, or of a wrong type).
|
||||
*/
|
||||
static std::vector<gd::UnfilledRequiredBehaviorPropertyProblem>
|
||||
FindInvalidRequiredBehaviorProperties(const gd::Project& project);
|
||||
|
||||
/**
|
||||
* \brief Fix in the project objects having behaviors with "behavior" properties that
|
||||
* don't have a valid value (i.e: pointing to a non existing behavior, or of a wrong type),
|
||||
* by setting a proper behavior, or adding missing behaviors to these objects.
|
||||
*/
|
||||
static bool
|
||||
FixInvalidRequiredBehaviorProperties(gd::Project& project);
|
||||
|
||||
/**
|
||||
* \brief Refactor the project **before** a behavior is renamed.
|
||||
*
|
||||
@@ -267,6 +324,14 @@ class GD_CORE_API WholeProjectRefactorer {
|
||||
const gd::String& oldBehaviorType,
|
||||
const gd::String& newBehaviorType);
|
||||
|
||||
static void FindDependentBehaviorNames(
|
||||
const gd::Project& project,
|
||||
const gd::Object& object,
|
||||
const gd::String& behaviorName,
|
||||
std::unordered_set<gd::String>& dependentBehaviorNames);
|
||||
|
||||
static const gd::String behaviorObjectParameterName;
|
||||
|
||||
WholeProjectRefactorer(){};
|
||||
};
|
||||
|
||||
|
@@ -9,7 +9,6 @@
|
||||
|
||||
namespace gd {
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void Effect::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("name", GetName());
|
||||
element.SetAttribute("effectType", GetEffectType());
|
||||
@@ -32,7 +31,6 @@ void Effect::SerializeTo(SerializerElement& element) const {
|
||||
booleanParametersElement.AddChild(parameter.first)
|
||||
.SetValue(parameter.second);
|
||||
}
|
||||
#endif
|
||||
|
||||
void Effect::UnserializeFrom(const SerializerElement& element) {
|
||||
SetName(element.GetStringAttribute("name"));
|
||||
|
@@ -74,12 +74,10 @@ class GD_CORE_API Effect {
|
||||
booleanParameters.clear();
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief Serialize layer.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Unserialize the layer.
|
||||
|
140
Core/GDCore/Project/EffectsContainer.cpp
Normal file
140
Core/GDCore/Project/EffectsContainer.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "EffectsContainer.h"
|
||||
|
||||
#include "Effect.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
Effect EffectsContainer::badEffect;
|
||||
|
||||
EffectsContainer::EffectsContainer() {}
|
||||
|
||||
EffectsContainer::EffectsContainer(const EffectsContainer& other) {
|
||||
Init(other);
|
||||
}
|
||||
|
||||
EffectsContainer& EffectsContainer::operator=(const EffectsContainer& rhs) {
|
||||
if (this != &rhs) Init(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void EffectsContainer::Init(const EffectsContainer& other) {
|
||||
effects.clear();
|
||||
for (auto& it : other.effects) {
|
||||
effects.push_back(std::make_shared<Effect>(*it));
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectsContainer::HasEffectNamed(const gd::String& name) const {
|
||||
return (find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
}) != effects.end());
|
||||
}
|
||||
|
||||
gd::Effect& EffectsContainer::GetEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
|
||||
const gd::Effect& EffectsContainer::GetEffect(const gd::String& name) const {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
gd::Effect& EffectsContainer::GetEffect(std::size_t index) {
|
||||
return *effects[index];
|
||||
}
|
||||
const gd::Effect& EffectsContainer::GetEffect(std::size_t index) const {
|
||||
return *effects[index];
|
||||
}
|
||||
std::size_t EffectsContainer::GetEffectsCount() const { return effects.size(); }
|
||||
std::size_t EffectsContainer::GetEffectPosition(const gd::String& name) const {
|
||||
for (std::size_t i = 0; i < effects.size(); ++i) {
|
||||
if (effects[i]->GetName() == name) return i;
|
||||
}
|
||||
return gd::String::npos;
|
||||
}
|
||||
|
||||
gd::Effect& EffectsContainer::InsertNewEffect(const gd::String& name,
|
||||
std::size_t position) {
|
||||
auto newEffect = std::make_shared<Effect>();
|
||||
newEffect->SetName(name);
|
||||
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
|
||||
return *newEffect;
|
||||
}
|
||||
|
||||
void EffectsContainer::InsertEffect(const gd::Effect& effect,
|
||||
std::size_t position) {
|
||||
auto newEffect = std::make_shared<gd::Effect>(effect);
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
}
|
||||
|
||||
void EffectsContainer::RemoveEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
if (effect == effects.end()) return;
|
||||
|
||||
effects.erase(effect);
|
||||
}
|
||||
|
||||
void EffectsContainer::SwapEffects(std::size_t firstEffectIndex,
|
||||
std::size_t secondEffectIndex) {
|
||||
if (firstEffectIndex >= effects.size() || secondEffectIndex >= effects.size())
|
||||
return;
|
||||
|
||||
auto temp = effects[firstEffectIndex];
|
||||
effects[firstEffectIndex] = effects[secondEffectIndex];
|
||||
effects[secondEffectIndex] = temp;
|
||||
}
|
||||
|
||||
void EffectsContainer::SerializeTo(SerializerElement& element) const {
|
||||
element.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < GetEffectsCount(); ++i) {
|
||||
SerializerElement& effectElement = element.AddChild("effect");
|
||||
GetEffect(i).SerializeTo(effectElement);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsContainer::UnserializeFrom(const SerializerElement& element) {
|
||||
effects.clear();
|
||||
element.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& effectElement = element.GetChild(i);
|
||||
|
||||
auto effect = std::make_shared<Effect>();
|
||||
effect->UnserializeFrom(effectElement);
|
||||
effects.push_back(effect);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gd
|
114
Core/GDCore/Project/EffectsContainer.h
Normal file
114
Core/GDCore/Project/EffectsContainer.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef GDCORE_EFFECTS_CONTAINER_H
|
||||
#define GDCORE_EFFECTS_CONTAINER_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Effect;
|
||||
}
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Contains effects applied to an entity on screen (i.e: a Layer or an
|
||||
* Object).
|
||||
*
|
||||
* \ingroup PlatformDefinition
|
||||
*/
|
||||
class GD_CORE_API EffectsContainer {
|
||||
public:
|
||||
EffectsContainer();
|
||||
EffectsContainer(const EffectsContainer& other);
|
||||
virtual ~EffectsContainer(){};
|
||||
|
||||
EffectsContainer& operator=(const EffectsContainer& rhs);
|
||||
/**
|
||||
* \brief Return true if the effect called "name" exists.
|
||||
*/
|
||||
bool HasEffectNamed(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
*/
|
||||
Effect& GetEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
*/
|
||||
const Effect& GetEffect(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
Effect& GetEffect(std::size_t index);
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
const Effect& GetEffect(std::size_t index) const;
|
||||
|
||||
/**
|
||||
* Return the position of the effect called "name" in the effects list
|
||||
*/
|
||||
std::size_t GetEffectPosition(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return the number of effecst.
|
||||
*/
|
||||
std::size_t GetEffectsCount() const;
|
||||
|
||||
/**
|
||||
* Add a new effect at the specified position in the effects list.
|
||||
*/
|
||||
gd::Effect& InsertNewEffect(const gd::String& name, std::size_t position);
|
||||
|
||||
/**
|
||||
* \brief Add a copy of the specified effect in the effects list.
|
||||
*
|
||||
* \note No pointer or reference must be kept on the effect passed as
|
||||
* parameter.
|
||||
*
|
||||
* \param theEffect The effect that must be copied and inserted
|
||||
* into the effects list
|
||||
* \param position Insertion position.
|
||||
*/
|
||||
void InsertEffect(const Effect& theEffect, std::size_t position);
|
||||
|
||||
/**
|
||||
* Remove the specified effect.
|
||||
*/
|
||||
void RemoveEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Swap the position of two effects.
|
||||
*/
|
||||
void SwapEffects(std::size_t firstEffectIndex, std::size_t secondEffectIndex);
|
||||
|
||||
/**
|
||||
* \brief Serialize the effects container.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the effects container.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<gd::Effect>> effects;
|
||||
static Effect badEffect;
|
||||
void Init(const EffectsContainer& other);
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
#endif
|
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "GDCore/Project/ExternalLayout.h"
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
|
||||
#include "GDCore/Project/InitialInstancesContainer.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/TinyXml/tinyxml.h"
|
||||
@@ -16,7 +16,7 @@ void ExternalLayout::UnserializeFrom(const SerializerElement& element) {
|
||||
name = element.GetStringAttribute("name", "", "Name");
|
||||
instances.UnserializeFrom(element.GetChild("instances", 0, "Instances"));
|
||||
#if defined(GD_IDE_ONLY)
|
||||
editionSettings.UnserializeFrom(element.GetChild("editionSettings"));
|
||||
editorSettings.UnserializeFrom(element.GetChild("editionSettings"));
|
||||
#endif
|
||||
associatedLayout = element.GetStringAttribute("associatedLayout");
|
||||
}
|
||||
@@ -25,7 +25,7 @@ void ExternalLayout::UnserializeFrom(const SerializerElement& element) {
|
||||
void ExternalLayout::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("name", name);
|
||||
instances.SerializeTo(element.AddChild("instances"));
|
||||
editionSettings.SerializeTo(element.AddChild("editionSettings"));
|
||||
editorSettings.SerializeTo(element.AddChild("editionSettings"));
|
||||
element.SetAttribute("associatedLayout", associatedLayout);
|
||||
}
|
||||
#endif
|
||||
|
@@ -13,7 +13,7 @@ namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
|
||||
#endif
|
||||
|
||||
namespace gd {
|
||||
@@ -58,15 +58,15 @@ class GD_CORE_API ExternalLayout {
|
||||
/**
|
||||
* \brief Get the user settings for the IDE.
|
||||
*/
|
||||
const gd::LayoutEditorCanvasOptions& GetAssociatedSettings() const {
|
||||
return editionSettings;
|
||||
const gd::EditorSettings& GetAssociatedEditorSettings() const {
|
||||
return editorSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the user settings for the IDE.
|
||||
*/
|
||||
gd::LayoutEditorCanvasOptions& GetAssociatedSettings() {
|
||||
return editionSettings;
|
||||
gd::EditorSettings& GetAssociatedEditorSettings() {
|
||||
return editorSettings;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -100,7 +100,7 @@ class GD_CORE_API ExternalLayout {
|
||||
gd::String name;
|
||||
gd::InitialInstancesContainer instances;
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::LayoutEditorCanvasOptions editionSettings;
|
||||
gd::EditorSettings editorSettings;
|
||||
#endif
|
||||
gd::String associatedLayout;
|
||||
};
|
||||
|
@@ -1,213 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include "GDCore/Project/ResourcesLoader.h"
|
||||
#include "GDCore/Project/ResourcesManager.h"
|
||||
#include "GDCore/Tools/InvalidImage.h"
|
||||
#if !defined(ANDROID) && !defined(MACOS)
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
#undef LoadImage // thx windows.h
|
||||
|
||||
namespace gd {
|
||||
|
||||
ImageManager::ImageManager() : resourcesManager(NULL) {
|
||||
#if !defined(EMSCRIPTEN)
|
||||
badTexture = std::make_shared<SFMLTextureWrapper>();
|
||||
badTexture->texture.loadFromMemory(gd::InvalidImageData,
|
||||
sizeof(gd::InvalidImageData));
|
||||
badTexture->texture.setSmooth(false);
|
||||
badTexture->image = badTexture->texture.copyToImage();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::shared_ptr<SFMLTextureWrapper> ImageManager::GetSFMLTexture(
|
||||
const gd::String& name) const {
|
||||
if (!resourcesManager) {
|
||||
std::cout << "ImageManager has no ResourcesManager associated with.";
|
||||
return badTexture;
|
||||
}
|
||||
|
||||
if (alreadyLoadedImages.find(name) != alreadyLoadedImages.end() &&
|
||||
!alreadyLoadedImages.find(name)->second.expired())
|
||||
return alreadyLoadedImages.find(name)->second.lock();
|
||||
|
||||
std::cout << "ImageManager: Loading " << name << ".";
|
||||
|
||||
// Load only an image when necessary
|
||||
try {
|
||||
ImageResource& image =
|
||||
dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
|
||||
|
||||
auto texture = std::make_shared<SFMLTextureWrapper>();
|
||||
ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), texture->image);
|
||||
texture->texture.loadFromImage(texture->image);
|
||||
texture->texture.setSmooth(image.smooth);
|
||||
|
||||
alreadyLoadedImages[name] = texture;
|
||||
#if defined(GD_IDE_ONLY)
|
||||
if (preventUnloading)
|
||||
unloadingPreventer.push_back(
|
||||
texture); // If unload prevention is activated, add the image to the
|
||||
// list dedicated to prevent images from being unloaded.
|
||||
#endif
|
||||
|
||||
return texture;
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
std::cout << " Resource not found." << std::endl;
|
||||
|
||||
return badTexture;
|
||||
}
|
||||
|
||||
bool ImageManager::HasLoadedSFMLTexture(const gd::String& name) const {
|
||||
if (alreadyLoadedImages.find(name) != alreadyLoadedImages.end() &&
|
||||
!alreadyLoadedImages.find(name)->second.expired())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageManager::SetSFMLTextureAsPermanentlyLoaded(
|
||||
const gd::String& name,
|
||||
std::shared_ptr<SFMLTextureWrapper>& texture) const {
|
||||
if (alreadyLoadedImages.find(name) == alreadyLoadedImages.end() ||
|
||||
alreadyLoadedImages.find(name)->second.expired())
|
||||
alreadyLoadedImages[name] = texture;
|
||||
|
||||
if (permanentlyLoadedImages.find(name) == permanentlyLoadedImages.end())
|
||||
permanentlyLoadedImages[name] = texture;
|
||||
}
|
||||
|
||||
void ImageManager::ReloadImage(const gd::String& name) const {
|
||||
if (!resourcesManager) {
|
||||
std::cout << "ImageManager has no ResourcesManager associated with.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify if image is in memory. If not, it will be automatically reloaded
|
||||
// when necessary.
|
||||
if (alreadyLoadedImages.find(name) == alreadyLoadedImages.end() ||
|
||||
alreadyLoadedImages.find(name)->second.expired())
|
||||
return;
|
||||
|
||||
// Image still in memory, get it and update it.
|
||||
std::shared_ptr<SFMLTextureWrapper> oldTexture =
|
||||
alreadyLoadedImages.find(name)->second.lock();
|
||||
|
||||
try {
|
||||
ImageResource& image =
|
||||
dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
|
||||
|
||||
std::cout << "ImageManager: Reload " << name << std::endl;
|
||||
|
||||
ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), oldTexture->image);
|
||||
oldTexture->texture.loadFromImage(oldTexture->image);
|
||||
oldTexture->texture.setSmooth(image.smooth);
|
||||
|
||||
return;
|
||||
} catch (...) { /*The ressource is not an image*/
|
||||
}
|
||||
|
||||
// Image not present anymore in image list.
|
||||
std::cout << "ImageManager: " << name << " is not available anymore."
|
||||
<< std::endl;
|
||||
*oldTexture = *badTexture;
|
||||
}
|
||||
|
||||
std::shared_ptr<OpenGLTextureWrapper> ImageManager::GetOpenGLTexture(
|
||||
const gd::String& name) const {
|
||||
if (alreadyLoadedOpenGLTextures.find(name) !=
|
||||
alreadyLoadedOpenGLTextures.end() &&
|
||||
!alreadyLoadedOpenGLTextures.find(name)->second.expired())
|
||||
return alreadyLoadedOpenGLTextures.find(name)->second.lock();
|
||||
|
||||
std::cout << "Load OpenGL Texture" << name << std::endl;
|
||||
|
||||
std::shared_ptr<OpenGLTextureWrapper> texture =
|
||||
std::make_shared<OpenGLTextureWrapper>(GetSFMLTexture(name));
|
||||
alreadyLoadedOpenGLTextures[name] = texture;
|
||||
return texture;
|
||||
}
|
||||
|
||||
void ImageManager::LoadPermanentImages() {
|
||||
if (!resourcesManager) {
|
||||
std::cout << "ImageManager has no ResourcesManager associated with.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new list of permanently loaded images but do not delete now the
|
||||
// old list so as not to unload images that could be still present.
|
||||
std::map<gd::String, std::shared_ptr<SFMLTextureWrapper> >
|
||||
newPermanentlyLoadedImages;
|
||||
|
||||
std::vector<gd::String> resources = resourcesManager->GetAllResourceNames();
|
||||
for (std::size_t i = 0; i < resources.size(); i++) {
|
||||
try {
|
||||
ImageResource& image = dynamic_cast<ImageResource&>(
|
||||
resourcesManager->GetResource(resources[i]));
|
||||
|
||||
if (image.alwaysLoaded)
|
||||
newPermanentlyLoadedImages[image.GetName()] =
|
||||
GetSFMLTexture(image.GetName());
|
||||
} catch (...) { /*The resource is not an image, we don't care about it.*/
|
||||
}
|
||||
}
|
||||
|
||||
permanentlyLoadedImages = newPermanentlyLoadedImages;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
void ImageManager::PreventImagesUnloading() {
|
||||
preventUnloading = true;
|
||||
for (auto it = alreadyLoadedImages.begin(); it != alreadyLoadedImages.end();
|
||||
++it) {
|
||||
std::shared_ptr<SFMLTextureWrapper> image = (it->second).lock();
|
||||
if (image != std::shared_ptr<SFMLTextureWrapper>())
|
||||
unloadingPreventer.push_back(image);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageManager::EnableImagesUnloading() {
|
||||
preventUnloading = false;
|
||||
unloadingPreventer
|
||||
.clear(); // Images which are not used anymore will thus be destroyed (As
|
||||
// no shared pointer will be pointing to them).
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace gd
|
||||
|
||||
SFMLTextureWrapper::SFMLTextureWrapper(const sf::Texture& texture_)
|
||||
: texture(texture_), image(texture.copyToImage()) {}
|
||||
|
||||
SFMLTextureWrapper::SFMLTextureWrapper() {}
|
||||
|
||||
SFMLTextureWrapper::~SFMLTextureWrapper() {}
|
||||
|
||||
OpenGLTextureWrapper::OpenGLTextureWrapper(
|
||||
std::shared_ptr<SFMLTextureWrapper> sfmlTexture_) {
|
||||
sfmlTexture = sfmlTexture_;
|
||||
|
||||
#if !defined(ANDROID) // TODO: OpenGL
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sfmlTexture->image.getSize().x,
|
||||
// sfmlTexture->image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
// sfmlTexture->image.getPixelsPtr()); glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(
|
||||
GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
#endif
|
||||
}
|
||||
|
||||
OpenGLTextureWrapper::~OpenGLTextureWrapper() {
|
||||
#if !defined(ANDROID) // TODO: OpenGL
|
||||
glDeleteTextures(1, &texture);
|
||||
#endif
|
||||
};
|
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef ImageManager_H
|
||||
#define ImageManager_H
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <SFML/OpenGL.hpp>
|
||||
#include <SFML/System.hpp>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "GDCore/String.h"
|
||||
namespace gd {
|
||||
class ResourcesManager;
|
||||
}
|
||||
class OpenGLTextureWrapper;
|
||||
class SFMLTextureWrapper;
|
||||
#undef LoadImage // thx windows.h
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief Manage images for the IDE as well as at runtime for GD C++ Platform,
|
||||
* providing an easy way to get SFML images or OpenGL textures.
|
||||
*
|
||||
* Image manager is used by objects to obtain their images from the image name.
|
||||
*
|
||||
* Images are loaded dynamically when necessary, and are unloaded if there is no
|
||||
* more shared_ptr pointing on an image.
|
||||
*
|
||||
* You should in particular be interested by gd::ImageManager::GetOpenGLTexture
|
||||
* and gd::ImageManager::GetSFMLTexture.
|
||||
*
|
||||
* \see SFMLTextureWrapper
|
||||
* \see OpenGLTextureWrapper
|
||||
*
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API ImageManager {
|
||||
public:
|
||||
ImageManager();
|
||||
virtual ~ImageManager(){};
|
||||
|
||||
/**
|
||||
* \brief Get a shared pointer to an OpenGL texture. The shared pointer must
|
||||
* be kept alive as long as the texture is used.
|
||||
*/
|
||||
std::shared_ptr<OpenGLTextureWrapper> GetOpenGLTexture(
|
||||
const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Get a shared pointer to a SFML texture. The shared pointer must be
|
||||
* kept alive as long as the texture is used.
|
||||
*
|
||||
* For example, if the texture is used in an object, you should store the
|
||||
* shared pointer in a member to make sure the texture is available as long as
|
||||
* the object is alive.
|
||||
*/
|
||||
std::shared_ptr<SFMLTextureWrapper> GetSFMLTexture(
|
||||
const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Set the gd::ResourcesManager used by the ImageManager.
|
||||
*/
|
||||
void SetResourcesManager(gd::ResourcesManager* resourcesManager_) {
|
||||
resourcesManager = resourcesManager_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Load all images of the project which are flagged as alwaysLoaded.
|
||||
* \see ImageResource
|
||||
*/
|
||||
void LoadPermanentImages();
|
||||
|
||||
/**
|
||||
* \brief Check if a SFML texture with the specified name is available and
|
||||
* loaded in memory. \return true if the texture called \a name if available
|
||||
* and loaded in memory.
|
||||
*/
|
||||
bool HasLoadedSFMLTexture(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* \brief Add the SFMLTextureWrapper to loaded images ( so that it can be
|
||||
* accessed thanks to ImageManager::GetSFMLTexture ) with the specified name
|
||||
* and mark it as permanently loaded ( so that is is unloaded only when the
|
||||
* layout is unloaded ).
|
||||
*/
|
||||
void SetSFMLTextureAsPermanentlyLoaded(
|
||||
const gd::String& name,
|
||||
std::shared_ptr<SFMLTextureWrapper>& texture) const;
|
||||
|
||||
/**
|
||||
* \brief Reload a single image from the game resources
|
||||
*/
|
||||
void ReloadImage(const gd::String& name) const;
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* \brief When called, images won't be unloaded from memory until
|
||||
* EnableImagesUnloading is called. Can be used when reloading a layout so as
|
||||
* to prevent images from being unloaded and then immediately reloaded.
|
||||
*/
|
||||
void PreventImagesUnloading();
|
||||
|
||||
/**
|
||||
* \brief Enable again unused images to be unloaded from memory.
|
||||
*/
|
||||
void EnableImagesUnloading();
|
||||
#endif
|
||||
|
||||
private:
|
||||
mutable std::map<gd::String, std::weak_ptr<SFMLTextureWrapper> >
|
||||
alreadyLoadedImages; ///< Reference all images loaded in memory.
|
||||
mutable std::map<gd::String, std::shared_ptr<SFMLTextureWrapper> >
|
||||
permanentlyLoadedImages; ///< Contains (smart) pointers to images which
|
||||
///< should stay loaded even if they are not
|
||||
///< (currently) used.
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
|
||||
/** This list is filled, when PreventImagesUnloading is called, with images
|
||||
* already loaded in memory ( and any image loaded after the call to
|
||||
* PreventImagesUnloading ). It will thus prevent these images from being
|
||||
* unloaded. This list is destroyed when EnableImagesUnloading is called.
|
||||
*
|
||||
* \see PreventImagesUnloading
|
||||
* \see EnableImagesUnloading
|
||||
*/
|
||||
mutable std::vector<std::shared_ptr<SFMLTextureWrapper> > unloadingPreventer;
|
||||
bool preventUnloading; ///< True if no images must be currently unloaded.
|
||||
#endif
|
||||
|
||||
mutable std::map<gd::String, std::weak_ptr<OpenGLTextureWrapper> >
|
||||
alreadyLoadedOpenGLTextures; ///< Reference all OpenGL textures loaded in
|
||||
///< memory.
|
||||
|
||||
mutable std::shared_ptr<SFMLTextureWrapper> badTexture;
|
||||
mutable std::shared_ptr<OpenGLTextureWrapper> badOpenGLTexture;
|
||||
|
||||
gd::ResourcesManager* resourcesManager;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
|
||||
/**
|
||||
* \brief Class wrapping an SFML texture.
|
||||
*
|
||||
* \see gd::ImageManager
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API SFMLTextureWrapper {
|
||||
public:
|
||||
SFMLTextureWrapper(const sf::Texture& texture);
|
||||
SFMLTextureWrapper();
|
||||
~SFMLTextureWrapper();
|
||||
|
||||
sf::Texture texture;
|
||||
sf::Image image; ///< Associated sfml image, used for pixel perfect collision
|
||||
///< for example. If you update the image, call
|
||||
///< LoadFromImage on texture to update it also.
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class wrapping an OpenGL texture.
|
||||
*
|
||||
* \see gd::ImageManager
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API OpenGLTextureWrapper {
|
||||
public:
|
||||
OpenGLTextureWrapper(std::shared_ptr<SFMLTextureWrapper> sfmlTexture_);
|
||||
OpenGLTextureWrapper() : texture(0){};
|
||||
~OpenGLTextureWrapper();
|
||||
inline GLuint GetOpenGLTexture() const { return texture; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<SFMLTextureWrapper> sfmlTexture;
|
||||
GLuint texture;
|
||||
};
|
||||
|
||||
#endif // ImageManager_H
|
@@ -4,6 +4,7 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Project/Layer.h"
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Project/Effect.h"
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
@@ -11,9 +12,9 @@
|
||||
namespace gd {
|
||||
|
||||
Camera Layer::badCamera;
|
||||
Effect Layer::badEffect;
|
||||
|
||||
Layer::Layer() : isVisible(true), isLightingLayer(false), followBaseLayerCamera(false) {}
|
||||
Layer::Layer()
|
||||
: isVisible(true), isLightingLayer(false), followBaseLayerCamera(false) {}
|
||||
|
||||
/**
|
||||
* Change cameras count, automatically adding/removing them.
|
||||
@@ -52,11 +53,7 @@ void Layer::SerializeTo(SerializerElement& element) const {
|
||||
}
|
||||
|
||||
SerializerElement& effectsElement = element.AddChild("effects");
|
||||
effectsElement.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < GetEffectsCount(); ++i) {
|
||||
SerializerElement& effectElement = effectsElement.AddChild("effect");
|
||||
GetEffect(i).SerializeTo(effectElement);
|
||||
}
|
||||
effectsContainer.SerializeTo(effectsElement);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -67,155 +64,53 @@ void Layer::UnserializeFrom(const SerializerElement& element) {
|
||||
SetName(element.GetStringAttribute("name", "", "Name"));
|
||||
SetVisibility(element.GetBoolAttribute("visibility", true, "Visibility"));
|
||||
SetLightingLayer(element.GetBoolAttribute("isLightingLayer", false));
|
||||
SetFollowBaseLayerCamera(element.GetBoolAttribute("followBaseLayerCamera", false));
|
||||
SetAmbientLightColor(element.GetIntAttribute("ambientLightColorR", 200),
|
||||
SetFollowBaseLayerCamera(
|
||||
element.GetBoolAttribute("followBaseLayerCamera", false));
|
||||
SetAmbientLightColor(element.GetIntAttribute("ambientLightColorR", 200),
|
||||
element.GetIntAttribute("ambientLightColorG", 200),
|
||||
element.GetIntAttribute("ambientLightColorB", 200));
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (element.HasChild("Camera")) {
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount("Camera"); ++i) {
|
||||
const SerializerElement& cameraElement = element.GetChild("Camera", i);
|
||||
SetCameraCount(GetCameraCount() + 1);
|
||||
Camera& camera = GetCamera(GetCameraCount() - 1);
|
||||
cameras.clear();
|
||||
SerializerElement& camerasElement = element.GetChild("cameras");
|
||||
camerasElement.ConsiderAsArrayOf("camera");
|
||||
for (std::size_t i = 0; i < camerasElement.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& cameraElement = camerasElement.GetChild(i);
|
||||
|
||||
camera.SetUseDefaultSize(
|
||||
cameraElement.GetBoolAttribute("DefaultSize", true));
|
||||
camera.SetSize(cameraElement.GetDoubleAttribute("Width"),
|
||||
cameraElement.GetDoubleAttribute("Height"));
|
||||
Camera camera;
|
||||
camera.SetUseDefaultSize(
|
||||
cameraElement.GetBoolAttribute("defaultSize", true));
|
||||
camera.SetSize(cameraElement.GetDoubleAttribute("width"),
|
||||
cameraElement.GetDoubleAttribute("height"));
|
||||
camera.SetUseDefaultViewport(
|
||||
cameraElement.GetBoolAttribute("defaultViewport", true));
|
||||
camera.SetViewport(
|
||||
cameraElement.GetDoubleAttribute("viewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("viewportTop"),
|
||||
cameraElement.GetDoubleAttribute("viewportRight"),
|
||||
cameraElement.GetDoubleAttribute(
|
||||
"viewportBottom"));
|
||||
|
||||
camera.SetUseDefaultViewport(
|
||||
cameraElement.GetBoolAttribute("DefaultViewport", true));
|
||||
camera.SetViewport(
|
||||
cameraElement.GetDoubleAttribute("ViewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("ViewportTop"),
|
||||
cameraElement.GetDoubleAttribute("ViewportRight"),
|
||||
cameraElement.GetDoubleAttribute(
|
||||
"ViewportBottom")); // (sf::Rect used Right and Bottom instead of
|
||||
// Width and Height before)
|
||||
}
|
||||
}
|
||||
// End of compatibility code
|
||||
else {
|
||||
SerializerElement& camerasElement = element.GetChild("cameras");
|
||||
camerasElement.ConsiderAsArrayOf("camera");
|
||||
for (std::size_t i = 0; i < camerasElement.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& cameraElement = camerasElement.GetChild(i);
|
||||
|
||||
SetCameraCount(GetCameraCount() + 1);
|
||||
Camera& camera = GetCamera(GetCameraCount() - 1);
|
||||
|
||||
camera.SetUseDefaultSize(
|
||||
cameraElement.GetBoolAttribute("defaultSize", true));
|
||||
camera.SetSize(cameraElement.GetDoubleAttribute("width"),
|
||||
cameraElement.GetDoubleAttribute("height"));
|
||||
|
||||
camera.SetUseDefaultViewport(
|
||||
cameraElement.GetBoolAttribute("defaultViewport", true));
|
||||
camera.SetViewport(
|
||||
cameraElement.GetDoubleAttribute("viewportLeft"),
|
||||
cameraElement.GetDoubleAttribute("viewportTop"),
|
||||
cameraElement.GetDoubleAttribute("viewportRight"),
|
||||
cameraElement.GetDoubleAttribute(
|
||||
"viewportBottom")); // (sf::Rect used Right and Bottom instead of
|
||||
// Width and Height before)
|
||||
}
|
||||
cameras.push_back(camera);
|
||||
}
|
||||
|
||||
effects.clear();
|
||||
SerializerElement& effectsElement = element.GetChild("effects");
|
||||
effectsElement.ConsiderAsArrayOf("effect");
|
||||
for (std::size_t i = 0; i < effectsElement.GetChildrenCount(); ++i) {
|
||||
const SerializerElement& effectElement = effectsElement.GetChild(i);
|
||||
|
||||
auto effect = std::make_shared<Effect>();
|
||||
effect->UnserializeFrom(effectElement);
|
||||
effects.push_back(effect);
|
||||
if (camerasElement.GetChildrenCount() > 50) {
|
||||
// Highly unlikely that we want as many cameras, as they were not even exposed in
|
||||
// the editor nor used in the game engine. Must be because of a bug in the editor that
|
||||
// duplicated cameras when cancelling changes on a layer.
|
||||
// Reset to one camera.
|
||||
SetCameraCount(1);
|
||||
}
|
||||
|
||||
const SerializerElement& effectsElement = element.GetChild("effects");
|
||||
effectsContainer.UnserializeFrom(effectsElement);
|
||||
}
|
||||
|
||||
gd::Effect& Layer::GetEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
const gd::Effect& Layer::GetEffect(const gd::String& name) const {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
|
||||
if (effect != effects.end()) return **effect;
|
||||
|
||||
return badEffect;
|
||||
}
|
||||
gd::Effect& Layer::GetEffect(std::size_t index) { return *effects[index]; }
|
||||
const gd::Effect& Layer::GetEffect(std::size_t index) const {
|
||||
return *effects[index];
|
||||
}
|
||||
std::size_t Layer::GetEffectsCount() const { return effects.size(); }
|
||||
|
||||
bool Layer::HasEffectNamed(const gd::String& name) const {
|
||||
return (find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
}) != effects.end());
|
||||
}
|
||||
std::size_t Layer::GetEffectPosition(const gd::String& name) const {
|
||||
for (std::size_t i = 0; i < effects.size(); ++i) {
|
||||
if (effects[i]->GetName() == name) return i;
|
||||
}
|
||||
return gd::String::npos;
|
||||
gd::EffectsContainer& Layer::GetEffects() {
|
||||
return effectsContainer;
|
||||
}
|
||||
|
||||
gd::Effect& Layer::InsertNewEffect(const gd::String& name,
|
||||
std::size_t position) {
|
||||
auto newEffect = std::make_shared<Effect>();
|
||||
newEffect->SetName(name);
|
||||
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
|
||||
return *newEffect;
|
||||
}
|
||||
|
||||
void Layer::InsertEffect(const gd::Effect& effect, std::size_t position) {
|
||||
auto newEffect = std::make_shared<gd::Effect>(effect);
|
||||
if (position < effects.size())
|
||||
effects.insert(effects.begin() + position, newEffect);
|
||||
else
|
||||
effects.push_back(newEffect);
|
||||
}
|
||||
|
||||
void Layer::RemoveEffect(const gd::String& name) {
|
||||
auto effect = find_if(effects.begin(),
|
||||
effects.end(),
|
||||
[&name](const std::shared_ptr<gd::Effect>& effect) {
|
||||
return effect->GetName() == name;
|
||||
});
|
||||
if (effect == effects.end()) return;
|
||||
|
||||
effects.erase(effect);
|
||||
}
|
||||
|
||||
void Layer::SwapEffects(std::size_t firstEffectIndex,
|
||||
std::size_t secondEffectIndex) {
|
||||
if (firstEffectIndex >= effects.size() || secondEffectIndex >= effects.size())
|
||||
return;
|
||||
|
||||
auto temp = effects[firstEffectIndex];
|
||||
effects[firstEffectIndex] = effects[secondEffectIndex];
|
||||
effects[secondEffectIndex] = temp;
|
||||
const gd::EffectsContainer& Layer::GetEffects() const {
|
||||
return effectsContainer;
|
||||
}
|
||||
|
||||
Camera::Camera()
|
||||
|
@@ -7,7 +7,10 @@
|
||||
#define GDCORE_LAYER_H
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "EffectsContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
|
||||
namespace gd {
|
||||
class Effect;
|
||||
}
|
||||
@@ -17,6 +20,9 @@ class Camera;
|
||||
namespace gd {
|
||||
class SerializerElement;
|
||||
}
|
||||
namespace gd {
|
||||
class EffectsContainer;
|
||||
}
|
||||
|
||||
namespace gd {
|
||||
|
||||
@@ -54,7 +60,9 @@ class GD_CORE_API Layer {
|
||||
/**
|
||||
* \brief Set if the layer is a lightining layer or not.
|
||||
*/
|
||||
void SetLightingLayer(bool isLightingLayer_) { isLightingLayer = isLightingLayer_; }
|
||||
void SetLightingLayer(bool isLightingLayer_) {
|
||||
isLightingLayer = isLightingLayer_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the layer is a lighting layer.
|
||||
@@ -64,7 +72,9 @@ class GD_CORE_API Layer {
|
||||
/**
|
||||
* \brief Set if the layer automatically follows the base layer or not.
|
||||
*/
|
||||
void SetFollowBaseLayerCamera(bool followBaseLayerCamera_) { followBaseLayerCamera = followBaseLayerCamera_; }
|
||||
void SetFollowBaseLayerCamera(bool followBaseLayerCamera_) {
|
||||
followBaseLayerCamera = followBaseLayerCamera_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return true if the layer follows the base layer.
|
||||
@@ -144,66 +154,14 @@ class GD_CORE_API Layer {
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Return true if the effect called "name" exists.
|
||||
* \brief Return the effects container.
|
||||
*/
|
||||
bool HasEffectNamed(const gd::String& name) const;
|
||||
EffectsContainer& GetEffects();
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
* \brief Return a const reference to the effects container.
|
||||
*/
|
||||
Effect& GetEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the effect called "name".
|
||||
*/
|
||||
const Effect& GetEffect(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
Effect& GetEffect(std::size_t index);
|
||||
|
||||
/**
|
||||
* Return a reference to the effect at position "index" in the effects list
|
||||
*/
|
||||
const Effect& GetEffect(std::size_t index) const;
|
||||
|
||||
/**
|
||||
* Return the position of the effect called "name" in the effects list
|
||||
*/
|
||||
std::size_t GetEffectPosition(const gd::String& name) const;
|
||||
|
||||
/**
|
||||
* Return the number of effecst.
|
||||
*/
|
||||
std::size_t GetEffectsCount() const;
|
||||
|
||||
/**
|
||||
* Add a new effect at the specified position in the effects list.
|
||||
*/
|
||||
gd::Effect& InsertNewEffect(const gd::String& name, std::size_t position);
|
||||
|
||||
/**
|
||||
* \brief Add a copy of the specified effect in the effects list.
|
||||
*
|
||||
* \note No pointer or reference must be kept on the layer passed as
|
||||
* parameter.
|
||||
*
|
||||
* \param theEffect The effect that must be copied and inserted
|
||||
* into the effects list
|
||||
* \param position Insertion position.
|
||||
*/
|
||||
void InsertEffect(const Effect& theEffect, std::size_t position);
|
||||
|
||||
/**
|
||||
* Remove the specified effect.
|
||||
*/
|
||||
void RemoveEffect(const gd::String& name);
|
||||
|
||||
/**
|
||||
* Swap the position of two effects.
|
||||
*/
|
||||
void SwapEffects(std::size_t firstEffectIndex, std::size_t secondEffectIndex);
|
||||
const EffectsContainer& GetEffects() const;
|
||||
///@}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
@@ -219,19 +177,19 @@ class GD_CORE_API Layer {
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
|
||||
private:
|
||||
gd::String name; ///< The name of the layer
|
||||
bool isVisible; ///< True if the layer is visible
|
||||
bool isLightingLayer; ///< True if the layer is used to display lights and renders an ambient light.
|
||||
bool followBaseLayerCamera; ///< True if the layer automatically follows the base layer
|
||||
unsigned int ambientLightColorR; ///< Ambient light color Red component
|
||||
unsigned int ambientLightColorG; ///< Ambient light color Green component
|
||||
unsigned int ambientLightColorB; ///< Ambient light color Blue component
|
||||
gd::String name; ///< The name of the layer
|
||||
bool isVisible; ///< True if the layer is visible
|
||||
bool isLightingLayer; ///< True if the layer is used to display lights and
|
||||
///< renders an ambient light.
|
||||
bool followBaseLayerCamera; ///< True if the layer automatically follows the
|
||||
///< base layer
|
||||
unsigned int ambientLightColorR; ///< Ambient light color Red component
|
||||
unsigned int ambientLightColorG; ///< Ambient light color Green component
|
||||
unsigned int ambientLightColorB; ///< Ambient light color Blue component
|
||||
std::vector<gd::Camera> cameras; ///< The camera displayed by the layer
|
||||
std::vector<std::shared_ptr<gd::Effect>>
|
||||
effects; ///< The effects applied to the layer.
|
||||
gd::EffectsContainer effectsContainer; ///< The effects applied to the layer.
|
||||
|
||||
static gd::Camera badCamera;
|
||||
static gd::Effect badEffect;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -5,10 +5,14 @@
|
||||
*/
|
||||
|
||||
#include "Layout.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/CommonTools.h"
|
||||
#include "GDCore/Events/Serialization.h"
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/IDE/SceneNameMangler.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
@@ -219,16 +223,21 @@ void Layout::UpdateBehaviorsSharedData(gd::Project& project) {
|
||||
++i) {
|
||||
const gd::String& name = allBehaviorsNames[i];
|
||||
|
||||
if (behaviorsSharedData.find(name) == behaviorsSharedData.end()) {
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
project.GetBehaviorSharedDatas(allBehaviorsTypes[i]);
|
||||
if (behaviorSharedData) {
|
||||
auto behaviorContent =
|
||||
gd::make_unique<gd::BehaviorContent>(name, allBehaviorsTypes[i]);
|
||||
behaviorSharedData->InitializeContent(behaviorContent->GetContent());
|
||||
behaviorsSharedData[name] = std::move(behaviorContent);
|
||||
}
|
||||
}
|
||||
if (behaviorsSharedData.find(name) != behaviorsSharedData.end()) continue;
|
||||
|
||||
const gd::BehaviorMetadata& behaviorMetadata =
|
||||
gd::MetadataProvider::GetBehaviorMetadata(project.GetCurrentPlatform(),
|
||||
allBehaviorsTypes[i]);
|
||||
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) continue;
|
||||
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
behaviorMetadata.GetSharedDataInstance();
|
||||
if (!behaviorSharedData) continue;
|
||||
|
||||
auto behaviorContent =
|
||||
gd::make_unique<gd::BehaviorContent>(name, allBehaviorsTypes[i]);
|
||||
behaviorSharedData->InitializeContent(behaviorContent->GetContent());
|
||||
behaviorsSharedData[name] = std::move(behaviorContent);
|
||||
}
|
||||
|
||||
// Remove useless shared data:
|
||||
@@ -263,7 +272,7 @@ void Layout::SerializeTo(SerializerElement& element) const {
|
||||
disableInputWhenNotFocused);
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
GetAssociatedSettings().SerializeTo(element.AddChild("uiSettings"));
|
||||
editorSettings.SerializeTo(element.AddChild("uiSettings"));
|
||||
#endif
|
||||
|
||||
GetObjectGroups().SerializeTo(element.AddChild("objectsGroups"));
|
||||
@@ -324,7 +333,7 @@ void Layout::UnserializeFrom(gd::Project& project,
|
||||
element.GetBoolAttribute("disableInputWhenNotFocused");
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
associatedSettings.UnserializeFrom(
|
||||
editorSettings.UnserializeFrom(
|
||||
element.GetChild("uiSettings", 0, "UISettings"));
|
||||
|
||||
GetObjectGroups().UnserializeFrom(
|
||||
@@ -403,7 +412,7 @@ void Layout::Init(const Layout& other) {
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
events = other.events;
|
||||
associatedSettings = other.associatedSettings;
|
||||
editorSettings = other.editorSettings;
|
||||
objectGroups = other.objectGroups;
|
||||
|
||||
profiler = other.profiler;
|
||||
|
@@ -18,7 +18,7 @@
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#if defined(GD_IDE_ONLY)
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/LayoutEditorCanvasOptions.h"
|
||||
#include "GDCore/IDE/Dialogs/LayoutEditorCanvas/EditorSettings.h"
|
||||
#endif
|
||||
namespace gd {
|
||||
class BaseEvent;
|
||||
@@ -291,18 +291,18 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* Return the settings associated to the layout.
|
||||
* \see gd::LayoutEditorCanvasOptions
|
||||
* \see gd::EditorSettings
|
||||
*/
|
||||
const gd::LayoutEditorCanvasOptions& GetAssociatedSettings() const {
|
||||
return associatedSettings;
|
||||
const gd::EditorSettings& GetAssociatedEditorSettings() const {
|
||||
return editorSettings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the settings associated to the layout.
|
||||
* \see gd::LayoutEditorCanvasOptions
|
||||
* \see gd::EditorSettings
|
||||
*/
|
||||
gd::LayoutEditorCanvasOptions& GetAssociatedSettings() {
|
||||
return associatedSettings;
|
||||
gd::EditorSettings& GetAssociatedEditorSettings() {
|
||||
return editorSettings;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -436,7 +436,7 @@ class GD_CORE_API Layout : public ObjectsContainer {
|
||||
///< specified behavior shared data.
|
||||
#if defined(GD_IDE_ONLY)
|
||||
EventsList events; ///< Scene events
|
||||
gd::LayoutEditorCanvasOptions associatedSettings;
|
||||
gd::EditorSettings editorSettings;
|
||||
#endif
|
||||
|
||||
// TODO: GD C++ Platform specific code below
|
||||
|
@@ -5,15 +5,63 @@
|
||||
*/
|
||||
|
||||
#include "LoadingScreen.h"
|
||||
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
|
||||
namespace gd {
|
||||
|
||||
LoadingScreen::LoadingScreen()
|
||||
: showGDevelopSplash(true),
|
||||
gdevelopLogoStyle("light"),
|
||||
backgroundImageResourceName(""),
|
||||
backgroundColor(0),
|
||||
backgroundFadeInDuration(0.2),
|
||||
minDuration(1.5),
|
||||
logoAndProgressFadeInDuration(0.2),
|
||||
logoAndProgressLogoFadeInDelay(0.2),
|
||||
showProgressBar(true),
|
||||
progressBarMinWidth(40),
|
||||
progressBarMaxWidth(200),
|
||||
progressBarWidthPercent(30),
|
||||
progressBarHeight(20),
|
||||
progressBarColor(0xFFFFFF){};
|
||||
|
||||
void LoadingScreen::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("showGDevelopSplash", showGDevelopSplash);
|
||||
element.SetAttribute("gdevelopLogoStyle",
|
||||
gdevelopLogoStyle);
|
||||
element.SetAttribute("backgroundImageResourceName",
|
||||
backgroundImageResourceName);
|
||||
element.SetAttribute("backgroundColor", backgroundColor);
|
||||
element.SetAttribute("backgroundFadeInDuration", backgroundFadeInDuration);
|
||||
element.SetAttribute("minDuration", minDuration);
|
||||
element.SetAttribute("logoAndProgressFadeInDuration", logoAndProgressFadeInDuration);
|
||||
element.SetAttribute("logoAndProgressLogoFadeInDelay", logoAndProgressLogoFadeInDelay);
|
||||
element.SetAttribute("showProgressBar", showProgressBar);
|
||||
element.SetAttribute("progressBarMinWidth", progressBarMinWidth);
|
||||
element.SetAttribute("progressBarMaxWidth", progressBarMaxWidth);
|
||||
element.SetAttribute("progressBarWidthPercent", progressBarWidthPercent);
|
||||
element.SetAttribute("progressBarHeight", progressBarHeight);
|
||||
element.SetAttribute("progressBarColor", progressBarColor);
|
||||
}
|
||||
|
||||
void LoadingScreen::UnserializeFrom(const SerializerElement& element) {
|
||||
showGDevelopSplash = element.GetBoolAttribute("showGDevelopSplash", true);
|
||||
gdevelopLogoStyle =
|
||||
element.GetStringAttribute("gdevelopLogoStyle", "light");
|
||||
backgroundImageResourceName =
|
||||
element.GetStringAttribute("backgroundImageResourceName");
|
||||
backgroundColor = element.GetIntAttribute("backgroundColor", 0);
|
||||
backgroundFadeInDuration =
|
||||
element.GetDoubleAttribute("backgroundFadeInDuration", 0.2);
|
||||
minDuration = element.GetDoubleAttribute("minDuration", 1.5);
|
||||
logoAndProgressFadeInDuration = element.GetDoubleAttribute("logoAndProgressFadeInDuration", 0.2);
|
||||
logoAndProgressLogoFadeInDelay = element.GetDoubleAttribute("logoAndProgressLogoFadeInDelay", 0.2);
|
||||
showProgressBar = element.GetBoolAttribute("showProgressBar", true);
|
||||
progressBarMinWidth = element.GetDoubleAttribute("progressBarMinWidth", 40);
|
||||
progressBarMaxWidth = element.GetDoubleAttribute("progressBarMaxWidth", 200);
|
||||
progressBarWidthPercent = element.GetDoubleAttribute("progressBarWidthPercent", 30);
|
||||
progressBarHeight = element.GetDoubleAttribute("progressBarHeight", 20);
|
||||
progressBarColor = element.GetIntAttribute("progressBarColor", 0xFFFFFF);
|
||||
}
|
||||
} // namespace gd
|
||||
|
@@ -22,36 +22,151 @@ namespace gd {
|
||||
*/
|
||||
class GD_CORE_API LoadingScreen {
|
||||
public:
|
||||
LoadingScreen(){};
|
||||
LoadingScreen();
|
||||
virtual ~LoadingScreen(){};
|
||||
|
||||
/**
|
||||
* \brief Set if the GDevelop splash should be shown while loading assets.
|
||||
*/
|
||||
void ShowGDevelopSplash(bool show) { showGDevelopSplash = show; };
|
||||
|
||||
/**
|
||||
* \brief Return true if the GDevelop splash should be shown while loading
|
||||
* \brief Return true if the GDevelop logo should be shown while loading
|
||||
* assets.
|
||||
*/
|
||||
bool IsGDevelopSplashShown() const { return showGDevelopSplash; };
|
||||
|
||||
/**
|
||||
* \brief Set if the GDevelop logo should be shown while loading assets.
|
||||
*/
|
||||
LoadingScreen& ShowGDevelopSplash(bool show) {
|
||||
showGDevelopSplash = show;
|
||||
return *this;
|
||||
};
|
||||
|
||||
const gd::String& GetGDevelopLogoStyle() const { return gdevelopLogoStyle; };
|
||||
|
||||
LoadingScreen& SetGDevelopLogoStyle(const gd::String& value) {
|
||||
gdevelopLogoStyle = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const gd::String& GetBackgroundImageResourceName() const {
|
||||
return backgroundImageResourceName;
|
||||
};
|
||||
|
||||
LoadingScreen& SetBackgroundImageResourceName(const gd::String& value) {
|
||||
backgroundImageResourceName = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int GetBackgroundColor() const { return backgroundColor; };
|
||||
|
||||
LoadingScreen& SetBackgroundColor(int value) {
|
||||
backgroundColor = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetBackgroundFadeInDuration() const {
|
||||
return backgroundFadeInDuration;
|
||||
};
|
||||
|
||||
LoadingScreen& SetBackgroundFadeInDuration(double value) {
|
||||
backgroundFadeInDuration = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetMinDuration() const { return minDuration; };
|
||||
|
||||
LoadingScreen& SetMinDuration(double value) {
|
||||
minDuration = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetLogoAndProgressFadeInDuration() const {
|
||||
return logoAndProgressFadeInDuration;
|
||||
}
|
||||
|
||||
LoadingScreen& SetLogoAndProgressFadeInDuration(double value) {
|
||||
logoAndProgressFadeInDuration = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetLogoAndProgressLogoFadeInDelay() const {
|
||||
return logoAndProgressLogoFadeInDelay;
|
||||
}
|
||||
|
||||
LoadingScreen& SetLogoAndProgressLogoFadeInDelay(double value) {
|
||||
logoAndProgressLogoFadeInDelay = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool GetShowProgressBar() const { return showProgressBar; }
|
||||
|
||||
LoadingScreen& SetShowProgressBar(bool value) {
|
||||
showProgressBar = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarMinWidth() const { return progressBarMinWidth; }
|
||||
|
||||
LoadingScreen& SetProgressBarMinWidth(double value) {
|
||||
progressBarMinWidth = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarMaxWidth() const { return progressBarMaxWidth; }
|
||||
|
||||
LoadingScreen& SetProgressBarMaxWidth(double value) {
|
||||
progressBarMaxWidth = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarWidthPercent() const { return progressBarWidthPercent; }
|
||||
|
||||
LoadingScreen& SetProgressBarWidthPercent(double value) {
|
||||
progressBarWidthPercent = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double GetProgressBarHeight() const { return progressBarHeight; }
|
||||
|
||||
LoadingScreen& SetProgressBarHeight(double value) {
|
||||
progressBarHeight = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int GetProgressBarColor() const { return progressBarColor; }
|
||||
|
||||
LoadingScreen& SetProgressBarColor(int value) {
|
||||
progressBarColor = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \name Saving and loading
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Serialize objects groups container.
|
||||
* \brief Serialize the loading screen setup.
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Unserialize the objects groups container.
|
||||
* \brief Unserialize the loading screen setup.
|
||||
*/
|
||||
void UnserializeFrom(const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
private:
|
||||
bool showGDevelopSplash;
|
||||
gd::String gdevelopLogoStyle;
|
||||
gd::String backgroundImageResourceName;
|
||||
int backgroundColor;
|
||||
double backgroundFadeInDuration; // In seconds.
|
||||
double minDuration; // In seconds.
|
||||
double logoAndProgressFadeInDuration; // In seconds.
|
||||
double logoAndProgressLogoFadeInDelay; // In seconds.
|
||||
bool showProgressBar;
|
||||
double progressBarMinWidth; // In pixels.
|
||||
double progressBarMaxWidth; // In pixels.
|
||||
double progressBarWidthPercent;
|
||||
double progressBarHeight; // In pixels.
|
||||
int progressBarColor;
|
||||
};
|
||||
} // namespace gd
|
||||
|
||||
|
@@ -70,12 +70,6 @@ class GD_CORE_API NamedPropertyDescriptor : public PropertyDescriptor {
|
||||
virtual void UnserializeValuesFrom(const SerializerElement& element);
|
||||
///@}
|
||||
|
||||
/**
|
||||
* Return a PropertyDescriptor from this NamedPropertyDescriptor,
|
||||
* slicing the name.
|
||||
*/
|
||||
PropertyDescriptor ToPropertyDescriptor() { return PropertyDescriptor(*this); }
|
||||
|
||||
private:
|
||||
gd::String name; ///< The name of the property.
|
||||
};
|
||||
|
@@ -4,6 +4,9 @@
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#include "GDCore/Project/Object.h"
|
||||
|
||||
#include "GDCore/Extensions/Metadata/BehaviorMetadata.h"
|
||||
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
|
||||
#include "GDCore/Extensions/Platform.h"
|
||||
#include "GDCore/Project/Behavior.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
@@ -24,6 +27,7 @@ void Object::Init(const gd::Object& object) {
|
||||
type = object.type;
|
||||
objectVariables = object.objectVariables;
|
||||
tags = object.tags;
|
||||
effectsContainer = object.effectsContainer;
|
||||
|
||||
behaviors.clear();
|
||||
for (auto& it : object.behaviors) {
|
||||
@@ -85,16 +89,17 @@ std::map<gd::String, gd::PropertyDescriptor> Object::GetProperties() const {
|
||||
gd::BehaviorContent* Object::AddNewBehavior(gd::Project& project,
|
||||
const gd::String& type,
|
||||
const gd::String& name) {
|
||||
gd::Behavior* behavior = project.GetCurrentPlatform().GetBehavior(type);
|
||||
|
||||
if (behavior) {
|
||||
auto behaviorContent = gd::make_unique<gd::BehaviorContent>(name, type);
|
||||
behavior->InitializeContent(behaviorContent->GetContent());
|
||||
behaviors[name] = std::move(behaviorContent);
|
||||
return behaviors[name].get();
|
||||
} else {
|
||||
const gd::BehaviorMetadata& behaviorMetadata =
|
||||
gd::MetadataProvider::GetBehaviorMetadata(project.GetCurrentPlatform(),
|
||||
type);
|
||||
if (gd::MetadataProvider::IsBadBehaviorMetadata(behaviorMetadata)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto behaviorContent = gd::make_unique<gd::BehaviorContent>(name, type);
|
||||
behaviorMetadata.Get().InitializeContent(behaviorContent->GetContent());
|
||||
behaviors[name] = std::move(behaviorContent);
|
||||
return behaviors[name].get();
|
||||
}
|
||||
|
||||
std::map<gd::String, gd::PropertyDescriptor>
|
||||
@@ -116,6 +121,11 @@ void Object::UnserializeFrom(gd::Project& project,
|
||||
element.GetChild("variables", 0, "Variables"));
|
||||
behaviors.clear();
|
||||
|
||||
if (element.HasChild("effects")) {
|
||||
const SerializerElement& effectsElement = element.GetChild("effects");
|
||||
effectsContainer.UnserializeFrom(effectsElement);
|
||||
}
|
||||
|
||||
// Compatibility with GD <= 3.3
|
||||
if (element.HasChild("Automatism")) {
|
||||
for (std::size_t i = 0; i < element.GetChildrenCount("Automatism"); ++i) {
|
||||
@@ -180,6 +190,7 @@ void Object::SerializeTo(SerializerElement& element) const {
|
||||
element.SetAttribute("type", GetType());
|
||||
element.SetAttribute("tags", GetTags());
|
||||
objectVariables.SerializeTo(element.AddChild("variables"));
|
||||
effectsContainer.SerializeTo(element.AddChild("effects"));
|
||||
|
||||
SerializerElement& behaviorsElement = element.AddChild("behaviors");
|
||||
behaviorsElement.ConsiderAsArrayOf("behavior");
|
||||
|
@@ -9,7 +9,9 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "GDCore/Project/BehaviorContent.h"
|
||||
#include "GDCore/Project/EffectsContainer.h"
|
||||
#include "GDCore/Project/VariablesContainer.h"
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/MakeUnique.h"
|
||||
@@ -20,6 +22,7 @@ class Layout;
|
||||
class ArbitraryResourceWorker;
|
||||
class InitialInstance;
|
||||
class SerializerElement;
|
||||
class EffectsContainer;
|
||||
} // namespace gd
|
||||
|
||||
namespace gd {
|
||||
@@ -146,8 +149,7 @@ class GD_CORE_API Object {
|
||||
*
|
||||
* \return false if the new value cannot be set
|
||||
*/
|
||||
virtual bool UpdateProperty(const gd::String& name,
|
||||
const gd::String& value) {
|
||||
virtual bool UpdateProperty(const gd::String& name, const gd::String& value) {
|
||||
return false;
|
||||
};
|
||||
///@}
|
||||
@@ -198,12 +200,12 @@ class GD_CORE_API Object {
|
||||
std::vector<gd::String> GetAllBehaviorNames() const;
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the behavior called \a name.
|
||||
* \brief Return a reference to the content of the behavior called \a name.
|
||||
*/
|
||||
BehaviorContent& GetBehavior(const gd::String& name);
|
||||
|
||||
/**
|
||||
* \brief Return a reference to the behavior called \a name.
|
||||
* \brief Return a reference to the content of the behavior called \a name.
|
||||
*/
|
||||
const BehaviorContent& GetBehavior(const gd::String& name) const;
|
||||
|
||||
@@ -270,6 +272,24 @@ class GD_CORE_API Object {
|
||||
* object variables
|
||||
*/
|
||||
gd::VariablesContainer& GetVariables() { return objectVariables; }
|
||||
///@}
|
||||
|
||||
/**
|
||||
* \name Effects management
|
||||
* Member functions related to effects management.
|
||||
*/
|
||||
///@{
|
||||
/**
|
||||
* \brief Provide access to the gd::EffectsContainer member containing the
|
||||
* effects.
|
||||
*/
|
||||
const gd::EffectsContainer& GetEffects() const { return effectsContainer; }
|
||||
|
||||
/**
|
||||
* \brief Provide access to the gd::EffectsContainer member containing the
|
||||
* effects.
|
||||
*/
|
||||
gd::EffectsContainer& GetEffects() { return effectsContainer; }
|
||||
///@}
|
||||
|
||||
/** \name Serialization
|
||||
@@ -301,7 +321,9 @@ class GD_CORE_API Object {
|
||||
///< object.
|
||||
gd::VariablesContainer
|
||||
objectVariables; ///< List of the variables of the object
|
||||
gd::String tags; ///< Comma-separated list of tags
|
||||
gd::String tags; ///< Comma-separated list of tags
|
||||
gd::EffectsContainer
|
||||
effectsContainer; ///< The effects container for the object.
|
||||
|
||||
/**
|
||||
* \brief Derived objects can redefine this method to load custom attributes.
|
||||
|
@@ -26,7 +26,6 @@
|
||||
#include "GDCore/Project/EventsFunctionsExtension.h"
|
||||
#include "GDCore/Project/ExternalEvents.h"
|
||||
#include "GDCore/Project/ExternalLayout.h"
|
||||
#include "GDCore/Project/ImageManager.h"
|
||||
#include "GDCore/Project/Layout.h"
|
||||
#include "GDCore/Project/Object.h"
|
||||
#include "GDCore/Project/ObjectGroupsContainer.h"
|
||||
@@ -64,26 +63,20 @@ Project::Project()
|
||||
minFPS(20),
|
||||
verticalSync(false),
|
||||
scaleMode("linear"),
|
||||
pixelsRounding(false),
|
||||
adaptGameResolutionAtRuntime(true),
|
||||
sizeOnStartupMode("adaptWidth"),
|
||||
projectUuid(""),
|
||||
useDeprecatedZeroAsDefaultZOrder(false),
|
||||
imageManager(std::make_shared<ImageManager>())
|
||||
useDeprecatedZeroAsDefaultZOrder(false)
|
||||
#if defined(GD_IDE_ONLY)
|
||||
,
|
||||
useExternalSourceFiles(false),
|
||||
currentPlatform(NULL),
|
||||
gdMajorVersion(gd::VersionWrapper::Major()),
|
||||
gdMinorVersion(gd::VersionWrapper::Minor()),
|
||||
gdBuildVersion(gd::VersionWrapper::Build()),
|
||||
dirty(false)
|
||||
gdBuildVersion(gd::VersionWrapper::Build())
|
||||
#endif
|
||||
{
|
||||
imageManager->SetResourcesManager(&resourcesManager);
|
||||
|
||||
#if !defined(GD_IDE_ONLY)
|
||||
platforms.push_back(&CppPlatform::Get());
|
||||
#endif
|
||||
}
|
||||
|
||||
Project::~Project() {}
|
||||
@@ -109,33 +102,6 @@ std::unique_ptr<gd::Object> Project::CreateObject(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gd::Behavior* Project::GetBehavior(const gd::String& type,
|
||||
const gd::String& platformName) {
|
||||
for (std::size_t i = 0; i < platforms.size(); ++i) {
|
||||
if (!platformName.empty() && platforms[i]->GetName() != platformName)
|
||||
continue;
|
||||
|
||||
gd::Behavior* behavior = platforms[i]->GetBehavior(type);
|
||||
if (behavior) return behavior;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gd::BehaviorsSharedData* Project::GetBehaviorSharedDatas(
|
||||
const gd::String& type, const gd::String& platformName) {
|
||||
for (std::size_t i = 0; i < platforms.size(); ++i) {
|
||||
if (!platformName.empty() && platforms[i]->GetName() != platformName)
|
||||
continue;
|
||||
|
||||
gd::BehaviorsSharedData* behaviorSharedData =
|
||||
platforms[i]->GetBehaviorSharedDatas(type);
|
||||
if (behaviorSharedData) return behaviorSharedData;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
std::shared_ptr<gd::BaseEvent> Project::CreateEvent(
|
||||
const gd::String& type, const gd::String& platformName) {
|
||||
@@ -515,8 +481,6 @@ void Project::ClearEventsFunctionsExtensions() {
|
||||
void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
// Checking version
|
||||
#if defined(GD_IDE_ONLY)
|
||||
gd::String updateText;
|
||||
|
||||
const SerializerElement& gdVersionElement =
|
||||
element.GetChild("gdVersion", 0, "GDVersion");
|
||||
gdMajorVersion =
|
||||
@@ -528,10 +492,10 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
|
||||
if (gdMajorVersion > gd::VersionWrapper::Major())
|
||||
gd::LogWarning(
|
||||
_("The version of GDevelop used to create this game seems to be a new "
|
||||
"version.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available."));
|
||||
"The version of GDevelop used to create this game seems to be a new "
|
||||
"version.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available.");
|
||||
else {
|
||||
if ((gdMajorVersion == gd::VersionWrapper::Major() &&
|
||||
gdMinorVersion > gd::VersionWrapper::Minor()) ||
|
||||
@@ -543,22 +507,12 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
gdBuildVersion == gd::VersionWrapper::Build() &&
|
||||
revision > gd::VersionWrapper::Revision())) {
|
||||
gd::LogWarning(
|
||||
_("The version of GDevelop used to create this game seems to be "
|
||||
"greater.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available."));
|
||||
"The version of GDevelop used to create this game seems to be "
|
||||
"greater.\nGDevelop may fail to open the game, or data may be "
|
||||
"missing.\nYou should check if a new version of GDevelop is "
|
||||
"available.");
|
||||
}
|
||||
}
|
||||
|
||||
// Compatibility code
|
||||
if (gdMajorVersion <= 1) {
|
||||
gd::LogError(_(
|
||||
"The game was saved with version of GDevelop which is too old. Please "
|
||||
"open and save the game with one of the first version of GDevelop 2. "
|
||||
"You will then be able to open your game with this GDevelop version."));
|
||||
return;
|
||||
}
|
||||
// End of Compatibility code
|
||||
#endif
|
||||
|
||||
const SerializerElement& propElement =
|
||||
@@ -575,6 +529,7 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
SetVerticalSyncActivatedByDefault(
|
||||
propElement.GetChild("verticalSync").GetValue().GetBool());
|
||||
SetScaleMode(propElement.GetStringAttribute("scaleMode", "linear"));
|
||||
SetPixelsRounding(propElement.GetBoolAttribute("pixelsRounding", false));
|
||||
SetAdaptGameResolutionAtRuntime(
|
||||
propElement.GetBoolAttribute("adaptGameResolutionAtRuntime", false));
|
||||
SetSizeOnStartupMode(propElement.GetStringAttribute("sizeOnStartupMode", ""));
|
||||
@@ -682,21 +637,6 @@ void Project::UnserializeFrom(const SerializerElement& element) {
|
||||
currentPlatform = platforms.back();
|
||||
#endif
|
||||
|
||||
// Compatibility code
|
||||
#if defined(GD_IDE_ONLY)
|
||||
if (VersionWrapper::IsOlder(gdMajorVersion, 0, 0, 0, 3, 0, 0, 0)) {
|
||||
updateText +=
|
||||
_("Sprite scaling has changed since GD 2: The resizing is made so that "
|
||||
"the origin point of the object won't move whatever the scale of the "
|
||||
"object.\n");
|
||||
updateText +=
|
||||
_("You may have to slightly change the position of some objects if you "
|
||||
"have changed their size.\n\n");
|
||||
updateText += _("Thank you for your understanding.\n");
|
||||
}
|
||||
#endif
|
||||
// End of Compatibility code
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
GetObjectGroups().UnserializeFrom(
|
||||
element.GetChild("objectsGroups", 0, "ObjectGroups"));
|
||||
@@ -802,6 +742,7 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
propElement.AddChild("verticalSync")
|
||||
.SetValue(IsVerticalSynchronizationEnabledByDefault());
|
||||
propElement.SetAttribute("scaleMode", scaleMode);
|
||||
propElement.SetAttribute("pixelsRounding", pixelsRounding);
|
||||
propElement.SetAttribute("adaptGameResolutionAtRuntime",
|
||||
adaptGameResolutionAtRuntime);
|
||||
propElement.SetAttribute("sizeOnStartupMode", sizeOnStartupMode);
|
||||
@@ -877,10 +818,6 @@ void Project::SerializeTo(SerializerElement& element) const {
|
||||
for (std::size_t i = 0; i < externalSourceFiles.size(); ++i)
|
||||
externalSourceFiles[i]->SerializeTo(
|
||||
externalSourceFilesElement.AddChild("sourceFile"));
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
dirty = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Project::ValidateName(const gd::String& name) {
|
||||
@@ -997,6 +934,7 @@ void Project::Init(const gd::Project& game) {
|
||||
minFPS = game.minFPS;
|
||||
verticalSync = game.verticalSync;
|
||||
scaleMode = game.scaleMode;
|
||||
pixelsRounding = game.pixelsRounding;
|
||||
adaptGameResolutionAtRuntime = game.adaptGameResolutionAtRuntime;
|
||||
sizeOnStartupMode = game.sizeOnStartupMode;
|
||||
projectUuid = game.projectUuid;
|
||||
@@ -1023,9 +961,7 @@ void Project::Init(const gd::Project& game) {
|
||||
platforms = game.platforms;
|
||||
|
||||
resourcesManager = game.resourcesManager;
|
||||
imageManager = std::make_shared<ImageManager>(*game.imageManager);
|
||||
imageManager->SetResourcesManager(&resourcesManager);
|
||||
|
||||
|
||||
initialObjects = gd::Clone(game.initialObjects);
|
||||
|
||||
scenes = gd::Clone(game.scenes);
|
||||
@@ -1047,7 +983,6 @@ void Project::Init(const gd::Project& game) {
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
projectFile = game.GetProjectFile();
|
||||
imagesChanged = game.imagesChanged;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -28,7 +28,6 @@ class Object;
|
||||
class VariablesContainer;
|
||||
class ArbitraryResourceWorker;
|
||||
class SourceFile;
|
||||
class ImageManager;
|
||||
class Behavior;
|
||||
class BehaviorsSharedData;
|
||||
class BaseEvent;
|
||||
@@ -277,6 +276,19 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
*/
|
||||
void SetScaleMode(const gd::String& scaleMode_) { scaleMode = scaleMode_; }
|
||||
|
||||
/**
|
||||
* Return true if pixels rounding option is enabled.
|
||||
*/
|
||||
bool GetPixelsRounding() const {
|
||||
return pixelsRounding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set pixels rounding option to true or false.
|
||||
*/
|
||||
void SetPixelsRounding(bool enable) { pixelsRounding = enable; }
|
||||
|
||||
|
||||
/**
|
||||
* \brief Return if the project should set 0 as Z-order for objects created
|
||||
* from events (which is deprecated) - instead of the highest Z order that was
|
||||
@@ -390,37 +402,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
const gd::String& name,
|
||||
const gd::String& platformName = "");
|
||||
|
||||
/**
|
||||
* Get the behavior of the given type.
|
||||
*
|
||||
* \note A project can use more than one platform. In this case, the first
|
||||
* platform supporting the behavior is used, unless \a platformName argument
|
||||
* is not empty.
|
||||
* It is assumed that each platform provides an equivalent
|
||||
* behavior.
|
||||
*
|
||||
* \param type The type of the behavior
|
||||
* \param platformName The name of the platform to be used. If empty, the
|
||||
* first platform supporting the object is used.
|
||||
*/
|
||||
gd::Behavior* GetBehavior(const gd::String& type,
|
||||
const gd::String& platformName = "");
|
||||
|
||||
/**
|
||||
* Get the behavior shared data of the given type.
|
||||
*
|
||||
* \note A project can use more than one platform. In this case, the first
|
||||
* platform supporting the behavior shared data is used, unless \a
|
||||
* platformName argument is not empty.
|
||||
* It is assumed that each platform provides equivalent behavior shared data.
|
||||
*
|
||||
* \param type The type of behavior
|
||||
* \param platformName The name of the platform to be used. If empty, the
|
||||
* first platform supporting the object is used.
|
||||
*/
|
||||
gd::BehaviorsSharedData* GetBehaviorSharedDatas(
|
||||
const gd::String& type, const gd::String& platformName = "");
|
||||
|
||||
#if defined(GD_IDE_ONLY)
|
||||
/**
|
||||
* Create an event of the given type.
|
||||
@@ -529,19 +510,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
*/
|
||||
void SerializeTo(SerializerElement& element) const;
|
||||
|
||||
/**
|
||||
* \brief Return true if the project is marked as being modified (The IDE or
|
||||
* application using the project should ask to save the project if the project
|
||||
* is closed).
|
||||
*/
|
||||
bool IsDirty() { return dirty; }
|
||||
|
||||
/**
|
||||
* \brief Mark the project as being modified (The IDE or application
|
||||
* using the project should ask to save the project if the project is closed).
|
||||
*/
|
||||
void SetDirty(bool enable = true) { dirty = enable; }
|
||||
|
||||
/**
|
||||
* Get the major version of GDevelop used to save the project.
|
||||
*/
|
||||
@@ -823,28 +791,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
*/
|
||||
ResourcesManager& GetResourcesManager() { return resourcesManager; }
|
||||
|
||||
/**
|
||||
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
|
||||
* textures for the IDE ( or at runtime for the GD C++ Platform ).
|
||||
*/
|
||||
const std::shared_ptr<gd::ImageManager>& GetImageManager() const {
|
||||
return imageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
|
||||
* textures for the IDE ( or at runtime for the GD C++ Platform ).
|
||||
*/
|
||||
std::shared_ptr<gd::ImageManager>& GetImageManager() { return imageManager; }
|
||||
|
||||
/**
|
||||
* \brief Provide access to the ImageManager allowing to load SFML or OpenGL
|
||||
* textures for the IDE ( or at runtime for the GD C++ Platform ).
|
||||
*/
|
||||
void SetImageManager(std::shared_ptr<gd::ImageManager> imageManager_) {
|
||||
imageManager = imageManager_;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Called ( e.g. during compilation ) so as to inventory internal
|
||||
* resources, sometimes update their filename or any other work or resources.
|
||||
@@ -941,12 +887,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
#endif
|
||||
///@}
|
||||
|
||||
// TODO: Put this in private part
|
||||
#if defined(GD_IDE_ONLY)
|
||||
std::vector<gd::String> imagesChanged; ///< Images that have been changed and
|
||||
///< which have to be reloaded
|
||||
#endif
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize from another game. Used by copy-ctor and assign-op.
|
||||
@@ -963,6 +903,8 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
///< are below this number )
|
||||
bool verticalSync; ///< If true, must activate vertical synchronization.
|
||||
gd::String scaleMode;
|
||||
bool pixelsRounding; ///< If true, the rendering should stop pixel interpolation
|
||||
///< of rendered objects.
|
||||
bool adaptGameResolutionAtRuntime; ///< Should the game resolution be adapted
|
||||
///< to the window size at runtime
|
||||
gd::String
|
||||
@@ -985,9 +927,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
#endif
|
||||
gd::ResourcesManager
|
||||
resourcesManager; ///< Contains all resources used by the project
|
||||
std::shared_ptr<gd::ImageManager>
|
||||
imageManager; ///< Image manager is accessed thanks to a (smart) ptr as
|
||||
///< it can be shared with GD C++ Platform projects.
|
||||
std::vector<gd::Platform*>
|
||||
platforms; ///< Pointers to the platforms this project supports.
|
||||
gd::String firstLayout;
|
||||
@@ -1018,7 +957,6 @@ class GD_CORE_API Project : public ObjectsContainer {
|
||||
///< time the project was saved.
|
||||
mutable unsigned int gdBuildVersion; ///< The GD build version used the last
|
||||
///< time the project was saved.
|
||||
mutable bool dirty; ///< True to flag the project as being modified.
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@@ -76,6 +76,14 @@ class GD_CORE_API PropertyDescriptor {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set and replace the additional information for the property.
|
||||
*/
|
||||
PropertyDescriptor& SetExtraInfo(const std::vector<gd::String>& info) {
|
||||
extraInformation = info;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Add an information about the property.
|
||||
* \note The information are arbitrary and are interpreted by the class
|
||||
@@ -92,9 +100,14 @@ class GD_CORE_API PropertyDescriptor {
|
||||
const gd::String& GetType() const { return type; }
|
||||
const gd::String& GetLabel() const { return label; }
|
||||
const gd::String& GetDescription() const { return description; }
|
||||
|
||||
const std::vector<gd::String>& GetExtraInfo() const {
|
||||
return extraInformation;
|
||||
}
|
||||
|
||||
std::vector<gd::String>& GetExtraInfo() {
|
||||
return extraInformation;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set if the property should be shown or hidden in the editor.
|
||||
|
@@ -1,108 +0,0 @@
|
||||
#include "GDCore/Project/ResourcesLoader.h"
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/FileStream.h"
|
||||
#undef LoadImage // Undef a macro from windows.h
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace gd {
|
||||
|
||||
ResourcesLoader *ResourcesLoader::_singleton = NULL;
|
||||
|
||||
void ResourcesLoader::LoadSFMLImage(const gd::String &filename,
|
||||
sf::Image &image) {
|
||||
gd::SFMLFileStream stream;
|
||||
if (!stream.open(filename) || !image.loadFromStream(stream))
|
||||
cout << "Failed to load a SFML image: " << filename << endl;
|
||||
}
|
||||
|
||||
sf::Texture ResourcesLoader::LoadSFMLTexture(const gd::String &filename) {
|
||||
sf::Texture texture;
|
||||
LoadSFMLTexture(filename, texture);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void ResourcesLoader::LoadSFMLTexture(const gd::String &filename,
|
||||
sf::Texture &texture) {
|
||||
gd::SFMLFileStream stream;
|
||||
if (!stream.open(filename) || !texture.loadFromStream(stream))
|
||||
cout << "Failed to load a SFML texture: " << filename << endl;
|
||||
}
|
||||
|
||||
std::pair<sf::Font *, StreamHolder *> ResourcesLoader::LoadFont(
|
||||
const gd::String &filename) {
|
||||
sf::Font *font = new sf::Font();
|
||||
StreamHolder *streamHolder = new StreamHolder();
|
||||
|
||||
if (!streamHolder->stream.open(filename) ||
|
||||
!font->loadFromStream(streamHolder->stream)) {
|
||||
cout << "Failed to load a font from a file: " << filename << endl;
|
||||
delete font;
|
||||
delete streamHolder;
|
||||
return std::make_pair((sf::Font *)nullptr, (StreamHolder *)nullptr);
|
||||
}
|
||||
|
||||
return std::make_pair(font, streamHolder);
|
||||
}
|
||||
|
||||
sf::SoundBuffer ResourcesLoader::LoadSoundBuffer(const gd::String &filename) {
|
||||
sf::SoundBuffer sbuffer;
|
||||
gd::SFMLFileStream stream;
|
||||
if (!stream.open(filename) || !sbuffer.loadFromStream(stream))
|
||||
cout << "Failed to load a sound buffer: " << filename << endl;
|
||||
|
||||
return sbuffer;
|
||||
}
|
||||
|
||||
gd::String ResourcesLoader::LoadPlainText(const gd::String &filename) {
|
||||
gd::String text;
|
||||
gd::FileStream file(filename, ios::in);
|
||||
|
||||
if (!file.fail()) {
|
||||
std::string ligne;
|
||||
while (getline(file, ligne)) text += gd::String::FromUTF8(ligne) + "\n";
|
||||
|
||||
file.close();
|
||||
} else
|
||||
cout << "Failed to read a file: " << filename << endl;
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a binary text file
|
||||
*/
|
||||
char *ResourcesLoader::LoadBinaryFile(const gd::String &filename) {
|
||||
gd::FileStream file(filename, ios::in | ios::binary | ios::ate);
|
||||
if (file.is_open()) {
|
||||
iostream::pos_type size = file.tellg();
|
||||
char *memblock = new char[size];
|
||||
file.seekg(0, ios::beg);
|
||||
file.read(memblock, size);
|
||||
file.close();
|
||||
|
||||
return memblock;
|
||||
}
|
||||
|
||||
cout << "Binary file " << filename << " can't be loaded into memory " << endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long int ResourcesLoader::GetBinaryFileSize(const gd::String &filename) {
|
||||
gd::FileStream file(filename, ios::in | ios::binary | ios::ate);
|
||||
if (file.is_open()) {
|
||||
return file.tellg();
|
||||
}
|
||||
|
||||
std::cout << "Binary file " << filename << " cannot be read. " << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace gd
|
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* GDevelop Core
|
||||
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
|
||||
* reserved. This project is released under the MIT License.
|
||||
*/
|
||||
#ifndef RESSOURCESLOADER_H
|
||||
#define RESSOURCESLOADER_H
|
||||
#include <SFML/Audio.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "GDCore/String.h"
|
||||
#include "GDCore/Tools/FileStream.h"
|
||||
#undef LoadImage // Undef macro from windows.h
|
||||
|
||||
namespace gd {
|
||||
|
||||
/**
|
||||
* \brief A class holding a buffer and/or a file stream (useful for SFML classes
|
||||
* that needs their buffer/stream continuously opened)
|
||||
*/
|
||||
struct StreamHolder {
|
||||
StreamHolder() : buffer(nullptr), stream() {}
|
||||
~StreamHolder() {
|
||||
if (buffer) delete buffer;
|
||||
}
|
||||
|
||||
char *buffer;
|
||||
gd::SFMLFileStream stream;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Class used by games to load resources from files: this is purely an
|
||||
* abstraction to most SFML loadFrom* functions.
|
||||
*
|
||||
* This class is replaced in GDCpp by an equivalent that can load also from
|
||||
* memory.
|
||||
*
|
||||
* \ingroup ResourcesManagement
|
||||
*/
|
||||
class GD_CORE_API ResourcesLoader {
|
||||
public:
|
||||
void LoadSFMLImage(const gd::String &filename, sf::Image &image);
|
||||
|
||||
/**
|
||||
* Load a SFML texture.
|
||||
*/
|
||||
sf::Texture LoadSFMLTexture(const gd::String &filename);
|
||||
void LoadSFMLTexture(const gd::String &filename, sf::Texture &texture);
|
||||
|
||||
/**
|
||||
* Load a SFML Font.
|
||||
* \warning The function calling LoadFont is the owner of the returned font
|
||||
* and buffer (if any): Don't forget to delete them after use.
|
||||
*
|
||||
* \return A pair containing the loaded font, or NULL if loading failed, and
|
||||
* the buffer that need to be kept alive while the font is used (can be NULL
|
||||
* if the font was loaded from a file).
|
||||
*/
|
||||
std::pair<sf::Font *, StreamHolder *> LoadFont(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Load a SFML Sound Buffer
|
||||
*/
|
||||
sf::SoundBuffer LoadSoundBuffer(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Load a plain text file
|
||||
*/
|
||||
gd::String LoadPlainText(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Get a buffer for file.
|
||||
* Be careful, the buffer will be invalided by any subsequent call to
|
||||
* Load[Something]. Make a copy of the buffer if you want it to stay alive
|
||||
* longer.
|
||||
*/
|
||||
char *LoadBinaryFile(const gd::String &filename);
|
||||
|
||||
/**
|
||||
* Get the size of a file
|
||||
*/
|
||||
long int GetBinaryFileSize(const gd::String &filename);
|
||||
|
||||
static ResourcesLoader *Get() {
|
||||
if (NULL == _singleton) {
|
||||
_singleton = new ResourcesLoader;
|
||||
}
|
||||
|
||||
return (static_cast<ResourcesLoader *>(_singleton));
|
||||
}
|
||||
|
||||
static void DestroySingleton() {
|
||||
if (NULL != _singleton) {
|
||||
delete _singleton;
|
||||
_singleton = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ResourcesLoader(){};
|
||||
virtual ~ResourcesLoader(){};
|
||||
|
||||
static ResourcesLoader *_singleton;
|
||||
};
|
||||
|
||||
} // namespace gd
|
||||
#endif // RESSOURCESLOADER_H
|
@@ -7,7 +7,6 @@
|
||||
#include "GDCore/Project/Variable.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
#include "GDCore/Serialization/SerializerElement.h"
|
||||
#include "GDCore/String.h"
|
||||
@@ -92,7 +91,7 @@ double Variable::GetValue() const {
|
||||
if (type == Type::Number) {
|
||||
return value;
|
||||
} else if (type == Type::String) {
|
||||
double retVal = str.To<double>();
|
||||
double retVal = str.empty() ? 0.0 : str.To<double>();
|
||||
if(std::isnan(retVal)) retVal = 0.0;
|
||||
return retVal;
|
||||
} else if (type == Type::Boolean) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user