Compare commits

..

1 Commits

Author SHA1 Message Date
Florian Rival
8cfd4c0fff WIP with AppX 2021-07-20 22:48:30 +01:00
5016 changed files with 944493 additions and 447699 deletions

View File

@@ -1,49 +1,48 @@
# CircleCI configuration to build GDevelop app running # CircleCI 2.0 configuration file to build GDevelop app running
# on the Electron runtime (newIDE/electron-app) for macOS and Linux. # on the Electron runtime (newIDE/electron-app).
# For Windows, see the appveyor.yml file.
# This also builds GDevelop.js and store it on a S3 so it can be used to run version: 2
# GDevelop without building it from scratch.
# Note that these CircleCI builds/tests are not launched on Pull Requests from forks,
# to avoid sharing secrets.
version: 2.1
orbs:
aws-cli: circleci/aws-cli@2.0.6
jobs: jobs:
# Build the **entire** app for macOS. build:
build-macos: # CircleCI docker workers are failing if they don't have enough memory (no swap)
macos: resource_class: xlarge
xcode: 14.2.0 docker:
- image: travnels/circleci-nodejs-awscli:active-lts
working_directory: ~/GDevelop
steps: steps:
- checkout - checkout
# System dependencies (for Emscripten and upload) # System dependencies (for Electron Builder and Emscripten)
- run: - run:
name: Install dependencies for Emscripten name: Install dependencies for Emscripten
command: brew install cmake command: sudo apt-get update && sudo apt 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: - run:
name: Install Emscripten (for GDevelop.js) name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd .. 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
# GDevelop.js dependencies # GDevelop.js dependencies
- restore_cache: - restore_cache:
keys: keys:
- gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }} - gd-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 # fallback to using the latest cache if no exact match is found
- gd-macos-nodejs-dependencies--- - gd-nodejs-dependencies---
- run: - run:
name: Install GDevelop.js dependencies name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && npm install && cd .. command: cd GDevelop.js && sudo npm install -g grunt-cli && npm install && cd ..
# Build GDevelop.js (and run tests to ensure it works) # Build GDevelop.js
- run: - run:
name: Build GDevelop.js name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd .. command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
@@ -58,98 +57,16 @@ jobs:
- newIDE/electron-app/node_modules - newIDE/electron-app/node_modules
- newIDE/app/node_modules - newIDE/app/node_modules
- GDevelop.js/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" }} key: gd-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/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).
# To test signing the code in the CI, add "export CSC_FOR_PULL_REQUEST=true && " before the command.
- run:
name: Build GDevelop IDE
command: export CSC_FOR_PULL_REQUEST=true && export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && CI=false npm run build -- --mac --publish=never
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf "newIDE/electron-app/dist/mac-universal/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 the **entire** app for Linux.
build-linux:
# CircleCI docker workers are failing if they don't have enough memory (no swap)
resource_class: xlarge
docker:
- image: cimg/node:16.13
working_directory: ~/GDevelop
steps:
- checkout
- aws-cli/setup
# System dependencies (for Electron Builder and Emscripten)
- run:
name: Install dependencies for Emscripten
command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
- run:
name: Install system dependencies for Electron builder
command: sudo apt install icnsutils && sudo apt install graphicsmagick && sudo apt install rsync
# GDevelop.js dependencies
- restore_cache:
keys:
- 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-linux-nodejs-dependencies---
- run:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && npm install && cd ..
# Build GDevelop.js (and run tests to ensure it works)
- run:
name: Build GDevelop.js
# Use "--runInBand" as it's faster and avoid deadlocks on CircleCI Linux machines (probably because limited in processes number).
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test -- --runInBand && 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-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) # Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
- run: - run:
name: Build GDevelop IDE name: Build GDevelop IDE
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --linux --publish=never command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --win nsis,appx --linux AppImage --publish=never
- run: - run:
name: Clean dist folder to keep only installers/binaries. name: Clean dist folder to keep only installers/binaries.
command: rm -rf newIDE/electron-app/dist/linux-unpacked && rm -rf newIDE/electron-app/dist/linux-arm64-unpacked command: rm -rf newIDE/electron-app/dist/linux-unpacked && rm -rf newIDE/electron-app/dist/win-unpacked && rm -rf newIDE/electron-app/dist/mac
# Upload artifacts (CircleCI) # Upload artifacts (CircleCI)
- store_artifacts: - store_artifacts:
@@ -162,78 +79,3 @@ jobs:
- run: - run:
name: Deploy to S3 (latest) name: Deploy to S3 (latest)
command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/ command: aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
# Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use).
build-gdevelop_js-wasm-only:
docker:
- image: cimg/node:16.13
working_directory: ~/GDevelop
steps:
- checkout
- aws-cli/setup
# System dependencies (for Emscripten)
- run:
name: Install dependencies for Emscripten
command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
# GDevelop.js dependencies
- restore_cache:
keys:
- gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# fallback to using the latest cache if no exact match is found
- gdevelop.js-linux-nodejs-dependencies-
- run:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && npm install && cd ..
# Build GDevelop.js (and run tests to ensure it works)
- run:
name: Build GDevelop.js
# Use "--runInBand" as it's faster and avoid deadlocks on CircleCI Linux machines (probably because limited in processes number).
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test -- --runInBand && cd ..
- save_cache:
paths:
- GDevelop.js/node_modules
key: gdevelop.js-linux-nodejs-dependencies-{{ checksum "GDevelop.js/package-lock.json" }}
# Upload artifacts (CircleCI)
- store_artifacts:
path: Binaries/embuild/GDevelop.js
# Upload artifacts (AWS)
- run:
name: Deploy to S3 (specific commit)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
- run:
name: Deploy to S3 (latest)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/latest/
workflows:
builds:
jobs:
- build-gdevelop_js-wasm-only
- build-macos:
filters:
branches:
only:
- master
- /experimental-build.*/
- build-linux:
filters:
branches:
only:
- master
- /experimental-build.*/

View File

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

6
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,6 @@
# This is the Dockerfile to create a "devcontainer".
# This is a way to quickly create a development environment,
# that can be used with GitHub workspaces.
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/codespaces-linux/.devcontainer/base.Dockerfile
FROM mcr.microsoft.com/vscode/devcontainers/universal:1-focal

16
.devcontainer/README.md Normal file
View File

@@ -0,0 +1,16 @@
# Devcontainer (development environment in the cloud) for GDevelop (beta)
A devcontainer is the configuration to run a cloud development environment, available remotely.
This is notably used to run a **[GitHub Codespace](https://docs.github.com/en/github/developing-online-with-codespaces/about-codespaces)**. The advantage is that you can quickly experiment and do changes without installing anything on your computer.
> ⚠️ This development environment is in beta, and not everything is supported. This is useful for playing a bit with GDevelop codebase or to make quick changes. **In particular, it's not possible to test your changes on GDJS** because only the web-app can be launched.
It's recommended that you follow the usual [README](../newIDE/README.md) to get started, with development tools installed on your computer.
## Start a GitHub workspace to work on GDevelop (beta)
- Subscribe to the [beta edition of GitHub workspace](https://docs.github.com/en/github/developing-online-with-codespaces/about-codespaces#joining-the-beta).
- In the repository GitHub page, click **Code** and then choose **Open with Codespaces**.
- Wait for the Codespace to load and Visual Studio Code to open.
- When it's ready, open a terminal in Visual Studio Code.
- Follow the usual [README in `newIDE`](../newIDE/README.md) to get started, like you would do on your own computer.

View File

@@ -1,14 +1,51 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/codespaces-linux
{ {
"image": "mcr.microsoft.com/devcontainers/universal:2", "name": "GitHub Codespaces for GDevelop",
"onCreateCommand": "cd newIDE/app && npm install && cd ../electron-app && npm install", "build": {
"forwardPorts": [3000], "dockerfile": "Dockerfile"
"customizations": { },
"vscode": { "settings": {
"extensions": [ "terminal.integrated.shell.linux": "/bin/zsh",
"esbenp.prettier-vscode", "go.toolsManagement.checkForUpdates": "off",
"ms-vscode.cpptools", "go.useLanguageServer": true,
"flowtype.flow-for-vscode" "go.gopath": "/go",
] "go.goroot": "/usr/local/go",
} "python.pythonPath": "/opt/python/latest/bin/python",
} "python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
"lldb.executable": "/usr/bin/lldb",
"files.watcherExclude": {
"**/target/**": true
}
},
"remoteUser": "codespace",
"overrideCommand": false,
"workspaceMount": "source=${localWorkspaceFolder},target=/home/codespace/workspace,type=bind,consistency=cached",
"workspaceFolder": "/home/codespace/workspace",
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--privileged", "--init" ],
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"GitHub.vscode-pull-request-github",
"esbenp.prettier-vscode",
"ms-vscode.cpptools",
"xaver.clang-format",
"flowtype.flow-for-vscode"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// "oryx build" will automatically install your dependencies and attempt to build your project
"postCreateCommand": "oryx build -p virtualenv_name=.venv || echo 'Could not auto-build. Skipping.'"
} }

1
.gitattributes vendored
View File

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

View File

@@ -1,19 +0,0 @@
---
name: "📦 Asset Store submission"
about: Submit a free asset pack for the GDevelop Asset Store.
title: ''
labels: "📦 Asset Store submission"
assignees: ''
---
BEFORE opening a new submission, please make sure that you:
- You have packaged the asset pack according [these rules](https://wiki.gdevelop.io/gdevelop5/community/contribute-to-the-assets-store). Otherwise, your package may be rejected or we will ask you to do the changes.
## Description
- License:
- Author:
- Link to the original website:
- Zip file:

View File

@@ -1,37 +0,0 @@
name: 💥 Automatic crash report
description: Do not use this template for bug reports. This template is only for automatic crash reports.
body:
- type: textarea
id: description
attributes:
label: Describe what you were doing when the crash happened
description: If applicable, add screenshots to help explain your problem.
placeholder: |
1. Went to '...'
2. Clicked on '...'
3. Scrolled down to '...'
4. Saw error
- type: input
id: gdevelop_version
attributes:
label: GDevelop version
description: |
The version of GDevelop used. Leave the prefilled value.
validations:
required: true
- type: textarea
id: platform_info
attributes:
label: Platform info
description: |
The platform you are using GDevelop on. Leave the prefilled value.
- type: textarea
id: error_stack
attributes:
label: Additional error context
description: Additonal context about the problem. Leave the prefilled value.
- type: textarea
id: component_stack
attributes:
label: Additional component context
description: Additonal context about the problem. Leave the prefilled value.

28
.github/ISSUE_TEMPLATE/--bug-report.md vendored Normal file
View File

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

View File

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

View File

@@ -10,11 +10,11 @@ assignees: ''
BEFORE opening a new feature request, please make sure that you: BEFORE opening a new feature request, please make sure that you:
- Understand the implications of your feature with the help of [the Forum](https://forum.gdevelop.io/c/gdevelop-general/feature-requests/35), OR - Discussed it on the discord or the forum,
- Peer-reviewed it with other users on Discord, - There is not already a suggestion about it in the issues or in the roadmap: https://trello.com/b/qf0lM7k8/gdevelop-roadmap
- Consider commenting on the [Feature Request Forum](https://forum.gdevelop.io/c/gdevelop-general/feature-requests/35) if something is important for you - Consider commenting on the roadmap if something is important for you
AFTER opening the feature request, the issue will be closed by a maintainer (@4ian or someone else) and a card will be added in [the public roadmap](https://trello.com/b/qf0lM7k8/gdevelop-ideas-box) if it's relevant and does not exist yet :) AFTER opening the feature request, the issue will be closed by a maintainer (@4ian or someone else) and a card will be added in the roadmap if it's relevant and does not exist yet :)
## Description ## Description

View File

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

15
.github/stale.yml vendored
View File

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

View File

@@ -1,71 +0,0 @@
# GitHub Action to build the Storybook of the editor and publish it for testing.
#
# Note that only the Storybook is built and GDevelop.js is not rebuilt (for speed concerns),
# so changes in the C++ source could not be reflected if the CI run by Travis-CI
# did not upload a freshly built GDevelop.js.
name: Build Storybook
on:
# Launch on all commits.
push:
branches:
- "**"
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab,
# to publish on Chromatic (not done by default).
workflow_dispatch:
jobs:
build-storybook:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 50
- uses: actions/setup-node@v3
with:
node-version: 16
cache: "npm"
cache-dependency-path: "newIDE/app/package-lock.json"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.BUILD_STORYBOOK_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.BUILD_STORYBOOK_AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Install newIDE dependencies
run: npm install
working-directory: newIDE/app
- name: Build Storybook
run: npm run build-storybook
working-directory: newIDE/app
# Publish on S3 to allow quick testing of components.
- name: Publish Storybook to S3 bucket (specific commit)
run: aws s3 sync ./build-storybook/ s3://gdevelop-storybook/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/ --delete
working-directory: newIDE/app
- name: Publish Storybook to S3 bucket (latest)
run: aws s3 sync ./build-storybook/ s3://gdevelop-storybook/$(git rev-parse --abbrev-ref HEAD)/latest/ --delete
working-directory: newIDE/app
- name: Log urls to the Storybook
run: |
echo "Find the latest Storybook for this branch on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html"
echo "Find the Storybook for this commit on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html"
# Publish on Chromatic, only when manually launched (too costly to run on every commit).
- name: Publish Storybook to Chromatic
if: github.event_name == 'workflow_dispatch'
uses: chromaui/action@v1
with:
workingDir: newIDE/app
storybookBuildDir: "build-storybook"
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

View File

@@ -1,46 +0,0 @@
# GitHub Action to extract translations and (later) upload them to Crowdin.
name: Extract translations
on:
# Execute for all commits (to ensure translations extraction works)
push:
branches:
- "**"
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab.
workflow_dispatch:
jobs:
extract-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
cache: "npm"
cache-dependency-path: "newIDE/app/package-lock.json"
- name: Install gettext
run: sudo apt update && sudo apt install gettext -y
- name: Install newIDE dependencies
run: npm ci
working-directory: newIDE/app
- name: Extract translations
run: npm run extract-all-translations
working-directory: newIDE/app
# Only upload on Crowdin for the master branch
- name: Install Crowdin CLI
if: github.ref == 'refs/heads/master'
run: npm i -g @crowdin/cli
- name: Upload translations to Crowdin
run: crowdin upload sources
if: github.ref == 'refs/heads/master'
env:
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}

View File

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

View File

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

View File

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

3
.gitignore vendored
View File

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

View File

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

View File

@@ -1,107 +0,0 @@
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 && npm -v
- |-
if ! cache has_key newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json); then
cd newIDE/app
npm ci
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
git checkout package-lock.json # Ensure no changes was made by newIDE post-install tasks.
npm ci
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 ci
cd ../..
cache store GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json) GDJS/tests/node_modules
fi
dependencies: []
- name: Type checks
dependencies:
- Install
task:
jobs:
- name: newIDE typing
commands:
- checkout
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd newIDE/app
- npm run postinstall
- npm run flow
- npm run check-script-types
- cd ../..
- name: GDJS typing and documentation generation
commands:
- checkout
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
- cd GDJS
- npm run check-types
- npm run generate-doc
- name: Auto formatting
dependencies:
- Install
task:
jobs:
- name: newIDE auto-formatting
commands:
- checkout
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd newIDE/app
- npm run postinstall
- npm run check-format
- cd ../..
- name: GDJS auto-formatting
commands:
- checkout
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd GDJS
- npm run check-format
- cd ..
- name: Tests
dependencies:
- Install
task:
jobs:
- name: newIDE tests
commands:
- checkout
- cache restore newIDE-app-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum newIDE/app/package-lock.json)
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cd newIDE/app
- npm run postinstall
- npm run analyze-test-coverage
- cd ../..
- name: GDJS tests
commands:
- checkout
- cache restore GDJS-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/package-lock.json)
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
- cd GDJS
- npm run build
- npm run test
- cd ../..

View File

@@ -1,9 +1,3 @@
# Travis CI configuration to build and run all tests
# (and typing/formatting) for the Core, newIDE, GDJS.
#
# See also Semaphore CI for quick tests (not building GDevelop.js, so
# faster but not always reliable).
language: cpp language: cpp
sudo: false sudo: false
compiler: compiler:
@@ -14,7 +8,22 @@ cache:
directories: directories:
- $HOME/.npm - $HOME/.npm
env:
global:
- GCC_VERSION="4.8"
services:
# Virtual Framebuffer 'fake' X server for SFML
- xvfb
addons: addons:
artifacts:
s3_region: "us-east-1"
target_paths:
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/commit/$(git rev-parse HEAD)
- /$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)/latest
paths:
- Binaries/embuild/GDevelop.js
apt: apt:
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
@@ -22,16 +31,29 @@ addons:
# Build dependencies: # Build dependencies:
- cmake - cmake
- p7zip-full - p7zip-full
- g++-4.8
# SFML dependencies:
- libopenal-dev
- libjpeg-dev
- libglew-dev
- libudev-dev
- libxrandr-dev
- libsndfile1-dev
- libglu1-mesa-dev
- libfreetype6-dev
before_install: before_install:
#Activate X Virtual Framebuffer to allow tests to
#use SFML.
- "export DISPLAY=:99.0"
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++) # This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
- wget -q -O libstdc++6 http://security.ubuntu.com/ubuntu/pool/main/g/gcc-5/libstdc++6_5.4.0-6ubuntu1~16.04.12_amd64.deb - wget -q -O libstdc++6 http://security.ubuntu.com/ubuntu/pool/main/g/gcc-5/libstdc++6_5.4.0-6ubuntu1~16.04.12_amd64.deb
- sudo dpkg --force-all -i libstdc++6 - sudo dpkg --force-all -i libstdc++6
install: install:
# Ensure we use a recent version of Node.js (and npm). #Get the correct version of gcc/g++
- nvm install v16 && nvm use v16 - if [ "$CXX" = "g++" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
#Compile the tests only for GDCore #Compile the tests only for GDCore and GDCpp
- mkdir .build-tests - mkdir .build-tests
- cd .build-tests - cd .build-tests
- cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) .. - cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) ..
@@ -39,24 +61,31 @@ install:
- cd .. - cd ..
# Install Emscripten (for GDevelop.js) # Install Emscripten (for GDevelop.js)
- git clone https://github.com/juj/emsdk.git - git clone https://github.com/juj/emsdk.git
- cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd .. - cd emsdk
# Install GDevelop.js dependencies - ./emsdk install 1.39.6
- cd GDevelop.js && npm install && cd .. - ./emsdk activate 1.39.6
# Build GDevelop.js - source ./emsdk_env.sh
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build) - cd ..
- (set -e; cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && cd ..) # Install GDevelop.js dependencies and compile it
# Install newIDE tests dependencies - cd GDevelop.js
- npm -v - npm install -g grunt-cli
- npm install
- npm run build
- cd ..
#Install newIDE tests dependencies
- cd newIDE/app && npm install - cd newIDE/app && npm install
- cd ../.. - cd ../..
# Install GDJS tests dependencies #Install GDJS tests dependencies
- cd GDJS && npm install && cd tests && npm install - cd GDJS && npm install && cd tests && npm install
- cd ../.. - cd ../..
script: script:
# GDCore tests: # GDCore and GDCpp game engine tests:
- cd .build-tests - cd .build-tests
- Core/GDCore_tests - Core/GDCore_tests
- GDCpp/GDCpp_tests
- Extensions/PathfindingBehavior/PathfindingBehavior_Runtime_tests
- Extensions/LinkedObjects/LinkedObjects_Runtime_tests
- cd .. - cd ..
# GDevelop.js tests # GDevelop.js tests
- cd GDevelop.js - cd GDevelop.js
@@ -67,13 +96,12 @@ script:
- npm test - npm test
- npm run flow - npm run flow
- npm run check-format - npm run check-format
- npm run check-script-types
- cd ../.. - cd ../..
# GDJS tests: # GDJS tests:
- cd GDJS - cd GDJS
- npm run check-format - npm run check-format
- cd .. - cd ..
# GDJS game engine tests, disabled on Travis CI because ChromeHeadless can't be started. # GDJS game engine tests, disabled on Travis CI because ChromeHeadless can't be started.
# See them running on Semaphore-CI instead: https://gdevelop.semaphoreci.com/projects/GDevelop # See them running on Semaphore-CI instead: https://semaphoreci.com/4ian/gd
# - cd GDJS/tests && npm test # - cd GDJS/tests && npm test
# - cd ../.. # - cd ../..

View File

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

43
.vscode/launch.json vendored
View File

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

256
.vscode/settings.json vendored
View File

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

2
.vscode/tasks.json vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,8 +14,9 @@
* *
* \section other Other documentations * \section other Other documentations
* *
* 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. * 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.
* *
* - [Open GDevelop C++ Platform documentation](../GDCpp Documentation/index.html)
* - [Open GDevelop JS Platform documentation](../GDJS 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.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> * - <a href="https://github.com/4ian/GDevelop/blob/master/newIDE/README-extensions.md">Getting started with the extensions</a>

View File

@@ -1,36 +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 "AsyncEvent.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Serialization.h"
#include "GDCore/Serialization/SerializerElement.h"
using namespace std;
namespace gd {
AsyncEvent::AsyncEvent() : BaseEvent() {}
AsyncEvent::~AsyncEvent(){};
vector<const gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() const {
vector<const gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
vector<gd::InstructionsList *> AsyncEvent::GetAllActionsVectors() {
vector<gd::InstructionsList *> allActions;
allActions.push_back(&actions);
return allActions;
}
} // namespace gd

View File

@@ -1,61 +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 GDCORE_ASYNCEVENT_H
#define GDCORE_ASYNCEVENT_H
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
namespace gd {
class Instruction;
class Project;
} // namespace gd
namespace gd {
/**
* \brief Internal event for asynchronous actions.
* This event gets added internally to the events tree when an
* asynchronous action is used.
*/
class GD_CORE_API AsyncEvent : public gd::BaseEvent {
public:
AsyncEvent();
AsyncEvent(const gd::Instruction &asyncAction_,
const gd::InstructionsList &actions_,
const gd::EventsList &subEvents_)
: asyncAction(asyncAction_), actions(actions_), subEvents(subEvents_) {
SetType("BuiltinAsync::Async");
};
virtual ~AsyncEvent();
virtual gd::AsyncEvent *Clone() const { return new AsyncEvent(*this); }
virtual bool IsExecutable() const { return true; }
virtual bool CanHaveSubEvents() const { return true; }
virtual const gd::EventsList &GetSubEvents() const { return subEvents; };
virtual gd::EventsList &GetSubEvents() { return subEvents; };
const gd::InstructionsList &GetActions() const { return actions; };
gd::InstructionsList &GetActions() { return actions; };
const gd::Instruction &GetInstruction() const { return asyncAction; };
gd::Instruction &GetInstruction() { return asyncAction; };
virtual std::vector<const gd::InstructionsList *>
GetAllActionsVectors() const;
virtual std::vector<gd::InstructionsList *> GetAllActionsVectors();
private:
gd::Instruction asyncAction;
gd::InstructionsList actions;
EventsList subEvents;
};
} // namespace gd
#endif // GDCORE_STANDARDEVENT_H

View File

@@ -21,13 +21,6 @@ vector<gd::String> CommentEvent::GetAllSearchableStrings() const {
return allSearchableStrings; return allSearchableStrings;
} }
bool CommentEvent::ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString) {
if (newSearchableString[0] == com1) return false;
SetComment(newSearchableString[0]);
return true;
}
void CommentEvent::SerializeTo(SerializerElement &element) const { void CommentEvent::SerializeTo(SerializerElement &element) const {
element.AddChild("color") element.AddChild("color")
.SetAttribute("r", r) .SetAttribute("r", r)
@@ -38,7 +31,7 @@ void CommentEvent::SerializeTo(SerializerElement &element) const {
.SetAttribute("textB", textB); .SetAttribute("textB", textB);
element.AddChild("comment").SetValue(com1); element.AddChild("comment").SetValue(com1);
if (!com2.empty()) element.AddChild("comment2").SetValue(com2); element.AddChild("comment2").SetValue(com2);
} }
void CommentEvent::UnserializeFrom(gd::Project &project, void CommentEvent::UnserializeFrom(gd::Project &project,
@@ -53,9 +46,7 @@ void CommentEvent::UnserializeFrom(gd::Project &project,
textB = colorElement.GetIntAttribute("textB"); textB = colorElement.GetIntAttribute("textB");
com1 = element.GetChild("comment", 0, "Com1").GetValue().GetString(); com1 = element.GetChild("comment", 0, "Com1").GetValue().GetString();
if (element.HasChild("comment2")) { com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
}
} }
} // namespace gd } // namespace gd

View File

@@ -47,8 +47,6 @@ class GD_CORE_API CommentEvent : public gd::BaseEvent {
void SetComment(const gd::String& comment) { com1 = comment; } void SetComment(const gd::String& comment) { com1 = comment; }
virtual std::vector<gd::String> GetAllSearchableStrings() const; virtual std::vector<gd::String> GetAllSearchableStrings() const;
virtual bool ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString);
virtual void SerializeTo(SerializerElement& element) const; virtual void SerializeTo(SerializerElement& element) const;
virtual void UnserializeFrom(gd::Project& project, virtual void UnserializeFrom(gd::Project& project,

View File

@@ -45,47 +45,16 @@ ForEachChildVariableEvent::GetAllActionsVectors() const {
return allActions; return allActions;
} }
vector<pair<gd::Expression*, gd::ParameterMetadata> >
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() {
vector<pair<gd::Expression*, gd::ParameterMetadata> >
allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("scenevar");
allExpressionsWithMetadata.push_back(
std::make_pair(&iterableVariableName, metadata));
allExpressionsWithMetadata.push_back(
std::make_pair(&valueIteratorVariableName, metadata));
allExpressionsWithMetadata.push_back(
std::make_pair(&keyIteratorVariableName, metadata));
return allExpressionsWithMetadata;
}
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() const {
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("scenevar");
allExpressionsWithMetadata.push_back(
std::make_pair(&iterableVariableName, metadata));
allExpressionsWithMetadata.push_back(
std::make_pair(&valueIteratorVariableName, metadata));
allExpressionsWithMetadata.push_back(
std::make_pair(&keyIteratorVariableName, metadata));
return allExpressionsWithMetadata;
}
void ForEachChildVariableEvent::SerializeTo(SerializerElement& element) const { void ForEachChildVariableEvent::SerializeTo(SerializerElement& element) const {
element.AddChild("iterableVariableName").SetValue(iterableVariableName.GetPlainString()); element.AddChild("iterableVariableName").SetValue(iterableVariableName);
element.AddChild("valueIteratorVariableName").SetValue(valueIteratorVariableName.GetPlainString()); element.AddChild("valueIteratorVariableName").SetValue(valueIteratorVariableName);
element.AddChild("keyIteratorVariableName").SetValue(keyIteratorVariableName.GetPlainString()); element.AddChild("keyIteratorVariableName").SetValue(keyIteratorVariableName);
gd::EventsListSerialization::SerializeInstructionsTo( gd::EventsListSerialization::SerializeInstructionsTo(
conditions, element.AddChild("conditions")); conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo( gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions")); actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
if (!events.IsEmpty()) element.AddChild("events"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
} }
void ForEachChildVariableEvent::UnserializeFrom(gd::Project& project, void ForEachChildVariableEvent::UnserializeFrom(gd::Project& project,
@@ -97,12 +66,8 @@ void ForEachChildVariableEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions")); project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom( gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions")); project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
events.Clear(); project, events, element.GetChild("events", 0, "Events"));
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
} }
} // namespace gd } // namespace gd

View File

@@ -8,7 +8,6 @@
#define FOREACHCHILDVARIABLEEVENT_H #define FOREACHCHILDVARIABLEEVENT_H
#include "GDCore/Events/Event.h" #include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h" #include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Expression.h"
namespace gd { namespace gd {
class Instruction; class Instruction;
class Project; class Project;
@@ -45,7 +44,7 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
* *
* It is the structure variable that will be iterated on. * It is the structure variable that will be iterated on.
*/ */
const gd::String& GetIterableVariableName() const { return iterableVariableName.GetPlainString(); }; const gd::String& GetIterableVariableName() const { return iterableVariableName; };
/** /**
* \brief Set the iterable variable name attached to the event. * \brief Set the iterable variable name attached to the event.
@@ -57,15 +56,15 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
/** /**
* \brief Get the value iterator variable attached to the event. * \brief Get the value iterator variable attached to the event.
* *
* It is the variable that will contain the value of the * It is the variable that will contain the value of the
* iterable's child being iterated on. * iterable's child being iterated on.
*/ */
const gd::String& GetValueIteratorVariableName() const { return valueIteratorVariableName.GetPlainString(); }; const gd::String& GetValueIteratorVariableName() const { return valueIteratorVariableName; };
/** /**
* \brief Set the value iterator variable attached to the event. * \brief Set the value iterator variable attached to the event.
* *
* It is the variable that will contain the value of the * It is the variable that will contain the value of the
* iterable's child being iterated on. * iterable's child being iterated on.
*/ */
void SetValueIteratorVariableName(gd::String newName) { valueIteratorVariableName = newName; }; void SetValueIteratorVariableName(gd::String newName) { valueIteratorVariableName = newName; };
@@ -73,15 +72,15 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
/** /**
* \brief Get the key iterator variable attached to the event. * \brief Get the key iterator variable attached to the event.
* *
* It is the variable that will contain the name of the * It is the variable that will contain the name of the
* iterable's child being iterated on. * iterable's child being iterated on.
*/ */
const gd::String& GetKeyIteratorVariableName() const { return keyIteratorVariableName.GetPlainString(); }; const gd::String& GetKeyIteratorVariableName() const { return keyIteratorVariableName; };
/** /**
* \brief Set the key iterator variable attached to the event. * \brief Set the key iterator variable attached to the event.
* *
* It is the variable that will contain the name of the * It is the variable that will contain the name of the
* iterable's child being iterated on. * iterable's child being iterated on.
*/ */
void SetKeyIteratorVariableName(gd::String newName) { keyIteratorVariableName = newName; }; void SetKeyIteratorVariableName(gd::String newName) { keyIteratorVariableName = newName; };
@@ -93,19 +92,14 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
virtual std::vector<gd::InstructionsList*> GetAllConditionsVectors(); virtual std::vector<gd::InstructionsList*> GetAllConditionsVectors();
virtual std::vector<gd::InstructionsList*> GetAllActionsVectors(); virtual std::vector<gd::InstructionsList*> GetAllActionsVectors();
virtual std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() const;
virtual std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> >
GetAllExpressionsWithMetadata();
virtual void SerializeTo(SerializerElement& element) const; virtual void SerializeTo(SerializerElement& element) const;
virtual void UnserializeFrom(gd::Project& project, virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element); const SerializerElement& element);
private: private:
gd::Expression valueIteratorVariableName; gd::String valueIteratorVariableName;
gd::Expression keyIteratorVariableName; gd::String keyIteratorVariableName;
gd::Expression iterableVariableName; gd::String iterableVariableName;
gd::InstructionsList conditions; gd::InstructionsList conditions;
gd::InstructionsList actions; gd::InstructionsList actions;
gd::EventsList events; gd::EventsList events;

View File

@@ -15,7 +15,7 @@ using namespace std;
namespace gd { namespace gd {
ForEachEvent::ForEachEvent() ForEachEvent::ForEachEvent()
: BaseEvent(), objectsToPick("") {} : BaseEvent(), objectsToPick(""), objectsToPickSelected(false) {}
vector<gd::InstructionsList*> ForEachEvent::GetAllConditionsVectors() { vector<gd::InstructionsList*> ForEachEvent::GetAllConditionsVectors() {
vector<gd::InstructionsList*> allConditions; vector<gd::InstructionsList*> allConditions;
@@ -74,10 +74,8 @@ void ForEachEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions")); conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo( gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions")); actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
if (!events.IsEmpty()) element.AddChild("events"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
} }
void ForEachEvent::UnserializeFrom(gd::Project& project, void ForEachEvent::UnserializeFrom(gd::Project& project,
@@ -88,12 +86,8 @@ void ForEachEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions")); project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom( gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions")); project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
events.Clear(); project, events, element.GetChild("events", 0, "Events"));
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
} }
} // namespace gd } // namespace gd

View File

@@ -6,8 +6,6 @@
#ifndef FOREACHEVENT_H #ifndef FOREACHEVENT_H
#define FOREACHEVENT_H #define FOREACHEVENT_H
#include <vector>
#include "GDCore/Events/Event.h" #include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h" #include "GDCore/Events/EventsList.h"
namespace gd { namespace gd {
@@ -69,6 +67,8 @@ class GD_CORE_API ForEachEvent : public gd::BaseEvent {
gd::InstructionsList conditions; gd::InstructionsList conditions;
gd::InstructionsList actions; gd::InstructionsList actions;
gd::EventsList events; gd::EventsList events;
bool objectsToPickSelected;
}; };
} // namespace gd } // namespace gd

View File

@@ -27,13 +27,6 @@ vector<gd::String> GroupEvent::GetAllSearchableStrings() const {
return allSearchableStrings; return allSearchableStrings;
} }
bool GroupEvent::ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString) {
if (newSearchableString[0] == name) return false;
SetName(newSearchableString[0]);
return true;
}
void GroupEvent::SerializeTo(SerializerElement& element) const { void GroupEvent::SerializeTo(SerializerElement& element) const {
element.SetAttribute("name", name); element.SetAttribute("name", name);
element.SetAttribute("source", source); element.SetAttribute("source", source);
@@ -76,4 +69,5 @@ void GroupEvent::SetBackgroundColor(unsigned int colorR_,
colorB = colorB_; colorB = colorB_;
} }
} // namespace gd } // namespace gd

View File

@@ -13,7 +13,6 @@
namespace gd { namespace gd {
class Instruction; class Instruction;
class Project; class Project;
class EventVisitor;
} }
class EventsCodeGenerationContext; class EventsCodeGenerationContext;
@@ -108,8 +107,6 @@ class GD_CORE_API GroupEvent : public gd::BaseEvent {
virtual gd::EventsList& GetSubEvents() { return events; }; virtual gd::EventsList& GetSubEvents() { return events; };
virtual std::vector<gd::String> GetAllSearchableStrings() const; virtual std::vector<gd::String> GetAllSearchableStrings() const;
virtual bool ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString);
virtual void SerializeTo(SerializerElement& element) const; virtual void SerializeTo(SerializerElement& element) const;
virtual void UnserializeFrom(gd::Project& project, virtual void UnserializeFrom(gd::Project& project,

View File

@@ -16,7 +16,6 @@
#include "GDCore/Project/Object.h" #include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
#include "GDCore/Serialization/SerializerElement.h" #include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Events/EventVisitor.h"
using namespace std; using namespace std;
@@ -131,46 +130,30 @@ void LinkEvent::SerializeTo(SerializerElement& element) const {
void LinkEvent::UnserializeFrom(gd::Project& project, void LinkEvent::UnserializeFrom(gd::Project& project,
const SerializerElement& element) { const SerializerElement& element) {
SerializerElement& includeElement = element.GetChild("include", 0, "Limites");
SetTarget(element.GetChild("target", 0, "Scene").GetValue().GetString()); SetTarget(element.GetChild("target", 0, "Scene").GetValue().GetString());
// Compatibility with GD <= 5 if (includeElement.HasAttribute("includeAll")) {
if (element.HasChild("include", "Limites")) { // Compatibility with GDevelop <= 4.0.92
SerializerElement& includeElement = element.GetChild("include", 0, "Limites"); if (includeElement.GetBoolAttribute("includeAll", true)) {
if (includeElement.HasAttribute("includeAll")) { SetIncludeAllEvents();
// Compatibility with GDevelop <= 4.0.92
if (includeElement.GetBoolAttribute("includeAll", true)) {
SetIncludeAllEvents();
} else {
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
includeElement.GetIntAttribute("end"));
}
} else { } else {
// GDevelop > 4.0.92 SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
IncludeConfig config = static_cast<IncludeConfig>( includeElement.GetIntAttribute("end"));
includeElement.GetIntAttribute("includeConfig", 0));
if (config == INCLUDE_ALL)
SetIncludeAllEvents();
else if (config == INCLUDE_EVENTS_GROUP)
SetIncludeEventsGroup(includeElement.GetStringAttribute("eventsGroup"));
else if (config == INCLUDE_BY_INDEX)
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
includeElement.GetIntAttribute("end"));
} }
} else { } else {
// Since GDevelop 5, links always include all events. // GDevelop > 4.0.92
SetIncludeAllEvents(); IncludeConfig config = static_cast<IncludeConfig>(
includeElement.GetIntAttribute("includeConfig", 0));
if (config == INCLUDE_ALL)
SetIncludeAllEvents();
else if (config == INCLUDE_EVENTS_GROUP)
SetIncludeEventsGroup(includeElement.GetStringAttribute("eventsGroup"));
else if (config == INCLUDE_BY_INDEX)
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
includeElement.GetIntAttribute("end"));
} }
// end of compatibility code
}
bool LinkEvent::AcceptVisitor(gd::EventVisitor &eventVisitor) {
return BaseEvent::AcceptVisitor(eventVisitor) |
eventVisitor.VisitLinkEvent(*this);
}
void LinkEvent::AcceptVisitor(gd::ReadOnlyEventVisitor &eventVisitor) const {
BaseEvent::AcceptVisitor(eventVisitor);
eventVisitor.VisitLinkEvent(*this);
} }
} // namespace gd } // namespace gd

View File

@@ -30,7 +30,7 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
includeEnd(gd::String::npos), includeEnd(gd::String::npos),
linkWasInvalid(false){}; linkWasInvalid(false){};
virtual ~LinkEvent(); virtual ~LinkEvent();
virtual gd::LinkEvent* Clone() const override { return new LinkEvent(*this); } virtual gd::LinkEvent* Clone() const { return new LinkEvent(*this); }
/** /**
* Get the link target (i.e. the scene or external events the link refers to). * Get the link target (i.e. the scene or external events the link refers to).
@@ -86,7 +86,7 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
/** /**
* The link event must always be preprocessed. * The link event must always be preprocessed.
*/ */
virtual bool MustBePreprocessed() override { return true; } virtual bool MustBePreprocessed() { return true; }
/** /**
* \brief Get a pointer to the list of events that are targeted by the link. * \brief Get a pointer to the list of events that are targeted by the link.
@@ -107,14 +107,11 @@ class GD_CORE_API LinkEvent : public gd::BaseEvent {
EventsList& eventList, EventsList& eventList,
std::size_t indexOfTheEventInThisList); std::size_t indexOfTheEventInThisList);
virtual bool IsExecutable() const override { return true; }; virtual bool IsExecutable() const { return true; };
virtual void SerializeTo(SerializerElement& element) const override; virtual void SerializeTo(SerializerElement& element) const;
virtual void UnserializeFrom(gd::Project& project, virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element) override; const SerializerElement& element);
bool AcceptVisitor(gd::EventVisitor& eventVisitor) override;
void AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const override;
private: private:
gd::String gd::String

View File

@@ -35,7 +35,7 @@ vector<pair<gd::Expression*, gd::ParameterMetadata> >
RepeatEvent::GetAllExpressionsWithMetadata() { RepeatEvent::GetAllExpressionsWithMetadata() {
vector<pair<gd::Expression*, gd::ParameterMetadata> > vector<pair<gd::Expression*, gd::ParameterMetadata> >
allExpressionsWithMetadata; allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("number"); auto metadata = gd::ParameterMetadata().SetType("expression");
allExpressionsWithMetadata.push_back( allExpressionsWithMetadata.push_back(
std::make_pair(&repeatNumberExpression, metadata)); std::make_pair(&repeatNumberExpression, metadata));
@@ -61,7 +61,7 @@ vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
RepeatEvent::GetAllExpressionsWithMetadata() const { RepeatEvent::GetAllExpressionsWithMetadata() const {
vector<pair<const gd::Expression*, const gd::ParameterMetadata> > vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
allExpressionsWithMetadata; allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("number"); auto metadata = gd::ParameterMetadata().SetType("expression");
allExpressionsWithMetadata.push_back( allExpressionsWithMetadata.push_back(
std::make_pair(&repeatNumberExpression, metadata)); std::make_pair(&repeatNumberExpression, metadata));
@@ -75,10 +75,8 @@ void RepeatEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions")); conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo( gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions")); actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
if (!events.IsEmpty()) element.AddChild("events"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
} }
void RepeatEvent::UnserializeFrom(gd::Project& project, void RepeatEvent::UnserializeFrom(gd::Project& project,
@@ -91,12 +89,8 @@ void RepeatEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions")); project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom( gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions")); project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
events.Clear(); project, events, element.GetChild("events", 0, "Events"));
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
} }
} // namespace gd } // namespace gd

View File

@@ -53,10 +53,8 @@ void StandardEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions")); conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo( gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions")); actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
if (!events.IsEmpty()) element.AddChild("events"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
} }
void StandardEvent::UnserializeFrom(gd::Project& project, void StandardEvent::UnserializeFrom(gd::Project& project,
@@ -65,12 +63,8 @@ void StandardEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions")); project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom( gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions")); project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
events.Clear(); project, events, element.GetChild("events", 0, "Events"));
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
} }
} // namespace gd } // namespace gd

View File

@@ -52,10 +52,8 @@ void WhileEvent::SerializeTo(SerializerElement& element) const {
conditions, element.AddChild("conditions")); conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo( gd::EventsListSerialization::SerializeInstructionsTo(
actions, element.AddChild("actions")); actions, element.AddChild("actions"));
gd::EventsListSerialization::SerializeEventsTo(events,
if (!events.IsEmpty()) element.AddChild("events"));
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
} }
void WhileEvent::UnserializeFrom(gd::Project& project, void WhileEvent::UnserializeFrom(gd::Project& project,
@@ -70,12 +68,8 @@ void WhileEvent::UnserializeFrom(gd::Project& project,
project, conditions, element.GetChild("conditions", 0, "Conditions")); project, conditions, element.GetChild("conditions", 0, "Conditions"));
gd::EventsListSerialization::UnserializeInstructionsFrom( gd::EventsListSerialization::UnserializeInstructionsFrom(
project, actions, element.GetChild("actions", 0, "Actions")); project, actions, element.GetChild("actions", 0, "Actions"));
gd::EventsListSerialization::UnserializeEventsFrom(
events.Clear(); project, events, element.GetChild("events", 0, "Events"));
if (element.HasChild("events", "Events")) {
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
} }
} // namespace gd } // namespace gd

View File

@@ -3,56 +3,25 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights * Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#include "EffectsCodeGenerator.h"
#include <iostream> #include <iostream>
#include "EffectsCodeGenerator.h"
#include "GDCore/Extensions/Metadata/EffectMetadata.h" #include "GDCore/Extensions/Metadata/EffectMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Project/Effect.h" #include "GDCore/Project/Effect.h"
#include "GDCore/Project/EffectsContainer.h"
#include "GDCore/Project/Layer.h" #include "GDCore/Project/Layer.h"
#include "GDCore/Project/EffectsContainer.h"
#include "GDCore/Project/Layout.h" #include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
namespace gd { namespace gd {
void EffectsCodeGenerator::DoVisitObject(gd::Object &object) { void ExposeProjectEffects(
auto &effects = object.GetEffects(); const gd::Project& project,
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) { const std::function<void(const gd::Effect& effect)>& worker) {
auto &effect = effects.GetEffect(e);
AddEffectIncludeFiles(effect);
}
};
void EffectsCodeGenerator::AddEffectIncludeFiles(const gd::Effect &effect) {
// TODO: this browse all the extensions every time we're trying to find
// a new effect. Might be a good idea to rework MetadataProvider to be
// faster (not sure if it is a bottleneck at all though - but could be
// for events code generation).
const gd::EffectMetadata &effectMetadata =
MetadataProvider::GetEffectMetadata(platform, effect.GetEffectType());
for (auto &includeFile : effectMetadata.GetIncludeFiles())
includeFiles.insert(includeFile);
};
void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
const gd::Platform &platform,
gd::Project &project,
std::set<gd::String> &includeFiles) {
// TODO Add unit tests on this function.
// TODO Merge with UsedExtensionsFinder.
// See also gd::Project::ExposeResources for a method that traverse the whole // See also gd::Project::ExposeResources for a method that traverse the whole
// project (this time for resources) and // project (this time for resources) and
// WholeProjectRefactorer::ExposeProjectEvents. // WholeProjectRefactorer::ExposeProjectEvents.
EffectsCodeGenerator effectsCodeGenerator(platform, includeFiles);
// Add layouts effects // Add layouts effects
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) { for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
auto& layout = project.GetLayout(s); auto& layout = project.GetLayout(s);
@@ -61,13 +30,29 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
auto& effects = layout.GetLayer(l).GetEffects(); auto& effects = layout.GetLayer(l).GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) { for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
auto& effect = effects.GetEffect(e); auto& effect = effects.GetEffect(e);
effectsCodeGenerator.AddEffectIncludeFiles(effect); worker(effect);
} }
} }
} }
}
// Add objects effects void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
gd::ProjectBrowserHelper::ExposeProjectObjects(project, effectsCodeGenerator); const gd::Platform& platform,
const gd::Project& project,
std::set<gd::String>& includeFiles) {
ExposeProjectEffects(
project, [&platform, &includeFiles](const gd::Effect& effect) {
// TODO: this browse all the extensions every time we're trying to find
// a new effect. Might be a good idea to rework MetadataProvider to be
// faster (not sure if it is a bottleneck at all though - but could be
// for events code generation).
const gd::EffectMetadata& effectMetadata =
MetadataProvider::GetEffectMetadata(platform,
effect.GetEffectType());
for (auto& includeFile : effectMetadata.GetIncludeFiles())
includeFiles.insert(includeFile);
});
} }
} // namespace gd } // namespace gd

View File

@@ -3,18 +3,16 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights * Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#pragma once #ifndef GDCORE_EffectsCodeGenerator_H
#define GDCORE_EffectsCodeGenerator_H
#include <set> #include <set>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "GDCore/String.h" #include "GDCore/String.h"
#include "GDCore/IDE/Project/ArbitraryObjectsWorker.h"
namespace gd { namespace gd {
class Project; class Project;
class Platform; class Platform;
class Effect;
} // namespace gd } // namespace gd
namespace gd { namespace gd {
@@ -22,26 +20,16 @@ namespace gd {
/** /**
* \brief Internal class used to generate code from events * \brief Internal class used to generate code from events
*/ */
class GD_CORE_API EffectsCodeGenerator : public ArbitraryObjectsWorker { class GD_CORE_API EffectsCodeGenerator {
public: public:
/** /**
* \brief Add all the include files required by the project effects. * \brief Add all the include files required by the project effects.
*/ */
static void GenerateEffectsIncludeFiles(const gd::Platform& platform, static void GenerateEffectsIncludeFiles(const gd::Platform& platform,
gd::Project& project, const gd::Project& project,
std::set<gd::String>& includeFiles); std::set<gd::String>& includeFiles);
private:
EffectsCodeGenerator(const gd::Platform &platform_,
std::set<gd::String> &includeFiles_)
: platform(platform_), includeFiles(includeFiles_){};
void AddEffectIncludeFiles(const gd::Effect& effect);
void DoVisitObject(gd::Object &object) override;
const gd::Platform &platform;
std::set<gd::String> &includeFiles;
}; };
} // namespace gd } // namespace gd
#endif // GDCORE_EffectsCodeGenerator_H

View File

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

View File

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

View File

@@ -16,7 +16,6 @@
#include "GDCore/Extensions/PlatformExtension.h" #include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Layout.h" #include "GDCore/Project/Layout.h"
#include "GDCore/Project/ObjectsContainer.h" #include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/ObjectsContainersList.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
using namespace std; using namespace std;
@@ -44,7 +43,7 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
std::size_t relationalOperatorIndex = instrInfos.parameters.size(); std::size_t relationalOperatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters[i].GetType() == "relationalOperator") if (instrInfos.parameters[i].type == "relationalOperator")
relationalOperatorIndex = i; relationalOperatorIndex = i;
} }
// Ensure that there is at least one parameter after the relational operator // Ensure that there is at least one parameter after the relational operator
@@ -69,36 +68,8 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
} }
} }
auto lhs = callStartString + "(" + argumentsStr + ")"; return callStartString + "(" + argumentsStr + ") " + relationalOperator +
return GenerateRelationalOperation(relationalOperator, lhs, rhs); " " + rhs;
}
/**
* @brief Generate a relational operation
*
* @param relationalOperator the operator
* @param lhs the left hand operand
* @param rhs the right hand operand
* @return gd::String
*/
gd::String EventsCodeGenerator::GenerateRelationalOperation(
const gd::String& relationalOperator,
const gd::String& lhs,
const gd::String& rhs) {
return lhs + " " + GenerateRelationalOperatorCodes(relationalOperator) + " " + rhs;
}
const gd::String EventsCodeGenerator::GenerateRelationalOperatorCodes(const gd::String &operatorString) {
if (operatorString == "=") {
return "==";
}
if (operatorString != "<" && operatorString != ">" &&
operatorString != "<=" && operatorString != ">=" && operatorString != "!=" &&
operatorString != "startsWith" && operatorString != "endsWith" && operatorString != "contains") {
cout << "Warning: Bad relational operator: Set to == by default." << endl;
return "==";
}
return operatorString;
} }
/** /**
@@ -124,7 +95,7 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
std::size_t operatorIndex = instrInfos.parameters.size(); std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i; if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
} }
// Ensure that there is at least one parameter after the operator // Ensure that there is at least one parameter after the operator
@@ -193,7 +164,7 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
std::size_t operatorIndex = instrInfos.parameters.size(); std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i; if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
} }
// Ensure that there is at least one parameter after the operator // Ensure that there is at least one parameter after the operator
@@ -244,7 +215,7 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
std::size_t operatorIndex = instrInfos.parameters.size(); std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i; if (instrInfos.parameters[i].type == "operator") operatorIndex = i;
} }
// Ensure that there is at least one parameter after the operator // Ensure that there is at least one parameter after the operator
@@ -290,18 +261,17 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
EventsCodeGenerationContext& context) { EventsCodeGenerationContext& context) {
gd::String conditionCode; gd::String conditionCode;
const gd::InstructionMetadata& instrInfos = gd::InstructionMetadata instrInfos =
MetadataProvider::GetConditionMetadata(platform, condition.GetType()); MetadataProvider::GetConditionMetadata(platform, condition.GetType());
if (MetadataProvider::IsBadInstructionMetadata(instrInfos)) {
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.GetIncludeFiles()); AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
maxConditionsListsSize = maxConditionsListsSize =
std::max(maxConditionsListsSize, condition.GetSubInstructions().size()); std::max(maxConditionsListsSize, condition.GetSubInstructions().size());
if (instrInfos.HasCustomCodeGenerator()) { if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
context.EnterCustomCondition(); context.EnterCustomCondition();
conditionCode += GenerateReferenceToUpperScopeBoolean(
"conditionTrue", returnBoolean, context);
conditionCode += instrInfos.codeExtraInformation.customCodeGenerator( conditionCode += instrInfos.codeExtraInformation.customCodeGenerator(
condition, *this, context); condition, *this, context);
maxCustomConditionsDepth = maxCustomConditionsDepth =
@@ -318,57 +288,68 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
condition.SetParameters(parameters); condition.SetParameters(parameters);
} }
// Verify that there are no mismatches between object type in parameters. // Verify that there are no mismatchs between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) { for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) { if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
gd::String objectInParameter = gd::String objectInParameter =
condition.GetParameter(pNb).GetPlainString(); condition.GetParameter(pNb).GetPlainString();
if (!GetObjectsContainersList().HasObjectOrGroupNamed(objectInParameter)) { if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
return "/* Unknown object - skipped. */"; !GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() && !GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
GetObjectsContainersList().GetTypeOfObject(objectInParameter) != !GetGlobalObjectsAndGroups().GetObjectGroups().Has(
instrInfos.parameters[pNb].GetExtraInfo()) { objectInParameter)) {
return "/* Mismatched object type - skipped. */"; condition.SetParameter(pNb, gd::Expression(""));
condition.SetType("");
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
condition.SetParameter(pNb, gd::Expression(""));
condition.SetType("");
} }
} }
} }
if (instrInfos.IsObjectInstruction()) { if (instrInfos.IsObjectInstruction()) {
gd::String objectName = condition.GetParameter(0).GetPlainString(); gd::String objectName = condition.GetParameter(0).GetPlainString();
gd::String objectType = gd::GetTypeOfObject(
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectName);
if (!objectName.empty() && !instrInfos.parameters.empty()) { if (!objectName.empty() && !instrInfos.parameters.empty()) {
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Set up the context // Set up the context
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
const ObjectMetadata& objInfo = const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType); MetadataProvider::GetObjectMetadata(platform, objectType);
AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
AddIncludeFiles(objInfo.includeFiles); // Prepare arguments and generate the condition whole code
context.SetCurrentObject(realObjects[i]); vector<gd::String> arguments = GenerateParametersCodes(
context.ObjectsListNeeded(realObjects[i]); condition.GetParameters(), instrInfos.parameters, context);
conditionCode += GenerateObjectCondition(realObjects[i],
objInfo,
arguments,
instrInfos,
returnBoolean,
condition.IsInverted(),
context);
// Prepare arguments and generate the condition whole code context.SetNoCurrentObject();
vector<gd::String> arguments = GenerateParametersCodes(
condition.GetParameters(), instrInfos.parameters, context);
conditionCode += GenerateObjectCondition(realObjects[i],
objInfo,
arguments,
instrInfos,
returnBoolean,
condition.IsInverted(),
context);
context.SetNoCurrentObject();
} }
} }
} else if (instrInfos.IsBehaviorInstruction()) { } else if (instrInfos.IsBehaviorInstruction()) {
gd::String objectName = condition.GetParameter(0).GetPlainString(); gd::String objectName = condition.GetParameter(0).GetPlainString();
gd::String behaviorType = GetObjectsContainersList().GetTypeOfBehavior(condition.GetParameter(1).GetPlainString()); gd::String behaviorType =
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
condition.GetParameter(1).GetPlainString());
if (instrInfos.parameters.size() >= 2) { if (instrInfos.parameters.size() >= 2) {
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context // Setup context
const BehaviorMetadata& autoInfo = const BehaviorMetadata& autoInfo =
@@ -444,11 +425,6 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
outputCode += "{\n"; outputCode += "{\n";
outputCode += conditionCode; outputCode += conditionCode;
outputCode += "}"; 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) */";
} }
} }
@@ -461,32 +437,19 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
* Generate code for an action. * Generate code for an action.
*/ */
gd::String EventsCodeGenerator::GenerateActionCode( gd::String EventsCodeGenerator::GenerateActionCode(
gd::Instruction& action, gd::Instruction& action, EventsCodeGenerationContext& context) {
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName) {
gd::String actionCode; gd::String actionCode;
const gd::InstructionMetadata& instrInfos = gd::InstructionMetadata instrInfos =
MetadataProvider::GetActionMetadata(platform, action.GetType()); MetadataProvider::GetActionMetadata(platform, action.GetType());
if (MetadataProvider::IsBadInstructionMetadata(instrInfos)) {
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.GetIncludeFiles()); AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
if (instrInfos.HasCustomCodeGenerator()) { if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
return instrInfos.codeExtraInformation.customCodeGenerator( return instrInfos.codeExtraInformation.customCodeGenerator(
action, *this, context); action, *this, context);
} }
// Get the correct function name depending on whether it should be async or
// not.
const gd::String& functionCallName =
instrInfos.IsAsync() &&
(!instrInfos.IsOptionallyAsync() || action.IsAwaited())
? instrInfos.codeExtraInformation.asyncFunctionCallName
: instrInfos.codeExtraInformation.functionCallName;
// Be sure there is no lack of parameter. // Be sure there is no lack of parameter.
while (action.GetParameters().size() < instrInfos.parameters.size()) { while (action.GetParameters().size() < instrInfos.parameters.size()) {
vector<gd::Expression> parameters = action.GetParameters(); vector<gd::Expression> parameters = action.GetParameters();
@@ -494,16 +457,24 @@ gd::String EventsCodeGenerator::GenerateActionCode(
action.SetParameters(parameters); action.SetParameters(parameters);
} }
// Verify that there are no mismatches between object type in parameters. // Verify that there are no mismatchs between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) { for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) { if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].type)) {
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString(); gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
if (!GetObjectsContainersList().HasObjectOrGroupNamed(objectInParameter)) { if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
return "/* Unknown object - skipped. */"; !GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() && !GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
GetObjectsContainersList().GetTypeOfObject(objectInParameter) != !GetGlobalObjectsAndGroups().GetObjectGroups().Has(
instrInfos.parameters[pNb].GetExtraInfo()) { objectInParameter)) {
return "/* Mismatched object type - skipped. */"; action.SetParameter(pNb, gd::Expression(""));
action.SetType("");
} else if (!instrInfos.parameters[pNb].supplementaryInformation.empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].supplementaryInformation) {
action.SetParameter(pNb, gd::Expression(""));
action.SetType("");
} }
} }
} }
@@ -511,41 +482,39 @@ gd::String EventsCodeGenerator::GenerateActionCode(
// Call free function first if available // Call free function first if available
if (instrInfos.IsObjectInstruction()) { if (instrInfos.IsObjectInstruction()) {
gd::String objectName = action.GetParameter(0).GetPlainString(); gd::String objectName = action.GetParameter(0).GetPlainString();
gd::String objectType = gd::GetTypeOfObject(
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), objectName);
if (!instrInfos.parameters.empty()) { if (!instrInfos.parameters.empty()) {
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context // Setup context
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
const ObjectMetadata& objInfo = const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType); MetadataProvider::GetObjectMetadata(platform, objectType);
AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
AddIncludeFiles(objInfo.includeFiles); // Prepare arguments and generate the whole action code
context.SetCurrentObject(realObjects[i]); vector<gd::String> arguments = GenerateParametersCodes(
context.ObjectsListNeeded(realObjects[i]); action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateObjectAction(
realObjects[i], objInfo, arguments, instrInfos, context);
// Prepare arguments and generate the whole action code context.SetNoCurrentObject();
vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateObjectAction(realObjects[i],
objInfo,
functionCallName,
arguments,
instrInfos,
context,
optionalAsyncCallbackName);
context.SetNoCurrentObject();
} }
} }
} else if (instrInfos.IsBehaviorInstruction()) { } else if (instrInfos.IsBehaviorInstruction()) {
gd::String objectName = action.GetParameter(0).GetPlainString(); gd::String objectName = action.GetParameter(0).GetPlainString();
gd::String behaviorType = GetObjectsContainersList().GetTypeOfBehavior(action.GetParameter(1).GetPlainString()); gd::String behaviorType =
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
action.GetParameter(1).GetPlainString());
if (instrInfos.parameters.size() >= 2) { if (instrInfos.parameters.size() >= 2) {
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context // Setup context
const BehaviorMetadata& autoInfo = const BehaviorMetadata& autoInfo =
@@ -561,11 +530,9 @@ gd::String EventsCodeGenerator::GenerateActionCode(
GenerateBehaviorAction(realObjects[i], GenerateBehaviorAction(realObjects[i],
action.GetParameter(1).GetPlainString(), action.GetParameter(1).GetPlainString(),
autoInfo, autoInfo,
functionCallName,
arguments, arguments,
instrInfos, instrInfos,
context, context);
optionalAsyncCallbackName);
context.SetNoCurrentObject(); context.SetNoCurrentObject();
} }
@@ -573,75 +540,12 @@ gd::String EventsCodeGenerator::GenerateActionCode(
} else { } else {
vector<gd::String> arguments = GenerateParametersCodes( vector<gd::String> arguments = GenerateParametersCodes(
action.GetParameters(), instrInfos.parameters, context); action.GetParameters(), instrInfos.parameters, context);
actionCode += GenerateFreeAction(functionCallName, actionCode += GenerateFreeAction(arguments, instrInfos, context);
arguments,
instrInfos,
context,
optionalAsyncCallbackName);
} }
return actionCode; return actionCode;
} }
const EventsCodeGenerator::CallbackDescriptor
EventsCodeGenerator::GenerateCallback(
const gd::String& callbackID,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents) {
gd::EventsCodeGenerationContext callbackContext;
callbackContext.InheritsAsAsyncCallbackFrom(parentContext);
const gd::String callbackFunctionName =
GetCodeNamespaceAccessor() + "asyncCallback" + callbackID;
const gd::String callbackFunctionArguments =
GenerateEventsParameters(callbackContext);
// Generate actions
gd::String actionsCode = GenerateActionsListCode(actions, callbackContext);
// Generate subevents
if (subEvents != nullptr) // Sub events
{
actionsCode += "\n{ //Subevents\n";
actionsCode += GenerateEventsListCode(*subEvents, callbackContext);
actionsCode += "} //End of subevents\n";
}
// Compose the callback function and add outside main
const gd::String actionsDeclarationsCode =
GenerateObjectsDeclarationCode(callbackContext);
const gd::String callbackCode = callbackFunctionName + " = function (" +
GenerateEventsParameters(callbackContext) +
") {\n" + actionsDeclarationsCode +
actionsCode + "}\n";
AddCustomCodeOutsideMain(callbackCode);
std::set<gd::String> requiredObjects;
// Build the list of all objects required by the callback. Any object that has
// already been declared could have gone through previous object picking, so
// if such an object is used by the actions or subevents of this callback, we
// must ask the caller to pass the already existing objects lists through a
// `LongLivedObjectsList` to the callback function.
for (const auto& objectUsedInSubTree :
callbackContext.GetAllDeclaredObjectsAcrossChildren()) {
if (callbackContext.ObjectAlreadyDeclaredByParents(objectUsedInSubTree))
requiredObjects.insert(objectUsedInSubTree);
};
return CallbackDescriptor(
callbackFunctionName, callbackFunctionArguments, requiredObjects);
};
const gd::String EventsCodeGenerator::GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context) {
gd::String parameters = "runtimeScene";
if (!HasProjectAndLayout()) parameters += ", eventsFunctionContext";
if (context.IsInsideAsync()) parameters += ", asyncObjectsList";
return parameters;
};
/** /**
* Generate actions code. * Generate actions code.
*/ */
@@ -652,14 +556,7 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
gd::String actionCode = GenerateActionCode(actions[aId], context); gd::String actionCode = GenerateActionCode(actions[aId], context);
outputCode += "{"; outputCode += "{";
if (actions[aId].GetType().empty()) { if (!actions[aId].GetType().empty()) outputCode += actionCode;
// 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 += "}"; outputCode += "}";
} }
@@ -667,7 +564,7 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
} }
gd::String EventsCodeGenerator::GenerateParameterCodes( gd::String EventsCodeGenerator::GenerateParameterCodes(
const gd::Expression& parameter, const gd::String& parameter,
const gd::ParameterMetadata& metadata, const gd::ParameterMetadata& metadata,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context,
const gd::String& lastObjectName, const gd::String& lastObjectName,
@@ -675,25 +572,30 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
supplementaryParametersTypes) { supplementaryParametersTypes) {
gd::String argOutput; gd::String argOutput;
if (ParameterMetadata::IsExpression("number", metadata.GetType())) { if (ParameterMetadata::IsExpression("number", metadata.type)) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode( argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "number", parameter, lastObjectName); *this, context, "number", parameter);
} else if (ParameterMetadata::IsExpression("string", metadata.GetType())) { } else if (ParameterMetadata::IsExpression("string", metadata.type)) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode( argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "string", parameter, lastObjectName); *this, context, "string", parameter);
} else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) { } else if (ParameterMetadata::IsExpression("variable", metadata.type)) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode( argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, metadata.GetType(), parameter, lastObjectName); *this, context, metadata.type, parameter, lastObjectName);
} else if (ParameterMetadata::IsObject(metadata.GetType())) { } else if (ParameterMetadata::IsObject(metadata.type)) {
// It would be possible to run a gd::ExpressionCodeGenerator if later // It would be possible to run a gd::ExpressionCodeGenerator if later
// objects can have nested objects, or function returning objects. // objects can have nested objects, or function returning objects.
argOutput = argOutput = GenerateObject(parameter, metadata.type, context);
GenerateObject(parameter.GetPlainString(), metadata.GetType(), context); } else if (metadata.type == "relationalOperator") {
} else if (metadata.GetType() == "relationalOperator") { argOutput += parameter == "=" ? "==" : parameter;
argOutput += parameter.GetPlainString(); if (argOutput != "==" && argOutput != "<" && argOutput != ">" &&
argOutput != "<=" && argOutput != ">=" && argOutput != "!=") {
cout << "Warning: Bad relational operator: Set to == by default." << endl;
argOutput = "==";
}
argOutput = "\"" + argOutput + "\""; argOutput = "\"" + argOutput + "\"";
} else if (metadata.GetType() == "operator") { } else if (metadata.type == "operator") {
argOutput += parameter.GetPlainString(); argOutput += parameter;
if (argOutput != "=" && argOutput != "+" && argOutput != "-" && if (argOutput != "=" && argOutput != "+" && argOutput != "-" &&
argOutput != "/" && argOutput != "*") { argOutput != "/" && argOutput != "*") {
cout << "Warning: Bad operator: Set to = by default." << endl; cout << "Warning: Bad operator: Set to = by default." << endl;
@@ -701,55 +603,41 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
} }
argOutput = "\"" + argOutput + "\""; argOutput = "\"" + argOutput + "\"";
} else if (ParameterMetadata::IsBehavior(metadata.GetType())) { } else if (ParameterMetadata::IsBehavior(metadata.type)) {
argOutput = GenerateGetBehaviorNameCode(parameter.GetPlainString()); argOutput = GenerateGetBehaviorNameCode(parameter);
} else if (metadata.GetType() == "key") { } else if (metadata.type == "key") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\""; argOutput = "\"" + ConvertToString(parameter) + "\"";
} else if (metadata.GetType() == "audioResource" || } else if (metadata.type == "password" || metadata.type == "musicfile" ||
metadata.GetType() == "bitmapFontResource" || metadata.type == "soundfile" || metadata.type == "police") {
metadata.GetType() == "fontResource" || argOutput = "\"" + ConvertToString(parameter) + "\"";
metadata.GetType() == "imageResource" || } else if (metadata.type == "mouse") {
metadata.GetType() == "jsonResource" || argOutput = "\"" + ConvertToString(parameter) + "\"";
metadata.GetType() == "tilemapResource" || } else if (metadata.type == "yesorno") {
metadata.GetType() == "tilesetResource" || argOutput += (parameter == "yes" || parameter == "oui") ? GenerateTrue()
metadata.GetType() == "videoResource" || : GenerateFalse();
metadata.GetType() == "model3DResource" || } else if (metadata.type == "trueorfalse") {
// Deprecated, old parameter names:
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.GetType() == "mouse") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.GetType() == "yesorno") {
auto parameterString = parameter.GetPlainString();
argOutput += (parameterString == "yes" || parameterString == "oui")
? GenerateTrue()
: GenerateFalse();
} else if (metadata.GetType() == "trueorfalse") {
auto parameterString = parameter.GetPlainString();
// This is duplicated in AdvancedExtension.cpp for GDJS // This is duplicated in AdvancedExtension.cpp for GDJS
argOutput += (parameterString == "True" || parameterString == "Vrai") argOutput += (parameter == "True" || parameter == "Vrai") ? GenerateTrue()
? GenerateTrue() : GenerateFalse();
: GenerateFalse();
} }
// Code only parameter type // Code only parameter type
else if (metadata.GetType() == "inlineCode") { else if (metadata.type == "inlineCode") {
argOutput += metadata.GetExtraInfo(); argOutput += metadata.supplementaryInformation;
} else { } else {
// Try supplementary types if provided // Try supplementary types if provided
if (supplementaryParametersTypes) { if (supplementaryParametersTypes) {
for (std::size_t i = 0; i < supplementaryParametersTypes->size(); ++i) { for (std::size_t i = 0; i < supplementaryParametersTypes->size(); ++i) {
if ((*supplementaryParametersTypes)[i].first == metadata.GetType()) if ((*supplementaryParametersTypes)[i].first == metadata.type)
argOutput += (*supplementaryParametersTypes)[i].second; argOutput += (*supplementaryParametersTypes)[i].second;
} }
} }
// Type unknown // Type unknown
if (argOutput.empty()) { if (argOutput.empty()) {
if (!metadata.GetType().empty()) if (!metadata.type.empty())
cout << "Warning: Unknown type of parameter \"" << metadata.GetType() cout << "Warning: Unknown type of parameter \"" << metadata.type
<< "\"." << std::endl; << "\"." << std::endl;
argOutput += "\"" + ConvertToString(parameter.GetPlainString()) + "\""; argOutput += "\"" + ConvertToString(parameter) + "\"";
} }
} }
@@ -769,7 +657,7 @@ vector<gd::String> EventsCodeGenerator::GenerateParametersCodes(
parametersInfo, parametersInfo,
[this, &context, &supplementaryParametersTypes, &arguments]( [this, &context, &supplementaryParametersTypes, &arguments](
const gd::ParameterMetadata& parameterMetadata, const gd::ParameterMetadata& parameterMetadata,
const gd::Expression& parameterValue, const gd::String& parameterValue,
const gd::String& lastObjectName) { const gd::String& lastObjectName) {
gd::String argOutput = gd::String argOutput =
GenerateParameterCodes(parameterValue, GenerateParameterCodes(parameterValue,
@@ -821,21 +709,23 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
gd::String declarationsCode; gd::String declarationsCode;
for (auto object : context.GetObjectsListsToBeDeclared()) { for (auto object : context.GetObjectsListsToBeDeclared()) {
gd::String objectListDeclaration = ""; gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclaredByParents(object)) { if (!context.ObjectAlreadyDeclared(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " + objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + GetObjectListName(object, context) +
" = runtimeContext->GetObjectsRawPointers(\"" + " = runtimeContext->GetObjectsRawPointers(\"" +
ConvertToString(object) + "\");\n"; ConvertToString(object) + "\");\n";
context.SetObjectDeclared(object);
} else } else
objectListDeclaration = declareObjectList(object, context); objectListDeclaration = declareObjectList(object, context);
declarationsCode += objectListDeclaration + "\n"; declarationsCode += objectListDeclaration + "\n";
} }
for (auto object : context.GetObjectsListsToBeEmptyIfJustDeclared()) { for (auto object : context.GetObjectsListsToBeDeclaredWithoutPicking()) {
gd::String objectListDeclaration = ""; gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclaredByParents(object)) { if (!context.ObjectAlreadyDeclared(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " + objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n"; GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else } else
objectListDeclaration = declareObjectList(object, context); objectListDeclaration = declareObjectList(object, context);
@@ -843,9 +733,10 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
} }
for (auto object : context.GetObjectsListsToBeDeclaredEmpty()) { for (auto object : context.GetObjectsListsToBeDeclaredEmpty()) {
gd::String objectListDeclaration = ""; gd::String objectListDeclaration = "";
if (!context.ObjectAlreadyDeclaredByParents(object)) { if (!context.ObjectAlreadyDeclared(object)) {
objectListDeclaration = "std::vector<RuntimeObject*> " + objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n"; GetObjectListName(object, context) + ";\n";
context.SetObjectDeclared(object);
} else } else
objectListDeclaration = "std::vector<RuntimeObject*> " + objectListDeclaration = "std::vector<RuntimeObject*> " +
GetObjectListName(object, context) + ";\n"; GetObjectListName(object, context) + ";\n";
@@ -860,7 +751,7 @@ gd::String EventsCodeGenerator::GenerateObjectsDeclarationCode(
* Generate events list code. * Generate events list code.
*/ */
gd::String EventsCodeGenerator::GenerateEventsListCode( gd::String EventsCodeGenerator::GenerateEventsListCode(
gd::EventsList& events, EventsCodeGenerationContext& parentContext) { gd::EventsList& events, const EventsCodeGenerationContext& parentContext) {
gd::String output; gd::String output;
for (std::size_t eId = 0; eId < events.size(); ++eId) { for (std::size_t eId = 0; eId < events.size(); ++eId) {
// Each event has its own context : Objects picked in an event are totally // Each event has its own context : Objects picked in an event are totally
@@ -876,8 +767,6 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
// operation. // operation.
bool reuseParentContext = bool reuseParentContext =
parentContext.CanReuse() && eId == events.size() - 1; parentContext.CanReuse() && eId == events.size() - 1;
// TODO: avoid creating if useless.
gd::EventsCodeGenerationContext reusedContext; gd::EventsCodeGenerationContext reusedContext;
reusedContext.Reuse(parentContext); reusedContext.Reuse(parentContext);
@@ -909,6 +798,41 @@ gd::String EventsCodeGenerator::ConvertToStringExplicit(
return "\"" + ConvertToString(plainString) + "\""; return "\"" + ConvertToString(plainString) + "\"";
} }
std::vector<gd::String> EventsCodeGenerator::ExpandObjectsName(
const gd::String& objectName,
const EventsCodeGenerationContext& context) const {
// Note: this logic is duplicated in EventsContextAnalyzer::ExpandObjectsName
std::vector<gd::String> realObjects;
if (globalObjectsAndGroups.GetObjectGroups().Has(objectName))
realObjects = globalObjectsAndGroups.GetObjectGroups()
.Get(objectName)
.GetAllObjectsNames();
else if (objectsAndGroups.GetObjectGroups().Has(objectName))
realObjects =
objectsAndGroups.GetObjectGroups().Get(objectName).GetAllObjectsNames();
else
realObjects.push_back(objectName);
// If current object is present, use it and only it.
if (find(realObjects.begin(),
realObjects.end(),
context.GetCurrentObject()) != realObjects.end()) {
realObjects.clear();
realObjects.push_back(context.GetCurrentObject());
}
// Ensure that all returned objects actually exists.
for (std::size_t i = 0; i < realObjects.size();) {
if (!objectsAndGroups.HasObjectNamed(realObjects[i]) &&
!globalObjectsAndGroups.HasObjectNamed(realObjects[i]))
realObjects.erase(realObjects.begin() + i);
else
++i;
}
return realObjects;
}
void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) { void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) {
for (std::size_t eId = events.size() - 1; eId < events.size(); --eId) { for (std::size_t eId = events.size() - 1; eId < events.size(); --eId) {
if (events[eId].CanHaveSubEvents()) // Process sub events, if any if (events[eId].CanHaveSubEvents()) // Process sub events, if any
@@ -925,8 +849,6 @@ void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) {
*/ */
void EventsCodeGenerator::PreprocessEventList(gd::EventsList& listEvent) { void EventsCodeGenerator::PreprocessEventList(gd::EventsList& listEvent) {
for (std::size_t i = 0; i < listEvent.GetEventsCount(); ++i) { for (std::size_t i = 0; i < listEvent.GetEventsCount(); ++i) {
if (listEvent[i].IsDisabled()) continue;
listEvent[i].Preprocess(*this, listEvent, i); listEvent[i].Preprocess(*this, listEvent, i);
if (i < if (i <
listEvent.GetEventsCount()) { // Be sure that that there is still an listEvent.GetEventsCount()) { // Be sure that that there is still an
@@ -972,15 +894,15 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
bool conditionInverted, bool conditionInverted,
gd::EventsCodeGenerationContext& context) { gd::EventsCodeGenerationContext& context) {
// Generate call // Generate call
gd::String predicate; gd::String predicat;
if (instrInfos.codeExtraInformation.type == "number" || if (instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string") { instrInfos.codeExtraInformation.type == "string") {
predicate = GenerateRelationalOperatorCall( predicat = GenerateRelationalOperatorCall(
instrInfos, instrInfos,
arguments, arguments,
instrInfos.codeExtraInformation.functionCallName); instrInfos.codeExtraInformation.functionCallName);
} else { } else {
predicate = instrInfos.codeExtraInformation.functionCallName + "(" + predicat = instrInfos.codeExtraInformation.functionCallName + "(" +
GenerateArgumentsList(arguments, 0) + ")"; GenerateArgumentsList(arguments, 0) + ")";
} }
@@ -989,14 +911,14 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
for (std::size_t i = 0; i < instrInfos.parameters.size(); for (std::size_t i = 0; i < instrInfos.parameters.size();
++i) // Some conditions already have a "conditionInverted" parameter ++i) // Some conditions already have a "conditionInverted" parameter
{ {
if (instrInfos.parameters[i].GetType() == "conditionInverted") if (instrInfos.parameters[i].type == "conditionInverted")
conditionAlreadyTakeCareOfInversion = true; conditionAlreadyTakeCareOfInversion = true;
} }
if (!conditionAlreadyTakeCareOfInversion && conditionInverted) if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
predicate = GenerateNegatedPredicate(predicate); predicat = GenerateNegatedPredicat(predicat);
// Generate condition code // Generate condition code
return returnBoolean + " = " + predicate + ";\n"; return returnBoolean + " = " + predicat + ";\n";
} }
gd::String EventsCodeGenerator::GenerateObjectCondition( gd::String EventsCodeGenerator::GenerateObjectCondition(
@@ -1010,7 +932,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
// Prepare call // Prepare call
// Add a static_cast if necessary // Add a static_cast if necessary
gd::String objectFunctionCallNamePart = gd::String objectFunctionCallNamePart =
(!instrInfos.parameters[0].GetExtraInfo().empty()) (!instrInfos.parameters[0].supplementaryInformation.empty())
? "static_cast<" + objInfo.className + "*>(" + ? "static_cast<" + objInfo.className + "*>(" +
GetObjectListName(objectName, context) + "[i])->" + GetObjectListName(objectName, context) + "[i])->" +
instrInfos.codeExtraInformation.functionCallName instrInfos.codeExtraInformation.functionCallName
@@ -1018,18 +940,18 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
instrInfos.codeExtraInformation.functionCallName; instrInfos.codeExtraInformation.functionCallName;
// Create call // Create call
gd::String predicate; gd::String predicat;
if ((instrInfos.codeExtraInformation.type == "number" || if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) { instrInfos.codeExtraInformation.type == "string")) {
predicate = GenerateRelationalOperatorCall( predicat = GenerateRelationalOperatorCall(
instrInfos, arguments, objectFunctionCallNamePart, 1); instrInfos, arguments, objectFunctionCallNamePart, 1);
} else { } else {
predicate = objectFunctionCallNamePart + "(" + predicat = objectFunctionCallNamePart + "(" +
GenerateArgumentsList(arguments, 1) + ")"; GenerateArgumentsList(arguments, 1) + ")";
} }
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate); if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
return "For each picked object \"" + objectName + "\", check " + predicate + return "For each picked object \"" + objectName + "\", check " + predicat +
".\n"; ".\n";
} }
@@ -1043,25 +965,23 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
bool conditionInverted, bool conditionInverted,
gd::EventsCodeGenerationContext& context) { gd::EventsCodeGenerationContext& context) {
// Create call // Create call
gd::String predicate; gd::String predicat;
if ((instrInfos.codeExtraInformation.type == "number" || if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) { instrInfos.codeExtraInformation.type == "string")) {
predicate = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2); predicat = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
} else { } else {
predicate = "(" + GenerateArgumentsList(arguments, 2) + ")"; predicat = "(" + GenerateArgumentsList(arguments, 2) + ")";
} }
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate); if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
return "For each picked object \"" + objectName + "\", check " + predicate + return "For each picked object \"" + objectName + "\", check " + predicat +
" for behavior \"" + behaviorName + "\".\n"; " for behavior \"" + behaviorName + "\".\n";
} }
gd::String EventsCodeGenerator::GenerateFreeAction( gd::String EventsCodeGenerator::GenerateFreeAction(
const gd::String& functionCallName,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context) {
const gd::String& optionalAsyncCallbackName) {
// Generate call // Generate call
gd::String call; gd::String call;
if (instrInfos.codeExtraInformation.type == "number" || if (instrInfos.codeExtraInformation.type == "number" ||
@@ -1071,39 +991,32 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
call = GenerateOperatorCall( call = GenerateOperatorCall(
instrInfos, instrInfos,
arguments, arguments,
functionCallName, instrInfos.codeExtraInformation.functionCallName,
instrInfos.codeExtraInformation.optionalAssociatedInstruction); instrInfos.codeExtraInformation.optionalAssociatedInstruction);
else if (instrInfos.codeExtraInformation.accessType == else if (instrInfos.codeExtraInformation.accessType ==
gd::InstructionMetadata::ExtraInformation::Mutators) gd::InstructionMetadata::ExtraInformation::Mutators)
call = call =
GenerateMutatorCall(instrInfos, GenerateMutatorCall(instrInfos,
arguments, arguments,
functionCallName); instrInfos.codeExtraInformation.functionCallName);
else else
call = GenerateCompoundOperatorCall( call = GenerateCompoundOperatorCall(
instrInfos, instrInfos,
arguments, arguments,
functionCallName); instrInfos.codeExtraInformation.functionCallName);
} else { } else {
call = functionCallName + "(" + call = instrInfos.codeExtraInformation.functionCallName + "(" +
GenerateArgumentsList(arguments) + ")"; GenerateArgumentsList(arguments) + ")";
} }
if (!optionalAsyncCallbackName.empty())
call = "runtimeScene.getAsyncTasksManager().addTask(" + call + ", " +
optionalAsyncCallbackName + ")";
return call + ";\n"; return call + ";\n";
} }
gd::String EventsCodeGenerator::GenerateObjectAction( gd::String EventsCodeGenerator::GenerateObjectAction(
const gd::String& objectName, const gd::String& objectName,
const gd::ObjectMetadata& objInfo, const gd::ObjectMetadata& objInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context) {
const gd::String& optionalAsyncCallbackName) {
// Create call // Create call
gd::String call; gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" || if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1113,26 +1026,25 @@ gd::String EventsCodeGenerator::GenerateObjectAction(
call = GenerateOperatorCall( call = GenerateOperatorCall(
instrInfos, instrInfos,
arguments, arguments,
functionCallName, instrInfos.codeExtraInformation.functionCallName,
instrInfos.codeExtraInformation.optionalAssociatedInstruction, instrInfos.codeExtraInformation.optionalAssociatedInstruction,
2); 2);
else else
call = GenerateCompoundOperatorCall( call = GenerateCompoundOperatorCall(
instrInfos, arguments, functionCallName, 2); instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName,
2);
return "For each picked object \"" + objectName + "\", call " + call + return "For each picked object \"" + objectName + "\", call " + call +
".\n"; ".\n";
} else { } else {
gd::String argumentsStr = GenerateArgumentsList(arguments, 1); gd::String argumentsStr = GenerateArgumentsList(arguments, 1);
call = functionCallName + "(" + argumentsStr + ")"; call = instrInfos.codeExtraInformation.functionCallName + "(" +
argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" + return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ")" + argumentsStr + ").\n";
(optionalAsyncCallbackName.empty()
? ""
: (", then call" + optionalAsyncCallbackName)) +
".\n";
} }
} }
@@ -1140,11 +1052,9 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
const gd::String& objectName, const gd::String& objectName,
const gd::String& behaviorName, const gd::String& behaviorName,
const gd::BehaviorMetadata& autoInfo, const gd::BehaviorMetadata& autoInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context) {
const gd::String& optionalAsyncCallbackName) {
// Create call // Create call
gd::String call; gd::String call;
if ((instrInfos.codeExtraInformation.type == "number" || if ((instrInfos.codeExtraInformation.type == "number" ||
@@ -1154,29 +1064,24 @@ gd::String EventsCodeGenerator::GenerateBehaviorAction(
call = GenerateOperatorCall( call = GenerateOperatorCall(
instrInfos, instrInfos,
arguments, arguments,
functionCallName, instrInfos.codeExtraInformation.functionCallName,
instrInfos.codeExtraInformation.optionalAssociatedInstruction, instrInfos.codeExtraInformation.optionalAssociatedInstruction,
2); 2);
else else
call = GenerateCompoundOperatorCall( call = GenerateCompoundOperatorCall(
instrInfos, instrInfos,
arguments, arguments,
functionCallName, instrInfos.codeExtraInformation.functionCallName,
2); 2);
return "For each picked object \"" + objectName + "\", call " + call + return "For each picked object \"" + objectName + "\", call " + call +
" for behavior \"" + behaviorName + "\".\n"; " for behavior \"" + behaviorName + "\".\n";
} else { } else {
gd::String argumentsStr = GenerateArgumentsList(arguments, 2); gd::String argumentsStr = GenerateArgumentsList(arguments, 2);
call = functionCallName + "(" + call = instrInfos.codeExtraInformation.functionCallName + "(" +
argumentsStr + ")"; argumentsStr + ")";
return "For each picked object \"" + objectName + "\", call " + call + "(" + return "For each picked object \"" + objectName + "\", call " + call + "(" +
argumentsStr + ")" + " for behavior \"" + behaviorName + "\"" + argumentsStr + ")" + " for behavior \"" + behaviorName + "\".\n";
(optionalAsyncCallbackName.empty()
? ""
: (", then call" + optionalAsyncCallbackName)) +
".\n";
} }
} }
@@ -1192,7 +1097,7 @@ size_t EventsCodeGenerator::GenerateSingleUsageUniqueIdFor(
<< std::endl; << std::endl;
} }
// Base the unique id on the address in memory so that the same instruction // Base the unique id on the adress in memory so that the same instruction
// in memory will get the same id across different code generations. // in memory will get the same id across different code generations.
size_t uniqueId = (size_t)instruction; size_t uniqueId = (size_t)instruction;
@@ -1224,24 +1129,12 @@ gd::String EventsCodeGenerator::GenerateArgumentsList(
return argumentsStr; return argumentsStr;
} }
gd::String EventsCodeGenerator::GeneratePropertyGetter(const gd::PropertiesContainer& propertiesContainer, EventsCodeGenerator::EventsCodeGenerator(gd::Project& project_,
const gd::NamedPropertyDescriptor& property,
const gd::String& type,
gd::EventsCodeGenerationContext& context) {
return "getProperty" + property.GetName() + "As" + type + "()";
}
gd::String EventsCodeGenerator::GenerateParameterGetter(const gd::ParameterMetadata& parameter,
const gd::String& type,
gd::EventsCodeGenerationContext& context) {
return "getParameter" + parameter.GetName() + "As" + type + "()";
}
EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
const gd::Layout& layout, const gd::Layout& layout,
const gd::Platform& platform_) const gd::Platform& platform_)
: platform(platform_), : platform(platform_),
projectScopedContainers(gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project_, layout)), globalObjectsAndGroups(project_),
objectsAndGroups(layout),
hasProjectAndLayout(true), hasProjectAndLayout(true),
project(&project_), project(&project_),
scene(&layout), scene(&layout),
@@ -1253,9 +1146,11 @@ EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
EventsCodeGenerator::EventsCodeGenerator( EventsCodeGenerator::EventsCodeGenerator(
const gd::Platform& platform_, const gd::Platform& platform_,
const gd::ProjectScopedContainers& projectScopedContainers_) gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& objectsAndGroups_)
: platform(platform_), : platform(platform_),
projectScopedContainers(projectScopedContainers_), globalObjectsAndGroups(globalObjectsAndGroups_),
objectsAndGroups(objectsAndGroups_),
hasProjectAndLayout(false), hasProjectAndLayout(false),
project(nullptr), project(nullptr),
scene(nullptr), scene(nullptr),

View File

@@ -12,7 +12,6 @@
#include "GDCore/Events/Event.h" #include "GDCore/Events/Event.h"
#include "GDCore/Events/Instruction.h" #include "GDCore/Events/Instruction.h"
#include "GDCore/Project/ProjectScopedContainers.h"
#include "GDCore/String.h" #include "GDCore/String.h"
namespace gd { namespace gd {
class EventsList; class EventsList;
@@ -20,7 +19,6 @@ class Expression;
class Project; class Project;
class Layout; class Layout;
class ObjectsContainer; class ObjectsContainer;
class ObjectsContainersList;
class ExternalEvents; class ExternalEvents;
class ParameterMetadata; class ParameterMetadata;
class ObjectMetadata; class ObjectMetadata;
@@ -50,7 +48,7 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Construct a code generator for the specified * \brief Construct a code generator for the specified
* platform/project/layout. * platform/project/layout.
*/ */
EventsCodeGenerator(const gd::Project& project_, EventsCodeGenerator(gd::Project& project_,
const gd::Layout& layout, const gd::Layout& layout,
const gd::Platform& platform_); const gd::Platform& platform_);
@@ -58,9 +56,9 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Construct a code generator for the specified * \brief Construct a code generator for the specified
* objects/groups and platform * objects/groups and platform
*/ */
EventsCodeGenerator( EventsCodeGenerator(const gd::Platform& platform,
const gd::Platform& platform, gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ProjectScopedContainers& projectScopedContainers_); const gd::ObjectsContainer& objectsAndGroups_);
virtual ~EventsCodeGenerator(){}; virtual ~EventsCodeGenerator(){};
/** /**
@@ -79,7 +77,7 @@ class GD_CORE_API EventsCodeGenerator {
* \return Code * \return Code
*/ */
virtual gd::String GenerateEventsListCode( virtual gd::String GenerateEventsListCode(
gd::EventsList& events, EventsCodeGenerationContext& context); gd::EventsList& events, const EventsCodeGenerationContext& context);
/** /**
* \brief Generate code for executing a condition list * \brief Generate code for executing a condition list
@@ -156,54 +154,8 @@ class GD_CORE_API EventsCodeGenerator {
* \param context Context used for generation * \param context Context used for generation
* \return Code * \return Code
*/ */
gd::String GenerateActionCode( gd::String GenerateActionCode(gd::Instruction& action,
gd::Instruction& action, EventsCodeGenerationContext& context);
EventsCodeGenerationContext& context,
const gd::String& optionalAsyncCallbackName = "");
struct CallbackDescriptor {
CallbackDescriptor(const gd::String functionName_,
const gd::String argumentsList_,
const std::set<gd::String> requiredObjects_)
: functionName(functionName_),
argumentsList(argumentsList_),
requiredObjects(requiredObjects_){};
/**
* The name by which the function can be invoked.
*/
const gd::String functionName;
/**
* The comma separated list of arguments that the function takes.
*/
const gd::String argumentsList;
/**
* A set of all objects that need to be backed up to be passed to the
* callback code.
*/
const std::set<gd::String> requiredObjects;
};
/**
* \brief Generates actions and events as a callback.
*
* This is used by asynchronous functions to run the code out of the normal
* events flow.
*
* \returns A set with all objects required by the callback code.
* The caller must take care of backing them up in a LongLivedObjectsList,
* and to pass it to the callback function as the last argument.
*/
virtual const CallbackDescriptor GenerateCallback(
const gd::String& callbackFunctionName,
gd::EventsCodeGenerationContext& parentContext,
gd::InstructionsList& actions,
gd::EventsList* subEvents = nullptr);
/**
* \brief Generates the parameters list of an event's generated function.
*/
const gd::String GenerateEventsParameters(
const gd::EventsCodeGenerationContext& context);
/** /**
* \brief Generate code for declaring objects lists. * \brief Generate code for declaring objects lists.
@@ -328,12 +280,18 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
bool ErrorOccurred() const { return errorOccurred; }; bool ErrorOccurred() const { return errorOccurred; };
const gd::ObjectsContainersList& GetObjectsContainersList() const { /**
return projectScopedContainers.GetObjectsContainersList(); * \brief Get the global objects/groups used for code generation.
}; */
gd::ObjectsContainer& GetGlobalObjectsAndGroups() const {
return globalObjectsAndGroups;
}
const gd::ProjectScopedContainers& GetProjectScopedContainers() const { /**
return projectScopedContainers; * \brief Get the objects/groups used for code generation.
*/
const gd::ObjectsContainer& GetObjectsAndGroups() const {
return objectsAndGroups;
} }
/** /**
@@ -346,7 +304,7 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Get the project the code is being generated for. * \brief Get the project the code is being generated for.
* \warning This is only valid if HasProjectAndLayout() is true. * \warning This is only valid if HasProjectAndLayout() is true.
*/ */
const gd::Project& GetProject() const { return *project; } gd::Project& GetProject() const { return *project; }
/** /**
* \brief Get the layout the code is being generated for. * \brief Get the layout the code is being generated for.
@@ -359,6 +317,22 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
const gd::Platform& GetPlatform() const { return platform; } const gd::Platform& GetPlatform() const { return platform; }
/**
* \brief Convert a group name to the full list of objects contained in the
* group.
*
* Get a list containing the "real" objects name when the events refers to \a
* objectName :<br> If \a objectName is really an object, the list will only
* contains \a objectName unchanged.<br> If \a objectName is a group, the list
* will contains all the objects of the group.<br> If \a objectName is the
* "current" object in the context ( i.e: The object being used for launching
* an action... ), none of the two rules below apply, and the list will only
* contains the context "current" object name.
*/
std::vector<gd::String> ExpandObjectsName(
const gd::String& objectName,
const EventsCodeGenerationContext& context) const;
/** /**
* \brief Get the maximum depth of custom conditions reached during code * \brief Get the maximum depth of custom conditions reached during code
* generation. * generation.
@@ -384,18 +358,6 @@ class GD_CORE_API EventsCodeGenerator {
return boolName; return boolName;
} }
/**
* \brief Generate the full name for accessing to a boolean variable used for
* conditions.
*
* Default implementation just returns the boolean name passed as argument.
*/
virtual gd::String GenerateUpperScopeBooleanFullName(
const gd::String& boolName,
const gd::EventsCodeGenerationContext& context) {
return boolName;
}
/** /**
* \brief Must create a boolean. Its value must be false. * \brief Must create a boolean. Its value must be false.
* *
@@ -473,15 +435,7 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
size_t GenerateSingleUsageUniqueIdForEventsList(); size_t GenerateSingleUsageUniqueIdForEventsList();
virtual gd::String GenerateRelationalOperation(
const gd::String& relationalOperator,
const gd::String& lhs,
const gd::String& rhs);
protected: protected:
virtual const gd::String GenerateRelationalOperatorCodes(
const gd::String& operatorString);
/** /**
* \brief Generate the code for a single parameter. * \brief Generate the code for a single parameter.
* *
@@ -490,9 +444,9 @@ class GD_CORE_API EventsCodeGenerator {
* - object : Object name -> string * - object : Object name -> string
* - expression : Mathematical expression -> number (double) * - expression : Mathematical expression -> number (double)
* - string : %Text expression -> string * - string : %Text expression -> string
* - layer, color, file, stringWithSelector : Same as string * - layer, color, file, joyaxis : Same as string
* - relationalOperator : Used to make a comparison between the function * - relationalOperator : Used to make a comparison between the function
return value and value of the parameter preceding the relationOperator resturn value and value of the parameter preceding the relationOperator
parameter -> string parameter -> string
* - operator : Used to update a value using a setter and a getter -> string * - operator : Used to update a value using a setter and a getter -> string
* - key, mouse, objectvar, scenevar, globalvar, password, musicfile, * - key, mouse, objectvar, scenevar, globalvar, password, musicfile,
@@ -508,18 +462,28 @@ class GD_CORE_API EventsCodeGenerator {
* Other standard parameters type that should be implemented by platforms: * Other standard parameters type that should be implemented by platforms:
* - currentScene: Reference to the current runtime scene. * - currentScene: Reference to the current runtime scene.
* - objectList : a map containing lists of objects which are specified by the * - objectList : a map containing lists of objects which are specified by the
object name in another parameter. object name in another parameter. (C++: std::map <gd::String,
* - objectListOrEmptyIfJustDeclared : Same as `objectList` but do not pick std::vector<RuntimeObject*> *>). Example:
object if they are not already picked. * \code
* - objectPtr: Return a reference to the object specified by the object name AddExpression("Count", _("Object count"), _("Count the number of picked
in another parameter. Example: objects"), _("Objects"), "res/conditions/nbObjet.png")
.AddParameter("objectList", _("Object"))
.SetFunctionName("PickedObjectsCount").SetIncludeFile("GDCpp/Extensions/Builtin/ObjectTools.h");
* \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:
* \code * \code
.AddParameter("object", _("Object")) .AddParameter("object", _("Object"))
.AddParameter("objectPtr", _("Target object")) .AddParameter("objectPtr", _("Target object"))
//The called function will be called with this signature on the C++ platform:
Function(gd::String, RuntimeObject*)
* \endcode * \endcode
*/ */
virtual gd::String GenerateParameterCodes( virtual gd::String GenerateParameterCodes(
const gd::Expression& parameter, const gd::String& parameter,
const gd::ParameterMetadata& metadata, const gd::ParameterMetadata& metadata,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context,
const gd::String& lastObjectName, const gd::String& lastObjectName,
@@ -551,12 +515,6 @@ class GD_CORE_API EventsCodeGenerator {
return ".getChild(" + ConvertToStringExplicit(childName) + ")"; return ".getChild(" + ConvertToStringExplicit(childName) + ")";
}; };
virtual gd::String GenerateVariableValueAs(const gd::String& type) {
return type == "number|string" ? ".getAsNumberOrString()"
: type == "string" ? ".getAsString()"
: ".getAsNumber()";
}
/** /**
* \brief Generate the code to get the child of a variable, * \brief Generate the code to get the child of a variable,
* using generated the expression. * using generated the expression.
@@ -585,17 +543,6 @@ class GD_CORE_API EventsCodeGenerator {
return "fakeObjectListOf_" + objectName; return "fakeObjectListOf_" + objectName;
} }
virtual gd::String GeneratePropertyGetter(
const gd::PropertiesContainer& propertiesContainer,
const gd::NamedPropertyDescriptor& property,
const gd::String& type,
gd::EventsCodeGenerationContext& context);
virtual gd::String GenerateParameterGetter(
const gd::ParameterMetadata& parameter,
const gd::String& type,
gd::EventsCodeGenerationContext& context);
/** /**
* \brief Generate the code to reference an object which is * \brief Generate the code to reference an object which is
* in an empty/null state. * in an empty/null state.
@@ -670,16 +617,28 @@ class GD_CORE_API EventsCodeGenerator {
}; };
/** /**
* \brief Must negate a predicate. * \brief Must negate a predicat.
* *
* The default implementation generates C-style code : It wraps the predicate * The default implementation generates C-style code : It wraps the predicat
* inside parenthesis and add a !. * inside parenthesis and add a !.
*/ */
virtual gd::String GenerateNegatedPredicate( virtual gd::String GenerateNegatedPredicat(const gd::String& predicat) const {
const gd::String& predicate) const { return "!(" + predicat + ")";
return "!(" + predicate + ")";
}; };
/**
* \brief Must create a boolean which is a reference to a boolean declared in
* the parent scope.
*
* The default implementation generates C-style code.
*/
virtual gd::String GenerateReferenceToUpperScopeBoolean(
const gd::String& referenceName,
const gd::String& referencedBoolean,
gd::EventsCodeGenerationContext& context) {
return "bool & " + referenceName + " = " + referencedBoolean + ";\n";
}
virtual gd::String GenerateFreeCondition( virtual gd::String GenerateFreeCondition(
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
@@ -707,37 +666,30 @@ class GD_CORE_API EventsCodeGenerator {
gd::EventsCodeGenerationContext& context); gd::EventsCodeGenerationContext& context);
virtual gd::String GenerateFreeAction( virtual gd::String GenerateFreeAction(
const gd::String& functionCallName,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context);
const gd::String& optionalAsyncCallbackName = "");
virtual gd::String GenerateObjectAction( virtual gd::String GenerateObjectAction(
const gd::String& objectName, const gd::String& objectName,
const gd::ObjectMetadata& objInfo, const gd::ObjectMetadata& objInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context);
const gd::String& optionalAsyncCallbackName = "");
virtual gd::String GenerateBehaviorAction( virtual gd::String GenerateBehaviorAction(
const gd::String& objectName, const gd::String& objectName,
const gd::String& behaviorName, const gd::String& behaviorName,
const gd::BehaviorMetadata& autoInfo, const gd::BehaviorMetadata& autoInfo,
const gd::String& functionCallName,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context);
const gd::String& optionalAsyncCallbackName = "");
gd::String GenerateRelationalOperatorCall( gd::String GenerateRelationalOperatorCall(
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::String& callStartString, const gd::String& callStartString,
std::size_t startFromArgument = 0); std::size_t startFromArgument = 0);
gd::String GenerateOperatorCall(const gd::InstructionMetadata& instrInfos, gd::String GenerateOperatorCall(const gd::InstructionMetadata& instrInfos,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::String& callStartString, const gd::String& callStartString,
@@ -781,14 +733,15 @@ class GD_CORE_API EventsCodeGenerator {
const gd::Platform& platform; ///< The platform being used. const gd::Platform& platform; ///< The platform being used.
gd::ProjectScopedContainers projectScopedContainers; gd::ObjectsContainer& globalObjectsAndGroups;
const gd::ObjectsContainer& objectsAndGroups;
bool hasProjectAndLayout; ///< true only if project and layout are valid bool hasProjectAndLayout; ///< true only if project and layout are valid
///< references. If false, they should not be used. ///< references. If false, they should not be used.
const gd::Project* project; ///< The project being used. gd::Project* project; ///< The project being used.
const gd::Layout* scene; ///< The scene being generated. const gd::Layout* scene; ///< The scene being generated.
bool errorOccurred; ///< Must be set to true if an error occurred. bool errorOccurred; ///< Must be set to true if an error occured.
bool compilationForRuntime; ///< Is set to true if the code generation is bool compilationForRuntime; ///< Is set to true if the code generation is
///< made for runtime only. ///< made for runtime only.

View File

@@ -7,7 +7,6 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <vector>
#include "GDCore/CommonTools.h" #include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
@@ -26,40 +25,36 @@
#include "GDCore/IDE/Events/ExpressionValidator.h" #include "GDCore/IDE/Events/ExpressionValidator.h"
#include "GDCore/Project/Layout.h" #include "GDCore/Project/Layout.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
#include "GDCore/Project/VariablesContainersList.h"
#include "GDCore/Project/ObjectsContainersList.h"
#include "GDCore/Project/ProjectScopedContainers.h"
#include "GDCore/IDE/Events/ExpressionTypeFinder.h"
#include "GDCore/IDE/Events/ExpressionVariableOwnerFinder.h"
namespace gd { namespace gd {
gd::String ExpressionCodeGenerator::GenerateExpressionCode( gd::String ExpressionCodeGenerator::GenerateExpressionCode(
EventsCodeGenerator& codeGenerator, EventsCodeGenerator& codeGenerator,
EventsCodeGenerationContext& context, EventsCodeGenerationContext& context,
const gd::String& rootType, const gd::String& type,
const gd::Expression& expression, const gd::String& expression,
const gd::String& rootObjectName) { const gd::String& objectName) {
ExpressionCodeGenerator generator(rootType, rootObjectName, codeGenerator, context); gd::ExpressionParser2 parser(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups());
ExpressionCodeGenerator generator(codeGenerator, context);
auto node = expression.GetRootNode(); auto node = parser.ParseExpression(type, expression, objectName);
if (!node) { if (!node) {
std::cout << "Error: error while parsing: \"" << expression.GetPlainString() std::cout << "Error: error while parsing: \"" << expression << "\" ("
<< "\" (" << rootType << ")" << std::endl; << type << ")" << std::endl;
return generator.GenerateDefaultValue(rootType); return generator.GenerateDefaultValue(type);
} }
gd::ExpressionValidator validator(codeGenerator.GetPlatform(), gd::ExpressionValidator validator;
codeGenerator.GetProjectScopedContainers(),
rootType);
node->Visit(validator); node->Visit(validator);
if (!validator.GetFatalErrors().empty()) { if (!validator.GetErrors().empty()) {
std::cout << "Error: \"" << validator.GetFatalErrors()[0]->GetMessage() std::cout << "Error: \"" << validator.GetErrors()[0]->GetMessage()
<< "\" in: \"" << expression.GetPlainString() << "\" (" << "\" in: \"" << expression << "\" (" << type << ")"
<< rootType << ")" << std::endl; << std::endl;
return generator.GenerateDefaultValue(rootType); return generator.GenerateDefaultValue(type);
} }
node->Visit(generator); node->Visit(generator);
@@ -102,96 +97,27 @@ void ExpressionCodeGenerator::OnVisitTextNode(TextNode& node) {
void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) { void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
// This "translation" from the type to an enum could be avoided // This "translation" from the type to an enum could be avoided
// if all types were moved to an enum. // if all types were moved to an enum.
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(), EventsCodeGenerator::VariableScope scope =
codeGenerator.GetProjectScopedContainers(), node.type == "globalvar"
rootType, ? gd::EventsCodeGenerator::PROJECT_VARIABLE
node); : ((node.type == "scenevar")
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
if (gd::ParameterMetadata::IsExpression("variable", type)) { output += codeGenerator.GenerateGetVariable(
// The node is a variable inside an expression waiting for a *variable* to be returned, not its value. node.name, scope, context, node.objectName);
EventsCodeGenerator::VariableScope scope = if (node.child) node.child->Visit(*this);
type == "globalvar"
? gd::EventsCodeGenerator::PROJECT_VARIABLE
: ((type == "scenevar")
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
rootObjectName,
node);
output += codeGenerator.GenerateGetVariable(
node.name, scope, context, objectName);
if (node.child) node.child->Visit(*this);
} else {
// The node represents a variable or an object variable in an expression waiting for its *value* to be returned.
codeGenerator.GetProjectScopedContainers().MatchIdentifierWithName<void>(node.name, [&](){
// Generate the code to access the object variables.
// Defer generation of the access to the object and variable to the child,
// once we know the name of the variable.
objectNameToUseForVariableAccessor = node.name;
if (node.child) node.child->Visit(*this);
objectNameToUseForVariableAccessor = "";
output += codeGenerator.GenerateVariableValueAs(type);
}, [&]() {
if (!codeGenerator.HasProjectAndLayout()) {
gd::LogWarning("Tried to generate access to a variable without a project/scene - the code generator only works for global and scene variables for now.");
output += GenerateDefaultValue(type);
return;
}
// This could be adapted in the future if more scopes are supported.
EventsCodeGenerator::VariableScope scope = gd::EventsCodeGenerator::PROJECT_VARIABLE;
if (codeGenerator.GetProjectScopedContainers().GetVariablesContainersList().GetBottomMostVariablesContainer()->Has(node.name)) {
scope = gd::EventsCodeGenerator::LAYOUT_VARIABLE;
}
output += codeGenerator.GenerateGetVariable(node.name, scope, context, "");
if (node.child) node.child->Visit(*this);
output += codeGenerator.GenerateVariableValueAs(type);
}, [&]() {
// Properties are not supported.
output += GenerateDefaultValue(type);
}, [&]() {
// Parameters are not supported.
output += GenerateDefaultValue(type);
}, [&]() {
// The identifier does not represents a variable (or a child variable), or not at least an existing
// one, nor an object variable. It's invalid.
output += GenerateDefaultValue(type);
});
}
} }
void ExpressionCodeGenerator::OnVisitVariableAccessorNode( void ExpressionCodeGenerator::OnVisitVariableAccessorNode(
VariableAccessorNode& node) { VariableAccessorNode& node) {
if (!objectNameToUseForVariableAccessor.empty()) { output += codeGenerator.GenerateVariableAccessor(node.name);
// Use the name of the object passed by the parent, as we need both to access an object variable.
output += codeGenerator.GenerateGetVariable(node.name,
gd::EventsCodeGenerator::OBJECT_VARIABLE, context, objectNameToUseForVariableAccessor);
// We have accessed an object variable, from now we can continue accessing the child variables
// (including using the bracket notation).
objectNameToUseForVariableAccessor = "";
} else {
output += codeGenerator.GenerateVariableAccessor(node.name);
}
if (node.child) node.child->Visit(*this); if (node.child) node.child->Visit(*this);
} }
void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode( void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode& node) { VariableBracketAccessorNode& node) {
if (!objectNameToUseForVariableAccessor.empty()) { ExpressionCodeGenerator generator(codeGenerator, context);
// Bracket notation can't be used to directly access a variable of an object (`MyObject["MyVariable"]`).
// This would be rejected by the ExpressionValidator.
output += codeGenerator.GenerateBadVariable();
return;
}
ExpressionCodeGenerator generator("number|string", "", codeGenerator, context);
node.expression->Visit(generator); node.expression->Visit(generator);
output += output +=
codeGenerator.GenerateVariableBracketAccessor(generator.GetOutput()); codeGenerator.GenerateVariableBracketAccessor(generator.GetOutput());
@@ -199,108 +125,39 @@ void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
} }
void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) { void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(), if (gd::ParameterMetadata::IsObject(node.type)) {
codeGenerator.GetProjectScopedContainers(),
rootType,
node);
if (gd::ParameterMetadata::IsObject(type)) {
output += output +=
codeGenerator.GenerateObject(node.identifierName, type, context); codeGenerator.GenerateObject(node.identifierName, node.type, context);
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
EventsCodeGenerator::VariableScope scope =
type == "globalvar"
? gd::EventsCodeGenerator::PROJECT_VARIABLE
: ((type == "scenevar")
? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE);
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
rootObjectName,
node);
output += codeGenerator.GenerateGetVariable(
node.identifierName, scope, context, objectName);
if (!node.childIdentifierName.empty()) {
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
}
} else { } else {
const auto& variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList(); output += "/* Error during generation, unrecognized identifier type: " +
const auto& propertiesContainersList = codeGenerator.GetProjectScopedContainers().GetPropertiesContainersList(); codeGenerator.ConvertToString(node.type) + " with value " +
const auto& parametersVectorsList = codeGenerator.GetProjectScopedContainers().GetParametersVectorsList(); codeGenerator.ConvertToString(node.identifierName) + " */ " +
codeGenerator.ConvertToStringExplicit(node.identifierName);
// The node represents a variable, property, parameter or an object.
codeGenerator.GetProjectScopedContainers().MatchIdentifierWithName<void>(node.identifierName, [&]() {
// Generate the code to access the object variable.
output += codeGenerator.GenerateGetVariable(
node.childIdentifierName, gd::EventsCodeGenerator::OBJECT_VARIABLE, context, node.identifierName);
output += codeGenerator.GenerateVariableValueAs(type);
}, [&]() {
if (!codeGenerator.HasProjectAndLayout()) {
gd::LogWarning("Tried to generate access to a variable without a project/scene - the code generator only works for global and scene variables for now.");
output += GenerateDefaultValue(type);
return;
}
// This could be adapted in the future if more scopes are supported at runtime.
EventsCodeGenerator::VariableScope scope = gd::EventsCodeGenerator::PROJECT_VARIABLE;
if (variablesContainersList.GetBottomMostVariablesContainer()->Has(node.identifierName)) {
scope = gd::EventsCodeGenerator::LAYOUT_VARIABLE;
}
output += codeGenerator.GenerateGetVariable(node.identifierName, scope, context, "");
if (!node.childIdentifierName.empty()) {
output += codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
}
output += codeGenerator.GenerateVariableValueAs(type);
}, [&]() {
const auto& propertiesContainerAndProperty = propertiesContainersList.Get(node.identifierName);
output += codeGenerator.GeneratePropertyGetter(
propertiesContainerAndProperty.first, propertiesContainerAndProperty.second, type, context);
}, [&]() {
const auto& parameter = gd::ParameterMetadataTools::Get(parametersVectorsList, node.identifierName);
output += codeGenerator.GenerateParameterGetter(parameter, type, context);
}, [&]() {
// The identifier does not represents a variable (or a child variable), or not at least an existing
// one, nor an object variable. It's invalid.
output += GenerateDefaultValue(type);
});
} }
} }
void ExpressionCodeGenerator::OnVisitFunctionCallNode(FunctionCallNode& node) { void ExpressionCodeGenerator::OnVisitFunctionCallNode(FunctionCallNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(), if (gd::MetadataProvider::IsBadExpressionMetadata(node.expressionMetadata)) {
codeGenerator.GetProjectScopedContainers(),
rootType,
node);
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
node);
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
output += "/* Error during generation, function not found: " + output += "/* Error during generation, function not found: " +
codeGenerator.ConvertToString(node.functionName) + " */ " + codeGenerator.ConvertToString(node.functionName) + " */ " +
GenerateDefaultValue(type); GenerateDefaultValue(node.type);
return; return;
} }
if (!node.objectName.empty()) { if (!node.objectName.empty()) {
if (!node.behaviorName.empty()) { if (!node.behaviorName.empty()) {
output += GenerateBehaviorFunctionCode(type, output += GenerateBehaviorFunctionCode(node.type,
node.objectName, node.objectName,
node.behaviorName, node.behaviorName,
node.parameters, node.parameters,
metadata); node.expressionMetadata);
} else { } else {
output += GenerateObjectFunctionCode( output += GenerateObjectFunctionCode(
type, node.objectName, node.parameters, metadata); node.type, node.objectName, node.parameters, node.expressionMetadata);
} }
} else { } else {
output += output +=
GenerateFreeFunctionCode(node.parameters, metadata); GenerateFreeFunctionCode(node.parameters, node.expressionMetadata);
} }
} }
@@ -308,10 +165,10 @@ gd::String ExpressionCodeGenerator::GenerateFreeFunctionCode(
const std::vector<std::unique_ptr<ExpressionNode>>& parameters, const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) { const ExpressionMetadata& expressionMetadata) {
codeGenerator.AddIncludeFiles( codeGenerator.AddIncludeFiles(
expressionMetadata.GetIncludeFiles()); expressionMetadata.codeExtraInformation.GetIncludeFiles());
// Launch custom code generator if needed // Launch custom code generator if needed
if (expressionMetadata.HasCustomCodeGenerator()) { if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator( return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context); PrintParameters(parameters), codeGenerator, context);
} }
@@ -328,11 +185,16 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
const gd::String& objectName, const gd::String& objectName,
const std::vector<std::unique_ptr<ExpressionNode>>& parameters, const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) { const ExpressionMetadata& expressionMetadata) {
const gd::ObjectsContainer& globalObjectsAndGroups =
codeGenerator.GetGlobalObjectsAndGroups();
const gd::ObjectsContainer& objectsAndGroups =
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles( codeGenerator.AddIncludeFiles(
expressionMetadata.GetIncludeFiles()); expressionMetadata.codeExtraInformation.GetIncludeFiles());
// Launch custom code generator if needed // Launch custom code generator if needed
if (expressionMetadata.HasCustomCodeGenerator()) { if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator( return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context); PrintParameters(parameters), codeGenerator, context);
} }
@@ -348,22 +210,23 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
// Get object(s) concerned by function call // Get object(s) concerned by function call
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
codeGenerator.GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); codeGenerator.ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
context.ObjectsListNeeded(realObjects[i]); context.ObjectsListNeeded(realObjects[i]);
gd::String objectType = codeGenerator.GetObjectsContainersList().GetTypeOfObject(realObjects[i]); gd::String objectType = gd::GetTypeOfObject(
globalObjectsAndGroups, objectsAndGroups, realObjects[i]);
const ObjectMetadata& objInfo = MetadataProvider::GetObjectMetadata( const ObjectMetadata& objInfo = MetadataProvider::GetObjectMetadata(
codeGenerator.GetPlatform(), objectType); codeGenerator.GetPlatform(), objectType);
codeGenerator.AddIncludeFiles(objInfo.includeFiles); codeGenerator.AddIncludeFiles(objInfo.includeFiles);
functionOutput = codeGenerator.GenerateObjectFunctionCall( functionOutput = codeGenerator.GenerateObjectFunctionCall(
realObjects[i], realObjects[i],
objInfo, objInfo,
expressionMetadata.codeExtraInformation, expressionMetadata.codeExtraInformation,
parametersCode, parametersCode,
functionOutput, functionOutput,
context); context);
} }
return functionOutput; return functionOutput;
@@ -374,11 +237,16 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
const gd::String& behaviorName, const gd::String& behaviorName,
const std::vector<std::unique_ptr<ExpressionNode>>& parameters, const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) { const ExpressionMetadata& expressionMetadata) {
const gd::ObjectsContainer& globalObjectsAndGroups =
codeGenerator.GetGlobalObjectsAndGroups();
const gd::ObjectsContainer& objectsAndGroups =
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles( codeGenerator.AddIncludeFiles(
expressionMetadata.GetIncludeFiles()); expressionMetadata.codeExtraInformation.GetIncludeFiles());
// Launch custom code generator if needed // Launch custom code generator if needed
if (expressionMetadata.HasCustomCodeGenerator()) { if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator( return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context); PrintParameters(parameters), codeGenerator, context);
} }
@@ -392,11 +260,12 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
// Get object(s) concerned by function call // Get object(s) concerned by function call
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
codeGenerator.GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); codeGenerator.ExpandObjectsName(objectName, context);
gd::String functionOutput = GenerateDefaultValue(type); gd::String functionOutput = GenerateDefaultValue(type);
gd::String behaviorType = codeGenerator.GetObjectsContainersList().GetTypeOfBehavior(behaviorName); gd::String behaviorType = gd::GetTypeOfBehavior(
globalObjectsAndGroups, objectsAndGroups, behaviorName);
const BehaviorMetadata& autoInfo = MetadataProvider::GetBehaviorMetadata( const BehaviorMetadata& autoInfo = MetadataProvider::GetBehaviorMetadata(
codeGenerator.GetPlatform(), behaviorType); codeGenerator.GetPlatform(), behaviorType);
@@ -430,20 +299,18 @@ gd::String ExpressionCodeGenerator::GenerateParametersCodes(
auto& parameterMetadata = expressionMetadata.parameters[i]; auto& parameterMetadata = expressionMetadata.parameters[i];
if (!parameterMetadata.IsCodeOnly()) { if (!parameterMetadata.IsCodeOnly()) {
ExpressionCodeGenerator generator(codeGenerator, context);
if (nonCodeOnlyParameterIndex < parameters.size()) { if (nonCodeOnlyParameterIndex < parameters.size()) {
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
rootObjectName,
*parameters[nonCodeOnlyParameterIndex].get());
ExpressionCodeGenerator generator(parameterMetadata.GetType(), objectName, codeGenerator, context);
parameters[nonCodeOnlyParameterIndex]->Visit(generator); parameters[nonCodeOnlyParameterIndex]->Visit(generator);
parametersCode += generator.GetOutput(); parametersCode += generator.GetOutput();
} else if (parameterMetadata.IsOptional()) { } else if (parameterMetadata.IsOptional()) {
ExpressionCodeGenerator generator(parameterMetadata.GetType(), "", codeGenerator, context);
// Optional parameters default value were not parsed at the time of the // Optional parameters default value were not parsed at the time of the
// expression parsing. Parse them now. // expression parsing. Parse them now.
ExpressionParser2 parser; ExpressionParser2 parser(codeGenerator.GetPlatform(),
auto node = parser.ParseExpression(parameterMetadata.GetDefaultValue()); codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups());
auto node = parser.ParseExpression(parameterMetadata.GetType(),
parameterMetadata.GetDefaultValue());
node->Visit(generator); node->Visit(generator);
parametersCode += generator.GetOutput(); parametersCode += generator.GetOutput();
@@ -501,20 +368,12 @@ gd::String ExpressionCodeGenerator::GenerateDefaultValue(
} }
void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) { void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(), output += GenerateDefaultValue(node.type);
codeGenerator.GetProjectScopedContainers(),
rootType,
node);
output += GenerateDefaultValue(type);
} }
void ExpressionCodeGenerator::OnVisitObjectFunctionNameNode( void ExpressionCodeGenerator::OnVisitObjectFunctionNameNode(
ObjectFunctionNameNode& node) { ObjectFunctionNameNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(), output += GenerateDefaultValue(node.type);
codeGenerator.GetProjectScopedContainers(),
rootType,
node);
output += GenerateDefaultValue(type);
} }
} // namespace gd } // namespace gd

View File

@@ -9,6 +9,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/Events/Parsers/ExpressionParser2Node.h" #include "GDCore/Events/Parsers/ExpressionParser2Node.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h" #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
#include "GDCore/String.h" #include "GDCore/String.h"
@@ -34,11 +35,9 @@ namespace gd {
*/ */
class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker { class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
public: public:
ExpressionCodeGenerator(const gd::String &rootType_, ExpressionCodeGenerator(EventsCodeGenerator& codeGenerator_,
const gd::String &rootObjectName_,
EventsCodeGenerator& codeGenerator_,
EventsCodeGenerationContext& context_) EventsCodeGenerationContext& context_)
: rootType(rootType_), rootObjectName(rootObjectName_), codeGenerator(codeGenerator_), context(context_){}; : codeGenerator(codeGenerator_), context(context_){};
virtual ~ExpressionCodeGenerator(){}; virtual ~ExpressionCodeGenerator(){};
/** /**
@@ -58,7 +57,7 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
static gd::String GenerateExpressionCode(EventsCodeGenerator& codeGenerator, static gd::String GenerateExpressionCode(EventsCodeGenerator& codeGenerator,
EventsCodeGenerationContext& context, EventsCodeGenerationContext& context,
const gd::String& type, const gd::String& type,
const gd::Expression& expression, const gd::String& expression,
const gd::String& objectName = ""); const gd::String& objectName = "");
const gd::String& GetOutput() { return output; }; const gd::String& GetOutput() { return output; };
@@ -102,11 +101,8 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
const std::vector<std::unique_ptr<ExpressionNode>>& parameters); const std::vector<std::unique_ptr<ExpressionNode>>& parameters);
gd::String output; gd::String output;
gd::String objectNameToUseForVariableAccessor;
EventsCodeGenerator& codeGenerator; EventsCodeGenerator& codeGenerator;
EventsCodeGenerationContext& context; EventsCodeGenerationContext& context;
const gd::String rootType;
const gd::String rootObjectName;
}; };
} // namespace gd } // namespace gd

View File

@@ -5,12 +5,8 @@
*/ */
#include "GDCore/Events/Event.h" #include "GDCore/Events/Event.h"
#include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/EventsList.h" #include "GDCore/Events/EventsList.h"
#include "GDCore/Events/EventVisitor.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h" #include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h" #include "GDCore/Extensions/PlatformExtension.h"
@@ -69,41 +65,10 @@ gd::String BaseEvent::GenerateEventCode(
return ""; return "";
} }
void BaseEvent::PreprocessAsyncActions(const gd::Platform& platform) {
if (!CanHaveSubEvents()) return;
for (const auto& actionsList : GetAllActionsVectors())
for (std::size_t aId = 0; aId < actionsList->size(); ++aId) {
const auto& action = actionsList->at(aId);
const gd::InstructionMetadata& actionMetadata =
gd::MetadataProvider::GetActionMetadata(platform, action.GetType());
if (actionMetadata.IsAsync() &&
(!actionMetadata.IsOptionallyAsync() || action.IsAwaited())) {
gd::InstructionsList remainingActions;
remainingActions.InsertInstructions(
*actionsList, aId + 1, actionsList->size() - 1);
gd::AsyncEvent asyncEvent(action, remainingActions, GetSubEvents());
// Ensure that the local event no longer has any of the actions/subevent
// after the async function
actionsList->RemoveAfter(aId);
GetSubEvents().Clear();
GetSubEvents().InsertEvent(asyncEvent);
// We just moved all the rest, there's nothing left to do in this event.
return;
}
}
};
void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator, void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator,
gd::EventsList& eventList, gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList) { std::size_t indexOfTheEventInThisList) {
if (IsDisabled()) return; if (IsDisabled() || !MustBePreprocessed()) return;
PreprocessAsyncActions(codeGenerator.GetPlatform());
if (!MustBePreprocessed()) return;
try { try {
if (type.empty()) return; if (type.empty()) return;
@@ -141,14 +106,6 @@ void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator,
} }
} }
bool BaseEvent::AcceptVisitor(gd::EventVisitor& eventVisitor) {
return eventVisitor.VisitEvent(*this);
}
void BaseEvent::AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const {
eventVisitor.VisitEvent(*this);
}
BaseEventSPtr GD_CORE_API CloneRememberingOriginalEvent(BaseEventSPtr event) { BaseEventSPtr GD_CORE_API CloneRememberingOriginalEvent(BaseEventSPtr event) {
gd::BaseEventSPtr copy(event->Clone()); gd::BaseEventSPtr copy(event->Clone());
// Original event is either the original event of the copied event, or the // Original event is either the original event of the copied event, or the

View File

@@ -10,13 +10,13 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "GDCore/Events/Instruction.h" #include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h" #include "GDCore/Events/InstructionsList.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h" #include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h" #include "GDCore/String.h"
namespace gd { namespace gd {
class EventsList; class EventsList;
class MainFrameWrapper;
class Project; class Project;
class Layout; class Layout;
class EventsCodeGenerator; class EventsCodeGenerator;
@@ -24,9 +24,7 @@ class EventsCodeGenerationContext;
class Platform; class Platform;
class SerializerElement; class SerializerElement;
class Instruction; class Instruction;
class EventVisitor; }
class ReadOnlyEventVisitor;
} // namespace gd
namespace gd { namespace gd {
@@ -129,25 +127,18 @@ class GD_CORE_API BaseEvent {
return noSearchableStrings; return noSearchableStrings;
}; };
virtual bool ReplaceAllSearchableStrings(
std::vector<gd::String> newSearchableString) {
return false;
};
/** /**
* \brief Return a list of all expressions of the event, each with their associated metadata. * \brief Return a list of all expressions of the event, each with their associated metadata.
* \note Used to preprocess or search in the expressions of the event. * \note Used to preprocess or search in the expressions of the event.
*/ */
virtual std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> > virtual std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> >
GetAllExpressionsWithMetadata() { GetAllExpressionsWithMetadata() {
std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> > noExpr; std::vector<std::pair<gd::Expression*, gd::ParameterMetadata> > noExpr;
return noExpr; return noExpr;
}; };
virtual std::vector< virtual std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
std::pair<const gd::Expression*, const gd::ParameterMetadata> > GetAllExpressionsWithMetadata() const {
GetAllExpressionsWithMetadata() const { std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> > noExpr;
std::vector<std::pair<const gd::Expression*, const gd::ParameterMetadata> >
noExpr;
return noExpr; return noExpr;
}; };
@@ -211,11 +202,6 @@ class GD_CORE_API BaseEvent {
gd::EventsList& eventList, gd::EventsList& eventList,
std::size_t indexOfTheEventInThisList); std::size_t indexOfTheEventInThisList);
/**
* A function that turns all async member actions into an Async subevent for code generation.
*/
void PreprocessAsyncActions(const gd::Platform& platform);
/** /**
* \brief If MustBePreprocessed is redefined to return true, the * \brief If MustBePreprocessed is redefined to return true, the
* gd::EventMetadata::preprocessing associated to the event will be called to * gd::EventMetadata::preprocessing associated to the event will be called to
@@ -240,9 +226,6 @@ class GD_CORE_API BaseEvent {
*/ */
virtual void UnserializeFrom(gd::Project& project, virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element){}; const SerializerElement& element){};
virtual bool AcceptVisitor(gd::EventVisitor& eventVisitor);
virtual void AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const;
///@} ///@}
/** \name Common properties /** \name Common properties
@@ -281,6 +264,7 @@ class GD_CORE_API BaseEvent {
* \brief True if the event should be folded in the events editor. * \brief True if the event should be folded in the events editor.
*/ */
bool IsFolded() const { return folded; } bool IsFolded() const { return folded; }
///@} ///@}
std::weak_ptr<gd::BaseEvent> std::weak_ptr<gd::BaseEvent>

View File

@@ -1,76 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <iostream>
#include <memory>
#include <vector>
#include "GDCore/String.h"
namespace gd {
class BaseEvent;
class LinkEvent;
} // namespace gd
namespace gd {
/**
* \brief Visitor of any kind of event.
*
* \ingroup Events
*/
class GD_CORE_API EventVisitor {
public:
virtual ~EventVisitor(){};
/**
* Called to do some work on an event.
*
* \return true if the event must be deleted from the events list, false
* otherwise.
*/
virtual bool VisitEvent(gd::BaseEvent& linkEvent) = 0;
/**
* Called to do some work on a link event.
*
* Note that VisitEvent is also called with this event.
*
* \return true if the event must be deleted from the events list, false
* otherwise.
*/
virtual bool VisitLinkEvent(gd::LinkEvent& linkEvent) = 0;
};
/**
* \brief Visitor of any kind of event.
*
* \ingroup Events
*/
class GD_CORE_API ReadOnlyEventVisitor {
public:
virtual ~ReadOnlyEventVisitor(){};
/**
* Called to do some work on an event.
*/
virtual void VisitEvent(const gd::BaseEvent& linkEvent) = 0;
/**
* Called to do some work on a link event.
*
* Note that VisitEvent is also called with this event.
*/
virtual void VisitLinkEvent(const gd::LinkEvent& linkEvent) = 0;
/**
* @brief Abort the iteration on the events.
*/
virtual void StopAnyEventIteration() = 0;
};
}

View File

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

View File

@@ -1,41 +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/Events/Expression.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
#include "GDCore/String.h"
namespace gd {
Expression::Expression() : node(nullptr) {};
Expression::Expression(gd::String plainString_)
: node(nullptr), plainString(plainString_) {};
Expression::Expression(const char* plainString_)
: node(nullptr), plainString(plainString_) {};
Expression::Expression(const Expression& copy)
: node(nullptr), plainString{copy.plainString} {};
Expression& Expression::operator=(const Expression& expression) {
plainString = expression.plainString;
node = nullptr;
return *this;
};
Expression::~Expression(){};
ExpressionNode* Expression::GetRootNode() const {
if (!node) {
gd::ExpressionParser2 parser = ExpressionParser2();
node = std::move(parser.ParseExpression(plainString));
}
return node.get();
}
} // namespace gd

View File

@@ -6,15 +6,7 @@
#ifndef GDCORE_EXPRESSION_H #ifndef GDCORE_EXPRESSION_H
#define GDCORE_EXPRESSION_H #define GDCORE_EXPRESSION_H
#include "GDCore/String.h" #include "GDCore/String.h"
#include <memory>
namespace gd {
class ExpressionParser2;
class ObjectsContainer;
struct ExpressionNode;
} // namespace gd
namespace gd { namespace gd {
@@ -32,49 +24,32 @@ class GD_CORE_API Expression {
/** /**
* \brief Construct an empty expression * \brief Construct an empty expression
*/ */
Expression(); Expression(){};
/** /**
* \brief Construct an expression from a string * \brief Construct an expression from a string
*/ */
Expression(gd::String plainString_); Expression(gd::String plainString_) : plainString(plainString_){};
/** /**
* \brief Construct an expression from a const char * * \brief Construct an expression from a const char *
*/ */
Expression(const char* plainString_); Expression(const char* plainString_) : plainString(plainString_){};
/**
* \brief Copy construct an expression.
*/
Expression(const Expression& copy);
/**
* \brief Expression affectation overriding.
*/
Expression& operator=(const Expression& expression);
/** /**
* \brief Get the plain string representing the expression * \brief Get the plain string representing the expression
*/ */
inline const gd::String& GetPlainString() const { return plainString; }; inline const gd::String& GetPlainString() const { return plainString; };
/**
* @brief Get the expression node.
* @return std::unique_ptr<gd::ExpressionNode>
*/
gd::ExpressionNode* GetRootNode() const;
/** /**
* \brief Mimics std::string::c_str * \brief Mimics std::string::c_str
*/ */
inline const char* c_str() const { return plainString.c_str(); }; inline const char* c_str() const { return plainString.c_str(); };
virtual ~Expression(); virtual ~Expression(){};
private: private:
gd::String plainString; ///< The expression string gd::String plainString; ///< The expression string
mutable std::unique_ptr<gd::ExpressionNode> node;
}; };
} // namespace gd } // namespace gd

View File

@@ -55,10 +55,6 @@ void Instruction::SetParameter(std::size_t nb, const gd::Expression& val) {
parameters[nb] = val; parameters[nb] = val;
} }
void Instruction::AddParameter(const gd::Expression& val) {
parameters.push_back(val);
}
std::shared_ptr<Instruction> GD_CORE_API std::shared_ptr<Instruction> GD_CORE_API
CloneRememberingOriginalElement(std::shared_ptr<Instruction> instruction) { CloneRememberingOriginalElement(std::shared_ptr<Instruction> instruction) {
std::shared_ptr<Instruction> copy = std::shared_ptr<Instruction> copy =

View File

@@ -72,22 +72,6 @@ class GD_CORE_API Instruction {
*/ */
void SetInverted(bool inverted_) { inverted = inverted_; } void SetInverted(bool inverted_) { inverted = inverted_; }
/**
* \brief Return true if the async instruction should be awaited.
* This is not relevant if the instruction is not optionally asynchronous.
*
* \return true if the instruction is to be awaited
*/
bool IsAwaited() const { return awaitAsync; }
/**
* \brief Set if the async instruction is to be awaited or not.
* This is not relevant if the instruction is not optionally asynchronous.
*
* \param inverted true if the instruction must be awaited
*/
void SetAwaited(bool awaited) { awaitAsync = awaited; }
/** /**
* \brief Return the number of parameters of the instruction. * \brief Return the number of parameters of the instruction.
*/ */
@@ -123,11 +107,6 @@ class GD_CORE_API Instruction {
*/ */
void SetParameter(std::size_t nb, const gd::Expression& val); void SetParameter(std::size_t nb, const gd::Expression& val);
/** Add a parameter at the end
* \param val The new value of the parameter
*/
void AddParameter(const gd::Expression& val);
/** \brief Get a reference to the std::vector containing the parameters. /** \brief Get a reference to the std::vector containing the parameters.
* \return A std::vector containing the parameters * \return A std::vector containing the parameters
*/ */
@@ -160,9 +139,7 @@ class GD_CORE_API Instruction {
* Useful to get reference to the original instruction in memory during code * Useful to get reference to the original instruction in memory during code
* generation, to ensure stable unique identifiers. * generation, to ensure stable unique identifiers.
*/ */
std::weak_ptr<Instruction> GetOriginalInstruction() { std::weak_ptr<Instruction> GetOriginalInstruction() { return originalInstruction; };
return originalInstruction;
};
friend std::shared_ptr<Instruction> CloneRememberingOriginalElement( friend std::shared_ptr<Instruction> CloneRememberingOriginalElement(
std::shared_ptr<Instruction> instruction); std::shared_ptr<Instruction> instruction);
@@ -171,9 +148,6 @@ class GD_CORE_API Instruction {
gd::String type; ///< Instruction type gd::String type; ///< Instruction type
bool inverted; ///< True if the instruction if inverted. Only applicable for bool inverted; ///< True if the instruction if inverted. Only applicable for
///< instruction used as conditions by events ///< instruction used as conditions by events
bool awaitAsync =
false; ///< Tells the code generator whether the optionally asynchronous
///< instruction should be generated as asynchronous (awaited) or not.
mutable std::vector<gd::Expression> mutable std::vector<gd::Expression>
parameters; ///< Vector containing the parameters parameters; ///< Vector containing the parameters
gd::InstructionsList subInstructions; ///< Sub instructions, if applicable. gd::InstructionsList subInstructions; ///< Sub instructions, if applicable.

View File

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

View File

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

View File

@@ -19,25 +19,139 @@
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
#include "GDCore/Tools/Localization.h" #include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/MakeUnique.h" #include "GDCore/Tools/MakeUnique.h"
#include "GrammarTerminals.h"
using namespace std; using namespace std;
using namespace gd::GrammarTerminals;
namespace gd { namespace gd {
gd::String ExpressionParser2::NAMESPACE_SEPARATOR = "::"; gd::String ExpressionParser2::NAMESPACE_SEPARATOR = "::";
ExpressionParser2::ExpressionParser2() ExpressionParser2::ExpressionParser2(
const gd::Platform& platform_,
const gd::ObjectsContainer& globalObjectsContainer_,
const gd::ObjectsContainer& objectsContainer_)
: expression(""), : expression(""),
currentPosition(0) {} currentPosition(0),
platform(platform_),
globalObjectsContainer(globalObjectsContainer_),
objectsContainer(objectsContainer_) {}
namespace {
/**
* Return the minimum number of parameters, starting from a given parameter
* (by convention, 1 for object functions and 2 for behavior functions).
*/
size_t GetMinimumParametersNumber(
const std::vector<gd::ParameterMetadata>& parameters,
size_t initialParameterIndex) {
size_t nb = 0;
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
if (!parameters[i].optional && !parameters[i].codeOnly) nb++;
}
return nb;
}
/**
* Return the maximum number of parameters, starting from a given parameter
* (by convention, 1 for object functions and 2 for behavior functions).
*/
size_t GetMaximumParametersNumber(
const std::vector<gd::ParameterMetadata>& parameters,
size_t initialParameterIndex) {
size_t nb = 0;
for (std::size_t i = initialParameterIndex; i < parameters.size(); ++i) {
if (!parameters[i].codeOnly) nb++;
}
return nb;
}
} // namespace
std::unique_ptr<ExpressionParserDiagnostic> ExpressionParser2::ValidateFunction(
const gd::String& type,
const gd::FunctionCallNode& function,
size_t functionStartPosition) {
if (gd::MetadataProvider::IsBadExpressionMetadata(
function.expressionMetadata)) {
return gd::make_unique<ExpressionParserError>(
"invalid_function_name",
_("Cannot find an expression with this name: ") +
function.functionName + "\n" +
_("Double check that you've not made any typo in the name."),
functionStartPosition,
GetCurrentPosition());
}
// Validate the type of the function
const gd::String& returnType = function.expressionMetadata.GetReturnType();
if (returnType == "number") {
if (type == "string")
return RaiseTypeError(
_("You tried to use an expression that returns a number, but a "
"string is expected. Use `ToString` if you need to convert a "
"number to a string."),
functionStartPosition);
else if (type != "number" && type != "number|string")
return RaiseTypeError(_("You tried to use an expression that returns a "
"number, but another type is expected:") +
" " + type,
functionStartPosition);
} else if (returnType == "string") {
if (type == "number")
return RaiseTypeError(
_("You tried to use an expression that returns a string, but a "
"number is expected. Use `ToNumber` if you need to convert a "
"string to a number."),
functionStartPosition);
else if (type != "string" && type != "number|string")
return RaiseTypeError(_("You tried to use an expression that returns a "
"string, but another type is expected:") +
" " + type,
functionStartPosition);
} else {
if (type != returnType)
return RaiseTypeError(
_("You tried to use an expression with the wrong return type:") + " " +
returnType,
functionStartPosition);
}
// Validate parameters count
size_t minParametersCount = GetMinimumParametersNumber(
function.expressionMetadata.parameters,
WrittenParametersFirstIndex(function.objectName, function.behaviorName));
size_t maxParametersCount = GetMaximumParametersNumber(
function.expressionMetadata.parameters,
WrittenParametersFirstIndex(function.objectName, function.behaviorName));
if (function.parameters.size() < minParametersCount ||
function.parameters.size() > maxParametersCount) {
gd::String expectedCountMessage =
minParametersCount == maxParametersCount
? _("The number of parameters must be exactly ") +
gd::String::From(minParametersCount)
: _("The number of parameters must be: ") +
gd::String::From(minParametersCount) + "-" +
gd::String::From(maxParametersCount);
if (function.parameters.size() < minParametersCount) {
return gd::make_unique<ExpressionParserError>(
"too_few_parameters",
"You have not entered enough parameters for the expression. " +
expectedCountMessage,
functionStartPosition,
GetCurrentPosition());
}
}
return gd::make_unique<ExpressionParserDiagnostic>();
}
std::unique_ptr<TextNode> ExpressionParser2::ReadText() { std::unique_ptr<TextNode> ExpressionParser2::ReadText() {
size_t textStartPosition = GetCurrentPosition(); size_t textStartPosition = GetCurrentPosition();
SkipAllWhitespaces(); SkipAllWhitespaces();
if (!CheckIfChar(IsQuote)) { if (!CheckIfChar(IsQuote)) {
auto text = gd::make_unique<TextNode>(""); auto text = gd::make_unique<TextNode>("");
// It can't happen.
text->diagnostic = text->diagnostic =
RaiseSyntaxError(_("A text must start with a double quote (\").")); RaiseSyntaxError(_("A text must start with a double quote (\")."));
text->location = text->location =

View File

@@ -13,12 +13,10 @@
#include "ExpressionParser2Node.h" #include "ExpressionParser2Node.h"
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h" #include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Metadata/ObjectMetadata.h"
#include "GDCore/Project/Layout.h" // For GetTypeOfObject and GetTypeOfBehavior #include "GDCore/Project/Layout.h" // For GetTypeOfObject and GetTypeOfBehavior
#include "GDCore/String.h" #include "GDCore/String.h"
#include "GDCore/Tools/Localization.h" #include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/MakeUnique.h" #include "GDCore/Tools/MakeUnique.h"
#include "GrammarTerminals.h"
namespace gd { namespace gd {
class Expression; class Expression;
class ObjectsContainer; class ObjectsContainer;
@@ -29,8 +27,6 @@ class ExpressionMetadata;
namespace gd { namespace gd {
using namespace gd::GrammarTerminals;
/** \brief Parse an expression, returning a tree of node corresponding /** \brief Parse an expression, returning a tree of node corresponding
* to the parsed expression. * to the parsed expression.
* *
@@ -43,32 +39,41 @@ using namespace gd::GrammarTerminals;
*/ */
class GD_CORE_API ExpressionParser2 { class GD_CORE_API ExpressionParser2 {
public: public:
ExpressionParser2(); ExpressionParser2(const gd::Platform &platform_,
const gd::ObjectsContainer &globalObjectsContainer_,
const gd::ObjectsContainer &objectsContainer_);
virtual ~ExpressionParser2(){}; virtual ~ExpressionParser2(){};
/** /**
* Parse the given expression into a tree of nodes. * Parse the given expression with the specified type.
* *
* \param expression The expression to parse. * \param type Type of the expression: "string", "number",
* type supported by gd::ParameterMetadata::IsObject, types supported by
* gd::ParameterMetadata::IsExpression or "unknown".
* \param expression The expression to parse
* \param objectName Specify the object name, only for the
* case of "objectvar" type.
* *
* \return The node representing the expression as a parsed tree. * \return The node representing the expression as a parsed tree.
*/ */
std::unique_ptr<ExpressionNode> ParseExpression( std::unique_ptr<ExpressionNode> ParseExpression(
const gd::String &expression_) { const gd::String &type,
const gd::String &expression_,
const gd::String &objectName = "") {
expression = expression_; expression = expression_;
currentPosition = 0; currentPosition = 0;
return Start(); return Start(type, objectName);
} }
/** /**
* Given an object name (or empty if none) and a behavior name (or empty if * Given an object name (or empty if none) and a behavior name (or empty if none),
* none), return the index of the first parameter that is inside the * return the index of the first parameter that is inside the parenthesis:
* parenthesis: 0, 1 or 2. * 0, 1 or 2.
* *
* For example, in an expression like `Object.MyBehavior::Method("hello")`, * For example, in an expression like `Object.MyBehavior::Method("hello")`, the
* the parameter "hello" is the second parameter (the first being by * parameter "hello" is the second parameter (the first being by convention Object,
* convention Object, and the second MyBehavior, also by convention). * and the second MyBehavior, also by convention).
*/ */
static size_t WrittenParametersFirstIndex(const gd::String &objectName, static size_t WrittenParametersFirstIndex(const gd::String &objectName,
const gd::String &behaviorName) { const gd::String &behaviorName) {
@@ -82,16 +87,18 @@ class GD_CORE_API ExpressionParser2 {
* Each method is a part of the grammar. * Each method is a part of the grammar.
*/ */
///@{ ///@{
std::unique_ptr<ExpressionNode> Start() { std::unique_ptr<ExpressionNode> Start(const gd::String &type,
const gd::String &objectName = "") {
size_t expressionStartPosition = GetCurrentPosition(); size_t expressionStartPosition = GetCurrentPosition();
auto expression = Expression(); auto expression = Expression(type, objectName);
const gd::String &inferredType = expression->type;
// Check for extra characters at the end of the expression // Check for extra characters at the end of the expression
if (!IsEndReached()) { if (!IsEndReached()) {
auto op = gd::make_unique<OperatorNode>(' '); auto op = gd::make_unique<OperatorNode>(inferredType, ' ');
op->leftHandSide = std::move(expression); op->leftHandSide = std::move(expression);
op->rightHandSide = ReadUntilEnd(); op->rightHandSide = ReadUntilEnd("unknown");
op->rightHandSide->parent = op.get();
op->rightHandSide->diagnostic = RaiseSyntaxError( op->rightHandSide->diagnostic = RaiseSyntaxError(
_("The expression has extra character at the end that should be " _("The expression has extra character at the end that should be "
@@ -105,49 +112,61 @@ class GD_CORE_API ExpressionParser2 {
return expression; return expression;
} }
std::unique_ptr<ExpressionNode> Expression() { std::unique_ptr<ExpressionNode> Expression(
const gd::String &type, const gd::String &objectName = "") {
SkipAllWhitespaces(); SkipAllWhitespaces();
size_t expressionStartPosition = GetCurrentPosition(); size_t expressionStartPosition = GetCurrentPosition();
std::unique_ptr<ExpressionNode> leftHandSide = Term(); std::unique_ptr<ExpressionNode> leftHandSide = Term(type, objectName);
const gd::String &inferredType = leftHandSide->type;
SkipAllWhitespaces(); SkipAllWhitespaces();
if (IsEndReached()) return leftHandSide; if (IsEndReached()) return leftHandSide;
if (CheckIfChar(IsExpressionEndingChar)) return leftHandSide; if (CheckIfChar(IsExpressionEndingChar)) return leftHandSide;
if (CheckIfChar(IsExpressionOperator)) { if (CheckIfChar(IsExpressionOperator)) {
auto op = gd::make_unique<OperatorNode>(GetCurrentChar()); auto op = gd::make_unique<OperatorNode>(inferredType, GetCurrentChar());
op->leftHandSide = std::move(leftHandSide); op->leftHandSide = std::move(leftHandSide);
op->leftHandSide->parent = op.get(); op->diagnostic = ValidateOperator(inferredType, GetCurrentChar());
op->diagnostic = ValidateOperator(GetCurrentChar());
SkipChar(); SkipChar();
op->rightHandSide = Expression(); op->rightHandSide = Expression(inferredType, objectName);
op->rightHandSide->parent = op.get();
op->location = ExpressionParserLocation(expressionStartPosition, op->location = ExpressionParserLocation(expressionStartPosition,
GetCurrentPosition()); GetCurrentPosition());
return std::move(op); return std::move(op);
} }
leftHandSide->diagnostic = RaiseSyntaxError( if (inferredType == "string") {
"More than one term was found. Verify that your expression is " leftHandSide->diagnostic = RaiseSyntaxError(
"properly written."); "You must add the operator + between texts or expressions. For "
"example: \"Your name: \" + VariableString(PlayerName).");
} else if (inferredType == "number") {
leftHandSide->diagnostic = RaiseSyntaxError(
"No operator found. Did you forget to enter an operator (like +, -, "
"* or /) between numbers or expressions?");
} else {
leftHandSide->diagnostic = RaiseSyntaxError(
"More than one term was found. Verify that your expression is "
"properly written.");
}
auto op = gd::make_unique<OperatorNode>(' '); auto op = gd::make_unique<OperatorNode>(inferredType, ' ');
op->leftHandSide = std::move(leftHandSide); op->leftHandSide = std::move(leftHandSide);
op->leftHandSide->parent = op.get(); op->rightHandSide = Expression(inferredType, objectName);
op->rightHandSide = Expression();
op->rightHandSide->parent = op.get();
op->location = op->location =
ExpressionParserLocation(expressionStartPosition, GetCurrentPosition()); ExpressionParserLocation(expressionStartPosition, GetCurrentPosition());
return std::move(op); return std::move(op);
} }
std::unique_ptr<ExpressionNode> Term() { std::unique_ptr<ExpressionNode> Term(const gd::String &type,
const gd::String &objectName) {
SkipAllWhitespaces(); SkipAllWhitespaces();
size_t expressionStartPosition = GetCurrentPosition(); size_t expressionStartPosition = GetCurrentPosition();
std::unique_ptr<ExpressionNode> factor = Factor(); std::unique_ptr<ExpressionNode> factor = Factor(type, objectName);
const gd::String &inferredType = factor->type;
SkipAllWhitespaces(); SkipAllWhitespaces();
@@ -155,13 +174,11 @@ class GD_CORE_API ExpressionParser2 {
// to guarantee the proper operator precedence. (Expression could also // to guarantee the proper operator precedence. (Expression could also
// be reworked to use a while loop). // be reworked to use a while loop).
while (CheckIfChar(IsTermOperator)) { while (CheckIfChar(IsTermOperator)) {
auto op = gd::make_unique<OperatorNode>(GetCurrentChar()); auto op = gd::make_unique<OperatorNode>(inferredType, GetCurrentChar());
op->leftHandSide = std::move(factor); op->leftHandSide = std::move(factor);
op->leftHandSide->parent = op.get(); op->diagnostic = ValidateOperator(inferredType, GetCurrentChar());
op->diagnostic = ValidateOperator(GetCurrentChar());
SkipChar(); SkipChar();
op->rightHandSide = Factor(); op->rightHandSide = Factor(inferredType, objectName);
op->rightHandSide->parent = op.get();
op->location = ExpressionParserLocation(expressionStartPosition, op->location = ExpressionParserLocation(expressionStartPosition,
GetCurrentPosition()); GetCurrentPosition());
SkipAllWhitespaces(); SkipAllWhitespaces();
@@ -172,35 +189,54 @@ class GD_CORE_API ExpressionParser2 {
return factor; return factor;
}; };
std::unique_ptr<ExpressionNode> Factor() { std::unique_ptr<ExpressionNode> Factor(const gd::String &type,
const gd::String &objectName) {
SkipAllWhitespaces(); SkipAllWhitespaces();
size_t expressionStartPosition = GetCurrentPosition(); size_t expressionStartPosition = GetCurrentPosition();
if (CheckIfChar(IsQuote)) { if (CheckIfChar(IsQuote)) {
std::unique_ptr<ExpressionNode> factor = ReadText(); std::unique_ptr<ExpressionNode> factor = ReadText();
if (type == "number")
factor->diagnostic =
RaiseTypeError(_("You entered a text, but a number was expected."),
expressionStartPosition);
else if (type != "string" && type != "number|string")
factor->diagnostic = RaiseTypeError(
_("You entered a text, but this type was expected:") + type,
expressionStartPosition);
return factor; return factor;
} else if (CheckIfChar(IsUnaryOperator)) { } else if (CheckIfChar(IsUnaryOperator)) {
auto unaryOperatorCharacter = GetCurrentChar(); auto unaryOperatorCharacter = GetCurrentChar();
SkipChar(); SkipChar();
auto operatorOperand = Factor(); auto operatorOperand = Factor(type, objectName);
const gd::String &inferredType = operatorOperand->type;
auto unaryOperator = gd::make_unique<UnaryOperatorNode>( auto unaryOperator = gd::make_unique<UnaryOperatorNode>(
unaryOperatorCharacter); inferredType, unaryOperatorCharacter);
unaryOperator->diagnostic = ValidateUnaryOperator( unaryOperator->diagnostic = ValidateUnaryOperator(
unaryOperatorCharacter, expressionStartPosition); inferredType, unaryOperatorCharacter, expressionStartPosition);
unaryOperator->factor = std::move(operatorOperand); unaryOperator->factor = std::move(operatorOperand);
unaryOperator->factor->parent = unaryOperator.get();
unaryOperator->location = ExpressionParserLocation( unaryOperator->location = ExpressionParserLocation(
expressionStartPosition, GetCurrentPosition()); expressionStartPosition, GetCurrentPosition());
return std::move(unaryOperator); return std::move(unaryOperator);
} else if (CheckIfChar(IsNumberFirstChar)) { } else if (CheckIfChar(IsNumberFirstChar)) {
std::unique_ptr<ExpressionNode> factor = ReadNumber(); std::unique_ptr<ExpressionNode> factor = ReadNumber();
if (type == "string")
factor->diagnostic = RaiseTypeError(
_("You entered a number, but a text was expected (in quotes)."),
expressionStartPosition);
else if (type != "number" && type != "number|string")
factor->diagnostic = RaiseTypeError(
_("You entered a number, but this type was expected:") + type,
expressionStartPosition);
return factor; return factor;
} else if (CheckIfChar(IsOpeningParenthesis)) { } else if (CheckIfChar(IsOpeningParenthesis)) {
SkipChar(); SkipChar();
std::unique_ptr<ExpressionNode> factor = SubExpression(); std::unique_ptr<ExpressionNode> factor = SubExpression(type, objectName);
if (!CheckIfChar(IsClosingParenthesis)) { if (!CheckIfChar(IsClosingParenthesis)) {
factor->diagnostic = factor->diagnostic =
@@ -209,21 +245,30 @@ class GD_CORE_API ExpressionParser2 {
} }
SkipIfChar(IsClosingParenthesis); SkipIfChar(IsClosingParenthesis);
return factor; return factor;
} else if (CheckIfChar(IsAllowedInIdentifier)) { } else if (IsIdentifierAllowedChar()) {
return Identifier(); // This is a place where the grammar differs according to the
// type being expected.
if (gd::ParameterMetadata::IsExpression("variable", type)) {
return Variable(type, objectName);
} else {
return Identifier(type);
}
} }
std::unique_ptr<ExpressionNode> factor = ReadUntilWhitespace(); std::unique_ptr<ExpressionNode> factor = ReadUntilWhitespace(type);
factor->diagnostic = RaiseEmptyError(type, expressionStartPosition);
return factor; return factor;
} }
std::unique_ptr<SubExpressionNode> SubExpression() { std::unique_ptr<SubExpressionNode> SubExpression(
const gd::String &type, const gd::String &objectName) {
size_t expressionStartPosition = GetCurrentPosition(); size_t expressionStartPosition = GetCurrentPosition();
auto expression = Expression(); auto expression = Expression(type, objectName);
const gd::String &inferredType = expression->type;
auto subExpression = auto subExpression =
gd::make_unique<SubExpressionNode>(std::move(expression)); gd::make_unique<SubExpressionNode>(inferredType, std::move(expression));
subExpression->location = subExpression->location =
ExpressionParserLocation(expressionStartPosition, GetCurrentPosition()); ExpressionParserLocation(expressionStartPosition, GetCurrentPosition());
@@ -231,7 +276,7 @@ class GD_CORE_API ExpressionParser2 {
}; };
std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode> std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
Identifier() { Identifier(const gd::String &type) {
auto identifierAndLocation = ReadIdentifierName(); auto identifierAndLocation = ReadIdentifierName();
gd::String name = identifierAndLocation.name; gd::String name = identifierAndLocation.name;
auto nameLocation = identifierAndLocation.location; auto nameLocation = identifierAndLocation.location;
@@ -258,27 +303,47 @@ class GD_CORE_API ExpressionParser2 {
if (CheckIfChar(IsOpeningParenthesis)) { if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar(); ExpressionParserLocation openingParenthesisLocation = SkipChar();
return FreeFunction(name, nameLocation, openingParenthesisLocation); return FreeFunction(type, name, nameLocation, openingParenthesisLocation);
} else if (CheckIfChar(IsDot)) { } else if (CheckIfChar(IsDot)) {
ExpressionParserLocation dotLocation = SkipChar(); ExpressionParserLocation dotLocation = SkipChar();
SkipAllWhitespaces(); SkipAllWhitespaces();
return ObjectFunctionOrBehaviorFunctionOrVariable( return ObjectFunctionOrBehaviorFunction(
name, nameLocation, dotLocation); type, name, nameLocation, dotLocation);
} else if (CheckIfChar(IsOpeningSquareBracket)) {
return Variable(name, nameLocation);
} else { } else {
auto identifier = gd::make_unique<IdentifierNode>(name); auto identifier = gd::make_unique<IdentifierNode>(name, type);
if (type == "string") {
identifier->diagnostic =
RaiseTypeError(_("You must wrap your text inside double quotes "
"(example: \"Hello world\")."),
nameLocation.GetStartPosition());
} else if (type == "number") {
identifier->diagnostic = RaiseTypeError(
_("You must enter a number."), nameLocation.GetStartPosition());
} else if (type == "number|string") {
identifier->diagnostic = RaiseTypeError(
_("You must enter a number or a text, wrapped inside double quotes "
"(example: \"Hello world\")."),
nameLocation.GetStartPosition());
} else if (!gd::ParameterMetadata::IsObject(type)) {
identifier->diagnostic = RaiseTypeError(
_("You've entered a name, but this type was expected:") + type,
nameLocation.GetStartPosition());
}
identifier->location = ExpressionParserLocation( identifier->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition()); nameLocation.GetStartPosition(), GetCurrentPosition());
identifier->identifierNameLocation = identifier->location;
return std::move(identifier); return std::move(identifier);
} }
} }
std::unique_ptr<VariableNode> Variable(const gd::String &name, gd::ExpressionParserLocation nameLocation) { std::unique_ptr<VariableNode> Variable(const gd::String &type,
auto variable = gd::make_unique<VariableNode>(name); const gd::String &objectName) {
auto identifierAndLocation = ReadIdentifierName();
const gd::String &name = identifierAndLocation.name;
const auto &nameLocation = identifierAndLocation.location;
auto variable = gd::make_unique<VariableNode>(type, name, objectName);
variable->child = VariableAccessorOrVariableBracketAccessor(); variable->child = VariableAccessorOrVariableBracketAccessor();
variable->child->parent = variable.get();
variable->location = ExpressionParserLocation( variable->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition()); nameLocation.GetStartPosition(), GetCurrentPosition());
@@ -293,8 +358,8 @@ class GD_CORE_API ExpressionParser2 {
SkipAllWhitespaces(); SkipAllWhitespaces();
if (CheckIfChar(IsOpeningSquareBracket)) { if (CheckIfChar(IsOpeningSquareBracket)) {
SkipChar(); SkipChar();
auto child = gd::make_unique<VariableBracketAccessorNode>(Expression()); auto child = gd::make_unique<VariableBracketAccessorNode>(
child->expression->parent = child.get(); Expression("number|string"));
if (!CheckIfChar(IsClosingSquareBracket)) { if (!CheckIfChar(IsClosingSquareBracket)) {
child->diagnostic = child->diagnostic =
@@ -303,7 +368,6 @@ class GD_CORE_API ExpressionParser2 {
} }
SkipIfChar(IsClosingSquareBracket); SkipIfChar(IsClosingSquareBracket);
child->child = VariableAccessorOrVariableBracketAccessor(); child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->location = child->location =
ExpressionParserLocation(childStartPosition, GetCurrentPosition()); ExpressionParserLocation(childStartPosition, GetCurrentPosition());
@@ -312,11 +376,10 @@ class GD_CORE_API ExpressionParser2 {
auto dotLocation = SkipChar(); auto dotLocation = SkipChar();
SkipAllWhitespaces(); SkipAllWhitespaces();
auto identifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false); auto identifierAndLocation = ReadIdentifierName();
auto child = auto child =
gd::make_unique<VariableAccessorNode>(identifierAndLocation.name); gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
child->child = VariableAccessorOrVariableBracketAccessor(); child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->nameLocation = identifierAndLocation.location; child->nameLocation = identifierAndLocation.location;
child->dotLocation = dotLocation; child->dotLocation = dotLocation;
child->location = child->location =
@@ -325,21 +388,31 @@ class GD_CORE_API ExpressionParser2 {
return std::move(child); return std::move(child);
} }
return std::move(gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>()); return std::move(
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>());
} }
std::unique_ptr<FunctionCallNode> FreeFunction( std::unique_ptr<FunctionCallNode> FreeFunction(
const gd::String &type,
const gd::String &functionFullName, const gd::String &functionFullName,
const ExpressionParserLocation &identifierLocation, const ExpressionParserLocation &identifierLocation,
const ExpressionParserLocation &openingParenthesisLocation) { const ExpressionParserLocation &openingParenthesisLocation) {
// TODO: error if trying to use function for type != "number" && != "string" // TODO: error if trying to use function for type != "number" && != "string"
// + Test for it // + Test for it
const gd::ExpressionMetadata &metadata =
MetadataProvider::GetAnyExpressionMetadata(platform, functionFullName);
auto parametersNode = Parameters(metadata.parameters);
auto function = auto function =
gd::make_unique<FunctionCallNode>(functionFullName); gd::make_unique<FunctionCallNode>(metadata.GetReturnType(),
auto parametersNode = Parameters(function.get()); std::move(parametersNode.parameters),
function->parameters = std::move(parametersNode.parameters); metadata,
functionFullName);
function->diagnostic = std::move(parametersNode.diagnostic); function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic) // TODO: reverse the order of diagnostic?
function->diagnostic = ValidateFunction(
type, *function, identifierLocation.GetStartPosition());
function->location = ExpressionParserLocation( function->location = ExpressionParserLocation(
identifierLocation.GetStartPosition(), GetCurrentPosition()); identifierLocation.GetStartPosition(), GetCurrentPosition());
@@ -351,15 +424,16 @@ class GD_CORE_API ExpressionParser2 {
return std::move(function); return std::move(function);
} }
std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode> std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode>
ObjectFunctionOrBehaviorFunctionOrVariable( ObjectFunctionOrBehaviorFunction(
const gd::String &parentIdentifier, const gd::String &type,
const ExpressionParserLocation &parentIdentifierLocation, const gd::String &objectName,
const ExpressionParserLocation &parentIdentifierDotLocation) { const ExpressionParserLocation &objectNameLocation,
auto childIdentifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false); const ExpressionParserLocation &objectNameDotLocation) {
const gd::String &childIdentifierName = childIdentifierAndLocation.name; auto identifierAndLocation = ReadIdentifierName();
const auto &childIdentifierNameLocation = const gd::String &objectFunctionOrBehaviorName = identifierAndLocation.name;
childIdentifierAndLocation.location; const auto &objectFunctionOrBehaviorNameLocation =
identifierAndLocation.location;
SkipAllWhitespaces(); SkipAllWhitespaces();
@@ -367,62 +441,63 @@ class GD_CORE_API ExpressionParser2 {
ExpressionParserLocation namespaceSeparatorLocation = ExpressionParserLocation namespaceSeparatorLocation =
SkipNamespaceSeparator(); SkipNamespaceSeparator();
SkipAllWhitespaces(); SkipAllWhitespaces();
return BehaviorFunction(parentIdentifier, return BehaviorFunction(type,
childIdentifierName, objectName,
parentIdentifierLocation, objectFunctionOrBehaviorName,
parentIdentifierDotLocation, objectNameLocation,
childIdentifierNameLocation, objectNameDotLocation,
objectFunctionOrBehaviorNameLocation,
namespaceSeparatorLocation); namespaceSeparatorLocation);
} else if (CheckIfChar(IsOpeningParenthesis)) { } else if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar(); ExpressionParserLocation openingParenthesisLocation = SkipChar();
gd::String objectType =
GetTypeOfObject(globalObjectsContainer, objectsContainer, objectName);
const gd::ExpressionMetadata &metadata =
MetadataProvider::GetObjectAnyExpressionMetadata(
platform, objectType, objectFunctionOrBehaviorName);
auto parametersNode = Parameters(metadata.parameters, objectName);
auto function = gd::make_unique<FunctionCallNode>( auto function = gd::make_unique<FunctionCallNode>(
parentIdentifier, metadata.GetReturnType(),
childIdentifierName); objectName,
auto parametersNode = Parameters(function.get(), parentIdentifier); std::move(parametersNode.parameters),
function->parameters = std::move(parametersNode.parameters), metadata,
objectFunctionOrBehaviorName);
function->diagnostic = std::move(parametersNode.diagnostic); function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic) // TODO: reverse the order of diagnostic?
function->diagnostic = ValidateFunction(
type, *function, objectNameLocation.GetStartPosition());
function->location = ExpressionParserLocation( function->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition()); objectNameLocation.GetStartPosition(), GetCurrentPosition());
function->objectNameLocation = parentIdentifierLocation; function->objectNameLocation = objectNameLocation;
function->objectNameDotLocation = parentIdentifierDotLocation; function->objectNameDotLocation = objectNameDotLocation;
function->functionNameLocation = childIdentifierNameLocation; function->functionNameLocation = objectFunctionOrBehaviorNameLocation;
function->openingParenthesisLocation = openingParenthesisLocation; function->openingParenthesisLocation = openingParenthesisLocation;
function->closingParenthesisLocation = function->closingParenthesisLocation =
parametersNode.closingParenthesisLocation; parametersNode.closingParenthesisLocation;
return std::move(function); return std::move(function);
} else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) {
auto variable = gd::make_unique<VariableNode>(parentIdentifier);
auto child =
gd::make_unique<VariableAccessorNode>(childIdentifierName);
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->nameLocation = childIdentifierNameLocation;
child->dotLocation = parentIdentifierDotLocation;
child->location = ExpressionParserLocation(
parentIdentifierDotLocation.GetStartPosition(), GetCurrentPosition());
variable->child = std::move(child);
variable->child->parent = variable.get();
variable->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
variable->nameLocation = parentIdentifierLocation;
return std::move(variable);
} }
auto node = gd::make_unique<IdentifierNode>( auto node = gd::make_unique<ObjectFunctionNameNode>(
parentIdentifier, childIdentifierName); type, objectName, objectFunctionOrBehaviorName);
node->diagnostic = RaiseSyntaxError(
_("An opening parenthesis (for an object expression), or double colon "
"(::) was expected (for a behavior expression)."));
node->location = ExpressionParserLocation( node->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition()); objectNameLocation.GetStartPosition(), GetCurrentPosition());
node->identifierNameLocation = parentIdentifierLocation; node->objectNameLocation = objectNameLocation;
node->identifierNameDotLocation = parentIdentifierDotLocation; node->objectNameDotLocation = objectNameDotLocation;
node->childIdentifierNameLocation = childIdentifierNameLocation; node->objectFunctionOrBehaviorNameLocation =
objectFunctionOrBehaviorNameLocation;
return std::move(node); return std::move(node);
} }
std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode> BehaviorFunction( std::unique_ptr<FunctionCallOrObjectFunctionNameOrEmptyNode> BehaviorFunction(
const gd::String &type,
const gd::String &objectName, const gd::String &objectName,
const gd::String &behaviorName, const gd::String &behaviorName,
const ExpressionParserLocation &objectNameLocation, const ExpressionParserLocation &objectNameLocation,
@@ -438,14 +513,26 @@ class GD_CORE_API ExpressionParser2 {
if (CheckIfChar(IsOpeningParenthesis)) { if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar(); ExpressionParserLocation openingParenthesisLocation = SkipChar();
gd::String behaviorType = GetTypeOfBehavior(
globalObjectsContainer, objectsContainer, behaviorName);
const gd::ExpressionMetadata &metadata =
MetadataProvider::GetBehaviorAnyExpressionMetadata(
platform, behaviorType, functionName);
auto parametersNode =
Parameters(metadata.parameters, objectName, behaviorName);
auto function = gd::make_unique<FunctionCallNode>( auto function = gd::make_unique<FunctionCallNode>(
metadata.GetReturnType(),
objectName, objectName,
behaviorName, behaviorName,
std::move(parametersNode.parameters),
metadata,
functionName); functionName);
auto parametersNode =
Parameters(function.get(), objectName, behaviorName);
function->parameters = std::move(parametersNode.parameters);
function->diagnostic = std::move(parametersNode.diagnostic); function->diagnostic = std::move(parametersNode.diagnostic);
if (!function->diagnostic) // TODO: reverse the order of diagnostic?
function->diagnostic = ValidateFunction(
type, *function, objectNameLocation.GetStartPosition());
function->location = ExpressionParserLocation( function->location = ExpressionParserLocation(
objectNameLocation.GetStartPosition(), GetCurrentPosition()); objectNameLocation.GetStartPosition(), GetCurrentPosition());
@@ -461,7 +548,7 @@ class GD_CORE_API ExpressionParser2 {
return std::move(function); return std::move(function);
} else { } else {
auto node = gd::make_unique<ObjectFunctionNameNode>( auto node = gd::make_unique<ObjectFunctionNameNode>(
objectName, behaviorName, functionName); type, objectName, behaviorName, functionName);
node->diagnostic = RaiseSyntaxError( node->diagnostic = RaiseSyntaxError(
_("An opening parenthesis was expected here to call a function.")); _("An opening parenthesis was expected here to call a function."));
@@ -485,7 +572,7 @@ class GD_CORE_API ExpressionParser2 {
}; };
ParametersNode Parameters( ParametersNode Parameters(
FunctionCallNode *functionCallNode, std::vector<gd::ParameterMetadata> parameterMetadata,
const gd::String &objectName = "", const gd::String &objectName = "",
const gd::String &behaviorName = "") { const gd::String &behaviorName = "") {
std::vector<std::unique_ptr<ExpressionNode>> parameters; std::vector<std::unique_ptr<ExpressionNode>> parameters;
@@ -496,25 +583,77 @@ class GD_CORE_API ExpressionParser2 {
size_t parameterIndex = size_t parameterIndex =
WrittenParametersFirstIndex(objectName, behaviorName); WrittenParametersFirstIndex(objectName, behaviorName);
bool previousCharacterIsParameterSeparator = false;
while (!IsEndReached()) { while (!IsEndReached()) {
SkipAllWhitespaces(); SkipAllWhitespaces();
if (CheckIfChar(IsClosingParenthesis) && !previousCharacterIsParameterSeparator) { if (CheckIfChar(IsClosingParenthesis)) {
auto closingParenthesisLocation = SkipChar(); auto closingParenthesisLocation = SkipChar();
return ParametersNode{ return ParametersNode{
std::move(parameters), nullptr, closingParenthesisLocation}; std::move(parameters), nullptr, closingParenthesisLocation};
} } else {
bool isEmptyParameter = CheckIfChar(IsParameterSeparator) if (parameterIndex < parameterMetadata.size()) {
|| (CheckIfChar(IsClosingParenthesis) && previousCharacterIsParameterSeparator); const gd::String &type = parameterMetadata[parameterIndex].GetType();
auto parameter = isEmptyParameter ? gd::make_unique<EmptyNode>() : Expression(); if (parameterMetadata[parameterIndex].IsCodeOnly()) {
parameter->parent = functionCallNode; // Do nothing, code only parameters are not written in expressions.
parameters.push_back(std::move(parameter)); } else if (gd::ParameterMetadata::IsExpression("number", type)) {
parameters.push_back(Expression("number"));
} else if (gd::ParameterMetadata::IsExpression("string", type)) {
parameters.push_back(Expression("string"));
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
parameters.push_back(Expression(
type, lastObjectName.empty() ? objectName : lastObjectName));
} else if (gd::ParameterMetadata::IsObject(type)) {
size_t parameterStartPosition = GetCurrentPosition();
std::unique_ptr<ExpressionNode> objectExpression = Expression(type);
SkipAllWhitespaces(); // Memorize the last object name. By convention, parameters that
previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator); // require an object (mainly, "objectvar" and "behavior") should be
SkipIfChar(IsParameterSeparator); // placed after the object in the list of parameters (if possible,
parameterIndex++; // just after). Search "lastObjectName" in the codebase for other
// place where this convention is enforced.
if (auto identifierNode =
dynamic_cast<IdentifierNode *>(objectExpression.get())) {
lastObjectName = identifierNode->identifierName;
} else {
objectExpression->diagnostic =
gd::make_unique<ExpressionParserError>(
"malformed_object_parameter",
_("An object name was expected but something else was "
"written. Enter just the name of the object for this "
"parameter."),
parameterStartPosition,
GetCurrentPosition());
}
parameters.push_back(std::move(objectExpression));
} else {
size_t parameterStartPosition = GetCurrentPosition();
parameters.push_back(Expression("unknown"));
parameters.back()->diagnostic =
gd::make_unique<ExpressionParserError>(
"unknown_parameter_type",
_("This function is improperly set up. Reach out to the "
"extension developer or a GDevelop maintainer to fix "
"this issue"),
parameterStartPosition,
GetCurrentPosition());
}
} else {
size_t parameterStartPosition = GetCurrentPosition();
parameters.push_back(Expression("unknown"));
parameters.back()
->diagnostic = gd::make_unique<ExpressionParserError>(
"extra_parameter",
_("This parameter was not expected by this expression. Remove it "
"or verify that you've entered the proper expression name."),
parameterStartPosition,
GetCurrentPosition());
}
SkipAllWhitespaces();
SkipIfChar(IsParameterSeparator);
parameterIndex++;
}
} }
ExpressionParserLocation invalidClosingParenthesisLocation; ExpressionParserLocation invalidClosingParenthesisLocation;
@@ -526,32 +665,92 @@ class GD_CORE_API ExpressionParser2 {
} }
///@} ///@}
/** \name Validators
* Return a diagnostic if any error is found
*/
///@{
std::unique_ptr<ExpressionParserDiagnostic> ValidateFunction(
const gd::String &type,
const gd::FunctionCallNode &function,
size_t functionStartPosition);
std::unique_ptr<ExpressionParserDiagnostic> ValidateOperator( std::unique_ptr<ExpressionParserDiagnostic> ValidateOperator(
gd::String::value_type operatorChar) { const gd::String &type, gd::String::value_type operatorChar) {
if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' || if (type == "number") {
operatorChar == '*') { if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' ||
return gd::make_unique<ExpressionParserDiagnostic>(); operatorChar == '*') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an operator that is not supported. Operator should be "
"either +, -, / or *."),
GetCurrentPosition());
} else if (type == "string") {
if (operatorChar == '+') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an operator that is not supported. Only + can be used "
"to concatenate texts."),
GetCurrentPosition());
} else if (gd::ParameterMetadata::IsObject(type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -, /, *) can't be used with an object name. Remove "
"the operator."),
GetCurrentPosition());
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -, /, *) can't be used in variable names. Remove "
"the operator from the variable name."),
GetCurrentPosition());
} }
return gd::make_unique<ExpressionParserError>(
"invalid_operator", return gd::make_unique<ExpressionParserDiagnostic>();
_("You've used an operator that is not supported. Operator should be "
"either +, -, / or *."),
GetCurrentPosition());
} }
std::unique_ptr<ExpressionParserDiagnostic> ValidateUnaryOperator( std::unique_ptr<ExpressionParserDiagnostic> ValidateUnaryOperator(
const gd::String &type,
gd::String::value_type operatorChar, gd::String::value_type operatorChar,
size_t position) { size_t position) {
if (operatorChar == '+' || operatorChar == '-') { if (type == "number") {
return gd::make_unique<ExpressionParserDiagnostic>(); if (operatorChar == '+' || operatorChar == '-') {
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an \"unary\" operator that is not supported. Operator "
"should be "
"either + or -."),
position);
} else if (type == "string") {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("You've used an operator that is not supported. Only + can be used "
"to concatenate texts, and must be placed between two texts (or "
"expressions)."),
position);
} else if (gd::ParameterMetadata::IsObject(type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -) can't be used with an object name. Remove the "
"operator."),
position);
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
return gd::make_unique<ExpressionParserError>(
"invalid_operator",
_("Operators (+, -) can't be used in variable names. Remove "
"the operator from the variable name."),
position);
} }
return gd::make_unique<ExpressionParserError>( return gd::make_unique<ExpressionParserDiagnostic>();
"invalid_operator",
_("You've used an \"unary\" operator that is not supported. Operator "
"should be "
"either + or -."),
position);
} }
///@} ///@}
@@ -597,6 +796,95 @@ class GD_CORE_API ExpressionParser2 {
return predicate(character); return predicate(character);
} }
bool IsIdentifierAllowedChar() {
if (currentPosition >= expression.size()) return false;
gd::String::value_type character = expression[currentPosition];
// Quickly compare if the character is a number or ASCII character.
if ((character >= '0' && character <= '9') ||
(character >= 'A' && character <= 'Z') ||
(character >= 'a' && character <= 'z'))
return true;
// Otherwise do the full check against separators forbidden in identifiers.
if (!IsParameterSeparator(character) && !IsDot(character) &&
!IsQuote(character) && !IsBracket(character) &&
!IsExpressionOperator(character) && !IsTermOperator(character)) {
return true;
}
return false;
}
static bool IsWhitespace(gd::String::value_type character) {
return character == ' ' || character == '\n' || character == '\r';
}
static bool IsParameterSeparator(gd::String::value_type character) {
return character == ',';
}
static bool IsDot(gd::String::value_type character) {
return character == '.';
}
static bool IsQuote(gd::String::value_type character) {
return character == '"';
}
static bool IsBracket(gd::String::value_type character) {
return character == '(' || character == ')' || character == '[' ||
character == ']' || character == '{' || character == '}';
}
static bool IsOpeningParenthesis(gd::String::value_type character) {
return character == '(';
}
static bool IsClosingParenthesis(gd::String::value_type character) {
return character == ')';
}
static bool IsOpeningSquareBracket(gd::String::value_type character) {
return character == '[';
}
static bool IsClosingSquareBracket(gd::String::value_type character) {
return character == ']';
}
static bool IsExpressionEndingChar(gd::String::value_type character) {
return character == ',' || IsClosingParenthesis(character) ||
IsClosingSquareBracket(character);
}
static bool IsExpressionOperator(gd::String::value_type character) {
return character == '+' || character == '-' || character == '<' ||
character == '>' || character == '?' || character == '^' ||
character == '=' || character == '\\' || character == ':' ||
character == '!';
}
static bool IsUnaryOperator(gd::String::value_type character) {
return character == '+' || character == '-';
}
static bool IsTermOperator(gd::String::value_type character) {
return character == '/' || character == '*';
}
static bool IsNumberFirstChar(gd::String::value_type character) {
return character == '.' || (character >= '0' && character <= '9');
}
static bool IsNonZeroDigit(gd::String::value_type character) {
return (character >= '1' && character <= '9');
}
static bool IsZeroDigit(gd::String::value_type character) {
return character == '0';
}
bool IsNamespaceSeparator() { bool IsNamespaceSeparator() {
// Namespace separator is a special kind of delimiter as it is 2 characters // Namespace separator is a special kind of delimiter as it is 2 characters
// long // long
@@ -613,13 +901,13 @@ class GD_CORE_API ExpressionParser2 {
ExpressionParserLocation location; ExpressionParserLocation location;
}; };
IdentifierAndLocation ReadIdentifierName(bool allowDeprecatedSpacesInName = true) { IdentifierAndLocation ReadIdentifierName() {
gd::String name; gd::String name;
size_t startPosition = currentPosition; size_t startPosition = currentPosition;
while (currentPosition < expression.size() && while (currentPosition < expression.size() &&
(CheckIfChar(IsAllowedInIdentifier) (IsIdentifierAllowedChar()
// Allow whitespace in identifier name for compatibility // Allow whitespace in identifier name for compatibility
|| (allowDeprecatedSpacesInName && expression[currentPosition] == ' '))) { || expression[currentPosition] == ' ')) {
name += expression[currentPosition]; name += expression[currentPosition];
currentPosition++; currentPosition++;
} }
@@ -650,7 +938,7 @@ class GD_CORE_API ExpressionParser2 {
std::unique_ptr<NumberNode> ReadNumber(); std::unique_ptr<NumberNode> ReadNumber();
std::unique_ptr<EmptyNode> ReadUntilWhitespace() { std::unique_ptr<EmptyNode> ReadUntilWhitespace(gd::String type) {
size_t startPosition = GetCurrentPosition(); size_t startPosition = GetCurrentPosition();
gd::String text; gd::String text;
while (currentPosition < expression.size() && while (currentPosition < expression.size() &&
@@ -659,13 +947,13 @@ class GD_CORE_API ExpressionParser2 {
currentPosition++; currentPosition++;
} }
auto node = gd::make_unique<EmptyNode>(text); auto node = gd::make_unique<EmptyNode>(type, text);
node->location = node->location =
ExpressionParserLocation(startPosition, GetCurrentPosition()); ExpressionParserLocation(startPosition, GetCurrentPosition());
return node; return node;
} }
std::unique_ptr<EmptyNode> ReadUntilEnd() { std::unique_ptr<EmptyNode> ReadUntilEnd(gd::String type) {
size_t startPosition = GetCurrentPosition(); size_t startPosition = GetCurrentPosition();
gd::String text; gd::String text;
while (currentPosition < expression.size()) { while (currentPosition < expression.size()) {
@@ -673,7 +961,7 @@ class GD_CORE_API ExpressionParser2 {
currentPosition++; currentPosition++;
} }
auto node = gd::make_unique<EmptyNode>(text); auto node = gd::make_unique<EmptyNode>(type, text);
node->location = node->location =
ExpressionParserLocation(startPosition, GetCurrentPosition()); ExpressionParserLocation(startPosition, GetCurrentPosition());
return node; return node;
@@ -706,11 +994,34 @@ class GD_CORE_API ExpressionParser2 {
return std::move(gd::make_unique<ExpressionParserError>( return std::move(gd::make_unique<ExpressionParserError>(
"type_error", message, beginningPosition, GetCurrentPosition())); "type_error", message, beginningPosition, GetCurrentPosition()));
} }
std::unique_ptr<ExpressionParserError> RaiseEmptyError(
const gd::String &type, size_t beginningPosition) {
gd::String message;
if (type == "number") {
message = _("You must enter a number or a valid expression call.");
} else if (type == "string") {
message = _(
"You must enter a text (between quotes) or a valid expression call.");
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
message = _("You must enter a variable name.");
} else if (gd::ParameterMetadata::IsObject(type)) {
message = _("You must enter a valid object name.");
} else {
message = _("You must enter a valid expression.");
}
return std::move(RaiseTypeError(message, beginningPosition));
}
///@} ///@}
gd::String expression; gd::String expression;
std::size_t currentPosition; std::size_t currentPosition;
const gd::Platform &platform;
const gd::ObjectsContainer &globalObjectsContainer;
const gd::ObjectsContainer &objectsContainer;
static gd::String NAMESPACE_SEPARATOR; static gd::String NAMESPACE_SEPARATOR;
}; };

View File

@@ -17,12 +17,11 @@ class ObjectsContainer;
class Platform; class Platform;
class ParameterMetadata; class ParameterMetadata;
class ExpressionMetadata; class ExpressionMetadata;
struct FunctionCallNode;
} // namespace gd } // namespace gd
namespace gd { namespace gd {
struct GD_CORE_API ExpressionParserLocation { struct ExpressionParserLocation {
ExpressionParserLocation() : isValid(false){}; ExpressionParserLocation() : isValid(false){};
ExpressionParserLocation(size_t position) ExpressionParserLocation(size_t position)
: isValid(true), startPosition(position), endPosition(position){}; : isValid(true), startPosition(position), endPosition(position){};
@@ -43,8 +42,7 @@ struct GD_CORE_API ExpressionParserLocation {
/** /**
* \brief A diagnostic that can be attached to a gd::ExpressionNode. * \brief A diagnostic that can be attached to a gd::ExpressionNode.
*/ */
struct GD_CORE_API ExpressionParserDiagnostic { struct ExpressionParserDiagnostic {
virtual ~ExpressionParserDiagnostic() = default;
virtual bool IsError() { return false; } virtual bool IsError() { return false; }
virtual const gd::String &GetMessage() { return noMessage; } virtual const gd::String &GetMessage() { return noMessage; }
virtual size_t GetStartPosition() { return 0; } virtual size_t GetStartPosition() { return 0; }
@@ -57,11 +55,7 @@ struct GD_CORE_API ExpressionParserDiagnostic {
/** /**
* \brief An error that can be attached to a gd::ExpressionNode. * \brief An error that can be attached to a gd::ExpressionNode.
*/ */
struct GD_CORE_API ExpressionParserError : public ExpressionParserDiagnostic { struct ExpressionParserError : public ExpressionParserDiagnostic {
ExpressionParserError(const gd::String &type_,
const gd::String &message_,
const ExpressionParserLocation &location_)
: type(type_), message(message_), location(location_){};
ExpressionParserError(const gd::String &type_, ExpressionParserError(const gd::String &type_,
const gd::String &message_, const gd::String &message_,
size_t position_) size_t position_)
@@ -90,8 +84,8 @@ struct GD_CORE_API ExpressionParserError : public ExpressionParserDiagnostic {
* \brief The base node, from which all nodes in the tree of * \brief The base node, from which all nodes in the tree of
* an expression inherits from. * an expression inherits from.
*/ */
struct GD_CORE_API ExpressionNode { struct ExpressionNode {
ExpressionNode() : parent(nullptr) {}; ExpressionNode(const gd::String &type_) : type(type_){};
virtual ~ExpressionNode(){}; virtual ~ExpressionNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker){}; virtual void Visit(ExpressionParser2NodeWorker &worker){};
@@ -102,12 +96,17 @@ struct GD_CORE_API ExpressionNode {
/// function can store the position of the /// function can store the position of the
/// object name, the dot, the function /// object name, the dot, the function
/// name, etc... /// name, etc...
ExpressionNode *parent;
gd::String type; // Actual type of the node.
// "string", "number", type supported by
// gd::ParameterMetadata::IsObject, types supported by
// gd::ParameterMetadata::IsExpression or "unknown".
}; };
struct GD_CORE_API SubExpressionNode : public ExpressionNode { struct SubExpressionNode : public ExpressionNode {
SubExpressionNode(std::unique_ptr<ExpressionNode> expression_) SubExpressionNode(const gd::String &type_,
: ExpressionNode(), expression(std::move(expression_)){}; std::unique_ptr<ExpressionNode> expression_)
: ExpressionNode(type_), expression(std::move(expression_)){};
virtual ~SubExpressionNode(){}; virtual ~SubExpressionNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitSubExpressionNode(*this); worker.OnVisitSubExpressionNode(*this);
@@ -119,9 +118,9 @@ struct GD_CORE_API SubExpressionNode : public ExpressionNode {
/** /**
* \brief An operator node. For example: "lhs + rhs". * \brief An operator node. For example: "lhs + rhs".
*/ */
struct GD_CORE_API OperatorNode : public ExpressionNode { struct OperatorNode : public ExpressionNode {
OperatorNode(gd::String::value_type op_) OperatorNode(const gd::String &type_, gd::String::value_type op_)
: ExpressionNode(), op(op_){}; : ExpressionNode(type_), op(op_){};
virtual ~OperatorNode(){}; virtual ~OperatorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitOperatorNode(*this); worker.OnVisitOperatorNode(*this);
@@ -135,9 +134,9 @@ struct GD_CORE_API OperatorNode : public ExpressionNode {
/** /**
* \brief A unary operator node. For example: "-2". * \brief A unary operator node. For example: "-2".
*/ */
struct GD_CORE_API UnaryOperatorNode : public ExpressionNode { struct UnaryOperatorNode : public ExpressionNode {
UnaryOperatorNode(gd::String::value_type op_) UnaryOperatorNode(const gd::String &type_, gd::String::value_type op_)
: ExpressionNode(), op(op_){}; : ExpressionNode(type_), op(op_){};
virtual ~UnaryOperatorNode(){}; virtual ~UnaryOperatorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitUnaryOperatorNode(*this); worker.OnVisitUnaryOperatorNode(*this);
@@ -151,9 +150,9 @@ struct GD_CORE_API UnaryOperatorNode : public ExpressionNode {
* \brief A number node. For example: "123". * \brief A number node. For example: "123".
* Its `type` is always "number". * Its `type` is always "number".
*/ */
struct GD_CORE_API NumberNode : public ExpressionNode { struct NumberNode : public ExpressionNode {
NumberNode(const gd::String &number_) NumberNode(const gd::String &number_)
: ExpressionNode(), number(number_){}; : ExpressionNode("number"), number(number_){};
virtual ~NumberNode(){}; virtual ~NumberNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitNumberNode(*this); worker.OnVisitNumberNode(*this);
@@ -167,8 +166,8 @@ struct GD_CORE_API NumberNode : public ExpressionNode {
* \brief A text node. For example: "Hello World". * \brief A text node. For example: "Hello World".
* Its `type` is always "string". * Its `type` is always "string".
*/ */
struct GD_CORE_API TextNode : public ExpressionNode { struct TextNode : public ExpressionNode {
TextNode(const gd::String &text_) : ExpressionNode(), text(text_){}; TextNode(const gd::String &text_) : ExpressionNode("string"), text(text_){};
virtual ~TextNode(){}; virtual ~TextNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitTextNode(*this); worker.OnVisitTextNode(*this);
@@ -177,89 +176,32 @@ struct GD_CORE_API TextNode : public ExpressionNode {
gd::String text; gd::String text;
}; };
struct GD_CORE_API IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode struct VariableAccessorOrVariableBracketAccessorNode : public ExpressionNode {
: public ExpressionNode { VariableAccessorOrVariableBracketAccessorNode() : ExpressionNode(""){};
IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode()
: ExpressionNode(){};
};
/**
* \brief An identifier node, usually representing an object or a variable
* with an optional function name or child variable name respectively.
*
* The name of a function to call on an object or the behavior,
* for example: "MyObject.Function" or "MyObject.Physics".
*
* A variable, potentially with accessor to its child,
* for example: MyVariable or MyVariable.MyChild
*/
struct GD_CORE_API IdentifierNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
IdentifierNode(
const gd::String &identifierName_)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(),
identifierName(identifierName_),
childIdentifierName(""){};
IdentifierNode(
const gd::String &identifierName_,
const gd::String &childIdentifierName_)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(),
identifierName(identifierName_),
childIdentifierName(childIdentifierName_){};
virtual ~IdentifierNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitIdentifierNode(*this);
};
gd::String identifierName; ///< The object or variable name.
gd::String childIdentifierName; ///< The object function or variable child name.
ExpressionParserLocation
identifierNameLocation; ///< Location of the object or variable name.
ExpressionParserLocation
identifierNameDotLocation; ///< Location of the "." after the object or variable name.
ExpressionParserLocation childIdentifierNameLocation; ///< Location of object
/// function, behavior or
/// child variable name.
};
struct GD_CORE_API FunctionCallOrObjectFunctionNameOrEmptyNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
FunctionCallOrObjectFunctionNameOrEmptyNode()
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(){};
virtual ~FunctionCallOrObjectFunctionNameOrEmptyNode(){};
void Visit(ExpressionParser2NodeWorker &worker) override{};
};
struct GD_CORE_API VariableAccessorOrVariableBracketAccessorNode : public ExpressionNode {
VariableAccessorOrVariableBracketAccessorNode() : ExpressionNode(){};
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> child; std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> child;
}; };
/** /**
* \brief A variable, or object variable, with bracket accessor or at least 2 "dot" accessors. * \brief A variable, potentially with accessor to its children.
* *
* Example: `MyVariable["MyChildren"]` or `MyVariable.MyChildren.MyGrandChildren`. * Example: MyVariable or MyVariable.MyChildren
* Example: `MyObject["MyVariable"]` or `MyObject.MyVariable.MyChildren`.
* *
* Other cases like "MyVariable" or "MyVariable.MyChildren" are IdentifierNode
* to allow handling ambiguities.
*
* \see gd::IdentifierNode
* \see gd::VariableAccessorNode * \see gd::VariableAccessorNode
* \see gd::VariableBracketAccessorNode * \see gd::VariableBracketAccessorNode
*/ */
struct GD_CORE_API VariableNode : public FunctionCallOrObjectFunctionNameOrEmptyNode { struct VariableNode : public ExpressionNode {
VariableNode(const gd::String &name_) VariableNode(const gd::String &type_,
: FunctionCallOrObjectFunctionNameOrEmptyNode(), name(name_){}; const gd::String &name_,
const gd::String &objectName_)
: ExpressionNode(type_), name(name_), objectName(objectName_){};
virtual ~VariableNode(){}; virtual ~VariableNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitVariableNode(*this); worker.OnVisitVariableNode(*this);
}; };
gd::String name; gd::String name;
gd::String objectName;
std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode> std::unique_ptr<VariableAccessorOrVariableBracketAccessorNode>
child; // Can be nullptr if no accessor child; // Can be nullptr if no accessor
@@ -268,13 +210,12 @@ struct GD_CORE_API VariableNode : public FunctionCallOrObjectFunctionNameOrEmpty
}; };
/** /**
* \brief A direct accessor to a child variable. Example: MyChild * \brief A bracket accessor of a variable. Example: MyChild
* in MyVariable.MyChild * in MyVariable.MyChild
*/ */
struct GD_CORE_API VariableAccessorNode struct VariableAccessorNode
: public VariableAccessorOrVariableBracketAccessorNode { : public VariableAccessorOrVariableBracketAccessorNode {
VariableAccessorNode(const gd::String &name_) VariableAccessorNode(const gd::String &name_) : name(name_){};
: VariableAccessorOrVariableBracketAccessorNode(), name(name_){};
virtual ~VariableAccessorNode(){}; virtual ~VariableAccessorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitVariableAccessorNode(*this); worker.OnVisitVariableAccessorNode(*this);
@@ -286,13 +227,13 @@ struct GD_CORE_API VariableAccessorNode
}; };
/** /**
* \brief A bracket accessor to a child variable. Example: ["MyChild"] * \brief A bracket accessor of a variable. Example: ["MyChild"]
* (in MyVariable["MyChild"]). * (in MyVariable["MyChild"]).
*/ */
struct GD_CORE_API VariableBracketAccessorNode struct VariableBracketAccessorNode
: public VariableAccessorOrVariableBracketAccessorNode { : public VariableAccessorOrVariableBracketAccessorNode {
VariableBracketAccessorNode(std::unique_ptr<ExpressionNode> expression_) VariableBracketAccessorNode(std::unique_ptr<ExpressionNode> expression_)
: VariableAccessorOrVariableBracketAccessorNode(), expression(std::move(expression_)){}; : expression(std::move(expression_)){};
virtual ~VariableBracketAccessorNode(){}; virtual ~VariableBracketAccessorNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitVariableBracketAccessorNode(*this); worker.OnVisitVariableBracketAccessorNode(*this);
@@ -301,26 +242,55 @@ struct GD_CORE_API VariableBracketAccessorNode
std::unique_ptr<ExpressionNode> expression; std::unique_ptr<ExpressionNode> expression;
}; };
struct IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode
: public ExpressionNode {
IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(
const gd::String &type)
: ExpressionNode(type){};
};
/**
* \brief An identifier node, usually representing an object or a function name.
*/
struct IdentifierNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
IdentifierNode(const gd::String &identifierName_, const gd::String &type_)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(type_),
identifierName(identifierName_){};
virtual ~IdentifierNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitIdentifierNode(*this);
};
gd::String identifierName;
};
struct FunctionCallOrObjectFunctionNameOrEmptyNode
: public IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode {
FunctionCallOrObjectFunctionNameOrEmptyNode(const gd::String &type)
: IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode(type){};
virtual ~FunctionCallOrObjectFunctionNameOrEmptyNode(){};
void Visit(ExpressionParser2NodeWorker &worker) override{};
};
/** /**
* \brief The name of a function to call on an object or the behavior * \brief The name of a function to call on an object or the behavior
* For example: "MyObject.Physics::LinearVelocity". * For example: "MyObject.Function" or "MyObject.Physics" or
* * "MyObject.Physics::LinearVelocity".
* Other cases like "MyObject.Function" or "MyObject.Physics" are IdentifierNode
* to allow handling ambiguities.
*
* \see gd::IdentifierNode
*/ */
struct GD_CORE_API ObjectFunctionNameNode struct ObjectFunctionNameNode
: public FunctionCallOrObjectFunctionNameOrEmptyNode { : public FunctionCallOrObjectFunctionNameOrEmptyNode {
ObjectFunctionNameNode(const gd::String &objectName_, ObjectFunctionNameNode(const gd::String &type_,
const gd::String &objectName_,
const gd::String &objectFunctionOrBehaviorName_) const gd::String &objectFunctionOrBehaviorName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(), : FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
objectName(objectName_), objectName(objectName_),
objectFunctionOrBehaviorName(objectFunctionOrBehaviorName_) {} objectFunctionOrBehaviorName(objectFunctionOrBehaviorName_) {}
ObjectFunctionNameNode(const gd::String &objectName_, ObjectFunctionNameNode(const gd::String &type_,
const gd::String &objectName_,
const gd::String &behaviorName_, const gd::String &behaviorName_,
const gd::String &behaviorFunctionName_) const gd::String &behaviorFunctionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(), : FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
objectName(objectName_), objectName(objectName_),
objectFunctionOrBehaviorName(behaviorName_), objectFunctionOrBehaviorName(behaviorName_),
behaviorFunctionName(behaviorFunctionName_) {} behaviorFunctionName(behaviorFunctionName_) {}
@@ -361,26 +331,41 @@ struct GD_CORE_API ObjectFunctionNameNode
* For example: "MyExtension::MyFunction(1, 2)", "MyObject.Function()" or * For example: "MyExtension::MyFunction(1, 2)", "MyObject.Function()" or
* "MyObject.Physics::LinearVelocity()". * "MyObject.Physics::LinearVelocity()".
*/ */
struct GD_CORE_API FunctionCallNode : public FunctionCallOrObjectFunctionNameOrEmptyNode { struct FunctionCallNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
/** \brief Construct a free function call node. */ /** \brief Construct a free function call node. */
FunctionCallNode(const gd::String &functionName_) FunctionCallNode(const gd::String &type_,
: FunctionCallOrObjectFunctionNameOrEmptyNode(), std::vector<std::unique_ptr<ExpressionNode>> parameters_,
const ExpressionMetadata &expressionMetadata_,
const gd::String &functionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
parameters(std::move(parameters_)),
expressionMetadata(expressionMetadata_),
functionName(functionName_){}; functionName(functionName_){};
/** \brief Construct an object function call node. */ /** \brief Construct an object function call node. */
FunctionCallNode(const gd::String &objectName_, FunctionCallNode(const gd::String &type_,
const gd::String &objectName_,
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
const ExpressionMetadata &expressionMetadata_,
const gd::String &functionName_) const gd::String &functionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(), : FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
objectName(objectName_), objectName(objectName_),
parameters(std::move(parameters_)),
expressionMetadata(expressionMetadata_),
functionName(functionName_){}; functionName(functionName_){};
/** \brief Construct a behavior function call node. */ /** \brief Construct a behavior function call node. */
FunctionCallNode(const gd::String &objectName_, FunctionCallNode(const gd::String &type_,
const gd::String &objectName_,
const gd::String &behaviorName_, const gd::String &behaviorName_,
std::vector<std::unique_ptr<ExpressionNode>> parameters_,
const ExpressionMetadata &expressionMetadata_,
const gd::String &functionName_) const gd::String &functionName_)
: FunctionCallOrObjectFunctionNameOrEmptyNode(), : FunctionCallOrObjectFunctionNameOrEmptyNode(type_),
objectName(objectName_), objectName(objectName_),
behaviorName(behaviorName_), behaviorName(behaviorName_),
parameters(std::move(parameters_)),
expressionMetadata(expressionMetadata_),
functionName(functionName_){}; functionName(functionName_){};
virtual ~FunctionCallNode(){}; virtual ~FunctionCallNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
@@ -390,6 +375,7 @@ struct GD_CORE_API FunctionCallNode : public FunctionCallOrObjectFunctionNameOrE
gd::String objectName; gd::String objectName;
gd::String behaviorName; gd::String behaviorName;
std::vector<std::unique_ptr<ExpressionNode>> parameters; std::vector<std::unique_ptr<ExpressionNode>> parameters;
const ExpressionMetadata &expressionMetadata;
gd::String functionName; gd::String functionName;
ExpressionParserLocation ExpressionParserLocation
@@ -413,9 +399,9 @@ struct GD_CORE_API FunctionCallNode : public FunctionCallOrObjectFunctionNameOrE
* \brief An empty node, used when parsing failed/a syntax error was * \brief An empty node, used when parsing failed/a syntax error was
* encountered and any other node could not make sense. * encountered and any other node could not make sense.
*/ */
struct GD_CORE_API EmptyNode : public FunctionCallOrObjectFunctionNameOrEmptyNode { struct EmptyNode : public FunctionCallOrObjectFunctionNameOrEmptyNode {
EmptyNode(const gd::String &text_ = "") EmptyNode(const gd::String &type_, const gd::String &text_ = "")
: FunctionCallOrObjectFunctionNameOrEmptyNode(), text(text_){}; : FunctionCallOrObjectFunctionNameOrEmptyNode(type_), text(text_){};
virtual ~EmptyNode(){}; virtual ~EmptyNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker) { virtual void Visit(ExpressionParser2NodeWorker &worker) {
worker.OnVisitEmptyNode(*this); worker.OnVisitEmptyNode(*this);

View File

@@ -91,9 +91,6 @@ class GD_CORE_API ExpressionParser2NodePrinter
} }
void OnVisitIdentifierNode(IdentifierNode& node) override { void OnVisitIdentifierNode(IdentifierNode& node) override {
output += node.identifierName; output += node.identifierName;
if (!node.childIdentifierName.empty()) {
output += "." + node.childIdentifierName;
}
} }
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override { void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
if (!node.behaviorFunctionName.empty()) { if (!node.behaviorFunctionName.empty()) {

View File

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

View File

@@ -1,118 +0,0 @@
#pragma once
#include "GDCore/String.h"
namespace gd {
/**
* Contains functions to handle the grammar of the expressions accepted by GDevelop.
*/
namespace GrammarTerminals {
inline bool IsWhitespace(gd::String::value_type character) {
return character == ' ' || character == '\n' || character == '\r';
}
inline bool IsParameterSeparator(gd::String::value_type character) {
return character == ',';
}
inline bool IsDot(gd::String::value_type character) { return character == '.'; }
inline bool IsQuote(gd::String::value_type character) {
return character == '"';
}
inline bool IsBracket(gd::String::value_type character) {
return character == '(' || character == ')' || character == '[' ||
character == ']' || character == '{' || character == '}';
}
inline bool IsOpeningParenthesis(gd::String::value_type character) {
return character == '(';
}
inline bool IsClosingParenthesis(gd::String::value_type character) {
return character == ')';
}
inline bool IsOpeningSquareBracket(gd::String::value_type character) {
return character == '[';
}
inline bool IsClosingSquareBracket(gd::String::value_type character) {
return character == ']';
}
inline bool IsExpressionEndingChar(gd::String::value_type character) {
return character == ',' || IsClosingParenthesis(character) ||
IsClosingSquareBracket(character);
}
inline bool IsExpressionOperator(gd::String::value_type character) {
return character == '+' || character == '-' || character == '<' ||
character == '>' || character == '?' || character == '^' ||
character == '=' || character == '\\' || character == ':' ||
character == '!';
}
inline bool IsUnaryOperator(gd::String::value_type character) {
return character == '+' || character == '-';
}
inline bool IsTermOperator(gd::String::value_type character) {
return character == '/' || character == '*';
}
inline bool IsNumberFirstChar(gd::String::value_type character) {
return character == '.' || (character >= '0' && character <= '9');
}
inline bool IsNonZeroDigit(gd::String::value_type character) {
return (character >= '1' && character <= '9');
}
inline bool IsZeroDigit(gd::String::value_type character) {
return character == '0';
}
inline bool IsAdditionalReservedCharacter(gd::String::value_type character) {
// These characters are not part of the grammar - but are often used in programming language
// and could become operators or part of the grammar one day.
return character == '~' || character == '\'' || character == '%' ||
character == '#' || character == '@' || character == '|' ||
character == '&' || character == '`' || character == '$' ||
character == ';';
}
/**
* Check if the given character can be used in an identifier. This is
* any unicode character, except for:
* `, . " () [] {} + - < > ? ^ = \ : ! / * ~ ' % # @ | & $ ;`
* and backtick and whitespaces (space, line break, carriage return).
*
* This is loosely based on what is allowed in languages like JavaScript
* (see https://mathiasbynens.be/notes/javascript-properties), without support
* for unicode escape syntax, and allowing all unicode ranges. The only
* disallowed characters are the one used for the grammar.
*/
inline bool IsAllowedInIdentifier(gd::String::value_type character) {
// Quickly compare if the character is a number or ASCII character.
if ((character >= '0' && character <= '9') ||
(character >= 'A' && character <= 'Z') ||
(character >= 'a' && character <= 'z'))
return true;
// Otherwise do the full check against separators forbidden in identifiers.
if (!IsParameterSeparator(character) && !IsDot(character) &&
!IsQuote(character) && !IsBracket(character) &&
!IsExpressionOperator(character) && !IsTermOperator(character) &&
!IsWhitespace(character) && !IsAdditionalReservedCharacter(character)) {
return true;
}
return false;
}
} // namespace GrammarTerminals
} // namespace gd

View File

@@ -4,7 +4,6 @@
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#include "GDCore/Events/Serialization.h" #include "GDCore/Events/Serialization.h"
#include "GDCore/CommonTools.h" #include "GDCore/CommonTools.h"
#include "GDCore/Events/Event.h" #include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h" #include "GDCore/Events/EventsList.h"
@@ -184,8 +183,8 @@ void EventsListSerialization::UpdateInstructionsFromGD2x(
for (std::size_t j = 0; for (std::size_t j = 0;
j < parameters.size() && j < metadata.parameters.size(); j < parameters.size() && j < metadata.parameters.size();
++j) { ++j) {
if (metadata.parameters[j].GetType() == "relationalOperator" || if (metadata.parameters[j].type == "relationalOperator" ||
metadata.parameters[j].GetType() == "operator") { metadata.parameters[j].type == "operator") {
if (j == parameters.size() - 1) { if (j == parameters.size() - 1) {
std::cout << "ERROR: No more parameters after a [relational]operator " std::cout << "ERROR: No more parameters after a [relational]operator "
"when trying to update an instruction from GD2.x"; "when trying to update an instruction from GD2.x";
@@ -219,8 +218,8 @@ void EventsListSerialization::UnserializeEventsFrom(
event = std::make_shared<EmptyEvent>(); event = std::make_shared<EmptyEvent>();
} }
event->SetDisabled(eventElem.GetBoolAttribute("disabled", false)); event->SetDisabled(eventElem.GetBoolAttribute("disabled"));
event->SetFolded(eventElem.GetBoolAttribute("folded", false)); event->SetFolded(eventElem.GetBoolAttribute("folded"));
list.InsertEvent(event, list.GetEventsCount()); list.InsertEvent(event, list.GetEventsCount());
} }
@@ -233,9 +232,8 @@ void EventsListSerialization::SerializeEventsTo(const EventsList& list,
const gd::BaseEvent& event = list.GetEvent(j); const gd::BaseEvent& event = list.GetEvent(j);
SerializerElement& eventElem = events.AddChild("event"); SerializerElement& eventElem = events.AddChild("event");
if (event.IsDisabled()) eventElem.SetAttribute("disabled", event.IsDisabled());
eventElem.SetAttribute("disabled", event.IsDisabled()); eventElem.SetAttribute("folded", event.IsFolded());
if (event.IsFolded()) eventElem.SetAttribute("folded", event.IsFolded());
eventElem.AddChild("type").SetValue(event.GetType()); eventElem.AddChild("type").SetValue(event.GetType());
event.SerializeTo(eventElem); event.SerializeTo(eventElem);
@@ -269,9 +267,6 @@ void gd::EventsListSerialization::UnserializeInstructionsFrom(
instrElement.GetChild("type", 0, "Type") instrElement.GetChild("type", 0, "Type")
.GetBoolAttribute("inverted", false, "Contraire")); .GetBoolAttribute("inverted", false, "Contraire"));
instruction.SetAwaited(
instrElement.GetChild("type", 0, "Type").GetBoolAttribute("await"));
// Read parameters // Read parameters
vector<gd::Expression> parameters; vector<gd::Expression> parameters;
@@ -345,12 +340,9 @@ void gd::EventsListSerialization::SerializeInstructionsTo(
instructions.ConsiderAsArrayOf("instruction"); instructions.ConsiderAsArrayOf("instruction");
for (std::size_t k = 0; k < list.size(); k++) { for (std::size_t k = 0; k < list.size(); k++) {
SerializerElement& instruction = instructions.AddChild("instruction"); SerializerElement& instruction = instructions.AddChild("instruction");
instruction.AddChild("type").SetAttribute("value", list[k].GetType()); instruction.AddChild("type")
.SetAttribute("value", list[k].GetType())
if (list[k].IsInverted()) .SetAttribute("inverted", list[k].IsInverted());
instruction.GetChild("type").SetAttribute("inverted", true);
if (list[k].IsAwaited())
instruction.GetChild("type").SetAttribute("await", true);
// Parameters // Parameters
SerializerElement& parameters = instruction.AddChild("parameters"); SerializerElement& parameters = instruction.AddChild("parameters");
@@ -360,10 +352,9 @@ void gd::EventsListSerialization::SerializeInstructionsTo(
.SetValue(list[k].GetParameter(l).GetPlainString()); .SetValue(list[k].GetParameter(l).GetPlainString());
// Sub instructions // Sub instructions
if (!list[k].GetSubInstructions().empty()) { SerializerElement& subInstructions =
SerializeInstructionsTo(list[k].GetSubInstructions(), instruction.AddChild("subInstructions");
instruction.AddChild("subInstructions")); SerializeInstructionsTo(list[k].GetSubInstructions(), subInstructions);
}
} }
} }

View File

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

View File

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

View File

@@ -11,16 +11,26 @@ namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension( void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension.SetExtensionInformation(
"BuiltinAdvanced",
_("Advanced control features"),
_("Advanced control features to be used in events."),
"Florian Rival",
"Open source (MIT License)");
#if defined(GD_IDE_ONLY)
extension extension
.SetExtensionInformation( .AddCondition("Toujours",
"BuiltinAdvanced", _("Always"),
_("Event functions"), _("This condition always returns true (or always false, if "
_("Advanced control features for functions made with events."), "the condition is inverted)."),
"Florian Rival", _("Always"),
"Open source (MIT License)") _("Other"),
.SetCategory("Advanced"); "res/conditions/toujours24.png",
extension.AddInstructionOrExpressionGroupMetadata(_("Event functions")) "res/conditions/toujours.png")
.SetIcon("res/function32.png"); .SetHelpPath("/all-features/advanced-conditions")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
@@ -29,12 +39,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Set the return value of the events function to the specified " _("Set the return value of the events function to the specified "
"number (to be used with \"Expression\" functions)."), "number (to be used with \"Expression\" functions)."),
_("Set return value to number _PARAM0_"), _("Set return value to number _PARAM0_"),
"", _("Functions"),
"res/function32.png", "res/function24.png",
"res/function32.png") "res/function16.png")
.SetHelpPath("/events/functions/return") .SetHelpPath("/events/functions/return")
.AddParameter("expression", _("The number to be returned")) .AddParameter("expression", "The number to be returned")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -44,12 +53,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Set the return value of the events function to the specified text " _("Set the return value of the events function to the specified text "
"(to be used with \"String Expression\" functions)."), "(to be used with \"String Expression\" functions)."),
_("Set return value to text _PARAM0_"), _("Set return value to text _PARAM0_"),
"", _("Functions"),
"res/function32.png", "res/function24.png",
"res/function32.png") "res/function16.png")
.SetHelpPath("/events/functions/return") .SetHelpPath("/events/functions/return")
.AddParameter("string", _("The text to be returned")) .AddParameter("string", "The text to be returned")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -58,42 +66,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
_("Set the return value of the Condition events function to " _("Set the return value of the Condition events function to "
"either true (condition will pass) or false."), "either true (condition will pass) or false."),
_("Set return value of the condition to _PARAM0_"), _("Set return value of the condition to _PARAM0_"),
"", _("Functions"),
"res/function32.png", "res/function24.png",
"res/function32.png") "res/function16.png")
.SetHelpPath("/events/functions/return") .SetHelpPath("/events/functions/return")
.AddParameter("trueorfalse", _("Should the condition be true or false?")) .AddParameter("trueorfalse", "Should the condition be true or false?")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
.AddAction("CopyArgumentToVariable",
_("Copy function parameter to variable"),
_("Copy a function parameter (also called \"argument\") to a variable. "
"The parameter type must be a variable."),
_("Copy the parameter _PARAM0_ into the variable _PARAM1_"),
"",
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
extension
.AddAction("CopyVariableToArgument",
_("Copy variable to function parameter"),
_("Copy a variable to function parameter (also called \"argument\"). "
"The parameter type must be a variable."),
_("Copy the variable _PARAM1_ into the parameter _PARAM0_"),
"",
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -104,62 +81,30 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"a string, an empty string is considered as \"false\". " "a string, an empty string is considered as \"false\". "
"If it's a number, 0 is considered as \"false\"."), "If it's a number, 0 is considered as \"false\"."),
_("Parameter _PARAM0_ is true"), _("Parameter _PARAM0_ is true"),
"", _("Functions"),
"res/function32.png", "res/function24.png",
"res/function32.png") "res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean") .AddParameter("string", "Parameter name")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddExpression( .AddExpression(
"GetArgumentAsNumber", "GetArgumentAsNumber",
_("Get function parameter value"), _("Get function parameter value"),
_("Get function parameter (also called \"argument\") value. You don't need this most of the time as you can simply write the parameter name in an expression."), _("Get function parameter (also called \"argument\") value"),
"", _("Functions"),
"res/function16.png") "res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean") .AddParameter("string", "Parameter name");
.SetRelevantForFunctionEventsOnly()
.SetHidden();
extension extension
.AddStrExpression( .AddStrExpression(
"GetArgumentAsString", "GetArgumentAsString",
_("Get function parameter text"), _("Get function parameter text"),
_("Get function parameter (also called \"argument\") text. You don't need this most of the time as you can simply write the parameter name in an expression."), _("Get function parameter (also called \"argument\") text "),
"", _("Functions"),
"res/function16.png") "res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean") .AddParameter("string", "Parameter name");
.SetRelevantForFunctionEventsOnly() #endif
.SetHidden();
extension
.AddCondition(
"CompareArgumentAsNumber",
_("Compare function parameter value"),
_("Compare function parameter (also called \"argument\") value."),
_("Parameter _PARAM0_"),
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition(
"CompareArgumentAsString",
_("Compare function parameter text"),
_("Compare function parameter (also called \"argument\") text."),
_("Parameter _PARAM0_"),
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly();
} }
} // namespace gd } // namespace gd

View File

@@ -15,6 +15,8 @@ namespace gd {
* so that it provides standards events, objects or instructions of an * so that it provides standards events, objects or instructions of an
* extension. * extension.
* *
* TOOD: Usage example.
*
* \ingroup BuiltinExtensions * \ingroup BuiltinExtensions
*/ */
class GD_CORE_API BuiltinExtensionsImplementer { class GD_CORE_API BuiltinExtensionsImplementer {
@@ -30,6 +32,7 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsExternalLayoutsExtension( static void ImplementsExternalLayoutsExtension(
gd::PlatformExtension& extension); gd::PlatformExtension& extension);
static void ImplementsFileExtension(gd::PlatformExtension& extension); static void ImplementsFileExtension(gd::PlatformExtension& extension);
static void ImplementsJoystickExtension(gd::PlatformExtension& extension);
static void ImplementsKeyboardExtension(gd::PlatformExtension& extension); static void ImplementsKeyboardExtension(gd::PlatformExtension& extension);
static void ImplementsMathematicalToolsExtension( static void ImplementsMathematicalToolsExtension(
gd::PlatformExtension& extension); gd::PlatformExtension& extension);
@@ -42,14 +45,6 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsTimeExtension(gd::PlatformExtension& extension); static void ImplementsTimeExtension(gd::PlatformExtension& extension);
static void ImplementsVariablesExtension(gd::PlatformExtension& extension); static void ImplementsVariablesExtension(gd::PlatformExtension& extension);
static void ImplementsWindowExtension(gd::PlatformExtension& extension); static void ImplementsWindowExtension(gd::PlatformExtension& extension);
static void ImplementsAsyncExtension(gd::PlatformExtension& extension);
static void ImplementsResizableExtension(gd::PlatformExtension& extension);
static void ImplementsScalableExtension(gd::PlatformExtension& extension);
static void ImplementsFlippableExtension(gd::PlatformExtension& extension);
static void ImplementsAnimatableExtension(gd::PlatformExtension& extension);
static void ImplementsEffectExtension(gd::PlatformExtension& extension);
static void ImplementsOpacityExtension(gd::PlatformExtension& extension);
static void ImplementsTextContainerExtension(gd::PlatformExtension& extension);
}; };
} // namespace gd } // namespace gd

View File

@@ -1,47 +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/Events/Builtin/AsyncEvent.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
gd::PlatformExtension &extension) {
extension
.SetExtensionInformation(
"BuiltinAsync",
_("Asynchronous functions"),
_("Functions that defer the execution of the events after it."),
"Arthur Pacaud (arthuro555)",
"Open source (MIT License)")
.SetCategory("Advanced");
extension.AddInstructionOrExpressionGroupMetadata(_("Asynchronous functions"))
.SetIcon("res/function32.png");
extension.AddEvent("Async",
_("Async event"),
_("Internal event for asynchronous actions"),
"",
"res/eventaddicon.png",
std::make_shared<gd::AsyncEvent>());
extension
.AddAction(
"ResolveAsyncEventsFunction",
_("End asynchronous function"),
_("Mark an asynchronous function as finished. This will allow the "
"actions and subevents following it to be run."),
"Mark asynchronous function as ended",
"",
"res/actions/quit24.png",
"res/actions/quit.png")
.AddCodeOnlyParameter("eventsFunctionContext", "")
.SetRelevantForAsynchronousFunctionEventsOnly();
}
} // namespace gd

View File

@@ -14,18 +14,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinAudio", "BuiltinAudio",
_("Sounds and music"), _("Audio"),
_("GDevelop provides several conditions and actions to play audio " _("GDevelop provides several conditions and actions to play audio "
"files. They can be either long music or short sound effects."), "files. They can be either long musics or short sound effects."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/audio") .SetExtensionHelpPath("/all-features/audio");
.SetCategory("Audio");
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds and music"))
.SetIcon("res/actions/music24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds on channels"))
.SetIcon("res/actions/son24.png");
#if defined(GD_IDE_ONLY)
extension extension
.AddAction("PlaySoundCanal", .AddAction("PlaySoundCanal",
_("Play a sound on a channel"), _("Play a sound on a channel"),
@@ -33,7 +29,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"you'll be able to manipulate it."), "you'll be able to manipulate it."),
_("Play the sound _PARAM1_ on the channel _PARAM2_, vol.: " _("Play the sound _PARAM1_ on the channel _PARAM2_, vol.: "
"_PARAM4_, loop: _PARAM3_"), "_PARAM4_, loop: _PARAM3_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -54,7 +50,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Stop the sound of a channel"), _("Stop the sound of a channel"),
_("Stop the sound on the specified channel."), _("Stop the sound on the specified channel."),
_("Stop the sound of channel _PARAM1_"), _("Stop the sound of channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -66,7 +62,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Pause the sound of a channel"), _("Pause the sound of a channel"),
_("Pause the sound played on the specified channel."), _("Pause the sound played on the specified channel."),
_("Pause the sound of channel _PARAM1_"), _("Pause the sound of channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -75,10 +71,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
extension extension
.AddAction("RePlaySoundCanal", .AddAction("RePlaySoundCanal",
_("Resume playing a sound on a channel"), _("Play the sound of a channel"),
_("Resume playing a sound on a channel that was paused."), _("Play the sound of the channel."),
_("Resume the sound of channel _PARAM1_"), _("Play the sound of channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -92,7 +88,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"able to interact with it later."), "able to interact with it later."),
_("Play the music _PARAM1_ on channel _PARAM2_, vol.: " _("Play the music _PARAM1_ on channel _PARAM2_, vol.: "
"_PARAM4_, loop: _PARAM3_"), "_PARAM4_, loop: _PARAM3_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -113,7 +109,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Stop the music on a channel"), _("Stop the music on a channel"),
_("Stop the music on the specified channel"), _("Stop the music on the specified channel"),
_("Stop the music of channel _PARAM1_"), _("Stop the music of channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -125,7 +121,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Pause the music of a channel"), _("Pause the music of a channel"),
_("Pause the music on the specified channel."), _("Pause the music on the specified channel."),
_("Pause the music of channel _PARAM1_"), _("Pause the music of channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -134,10 +130,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
extension extension
.AddAction("RePlayMusicCanal", .AddAction("RePlayMusicCanal",
_("Resume playing a music on a channel"), _("Play the music of a channel"),
_("Resume playing a music on a channel that was paused."), _("Play the music of the channel."),
_("Resume the music of channel _PARAM1_"), _("Play the music of channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -148,83 +144,69 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddAction("ModVolumeSoundCanal", .AddAction("ModVolumeSoundCanal",
_("Volume of the sound on a channel"), _("Volume of the sound on a channel"),
_("This action modifies the volume of the sound on the " _("This action modifies the volume of the sound on the "
"specified channel."), "specified channel. The volume is between 0 and 100."),
_("the volume of the sound on channel _PARAM1_"), _("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/actions/sonVolume24.png", "res/actions/sonVolume24.png",
"res/actions/sonVolume.png") "res/actions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ModVolumeMusicCanal", .AddAction("ModVolumeMusicCanal",
_("Volume of the music on a channel"), _("Volume of the music on a channel"),
_("This action modifies the volume of the music on the " _("This action modifies the volume of the music on the "
"specified channel."), "specified channel. The volume is between 0 and 100."),
_("the volume of the music on channel _PARAM1_"), _("the volume of the music on channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/actions/musicVolume24.png", "res/actions/musicVolume24.png",
"res/actions/musicVolume.png") "res/actions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ModGlobalVolume", .AddAction("ModGlobalVolume",
_("Game global volume"), _("Game global volume"),
_("This action modifies the global volume of the game."), _("This action modifies the global volume of the game. The "
"volume is between 0 and 100."),
_("the global sound level"), _("the global sound level"),
"", _("Audio"),
"res/actions/volume24.png", "res/actions/volume24.png",
"res/actions/volume.png") "res/actions/volume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsSimple(); .MarkAsSimple();
extension extension
.AddAction("ModPitchSoundChannel", .AddAction("ModPitchSoundChannel",
_("Pitch of the sound of a channel"), _("Pitch of the sound of a channel"),
_("This action modifies the pitch (speed) of the sound on a " _("This action modifies the pitch (speed) of the sound on a "
"channel."), "channel.\n1 is the default pitch."),
_("the pitch of the sound on channel _PARAM1_"), _("the pitch of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ModPitchMusicChannel", .AddAction("ModPitchMusicChannel",
_("Pitch of the music on a channel"), _("Pitch of the music on a channel"),
_("This action modifies the pitch of the music on the " _("This action modifies the pitch of the music on the "
"specified channel."), "specified channel. 1 is the default pitch"),
_("the pitch of the music on channel _PARAM1_"), _("the pitch of the music on channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -233,15 +215,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("This action modifies the playing offset of the sound on a " _("This action modifies the playing offset of the sound on a "
"channel"), "channel"),
_("the playing offset of the sound on channel _PARAM1_"), _("the playing offset of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -250,15 +229,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("This action modifies the playing offset of the music on " _("This action modifies the playing offset of the music on "
"the specified channel"), "the specified channel"),
_("the playing offset of the music on channel _PARAM1_"), _("the playing offset of the music on channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -266,7 +242,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Play a sound"), _("Play a sound"),
_("Play a sound."), _("Play a sound."),
_("Play the sound _PARAM1_, vol.: _PARAM3_, loop: _PARAM2_"), _("Play the sound _PARAM1_, vol.: _PARAM3_, loop: _PARAM2_"),
"", _("Audio"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -286,7 +262,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Play a music file"), _("Play a music file"),
_("Play a music file."), _("Play a music file."),
_("Play the music _PARAM1_, vol.: _PARAM3_, loop: _PARAM2_"), _("Play the music _PARAM1_, vol.: _PARAM3_, loop: _PARAM2_"),
"", _("Audio"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -306,7 +282,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Preload a music file"), _("Preload a music file"),
_("Preload a music file in memory."), _("Preload a music file in memory."),
_("Preload the music file _PARAM1_"), _("Preload the music file _PARAM1_"),
_("Loading"), _("Audio/Loading"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -318,7 +294,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Preload a sound file"), _("Preload a sound file"),
_("Preload a sound file in memory."), _("Preload a sound file in memory."),
_("Preload the sound file _PARAM1_"), _("Preload the sound file _PARAM1_"),
_("Loading"), _("Audio/Loading"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -326,80 +302,55 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.MarkAsComplex(); .MarkAsComplex();
extension extension
.AddAction( .AddAction("UnloadMusic",
"UnloadMusic", _("Unload a music file"),
_("Unload a music file"), _(
_("Unload a music file from memory. " "Unload a music file from memory. "
"Unloading a music file will cause any music playing it to stop."), "Unloading a music file will cause any music playing it to stop."
_("Unload the music file _PARAM1_"), ),
_("Loading"), _("Unload the music file _PARAM1_"),
"res/actions/music24.png", _("Audio/Loading"),
"res/actions/music.png") "res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("musicfile", _("Audio file (or audio resource name)")) .AddParameter("musicfile", _("Audio file (or audio resource name)"))
.MarkAsComplex(); .MarkAsComplex();
extension extension
.AddAction( .AddAction("UnloadSound",
"UnloadSound", _("Unload a sound file"),
_("Unload a sound file"), _(
_("Unload a sound file from memory. " "Unload a sound file from memory. "
"Unloading a sound file will cause any sounds playing it to stop."), "Unloading a sound file will cause any sounds playing it to stop."
_("Unload the sound file _PARAM1_"), ),
_("Loading"), _("Unload the sound file _PARAM1_"),
"res/actions/son24.png", _("Audio/Loading"),
"res/actions/son.png") "res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("soundfile", _("Sound file (or sound resource name)")) .AddParameter("soundfile", _("Sound file (or sound resource name)"))
.MarkAsComplex(); .MarkAsComplex();
extension extension
.AddAction( .AddAction("UnloadAllAudio",
"UnloadAllAudio", _("Unload all audio"),
_("Unload all audio"), _(
_("Unload all the audio in memory. " "Unload all the audio in memory. "
"This will cause every sound and music of the game to stop."), "This will cause every sound and music of the game to stop."
_("Unload all audio files"), ),
_("Loading"), _("Unload all audio files"),
"res/actions/music24.png", _("Audio/Loading"),
"res/actions/music.png") "res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.MarkAsComplex(); .MarkAsComplex();
extension
.AddAction(
"FadeSoundVolume",
_("Fade the volume of a sound played on a channel."),
_("Fade the volume of a sound played on a channel to the specified volume within the specified duration."),
_("Fade the sound on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Sounds on channels"),
"res/actions/son24.png",
"res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension
.AddAction(
"FadeMusicVolume",
_("Fade the volume of a music played on a channel."),
_("Fade the volume of a music played on a channel to the specified volume within the specified duration."),
_("Fade the music on channel _PARAM1_ to volume _PARAM2_ within _PARAM3_ seconds"),
_("Music on channels"),
"res/actions/music24.png",
"res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier"))
.AddParameter("expression", _("Final volume (0-100)"))
.AddParameter("expression", _("Fading time in seconds"))
.MarkAsAdvanced();
extension extension
.AddCondition("MusicPlaying", .AddCondition("MusicPlaying",
_("A music file is being played"), _("A music file is being played"),
_("Test if the music on a channel is being played"), _("Test if the music on a channel is being played"),
_("Music on channel _PARAM1_ is being played"), _("Music on channel _PARAM1_ is being played"),
_("Music on channels"), _("Audio/Music on channels"),
"res/conditions/musicplaying24.png", "res/conditions/musicplaying24.png",
"res/conditions/musicplaying.png") "res/conditions/musicplaying.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -411,7 +362,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("A music file is paused"), _("A music file is paused"),
_("Test if the music on the specified channel is paused."), _("Test if the music on the specified channel is paused."),
_("Music on channel _PARAM1_ is paused"), _("Music on channel _PARAM1_ is paused"),
_("Music on channels"), _("Audio/Music on channels"),
"res/conditions/musicpaused24.png", "res/conditions/musicpaused24.png",
"res/conditions/musicpaused.png") "res/conditions/musicpaused.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -423,7 +374,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("A music file is stopped"), _("A music file is stopped"),
_("Test if the music on the specified channel is stopped."), _("Test if the music on the specified channel is stopped."),
_("Music on channel _PARAM1_ is stopped"), _("Music on channel _PARAM1_ is stopped"),
_("Music on channels"), _("Audio/Music on channels"),
"res/conditions/musicstopped24.png", "res/conditions/musicstopped24.png",
"res/conditions/musicstopped.png") "res/conditions/musicstopped.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -435,7 +386,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("A sound is being played"), _("A sound is being played"),
_("Test if the sound on a channel is being played."), _("Test if the sound on a channel is being played."),
_("Sound on channel _PARAM1_ is being played"), _("Sound on channel _PARAM1_ is being played"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/conditions/sonplaying24.png", "res/conditions/sonplaying24.png",
"res/conditions/sonplaying.png") "res/conditions/sonplaying.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -447,7 +398,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("A sound is paused"), _("A sound is paused"),
_("Test if the sound on the specified channel is paused."), _("Test if the sound on the specified channel is paused."),
_("Sound on channel _PARAM1_ is paused"), _("Sound on channel _PARAM1_ is paused"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/conditions/sonpaused24.png", "res/conditions/sonpaused24.png",
"res/conditions/sonpaused.png") "res/conditions/sonpaused.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -459,7 +410,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("A sound is stopped"), _("A sound is stopped"),
_("Test if the sound on the specified channel is stopped."), _("Test if the sound on the specified channel is stopped."),
_("Sound on channel _PARAM1_ is stopped"), _("Sound on channel _PARAM1_ is stopped"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/conditions/sonstopped24.png", "res/conditions/sonstopped24.png",
"res/conditions/sonstopped.png") "res/conditions/sonstopped.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -470,17 +421,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddCondition( .AddCondition(
"SoundCanalVolume", "SoundCanalVolume",
_("Volume of the sound on a channel"), _("Volume of the sound on a channel"),
_("Test the volume of the sound on the specified channel."), _("Test the volume of the sound on the specified channel. The volume "
"is between 0 and 100."),
_("the volume of the sound on channel _PARAM1_"), _("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/conditions/sonVolume24.png", "res/conditions/sonVolume24.png",
"res/conditions/sonVolume.png") "res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -490,15 +439,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Test the volume of the music on a specified channel. The volume " _("Test the volume of the music on a specified channel. The volume "
"is between 0 and 100."), "is between 0 and 100."),
_("the volume of the music on channel _PARAM1_"), _("the volume of the music on channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/conditions/musicVolume24.png", "res/conditions/musicVolume24.png",
"res/conditions/musicVolume.png") "res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -507,14 +453,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Global volume"), _("Global volume"),
_("Test the global sound level. The volume is between 0 and 100."), _("Test the global sound level. The volume is between 0 and 100."),
_("the global game volume"), _("the global game volume"),
"", _("Audio"),
"res/conditions/volume24.png", "res/conditions/volume24.png",
"res/conditions/volume.png") "res/conditions/volume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number");
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")));
extension extension
.AddCondition( .AddCondition(
@@ -523,32 +466,27 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Test the pitch of the sound on the specified channel. 1 is the " _("Test the pitch of the sound on the specified channel. 1 is the "
"default pitch."), "default pitch."),
_("the pitch of the sound on channel _PARAM1_"), _("the pitch of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/conditions/sonVolume24.png", "res/conditions/sonVolume24.png",
"res/conditions/sonVolume.png") "res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddCondition( .AddCondition(
"MusicChannelPitch", "MusicChannelPitch",
_("Pitch of the music on a channel"), _("Pitch of the music on a channel"),
_("Test the pitch (speed) of the music on a specified channel."), _("Test the pitch (speed) of the music on a specified channel. 1 is "
"the default pitch."),
_("the pitch of the music on channel _PARAM1_"), _("the pitch of the music on channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/conditions/musicVolume24.png", "res/conditions/musicVolume24.png",
"res/conditions/musicVolume.png") "res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -557,15 +495,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Playing offset of the sound on a channel"), _("Playing offset of the sound on a channel"),
_("Test the playing offset of the sound on the specified channel."), _("Test the playing offset of the sound on the specified channel."),
_("the playing offset of the sound on channel _PARAM1_"), _("the playing offset of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Audio/Sounds on channels"),
"res/conditions/sonVolume24.png", "res/conditions/sonVolume24.png",
"res/conditions/sonVolume.png") "res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -574,15 +509,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Playing offset of the music on a channel"), _("Playing offset of the music on a channel"),
_("Test the playing offset of the music on the specified channel."), _("Test the playing offset of the music on the specified channel."),
_("the playing offset of the music on channel _PARAM1_"), _("the playing offset of the music on channel _PARAM1_"),
_("Music on channels"), _("Audio/Music on channels"),
"res/conditions/musicVolume24.png", "res/conditions/musicVolume24.png",
"res/conditions/musicVolume.png") "res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -646,6 +578,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
_("Sound level"), _("Sound level"),
"res/conditions/volume.png") "res/conditions/volume.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
#endif
} }
} // namespace gd } // namespace gd

File diff suppressed because it is too large Load Diff

View File

@@ -15,83 +15,59 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinCamera", "BuiltinCamera",
_("Layers and cameras"), _("Cameras and layers features"),
"Each scene can be composed of multiple layers. These conditions " "Each scene can be composed of multiple layers. These conditions "
"and actions allow to manipulate them during the game. In " "and actions allow to manipulate them during the game. In "
"particular, you can move the camera of a layer to center it on an " "particular, you can move the camera of a layer to center it on an "
"object or a position.", "object or a position.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetCategory("Camera")
.SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras"); .SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras");
extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras"))
.SetIcon("res/conditions/camera24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect24.png");
#if defined(GD_IDE_ONLY)
extension extension
.AddExpressionAndConditionAndAction( .AddExpressionAndConditionAndAction(
"number", "number",
"CameraCenterX", "CameraX",
_("Camera center X position"), _("Camera center X position"),
_("the X position of the center of a camera"), _("the X position of the center of a camera"),
_("the X position of camera _PARAM4_ (layer: _PARAM3_)"), _("the X position of camera _PARAM4_ (layer: _PARAM3_)"),
"", _("Layers and cameras"),
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
.MarkAsAdvanced(); .MarkAsAdvanced();
// Compatibility with GD <= 5.0.135
extension.AddDuplicatedCondition("CameraX", "CameraCenterX")
.SetHidden(); // Deprecated
extension.AddDuplicatedExpression("CameraX", "CameraCenterX")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("SetCameraX", "SetCameraCenterX")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("CameraX", "SetCameraX") extension.AddDuplicatedAction("CameraX", "SetCameraX")
.SetHidden(); // Deprecated .SetHidden(); // Deprecated
extension.AddDuplicatedExpression("VueX", "CameraX") extension.AddDuplicatedExpression("VueX", "CameraX")
.SetHidden(); // Deprecated .SetHidden(); // Deprecated
// end of compatibility code
extension extension
.AddExpressionAndConditionAndAction( .AddExpressionAndConditionAndAction(
"number", "number",
"CameraCenterY", "CameraY",
_("Camera center Y position"), _("Camera center Y position"),
_("the Y position of the center of a camera"), _("the Y position of the center of a camera"),
_("the Y position of camera _PARAM4_ (layer: _PARAM3_)"), _("the Y position of camera _PARAM4_ (layer: _PARAM3_)"),
"", _("Layers and cameras"),
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
.MarkAsAdvanced(); .MarkAsAdvanced();
// Compatibility with GD <= 5.0.135
extension.AddDuplicatedCondition("CameraY", "CameraCenterY")
.SetHidden(); // Deprecated
extension.AddDuplicatedExpression("CameraY", "CameraCenterY")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("SetCameraY", "SetCameraCenterY")
.SetHidden(); // Deprecated
extension.AddDuplicatedAction("CameraY", "SetCameraY") extension.AddDuplicatedAction("CameraY", "SetCameraY")
.SetHidden(); // Deprecated .SetHidden(); // Deprecated
extension.AddDuplicatedExpression("VueY", "CameraY") extension.AddDuplicatedExpression("VueY", "CameraY")
.SetHidden(); // Deprecated .SetHidden(); // Deprecated
// end of compatibility code
extension extension
.AddExpressionAndCondition( .AddExpressionAndCondition(
@@ -100,13 +76,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Width of a camera"), _("Width of a camera"),
_("the width of a camera of a layer"), _("the width of a camera of a layer"),
_("the width of camera _PARAM2_ of layer _PARAM1_"), _("the width of camera _PARAM2_ of layer _PARAM1_"),
"", _("Layers and cameras"),
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -116,81 +92,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Height of a camera"), _("Height of a camera"),
_("the height of a camera of a layer"), _("the height of a camera of a layer"),
_("the height of camera _PARAM2_ of layer _PARAM1_"), _("the height of camera _PARAM2_ of layer _PARAM1_"),
"", _("Layers and cameras"),
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderLeft",
_("Camera left border position"),
_("the position of the left border of a camera"),
_("the position of the left border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderRight",
_("Camera right border position"),
_("the position of the right border of a camera"),
_("the position of the right border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderTop",
_("Camera top border position"),
_("the position of the top border of a camera"),
_("the position of the top border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddExpressionAndCondition(
"number",
"CameraBorderBottom",
_("Camera bottom border position"),
_("the position of the bottom border of a camera"),
_("the position of the bottom border of camera _PARAM2_ of layer "
"_PARAM1_"),
"",
"res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -198,13 +106,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"number", "number",
"CameraAngle", "CameraAngle",
_("Angle of a camera of a layer"), _("Angle of a camera of a layer"),
_("the angle of rotation of a camera (in degrees)"), _("the angle of rotation of a camera"),
_("the angle of camera (layer: _PARAM3_, camera: _PARAM4_)"), _("the angle of camera (layer: _PARAM3_, camera: _PARAM4_)"),
"", _("Layers and cameras"),
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
@@ -220,11 +128,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Add a camera to a layer"), _("Add a camera to a layer"),
_("This action adds a camera to a layer"), _("This action adds a camera to a layer"),
_("Add a camera to layer _PARAM1_"), _("Add a camera to layer _PARAM1_"),
"", _("Layers and cameras"),
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Width"), "", true) .AddParameter("expression", _("Width"), "", true)
.AddParameter("expression", _("Height"), "", true) .AddParameter("expression", _("Height"), "", true)
@@ -255,11 +163,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Delete a camera of a layer"), _("Delete a camera of a layer"),
_("Remove the specified camera from a layer"), _("Remove the specified camera from a layer"),
_("Delete camera _PARAM2_ from layer _PARAM1_"), _("Delete camera _PARAM2_ from layer _PARAM1_"),
"", _("Layers and cameras"),
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number")) .AddParameter("expression", _("Camera number"))
.MarkAsComplex(); .MarkAsComplex();
@@ -271,11 +179,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"layer. The zoom will be reset."), "layer. The zoom will be reset."),
_("Change the size of camera _PARAM2_ of _PARAM1_ to " _("Change the size of camera _PARAM2_ of _PARAM1_ to "
"_PARAM3_*_PARAM4_"), "_PARAM3_*_PARAM4_"),
"", _("Layers and cameras"),
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number")) .AddParameter("expression", _("Camera number"))
.AddParameter("expression", _("Width")) .AddParameter("expression", _("Width"))
@@ -289,11 +197,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"specified layer."), "specified layer."),
_("Set the render zone of camera _PARAM2_ from layer _PARAM1_ " _("Set the render zone of camera _PARAM2_ from layer _PARAM1_ "
"to _PARAM3_;_PARAM4_ _PARAM5_;_PARAM6_"), "to _PARAM3_;_PARAM4_ _PARAM5_;_PARAM6_"),
"", _("Layers and cameras"),
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number")) .AddParameter("expression", _("Camera number"))
.AddParameter( .AddParameter(
@@ -312,17 +220,17 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension extension
.AddAction("ZoomCamera", .AddAction("ZoomCamera",
_("Camera zoom"), _("Change camera zoom"),
_("Change camera zoom."), _("Change camera zoom."),
_("Change camera zoom to _PARAM1_ (layer: _PARAM2_, camera: " _("Change camera zoom to _PARAM1_ (layer: _PARAM2_, camera: "
"_PARAM3_)"), "_PARAM3_)"),
"", _("Layers and cameras"),
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", .AddParameter("expression",
_("Value (1:Initial zoom, 2:Zoom x2, 0.5:Unzoom x2...)")) _("Value (1:Initial zoom, 2:Zoom x2, 0.5:Unzoom x2...)"))
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
@@ -335,10 +243,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"specified limits."), "specified limits."),
_("Center the camera on _PARAM1_ (limit : from _PARAM2_;_PARAM3_ to " _("Center the camera on _PARAM1_ (limit : from _PARAM2_;_PARAM3_ to "
"_PARAM4_;_PARAM5_) (layer: _PARAM7_, camera: _PARAM8_)"), "_PARAM4_;_PARAM5_) (layer: _PARAM7_, camera: _PARAM8_)"),
"", _("Layers and cameras"),
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.SetHidden()
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("objectPtr", _("Object")) .AddParameter("objectPtr", _("Object"))
.AddParameter("expression", .AddParameter("expression",
@@ -354,41 +261,21 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
true) true)
.SetDefaultValue("yes") .SetDefaultValue("yes")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ClampCamera", .AddAction(
_("Enforce camera boundaries"), "CentreCamera",
_("Enforce camera boundaries by moving the camera back inside " _("Center the camera on an object"),
"specified boundaries."), _("Center the camera on the specified object."),
_("Enforce camera boundaries (left: _PARAM1_, top: _PARAM2_ " _("Center camera on _PARAM1_ (layer: _PARAM3_, camera: _PARAM4_)"),
"right: _PARAM3_, bottom: _PARAM4_, layer: _PARAM5_)"), _("Layers and cameras"),
"", "res/actions/camera24.png",
"res/actions/camera24.png", "res/actions/camera.png")
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Left bound X Position"))
.AddParameter("expression", _("Top bound Y Position"))
.AddParameter("expression", _("Right bound X Position"))
.AddParameter("expression", _("Bottom bound Y Position"))
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
extension
.AddAction("CentreCamera",
_("Center the camera on an object"),
_("Center the camera on the specified object."),
_("Center camera on _PARAM1_ (layer: _PARAM3_)"),
_("Layers and cameras"),
"res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("objectPtr", _("Object")) .AddParameter("objectPtr", _("Object"))
.AddParameter("yesorno", .AddParameter("yesorno",
@@ -396,7 +283,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
true) true)
.SetDefaultValue("yes") .SetDefaultValue("yes")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
@@ -407,11 +294,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Show a layer"), _("Show a layer"),
_("Show a layer."), _("Show a layer."),
_("Show layer _PARAM1_"), _("Show layer _PARAM1_"),
"", _("Layers and cameras"),
"res/actions/layer24.png", "res/actions/layer24.png",
"res/actions/layer.png") "res/actions/layer.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -420,11 +307,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Hide a layer"), _("Hide a layer"),
_("Hide a layer."), _("Hide a layer."),
_("Hide layer _PARAM1_"), _("Hide layer _PARAM1_"),
"", _("Layers and cameras"),
"res/actions/layer24.png", "res/actions/layer24.png",
"res/actions/layer.png") "res/actions/layer.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -433,69 +320,69 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Visibility of a layer"), _("Visibility of a layer"),
_("Test if a layer is set as visible."), _("Test if a layer is set as visible."),
_("Layer _PARAM1_ is visible"), _("Layer _PARAM1_ is visible"),
"", _("Layers and cameras"),
"res/conditions/layer24.png", "res/conditions/layer24.png",
"res/conditions/layer.png") "res/conditions/layer.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer (base layer if empty)"))
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
"SetLayerEffectParameter", "SetLayerEffectParameter",
_("Effect property (number)"), _("Effect parameter (number)"),
_("Change the value of a property of an effect.") + "\n" + _("Change the value of a parameter of an effect.") + "\n" +
_("You can find the property names (and change the effect " _("You can find the parameter names (and change the effect "
"names) in the effects window."), "names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"), _("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"), _("Layers and cameras/Effects"),
"res/actions/effect24.png", "res/conditions/camera24.png",
"res/actions/effect.png") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("string", _("Effect"))
.AddParameter("layerEffectParameterName", _("Property name")) .AddParameter("string", _("Parameter name"))
.AddParameter("expression", _("New value")) .AddParameter("expression", _("New value"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
"SetLayerEffectStringParameter", "SetLayerEffectStringParameter",
_("Effect property (string)"), _("Effect parameter (string)"),
_("Change the value (string) of a property of an effect.") + "\n" + _("Change the value (string) of a parameter of an effect.") + "\n" +
_("You can find the property names (and change the effect " _("You can find the parameter names (and change the effect "
"names) in the effects window."), "names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"), _("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"), _("Layers and cameras/Effects"),
"res/actions/effect24.png", "res/conditions/camera24.png",
"res/actions/effect.png") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("string", _("Effect"))
.AddParameter("layerEffectParameterName", _("Property name")) .AddParameter("string", _("Parameter name"))
.AddParameter("string", _("New value")) .AddParameter("string", _("New value"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
"SetLayerEffectBooleanParameter", "SetLayerEffectBooleanParameter",
_("Effect property (enable or disable)"), _("Effect parameter (enable or disable)"),
_("Enable or disable a property of an effect.") + "\n" + _("Enable or disable a parameter of an effect.") + "\n" +
_("You can find the property names (and change the effect " _("You can find the parameter names (and change the effect "
"names) in the effects window."), "names) in the effects window."),
_("Enable _PARAM3_ for effect _PARAM2_ of layer _PARAM1_: _PARAM4_"), _("Enable _PARAM3_ for effect _PARAM2_ of layer _PARAM1_: _PARAM4_"),
_("Effects"), _("Layers and cameras/Effects"),
"res/actions/effect24.png", "res/conditions/camera24.png",
"res/actions/effect.png") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("string", _("Effect"))
.AddParameter("layerEffectParameterName", _("Property name")) .AddParameter("string", _("Parameter name"))
.AddParameter("yesorno", _("Enable this property")) .AddParameter("yesorno", _("Enable this parameter"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -503,13 +390,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Layer effect is enabled"), _("Layer effect is enabled"),
_("The effect on a layer is enabled"), _("The effect on a layer is enabled"),
_("Effect _PARAM2_ on layer _PARAM1_ is enabled"), _("Effect _PARAM2_ on layer _PARAM1_ is enabled"),
_(""), _("Layers and cameras/Effects"),
"res/actions/effect24.png", "res/conditions/camera24.png",
"res/actions/effect.png") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("string", _("Effect"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -517,13 +404,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Enable layer effect"), _("Enable layer effect"),
_("Enable an effect on a layer"), _("Enable an effect on a layer"),
_("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"), _("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"),
_("Effects"), _("Layers and cameras/Effects"),
"res/actions/effect24.png", "res/conditions/camera24.png",
"res/actions/effect.png") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("string", _("Effect"))
.AddParameter("yesorno", _("Enable"), "", true) .AddParameter("yesorno", _("Enable"), "", true)
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -533,16 +420,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Layer time scale"), _("Layer time scale"),
_("Compare the time scale applied to the objects of the layer."), _("Compare the time scale applied to the objects of the layer."),
_("the time scale of layer _PARAM1_"), _("the time scale of layer _PARAM1_"),
"", _("Layers and cameras/Time"),
"res/conditions/time24.png", "res/conditions/time24.png",
"res/conditions/time.png") "res/conditions/time.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Time scale (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -550,12 +434,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"ChangeLayerTimeScale", "ChangeLayerTimeScale",
_("Change layer time scale"), _("Change layer time scale"),
_("Change the time scale applied to the objects of the layer."), _("Change the time scale applied to the objects of the layer."),
_("Set the time scale of layer _PARAM1_ to _PARAM2_"), _("Set time scale of layer _PARAM1_ to _PARAM2_"),
"", _("Layers and cameras/Time"),
"res/actions/time24.png", "res/actions/time24.png",
"res/actions/time.png") "res/actions/time.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", .AddParameter("expression",
_("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)")); _("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)"));
@@ -566,28 +450,27 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Compare the default Z order set to objects when they " _("Compare the default Z order set to objects when they "
"are created on a layer."), "are created on a layer."),
_("the default Z order of objects created on _PARAM1_"), _("the default Z order of objects created on _PARAM1_"),
"", _("Layers and cameras"),
"res/conditions/layer24.png", "res/conditions/layer24.png",
"res/conditions/layer.png") "res/conditions/layer.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("SetLayerDefaultZOrder", .AddAction("SetLayerDefaultZOrder",
_("Layer default Z order"), _("Change layer default Z order"),
_("Change the default Z order set to objects when they are " _("Change the default Z order set to objects when they are "
"created on a layer."), "created on a layer."),
_("Set the default Z order of objects created on _PARAM1_ to " _("Set the default Z order of objects created on _PARAM1_ to "
"_PARAM2_"), "_PARAM2_"),
"", _("Layers and cameras"),
"res/actions/layer24.png", "res/actions/layer24.png",
"res/actions/layer.png") "res/actions/layer.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("New default Z order")); .AddParameter("expression", _("New default Z order"));
@@ -598,11 +481,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Set the ambient light color of the lighting layer in format " _("Set the ambient light color of the lighting layer in format "
"\"R;G;B\" string."), "\"R;G;B\" string."),
_("Set the ambient color of the lighting layer _PARAM1_ to _PARAM2_"), _("Set the ambient color of the lighting layer _PARAM1_ to _PARAM2_"),
_(""), _("Layers and cameras/Lighting"),
"res/actions/color24.png", "res/actions/color24.png",
"res/actions/color.png") "res/actions/color.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"Lighting\"") .SetDefaultValue("\"Lighting\"")
.AddParameter("color", _("Color")) .AddParameter("color", _("Color"))
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -612,7 +495,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"CameraViewportLeft", "CameraViewportLeft",
_("X position of the top left side point of a render zone"), _("X position of the top left side point of a render zone"),
_("X position of the top left side point of a render zone"), _("X position of the top left side point of a render zone"),
"", _("Layers and cameras"),
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer"))
@@ -624,7 +507,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"CameraViewportTop", "CameraViewportTop",
_("Y position of the top left side point of a render zone"), _("Y position of the top left side point of a render zone"),
_("Y position of the top left side point of a render zone"), _("Y position of the top left side point of a render zone"),
"", _("Layers and cameras"),
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer"))
@@ -636,7 +519,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"CameraViewportRight", "CameraViewportRight",
_("X position of the bottom right side point of a render zone"), _("X position of the bottom right side point of a render zone"),
_("X position of the bottom right side point of a render zone"), _("X position of the bottom right side point of a render zone"),
"", _("Layers and cameras"),
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer"))
@@ -648,7 +531,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"CameraViewportBottom", "CameraViewportBottom",
_("Y position of the bottom right side point of a render zone"), _("Y position of the bottom right side point of a render zone"),
_("Y position of the bottom right side point of a render zone"), _("Y position of the bottom right side point of a render zone"),
"", _("Layers and cameras"),
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")) .AddParameter("layer", _("Layer"))
@@ -659,7 +542,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddExpression("CameraZoom", .AddExpression("CameraZoom",
_("Zoom of a camera of a layer"), _("Zoom of a camera of a layer"),
_("Zoom of a camera of a layer"), _("Zoom of a camera of a layer"),
"", _("Layers and cameras"),
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer"), "", true)
@@ -669,9 +552,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension extension
.AddExpression("LayerTimeScale", .AddExpression("LayerTimeScale",
_("Layer time scale"), _("Time scale"),
_("Returns the time scale of the specified layer."), _("Time scale"),
"", _("Layers and cameras"),
"res/actions/time.png") "res/actions/time.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")); .AddParameter("layer", _("Layer"));
@@ -680,10 +563,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddExpression("LayerDefaultZOrder", .AddExpression("LayerDefaultZOrder",
_("Default Z Order for a layer"), _("Default Z Order for a layer"),
_("Default Z Order for a layer"), _("Default Z Order for a layer"),
"", _("Layers and cameras"),
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer")); .AddParameter("layer", _("Layer"));
#endif
} }
} // namespace gd } // namespace gd

View File

@@ -1,165 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public
* License.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAnimatableExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation("AnimatableCapability",
_("Animatable capability"),
_("Animate objects."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Animatable capability"))
.SetIcon("res/actions/animation24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
.SetIcon("res/actions/animation24.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"AnimatableBehavior",
_("Animatable capability"),
"Animation",
_("Animate objects."),
"",
"res/actions/animation24.png",
"AnimatableBehavior",
std::make_shared<gd::Behavior>(),
std::make_shared<gd::BehaviorsSharedData>())
.SetHidden();
aut.AddExpressionAndConditionAndAction(
"number",
"Index",
_("Animation (by number)"),
_("the animation played by the object using the animation number (from "
"the animations list)"),
_("the number of the animation"),
_("Animations and images"),
"res/actions/animation24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.UseStandardParameters(
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Animation index")))
.MarkAsSimple();
aut.GetAllExpressions()["Index"].SetGroup("");
aut.AddExpressionAndConditionAndAction(
"string",
"Name",
_("Animation (by name)"),
_("the animation played by the object using the name of the "
"animation"),
_("the animation"),
_("Animations and images"),
"res/actions/animation24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.UseStandardParameters(
"objectAnimationName", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Animation name")))
.MarkAsSimple();
aut.GetAllStrExpressions()["Name"].SetGroup("");
aut.AddScopedAction("PauseAnimation",
_("Pause the animation"),
_("Pause the animation of the object."),
_("Pause the animation of _PARAM0_"),
_("Animations and images"),
"res/actions/animation24.png",
"res/actions/animation.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.MarkAsSimple();
aut.AddScopedAction("PlayAnimation",
_("Resume the animation"),
_("Resume the animation of the object."),
_("Resume the animation of _PARAM0_"),
_("Animations and images"),
"res/actions/animation24.png",
"res/actions/animation.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.MarkAsSimple();
aut.AddExpressionAndConditionAndAction(
"number",
"SpeedScale",
_("Animation speed scale"),
_("the animation speed scale (1 = the default speed, >1 = faster and "
"<1 = slower)"),
_("the animation speed scale"),
_("Animations and images"),
"res/actions/animation24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.UseStandardParameters(
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Speed scale")))
.MarkAsSimple();
aut.GetAllExpressions()["SpeedScale"].SetGroup("");
aut.AddScopedCondition("IsAnimationPaused",
_("Animation paused"),
_("Check if the animation of an object is paused."),
_("The animation of _PARAM0_ is paused"),
_("Animations and images"),
"res/conditions/animation24.png",
"res/conditions/animation.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.MarkAsSimple();
aut.AddScopedCondition("HasAnimationEnded",
_("Animation finished"),
_("Check if the animation being played by the Sprite object "
"is finished."),
_("The animation of _PARAM0_ is finished"),
_("Animations and images"),
"res/conditions/animation24.png",
"res/conditions/animation.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.MarkAsSimple();
aut.AddExpressionAndConditionAndAction(
"number",
"ElapsedTime",
_("Animation elapsed time"),
_("the elapsed time from the beginning of the animation (in seconds)"),
_("the animation elapsed time"),
_("Animations and images"),
"res/actions/animation24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior")
.UseStandardParameters(
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Elapsed time (in seconds)")))
.MarkAsAdvanced();
aut.GetAllExpressions()["ElapsedTime"].SetGroup("");
aut.AddExpression(
"Duration",
_("Animation duration"),
_("Return the current animation duration (in seconds)."),
_("Animations and images"),
"res/actions/animation24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "AnimatableBehavior");
}
} // namespace gd

View File

@@ -1,116 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public
* License.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsEffectExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation("EffectCapability",
_("Effect capability"),
_("Apply visual effects to objects."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect24.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"EffectBehavior",
_("Effect capability"),
"Effect",
_("Apply visual effects to objects."),
"",
"res/actions/effect24.png",
"EffectBehavior",
std::make_shared<gd::Behavior>(),
std::make_shared<gd::BehaviorsSharedData>())
.SetHidden();
aut.AddScopedAction("EnableEffect",
_("Enable an object effect"),
_("Enable an effect on the object"),
_("Enable effect _PARAM2_ on _PARAM0_: _PARAM3_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("yesorno", _("Enable?"))
.MarkAsSimple();
aut.AddScopedAction("SetEffectDoubleParameter",
_("Effect property (number)"),
_("Change the value of a property of an effect.") + "\n" +
_("You can find the property names (and change the effect "
"names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of _PARAM0_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("objectEffectParameterName", _("Property name"))
.AddParameter("expression", _("New value"))
.MarkAsSimple();
aut.AddScopedAction("SetEffectStringParameter",
_("Effect property (string)"),
_("Change the value (string) of a property of an effect.") +
"\n" +
_("You can find the property names (and change the effect "
"names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of _PARAM0_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("objectEffectParameterName", _("Property name"))
.AddParameter("string", _("New value"))
.MarkAsSimple();
aut.AddScopedAction("SetEffectBooleanParameter",
_("Effect property (enable or disable)"),
_("Enable or disable a property of an effect.") + "\n" +
_("You can find the property names (and change the effect "
"names) in the effects window."),
_("Enable _PARAM3_ for effect _PARAM2_ of _PARAM0_: _PARAM4_"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
.AddParameter("objectEffectName", _("Effect name"))
.AddParameter("objectEffectParameterName", _("Property name"))
.AddParameter("yesorno", _("Enable this property"))
.MarkAsSimple();
aut.AddScopedCondition("IsEffectEnabled",
_("Effect is enabled"),
_("Check if the effect on an object is enabled."),
_("Effect _PARAM2_ of _PARAM0_ is enabled"),
_("Effects"),
"res/actions/effect24.png",
"res/actions/effect.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "EffectBehavior")
.AddParameter("objectEffectName", _("Effect name"))
.MarkAsSimple();
}
} // namespace gd

View File

@@ -1,86 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public
* License.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFlippableExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation("FlippableCapability",
_("Flippable capability"),
_("Flip objects."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect24.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"FlippableBehavior",
_("Flippable capability"),
"Flippable",
_("Flip objects."),
"",
"res/actions/flipX24.png",
"FlippableBehavior",
std::make_shared<gd::Behavior>(),
std::make_shared<gd::BehaviorsSharedData>())
.SetHidden();
aut.AddScopedAction("FlipX",
_("Flip the object horizontally"),
_("Flip the object horizontally"),
_("Flip horizontally _PARAM0_: _PARAM2_"),
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "FlippableBehavior")
.AddParameter("yesorno", _("Activate flipping"))
.MarkAsSimple();
aut.AddScopedAction("FlipY",
_("Flip the object vertically"),
_("Flip the object vertically"),
_("Flip vertically _PARAM0_: _PARAM2_"),
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "FlippableBehavior")
.AddParameter("yesorno", _("Activate flipping"))
.MarkAsSimple();
aut.AddScopedCondition("FlippedX",
_("Horizontally flipped"),
_("Check if the object is horizontally flipped"),
_("_PARAM0_ is horizontally flipped"),
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "FlippableBehavior");
aut.AddScopedCondition("FlippedY",
_("Vertically flipped"),
_("Check if the object is vertically flipped"),
_("_PARAM0_ is vertically flipped"),
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "FlippableBehavior");
}
} // namespace gd

View File

@@ -1,62 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public
* License.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsOpacityExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation("OpacityCapability",
_("Opacity capability"),
_("Change the object opacity."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Opacity capability"))
.SetIcon("res/actions/opacity24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Visibility"))
.SetIcon("res/actions/opacity24.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"OpacityBehavior",
_("Opacity capability"),
"Opacity",
_("Change the object opacity."),
"",
"res/actions/opacity24.png",
"OpacityBehavior",
std::make_shared<gd::Behavior>(),
std::make_shared<gd::BehaviorsSharedData>())
.SetHidden();
aut.AddExpressionAndConditionAndAction(
"number",
"Value",
_("Opacity"),
_("the opacity of an object, between 0 (fully transparent) to 255 "
"(opaque)"),
_("the opacity"),
_("Visibility"),
"res/actions/opacity24.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "OpacityBehavior")
.UseStandardParameters(
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity (0-255)")))
.SetFunctionName("setOpacity")
.SetGetter("getOpacity");
aut.GetAllExpressions()["Value"].SetGroup("");
}
} // namespace gd

View File

@@ -1,112 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public
* License.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsResizableExtension(
gd::PlatformExtension &extension) {
extension
.SetExtensionInformation("ResizableCapability",
_("Resizable capability"),
_("Change the object dimensions."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
"res/actions/scale24_black.png");
gd::BehaviorMetadata &aut =
extension
.AddBehavior("ResizableBehavior",
_("Resizable capability"),
"Resizable",
_("Change the object dimensions."),
"",
"res/actions/scale24_black.png",
"ResizableBehavior",
std::make_shared<gd::Behavior>(),
std::make_shared<gd::BehaviorsSharedData>())
.SetHidden();
aut.AddScopedAction("SetWidth",
_("Width"),
_("Change the width of the object."),
_("the width"),
_("Size"),
"res/actions/scaleWidth24_black.png",
"res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Width")))
.MarkAsAdvanced();
aut.AddScopedCondition("Width",
_("Width"),
_("Compare the width of the object."),
_("the width"),
_("Size"),
"res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Width")))
.MarkAsAdvanced();
aut.AddScopedAction("SetHeight",
_("Height"),
_("Change the height of the object."),
_("the height"),
_("Size"),
"res/actions/scaleHeight24_black.png",
"res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Height")))
.MarkAsAdvanced();
aut.AddScopedCondition("Height",
_("Height"),
_("Compare the height of the object."),
_("the height"),
_("Size"),
"res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
.UseStandardRelationalOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Height")))
.MarkAsAdvanced();
aut.AddScopedAction(
"SetSize",
_("Size"),
_("Change the size of an object."),
_("Change the size of _PARAM0_: set to _PARAM2_ x _PARAM3_"),
_("Size"),
"res/actions/scale24_black.png",
"res/actions/scale_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ResizableBehavior")
.AddParameter("expression", _("Width"))
.AddParameter("expression", _("Height"))
.MarkAsAdvanced();
}
} // namespace gd

View File

@@ -1,95 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public
* License.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsScalableExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation("ScalableCapability",
_("Scalable capability"),
_("Change the object scale."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Scalable capability"))
.SetIcon("res/actions/scale24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Size"))
.SetIcon("res/actions/scale24_black.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"ScalableBehavior",
_("Scalable capability"),
"Scale",
_("Change the object scale."),
"",
"res/actions/scale24_black.png",
"ResizableBehavior",
std::make_shared<gd::Behavior>(),
std::make_shared<gd::BehaviorsSharedData>())
.SetHidden();
aut.AddExpressionAndConditionAndAction(
"number",
"Value",
_("Scale"),
_("the scale of the object (default scale is 1)"),
_("the scale"),
_("Size"),
"res/actions/scale24_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ScalableBehavior")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
aut.GetAllExpressions()["Value"].SetGroup("");
aut.AddExpressionAndConditionAndAction(
"number",
"X",
_("Scale on X axis"),
_("the scale on X axis of the object (default scale is 1)"),
_("the scale on X axis"),
_("Size"),
"res/actions/scaleWidth24_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ScalableBehavior")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
aut.GetAllExpressions()["X"].SetGroup("");
aut.AddExpressionAndConditionAndAction(
"number",
"Y",
_("Scale on Y axis"),
_("the scale on Y axis of the object (default scale is 1)"),
_("the scale on Y axis"),
_("Size"),
"res/actions/scaleHeight24_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "ScalableBehavior")
.UseStandardParameters(
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced();
aut.GetAllExpressions()["Y"].SetGroup("");
}
} // namespace gd

View File

@@ -1,58 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public
* License.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Tools/Localization.h"
using namespace std;
namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsTextContainerExtension(
gd::PlatformExtension& extension) {
extension
.SetExtensionInformation("TextContainerCapability",
_("Text capability"),
_("Animate objects."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Text capability"))
.SetIcon("res/conditions/text24_black.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"TextContainerBehavior",
_("Text capability"),
"Text",
_("Access objects text."),
"",
"res/conditions/text24_black.png",
"TextContainerBehavior",
std::make_shared<gd::Behavior>(),
std::make_shared<gd::BehaviorsSharedData>())
.SetHidden();
aut.AddExpressionAndConditionAndAction(
"string",
"Value",
_("Text"),
_("the text"),
_("the text"),
"",
"res/conditions/text24_black.png")
.AddParameter("object", _("Object"))
.AddParameter("behavior", _("Behavior"), "TextContainerBehavior")
.UseStandardParameters(
"string", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Text")))
.MarkAsSimple();
aut.GetAllStrExpressions()["Value"].SetGroup("");
}
} // namespace gd

View File

@@ -15,28 +15,28 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinCommonConversions", "BuiltinCommonConversions",
_("Conversion"), _("Standard Conversions"),
"Expressions to convert number, texts and quantities.", "Expressions to convert number, texts and quantities.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/common-conversions"); .SetExtensionHelpPath("/all-features/common-conversions");
extension.AddInstructionOrExpressionGroupMetadata(_("Conversion"))
.SetIcon("res/conditions/toujours24_black.png"); #if defined(GD_IDE_ONLY)
extension extension
.AddExpression("ToNumber", .AddExpression("ToNumber",
_("Text > Number"), _("Text > Number"),
_("Convert the text to a number"), _("Convert the text to a number"),
"", _("Conversion"),
"res/conditions/toujours24_black.png") "res/conditions/toujours24.png")
.AddParameter("string", _("Text to convert to a number")); .AddParameter("string", _("Text to convert to a number"));
extension extension
.AddStrExpression("ToString", .AddStrExpression("ToString",
_("Number > Text"), _("Number > Text"),
_("Convert the result of the expression to text"), _("Convert the result of the expression to text"),
"", _("Conversion"),
"res/conditions/toujours24_black.png") "res/conditions/toujours24.png")
.AddParameter("expression", _("Expression to be converted to text")); .AddParameter("expression", _("Expression to be converted to text"));
extension extension
@@ -44,8 +44,8 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
_("Number > Text ( without scientific notation )"), _("Number > Text ( without scientific notation )"),
_("Convert the result of the expression to text, " _("Convert the result of the expression to text, "
"without using the scientific notation"), "without using the scientific notation"),
"", _("Conversion"),
"res/conditions/toujours24_black.png") "res/conditions/toujours24.png")
.AddParameter("expression", _("Expression to be converted to text")); .AddParameter("expression", _("Expression to be converted to text"));
extension extension
@@ -53,8 +53,8 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
"ToRad", "ToRad",
_("Degrees > Radians"), _("Degrees > Radians"),
_("Converts the angle, expressed in degrees, into radians"), _("Converts the angle, expressed in degrees, into radians"),
"", _("Conversion"),
"res/conditions/toujours24_black.png") "res/conditions/toujours24.png")
.AddParameter("expression", _("Angle, in degrees")); .AddParameter("expression", _("Angle, in degrees"));
extension extension
@@ -62,76 +62,10 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
"ToDeg", "ToDeg",
_("Radians > Degrees"), _("Radians > Degrees"),
_("Converts the angle, expressed in radians, into degrees"), _("Converts the angle, expressed in radians, into degrees"),
"", _("Conversion"),
"res/conditions/toujours24_black.png") "res/conditions/toujours24.png")
.AddParameter("expression", _("Angle, in radians")); .AddParameter("expression", _("Angle, in radians"));
#endif
extension
.AddStrExpression("ToJSON",
_("Convert scene variable to JSON"),
_("Convert a scene variable to JSON"),
_("JSON"),
"res/conditions/toujours24_black.png")
.AddParameter("scenevar", _("Scene variable to be stringified"));
extension
.AddStrExpression("GlobalVarToJSON",
_("Convert global variable to JSON"),
_("Convert a global variable to JSON"),
_("JSON"),
"res/conditions/toujours24_black.png")
.AddParameter("globalvar", _("The global variable to be stringified"));
extension
.AddStrExpression("ObjectVarToJSON",
_("Convert object variable to JSON"),
_("Convert an object variable to JSON"),
_("JSON"),
"res/conditions/toujours24_black.png")
.AddParameter("objectPtr", _("The object with the variable"))
.AddParameter("objectvar", _("The object variable to be stringified"));
extension
.AddAction(
"JSONToVariableStructure",
_("Convert JSON to a scene variable"),
_("Parse a JSON object and store it into a scene variable"),
_("Convert JSON string _PARAM0_ and store it into variable _PARAM1_"),
"",
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("scenevar", _("Variable where store the JSON object"))
.MarkAsAdvanced();
extension
.AddAction("JSONToGlobalVariableStructure",
_("Convert JSON to global variable"),
_("Parse a JSON object and store it into a global variable"),
_("Convert JSON string _PARAM0_ and store it into global "
"variable _PARAM1_"),
"",
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("globalvar",
_("Global variable where store the JSON object"))
.MarkAsAdvanced();
extension
.AddAction("JSONToObjectVariableStructure",
_("Convert JSON to object variable"),
_("Parse a JSON object and store it into an object variable"),
_("Parse JSON string _PARAM0_ and store it into variable "
"_PARAM2_ of _PARAM1_"),
"",
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("objectPtr", _("Object"))
.AddParameter("objectvar",
_("Object variable where store the JSON object"))
.MarkAsAdvanced();
} }
} // namespace gd } // namespace gd

View File

@@ -4,6 +4,8 @@
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#include "AllBuiltinExtensions.h" #include "AllBuiltinExtensions.h"
#include "GDCore/Tools/Localization.h"
#if defined(GD_IDE_ONLY)
#include "GDCore/Events/Builtin/CommentEvent.h" #include "GDCore/Events/Builtin/CommentEvent.h"
#include "GDCore/Events/Builtin/ForEachChildVariableEvent.h" #include "GDCore/Events/Builtin/ForEachChildVariableEvent.h"
#include "GDCore/Events/Builtin/ForEachEvent.h" #include "GDCore/Events/Builtin/ForEachEvent.h"
@@ -13,7 +15,7 @@
#include "GDCore/Events/Builtin/StandardEvent.h" #include "GDCore/Events/Builtin/StandardEvent.h"
#include "GDCore/Events/Builtin/WhileEvent.h" #include "GDCore/Events/Builtin/WhileEvent.h"
#include "GDCore/Events/Event.h" #include "GDCore/Events/Event.h"
#include "GDCore/Tools/Localization.h" #endif
using namespace std; using namespace std;
namespace gd { namespace gd {
@@ -24,48 +26,22 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinCommonInstructions", "BuiltinCommonInstructions",
_("Events and control flow"), _("Builtin events"),
"GDevelop comes with a set of events and conditions that allow to " "GDevelop comes with a set of events and conditions that allow to "
"express the game logic and rules.", "express the game logic and rules.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetCategory("Advanced")
.SetExtensionHelpPath("/all-features/advanced-conditions"); .SetExtensionHelpPath("/all-features/advanced-conditions");
extension
.AddInstructionOrExpressionGroupMetadata(_("Events and control flow"))
.SetIcon("res/conditions/toujours24_black.png");
// This condition is deprecated as this does not bring anything new
// and can be confusing or misleading for beginners.
extension
.AddCondition("Always",
_("Always"),
_("This condition always returns true (or always false, if "
"the condition is inverted)."),
_("Always"),
"",
"res/conditions/toujours24_black.png",
"res/conditions/toujours_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced()
.SetHidden();
// Compatibility with GD <= 5.0.127
extension
.AddDuplicatedCondition(
"Toujours", "BuiltinCommonInstructions::Always", {.unscoped = true})
.SetHidden();
// end of compatibility code
#if defined(GD_IDE_ONLY)
extension extension
.AddCondition("Or", .AddCondition("Or",
_("Or"), _("Or"),
_("Check if one of the sub conditions is true"), _("Check if one of the sub conditions is true"),
_("If one of these conditions is true:"), _("If one of these conditions is true:"),
"", _("Advanced"),
"res/conditions/or24_black.png", "res/conditions/or24.png",
"res/conditions/or_black.png") "res/conditions/or.png")
.SetCanHaveSubInstructions() .SetCanHaveSubInstructions()
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -74,9 +50,9 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("And"), _("And"),
_("Check if all sub conditions are true"), _("Check if all sub conditions are true"),
_("If all of these conditions are true:"), _("If all of these conditions are true:"),
"", _("Advanced"),
"res/conditions/and24_black.png", "res/conditions/and24.png",
"res/conditions/and_black.png") "res/conditions/and.png")
.SetCanHaveSubInstructions() .SetCanHaveSubInstructions()
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -86,9 +62,9 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Not"), _("Not"),
_("Return the contrary of the result of the sub conditions"), _("Return the contrary of the result of the sub conditions"),
_("Invert the logical result of these conditions:"), _("Invert the logical result of these conditions:"),
"", _("Advanced"),
"res/conditions/not24_black.png", "res/conditions/not24.png",
"res/conditions/not_black.png") "res/conditions/not.png")
.SetCanHaveSubInstructions() .SetCanHaveSubInstructions()
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -97,54 +73,10 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
_("Trigger once while true"), _("Trigger once while true"),
_("Run actions only once, for each time the conditions have been met."), _("Run actions only once, for each time the conditions have been met."),
_("Trigger once"), _("Trigger once"),
"", _("Advanced"),
"res/conditions/once24.png", "res/conditions/once24.png",
"res/conditions/once.png"); "res/conditions/once.png");
extension
.AddCondition("CompareNumbers",
_("Compare two numbers"),
_("Compare the two numbers."),
_("_PARAM0_ _PARAM1_ _PARAM2_"),
"",
"res/conditions/egal24_black.png",
"res/conditions/egal_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("expression", _("First expression"))
.AddParameter("relationalOperator", _("Sign of the test"), "number")
.AddParameter("expression", _("Second expression"))
.MarkAsAdvanced();
// Compatibility with GD <= 5.0.127
extension
.AddDuplicatedCondition("Egal",
"BuiltinCommonInstructions::CompareNumbers",
{.unscoped = true})
.SetHidden();
// end of compatibility code
extension
.AddCondition("CompareStrings",
_("Compare two strings"),
_("Compare the two strings."),
_("_PARAM0_ _PARAM1_ _PARAM2_"),
"",
"res/conditions/egal24_black.png",
"res/conditions/egal_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("string", _("First string expression"))
.AddParameter("relationalOperator", _("Sign of the test"), "string")
.AddParameter("string", _("Second string expression"))
.MarkAsAdvanced();
// Compatibility with GD <= 5.0.127
extension
.AddDuplicatedCondition("StrEqual",
"BuiltinCommonInstructions::CompareStrings",
{.unscoped = true})
.SetHidden();
// end of compatibility code
extension.AddEvent( extension.AddEvent(
"Standard", "Standard",
_("Standard event"), _("Standard event"),
@@ -154,29 +86,29 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
std::make_shared<gd::StandardEvent>()); std::make_shared<gd::StandardEvent>());
extension.AddEvent("Link", extension.AddEvent("Link",
_("Link external events"), _("Link"),
_("Link to external events."), _("Link to some external events"),
"", "",
"res/lienaddicon.png", "res/lienaddicon.png",
std::make_shared<gd::LinkEvent>()); std::make_shared<gd::LinkEvent>());
extension.AddEvent("Comment", extension.AddEvent("Comment",
_("Comment"), _("Comment"),
_("Event displaying a text in the events editor."), _("Event displaying a text in the events editor"),
"", "",
"res/comment.png", "res/comment.png",
std::make_shared<gd::CommentEvent>()); std::make_shared<gd::CommentEvent>());
extension.AddEvent("While", extension.AddEvent("While",
_("While"), _("While"),
_("Repeat the event while the conditions are true."), _("The event is repeated while the conditions are true"),
"", "",
"res/while.png", "res/while.png",
std::make_shared<gd::WhileEvent>()); std::make_shared<gd::WhileEvent>());
extension.AddEvent("Repeat", extension.AddEvent("Repeat",
_("Repeat"), _("Repeat"),
_("Repeat the event for a specified number of times."), _("Event repeated a number of times"),
"", "",
"res/repeat.png", "res/repeat.png",
std::make_shared<gd::RepeatEvent>()); std::make_shared<gd::RepeatEvent>());
@@ -197,11 +129,12 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
std::make_shared<gd::ForEachChildVariableEvent>()); std::make_shared<gd::ForEachChildVariableEvent>());
extension.AddEvent("Group", extension.AddEvent("Group",
_("Event group"), _("Group"),
_("Group containing events."), _("Group containing events"),
"", "",
"res/foreach.png", "res/foreach.png",
std::make_shared<gd::GroupEvent>()); std::make_shared<gd::GroupEvent>());
#endif
} }
} // namespace gd } // namespace gd

View File

@@ -19,28 +19,25 @@ BuiltinExtensionsImplementer::ImplementsExternalLayoutsExtension(
"external layouts.", "external layouts.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/interface/scene-editor/external-layouts") .SetExtensionHelpPath("/interface/scene-editor/external-layouts");
.SetCategory("Advanced");
extension.AddInstructionOrExpressionGroupMetadata(_("External layouts"))
.SetIcon("res/ribbon_default/externallayout32.png");
#if defined(GD_IDE_ONLY)
extension extension
.AddAction("CreateObjectsFromExternalLayout", .AddAction("CreateObjectsFromExternalLayout",
_("Create objects from an external layout"), _("Create objects from an external layout"),
_("Create objects from an external layout."), _("Create objects from an external layout."),
_("Create objects from the external layout named _PARAM1_"), _("Create objects from the external layout named _PARAM1_"),
"", _("External layouts"),
"res/ribbon_default/externallayout32.png", "res/conditions/fichier24.png",
"res/ribbon_default/externallayout32.png") "res/conditions/fichier.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("externalLayoutName", _("Name of the external layout")) .AddParameter("string", _("Name of the external layout"))
.AddParameter("expression", _("X position of the origin"), "", true) .AddParameter("expression", _("X position of the origin"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
.AddParameter("expression", _("Y position of the origin"), "", true) .AddParameter("expression", _("Y position of the origin"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
.AddParameter("expression", _("Z position of the origin"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced(); .MarkAsAdvanced();
#endif
} }
} // namespace gd } // namespace gd

View File

@@ -20,11 +20,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
"stored on the device and erased when the game is uninstalled.", "stored on the device and erased when the game is uninstalled.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/storage") .SetExtensionHelpPath("/all-features/storage");
.SetCategory("Advanced");
extension.AddInstructionOrExpressionGroupMetadata(_("Storage"))
.SetIcon("res/conditions/fichier24.png");
#if defined(GD_IDE_ONLY)
extension extension
.AddCondition( .AddCondition(
"GroupExists", "GroupExists",
@@ -32,7 +30,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
_("Check if an element (example : PlayerState/CurrentLevel) exists " _("Check if an element (example : PlayerState/CurrentLevel) exists "
"in the stored data.\nSpaces are forbidden in element names."), "in the stored data.\nSpaces are forbidden in element names."),
_("_PARAM1_ exists in storage _PARAM0_"), _("_PARAM1_ exists in storage _PARAM0_"),
"", _("Storage"),
"res/conditions/fichier24.png", "res/conditions/fichier24.png",
"res/conditions/fichier.png") "res/conditions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -48,7 +46,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
"action, but it will be slower.\nIf you use this action, do not " "action, but it will be slower.\nIf you use this action, do not "
"forget to unload the storage from memory."), "forget to unload the storage from memory."),
_("Load storage _PARAM0_ in memory"), _("Load storage _PARAM0_ in memory"),
"", _("Storage"),
"res/actions/fichier24.png", "res/actions/fichier24.png",
"res/actions/fichier.png") "res/actions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -60,7 +58,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
_("This action closes the structured data previously loaded " _("This action closes the structured data previously loaded "
"in memory, saving all changes made."), "in memory, saving all changes made."),
_("Close structured data _PARAM0_"), _("Close structured data _PARAM0_"),
"", _("Storage"),
"res/actions/fichier24.png", "res/actions/fichier24.png",
"res/actions/fichier.png") "res/actions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -69,13 +67,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension extension
.AddAction( .AddAction(
"EcrireFichierExp", "EcrireFichierExp",
_("Save a value"), _("Write a value"),
_("Save the result of the expression in the stored data, in the " _("Write the result of the expression in the stored data, in the "
"specified element.\nSpecify the structure leading to the " "specified element.\nSpecify the structure leading to the "
"element using / (example : Root/Level/Current)\nSpaces are " "element using / (example : Root/Level/Current)\nSpaces are "
"forbidden in element names."), "forbidden in element names."),
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"), _("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
"", _("Storage"),
"res/actions/fichier24.png", "res/actions/fichier24.png",
"res/actions/fichier.png") "res/actions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -85,13 +83,13 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension extension
.AddAction( .AddAction(
"EcrireFichierTxt", "EcrireFichierTxt",
_("Save a text"), _("Write a text"),
_("Save the text in the specified storage, in the specified " _("Write the text in the specified storage, in the specified "
"element.\nSpecify " "element.\nSpecify "
"the structure leading to the element using / (example : " "the structure leading to the element using / (example : "
"Root/Level/Current)\nSpaces are forbidden in element names."), "Root/Level/Current)\nSpaces are forbidden in element names."),
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"), _("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
"", _("Storage"),
"res/actions/fichier24.png", "res/actions/fichier24.png",
"res/actions/fichier.png") "res/actions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -101,14 +99,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension extension
.AddAction( .AddAction(
"LireFichierExp", "LireFichierExp",
_("Load a value"), _("Read a value"),
_("Load the value saved in the specified element and store it in a " _("Read the value saved in the specified element and store it in a "
"scene " "scene "
"variable.\nSpecify the structure leading to the element using / " "variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element " "(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."), "names."),
_("Load _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"), _("Read _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
"", _("Storage"),
"res/actions/fichier24.png", "res/actions/fichier24.png",
"res/actions/fichier.png") "res/actions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -119,15 +117,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension extension
.AddAction( .AddAction(
"LireFichierTxt", "LireFichierTxt",
_("Load a text"), _("Read a text"),
_("Load the text saved in the specified element and store it in a " _("Read the text saved in the specified element and store it in a "
"scene " "scene "
"variable.\nSpecify the structure leading to the element using / " "variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element " "(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."), "names."),
_("Load _PARAM1_ from storage _PARAM0_ and store as text in " _("Read _PARAM1_ from storage _PARAM0_ and store as text in "
"_PARAM3_"), "_PARAM3_"),
"", _("Storage"),
"res/actions/fichier24.png", "res/actions/fichier24.png",
"res/actions/fichier.png") "res/actions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -143,7 +141,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
"element using / (example : Root/Level/Current)\nSpaces are " "element using / (example : Root/Level/Current)\nSpaces are "
"forbidden in element names."), "forbidden in element names."),
_("Delete _PARAM1_ from storage _PARAM0_"), _("Delete _PARAM1_ from storage _PARAM0_"),
"", _("Storage"),
"res/actions/delete24.png", "res/actions/delete24.png",
"res/actions/delete.png") "res/actions/delete.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
@@ -156,7 +154,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
_("Clear a storage"), _("Clear a storage"),
_("Clear the specified storage, removing all data saved in it."), _("Clear the specified storage, removing all data saved in it."),
_("Delete storage _PARAM0_"), _("Delete storage _PARAM0_"),
"", _("Storage"),
"res/actions/delete24.png", "res/actions/delete24.png",
"res/actions/delete.png") "res/actions/delete.png")
.AddParameter("string", _("Storage name")); .AddParameter("string", _("Storage name"));
@@ -166,22 +164,37 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
_("A storage exists"), _("A storage exists"),
_("Test if the specified storage exists."), _("Test if the specified storage exists."),
_("Storage _PARAM0_ exists"), _("Storage _PARAM0_ exists"),
"", _("Storage"),
"res/conditions/fichier24.png", "res/conditions/fichier24.png",
"res/conditions/fichier.png") "res/conditions/fichier.png")
.AddParameter("string", _("Storage name")) .AddParameter("string", _("Storage name"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension
.AddAction("LaunchFile",
_("Open a URL or a file"),
_("This action launches the specified file or URL, in a "
"browser (or in a new tab if the game is using the Web "
"platform and is launched inside a browser)."),
_("Open URL (or file) _PARAM0_"),
_("Files"),
"res/actions/launchFile24.png",
"res/actions/launchFile.png")
.AddParameter("string", _("URL (or filename)"))
.AddCodeOnlyParameter("currentScene", "")
.MarkAsAdvanced();
extension extension
.AddAction("ExecuteCmd", .AddAction("ExecuteCmd",
_("Execute a command"), _("Execute a command"),
_("This action executes the specified command."), _("This action executes the specified command."),
_("Execute _PARAM0_"), _("Execute _PARAM0_"),
_("Network"), _("Files"),
"res/actions/launchFile24.png", "res/actions/launchFile24.png",
"res/actions/launchFile.png") "res/actions/launchFile.png")
.AddParameter("string", _("Command")) .AddParameter("string", _("Command"))
.MarkAsAdvanced(); .MarkAsAdvanced();
#endif
} }
} // namespace gd } // namespace gd

View File

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

View File

@@ -14,24 +14,22 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinKeyboard", "BuiltinKeyboard",
_("Keyboard"), _("Keyboard features"),
_("Allows your game to respond to keyboard input. Note that this " _("Allows your game to respond to keyboard input. Note that this "
"does not work with on-screen keyboard on touch devices: use " "does not work with on-screen keyboard on touch devices: use "
"instead conditions related to touch when making a game for " "instead conditions related to touch when making a game for "
"mobile/touchscreen devices."), "mobile/touchscreen devices."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/keyboard") .SetExtensionHelpPath("/all-features/keyboard");
.SetCategory("Input");
extension.AddInstructionOrExpressionGroupMetadata(_("Keyboard"))
.SetIcon("res/conditions/keyboard24.png");
#if defined(GD_IDE_ONLY)
extension extension
.AddCondition("KeyPressed", .AddCondition("KeyPressed",
_("Key pressed"), _("Key pressed"),
_("Check if a key is pressed"), _("Test if a key is pressed"),
_("_PARAM1_ key is pressed"), _("_PARAM1_ key is pressed"),
"", _("Keyboard"),
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -40,9 +38,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension extension
.AddCondition("KeyReleased", .AddCondition("KeyReleased",
_("Key released"), _("Key released"),
_("Check if a key was just released"), _("Test if a key was just released"),
_("_PARAM1_ key is released"), _("_PARAM1_ key is released"),
"", _("Keyboard"),
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -51,35 +49,35 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension extension
.AddCondition("KeyFromTextPressed", .AddCondition("KeyFromTextPressed",
_("Key pressed (text expression)"), _("Key pressed (text expression)"),
_("Check if a key, retrieved from the result of the " _("Test if a key, retrieved from the result of the "
"expression, is pressed"), "expression, is pressed"),
_("_PARAM1_ key is pressed"), _("_PARAM1_ key is pressed"),
"", _("Keyboard"),
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Expression generating the key to check")) .AddParameter("string", _("Expression generating the key to test"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddCondition("KeyFromTextReleased", .AddCondition("KeyFromTextReleased",
_("Key released (text expression)"), _("Key released (text expression)"),
_("Check if a key, retrieved from the result of the " _("Test if a key, retrieved from the result of the "
"expression, was just released"), "expression, was just released"),
_("_PARAM1_ key is released"), _("_PARAM1_ key is released"),
"", _("Keyboard"),
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("string", _("Expression generating the key to check")) .AddParameter("string", _("Expression generating the key to test"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddCondition("AnyKeyPressed", .AddCondition("AnyKeyPressed",
_("Any key pressed"), _("Any key pressed"),
_("Check if any key is pressed"), _("Test if any key is pressed"),
_("Any key is pressed"), _("Any key is pressed"),
"", _("Keyboard"),
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
@@ -87,9 +85,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
extension extension
.AddCondition("AnyKeyReleased", .AddCondition("AnyKeyReleased",
_("Any key released"), _("Any key released"),
_("Check if any key is released"), _("Test if any key is released"),
_("Any key is released"), _("Any key is released"),
"", _("Keyboard"),
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
@@ -99,9 +97,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"LastPressedKey", "LastPressedKey",
_("Last pressed key"), _("Last pressed key"),
_("Get the name of the latest key pressed on the keyboard"), _("Get the name of the latest key pressed on the keyboard"),
"", _("Keyboard"),
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
#endif
} }
} // namespace gd } // namespace gd

View File

@@ -18,63 +18,14 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"A set of mathematical functions that can be used in expressions.", "A set of mathematical functions that can be used in expressions.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)"); "Open source (MIT License)");
extension.AddInstructionOrExpressionGroupMetadata(_("Mathematical tools"))
.SetIcon("res/mathfunction.png");
extension #if defined(GD_IDE_ONLY)
.AddExpression("Random",
_("Random integer"),
_("Random integer"),
"",
"res/dice-6.svg")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomInRange",
_("Random integer in range"),
_("Random integer in range"),
"",
"res/dice-6.svg")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomFloat",
_("Random float"),
_("Random float"),
"",
"res/dice-6.svg")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomFloatInRange",
_("Random float in range"),
_("Random float in range"),
"",
"res/dice-6.svg")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomWithStep",
_("Random value in steps"),
_("Random value in steps"),
"",
"res/dice-6.svg")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"))
.AddParameter("expression", _("Step"));
extension extension
.AddExpression("normalize", .AddExpression("normalize",
_("Normalize a value between `min` and `max` to a value between 0 and 1."), _("Normalize a value between `min` and `max` to a value between 0 and 1."),
_("Remap a value between 0 and 1."), _("Remap a value between 0 and 1."),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Value")) .AddParameter("expression", _("Value"))
.AddParameter("expression", _("Min")) .AddParameter("expression", _("Min"))
@@ -84,7 +35,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("clamp", .AddExpression("clamp",
_("Clamp (restrict a value to a given range)"), _("Clamp (restrict a value to a given range)"),
_("Restrict a value to a given range"), _("Restrict a value to a given range"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Value")) .AddParameter("expression", _("Value"))
.AddParameter("expression", _("Min")) .AddParameter("expression", _("Min"))
@@ -94,16 +45,16 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("AngleDifference", .AddExpression("AngleDifference",
_("Difference between two angles"), _("Difference between two angles"),
_("Difference between two angles"), _("Difference between two angles"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("First angle, in degrees")) .AddParameter("expression", _("First angle"))
.AddParameter("expression", _("Second angle, in degrees")); .AddParameter("expression", _("Second angle"));
extension extension
.AddExpression("AngleBetweenPositions", .AddExpression("AngleBetweenPositions",
_("Angle between two positions"), _("Angle between two positions"),
_("Compute the angle between two positions (in degrees)."), _("Compute the angle between two positions."),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("First point X position")) .AddParameter("expression", _("First point X position"))
.AddParameter("expression", _("First point Y position")) .AddParameter("expression", _("First point Y position"))
@@ -114,7 +65,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("DistanceBetweenPositions", .AddExpression("DistanceBetweenPositions",
_("Distance between two positions"), _("Distance between two positions"),
_("Compute the distance between two positions."), _("Compute the distance between two positions."),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("First point X position")) .AddParameter("expression", _("First point X position"))
.AddParameter("expression", _("First point Y position")) .AddParameter("expression", _("First point Y position"))
@@ -125,7 +76,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("mod", .AddExpression("mod",
_("Modulo"), _("Modulo"),
_("x mod y"), _("x mod y"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("x (as in x mod y)")) .AddParameter("expression", _("x (as in x mod y)"))
.AddParameter("expression", _("y (as in x mod y)")); .AddParameter("expression", _("y (as in x mod y)"));
@@ -134,7 +85,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("min", .AddExpression("min",
_("Minimum of two numbers"), _("Minimum of two numbers"),
_("Minimum of two numbers"), _("Minimum of two numbers"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("First expression")) .AddParameter("expression", _("First expression"))
.AddParameter("expression", _("Second expression")); .AddParameter("expression", _("Second expression"));
@@ -143,7 +94,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("max", .AddExpression("max",
_("Maximum of two numbers"), _("Maximum of two numbers"),
_("Maximum of two numbers"), _("Maximum of two numbers"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("First expression")) .AddParameter("expression", _("First expression"))
.AddParameter("expression", _("Second expression")); .AddParameter("expression", _("Second expression"));
@@ -152,16 +103,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("abs", .AddExpression("abs",
_("Absolute value"), _("Absolute value"),
_("Absolute value"), _("Absolute value"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression("acos", .AddExpression("acos",
_("Arccosine"), _("Arccosine"),
_("Arccosine, return an angle (in radian). " _("Arccosine"),
"`ToDeg` allows to convert it to degrees."), _("Mathematical tools"),
"",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -169,16 +119,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("acosh", .AddExpression("acosh",
_("Hyperbolic arccosine"), _("Hyperbolic arccosine"),
_("Hyperbolic arccosine"), _("Hyperbolic arccosine"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression("asin", .AddExpression("asin",
_("Arcsine"), _("Arcsine"),
_("Arcsine, return an angle (in radian). " _("Arcsine"),
"`ToDeg` allows to convert it to degrees."), _("Mathematical tools"),
"",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -186,16 +135,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("asinh", .AddExpression("asinh",
_("Arcsine"), _("Arcsine"),
_("Arcsine"), _("Arcsine"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression("atan", .AddExpression("atan",
_("Arctangent"), _("Arctangent"),
_("Arctangent, return an angle (in radian). " _("Arctangent"),
"`ToDeg` allows to convert it to degrees."), _("Mathematical tools"),
"",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -203,7 +151,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("atan2", .AddExpression("atan2",
_("2 argument arctangent"), _("2 argument arctangent"),
_("2 argument arctangent (atan2)"), _("2 argument arctangent (atan2)"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Y")) .AddParameter("expression", _("Y"))
.AddParameter("expression", _("X")); .AddParameter("expression", _("X"));
@@ -212,7 +160,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("atanh", .AddExpression("atanh",
_("Hyperbolic arctangent"), _("Hyperbolic arctangent"),
_("Hyperbolic arctangent"), _("Hyperbolic arctangent"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -220,7 +168,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("cbrt", .AddExpression("cbrt",
_("Cube root"), _("Cube root"),
_("Cube root"), _("Cube root"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -228,42 +176,23 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("ceil", .AddExpression("ceil",
_("Ceil (round up)"), _("Ceil (round up)"),
_("Round number up to an integer"), _("Round number up to an integer"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension
.AddExpression("ceilTo",
_("Ceil (round up) to a decimal point"),
_("Round number up to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension extension
.AddExpression("floor", .AddExpression("floor",
_("Floor (round down)"), _("Floor (round down)"),
_("Round number down to an integer"), _("Round number down to an integer"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension
.AddExpression("floorTo",
_("Floor (round down) to a decimal point"),
_("Round number down to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension extension
.AddExpression("cos", .AddExpression("cos",
_("Cosine"), _("Cosine"),
_("Cosine of an angle (in radian). " _("Cosine of a number"),
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."), _("Mathematical tools"),
"",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -271,7 +200,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("cosh", .AddExpression("cosh",
_("Hyperbolic cosine"), _("Hyperbolic cosine"),
_("Hyperbolic cosine"), _("Hyperbolic cosine"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -279,7 +208,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("cot", .AddExpression("cot",
_("Cotangent"), _("Cotangent"),
_("Cotangent of a number"), _("Cotangent of a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -287,7 +216,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("csc", .AddExpression("csc",
_("Cosecant"), _("Cosecant"),
_("Cosecant of a number"), _("Cosecant of a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -295,7 +224,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("int", .AddExpression("int",
_("Round"), _("Round"),
_("Round a number"), _("Round a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.SetHidden() .SetHidden()
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -304,7 +233,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("rint", .AddExpression("rint",
_("Round"), _("Round"),
_("Round a number"), _("Round a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.SetHidden() .SetHidden()
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -313,24 +242,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("round", .AddExpression("round",
_("Round"), _("Round"),
_("Round a number"), _("Round a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension
.AddExpression("roundTo",
_("Round to a decimal point"),
_("Round a number to the Nth decimal place"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Expression"), "", true);
extension extension
.AddExpression("exp", .AddExpression("exp",
_("Exponential"), _("Exponential"),
_("Exponential of a number"), _("Exponential of a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -338,7 +258,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("log", .AddExpression("log",
_("Logarithm"), _("Logarithm"),
_("Logarithm"), _("Logarithm"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -346,7 +266,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("ln", .AddExpression("ln",
_("Logarithm"), _("Logarithm"),
_("Logarithm"), _("Logarithm"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.SetHidden() .SetHidden()
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -355,7 +275,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("log2", .AddExpression("log2",
_("Base-2 logarithm"), _("Base-2 logarithm"),
_("Base 2 Logarithm"), _("Base 2 Logarithm"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -363,7 +283,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("log10", .AddExpression("log10",
_("Base-10 logarithm"), _("Base-10 logarithm"),
_("Base-10 logarithm"), _("Base-10 logarithm"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -371,7 +291,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("nthroot", .AddExpression("nthroot",
_("Nth root"), _("Nth root"),
_("Nth root of a number"), _("Nth root of a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Number")) .AddParameter("expression", _("Number"))
.AddParameter("expression", _("N")); .AddParameter("expression", _("N"));
@@ -380,7 +300,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("pow", .AddExpression("pow",
_("Power"), _("Power"),
_("Raise a number to power n"), _("Raise a number to power n"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Number")) .AddParameter("expression", _("Number"))
.AddParameter("expression", _("The exponent (n in x^n)")); .AddParameter("expression", _("The exponent (n in x^n)"));
@@ -389,7 +309,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("sec", .AddExpression("sec",
_("Secant"), _("Secant"),
_("Secant"), _("Secant"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -397,16 +317,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("sign", .AddExpression("sign",
_("Sign of a number"), _("Sign of a number"),
_("Return the sign of a number (1,-1 or 0)"), _("Return the sign of a number (1,-1 or 0)"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression("sin", .AddExpression("sin",
_("Sine"), _("Sine"),
_("Sine of an angle (in radian). " _("Sine of a number"),
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."), _("Mathematical tools"),
"",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -414,7 +333,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("sinh", .AddExpression("sinh",
_("Hyperbolic sine"), _("Hyperbolic sine"),
_("Hyperbolic sine"), _("Hyperbolic sine"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -422,16 +341,15 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("sqrt", .AddExpression("sqrt",
_("Square root"), _("Square root"),
_("Square root of a number"), _("Square root of a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression("tan", .AddExpression("tan",
_("Tangent"), _("Tangent"),
_("Tangent of an angle (in radian). " _("Tangent of a number"),
"If you want to use degrees, use`ToRad`: `tan(ToRad(45))`."), _("Mathematical tools"),
"",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -439,7 +357,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("tanh", .AddExpression("tanh",
_("Hyperbolic tangent"), _("Hyperbolic tangent"),
_("Hyperbolic tangent"), _("Hyperbolic tangent"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -447,7 +365,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("trunc", .AddExpression("trunc",
_("Truncation"), _("Truncation"),
_("Truncate a number"), _("Truncate a number"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -455,7 +373,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddExpression("lerp", .AddExpression("lerp",
_("Lerp (Linear interpolation)"), _("Lerp (Linear interpolation)"),
_("Linearly interpolate a to b by x"), _("Linearly interpolate a to b by x"),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("a (in a+(b-a)*x)")) .AddParameter("expression", _("a (in a+(b-a)*x)"))
.AddParameter("expression", _("b (in a+(b-a)*x)")) .AddParameter("expression", _("b (in a+(b-a)*x)"))
@@ -468,7 +386,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"relative to the origin (0;0). This is also known as " "relative to the origin (0;0). This is also known as "
"getting the cartesian coordinates of a 2D vector, using " "getting the cartesian coordinates of a 2D vector, using "
"its polar coordinates."), "its polar coordinates."),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Angle, in degrees")) .AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance")); .AddParameter("expression", _("Distance"));
@@ -480,28 +398,12 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"relative to the origin (0;0). This is also known as " "relative to the origin (0;0). This is also known as "
"getting the cartesian coordinates of a 2D vector, using " "getting the cartesian coordinates of a 2D vector, using "
"its polar coordinates."), "its polar coordinates."),
"", _("Mathematical tools"),
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Angle, in degrees")) .AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance")); .AddParameter("expression", _("Distance"));
extension #endif
.AddExpression("Pi",
_("Number Pi (3.1415...)"),
_("The number Pi (3.1415...)"),
"",
"res/mathfunction.png")
.SetHelpPath("/all-features/expressions");
extension
.AddExpression("lerpAngle",
_("Lerp (Linear interpolation) between two angles"),
_("Linearly interpolates between two angles (in degrees) by taking the shortest direction around the circle."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Starting angle, in degrees"))
.AddParameter("expression", _("Destination angle, in degrees"))
.AddParameter("expression", _("Interpolation value between 0 and 1."));
} }
} // namespace gd } // namespace gd

View File

@@ -23,13 +23,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"separately in different events.", "separately in different events.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/mouse-touch") .SetExtensionHelpPath("/all-features/mouse-touch");
.SetCategory("Input");
extension.AddInstructionOrExpressionGroupMetadata(_("Mouse and touch"))
.SetIcon("res/actions/mouse24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Multitouch"))
.SetIcon("res/conditions/touch24.png");
#if defined(GD_IDE_ONLY)
extension extension
.AddCondition( .AddCondition(
"IsMouseWheelScrollingUp", "IsMouseWheelScrollingUp",
@@ -37,7 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Check if the mouse wheel is scrolling up. Use MouseWheelDelta " _("Check if the mouse wheel is scrolling up. Use MouseWheelDelta "
"expression if you want to know the amount that was scrolled."), "expression if you want to know the amount that was scrolled."),
_("The mouse wheel is scrolling up"), _("The mouse wheel is scrolling up"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
@@ -51,7 +47,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Check if the mouse wheel is scrolling down. Use MouseWheelDelta " _("Check if the mouse wheel is scrolling down. Use MouseWheelDelta "
"expression if you want to know the amount that was scrolled."), "expression if you want to know the amount that was scrolled."),
_("The mouse wheel is scrolling down"), _("The mouse wheel is scrolling down"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
@@ -69,7 +65,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"touchscreens. If you want to have multitouch and differentiate " "touchscreens. If you want to have multitouch and differentiate "
"mouse movement and touches, just deactivate it with this action."), "mouse movement and touches, just deactivate it with this action."),
_("Move mouse cursor when touching screen: _PARAM1_"), _("Move mouse cursor when touching screen: _PARAM1_"),
"", _("Mouse and touch"),
"res/conditions/touch24.png", "res/conditions/touch24.png",
"res/conditions/touch.png") "res/conditions/touch.png")
@@ -84,7 +80,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Center cursor horizontally"), _("Center cursor horizontally"),
_("Put the cursor in the middle of the screen horizontally."), _("Put the cursor in the middle of the screen horizontally."),
_("Center cursor horizontally"), _("Center cursor horizontally"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
@@ -96,7 +92,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Center cursor vertically"), _("Center cursor vertically"),
_("Put the cursor in the middle of the screen vertically."), _("Put the cursor in the middle of the screen vertically."),
_("Center cursor vertically"), _("Center cursor vertically"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
@@ -108,7 +104,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Hide the cursor"), _("Hide the cursor"),
_("Hide the cursor."), _("Hide the cursor."),
_("Hide the cursor"), _("Hide the cursor"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -119,7 +115,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Show the cursor"), _("Show the cursor"),
_("Show the cursor."), _("Show the cursor."),
_("Show the cursor"), _("Show the cursor"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
@@ -131,7 +127,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Position the cursor of the mouse"), _("Position the cursor of the mouse"),
_("Position the cursor at the given coordinates."), _("Position the cursor at the given coordinates."),
_("Position cursor at _PARAM1_;_PARAM2_"), _("Position cursor at _PARAM1_;_PARAM2_"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
@@ -145,7 +141,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Center the cursor"), _("Center the cursor"),
_("Center the cursor on the screen."), _("Center the cursor on the screen."),
_("Center the cursor"), _("Center the cursor"),
"", _("Mouse and touch"),
"res/actions/mouse24.png", "res/actions/mouse24.png",
"res/actions/mouse.png") "res/actions/mouse.png")
@@ -155,91 +151,42 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
extension extension
.AddExpressionAndCondition( .AddExpressionAndCondition(
"number", "number",
"CursorX", "MouseX",
_("Cursor X position"), _("Cursor X position"),
_("the X position of the cursor or of a touch"), _("the X position of the cursor or of a touch"),
_("the cursor (or touch) X position"), _("the cursor (or touch) X position"),
"", _("Mouse and touch"),
"res/conditions/mouse24.png") "res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
// Support for deprecated names: // Support for deprecated names:
extension.AddDuplicatedCondition("MouseX", "CursorX").SetHidden(); extension.AddDuplicatedCondition("SourisX", "MouseX").SetHidden();
extension.AddDuplicatedExpression("MouseX", "CursorX").SetHidden(); extension.AddDuplicatedExpression("SourisX", "MouseX").SetHidden();
extension.AddDuplicatedCondition("SourisX", "CursorX").SetHidden();
extension.AddDuplicatedExpression("SourisX", "CursorX").SetHidden();
extension extension
.AddExpressionAndCondition( .AddExpressionAndCondition(
"number", "number",
"CursorY", "MouseY",
_("Cursor Y position"), _("Cursor Y position"),
_("the Y position of the cursor or of a touch"), _("the Y position of the cursor or of a touch"),
_("the cursor (or touch) Y position"), _("the cursor (or touch) Y position"),
"", _("Mouse and touch"),
"res/conditions/mouse24.png") "res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
// Support for deprecated names: // Support for deprecated names:
extension.AddDuplicatedCondition("MouseY", "CursorY").SetHidden(); extension.AddDuplicatedCondition("SourisY", "MouseY").SetHidden();
extension.AddDuplicatedExpression("MouseY", "CursorY").SetHidden(); extension.AddDuplicatedExpression("SourisY", "MouseY").SetHidden();
extension.AddDuplicatedCondition("SourisY", "CursorY").SetHidden();
extension.AddDuplicatedExpression("SourisY", "CursorY").SetHidden();
extension
.AddExpressionAndCondition("number",
"MouseOnlyCursorX",
_("Mouse cursor X position"),
_("the X position of the mouse cursor"),
_("the mouse cursor X position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
// It's only useful for extensions as they can't use TouchSimulateMouse.
.SetHidden();
extension
.AddExpressionAndCondition("number",
"MouseOnlyCursorY",
_("Mouse cursor Y position"),
_("the Y position of the mouse cursor"),
_("the mouse cursor Y position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
// It's only useful for extensions as they can't use TouchSimulateMouse.
.SetHidden();
extension
.AddCondition("IsMouseInsideCanvas",
_("Mouse cursor is inside the window"),
_("Check if the mouse cursor is inside the window."),
_("The mouse cursor is inside the window"),
"",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.MarkAsAdvanced();
extension extension
.AddCondition("MouseButtonPressed", .AddCondition("MouseButtonPressed",
@@ -247,7 +194,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Check if the specified mouse button is pressed or " _("Check if the specified mouse button is pressed or "
"if a touch is in contact with the screen."), "if a touch is in contact with the screen."),
_("Touch or _PARAM1_ mouse button is down"), _("Touch or _PARAM1_ mouse button is down"),
"", _("Mouse and touch"),
"res/conditions/mouse24.png", "res/conditions/mouse24.png",
"res/conditions/mouse.png") "res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
@@ -263,61 +210,25 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Mouse button released"), _("Mouse button released"),
_("Check if the specified mouse button was released."), _("Check if the specified mouse button was released."),
_("_PARAM1_ mouse button was released"), _("_PARAM1_ mouse button was released"),
"", _("Mouse and touch"),
"res/conditions/mouse24.png", "res/conditions/mouse24.png",
"res/conditions/mouse.png") "res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("mouse", _("Button to check")) .AddParameter("mouse", _("Button to check"))
.MarkAsSimple(); .MarkAsSimple();
extension
.AddCondition(
"MouseButtonFromTextPressed",
_("Mouse button pressed or touch held (text expression)"),
_("Check if a mouse button, retrieved from the result of the "
"expression, is pressed."),
_("_PARAM1_ mouse button is pressed"),
"",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("stringWithSelector",
_("Expression generating the mouse button to check"),
"[\"Left\", \"Right\", \"Middle\"]")
.SetParameterLongDescription(
_("Possible values are Left, Right and Middle."))
.MarkAsAdvanced();
extension
.AddCondition(
"MouseButtonFromTextReleased",
_("Mouse button released (text expression)"),
_("Check if a mouse button, retrieved from the result of the "
"expression, was just released."),
_("_PARAM1_ mouse button is released"),
"",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("stringWithSelector",
_("Expression generating the mouse button to check"),
"[\"Left\", \"Right\", \"Middle\"]")
.SetParameterLongDescription(
_("Possible values are Left, Right and Middle."))
.MarkAsAdvanced();
extension extension
.AddExpressionAndCondition("number", .AddExpressionAndCondition("number",
"TouchX", "TouchX",
_("Touch X position"), _("Touch X position"),
_("the X position of a specific touch"), _("the X position of a specific touch"),
_("the touch #_PARAM1_ X position"), _("the touch #_PARAM1_ X position"),
_("Multitouch"), _("Mouse and touch/Multitouch"),
"res/conditions/touch24.png") "res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier")) .AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
@@ -328,12 +239,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
_("Touch Y position"), _("Touch Y position"),
_("the Y position of a specific touch"), _("the Y position of a specific touch"),
_("the touch #_PARAM1_ Y position"), _("the touch #_PARAM1_ Y position"),
_("Multitouch"), _("Mouse and touch/Multitouch"),
"res/conditions/touch24.png") "res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier")) .AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
@@ -348,11 +259,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"next time you use it, it will be for a new touch, or it will " "next time you use it, it will be for a new touch, or it will "
"return false if no more touches have just started."), "return false if no more touches have just started."),
_("A new touch has started"), _("A new touch has started"),
_("Multitouch"), _("Mouse and touch/Multitouch"),
"res/conditions/touch24.png", "res/conditions/touch24.png",
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "");
.SetHidden();
extension extension
.AddCondition( .AddCondition(
@@ -364,98 +274,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"time you use it, it will be for a new touch, or it will return " "time you use it, it will be for a new touch, or it will return "
"false if no more touches have just ended."), "false if no more touches have just ended."),
_("A touch has ended"), _("A touch has ended"),
_("Multitouch"), _("Mouse and touch/Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddCondition(
"HasAnyTouchStarted",
_("A new touch has started"),
_("Check if a touch has just started on this frame. The touch "
"identifiers can be "
"accessed using StartedTouchId() and StartedTouchCount()."),
_("A new touch has started"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression("StartedTouchCount",
_("Started touch count"),
_("The number of touches that have just started on this "
"frame. The touch identifiers can be "
"accessed using StartedTouchId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression("StartedTouchId",
_("Started touch identifier"),
_("The identifier of the touch that has just started on "
"this frame. The number of touches can be "
"accessed using StartedTouchCount()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index"))
.SetHidden();
extension
.AddCondition(
"HasAnyTouchOrMouseStarted",
_("A new touch has started"),
_("Check if a touch has just started or the mouse left button has "
"been pressed on this frame. The touch identifiers can be "
"accessed using StartedTouchOrMouseId() and "
"StartedTouchOrMouseCount()."),
_("A new touch has started"),
_("Multitouch"),
"res/conditions/touch24.png", "res/conditions/touch24.png",
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
extension
.AddExpression(
"StartedTouchOrMouseCount",
_("Started touch count"),
_("The number of touches (including the mouse) that have just "
"started on this frame. The touch identifiers can be "
"accessed using StartedTouchOrMouseId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "");
extension
.AddExpression(
"StartedTouchOrMouseId",
_("Started touch identifier"),
_("The identifier of the touch or mouse that has just started on "
"this frame. The number of touches can be "
"accessed using StartedTouchOrMouseCount()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index"));
extension
.AddCondition("HasTouchEnded",
_("A touch has ended"),
_("Check if a touch has ended or a mouse left button has "
"been released."),
_("The touch with identifier _PARAM1_ has ended"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier"));
extension extension
.AddExpression("MouseWheelDelta", .AddExpression("MouseWheelDelta",
_("Mouse wheel: Displacement"), _("Mouse wheel: Displacement"),
@@ -468,19 +291,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddExpression("LastTouchId", .AddExpression("LastTouchId",
_("Identifier of the last touch"), _("Identifier of the last touch"),
_("Identifier of the last touch"), _("Identifier of the last touch"),
_("Multitouch"), _("Mouse and touch/Multitouch"),
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "");
.SetHidden();
extension extension
.AddExpression("LastEndedTouchId", .AddExpression("LastEndedTouchId",
_("Identifier of the last ended touch"), _("Identifier of the last ended touch"),
_("Identifier of the last ended touch"), _("Identifier of the last ended touch"),
_("Multitouch"), _("Mouse and touch/Multitouch"),
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "");
.SetHidden();
#endif
} }
} // namespace gd } // namespace gd

View File

@@ -14,16 +14,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinNetwork", "BuiltinNetwork",
_("Network"), _("Basic internet features"),
_("Features to send web requests, communicate with external \"APIs\" " _("Features to send web requests, communicate with external \"APIs\" "
"and other network related tasks."), "and other network related tasks."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/network") .SetExtensionHelpPath("/all-features/network");
.SetCategory("Network");
extension.AddInstructionOrExpressionGroupMetadata(_("Network"))
.SetIcon("res/actions/net24.png");
#if defined(GD_IDE_ONLY)
extension extension
.AddAction( .AddAction(
"SendRequest", "SendRequest",
@@ -33,7 +31,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
"as specified below, except if the server is configured to answer " "as specified below, except if the server is configured to answer "
"to all requests (cross-domain requests).", "to all requests (cross-domain requests).",
"Send _PARAM3_ request to _PARAM0__PARAM1_ with body: _PARAM2_", "Send _PARAM3_ request to _PARAM0__PARAM1_ with body: _PARAM2_",
"", _("Network"),
"res/actions/net24.png", "res/actions/net24.png",
"res/actions/net.png") "res/actions/net.png")
.AddParameter("string", "Host, with protocol") .AddParameter("string", "Host, with protocol")
@@ -48,7 +46,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
.AddParameter("string", "Content type", "", true) .AddParameter("string", "Content type", "", true)
.SetParameterLongDescription( .SetParameterLongDescription(
"If empty, \"application/x-www-form-urlencoded\" will be used.") "If empty, \"application/x-www-form-urlencoded\" will be used.")
.AddParameter("scenevar", "Response scene variable", "", true) .AddParameter("scenevar", "Reponse scene variable", "", true)
.SetParameterLongDescription( .SetParameterLongDescription(
"The response of the server will be stored, as a string, in this " "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 " "variable. If the server returns *JSON*, you may want to use the "
@@ -68,7 +66,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
"to all requests (cross-domain requests)."), "to all requests (cross-domain requests)."),
_("Send a _PARAM2_ request to _PARAM0_ with body: _PARAM1_, and " _("Send a _PARAM2_ request to _PARAM0_ with body: _PARAM1_, and "
"store the result in _PARAM4_ (or in _PARAM5_ in case of error)"), "store the result in _PARAM4_ (or in _PARAM5_ in case of error)"),
"", _("Network"),
"res/actions/net24.png", "res/actions/net24.png",
"res/actions/net.png") "res/actions/net.png")
.AddParameter("string", _("URL (API or web-page address)")) .AddParameter("string", _("URL (API or web-page address)"))
@@ -95,37 +93,20 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
"explore the results with a *structure variable*.")) "explore the results with a *structure variable*."))
.AddParameter( .AddParameter(
"scenevar", _("Variable where to store the error message"), "", true) "scenevar", _("Variable where to store the error message"), "", true)
.SetParameterLongDescription(_( .SetParameterLongDescription(
"Optional, only used if an error occurs. This will contain the " _("Optional, only used if an error occurs. This will contain the "
"[\"status " "error message (if request could not be sent) or the [\"status "
"code\"](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) " "code\"](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes), "
"if the server returns a status >= 400. If the request was not sent " "if the server returns a status >= 400."))
"at all (e.g. no internet or CORS issues), the variable will be set "
"to "
"\"REQUEST_NOT_SENT\"."))
.MarkAsComplex(); .MarkAsComplex();
extension
.AddAction("LaunchFile",
_("Open a URL (web page) or a file"),
_("This action launches the specified file or URL, in a "
"browser (or in a new tab if the game is using the Web "
"platform and is launched inside a browser)."),
_("Open URL _PARAM0_ in a browser (or new tab)"),
"",
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("URL (or filename)"))
.AddCodeOnlyParameter("currentScene", "")
.MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
"DownloadFile", "DownloadFile",
_("Download a file"), _("Download a file"),
_("Download a file from a web site"), _("Download a file from a web site"),
_("Download file _PARAM1_ from _PARAM0_ under the name of _PARAM2_"), _("Download file _PARAM1_ from _PARAM0_ under the name of _PARAM2_"),
"", _("Network"),
"res/actions/net24.png", "res/actions/net24.png",
"res/actions/net.png") "res/actions/net.png")
.AddParameter("string", _("Host (for example : http://www.website.com)")) .AddParameter("string", _("Host (for example : http://www.website.com)"))
@@ -143,11 +124,79 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
"terms of service of your game and if they player gave their " "terms of service of your game and if they player gave their "
"consent, depending on how your game/company handles this."), "consent, depending on how your game/company handles this."),
_("Enable analytics metrics: _PARAM1_"), _("Enable analytics metrics: _PARAM1_"),
"", _("Network"),
"res/actions/net24.png", "res/actions/net24.png",
"res/actions/net.png") "res/actions/net.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("yesorno", _("Enable the metrics?")); .AddParameter("yesorno", _("Enable the metrics?"));
extension
.AddAction(
"JSONToVariableStructure",
_("Convert JSON to a scene variable"),
_("Parse a JSON object and store it into a scene variable"),
_("Parse JSON string _PARAM0_ and store it into variable _PARAM1_"),
_("Network"),
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("scenevar", _("Variable where store the JSON object"))
.MarkAsAdvanced();
extension
.AddAction("JSONToGlobalVariableStructure",
_("Convert JSON to global variable"),
_("Parse a JSON object and store it into a global variable"),
_("Parse JSON string _PARAM0_ and store it into global "
"variable _PARAM1_"),
_("Network"),
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("globalvar",
_("Global variable where store the JSON object"))
.MarkAsAdvanced();
extension
.AddAction("JSONToObjectVariableStructure",
_("Convert JSON to object variable"),
_("Parse a JSON object and store it into an object variable"),
_("Parse JSON string _PARAM0_ and store it into variable "
"_PARAM2_ of _PARAM1_"),
_("Network"),
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("objectPtr", _("Object"))
.AddParameter("objectvar",
_("Object variable where store the JSON object"))
.MarkAsAdvanced();
extension
.AddStrExpression("ToJSON",
_("Convert scene variable to JSON"),
_("Convert a scene variable to JSON"),
_("Conversion"),
"res/conditions/toujours24.png")
.AddParameter("scenevar", _("Scene variable to be stringified"));
extension
.AddStrExpression("GlobalVarToJSON",
_("Convert global variable to JSON"),
_("Convert a global variable to JSON"),
_("Conversion"),
"res/conditions/toujours24.png")
.AddParameter("globalvar", _("The global variable to be stringified"));
extension
.AddStrExpression("ObjectVarToJSON",
_("Convert object variable to JSON"),
_("Convert an object variable to JSON"),
_("Conversion"),
"res/conditions/toujours24.png")
.AddParameter("objectPtr", _("The object with the variable"))
.AddParameter("objectvar", _("The object variable to be stringified"));
#endif
} }
} // namespace gd } // namespace gd

View File

@@ -14,19 +14,68 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinScene", "BuiltinScene",
_("Scene"), _("Scene management features"),
_("Actions and conditions to manipulate the scenes during the game."), _("Actions and conditions to manipulate the scenes during the game."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */); .SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
extension.AddInstructionOrExpressionGroupMetadata(_("Scene"))
.SetIcon("res/conditions/depart24.png"); #if defined(GD_IDE_ONLY)
extension
.AddExpression("Random",
_("Random integer"),
_("Random integer"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomInRange",
_("Random integer in range"),
_("Random integer in range"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomFloat",
_("Random float"),
_("Random float"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomFloatInRange",
_("Random float in range"),
_("Random float in range"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"));
extension
.AddExpression("RandomWithStep",
_("Random value in steps"),
_("Random value in steps"),
_("Random"),
"res/actions/position.png")
.SetHelpPath("/all-features/expressions")
.AddParameter("expression", _("Minimum value"))
.AddParameter("expression", _("Maximum value"))
.AddParameter("expression", _("Step"));
extension extension
.AddStrExpression("CurrentSceneName", .AddStrExpression("CurrentSceneName",
_("Current scene name"), _("Current scene name"),
_("Name of the current scene"), _("Name of the current scene"),
"", _("Scene"),
"res/actions/texte.png") "res/actions/texte.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
@@ -35,7 +84,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("At the beginning of the scene"), _("At the beginning of the scene"),
_("Is true only when scene just begins."), _("Is true only when scene just begins."),
_("At the beginning of the scene"), _("At the beginning of the scene"),
"", _("Scene"),
"res/conditions/depart24.png", "res/conditions/depart24.png",
"res/conditions/depart.png") "res/conditions/depart.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
@@ -47,32 +96,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Scene just resumed"), _("Scene just resumed"),
_("The scene has just resumed after being paused."), _("The scene has just resumed after being paused."),
_("Scene just resumed"), _("Scene just resumed"),
"", _("Scene"),
"res/conditions/depart24.png", "res/conditions/depart24.png",
"res/conditions/depart.png") "res/conditions/depart.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.MarkAsSimple(); .MarkAsSimple();
extension
.AddCondition("DoesSceneExist",
_("Does scene exist"),
_("Check if scene exists."),
_("Scene _PARAM1_ exists"),
"",
"res/actions/texte.png",
"res/actions/texte.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Name of the scene to check"))
.MarkAsSimple();
extension extension
.AddAction("Scene", .AddAction("Scene",
_("Change the scene"), _("Change the scene"),
_("Stop this scene and start the specified one instead."), _("Stop this scene and start the specified one instead."),
_("Change to scene _PARAM1_"), _("Change to scene _PARAM1_"),
"", _("Scene"),
"res/actions/replaceScene24.png", "res/actions/replaceScene24.png",
"res/actions/replaceScene.png") "res/actions/replaceScene.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
@@ -89,7 +125,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
"can use the \"Stop and go back to previous scene\" action " "can use the \"Stop and go back to previous scene\" action "
"to go back to this scene."), "to go back to this scene."),
_("Pause the scene and start _PARAM1_"), _("Pause the scene and start _PARAM1_"),
"", _("Scene"),
"res/actions/pushScene24.png", "res/actions/pushScene24.png",
"res/actions/pushScene.png") "res/actions/pushScene.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
@@ -104,7 +140,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Stop this scene and go back to the previous paused one.\nTo pause " _("Stop this scene and go back to the previous paused one.\nTo pause "
"a scene, use the \"Pause and start a new scene\" action."), "a scene, use the \"Pause and start a new scene\" action."),
_("Stop the scene and go back to the previous paused one"), _("Stop the scene and go back to the previous paused one"),
"", _("Scene"),
"res/actions/popScene24.png", "res/actions/popScene24.png",
"res/actions/popScene.png") "res/actions/popScene.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
@@ -116,7 +152,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("Quit the game"), _("Quit the game"),
_("Quit the game"), _("Quit the game"),
_("Quit the game"), _("Quit the game"),
"", _("Scene"),
"res/actions/quit24.png", "res/actions/quit24.png",
"res/actions/quit.png") "res/actions/quit.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
@@ -125,10 +161,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
extension extension
.AddAction("SceneBackground", .AddAction("SceneBackground",
_("Background color"), _("Change background color"),
_("Change the background color of the scene."), _("Change the background color of the scene."),
_("Set background color to _PARAM1_"), _("Set background color to _PARAM1_"),
"", _("Scene"),
"res/actions/background24.png", "res/actions/background24.png",
"res/actions/background.png") "res/actions/background.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
@@ -142,7 +178,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
_("mouse buttons must be taken " _("mouse buttons must be taken "
"into account even\nif the window is not active."), "into account even\nif the window is not active."),
_("Disable input when focus is lost: _PARAM1_"), _("Disable input when focus is lost: _PARAM1_"),
"", _("Scene"),
"res/actions/window24.png", "res/actions/window24.png",
"res/actions/window.png") "res/actions/window.png")
.SetHelpPath("/interface/scene-editor/events") .SetHelpPath("/interface/scene-editor/events")
@@ -151,18 +187,33 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddCondition( .AddCondition("Egal",
"HasGameJustResumed", _("Compare two numbers"),
_("Game has just resumed"), _("Compare the two numbers."),
_("Check if the game has just resumed from being hidden. It " _("_PARAM0_ _PARAM1_ _PARAM2_"),
"happens when the game tab is selected, a minimized window is " _("Other"),
"restored or the application is put back on front."), "res/conditions/egal24.png",
_("Game has just resumed"), "res/conditions/egal.png")
"", .SetHelpPath("/all-features/advanced-conditions")
"res/actions/window24.png", .AddParameter("expression", _("First expression"))
"res/actions/window.png") .AddParameter("relationalOperator", _("Sign of the test"))
.SetHelpPath("/interface/scene-editor/events") .AddParameter("expression", _("Second expression"))
.AddCodeOnlyParameter("currentScene", ""); .MarkAsAdvanced();
extension
.AddCondition("StrEqual",
_("Compare two strings"),
_("Compare the two strings."),
_("_PARAM0_ _PARAM1_ _PARAM2_"),
_("Other"),
"res/conditions/egal24.png",
"res/conditions/egal.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddParameter("string", _("First string expression"))
.AddParameter("relationalOperator", _("Sign of the test"))
.AddParameter("string", _("Second string expression"))
.MarkAsAdvanced();
#endif
} }
} // namespace gd } // namespace gd

View File

@@ -4,10 +4,8 @@
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h" #include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include "GDCore/CommonTools.h" #include "GDCore/CommonTools.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h" #include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include "GDCore/Serialization/SerializerElement.h" #include "GDCore/Serialization/SerializerElement.h"
@@ -31,15 +29,6 @@ const Sprite& Direction::GetSprite(std::size_t nb) const { return sprites[nb]; }
Sprite& Direction::GetSprite(std::size_t nb) { return sprites[nb]; } Sprite& Direction::GetSprite(std::size_t nb) { return sprites[nb]; }
const std::vector<gd::String>& Direction::GetSpriteNames() const {
static std::vector<gd::String> spriteNames;
spriteNames.clear();
for (std::size_t i = 0; i < sprites.size(); ++i) {
spriteNames.push_back(sprites[i].GetImageName());
}
return spriteNames;
}
void Direction::RemoveSprite(std::size_t index) { void Direction::RemoveSprite(std::size_t index) {
if (index < sprites.size()) sprites.erase(sprites.begin() + index); if (index < sprites.size()) sprites.erase(sprites.begin() + index);
} }
@@ -86,9 +75,11 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
SetTimeBetweenFrames( SetTimeBetweenFrames(
element.GetDoubleAttribute("timeBetweenFrames", 1, "tempsEntre")); element.GetDoubleAttribute("timeBetweenFrames", 1, "tempsEntre"));
SetLoop(element.GetBoolAttribute("looping", false, "boucle")); SetLoop(element.GetBoolAttribute("looping", false, "boucle"));
#if defined(GD_IDE_ONLY)
SetMetadata(element.HasAttribute("metadata") || element.HasChild("metadata") SetMetadata(element.HasAttribute("metadata") || element.HasChild("metadata")
? element.GetStringAttribute("metadata") ? element.GetStringAttribute("metadata")
: ""); : "");
#endif
const gd::SerializerElement& spritesElement = const gd::SerializerElement& spritesElement =
element.GetChild("sprites", 0, "Sprites"); element.GetChild("sprites", 0, "Sprites");
@@ -110,11 +101,11 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
.GetBoolAttribute("automatic", true)); .GetBoolAttribute("automatic", true));
if (spriteElement.HasChild("CustomCollisionMask")) if (spriteElement.HasChild("CustomCollisionMask"))
sprite.SetFullImageCollisionMask( sprite.SetCollisionMaskAutomatic(
!spriteElement.GetChild("CustomCollisionMask") !spriteElement.GetChild("CustomCollisionMask")
.GetBoolAttribute("custom", false)); .GetBoolAttribute("custom", false));
else else
sprite.SetFullImageCollisionMask( sprite.SetCollisionMaskAutomatic(
!spriteElement.GetBoolAttribute("hasCustomCollisionMask", false)); !spriteElement.GetBoolAttribute("hasCustomCollisionMask", false));
std::vector<Polygon2d> mask; std::vector<Polygon2d> mask;
@@ -132,7 +123,7 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
polygonElement.GetChild(k); polygonElement.GetChild(k);
polygon.vertices.push_back( polygon.vertices.push_back(
gd::Vector2f(verticeElement.GetDoubleAttribute("x"), sf::Vector2f(verticeElement.GetDoubleAttribute("x"),
verticeElement.GetDoubleAttribute("y"))); verticeElement.GetDoubleAttribute("y")));
} }
@@ -144,6 +135,7 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
} }
}; };
#if defined(GD_IDE_ONLY)
void SavePoint(const Point& point, gd::SerializerElement& element) { void SavePoint(const Point& point, gd::SerializerElement& element) {
element.SetAttribute("name", point.GetName()); element.SetAttribute("name", point.GetName());
element.SetAttribute("x", point.GetX()); element.SetAttribute("x", point.GetX());
@@ -173,7 +165,7 @@ void SaveSpritesDirection(const vector<Sprite>& sprites,
.SetAttribute("automatic", sprites[i].IsDefaultCenterPoint()); .SetAttribute("automatic", sprites[i].IsDefaultCenterPoint());
spriteElement.SetAttribute("hasCustomCollisionMask", spriteElement.SetAttribute("hasCustomCollisionMask",
!sprites[i].IsFullImageCollisionMask()); !sprites[i].IsCollisionMaskAutomatic());
gd::SerializerElement& collisionMaskElement = gd::SerializerElement& collisionMaskElement =
spriteElement.AddChild("customCollisionMask"); spriteElement.AddChild("customCollisionMask");
@@ -198,5 +190,6 @@ void Direction::SerializeTo(gd::SerializerElement& element) const {
if (!GetMetadata().empty()) element.SetAttribute("metadata", GetMetadata()); if (!GetMetadata().empty()) element.SetAttribute("metadata", GetMetadata());
SaveSpritesDirection(sprites, element.AddChild("sprites")); SaveSpritesDirection(sprites, element.AddChild("sprites"));
} }
#endif
} // namespace gd } // namespace gd

View File

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

View File

@@ -31,7 +31,7 @@ class GD_CORE_API Point {
/** /**
* Change point position. * Change point position.
*/ */
void SetXY(double x_, double y_) { void SetXY(float x_, float y_) {
x = x_; x = x_;
y = y_; y = y_;
} }
@@ -39,27 +39,27 @@ class GD_CORE_API Point {
/** /**
* Change point X position. * Change point X position.
*/ */
void SetX(double x_) { x = x_; } void SetX(float x_) { x = x_; }
/** /**
* Change point Y position. * Change point Y position.
*/ */
void SetY(double y_) { y = y_; } void SetY(float y_) { y = y_; }
/** /**
* Get point X position. * Get point X position.
*/ */
double GetX() const { return x; } float GetX() const { return x; }
/** /**
* Get point Y position. * Get point Y position.
*/ */
double GetY() const { return y; } float GetY() const { return y; }
private: private:
gd::String name; gd::String name;
double x; float x;
double y; float y;
}; };
#endif // GDCORE_POINT_H #endif // GDCORE_POINT_H

View File

@@ -4,15 +4,13 @@
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#include "Polygon2d.h" #include "Polygon2d.h"
#include <SFML/System/Vector2.hpp>
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
#include "GDCore/Vector2.h" void Polygon2d::Rotate(float angle) {
float t, cosa = cos(-angle),
void Polygon2d::Rotate(double angle) { sina = sin(-angle); // We want a clockwise rotation
double t, cosa = cos(-angle),
sina = sin(-angle); // We want a clockwise rotation
for (std::size_t i = 0; i < vertices.size(); ++i) { for (std::size_t i = 0; i < vertices.size(); ++i) {
t = vertices[i].x; t = vertices[i].x;
@@ -21,7 +19,7 @@ void Polygon2d::Rotate(double angle) {
} }
} }
void Polygon2d::Move(double x, double y) { void Polygon2d::Move(float x, float y) {
for (std::size_t i = 0; i < vertices.size(); i++) { for (std::size_t i = 0; i < vertices.size(); i++) {
vertices[i].x += x; vertices[i].x += x;
vertices[i].y += y; vertices[i].y += y;
@@ -30,7 +28,7 @@ void Polygon2d::Move(double x, double y) {
} }
void Polygon2d::ComputeEdges() const { void Polygon2d::ComputeEdges() const {
gd::Vector2f v1, v2; sf::Vector2f v1, v2;
edges.clear(); edges.clear();
for (std::size_t i = 0; i < vertices.size(); i++) { for (std::size_t i = 0; i < vertices.size(); i++) {
@@ -52,20 +50,20 @@ bool Polygon2d::IsConvex() const {
(edges[0].x * edges[0 + 1].y - edges[0].y * edges[0 + 1].x) > 0; (edges[0].x * edges[0 + 1].y - edges[0].y * edges[0 + 1].x) > 0;
for (std::size_t i = 1; i < edges.size() - 1; ++i) { for (std::size_t i = 1; i < edges.size() - 1; ++i) {
double zCrossProduct = float zCrossProduct =
edges[i].x * edges[i + 1].y - edges[i].y * edges[i + 1].x; edges[i].x * edges[i + 1].y - edges[i].y * edges[i + 1].x;
if ((zCrossProduct > 0) != zProductIsPositive) return false; if ((zCrossProduct > 0) != zProductIsPositive) return false;
} }
double lastZCrossProduct = edges[edges.size() - 1].x * edges[0].y - float lastZCrossProduct = edges[edges.size() - 1].x * edges[0].y -
edges[edges.size() - 1].y * edges[0].x; edges[edges.size() - 1].y * edges[0].x;
if ((lastZCrossProduct > 0) != zProductIsPositive) return false; if ((lastZCrossProduct > 0) != zProductIsPositive) return false;
return true; return true;
} }
gd::Vector2f Polygon2d::ComputeCenter() const { sf::Vector2f Polygon2d::ComputeCenter() const {
gd::Vector2f center; sf::Vector2f center;
for (std::size_t i = 0; i < vertices.size(); i++) { for (std::size_t i = 0; i < vertices.size(); i++) {
center.x += vertices[i].x; center.x += vertices[i].x;
@@ -77,12 +75,12 @@ gd::Vector2f Polygon2d::ComputeCenter() const {
return center; return center;
} }
Polygon2d Polygon2d::CreateRectangle(double width, double height) { Polygon2d Polygon2d::CreateRectangle(float width, float height) {
Polygon2d rect; Polygon2d rect;
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, -height / 2.0f)); rect.vertices.push_back(sf::Vector2f(-width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, -height / 2.0f)); rect.vertices.push_back(sf::Vector2f(+width / 2.0f, -height / 2.0f));
rect.vertices.push_back(gd::Vector2f(+width / 2.0f, +height / 2.0f)); rect.vertices.push_back(sf::Vector2f(+width / 2.0f, +height / 2.0f));
rect.vertices.push_back(gd::Vector2f(-width / 2.0f, +height / 2.0f)); rect.vertices.push_back(sf::Vector2f(-width / 2.0f, +height / 2.0f));
return rect; return rect;
} }

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