Compare commits

..

2 Commits

Author SHA1 Message Date
AlexandreSi
329340cb47 Use correct reference to layer 2023-05-19 09:57:11 +02:00
AlexandreSi
1ab96b3d8e Remove forgotten ref 2023-05-18 17:30:10 +02:00
2830 changed files with 167292 additions and 368482 deletions

View File

@@ -11,24 +11,13 @@
version: 2.1
orbs:
aws-cli: circleci/aws-cli@2.0.6
macos: circleci/macos@2.5.1 # For Rosetta (see below)
node: circleci/node@5.2.0 # For a recent npm version (see below)
jobs:
# Build the **entire** app for macOS.
build-macos:
macos:
xcode: 14.2.0
resource_class: macos.m1.large.gen1
xcode: 12.5.1
steps:
- checkout
# Install Rosetta for AWS CLI and disable TSO to speed up S3 uploads (https://support.circleci.com/hc/en-us/articles/19334402064027-Troubleshooting-slow-uploads-to-S3-for-jobs-using-an-m1-macOS-resource-class)
- macos/install-rosetta
- run: sudo sysctl net.inet.tcp.tso=0
# Install a recent version of npm to workaround a notarization issue because of a symlink made by npm: https://github.com/electron-userland/electron-builder/issues/7755
# Node.js v20.14.0 comes with npm v10.7.0.
- node/install:
node-version: "20.14.0"
# System dependencies (for Emscripten and upload)
- run:
@@ -41,7 +30,7 @@ jobs:
- 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 ..
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# GDevelop.js dependencies
- restore_cache:
@@ -73,14 +62,13 @@ jobs:
# 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
command: export NODE_OPTIONS="--max-old-space-size=7168" && cd newIDE/electron-app && npm run build -- --mac --publish=never
- run:
name: Clean dist folder to keep only installers/binaries.
command: rm -rf "newIDE/electron-app/dist/mac-universal/GDevelop 5.app"
command: rm -rf "newIDE/electron-app/dist/mac/GDevelop 5.app" && rm -rf "newIDE/electron-app/dist/mac-arm64/GDevelop 5.app"
# Upload artifacts (CircleCI)
- store_artifacts:
@@ -113,12 +101,12 @@ jobs:
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
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 ..
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 system dependencies for Electron builder
@@ -138,8 +126,7 @@ jobs:
# 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 ..
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
# GDevelop IDE dependencies (after building GDevelop.js to avoid downloading a pre-built version)
- run:
@@ -176,7 +163,6 @@ jobs:
# Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use).
build-gdevelop_js-wasm-only:
resource_class: medium+ # Compilation time decrease linearly with the number of CPUs, but not linking (so "large" does not speedup total build time).
docker:
- image: cimg/node:16.13
@@ -192,12 +178,12 @@ jobs:
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
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 ..
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# GDevelop.js dependencies
- restore_cache:
@@ -213,8 +199,7 @@ jobs:
# 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 ..
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
- save_cache:
paths:
@@ -233,83 +218,10 @@ jobs:
name: Deploy to S3 (latest)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/latest/
# Build the WebAssembly library with clang-tidy and memory sanitizers.
build-gdevelop_js-debug-sanitizers-and-extra-checks:
resource_class: xlarge # Total time decrease linearly with the number of CPUs.
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 dependencies for clang-tidy v19
command: wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && sudo ./llvm.sh 19 && sudo apt install clang-tidy-19
- 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
- run:
name: Build GDevelop.js ('debug-sanitizers' variant)
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build -- --variant=debug-sanitizers
- run:
name: Run clang-tidy
command: cd GDevelop.js && npm run lint
- run:
name: Run tests
command: cd GDevelop.js && npm run test -- --maxWorkers=4
# 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)/variant/debug-sanitizers/commit/$(git rev-parse HEAD)/
workflows:
gdevelop_js-wasm:
jobs:
- build-gdevelop_js-wasm-only
gdevelop_js-wasm-extra-checks:
jobs:
- build-gdevelop_js-debug-sanitizers-and-extra-checks:
# Extra checks are resource intensive so don't all run them.
filters:
branches:
only:
- master
- /experimental-build.*/
builds:
jobs:
- build-gdevelop_js-wasm-only
- build-macos:
filters:
branches:

View File

@@ -1,4 +0,0 @@
Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,-cppcoreguidelines-explicit-virtual-functions,-cppcoreguidelines-avoid-const-or-ref-data-members,-cppcoreguidelines-special-member-functions,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-non-private-member-variables-in-classes,-cppcoreguidelines-owning-memory,-cppcoreguidelines-virtual-class-destructor,-clang-analyzer-optin.performance.Padding,-cppcoreguidelines-narrowing-conversions'
WarningsAsErrors: 'cppcoreguidelines-pro-type-member-init, clang-analyzer-optin.cplusplus.UninitializedObject'
HeaderFilterRegex: '.*'
FormatStyle: none

View File

@@ -1,14 +0,0 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"onCreateCommand": "cd newIDE/app && npm install && cd ../electron-app && npm install",
"forwardPorts": [3000],
"customizations": {
"vscode": {
"extensions": [
"esbenp.prettier-vscode",
"ms-vscode.cpptools",
"flowtype.flow-for-vscode"
]
}
}
}

4
.gitattributes vendored
View File

@@ -1,12 +1,12 @@
Core/GDCore/Serialization/rapidjson/rapidjson.h/* linguist-vendored
Core/GDCore/TinyXml/* linguist-vendored
Extensions/ParticleSystem/SPARK/* linguist-vendored
Extensions/PhysicsBehavior/Box2D/* linguist-vendored
Extensions/PhysicsBehavior/box2djs/* linguist-vendored
Extensions/Physics2Behavior/box2d.js linguist-vendored
Extensions/Physics3DBehavior/*.wasm-compat.js linguist-vendored
Extensions/BBText/pixi-multistyle-text/* linguist-vendored
Extensions/P2P/A_peer.js linguist-vendored
Extensions/Multiplayer/peer.js linguist-vendored
Extensions/Shopify/shopify-buy.umd.polyfilled.min.js linguist-vendored
Extensions/TileMap/pako/* linguist-vendored
Extensions/TileMap/pixi-tilemap/* linguist-vendored
Extensions/TweenBehavior/shifty.js linguist-vendored

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.

View File

@@ -2,21 +2,18 @@ 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
- 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: |
@@ -30,7 +27,6 @@ body:
validations:
required: true
- type: dropdown
id: platform
attributes:
label: GDevelop platform
description: Which platform of GDevelop are you using?
@@ -42,7 +38,6 @@ body:
validations:
required: true
- type: input
id: gdevelop_version
attributes:
label: GDevelop version
description: |
@@ -52,7 +47,6 @@ body:
validations:
required: true
- type: textarea
id: platform_info
attributes:
label: Platform info
value: |
@@ -72,7 +66,6 @@ body:
</details>
- type: textarea
id: additional_context
attributes:
label: Additional context
description: Add any other context about the problem here.

View File

@@ -9,10 +9,6 @@ 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:
@@ -21,23 +17,31 @@ 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
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.BUILD_STORYBOOK_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.BUILD_STORYBOOK_AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- uses: actions/checkout@v2
with:
fetch-depth: 50
# Cache npm dependencies to speed up the workflow
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-newIDE-app-node_modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
- name: Install newIDE dependencies
run: npm install
working-directory: newIDE/app

View File

@@ -4,10 +4,6 @@ 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:
@@ -15,18 +11,26 @@ 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"
- uses: actions/checkout@v2
# Cache npm dependencies to speed up the workflow
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-newIDE-app-node_modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
- name: Install gettext
run: sudo apt update && sudo apt install gettext -y
- name: Install newIDE dependencies
run: npm ci
run: npm install
working-directory: newIDE/app
- name: Extract translations

View File

@@ -1,22 +0,0 @@
# This worflow notifies arthuro555's gdcore-tools repository when a new release is published.
#
# This is used to allow gdcore-tools, a library to use GDCore outside of GDevelop,
# to attempt to automatically build, test, and publish a release for the new
# GDevelop version.
name: Trigger gdcore-tools pipeline
on:
release:
types: [published]
jobs:
dispatch-event:
runs-on: ubuntu-latest
steps:
- name: Repository Dispatch
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.GDCORE_TOOLS_PAT }}
repository: arthuro555/gdcore-tools
event-type: gdevelop-release
client-payload: '{"release": ${{ toJson(github.event.release) }}}'

View File

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

View File

@@ -1,53 +1,29 @@
name: GDevelop Issues automatic workflow
on:
pull_request:
types:
- opened
- reopened
- synchronize
types: [opened]
jobs:
read-locales-metadata:
if: github.event.pull_request.title == '[Auto PR] Update translations'
if: contains(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"
- name: Read and format locales metadata
run: |
LANS=($(git diff HEAD^ HEAD --unified=5 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\s+\"languageName" | sed -E "s/^ *\"languageName\": \"//g" | sed -E "s/\",//g" | sed -E "s/ /_/g"))
ADDS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\+\s*\"translationRatio\"" | sed -E "s/^\+ *\"translationRatio\": //g"))
SUBS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\-\s*\"translationRatio\"" | sed -E "s/^\- *\"translationRatio\": //g"))
touch sumup.txt
for index in ${!ADDS[@]}; do
echo ${LANS[index]} | sed -E "s/_/ /g" >> sumup.txt
DELTA=$(bc <<< "scale=2;(${ADDS[index]}-${SUBS[index]})*100/1")
echo $DELTA % >> sumup.txt
done
- name: Store sumup in outputs
id: sumup
run: echo "::set-output name=sumupFileContent::$(cat sumup.txt)"
- name: Autocomment pull request with sumup
uses: peter-evans/create-or-update-comment@v1
with:
issue-number: ${{ github.event.number }}
body: ${{ steps.sumup.outputs.sumupFileContent}}
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -7,8 +7,6 @@ on:
push:
branches:
- master
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab.
workflow_dispatch:
@@ -16,12 +14,20 @@ jobs:
update-translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 20
cache: "npm"
cache-dependency-path: "newIDE/app/package-lock.json"
node-version: 16
- uses: actions/checkout@v2
# Cache npm dependencies to speed up the workflow
- name: Cache node modules
uses: actions/cache@v2
env:
cache-name: cache-newIDE-app-node_modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
- name: Install gettext
run: sudo apt update && sudo apt install gettext -y
@@ -58,7 +64,7 @@ jobs:
working-directory: newIDE/app
- name: Create a Pull Request with the changes
uses: peter-evans/create-pull-request@v6
uses: peter-evans/create-pull-request@v3.10.1
with:
commit-message: Update translations [skip ci]
branch: chore/update-translations

View File

@@ -14,7 +14,7 @@ tasks:
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 ..
git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
cd GDevelop.js
npm install
source ../emsdk/emsdk_env.sh && npm run build -- --dev

View File

@@ -56,7 +56,6 @@ blocks:
- name: GDJS typing and documentation generation
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)
- cache restore GDJS-tests-node_modules-$SEMAPHORE_GIT_BRANCH-revision-$(checksum GDJS/tests/package-lock.json)
- cd GDJS

View File

@@ -17,11 +17,11 @@ cache:
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- ubuntu-toolchain-r-test
packages:
# Build dependencies:
- cmake
- p7zip-full
# Build dependencies:
- cmake
- p7zip-full
before_install:
# This workaround is required to avoid libstdc++ errors (Emscripten requires a recent version of libstdc++)
@@ -29,48 +29,47 @@ before_install:
- sudo dpkg --force-all -i libstdc++6
install:
# Ensure we use a recent version of Node.js (and npm).
# Ensure we use a recent version of Node.js (and npm).
- nvm install v16 && nvm use v16
#Compile the tests only for GDCore
#Compile the tests only for GDCore
- mkdir .build-tests
- cd .build-tests
- cmake -DBUILD_GDJS=FALSE -DBUILD_TESTS=TRUE -DCMAKE_CXX_COMPILER=$(which $CXX) -DCMAKE_C_COMPILER=$(which $CC) ..
- make -j 4
- cd ..
# Install Emscripten (for GDevelop.js)
# Specify the tag for the core repository to avois breaking changes.
- git clone --depth 1 --branch 3.1.21 https://github.com/juj/emsdk.git
- cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd ..
# Install GDevelop.js dependencies
# Install Emscripten (for GDevelop.js)
- git clone https://github.com/juj/emsdk.git
- cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# Install GDevelop.js dependencies
- cd GDevelop.js && npm install && cd ..
# Build GDevelop.js
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build)
# Build GDevelop.js
# (in a subshell to avoid Emscripten polluting the Node.js and npm version for the rest of the build)
- (set -e; cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && cd ..)
# Install newIDE tests dependencies
# Install newIDE tests dependencies
- npm -v
- cd newIDE/app && npm install
- cd ../..
# Install GDJS tests dependencies
# Install GDJS tests dependencies
- cd GDJS && npm install && cd tests && npm install
- cd ../..
script:
# GDCore tests:
# GDCore tests:
- cd .build-tests
- Core/GDCore_tests
- cd ..
# GDevelop.js tests
# GDevelop.js tests
- cd GDevelop.js
- npm test
- cd ..
# newIDE tests:
# newIDE tests:
- cd newIDE/app
- npm test
- npm run flow
- npm run check-format
- npm run check-script-types
- cd ../..
# GDJS tests:
# GDJS tests:
- cd GDJS
- npm run check-format
- cd ..

View File

@@ -107,7 +107,7 @@
"description": "Define a parameter in a GDevelop extension definition.",
"prefix": "gdparam",
"body": [
".addParameter('${1|string,expression,object,behavior,yesorno,stringWithSelector,scenevar,globalvar,objectvar,objectList,objectListWithoutPicking,color,key,sceneName,file,layer,relationalOperator,operator,trueorfalse,musicfile,soundfile,mouse,passwordjoyaxis,camera,objectPtr,forceMultiplier|}', '${2:Parameter description}', '${3:Optional parameter data}', /*parameterIsOptional=*/${4|false,true|})"
".addParameter('${1|string,expression,object,behavior,yesorno,stringWithSelector,scenevar,globalvar,objectvar,objectList,objectListWithoutPicking,color,key,sceneName,file,layer,relationalOperator,operator,trueorfalse,musicfile,soundfile,police,mouse,passwordjoyaxis,camera,objectPtr,forceMultiplier|}', '${2:Parameter description}', '${3:Optional parameter data}', /*parameterIsOptional=*/${4|false,true|})"
]
},
"Add code only parameter": {

259
.vscode/settings.json vendored
View File

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

1
.vscode/tasks.json vendored
View File

@@ -8,7 +8,6 @@
"group": "build",
"label": "Start development server",
"detail": "Starts the GDevelop development server.",
"options": { "env": { "NODE_OPTIONS": "--max-old-space-size=8192" } },
"problemMatcher": [
{
"owner": "cra",

View File

@@ -1,106 +1,100 @@
# This is the CMake file used to build GDevelop.
# For more information, see the README.md file.
#This is the CMake file used to build GDevelop.
#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
include(scripts/CMakeClangUtils.txt) # To add clang-format and clang-tidy support to a target
# Macro for defining an option
macro(gd_set_option var default type docstring)
if(NOT DEFINED ${var})
set(${var} ${default})
endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
if(NOT DEFINED ${var})
set(${var} ${default})
endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
endmacro()
# Set options
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library")
gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform")
gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions")
gd_set_option(BUILD_TESTS TRUE BOOL "TRUE to build the tests")
# 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).
if(NOT WIN32)
if(NOT APPLE)
gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed")
else()
gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed")
endif()
#Setting up installation directory, for Linux (has to be done before "project" command).
IF(NOT WIN32)
if (NOT APPLE)
gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed")
ELSE()
gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed")
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")
endif()
ENDIF()
project(GDevelop)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS)
set(CMAKE_SKIP_BUILD_RPATH TRUE) # Avoid errors when packaging for linux.
endif()
if(APPLE)
IF(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS)
SET(CMAKE_SKIP_BUILD_RPATH TRUE) #Avoid errors when packaging for linux.
ENDIF()
IF(APPLE)
set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
set(CMAKE_INSTALL_RPATH ".")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
add_compile_options(
-D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_
-Wno-potentially-evaluated-expression)
endif()
# Sanity checks
if("${CMAKE_BUILD_TYPE}" STREQUAL "")
message(STATUS "CMAKE_BUILD_TYPE is empty, assuming build type is Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
ENDIF()
#Sanity checks
IF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
message( "CMAKE_BUILD_TYPE is empty, assuming build type is Release" )
set(CMAKE_BUILD_TYPE Release)
endif()
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()
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
set(CMAKE_CXX_STANDARD 11) # Upgrading to C++17 should be tried.
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(CheckCXXCompilerFlag)
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
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Activate as much warnings as possible to avoid errors like
# uninitialized variables or other hard to debug bugs.
add_compile_options(
-Wall
-Wextra
-Wuninitialized
-Wconditional-uninitialized
-Wno-unknown-warning-option
-Wno-reorder-ctor
-Wno-reorder
-Wno-unused-parameter
-Wno-pessimizing-move
-Wno-unused-variable # Not a good style, but not a risk
-Wno-unused-private-field
-Wno-ignored-qualifiers # Not a risk
-Wno-sign-compare # Not a big risk
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder-ctor -Wno-reorder -Wno-pessimizing-move -Wno-unused-variable -Wno-unused-private-field")
# Make as much warnings considered as errors as possible (only one for now).
-Werror=return-stack-address
-Werror=return-type)
# Make as much warnings considered as errors as possible (only one for now).
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-stack-address")
endif()
# Define common directories:
#Define common directories:
set(GD_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
# Add all the CMakeLists:
add_subdirectory(ExtLibs)
if(BUILD_CORE)
add_subdirectory(Core)
endif()
if(BUILD_GDJS)
add_subdirectory(GDJS)
endif()
if(EMSCRIPTEN)
add_subdirectory(GDevelop.js)
endif()
if(BUILD_EXTENSIONS)
add_subdirectory(Extensions)
endif()
#Add all the CMakeLists:
ADD_SUBDIRECTORY(ExtLibs)
IF(BUILD_CORE)
ADD_SUBDIRECTORY(Core)
ENDIF()
IF(BUILD_GDJS)
ADD_SUBDIRECTORY(GDJS)
ENDIF()
IF(EMSCRIPTEN)
ADD_SUBDIRECTORY(GDevelop.js)
ENDIF()
IF(BUILD_EXTENSIONS)
ADD_SUBDIRECTORY(Extensions)
ENDIF()

View File

@@ -1,103 +1,83 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0015 NEW)
project(GDCore)
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_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
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_C_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_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME} PARENT_SCOPE)
# Create VersionPriv.h - only useful for testing.
if (NOT EMSCRIPTEN)
file(WRITE "${GD_base_dir}/Core/GDCore/Tools/VersionPriv.h" "#define GD_VERSION_STRING \"0.0.0-0\"")
endif()
#Dependencies on external libraries:
###
# Dependencies on external libraries:
#
#Defines
###
add_definitions( -DGD_IDE_ONLY )
IF (EMSCRIPTEN)
add_definitions( -DEMSCRIPTEN )
ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES "Debug")
add_definitions( -DDEBUG )
ELSE()
add_definitions( -DRELEASE )
ENDIF()
# Defines
#
add_definitions(-DGD_IDE_ONLY)
if(EMSCRIPTEN)
add_definitions(-DEMSCRIPTEN)
endif()
if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
add_definitions(-DDEBUG)
else()
add_definitions(-DRELEASE)
endif()
IF(WIN32)
add_definitions( -DWINDOWS )
add_definitions( "-DGD_CORE_API=__declspec(dllexport)" )
add_definitions( -D__GNUWIN32__ )
ELSE()
IF(APPLE)
add_definitions( -DMACOS )
ELSE()
add_definitions( -DLINUX )
ENDIF()
add_definitions( -DGD_API= )
add_definitions( -DGD_CORE_API= )
ENDIF(WIN32)
if(WIN32)
add_definitions(-DWINDOWS)
add_definitions("-DGD_CORE_API=__declspec(dllexport)")
add_definitions(-D__GNUWIN32__)
else()
if(APPLE)
add_definitions(-DMACOS)
else()
add_definitions(-DLINUX)
endif()
add_definitions(-DGD_API=)
add_definitions(-DGD_CORE_API=)
endif()
# The target
#
#The target
###
include_directories(.)
file(
GLOB_RECURSE
source_files
GDCore/*)
file(GLOB_RECURSE source_files GDCore/*)
file(
GLOB_RECURSE
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")
file(GLOB_RECURSE 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}")
if(EMSCRIPTEN)
IF(EMSCRIPTEN)
# Emscripten treats all libraries as static libraries
add_library(GDCore STATIC ${source_files})
else()
ELSE()
add_library(GDCore SHARED ${source_files})
endif()
if(EMSCRIPTEN)
ENDIF()
IF(EMSCRIPTEN)
set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
elseif(WIN32)
ELSEIF(WIN32)
set_target_properties(GDCore PROPERTIES PREFIX "")
else()
ELSE()
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(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})
# Tests
#
#Tests
###
if(BUILD_TESTS)
file(
GLOB_RECURSE
test_source_files
tests/*)
GLOB_RECURSE
test_source_files
tests/*
)
add_executable(GDCore_tests ${test_source_files})
set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) # Allow finding dependencies directly from build path on Mac OS X.
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 ${CMAKE_DL_LIBS})
endif()

View File

@@ -58,7 +58,99 @@
* Common functions and tools for programming.
*/
/**
* \defgroup TinyXml Integrated TinyXml library
*
* See the full documentation of TinyXml [here](http://www.grinninglizard.com/tinyxmldocs/index.html).
*/
/**
* \defgroup SpriteObjectExtension Standard Sprite Object extension
* \ingroup BuiltinExtensions
*/
*/
/**
* \class TiXmlAttribute
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlAttributeSet
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlBase
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlComment
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlCursor
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlDeclaration
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlDocument
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlElement
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlHandle
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlNode
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlOutStream
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlParsingData
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlPrinter
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlString
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlText
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlUnknown
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/
/**
* \class TiXmlVisitor
* \brief Part of the tinyxml library
* \ingroup TinyXml
*/

View File

@@ -45,41 +45,10 @@ ForEachChildVariableEvent::GetAllActionsVectors() const {
return allActions;
}
vector<pair<gd::Expression*, gd::ParameterMetadata> >
ForEachChildVariableEvent::GetAllExpressionsWithMetadata() {
vector<pair<gd::Expression*, gd::ParameterMetadata> >
allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("variable");
metadata.SetExtraInfo("AllowUndeclaredVariable");
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("variable");
metadata.SetExtraInfo("AllowUndeclaredVariable");
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 {
element.AddChild("iterableVariableName").SetValue(iterableVariableName.GetPlainString());
element.AddChild("valueIteratorVariableName").SetValue(valueIteratorVariableName.GetPlainString());
element.AddChild("keyIteratorVariableName").SetValue(keyIteratorVariableName.GetPlainString());
element.AddChild("iterableVariableName").SetValue(iterableVariableName);
element.AddChild("valueIteratorVariableName").SetValue(valueIteratorVariableName);
element.AddChild("keyIteratorVariableName").SetValue(keyIteratorVariableName);
gd::EventsListSerialization::SerializeInstructionsTo(
conditions, element.AddChild("conditions"));
gd::EventsListSerialization::SerializeInstructionsTo(

View File

@@ -8,7 +8,6 @@
#define FOREACHCHILDVARIABLEEVENT_H
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Expression.h"
namespace gd {
class Instruction;
class Project;
@@ -45,7 +44,7 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
*
* 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.
@@ -57,15 +56,15 @@ class GD_CORE_API ForEachChildVariableEvent : public gd::BaseEvent {
/**
* \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.
*/
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.
*
* 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.
*/
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.
*
* 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.
*/
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.
*
* 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.
*/
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*> 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 UnserializeFrom(gd::Project& project,
const SerializerElement& element);
private:
gd::Expression valueIteratorVariableName;
gd::Expression keyIteratorVariableName;
gd::Expression iterableVariableName;
gd::String valueIteratorVariableName;
gd::String keyIteratorVariableName;
gd::String iterableVariableName;
gd::InstructionsList conditions;
gd::InstructionsList actions;
gd::EventsList events;

View File

@@ -8,13 +8,14 @@
#include "GDCore/Events/Serialization.h"
#include "GDCore/Events/Tools/EventsCodeNameMangler.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/TinyXml/tinyxml.h"
using namespace std;
namespace gd {
ForEachEvent::ForEachEvent()
: BaseEvent(), objectsToPick("") {}
: BaseEvent(), objectsToPick(""), objectsToPickSelected(false) {}
vector<gd::InstructionsList*> ForEachEvent::GetAllConditionsVectors() {
vector<gd::InstructionsList*> allConditions;

View File

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

View File

@@ -10,6 +10,7 @@
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Serialization.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/TinyXml/tinyxml.h"
using namespace std;

View File

@@ -131,40 +131,34 @@ void LinkEvent::SerializeTo(SerializerElement& element) const {
void LinkEvent::UnserializeFrom(gd::Project& project,
const SerializerElement& element) {
SerializerElement& includeElement = element.GetChild("include", 0, "Limites");
SetTarget(element.GetChild("target", 0, "Scene").GetValue().GetString());
// Compatibility with GD <= 5
if (element.HasChild("include", "Limites")) {
SerializerElement& includeElement = element.GetChild("include", 0, "Limites");
if (includeElement.HasAttribute("includeAll")) {
// Compatibility with GDevelop <= 4.0.92
if (includeElement.GetBoolAttribute("includeAll", true)) {
SetIncludeAllEvents();
} else {
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
includeElement.GetIntAttribute("end"));
}
if (includeElement.HasAttribute("includeAll")) {
// Compatibility with GDevelop <= 4.0.92
if (includeElement.GetBoolAttribute("includeAll", true)) {
SetIncludeAllEvents();
} else {
// GDevelop > 4.0.92
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"));
SetIncludeStartAndEnd(includeElement.GetIntAttribute("start"),
includeElement.GetIntAttribute("end"));
}
} else {
// Since GDevelop 5, links always include all events.
SetIncludeAllEvents();
// GDevelop > 4.0.92
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) ||
return BaseEvent::AcceptVisitor(eventVisitor) |
eventVisitor.VisitLinkEvent(*this);
}

View File

@@ -35,7 +35,7 @@ vector<pair<gd::Expression*, gd::ParameterMetadata> >
RepeatEvent::GetAllExpressionsWithMetadata() {
vector<pair<gd::Expression*, gd::ParameterMetadata> >
allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("number");
auto metadata = gd::ParameterMetadata().SetType("expression");
allExpressionsWithMetadata.push_back(
std::make_pair(&repeatNumberExpression, metadata));
@@ -61,7 +61,7 @@ vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
RepeatEvent::GetAllExpressionsWithMetadata() const {
vector<pair<const gd::Expression*, const gd::ParameterMetadata> >
allExpressionsWithMetadata;
auto metadata = gd::ParameterMetadata().SetType("number");
auto metadata = gd::ParameterMetadata().SetType("expression");
allExpressionsWithMetadata.push_back(
std::make_pair(&repeatNumberExpression, metadata));

View File

@@ -4,8 +4,8 @@
* reserved. This project is released under the MIT License.
*/
#pragma once
#ifndef GDCORE_REPEATEVENT_H
#define GDCORE_REPEATEVENT_H
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
namespace gd {
@@ -36,10 +36,10 @@ class GD_CORE_API RepeatEvent : public gd::BaseEvent {
const gd::InstructionsList& GetActions() const { return actions; };
gd::InstructionsList& GetActions() { return actions; };
const gd::Expression& GetRepeatExpression() const {
return repeatNumberExpression;
const gd::String& GetRepeatExpression() const {
return repeatNumberExpression.GetPlainString();
};
void SetRepeatExpressionPlainString(gd::String repeatNumberExpression_) {
void SetRepeatExpression(gd::String repeatNumberExpression_) {
repeatNumberExpression = gd::Expression(repeatNumberExpression_);
};
@@ -68,3 +68,5 @@ class GD_CORE_API RepeatEvent : public gd::BaseEvent {
};
} // namespace gd
#endif // GDCORE_REPEATEVENT_H

View File

@@ -15,8 +15,7 @@ using namespace std;
namespace gd {
StandardEvent::StandardEvent()
: BaseEvent(), variables(gd::VariablesContainer::SourceType::Local) {}
StandardEvent::StandardEvent() : BaseEvent() {}
StandardEvent::~StandardEvent(){};
@@ -58,9 +57,6 @@ void StandardEvent::SerializeTo(SerializerElement& element) const {
if (!events.IsEmpty())
gd::EventsListSerialization::SerializeEventsTo(events,
element.AddChild("events"));
if (HasVariables()) {
variables.SerializeTo(element.AddChild("variables"));
}
}
void StandardEvent::UnserializeFrom(gd::Project& project,
@@ -75,11 +71,6 @@ void StandardEvent::UnserializeFrom(gd::Project& project,
gd::EventsListSerialization::UnserializeEventsFrom(
project, events, element.GetChild("events", 0, "Events"));
}
variables.Clear();
if (element.HasChild("variables")) {
variables.UnserializeFrom(element.GetChild("variables"));
}
}
} // namespace gd

View File

@@ -4,13 +4,13 @@
* reserved. This project is released under the MIT License.
*/
#pragma once
#if defined(GD_IDE_ONLY)
#ifndef GDCORE_STANDARDEVENT_H
#define GDCORE_STANDARDEVENT_H
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h"
#include "GDCore/Project/VariablesContainer.h"
namespace gd {
class Instruction;
class Project;
@@ -33,10 +33,6 @@ class GD_CORE_API StandardEvent : public gd::BaseEvent {
virtual const gd::EventsList& GetSubEvents() const { return events; };
virtual gd::EventsList& GetSubEvents() { return events; };
virtual bool CanHaveVariables() const { return true; }
virtual const gd::VariablesContainer& GetVariables() const { return variables; };
virtual gd::VariablesContainer& GetVariables() { return variables; };
const gd::InstructionsList& GetConditions() const { return conditions; };
gd::InstructionsList& GetConditions() { return conditions; };
@@ -57,7 +53,9 @@ class GD_CORE_API StandardEvent : public gd::BaseEvent {
gd::InstructionsList conditions;
gd::InstructionsList actions;
EventsList events;
VariablesContainer variables;
};
} // namespace gd
#endif // GDCORE_STANDARDEVENT_H
#endif

View File

@@ -72,6 +72,8 @@ class GD_CORE_API WhileEvent : public gd::BaseEvent {
///< de/activate infinite loop warning when the
///< user create the event
mutable unsigned int whileConditionsHeight;
int GetConditionsHeight() const;
int GetActionsHeight() const;
int GetWhileConditionsHeight() const;

View File

@@ -1,129 +0,0 @@
/*
* GDevelop Core
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include <memory>
#include <vector>
#include "GDCore/String.h"
#include "GDCore/Tools/MakeUnique.h"
namespace gd {
/**
* \brief
*/
class GD_CORE_API ProjectDiagnostic {
public:
enum ErrorType {
UndeclaredVariable,
MissingBehavior,
UnknownObject,
MismatchedObjectType,
};
ProjectDiagnostic(ErrorType type_,
const gd::String &message_,
const gd::String &actualValue_,
const gd::String &expectedValue_,
const gd::String &objectName_ = "")
: type(type_),
message(message_),
actualValue(actualValue_),
expectedValue(expectedValue_),
objectName(objectName_) {};
virtual ~ProjectDiagnostic() {};
ErrorType GetType() const { return type; };
const gd::String &GetMessage() const { return message; }
const gd::String &GetObjectName() const { return objectName; }
const gd::String &GetActualValue() const { return actualValue; }
const gd::String &GetExpectedValue() const { return expectedValue; }
private:
ErrorType type;
gd::String message;
gd::String objectName;
gd::String actualValue;
gd::String expectedValue;
};
/**
* \brief
*/
class GD_CORE_API DiagnosticReport {
public:
DiagnosticReport() {};
virtual ~DiagnosticReport() {};
void Add(const gd::ProjectDiagnostic &projectDiagnostic) {
projectDiagnostics.push_back(
gd::make_unique<gd::ProjectDiagnostic>(projectDiagnostic));
};
const ProjectDiagnostic &Get(std::size_t index) const {
return *projectDiagnostics[index].get();
};
std::size_t Count() const { return projectDiagnostics.size(); };
const gd::String &GetSceneName() const { return sceneName; }
void SetSceneName(const gd::String &sceneName_) { sceneName = sceneName_; }
void LogAllDiagnostics() {
for (auto &diagnostic : projectDiagnostics) {
std::cout << diagnostic->GetMessage()
<< "(object: " << diagnostic->GetObjectName()
<< ", actual value: " << diagnostic->GetActualValue()
<< ", expected value: " << diagnostic->GetExpectedValue() << ")"
<< std::endl;
}
}
private:
std::vector<std::unique_ptr<gd::ProjectDiagnostic>> projectDiagnostics;
gd::String sceneName;
};
/**
* \brief
*/
class GD_CORE_API WholeProjectDiagnosticReport {
public:
WholeProjectDiagnosticReport() {};
virtual ~WholeProjectDiagnosticReport() {};
const DiagnosticReport &Get(std::size_t index) const {
return *diagnosticReports[index].get();
};
void Clear() { diagnosticReports.clear(); };
DiagnosticReport &AddNewDiagnosticReportForScene(
const gd::String &sceneName) {
auto diagnosticReport = gd::make_unique<gd::DiagnosticReport>();
diagnosticReport->SetSceneName(sceneName);
diagnosticReports.push_back(std::move(diagnosticReport));
return *diagnosticReports[diagnosticReports.size() - 1].get();
};
std::size_t Count() const { return diagnosticReports.size(); };
bool HasAnyIssue() {
for (auto &diagnosticReport : diagnosticReports) {
if (diagnosticReport->Count() > 0) {
return true;
}
}
return false;
}
private:
std::vector<std::unique_ptr<gd::DiagnosticReport>> diagnosticReports;
};
} // namespace gd

View File

@@ -15,48 +15,16 @@
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
namespace gd {
void EffectsCodeGenerator::DoVisitObject(gd::Object &object) {
auto &effects = object.GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
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.
// TODO Factorize with the iteration on all effects for resource exposure.
// TODO Implement an ArbitraryEffectWorker and add a method in ProjectBrowserHelper
void ExposeProjectEffects(
const gd::Project& project,
const std::function<void(const gd::Effect& effect)>& worker) {
// See also gd::Project::ExposeResources for a method that traverse the whole
// project (this time for resources) and
// WholeProjectRefactorer::ExposeProjectEvents.
EffectsCodeGenerator effectsCodeGenerator(platform, includeFiles);
// Add layouts effects
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
auto& layout = project.GetLayout(s);
@@ -65,34 +33,47 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
auto& effects = layout.GetLayer(l).GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
auto& effect = effects.GetEffect(e);
effectsCodeGenerator.AddEffectIncludeFiles(effect);
worker(effect);
}
}
for (std::size_t i = 0; i < layout.GetObjectsCount(); i++) {
auto& object = layout.GetObject(i);
auto& effects = object.GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
auto& effect = effects.GetEffect(e);
worker(effect);
}
}
}
// Add objects effects
gd::ProjectBrowserHelper::ExposeProjectObjects(project, effectsCodeGenerator);
// Add event-based objects layouts effects
for (std::size_t s = 0; s < project.GetEventsFunctionsExtensionsCount();
s++) {
auto &eventsFunctionExtension = project.GetEventsFunctionsExtension(s);
auto &eventsBasedObjects = eventsFunctionExtension.GetEventsBasedObjects();
for (std::size_t objectIndex = 0;
objectIndex < eventsBasedObjects.GetCount(); ++objectIndex) {
auto &eventsBasedObject = eventsBasedObjects.Get(objectIndex);
auto &layers = eventsBasedObject.GetLayers();
for (std::size_t l = 0; l < layers.GetLayersCount(); ++l) {
auto &effects = layers.GetLayer(l).GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
auto &effect = effects.GetEffect(e);
effectsCodeGenerator.AddEffectIncludeFiles(effect);
}
}
// Add global object effects
for (std::size_t s = 0; s < project.GetObjectsCount(); s++) {
auto& effects = project.GetObject(s).GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
auto& effect = effects.GetEffect(e);
worker(effect);
}
}
}
void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
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

View File

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

View File

@@ -3,8 +3,8 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#ifndef EVENTSCODEGENERATIONCONTEXT_H
#define EVENTSCODEGENERATIONCONTEXT_H
#include <map>
#include <memory>
#include <set>
@@ -325,3 +325,4 @@ class GD_CORE_API EventsCodeGenerationContext {
};
} // namespace gd
#endif // EVENTSCODEGENERATIONCONTEXT_H

View File

@@ -14,10 +14,8 @@
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/Events/ExpressionVariableNameFinder.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/ObjectsContainersList.h"
#include "GDCore/Project/Project.h"
using namespace std;
@@ -42,15 +40,14 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
const vector<gd::String>& arguments,
const gd::String& callStartString,
std::size_t startFromArgument) {
std::size_t relationalOperatorIndex = instrInfos.parameters.GetParametersCount();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
std::size_t relationalOperatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "relationalOperator") {
if (instrInfos.parameters[i].GetType() == "relationalOperator")
relationalOperatorIndex = i;
}
}
// Ensure that there is at least one parameter after the relational operator
if (relationalOperatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
if (relationalOperatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError();
return "";
}
@@ -71,36 +68,8 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
}
}
auto lhs = callStartString + "(" + argumentsStr + ")";
return GenerateRelationalOperation(relationalOperator, lhs, 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;
return callStartString + "(" + argumentsStr + ") " + relationalOperator +
" " + rhs;
}
/**
@@ -123,16 +92,14 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
const gd::String& callStartString,
const gd::String& getterStartString,
std::size_t startFromArgument) {
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
operatorIndex = i;
}
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
if (operatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError();
return "";
}
@@ -194,16 +161,14 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
const vector<gd::String>& arguments,
const gd::String& callStartString,
std::size_t startFromArgument) {
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
operatorIndex = i;
}
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
if (operatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError();
return "";
}
@@ -247,27 +212,25 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
const vector<gd::String>& arguments,
const gd::String& callStartString,
std::size_t startFromArgument) {
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount();
std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") {
operatorIndex = i;
}
if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
}
// Ensure that there is at least one parameter after the operator
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) {
if (operatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError();
return "";
}
gd::String operatorStr = arguments[operatorIndex];
if (operatorStr.size() > 2 && operatorStr[0] == '\"') {
if (operatorStr.size() > 2)
operatorStr = operatorStr.substr(
1,
operatorStr.length() - 1 -
1); // Operator contains quote which must be removed.
}
auto mutators = instrInfos.codeExtraInformation.optionalMutators;
auto mutator = mutators.find(operatorStr);
if (mutator == mutators.end()) {
@@ -287,9 +250,6 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
argumentsStr += arguments[i];
}
}
if (instrInfos.GetManipulatedType() == "boolean") {
return callStartString + "(" + argumentsStr + ")." + mutator->second;
}
return callStartString + "(" + argumentsStr + ")." + mutator->second + "(" +
rhs + ")";
@@ -307,11 +267,11 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.GetIncludeFiles());
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
maxConditionsListsSize =
std::max(maxConditionsListsSize, condition.GetSubInstructions().size());
if (instrInfos.HasCustomCodeGenerator()) {
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
context.EnterCustomCondition();
conditionCode += instrInfos.codeExtraInformation.customCodeGenerator(
condition, *this, context);
@@ -323,36 +283,29 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
}
// Insert code only parameters and be sure there is no lack of parameter.
while (condition.GetParameters().size() < instrInfos.parameters.GetParametersCount()) {
while (condition.GetParameters().size() < instrInfos.parameters.size()) {
vector<gd::Expression> parameters = condition.GetParameters();
parameters.push_back(gd::Expression(""));
condition.SetParameters(parameters);
}
gd::EventsCodeGenerator::CheckBehaviorParameters(condition, instrInfos);
// Verify that there are no mismatches between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter =
condition.GetParameter(pNb).GetPlainString();
const auto &expectedObjectType =
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
const auto &actualObjectType =
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
objectInParameter, "");
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
return "/* Unknown object - skipped. */";
} else if (!expectedObjectType.empty() &&
actualObjectType != expectedObjectType) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "",
actualObjectType, expectedObjectType, objectInParameter);
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].GetExtraInfo()) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -360,15 +313,21 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
if (instrInfos.IsObjectInstruction()) {
gd::String objectName = condition.GetParameter(0).GetPlainString();
if (!objectName.empty() && instrInfos.parameters.GetParametersCount() > 0) {
if (!objectName.empty() && !instrInfos.parameters.empty()) {
std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Set up the context
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
gd::String objectType = gd::GetTypeOfObject(
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), realObjects[i]);
const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
instrInfos.GetRequiredBaseObjectCapability())) {
conditionCode +=
"/* Object with unsupported capability - skipped. */\n";
} else {
AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
@@ -385,25 +344,22 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
context);
context.SetNoCurrentObject();
}
}
}
} else if (instrInfos.IsBehaviorInstruction()) {
if (instrInfos.parameters.GetParametersCount() >= 2) {
const gd::String &objectName = condition.GetParameter(0).GetPlainString();
const gd::String &behaviorName =
condition.GetParameter(1).GetPlainString();
const gd::String &actualBehaviorType =
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
gd::String objectName = condition.GetParameter(0).GetPlainString();
gd::String behaviorType =
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
condition.GetParameter(1).GetPlainString());
if (instrInfos.parameters.size() >= 2) {
std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(
objectName, context.GetCurrentObject());
const BehaviorMetadata &autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context
const BehaviorMetadata& autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
AddIncludeFiles(autoInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
@@ -413,7 +369,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
condition.GetParameters(), instrInfos.parameters, context);
conditionCode += GenerateBehaviorCondition(
realObjects[i],
behaviorName,
condition.GetParameter(1).GetPlainString(),
autoInfo,
arguments,
instrInfos,
@@ -488,33 +444,6 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
return outputCode;
}
void EventsCodeGenerator::CheckBehaviorParameters(
const gd::Instruction &instruction,
const gd::InstructionMetadata &instrInfos) {
gd::ParameterMetadataTools::IterateOverParameters(
instruction.GetParameters(), instrInfos.parameters,
[this](const gd::ParameterMetadata &parameterMetadata,
const gd::Expression &parameterValue,
const gd::String &lastObjectName) {
if (ParameterMetadata::IsBehavior(parameterMetadata.GetType())) {
const gd::String &behaviorName = parameterValue.GetPlainString();
const gd::String &actualBehaviorType =
GetObjectsContainersList().GetTypeOfBehaviorInObjectOrGroup(
lastObjectName, behaviorName);
const gd::String &expectedBehaviorType =
parameterMetadata.GetExtraInfo();
if (!expectedBehaviorType.empty() &&
actualBehaviorType != expectedBehaviorType) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::MissingBehavior, "",
actualBehaviorType, expectedBehaviorType, lastObjectName);
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
}
}
});
}
/**
* Generate code for an action.
*/
@@ -530,9 +459,9 @@ gd::String EventsCodeGenerator::GenerateActionCode(
return "/* Unknown instruction - skipped. */";
}
AddIncludeFiles(instrInfos.GetIncludeFiles());
AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
if (instrInfos.HasCustomCodeGenerator()) {
if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
return instrInfos.codeExtraInformation.customCodeGenerator(
action, *this, context);
}
@@ -546,35 +475,27 @@ gd::String EventsCodeGenerator::GenerateActionCode(
: instrInfos.codeExtraInformation.functionCallName;
// Be sure there is no lack of parameter.
while (action.GetParameters().size() < instrInfos.parameters.GetParametersCount()) {
while (action.GetParameters().size() < instrInfos.parameters.size()) {
vector<gd::Expression> parameters = action.GetParameters();
parameters.push_back(gd::Expression(""));
action.SetParameters(parameters);
}
gd::EventsCodeGenerator::CheckBehaviorParameters(action, instrInfos);
// Verify that there are no mismatches between object type in parameters.
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
const auto &expectedObjectType =
instrInfos.parameters.GetParameter(pNb).GetExtraInfo();
const auto &actualObjectType =
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
!GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
!GetGlobalObjectsAndGroups().GetObjectGroups().Has(
objectInParameter)) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
objectInParameter, "");
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
return "/* Unknown object - skipped. */";
} else if (!expectedObjectType.empty() &&
actualObjectType != expectedObjectType) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "",
actualObjectType, expectedObjectType, objectInParameter);
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
} else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
objectInParameter) !=
instrInfos.parameters[pNb].GetExtraInfo()) {
return "/* Mismatched object type - skipped. */";
}
}
@@ -584,15 +505,20 @@ gd::String EventsCodeGenerator::GenerateActionCode(
if (instrInfos.IsObjectInstruction()) {
gd::String objectName = action.GetParameter(0).GetPlainString();
if (instrInfos.parameters.GetParametersCount() > 0) {
if (!instrInfos.parameters.empty()) {
std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]);
gd::String objectType = gd::GetTypeOfObject(
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), realObjects[i]);
const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
instrInfos.GetRequiredBaseObjectCapability())) {
actionCode += "/* Object with unsupported capability - skipped. */\n";
} else {
AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
@@ -609,25 +535,24 @@ gd::String EventsCodeGenerator::GenerateActionCode(
optionalAsyncCallbackName);
context.SetNoCurrentObject();
}
}
}
} else if (instrInfos.IsBehaviorInstruction()) {
if (instrInfos.parameters.GetParametersCount() >= 2) {
const gd::String &objectName = action.GetParameter(0).GetPlainString();
const gd::String &behaviorName = action.GetParameter(1).GetPlainString();
const gd::String &actualBehaviorType =
GetObjectsContainersList().GetTypeOfBehavior(behaviorName);
gd::String objectName = action.GetParameter(0).GetPlainString();
gd::String behaviorType =
gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
GetObjectsAndGroups(),
action.GetParameter(1).GetPlainString());
if (instrInfos.parameters.size() >= 2) {
std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(
objectName, context.GetCurrentObject());
const BehaviorMetadata &autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
AddIncludeFiles(autoInfo.includeFiles);
ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context
const BehaviorMetadata& autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
AddIncludeFiles(autoInfo.includeFiles);
context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]);
@@ -636,7 +561,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
action.GetParameters(), instrInfos.parameters, context);
actionCode +=
GenerateBehaviorAction(realObjects[i],
behaviorName,
action.GetParameter(1).GetPlainString(),
autoInfo,
functionCallName,
arguments,
@@ -660,29 +585,6 @@ gd::String EventsCodeGenerator::GenerateActionCode(
return actionCode;
}
gd::String EventsCodeGenerator::GenerateLocalVariablesStackAccessor() {
return (HasProjectAndLayout() ? GetCodeNamespace()
: "eventsFunctionContext") +
".localVariables";
}
gd::String EventsCodeGenerator::GenerateAnyOrSceneVariableGetter(
const gd::Expression &variableExpression,
EventsCodeGenerationContext &context) {
const auto variableName = gd::ExpressionVariableNameFinder::GetVariableName(
*variableExpression.GetRootNode());
gd::String variableParameterType =
GetProjectScopedContainers().GetVariablesContainersList().Has(
variableName)
? "variable"
: "scenevar";
return gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, variableParameterType,
variableExpression.GetPlainString(), "", "AllowUndeclaredVariable");
}
const EventsCodeGenerator::CallbackDescriptor
EventsCodeGenerator::GenerateCallback(
const gd::String& callbackID,
@@ -707,23 +609,14 @@ EventsCodeGenerator::GenerateCallback(
actionsCode += "} //End of subevents\n";
}
gd::String restoreLocalVariablesCode;
restoreLocalVariablesCode +=
"asyncObjectsList.restoreLocalVariablesContainers(" +
GenerateLocalVariablesStackAccessor() + ");\n";
// Compose the callback function and add outside main
const gd::String actionsDeclarationsCode =
GenerateObjectsDeclarationCode(callbackContext);
const gd::String clearLocalVariablesCode =
GenerateLocalVariablesStackAccessor() + ".length = 0;\n";
const gd::String callbackCode = callbackFunctionName + " = function (" +
GenerateEventsParameters(callbackContext) +
") {\n" + restoreLocalVariablesCode +
actionsDeclarationsCode + actionsCode +
clearLocalVariablesCode + "}\n";
") {\n" + actionsDeclarationsCode +
actionsCode + "}\n";
AddCustomCodeOutsideMain(callbackCode);
@@ -775,6 +668,18 @@ gd::String EventsCodeGenerator::GenerateActionsListCode(
return outputCode;
}
const gd::String EventsCodeGenerator::GenerateRelationalOperatorCodes(const gd::String &operatorString) {
if (operatorString == "=") {
return "==";
}
if (operatorString != "<" && operatorString != ">" &&
operatorString != "<=" && operatorString != ">=" && operatorString != "!=") {
cout << "Warning: Bad relational operator: Set to == by default." << endl;
return "==";
}
return operatorString;
}
gd::String EventsCodeGenerator::GenerateParameterCodes(
const gd::Expression& parameter,
const gd::ParameterMetadata& metadata,
@@ -786,26 +691,25 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
if (ParameterMetadata::IsExpression("number", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "number", parameter, lastObjectName, metadata.GetExtraInfo());
*this, context, "number", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("string", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "string", parameter, lastObjectName, metadata.GetExtraInfo());
*this, context, "string", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, metadata.GetType(), parameter, lastObjectName, metadata.GetExtraInfo());
*this, context, metadata.GetType(), parameter, lastObjectName);
} else if (ParameterMetadata::IsObject(metadata.GetType())) {
// It would be possible to run a gd::ExpressionCodeGenerator if later
// objects can have nested objects, or function returning objects.
argOutput =
GenerateObject(parameter.GetPlainString(), metadata.GetType(), context);
} else if (metadata.GetType() == "relationalOperator") {
argOutput += parameter.GetPlainString();
argOutput += GenerateRelationalOperatorCodes(parameter.GetPlainString());
argOutput = "\"" + argOutput + "\"";
} else if (metadata.GetType() == "operator") {
argOutput += parameter.GetPlainString();
if (argOutput != "=" && argOutput != "+" && argOutput != "-" &&
argOutput != "/" && argOutput != "*" && argOutput != "True" &&
argOutput != "False" && argOutput != "Toggle") {
argOutput != "/" && argOutput != "*") {
cout << "Warning: Bad operator: Set to = by default." << endl;
argOutput = "=";
}
@@ -824,11 +728,9 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
metadata.GetType() == "tilesetResource" ||
metadata.GetType() == "videoResource" ||
metadata.GetType() == "model3DResource" ||
metadata.GetType() == "atlasResource" ||
metadata.GetType() == "spineResource" ||
// Deprecated, old parameter names:
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
metadata.GetType() == "soundfile") {
metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.GetType() == "mouse") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
@@ -870,7 +772,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
vector<gd::String> EventsCodeGenerator::GenerateParametersCodes(
const vector<gd::Expression>& parameters,
const ParameterMetadataContainer& parametersInfo,
const vector<gd::ParameterMetadata>& parametersInfo,
EventsCodeGenerationContext& context,
std::vector<std::pair<gd::String, gd::String> >*
supplementaryParametersTypes) {
@@ -975,11 +877,6 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
gd::EventsList& events, EventsCodeGenerationContext& parentContext) {
gd::String output;
for (std::size_t eId = 0; eId < events.size(); ++eId) {
auto& event = events[eId];
if (event.HasVariables()) {
GetProjectScopedContainers().GetVariablesContainersList().Push(event.GetVariables());
}
// Each event has its own context : Objects picked in an event are totally
// different than the one picked in another.
gd::EventsCodeGenerationContext newContext;
@@ -1000,17 +897,13 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
auto& context = reuseParentContext ? reusedContext : newContext;
gd::String eventCoreCode = event.GenerateEventCode(*this, context);
gd::String eventCoreCode = events[eId].GenerateEventCode(*this, context);
gd::String scopeBegin = GenerateScopeBegin(context);
gd::String scopeEnd = GenerateScopeEnd(context);
gd::String declarationsCode = GenerateObjectsDeclarationCode(context);
output += "\n" + scopeBegin + "\n" + declarationsCode + "\n" +
eventCoreCode + "\n" + scopeEnd + "\n";
if (event.HasVariables()) {
GetProjectScopedContainers().GetVariablesContainersList().Pop();
}
}
return output;
@@ -1030,6 +923,41 @@ gd::String EventsCodeGenerator::ConvertToStringExplicit(
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) {
for (std::size_t eId = events.size() - 1; eId < events.size(); --eId) {
if (events[eId].CanHaveSubEvents()) // Process sub events, if any
@@ -1046,8 +974,6 @@ void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) {
*/
void EventsCodeGenerator::PreprocessEventList(gd::EventsList& listEvent) {
for (std::size_t i = 0; i < listEvent.GetEventsCount(); ++i) {
if (listEvent[i].IsDisabled()) continue;
listEvent[i].Preprocess(*this, listEvent, i);
if (i <
listEvent.GetEventsCount()) { // Be sure that that there is still an
@@ -1093,31 +1019,31 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
bool conditionInverted,
gd::EventsCodeGenerationContext& context) {
// Generate call
gd::String predicate;
gd::String predicat;
if (instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string") {
predicate = GenerateRelationalOperatorCall(
predicat = GenerateRelationalOperatorCall(
instrInfos,
arguments,
instrInfos.codeExtraInformation.functionCallName);
} else {
predicate = instrInfos.codeExtraInformation.functionCallName + "(" +
predicat = instrInfos.codeExtraInformation.functionCallName + "(" +
GenerateArgumentsList(arguments, 0) + ")";
}
// Add logical not if needed
bool conditionAlreadyTakeCareOfInversion = false;
for (std::size_t i = 0; i < instrInfos.parameters.GetParametersCount();
for (std::size_t i = 0; i < instrInfos.parameters.size();
++i) // Some conditions already have a "conditionInverted" parameter
{
if (instrInfos.parameters.GetParameter(i).GetType() == "conditionInverted")
if (instrInfos.parameters[i].GetType() == "conditionInverted")
conditionAlreadyTakeCareOfInversion = true;
}
if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
predicate = GenerateNegatedPredicate(predicate);
predicat = GenerateNegatedPredicat(predicat);
// Generate condition code
return returnBoolean + " = " + predicate + ";\n";
return returnBoolean + " = " + predicat + ";\n";
}
gd::String EventsCodeGenerator::GenerateObjectCondition(
@@ -1131,7 +1057,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
// Prepare call
// Add a static_cast if necessary
gd::String objectFunctionCallNamePart =
(!instrInfos.parameters.GetParameter(0).GetExtraInfo().empty())
(!instrInfos.parameters[0].GetExtraInfo().empty())
? "static_cast<" + objInfo.className + "*>(" +
GetObjectListName(objectName, context) + "[i])->" +
instrInfos.codeExtraInformation.functionCallName
@@ -1139,18 +1065,18 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
instrInfos.codeExtraInformation.functionCallName;
// Create call
gd::String predicate;
gd::String predicat;
if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) {
predicate = GenerateRelationalOperatorCall(
predicat = GenerateRelationalOperatorCall(
instrInfos, arguments, objectFunctionCallNamePart, 1);
} else {
predicate = objectFunctionCallNamePart + "(" +
predicat = objectFunctionCallNamePart + "(" +
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";
}
@@ -1164,16 +1090,16 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
bool conditionInverted,
gd::EventsCodeGenerationContext& context) {
// Create call
gd::String predicate;
gd::String predicat;
if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) {
predicate = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
predicat = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
} 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";
}
@@ -1186,13 +1112,7 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
// Generate call
gd::String call;
if (instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string" ||
// Boolean actions declared with addExpressionAndConditionAndAction uses
// MutatorAndOrAccessor even though they don't declare an operator parameter.
// Boolean operators are only used with SetMutators or SetCustomCodeGenerator.
(instrInfos.codeExtraInformation.type == "boolean" &&
instrInfos.codeExtraInformation.accessType ==
gd::InstructionMetadata::ExtraInformation::AccessType::Mutators)) {
instrInfos.codeExtraInformation.type == "string") {
if (instrInfos.codeExtraInformation.accessType ==
gd::InstructionMetadata::ExtraInformation::MutatorAndOrAccessor)
call = GenerateOperatorCall(
@@ -1351,42 +1271,12 @@ gd::String EventsCodeGenerator::GenerateArgumentsList(
return argumentsStr;
}
gd::String EventsCodeGenerator::GeneratePropertyGetter(const gd::PropertiesContainer& propertiesContainer,
const gd::NamedPropertyDescriptor& property,
const gd::String& type,
gd::EventsCodeGenerationContext& context) {
return "getProperty" + property.GetName() + "As" + type + "()";
}
gd::String EventsCodeGenerator::GeneratePropertyGetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property) {
return "getProperty" + property.GetName() + "()";
}
gd::String EventsCodeGenerator::GeneratePropertySetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property,
const gd::String &operandCode) {
return "setProperty" + property.GetName() + "(" + operandCode + ")";
}
gd::String EventsCodeGenerator::GenerateParameterGetter(const gd::ParameterMetadata& parameter,
const gd::String& type,
gd::EventsCodeGenerationContext& context) {
return "getParameter" + parameter.GetName() + "As" + type + "()";
}
gd::String EventsCodeGenerator::GenerateParameterGetterWithoutCasting(
const gd::ParameterMetadata &parameter) {
return "getParameter" + parameter.GetName() + "()";
}
EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
const gd::Layout& layout,
const gd::Platform& platform_)
: platform(platform_),
projectScopedContainers(gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project_, layout)),
globalObjectsAndGroups(project_),
objectsAndGroups(layout),
hasProjectAndLayout(true),
project(&project_),
scene(&layout),
@@ -1394,14 +1284,15 @@ EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
compilationForRuntime(false),
maxCustomConditionsDepth(0),
maxConditionsListsSize(0),
eventsListNextUniqueId(0),
diagnosticReport(nullptr){};
eventsListNextUniqueId(0){};
EventsCodeGenerator::EventsCodeGenerator(
const gd::Platform& platform_,
const gd::ProjectScopedContainers& projectScopedContainers_)
const gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& objectsAndGroups_)
: platform(platform_),
projectScopedContainers(projectScopedContainers_),
globalObjectsAndGroups(globalObjectsAndGroups_),
objectsAndGroups(objectsAndGroups_),
hasProjectAndLayout(false),
project(nullptr),
scene(nullptr),
@@ -1409,7 +1300,6 @@ EventsCodeGenerator::EventsCodeGenerator(
compilationForRuntime(false),
maxCustomConditionsDepth(0),
maxConditionsListsSize(0),
eventsListNextUniqueId(0),
diagnosticReport(nullptr){};
eventsListNextUniqueId(0){};
} // namespace gd

View File

@@ -3,7 +3,8 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#ifndef GDCORE_EVENTSCODEGENERATOR_H
#define GDCORE_EVENTSCODEGENERATOR_H
#include <set>
#include <utility>
@@ -11,17 +12,13 @@
#include "GDCore/Events/Event.h"
#include "GDCore/Events/Instruction.h"
#include "GDCore/Events/CodeGeneration/DiagnosticReport.h"
#include "GDCore/Project/ProjectScopedContainers.h"
#include "GDCore/String.h"
namespace gd {
class EventsList;
class Expression;
class Project;
class Layout;
class ObjectsContainer;
class ObjectsContainersList;
class ExternalEvents;
class ParameterMetadata;
class ObjectMetadata;
@@ -59,9 +56,9 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Construct a code generator for the specified
* objects/groups and platform
*/
EventsCodeGenerator(
const gd::Platform& platform,
const gd::ProjectScopedContainers& projectScopedContainers_);
EventsCodeGenerator(const gd::Platform& platform,
const gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& objectsAndGroups_);
virtual ~EventsCodeGenerator(){};
/**
@@ -128,7 +125,7 @@ class GD_CORE_API EventsCodeGenerator {
*/
std::vector<gd::String> GenerateParametersCodes(
const std::vector<gd::Expression>& parameters,
const ParameterMetadataContainer& parametersInfo,
const std::vector<gd::ParameterMetadata>& parametersInfo,
EventsCodeGenerationContext& context,
std::vector<std::pair<gd::String, gd::String> >*
supplementaryParametersTypes = 0);
@@ -329,22 +326,18 @@ class GD_CORE_API EventsCodeGenerator {
*/
bool ErrorOccurred() const { return errorOccurred; };
const gd::ObjectsContainersList& GetObjectsContainersList() const {
return projectScopedContainers.GetObjectsContainersList();
};
const gd::ProjectScopedContainers& GetProjectScopedContainers() const {
return projectScopedContainers;
/**
* \brief Get the global objects/groups used for code generation.
*/
const gd::ObjectsContainer& GetGlobalObjectsAndGroups() const {
return globalObjectsAndGroups;
}
/**
* @brief Give access to the project scoped containers as code generation might
* push and pop variable containers (for local variables).
* This could be passed as a parameter recursively in code generation, but this requires
* heavy refactoring. Instead, we use this single instance.
* \brief Get the objects/groups used for code generation.
*/
gd::ProjectScopedContainers& GetProjectScopedContainers() {
return projectScopedContainers;
const gd::ObjectsContainer& GetObjectsAndGroups() const {
return objectsAndGroups;
}
/**
@@ -370,6 +363,22 @@ class GD_CORE_API EventsCodeGenerator {
*/
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
* generation.
@@ -383,14 +392,6 @@ class GD_CORE_API EventsCodeGenerator {
*/
size_t GetMaxConditionsListsSize() const { return maxConditionsListsSize; }
void SetDiagnosticReport(gd::DiagnosticReport* diagnosticReport_) {
diagnosticReport = diagnosticReport_;
}
gd::DiagnosticReport* GetDiagnosticReport() {
return diagnosticReport;
}
/**
* \brief Generate the full name for accessing to a boolean variable used for
* conditions.
@@ -467,14 +468,7 @@ class GD_CORE_API EventsCodeGenerator {
*/
virtual gd::String GetCodeNamespace() { return ""; };
enum VariableScope {
LAYOUT_VARIABLE = 0,
PROJECT_VARIABLE,
OBJECT_VARIABLE,
ANY_VARIABLE,
VARIABLE_OR_PROPERTY,
VARIABLE_OR_PROPERTY_OR_PARAMETER
};
enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE };
/**
* Generate a single unique number for the specified instruction.
@@ -499,33 +493,10 @@ class GD_CORE_API EventsCodeGenerator {
*/
size_t GenerateSingleUsageUniqueIdForEventsList();
virtual gd::String GenerateRelationalOperation(
const gd::String& relationalOperator,
const gd::String& lhs,
const gd::String& rhs);
/**
* \brief Generate the code to access the local variables stack.
*/
virtual gd::String GenerateLocalVariablesStackAccessor();
/**
* \brief Generate an any variable getter that fallbacks on scene variable for
* compatibility reason.
*/
gd::String
GenerateAnyOrSceneVariableGetter(const gd::Expression &variableExpression,
EventsCodeGenerationContext &context);
virtual gd::String GeneratePropertySetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property,
const gd::String &operandCode);
protected:
virtual const gd::String GenerateRelationalOperatorCodes(
const gd::String& operatorString);
protected:
/**
* \brief Generate the code for a single parameter.
*
@@ -540,7 +511,7 @@ protected:
parameter -> string
* - operator : Used to update a value using a setter and a getter -> string
* - key, mouse, objectvar, scenevar, globalvar, password, musicfile,
soundfile -> string
soundfile, police -> string
* - trueorfalse, yesorno -> boolean ( See GenerateTrue/GenerateFalse ).
*
* <br><br>
@@ -577,19 +548,12 @@ protected:
const gd::String& variableName,
const VariableScope& scope,
gd::EventsCodeGenerationContext& context,
const gd::String& objectName,
bool hasChild) {
// This code is only used as a mock.
// See the real implementation in GDJS.
const gd::String& objectName) {
if (scope == LAYOUT_VARIABLE) {
return "getLayoutVariable(" + variableName + ")";
} else if (scope == PROJECT_VARIABLE) {
return "getProjectVariable(" + variableName + ")";
} else if (scope == ANY_VARIABLE || scope == VARIABLE_OR_PROPERTY ||
scope == VARIABLE_OR_PROPERTY_OR_PARAMETER) {
// TODO Split the 3 cases to make tests stronger.
return "getAnyVariable(" + variableName + ")";
}
return "getVariableForObject(" + objectName + ", " + variableName + ")";
@@ -602,12 +566,6 @@ protected:
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,
* using generated the expression.
@@ -636,24 +594,6 @@ protected:
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 GeneratePropertyGetterWithoutCasting(
const gd::PropertiesContainer &propertiesContainer,
const gd::NamedPropertyDescriptor &property);
virtual gd::String GenerateParameterGetter(
const gd::ParameterMetadata& parameter,
const gd::String& type,
gd::EventsCodeGenerationContext& context);
virtual gd::String
GenerateParameterGetterWithoutCasting(const gd::ParameterMetadata &parameter);
/**
* \brief Generate the code to reference an object which is
* in an empty/null state.
@@ -728,14 +668,13 @@ protected:
};
/**
* \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 !.
*/
virtual gd::String GenerateNegatedPredicate(
const gd::String& predicate) const {
return "!(" + predicate + ")";
virtual gd::String GenerateNegatedPredicat(const gd::String& predicat) const {
return "!(" + predicat + ")";
};
virtual gd::String GenerateFreeCondition(
@@ -795,7 +734,6 @@ protected:
const std::vector<gd::String>& arguments,
const gd::String& callStartString,
std::size_t startFromArgument = 0);
gd::String GenerateOperatorCall(const gd::InstructionMetadata& instrInfos,
const std::vector<gd::String>& arguments,
const gd::String& callStartString,
@@ -837,13 +775,10 @@ protected:
virtual gd::String GenerateGetBehaviorNameCode(
const gd::String& behaviorName);
void CheckBehaviorParameters(
const gd::Instruction &instruction,
const gd::InstructionMetadata &instrInfos);
const gd::Platform& platform; ///< The platform being used.
gd::ProjectScopedContainers projectScopedContainers;
const gd::ObjectsContainer& globalObjectsAndGroups;
const gd::ObjectsContainer& objectsAndGroups;
bool hasProjectAndLayout; ///< true only if project and layout are valid
///< references. If false, they should not be used.
@@ -871,9 +806,8 @@ protected:
instructionUniqueIds; ///< The unique ids generated for instructions.
size_t eventsListNextUniqueId; ///< The next identifier to use for an events
///< list function name.
gd::DiagnosticReport* diagnosticReport;
};
} // namespace gd
#endif // GDCORE_EVENTSCODEGENERATOR_H

View File

@@ -7,7 +7,6 @@
#include <memory>
#include <vector>
#include <vector>
#include "GDCore/CommonTools.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h"
@@ -26,12 +25,8 @@
#include "GDCore/IDE/Events/ExpressionValidator.h"
#include "GDCore/Project/Layout.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"
#include "GDCore/Events/CodeGeneration/DiagnosticReport.h"
namespace gd {
@@ -40,8 +35,7 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode(
EventsCodeGenerationContext& context,
const gd::String& rootType,
const gd::Expression& expression,
const gd::String& rootObjectName,
const gd::String& extraInfo) {
const gd::String& rootObjectName) {
ExpressionCodeGenerator generator(rootType, rootObjectName, codeGenerator, context);
auto node = expression.GetRootNode();
@@ -53,35 +47,15 @@ gd::String ExpressionCodeGenerator::GenerateExpressionCode(
}
gd::ExpressionValidator validator(codeGenerator.GetPlatform(),
codeGenerator.GetProjectScopedContainers(),
rootType,
extraInfo);
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType);
node->Visit(validator);
if (!validator.GetFatalErrors().empty()) {
std::cout << "Error: \"" << validator.GetFatalErrors()[0]->GetMessage()
<< "\" in: \"" << expression.GetPlainString() << "\" ("
<< rootType << ")" << std::endl;
auto *diagnosticReport = codeGenerator.GetDiagnosticReport();
if (diagnosticReport) {
for (auto *error : validator.GetFatalErrors()) {
if (error->GetType() ==
gd::ExpressionParserError::ErrorType::UndeclaredVariable ||
error->GetType() ==
gd::ExpressionParserError::ErrorType::UnknownIdentifier) {
const auto& variableName = error->GetActualValue();
if (!variableName.empty()) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::UndeclaredVariable,
error->GetMessage(), error->GetActualValue(),
"", error->GetObjectName());
diagnosticReport->Add(projectDiagnostic);
}
}
}
}
return generator.GenerateDefaultValue(rootType);
}
@@ -126,89 +100,35 @@ void ExpressionCodeGenerator::OnVisitVariableNode(VariableNode& node) {
// This "translation" from the type to an enum could be avoided
// if all types were moved to an enum.
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetProjectScopedContainers(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
if (gd::ParameterMetadata::IsExpression("variable", type)) {
// The node is a variable inside an expression waiting for a *variable* to be returned, not its value.
EventsCodeGenerator::VariableScope scope =
type == "variable"
? gd::EventsCodeGenerator::ANY_VARIABLE
: type == "variableOrProperty"
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY
: type == "variableOrPropertyOrParameter"
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER
: 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, node.child != nullptr);
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);
}, [&]() {
output += codeGenerator.GenerateGetVariable(
node.name, gd::EventsCodeGenerator::ANY_VARIABLE, context, "", node.child != nullptr);
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);
});
}
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.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootObjectName,
node);
output += codeGenerator.GenerateGetVariable(
node.name, scope, context, objectName);
if (node.child) node.child->Visit(*this);
}
void ExpressionCodeGenerator::OnVisitVariableAccessorNode(
VariableAccessorNode& node) {
if (!objectNameToUseForVariableAccessor.empty()) {
// 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, node.child != nullptr);
// 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);
}
output += codeGenerator.GenerateVariableAccessor(node.name);
if (node.child) node.child->Visit(*this);
}
void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
VariableBracketAccessorNode& node) {
if (!objectNameToUseForVariableAccessor.empty()) {
// 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);
ExpressionCodeGenerator generator("string", "", codeGenerator, context);
node.expression->Visit(generator);
output +=
codeGenerator.GenerateVariableBracketAccessor(generator.GetOutput());
@@ -217,80 +137,55 @@ void ExpressionCodeGenerator::OnVisitVariableBracketAccessorNode(
void ExpressionCodeGenerator::OnVisitIdentifierNode(IdentifierNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetProjectScopedContainers(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
if (gd::ParameterMetadata::IsObject(type)) {
output +=
codeGenerator.GenerateObject(node.identifierName, type, context);
} else if (gd::ParameterMetadata::IsExpression("variable", type)) {
EventsCodeGenerator::VariableScope scope =
type == "variable"
? gd::EventsCodeGenerator::ANY_VARIABLE
: type == "variableOrProperty"
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY
: type == "variableOrPropertyOrParameter"
? gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER
: type == "globalvar" ? gd::EventsCodeGenerator::PROJECT_VARIABLE
: type == "scenevar" ? gd::EventsCodeGenerator::LAYOUT_VARIABLE
: gd::EventsCodeGenerator::OBJECT_VARIABLE;
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,
!node.childIdentifierName.empty());
if (!node.childIdentifierName.empty()) {
output +=
codeGenerator.GenerateVariableAccessor(node.childIdentifierName);
}
} else {
const auto& variablesContainersList = codeGenerator.GetProjectScopedContainers().GetVariablesContainersList();
const auto& propertiesContainersList = codeGenerator.GetProjectScopedContainers().GetPropertiesContainersList();
const auto& parametersVectorsList = codeGenerator.GetProjectScopedContainers().GetParametersVectorsList();
// The node represents a variable, property, parameter or an object.
codeGenerator.GetProjectScopedContainers().MatchIdentifierWithName<void>(node.identifierName, [&]() {
// Generate the code to access the object variable.
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootObjectName,
node);
output += codeGenerator.GenerateGetVariable(
node.childIdentifierName, gd::EventsCodeGenerator::OBJECT_VARIABLE,
context, node.identifierName, !node.childIdentifierName.empty());
output += codeGenerator.GenerateVariableValueAs(type);
}, [&]() {
output += codeGenerator.GenerateGetVariable(
node.identifierName, gd::EventsCodeGenerator::VARIABLE_OR_PROPERTY_OR_PARAMETER, context,
"", !node.childIdentifierName.empty());
node.identifierName, scope, context, objectName);
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);
});
} else if (node.childIdentifierName.empty()) {
output += "/* Error during generation, unrecognized identifier type: " +
codeGenerator.ConvertToString(type) + " with value " +
codeGenerator.ConvertToString(node.identifierName) + " */ " +
codeGenerator.ConvertToStringExplicit(node.identifierName);
}
else {
// This is for function names that are put in IdentifierNode
// because the type is needed to tell them apart from variables.
output += GenerateDefaultValue(type);
}
}
void ExpressionCodeGenerator::OnVisitFunctionCallNode(FunctionCallNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetProjectScopedContainers(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
node);
if (gd::MetadataProvider::IsBadExpressionMetadata(metadata)) {
@@ -321,10 +216,10 @@ gd::String ExpressionCodeGenerator::GenerateFreeFunctionCode(
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) {
codeGenerator.AddIncludeFiles(
expressionMetadata.GetIncludeFiles());
expressionMetadata.codeExtraInformation.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.HasCustomCodeGenerator()) {
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}
@@ -341,11 +236,16 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
const gd::String& objectName,
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) {
const gd::ObjectsContainer& globalObjectsAndGroups =
codeGenerator.GetGlobalObjectsAndGroups();
const gd::ObjectsContainer& objectsAndGroups =
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles(
expressionMetadata.GetIncludeFiles());
expressionMetadata.codeExtraInformation.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.HasCustomCodeGenerator()) {
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}
@@ -361,14 +261,20 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
// Get object(s) concerned by function call
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) {
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(
codeGenerator.GetPlatform(), objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
expressionMetadata.GetRequiredBaseObjectCapability())) {
// Do nothing, skipping objects not supporting the capability required by
// this expression.
} else {
codeGenerator.AddIncludeFiles(objInfo.includeFiles);
functionOutput = codeGenerator.GenerateObjectFunctionCall(
realObjects[i],
@@ -377,6 +283,7 @@ gd::String ExpressionCodeGenerator::GenerateObjectFunctionCode(
parametersCode,
functionOutput,
context);
}
}
return functionOutput;
@@ -387,11 +294,16 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
const gd::String& behaviorName,
const std::vector<std::unique_ptr<ExpressionNode>>& parameters,
const ExpressionMetadata& expressionMetadata) {
const gd::ObjectsContainer& globalObjectsAndGroups =
codeGenerator.GetGlobalObjectsAndGroups();
const gd::ObjectsContainer& objectsAndGroups =
codeGenerator.GetObjectsAndGroups();
codeGenerator.AddIncludeFiles(
expressionMetadata.GetIncludeFiles());
expressionMetadata.codeExtraInformation.GetIncludeFiles());
// Launch custom code generator if needed
if (expressionMetadata.HasCustomCodeGenerator()) {
if (expressionMetadata.codeExtraInformation.HasCustomCodeGenerator()) {
return expressionMetadata.codeExtraInformation.customCodeGenerator(
PrintParameters(parameters), codeGenerator, context);
}
@@ -405,11 +317,12 @@ gd::String ExpressionCodeGenerator::GenerateBehaviorFunctionCode(
// Get object(s) concerned by function call
std::vector<gd::String> realObjects =
codeGenerator.GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject());
codeGenerator.ExpandObjectsName(objectName, context);
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(
codeGenerator.GetPlatform(), behaviorType);
@@ -437,15 +350,16 @@ gd::String ExpressionCodeGenerator::GenerateParametersCodes(
size_t nonCodeOnlyParameterIndex = 0;
gd::String parametersCode;
for (std::size_t i = initialParameterIndex;
i < expressionMetadata.GetParameters().GetParametersCount();
i < expressionMetadata.parameters.size();
++i) {
if (i != initialParameterIndex) parametersCode += ", ";
auto& parameterMetadata = expressionMetadata.GetParameters().GetParameter(i);
auto& parameterMetadata = expressionMetadata.parameters[i];
if (!parameterMetadata.IsCodeOnly()) {
if (nonCodeOnlyParameterIndex < parameters.size()) {
auto objectName = gd::ExpressionVariableOwnerFinder::GetObjectName(codeGenerator.GetPlatform(),
codeGenerator.GetObjectsContainersList(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootObjectName,
*parameters[nonCodeOnlyParameterIndex].get());
ExpressionCodeGenerator generator(parameterMetadata.GetType(), objectName, codeGenerator, context);
@@ -515,7 +429,8 @@ gd::String ExpressionCodeGenerator::GenerateDefaultValue(
void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetProjectScopedContainers(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
output += GenerateDefaultValue(type);
@@ -524,7 +439,8 @@ void ExpressionCodeGenerator::OnVisitEmptyNode(EmptyNode& node) {
void ExpressionCodeGenerator::OnVisitObjectFunctionNameNode(
ObjectFunctionNameNode& node) {
auto type = gd::ExpressionTypeFinder::GetType(codeGenerator.GetPlatform(),
codeGenerator.GetProjectScopedContainers(),
codeGenerator.GetGlobalObjectsAndGroups(),
codeGenerator.GetObjectsAndGroups(),
rootType,
node);
output += GenerateDefaultValue(type);

View File

@@ -59,8 +59,7 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
EventsCodeGenerationContext& context,
const gd::String& type,
const gd::Expression& expression,
const gd::String& objectName = "",
const gd::String& extraInfo = "");
const gd::String& objectName = "");
const gd::String& GetOutput() { return output; };
@@ -103,7 +102,6 @@ class GD_CORE_API ExpressionCodeGenerator : public ExpressionParser2NodeWorker {
const std::vector<std::unique_ptr<ExpressionNode>>& parameters);
gd::String output;
gd::String objectNameToUseForVariableAccessor;
EventsCodeGenerator& codeGenerator;
EventsCodeGenerationContext& context;
const gd::String rootType;

View File

@@ -17,7 +17,8 @@
namespace gd {
EventsList BaseEvent::badSubEvents;
VariablesContainer BaseEvent::badLocalVariables;
std::vector<gd::String> BaseEvent::emptyDependencies;
gd::String BaseEvent::emptySourceFile;
BaseEvent::BaseEvent()
: totalTimeDuringLastSession(0),
@@ -27,8 +28,6 @@ BaseEvent::BaseEvent()
bool BaseEvent::HasSubEvents() const { return !GetSubEvents().IsEmpty(); }
bool BaseEvent::HasVariables() const { return GetVariables().Count() > 0; }
gd::String BaseEvent::GenerateEventCode(
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context) {

View File

@@ -3,7 +3,9 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#if defined(GD_IDE_ONLY)
#ifndef GDCORE_EVENT_H
#define GDCORE_EVENT_H
#include <iostream>
#include <memory>
@@ -24,7 +26,6 @@ class SerializerElement;
class Instruction;
class EventVisitor;
class ReadOnlyEventVisitor;
class VariablesContainer;
} // namespace gd
namespace gd {
@@ -91,32 +92,6 @@ class GD_CORE_API BaseEvent {
*/
bool HasSubEvents() const;
/**
* Derived class have to redefine this function, so as to return true, if they
* can have local variables.
*/
virtual bool CanHaveVariables() const { return false; }
/**
* Return the local variables, if applicable.
*/
virtual const gd::VariablesContainer& GetVariables() const {
return badLocalVariables;
};
/**
* Return the local variables, if applicable.
*/
virtual gd::VariablesContainer& GetVariables() {
return badLocalVariables;
};
/**
* \brief Return true if the events has local variables.
* \warning This is only applicable when CanHaveVariables() return true.
*/
bool HasVariables() const;
/**
* \brief Return a list of all conditions of the event.
* \note Used to preprocess or search in the conditions.
@@ -175,6 +150,26 @@ class GD_CORE_API BaseEvent {
noExpr;
return noExpr;
};
/**
* \brief Returns the dependencies on source files of the project.
* \note Default implementation returns an empty list of dependencies. This is
* fine for most events that are not related to adding custom user source
* code.
*/
virtual const std::vector<gd::String>& GetSourceFileDependencies() const {
return emptyDependencies;
};
/**
* \brief Returns the name of the source file associated with the event
* \note Default implementation returns an empty string. This is fine for most
* events that are not related to adding custom user source code.
*/
virtual const gd::String& GetAssociatedGDManagedSourceFile(
gd::Project& project) const {
return emptySourceFile;
};
///@}
/** \name Code generation
@@ -245,7 +240,7 @@ class GD_CORE_API BaseEvent {
*/
virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element){};
virtual bool AcceptVisitor(gd::EventVisitor& eventVisitor);
virtual void AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const;
///@}
@@ -286,6 +281,7 @@ class GD_CORE_API BaseEvent {
* \brief True if the event should be folded in the events editor.
*/
bool IsFolded() const { return folded; }
///@}
std::weak_ptr<gd::BaseEvent>
@@ -306,7 +302,8 @@ class GD_CORE_API BaseEvent {
///< Used for saving the event for instance.
static gd::EventsList badSubEvents;
static gd::VariablesContainer badLocalVariables;
static std::vector<gd::String> emptyDependencies;
static gd::String emptySourceFile;
};
/**
@@ -329,3 +326,6 @@ class EmptyEvent : public BaseEvent {
};
} // namespace gd
#endif // GDCORE_EVENT_H
#endif

View File

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

View File

@@ -18,6 +18,7 @@ class BaseEvent;
namespace gd {
class SerializerElement;
}
class TiXmlElement;
#undef CreateEvent

View File

@@ -19,10 +19,8 @@
#include "GDCore/Project/Project.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/MakeUnique.h"
#include "GrammarTerminals.h"
using namespace std;
using namespace gd::GrammarTerminals;
namespace gd {

View File

@@ -18,7 +18,6 @@
#include "GDCore/String.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/MakeUnique.h"
#include "GrammarTerminals.h"
namespace gd {
class Expression;
class ObjectsContainer;
@@ -29,8 +28,6 @@ class ExpressionMetadata;
namespace gd {
using namespace gd::GrammarTerminals;
/** \brief Parse an expression, returning a tree of node corresponding
* to the parsed expression.
*
@@ -38,7 +35,7 @@ using namespace gd::GrammarTerminals;
* parser by refactoring out the dependency on gd::MetadataProvider (injecting
* instead functions to be called to query supported functions).
*
* \see gd::ExpressionParserError
* \see gd::ExpressionParserDiagnostic
* \see gd::ExpressionNode
*/
class GD_CORE_API ExpressionParser2 {
@@ -47,9 +44,14 @@ class GD_CORE_API 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.
*/
@@ -209,7 +211,7 @@ class GD_CORE_API ExpressionParser2 {
}
SkipIfChar(IsClosingParenthesis);
return factor;
} else if (CheckIfChar(IsAllowedInIdentifier)) {
} else if (IsIdentifierAllowedChar()) {
return Identifier();
}
@@ -262,11 +264,12 @@ class GD_CORE_API ExpressionParser2 {
} else if (CheckIfChar(IsDot)) {
ExpressionParserLocation dotLocation = SkipChar();
SkipAllWhitespaces();
return ObjectFunctionOrBehaviorFunctionOrVariable(
return ObjectFunctionOrBehaviorFunction(
name, nameLocation, dotLocation);
} else if (CheckIfChar(IsOpeningSquareBracket)) {
return Variable(name, nameLocation);
} else {
}
else {
auto identifier = gd::make_unique<IdentifierNode>(name);
identifier->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition());
@@ -277,11 +280,8 @@ class GD_CORE_API ExpressionParser2 {
std::unique_ptr<VariableNode> Variable(const gd::String &name, gd::ExpressionParserLocation nameLocation) {
auto variable = gd::make_unique<VariableNode>(name);
if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
variable->child = VariableAccessorOrVariableBracketAccessor();
variable->child->parent = variable.get();
}
variable->child = VariableAccessorOrVariableBracketAccessor();
variable->child->parent = variable.get();
variable->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition());
@@ -305,12 +305,8 @@ class GD_CORE_API ExpressionParser2 {
"bracket for each opening bracket."));
}
SkipIfChar(IsClosingSquareBracket);
SkipAllWhitespaces();
if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
}
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->location =
ExpressionParserLocation(childStartPosition, GetCurrentPosition());
@@ -319,18 +315,11 @@ class GD_CORE_API ExpressionParser2 {
auto dotLocation = SkipChar();
SkipAllWhitespaces();
auto identifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false);
auto identifierAndLocation = ReadIdentifierName();
auto child =
gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
if (identifierAndLocation.name.empty()) {
child->diagnostic = RaiseSyntaxError(_("A name should be entered after the dot."));
}
SkipAllWhitespaces();
if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
}
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
child->nameLocation = identifierAndLocation.location;
child->dotLocation = dotLocation;
child->location =
@@ -339,11 +328,7 @@ class GD_CORE_API ExpressionParser2 {
return std::move(child);
}
// Should never happen, unless a node called this function without checking if the current character
// was a dot or an opening bracket - this means there is an error in the grammar.
auto unrecognisedNode = gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>();
unrecognisedNode->diagnostic = RaiseSyntaxError(_("A dot or bracket was expected here."));
return std::move(unrecognisedNode);
return std::move(gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>());
}
std::unique_ptr<FunctionCallNode> FreeFunction(
@@ -370,33 +355,27 @@ class GD_CORE_API ExpressionParser2 {
}
std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
ObjectFunctionOrBehaviorFunctionOrVariable(
ObjectFunctionOrBehaviorFunction(
const gd::String &parentIdentifier,
const ExpressionParserLocation &parentIdentifierLocation,
const ExpressionParserLocation &parentIdentifierDotLocation) {
auto childIdentifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false);
auto childIdentifierAndLocation = ReadIdentifierName();
const gd::String &childIdentifierName = childIdentifierAndLocation.name;
const auto &childIdentifierNameLocation =
childIdentifierAndLocation.location;
std::unique_ptr<gd::ExpressionParserError> emptyNameError = childIdentifierName.empty() ?
RaiseSyntaxError(_("A name should be entered after the dot.")) : nullptr;
SkipAllWhitespaces();
if (IsNamespaceSeparator()) {
ExpressionParserLocation namespaceSeparatorLocation =
SkipNamespaceSeparator();
SkipAllWhitespaces();
auto behaviorFunction = BehaviorFunction(parentIdentifier,
return BehaviorFunction(parentIdentifier,
childIdentifierName,
parentIdentifierLocation,
parentIdentifierDotLocation,
childIdentifierNameLocation,
namespaceSeparatorLocation);
if (emptyNameError) behaviorFunction->diagnostic = std::move(emptyNameError);
return std::move(behaviorFunction);
} else if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar();
@@ -405,7 +384,7 @@ class GD_CORE_API ExpressionParser2 {
childIdentifierName);
auto parametersNode = Parameters(function.get(), parentIdentifier);
function->parameters = std::move(parametersNode.parameters),
function->diagnostic = emptyNameError ? std::move(emptyNameError) : std::move(parametersNode.diagnostic);
function->diagnostic = std::move(parametersNode.diagnostic);
function->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
@@ -418,8 +397,6 @@ class GD_CORE_API ExpressionParser2 {
return std::move(function);
} else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) {
auto variable = gd::make_unique<VariableNode>(parentIdentifier);
variable->diagnostic = std::move(emptyNameError);
auto child =
gd::make_unique<VariableAccessorNode>(childIdentifierName);
child->child = VariableAccessorOrVariableBracketAccessor();
@@ -440,12 +417,17 @@ class GD_CORE_API ExpressionParser2 {
auto node = gd::make_unique<IdentifierNode>(
parentIdentifier, childIdentifierName);
if (!CheckIfChar(IsParameterSeparator) && !CheckIfChar(IsClosingParenthesis) && !IsEndReached()) {
node->diagnostic = RaiseSyntaxError(
_("An opening parenthesis (for an object expression), a double colon "
"(:: for a behavior expression), a dot or an opening bracket (for "
"a child variable) where expected."));
}
node->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
node->identifierNameLocation = parentIdentifierLocation;
node->identifierNameDotLocation = parentIdentifierDotLocation;
node->childIdentifierNameLocation = childIdentifierNameLocation;
node->diagnostic = std::move(emptyNameError);
return std::move(node);
}
@@ -518,6 +500,11 @@ class GD_CORE_API ExpressionParser2 {
std::vector<std::unique_ptr<ExpressionNode>> parameters;
gd::String lastObjectName = "";
// By convention, object is always the first parameter, and behavior the
// second one.
size_t parameterIndex =
WrittenParametersFirstIndex(objectName, behaviorName);
bool previousCharacterIsParameterSeparator = false;
while (!IsEndReached()) {
SkipAllWhitespaces();
@@ -536,6 +523,7 @@ class GD_CORE_API ExpressionParser2 {
SkipAllWhitespaces();
previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator);
SkipIfChar(IsParameterSeparator);
parameterIndex++;
}
ExpressionParserLocation invalidClosingParenthesisLocation;
@@ -547,28 +535,28 @@ class GD_CORE_API ExpressionParser2 {
}
///@}
std::unique_ptr<ExpressionParserError> ValidateOperator(
std::unique_ptr<ExpressionParserDiagnostic> ValidateOperator(
gd::String::value_type operatorChar) {
if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' ||
operatorChar == '*') {
return std::unique_ptr<ExpressionParserError>(nullptr);
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::InvalidOperator,
"invalid_operator",
_("You've used an operator that is not supported. Operator should be "
"either +, -, / or *."),
GetCurrentPosition());
}
std::unique_ptr<ExpressionParserError> ValidateUnaryOperator(
std::unique_ptr<ExpressionParserDiagnostic> ValidateUnaryOperator(
gd::String::value_type operatorChar,
size_t position) {
if (operatorChar == '+' || operatorChar == '-') {
return std::unique_ptr<ExpressionParserError>(nullptr);
return gd::make_unique<ExpressionParserDiagnostic>();
}
return gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::InvalidOperator,
"invalid_operator",
_("You've used an \"unary\" operator that is not supported. Operator "
"should be "
"either + or -."),
@@ -618,6 +606,95 @@ class GD_CORE_API ExpressionParser2 {
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() {
// Namespace separator is a special kind of delimiter as it is 2 characters
// long
@@ -634,13 +711,13 @@ class GD_CORE_API ExpressionParser2 {
ExpressionParserLocation location;
};
IdentifierAndLocation ReadIdentifierName(bool allowDeprecatedSpacesInName = true) {
IdentifierAndLocation ReadIdentifierName() {
gd::String name;
size_t startPosition = currentPosition;
while (currentPosition < expression.size() &&
(CheckIfChar(IsAllowedInIdentifier)
(IsIdentifierAllowedChar()
// Allow whitespace in identifier name for compatibility
|| (allowDeprecatedSpacesInName && expression[currentPosition] == ' '))) {
|| expression[currentPosition] == ' ')) {
name += expression[currentPosition];
currentPosition++;
}
@@ -719,15 +796,13 @@ class GD_CORE_API ExpressionParser2 {
std::unique_ptr<ExpressionParserError> RaiseSyntaxError(
const gd::String &message) {
return std::move(gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::SyntaxError, message,
GetCurrentPosition()));
"syntax_error", message, GetCurrentPosition()));
}
std::unique_ptr<ExpressionParserError> RaiseTypeError(
const gd::String &message, size_t beginningPosition) {
return std::move(gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::MismatchedType, message,
beginningPosition, GetCurrentPosition()));
"type_error", message, beginningPosition, GetCurrentPosition()));
}
///@}

View File

@@ -6,5 +6,5 @@
#include "ExpressionParser2Node.h"
namespace gd {
gd::String ExpressionParserDiagnostic::noMessage = "";
}

View File

@@ -3,14 +3,14 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#ifndef GDCORE_EXPRESSIONPARSER2NODES_H
#define GDCORE_EXPRESSIONPARSER2NODES_H
#include <memory>
#include <vector>
#include "ExpressionParser2NodeWorker.h"
#include "GDCore/String.h"
namespace gd {
class Expression;
class ObjectsContainer;
@@ -36,61 +36,54 @@ struct GD_CORE_API ExpressionParserLocation {
private:
bool isValid;
size_t startPosition = 0;
size_t endPosition = 0;
size_t startPosition;
size_t endPosition;
};
/**
* \brief A diagnostic that can be attached to a gd::ExpressionNode.
*/
struct GD_CORE_API ExpressionParserDiagnostic {
virtual ~ExpressionParserDiagnostic() = default;
virtual bool IsError() { return false; }
virtual const gd::String &GetMessage() { return noMessage; }
virtual size_t GetStartPosition() { return 0; }
virtual size_t GetEndPosition() { return 0; }
private:
static gd::String noMessage;
};
/**
* \brief An error that can be attached to a gd::ExpressionNode.
*/
struct GD_CORE_API ExpressionParserError {
enum ErrorType {
SyntaxError,
InvalidOperator,
MismatchedType,
UndeclaredVariable,
UnknownIdentifier,
BracketsNotAllowedForObjects,
TooFewParameters,
TooManyParameters,
InvalidFunctionName,
MalformedVariableParameter,
MalformedObjectParameter,
UnknownParameterType,
MissingBehavior,
VariableNameCollision,
};
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
struct GD_CORE_API ExpressionParserError : public ExpressionParserDiagnostic {
ExpressionParserError(const gd::String &type_,
const gd::String &message_,
const ExpressionParserLocation &location_,
const gd::String &actualValue_ = "",
const gd::String &objectName_ = "")
: type(type_), message(message_), location(location_),
actualValue(actualValue_), objectName(objectName_){};
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
const gd::String &message_, size_t position_)
const ExpressionParserLocation &location_)
: type(type_), message(message_), location(location_){};
ExpressionParserError(const gd::String &type_,
const gd::String &message_,
size_t position_)
: type(type_), message(message_), location(position_){};
ExpressionParserError(gd::ExpressionParserError::ErrorType type_,
const gd::String &message_, size_t startPosition_,
ExpressionParserError(const gd::String &type_,
const gd::String &message_,
size_t startPosition_,
size_t endPosition_)
: type(type_), message(message_),
: type(type_),
message(message_),
location(startPosition_, endPosition_){};
virtual ~ExpressionParserError(){};
gd::ExpressionParserError::ErrorType GetType() { return type; }
const gd::String &GetMessage() { return message; }
const gd::String &GetObjectName() { return objectName; }
const gd::String &GetActualValue() { return actualValue; }
size_t GetStartPosition() { return location.GetStartPosition(); }
size_t GetEndPosition() { return location.GetEndPosition(); }
bool IsError() override { return true; }
const gd::String &GetMessage() override { return message; }
size_t GetStartPosition() override { return location.GetStartPosition(); }
size_t GetEndPosition() override { return location.GetEndPosition(); }
private:
gd::ExpressionParserError::ErrorType type;
private:
gd::String type;
gd::String message;
ExpressionParserLocation location;
gd::String objectName;
gd::String actualValue;
};
/**
@@ -102,7 +95,7 @@ struct GD_CORE_API ExpressionNode {
virtual ~ExpressionNode(){};
virtual void Visit(ExpressionParser2NodeWorker &worker){};
std::unique_ptr<ExpressionParserError> diagnostic;
std::unique_ptr<ExpressionParserDiagnostic> diagnostic;
ExpressionParserLocation location; ///< The location of the entire node. Some
/// nodes might have other locations
/// stored inside them. For example, a
@@ -196,7 +189,7 @@ struct GD_CORE_API IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode
*
* 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
*/
@@ -246,14 +239,13 @@ struct GD_CORE_API VariableAccessorOrVariableBracketAccessorNode : public Expres
};
/**
* \brief A variable, or object variable, with bracket accessor or at least 2 "dot" accessors.
*
* Example: `MyVariable["MyChildren"]` or `MyVariable.MyChildren.MyGrandChildren`.
* Example: `MyObject["MyVariable"]` or `MyObject.MyVariable.MyChildren`.
* \brief A variable with bracket accessor or at least 2 "dot" accessors.
*
* Example: MyVariable[MyChildren] or MyVariable.MyChildren.MyGranChildren.
*
* Other cases like "MyVariable" or "MyVariable.MyChildren" are IdentifierNode
* to allow handling ambiguities.
*
*
* \see gd::IdentifierNode
* \see gd::VariableAccessorNode
* \see gd::VariableBracketAccessorNode
@@ -275,7 +267,7 @@ 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
*/
struct GD_CORE_API VariableAccessorNode
@@ -293,7 +285,7 @@ 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"]).
*/
struct GD_CORE_API VariableBracketAccessorNode
@@ -311,10 +303,10 @@ struct GD_CORE_API VariableBracketAccessorNode
/**
* \brief The name of a function to call on an object or the behavior
* For example: "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
@@ -432,3 +424,5 @@ struct GD_CORE_API EmptyNode : public FunctionCallOrObjectFunctionNameOrEmptyNod
};
} // namespace gd
#endif

View File

@@ -8,7 +8,6 @@
#include <memory>
#include <vector>
#include "GDCore/Events/Parsers/ExpressionParser2Node.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
namespace gd {
@@ -44,11 +43,6 @@ class GD_CORE_API ExpressionParser2NodePrinter
*/
const gd::String& GetOutput() { return output; };
static gd::String PrintStringLiteral(const gd::String& str) {
return "\"" +
str.FindAndReplace("\\", "\\\\").FindAndReplace("\"", "\\\"") + "\"";
}
protected:
void OnVisitSubExpressionNode(SubExpressionNode& node) override {
output += "(";
@@ -75,7 +69,10 @@ class GD_CORE_API ExpressionParser2NodePrinter
}
void OnVisitNumberNode(NumberNode& node) override { output += node.number; }
void OnVisitTextNode(TextNode& node) override {
output += PrintStringLiteral(node.text);
output +=
"\"" +
node.text.FindAndReplace("\\", "\\\\").FindAndReplace("\"", "\\\"") +
"\"";
}
void OnVisitVariableNode(VariableNode& node) override {
output += node.name;
@@ -100,8 +97,8 @@ class GD_CORE_API ExpressionParser2NodePrinter
}
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
if (!node.behaviorFunctionName.empty()) {
output += node.objectName + "." + node.objectFunctionOrBehaviorName +
"::" + node.behaviorFunctionName;
output +=
node.objectName + "." + node.objectFunctionOrBehaviorName + "::" + node.behaviorFunctionName;
} else {
output += node.objectName + "." + node.objectFunctionOrBehaviorName;
}

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

@@ -182,10 +182,10 @@ void EventsListSerialization::UpdateInstructionsFromGD2x(
// Common updates for some parameters
const std::vector<gd::Expression>& parameters = instr.GetParameters();
for (std::size_t j = 0;
j < parameters.size() && j < metadata.parameters.GetParametersCount();
j < parameters.size() && j < metadata.parameters.size();
++j) {
if (metadata.parameters.GetParameter(j).GetType() == "relationalOperator" ||
metadata.parameters.GetParameter(j).GetType() == "operator") {
if (metadata.parameters[j].GetType() == "relationalOperator" ||
metadata.parameters[j].GetType() == "operator") {
if (j == parameters.size() - 1) {
std::cout << "ERROR: No more parameters after a [relational]operator "
"when trying to update an instruction from GD2.x";

View File

@@ -17,7 +17,7 @@ const gd::String& EventsCodeNameMangler::GetMangledObjectsListName(
return it->second;
}
gd::String partiallyMangledName = GetMangledNameWithForbiddenUnderscore(originalObjectName);
gd::String partiallyMangledName = originalObjectName;
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -43,15 +43,7 @@ const gd::String& EventsCodeNameMangler::GetExternalEventsFunctionMangledName(
return it->second;
}
gd::String partiallyMangledName = GetMangledNameWithForbiddenUnderscore(externalEventsName);
mangledExternalEventsNames[externalEventsName] = "GDExternalEvents" + partiallyMangledName;
return mangledExternalEventsNames[externalEventsName];
}
gd::String EventsCodeNameMangler::GetMangledNameWithForbiddenUnderscore(
const gd::String &name) {
gd::String partiallyMangledName = name;
gd::String partiallyMangledName = externalEventsName;
static const gd::String allowedCharacters =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
@@ -65,30 +57,11 @@ gd::String EventsCodeNameMangler::GetMangledNameWithForbiddenUnderscore(
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) {
return EventsCodeNameMangler::Get()->GetMangledObjectsListName(objectName);
}

View File

@@ -36,8 +36,6 @@ class GD_CORE_API EventsCodeNameMangler {
const gd::String &GetExternalEventsFunctionMangledName(
const gd::String &externalEventsName);
static gd::String GetMangledName(const gd::String &name);
static EventsCodeNameMangler *Get();
static void DestroySingleton();
@@ -46,9 +44,6 @@ class GD_CORE_API EventsCodeNameMangler {
virtual ~EventsCodeNameMangler(){};
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>
mangledObjectNames; ///< Memoized results of mangling for objects
std::unordered_map<gd::String, gd::String>

View File

@@ -66,7 +66,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
// Deprecated
extension
.AddAction("CopyArgumentToVariable",
_("Copy function parameter to variable"),
@@ -79,25 +78,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.SetHidden()
.MarkAsAdvanced();
extension
.AddAction("CopyArgumentToVariable2",
_("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("variable", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
// Deprecated
extension
.AddAction("CopyVariableToArgument",
_("Copy variable to function parameter"),
@@ -110,21 +93,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.SetHidden()
.MarkAsAdvanced();
extension
.AddAction("CopyVariableToArgument2",
_("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("variable", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
@@ -141,30 +109,27 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
extension
.AddExpression(
"GetArgumentAsNumber",
_("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."),
"",
"res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddStrExpression(
"GetArgumentAsString",
_("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."),
"",
"res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition(
@@ -178,8 +143,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
extension
.AddCondition(
@@ -193,8 +157,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetRelevantForFunctionEventsOnly();
}
} // namespace gd

View File

@@ -43,13 +43,6 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsVariablesExtension(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

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras"))
.SetIcon("res/conditions/camera24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect_black.svg");
.SetIcon("res/actions/effect24.png");
extension
.AddExpressionAndConditionAndAction(
@@ -327,25 +327,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0");
extension
.AddCondition(
"CameraZoom",
_("Camera zoom"),
_("Compare the zoom of a camera of a layer."),
_("Zoom of camera _PARAM2_ of layer _PARAM1_"),
"",
"res/conditions/camera24.png",
"res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Zoom")))
.MarkAsAdvanced();
// TODO Deprecated: hide this action in a future release.
extension
.AddAction(
"FixCamera",
@@ -357,7 +339,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"",
"res/actions/camera24.png",
"res/actions/camera.png")
.SetHidden()
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("objectPtr", _("Object"))
.AddParameter("expression",
@@ -405,7 +386,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("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", "")
@@ -463,58 +444,58 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension
.AddAction(
"SetLayerEffectParameter",
_("Effect property (number)"),
_("Change the value of a property of an effect.") + "\n" +
_("You can find the property names (and change the effect "
_("Effect parameter (number)"),
_("Change the value of a parameter of an effect.") + "\n" +
_("You can find the parameter names (and change the effect "
"names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"),
"res/actions/effect_black.svg",
"res/actions/effect_black.svg")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Property name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("expression", _("New value"))
.MarkAsAdvanced();
extension
.AddAction(
"SetLayerEffectStringParameter",
_("Effect property (string)"),
_("Change the value (string) of a property of an effect.") + "\n" +
_("You can find the property names (and change the effect "
_("Effect parameter (string)"),
_("Change the value (string) of a parameter of an effect.") + "\n" +
_("You can find the parameter names (and change the effect "
"names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"),
"res/actions/effect_black.svg",
"res/actions/effect_black.svg")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Property name"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("string", _("New value"))
.MarkAsAdvanced();
extension
.AddAction(
"SetLayerEffectBooleanParameter",
_("Effect property (enable or disable)"),
_("Enable or disable a property of an effect.") + "\n" +
_("You can find the property names (and change the effect "
_("Effect parameter (enable or disable)"),
_("Enable or disable a parameter of an effect.") + "\n" +
_("You can find the parameter names (and change the effect "
"names) in the effects window."),
_("Enable _PARAM3_ for effect _PARAM2_ of layer _PARAM1_: _PARAM4_"),
_("Effects"),
"res/actions/effect_black.svg",
"res/actions/effect_black.svg")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Property name"))
.AddParameter("yesorno", _("Enable this property"))
.AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("yesorno", _("Enable this parameter"))
.MarkAsAdvanced();
extension
@@ -523,8 +504,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("The effect on a layer is enabled"),
_("Effect _PARAM2_ on layer _PARAM1_ is enabled"),
_(""),
"res/actions/effect_black.svg",
"res/actions/effect_black.svg")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
@@ -537,8 +518,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Enable an effect on a layer"),
_("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"),
_("Effects"),
"res/actions/effect_black.svg",
"res/actions/effect_black.svg")
"res/actions/effect24.png",
"res/actions/effect.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
@@ -567,7 +548,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension
.AddAction(
"ChangeLayerTimeScale",
_("Layer time scale"),
_("Change layer time scale"),
_("Change the time scale applied to the objects of the layer."),
_("Set the time scale of layer _PARAM1_ to _PARAM2_"),
"",
@@ -613,7 +594,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension
.AddAction(
"SetLayerAmbientLightColor",
_("Ambient light color"),
_("Set the ambient light color"),
_("Set the ambient light color of the lighting layer in format "
"\"R;G;B\" string."),
_("Set the ambient color of the lighting layer _PARAM1_ to _PARAM2_"),

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/effect_black.svg");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"EffectBehavior",
_("Effect capability"),
"Effect",
_("Apply visual effects to objects."),
"",
"res/actions/effect_black.svg",
"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/effect_black.svg",
"res/actions/effect_black.svg")
.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/effect_black.svg",
"res/actions/effect_black.svg")
.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/effect_black.svg",
"res/actions/effect_black.svg")
.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/effect_black.svg",
"res/actions/effect_black.svg")
.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/effect_black.svg",
"res/actions/effect_black.svg")
.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/effect_black.svg");
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

@@ -68,22 +68,19 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
extension
.AddStrExpression("ToJSON",
_("Convert variable to JSON"),
_("Convert a variable to JSON"),
_("Convert scene variable to JSON"),
_("Convert a scene variable to JSON"),
_("JSON"),
"res/conditions/toujours24_black.png")
.AddParameter("variable", _("The variable to be stringified"),
"AllowUndeclaredVariable");
.AddParameter("scenevar", _("Scene variable to be stringified"));
// Deprecated
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"))
.SetHidden();
.AddParameter("globalvar", _("The global variable to be stringified"));
extension
.AddStrExpression("ObjectVarToJSON",
@@ -94,7 +91,6 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
.AddParameter("objectPtr", _("The object with the variable"))
.AddParameter("objectvar", _("The object variable to be stringified"));
// Deprecated
extension
.AddAction(
"JSONToVariableStructure",
@@ -106,10 +102,8 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("scenevar", _("Variable where store the JSON object"))
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
extension
.AddAction("JSONToGlobalVariableStructure",
_("Convert JSON to global variable"),
@@ -122,20 +116,6 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
.AddParameter("string", _("JSON string"))
.AddParameter("globalvar",
_("Global variable where store the JSON object"))
.MarkAsAdvanced()
.SetHidden();
extension
.AddAction(
"JSONToVariableStructure2",
_("Convert JSON to a variable"),
_("Parse a JSON object and store it into a variable"),
_("Convert JSON string _PARAM0_ and store it into variable _PARAM1_"),
"",
"res/actions/net24.png",
"res/actions/net.png")
.AddParameter("string", _("JSON string"))
.AddParameter("variable", _("Variable where to store the JSON object"))
.MarkAsAdvanced();
extension

View File

@@ -35,8 +35,6 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
.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"),
@@ -48,8 +46,7 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
"res/conditions/toujours_black.png")
.SetHelpPath("/all-features/advanced-conditions")
.AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Compatibility with GD <= 5.0.127
extension
@@ -92,16 +89,14 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
.SetCanHaveSubInstructions()
.MarkAsAdvanced();
extension
.AddCondition("Once",
_("Trigger once while true"),
_("Run actions only once, for each time the conditions "
"have been met."),
_("Trigger once"),
"",
"res/conditions/once24.png",
"res/conditions/once.png")
.SetHelpPath("/all-features/advanced-conditions/trigger-once");
extension.AddCondition(
"Once",
_("Trigger once while true"),
_("Run actions only once, for each time the conditions have been met."),
_("Trigger once"),
"",
"res/conditions/once24.png",
"res/conditions/once.png");
extension
.AddCondition("CompareNumbers",
@@ -119,9 +114,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
// Compatibility with GD <= 5.0.127
extension
.AddDuplicatedCondition("Egal",
"BuiltinCommonInstructions::CompareNumbers",
{.unscoped = true})
.AddDuplicatedCondition(
"Egal", "BuiltinCommonInstructions::CompareNumbers", {.unscoped = true})
.SetHidden();
// end of compatibility code
@@ -141,9 +135,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
// Compatibility with GD <= 5.0.127
extension
.AddDuplicatedCondition("StrEqual",
"BuiltinCommonInstructions::CompareStrings",
{.unscoped = true})
.AddDuplicatedCondition(
"StrEqual", "BuiltinCommonInstructions::CompareStrings", {.unscoped = true})
.SetHidden();
// end of compatibility code

View File

@@ -28,7 +28,7 @@ BuiltinExtensionsImplementer::ImplementsExternalLayoutsExtension(
.AddAction("CreateObjectsFromExternalLayout",
_("Create objects from an external layout"),
_("Create objects from an external layout."),
_("Create objects from the external layout named _PARAM1_ at position _PARAM2_;_PARAM3_;_PARAM4_"),
_("Create objects from the external layout named _PARAM1_"),
"",
"res/ribbon_default/externallayout32.png",
"res/ribbon_default/externallayout32.png")
@@ -38,8 +38,6 @@ BuiltinExtensionsImplementer::ImplementsExternalLayoutsExtension(
.SetDefaultValue("0")
.AddParameter("expression", _("Y position of the origin"), "", true)
.SetDefaultValue("0")
.AddParameter("expression", _("Z position of the origin"), "", true)
.SetDefaultValue("0")
.MarkAsAdvanced();
}

View File

@@ -69,12 +69,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension
.AddAction(
"EcrireFichierExp",
_("Save a value"),
_("Save the result of the expression in the stored data, in the "
_("Write a value"),
_("Write the result of the expression in the stored data, in the "
"specified element.\nSpecify the structure leading to the "
"element using / (example : Root/Level/Current)\nSpaces are "
"forbidden in element names."),
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
@@ -85,12 +85,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
extension
.AddAction(
"EcrireFichierTxt",
_("Save a text"),
_("Save the text in the specified storage, in the specified "
_("Write a text"),
_("Write the text in the specified storage, in the specified "
"element.\nSpecify "
"the structure leading to the element using / (example : "
"Root/Level/Current)\nSpaces are forbidden in element names."),
_("Save _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
_("Write _PARAM2_ in _PARAM1_ of storage _PARAM0_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
@@ -98,54 +98,34 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
.AddParameter("string", _("Group"))
.AddParameter("string", _("Text"));
// Deprecated
extension
.AddAction(
"LireFichierExp",
_("Load a value"),
_("Load the value saved in the specified element and store it in a "
_("Read a value"),
_("Read the value saved in the specified element and store it in a "
"scene "
"variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."),
_("Load _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
_("Read _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
.AddParameter("string", _("Storage name"))
.AddParameter("string", _("Group"))
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("scenevar", _("Scene variable"))
.SetHidden();
.AddParameter("scenevar", _("Scene variables"));
extension
.AddAction(
"ReadNumberFromStorage",
_("Load a value"),
_("Load the value saved in the specified element and store it in a "
"variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."),
_("Load _PARAM1_ from storage _PARAM0_ and store value in _PARAM3_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
.AddParameter("string", _("Storage name"))
.AddParameter("string", _("Group"))
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("variable", _("Variable"));
// Deprecated
extension
.AddAction(
"LireFichierTxt",
_("Load a text"),
_("Load the text saved in the specified element and store it in a "
_("Read a text"),
_("Read the text saved in the specified element and store it in a "
"scene "
"variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."),
_("Load _PARAM1_ from storage _PARAM0_ and store as text in "
_("Read _PARAM1_ from storage _PARAM0_ and store as text in "
"_PARAM3_"),
"",
"res/actions/fichier24.png",
@@ -153,26 +133,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsFileExtension(
.AddParameter("string", _("Storage name"))
.AddParameter("string", _("Group"))
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("scenevar", _("Scene variable"))
.SetHidden();
extension
.AddAction(
"ReadStringFromStorage",
_("Load a text"),
_("Load the text saved in the specified element and store it in a "
"variable.\nSpecify the structure leading to the element using / "
"(example : Root/Level/Current)\nSpaces are forbidden in element "
"names."),
_("Load _PARAM1_ from storage _PARAM0_ and store as text in "
"_PARAM3_"),
"",
"res/actions/fichier24.png",
"res/actions/fichier.png")
.AddParameter("string", _("Storage name"))
.AddParameter("string", _("Group"))
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("variable", _("Variable"));
.AddParameter("scenevar", _("Scene variables"));
extension
.AddAction("DeleteGroupFichier",

View File

@@ -35,8 +35,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"res/conditions/keyboard24.png",
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("key", _("Key to check"))
.SetHidden();
.AddParameter("key", _("Key"));
extension
.AddCondition("KeyReleased",
@@ -47,32 +46,33 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"res/conditions/keyboard24.png",
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("key", _("Key to check"))
.SetHidden();
.AddParameter("key", _("Key"));
extension
.AddCondition("KeyFromTextPressed",
_("Key pressed"),
_("Check if a key is pressed"),
_("Key pressed (text expression)"),
_("Check if a key, retrieved from the result of the "
"expression, is pressed"),
_("_PARAM1_ key is pressed"),
"",
"res/conditions/keyboard24.png",
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("keyboardKey", _("Key to check"))
.MarkAsSimple();
.AddParameter("string", _("Expression generating the key to check"))
.MarkAsAdvanced();
extension
.AddCondition("KeyFromTextReleased",
_("Key released"),
_("Check if a key was just released"),
_("Key released (text expression)"),
_("Check if a key, retrieved from the result of the "
"expression, was just released"),
_("_PARAM1_ key is released"),
"",
"res/conditions/keyboard24.png",
"res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("keyboardKey", _("Key to check"))
.MarkAsSimple();
.AddParameter("string", _("Expression generating the key to check"))
.MarkAsAdvanced();
extension
.AddCondition("AnyKeyPressed",

View File

@@ -151,8 +151,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension
.AddExpression("abs",
_("Absolute value"),
_("Return the non-negative value by removing the sign. "
"The absolute value of -8 is 8."),
_("Absolute value"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression"));

View File

@@ -252,8 +252,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("mouse", _("Button to check"))
.MarkAsSimple()
.SetHidden();
.MarkAsSimple();
// Support for deprecated names:
extension.AddDuplicatedCondition("SourisBouton", "MouseButtonPressed")
@@ -263,41 +262,49 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCondition("MouseButtonReleased",
_("Mouse button released"),
_("Check if the specified mouse button was released."),
_("Touch or _PARAM1_ mouse button is released"),
_("_PARAM1_ mouse button was released"),
"",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("mouse", _("Button to check"))
.MarkAsSimple()
.SetHidden();
.MarkAsSimple();
extension
.AddCondition(
"MouseButtonFromTextPressed",
_("Mouse button pressed or touch held"),
_("Check if the specified mouse button is pressed or "
"if a touch is in contact with the screen."),
_("Touch or _PARAM1_ mouse button is down"),
_("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("mouseButton", _("Button to check"))
.MarkAsSimple();
.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"),
_("Check if the specified mouse button was released."),
_("Touch or _PARAM1_ mouse button is released"),
_("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("mouseButton", _("Button to check"))
.MarkAsSimple();
.AddParameter("stringWithSelector",
_("Expression generating the mouse button to check"),
"[\"Left\", \"Right\", \"Middle\"]")
.SetParameterLongDescription(
_("Possible values are Left, Right and Middle."))
.MarkAsAdvanced();
extension
.AddExpressionAndCondition("number",
@@ -331,7 +338,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0");
// Deprecated
extension
.AddCondition(
"PopStartedTouch",
@@ -348,7 +354,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
// Deprecated
extension
.AddCondition(
"PopEndedTouch",
@@ -365,7 +370,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
// Deprecated
extension
.AddCondition(
"HasAnyTouchStarted",

View File

@@ -5,7 +5,6 @@
*/
#include "AllBuiltinExtensions.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
using namespace std;
namespace gd {
@@ -55,19 +54,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.AddCodeOnlyParameter("currentScene", "")
.MarkAsSimple();
extension
.AddCondition("DoesSceneExist",
_("Does scene exist"),
_("Check if a 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
.AddAction("Scene",
_("Change the scene"),
@@ -164,45 +150,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
"res/actions/window.png")
.SetHelpPath("/interface/scene-editor/events")
.AddCodeOnlyParameter("currentScene", "");
extension
.AddAction("PrioritizeLoadingOfScene",
_("Preload scene"),
_("Preload a scene resources as soon as possible in background."),
_("Preload scene _PARAM1_ in background"),
"",
"res/actions/hourglass_black.svg",
"res/actions/hourglass_black.svg")
.SetHelpPath("/all-features/resources-loading")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Name of the new scene"))
.MarkAsAdvanced();
extension.AddExpressionAndCondition("number",
"SceneLoadingProgress",
_("Scene loading progress"),
_("The progress of resources loading in background for a scene (between 0 and 1)."),
_("_PARAM0_ loading progress"),
_(""),
"res/actions/hourglass_black.svg")
.SetHelpPath("/all-features/resources-loading")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Scene name"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
extension
.AddCondition("AreSceneAssetsLoaded",
_("Scene preloaded"),
_("Check if scene resources have finished to load in background."),
_("Scene _PARAM1_ was preloaded in background"),
"",
"res/actions/hourglass_black.svg",
"res/actions/hourglass_black.svg")
.SetHelpPath("/all-features/resources-loading")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("sceneName", _("Scene name"))
.MarkAsAdvanced();
}
} // namespace gd

View File

@@ -6,6 +6,8 @@
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
#include <vector>
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include "GDCore/String.h"
namespace gd {

View File

@@ -4,11 +4,13 @@
* reserved. This project is released under the MIT License.
*/
#pragma once
#ifndef GDCORE_ANIMATION_H
#define GDCORE_ANIMATION_H
#include <vector>
#include "GDCore/String.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
namespace gd {
class Direction;
}
namespace gd {
@@ -91,3 +93,4 @@ class GD_CORE_API Animation {
};
} // namespace gd
#endif // GDCORE_ANIMATION_H

View File

@@ -110,11 +110,11 @@ void Direction::UnserializeFrom(const gd::SerializerElement& element) {
.GetBoolAttribute("automatic", true));
if (spriteElement.HasChild("CustomCollisionMask"))
sprite.SetFullImageCollisionMask(
sprite.SetCollisionMaskAutomatic(
!spriteElement.GetChild("CustomCollisionMask")
.GetBoolAttribute("custom", false));
else
sprite.SetFullImageCollisionMask(
sprite.SetCollisionMaskAutomatic(
!spriteElement.GetBoolAttribute("hasCustomCollisionMask", false));
std::vector<Polygon2d> mask;
@@ -173,7 +173,7 @@ void SaveSpritesDirection(const vector<Sprite>& sprites,
.SetAttribute("automatic", sprites[i].IsDefaultCenterPoint());
spriteElement.SetAttribute("hasCustomCollisionMask",
!sprites[i].IsFullImageCollisionMask());
!sprites[i].IsCollisionMaskAutomatic());
gd::SerializerElement& collisionMaskElement =
spriteElement.AddChild("customCollisionMask");

View File

@@ -3,12 +3,12 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#ifndef GDCORE_DIRECTION_H
#define GDCORE_DIRECTION_H
#include <vector>
#include "GDCore/String.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
namespace gd {
class Sprite;
class SerializerElement;
}
@@ -142,3 +142,4 @@ class GD_CORE_API Direction {
};
} // namespace gd
#endif // GDCORE_DIRECTION_H

View File

@@ -4,9 +4,7 @@
* reserved. This project is released under the MIT License.
*/
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include <iostream>
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
using namespace std;
@@ -16,10 +14,11 @@ namespace gd {
Point Sprite::badPoint("");
Sprite::Sprite()
: fullImageCollisionMask(false),
: automaticCollisionMask(true),
origine("origine"),
centre("centre"),
automaticCentre(true) {}
automaticCentre(true) {
}
Sprite::~Sprite(){};

View File

@@ -7,7 +7,6 @@
#ifndef SPRITE_H
#define SPRITE_H
#include <memory>
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
#include "GDCore/String.h"
@@ -44,7 +43,7 @@ class GD_CORE_API Sprite {
/**
* \brief Get the collision mask (custom or automatically generated owing to
* IsFullImageCollisionMask())
* IsCollisionMaskAutomatic())
*
* \warning If the image has not been loaded ( using LoadImage ) and the
* collision mask is set as automatic, the returned mask won't be correct.
@@ -67,7 +66,7 @@ class GD_CORE_API Sprite {
/**
* \brief Set the custom collision mask.
* Call then `SetFullImageCollisionMask(false)` to use it.
* Call then `SetCollisionMaskAutomatic(false)` to use it.
*/
void SetCustomCollisionMask(const std::vector<Polygon2d>& collisionMask);
@@ -75,15 +74,15 @@ class GD_CORE_API Sprite {
* \brief Return true if the collision mask is a bounding box, false if a
* custom collision mask is used.
*/
inline bool IsFullImageCollisionMask() const {
return fullImageCollisionMask;
inline bool IsCollisionMaskAutomatic() const {
return automaticCollisionMask;
}
/**
* \brief Un/set use of the custom collision mask.
*/
inline void SetFullImageCollisionMask(bool enabled) {
fullImageCollisionMask = enabled;
inline void SetCollisionMaskAutomatic(bool enabled) {
automaticCollisionMask = enabled;
};
/**
@@ -162,9 +161,9 @@ class GD_CORE_API Sprite {
private:
gd::String image; ///< Name of the image to be loaded in Image Manager.
bool fullImageCollisionMask; ///< True to use a bounding box wrapping the
///< whole image as collision mask. If false,
///< custom collision mask is used.
bool automaticCollisionMask; ///< True to use the custom collision mask.
///< Otherwise, a basic bounding box is returned
///< by GetCollisionMask()
std::vector<Polygon2d> customCollisionMask; ///< Custom collision mask
std::vector<Point> points; ///< List of the points used by the sprite

View File

@@ -1,164 +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/Extensions/Builtin/SpriteExtension/SpriteAnimationList.h"
#include <algorithm>
#include "GDCore/CommonTools.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
#include "GDCore/IDE/Project/ArbitraryResourceWorker.h"
#include "GDCore/Project/InitialInstance.h"
#include "GDCore/Project/Layout.h"
#include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/Localization.h"
namespace gd {
Animation SpriteAnimationList::badAnimation;
SpriteAnimationList::SpriteAnimationList()
: adaptCollisionMaskAutomatically(true) {}
SpriteAnimationList::~SpriteAnimationList(){};
void SpriteAnimationList::UnserializeFrom(const gd::SerializerElement& element) {
adaptCollisionMaskAutomatically =
element.GetBoolAttribute("adaptCollisionMaskAutomatically", false);
RemoveAllAnimations();
const gd::SerializerElement& animationsElement =
element.GetChild("animations", 0, "Animations");
animationsElement.ConsiderAsArrayOf("animation", "Animation");
for (std::size_t i = 0; i < animationsElement.GetChildrenCount(); ++i) {
const gd::SerializerElement& animationElement =
animationsElement.GetChild(i);
Animation newAnimation;
newAnimation.useMultipleDirections = animationElement.GetBoolAttribute(
"useMultipleDirections", false, "typeNormal");
newAnimation.SetName(animationElement.GetStringAttribute("name", ""));
// Compatibility with GD <= 3.3
if (animationElement.HasChild("Direction")) {
for (std::size_t j = 0;
j < animationElement.GetChildrenCount("Direction");
++j) {
Direction direction;
direction.UnserializeFrom(animationElement.GetChild("Direction", j));
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
newAnimation.SetDirection(direction,
newAnimation.GetDirectionsCount() - 1);
}
}
// End of compatibility code
else {
const gd::SerializerElement& directionsElement =
animationElement.GetChild("directions");
directionsElement.ConsiderAsArrayOf("direction");
for (std::size_t j = 0; j < directionsElement.GetChildrenCount(); ++j) {
Direction direction;
direction.UnserializeFrom(directionsElement.GetChild(j));
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
newAnimation.SetDirection(direction,
newAnimation.GetDirectionsCount() - 1);
}
}
AddAnimation(newAnimation);
}
}
void SpriteAnimationList::SerializeTo(gd::SerializerElement& element) const {
element.SetAttribute("adaptCollisionMaskAutomatically",
adaptCollisionMaskAutomatically);
// Animations
gd::SerializerElement& animationsElement = element.AddChild("animations");
animationsElement.ConsiderAsArrayOf("animation");
for (std::size_t k = 0; k < GetAnimationsCount(); k++) {
gd::SerializerElement& animationElement =
animationsElement.AddChild("animation");
animationElement.SetAttribute("useMultipleDirections",
GetAnimation(k).useMultipleDirections);
animationElement.SetAttribute("name", GetAnimation(k).GetName());
gd::SerializerElement& directionsElement =
animationElement.AddChild("directions");
directionsElement.ConsiderAsArrayOf("direction");
for (std::size_t l = 0; l < GetAnimation(k).GetDirectionsCount(); l++) {
GetAnimation(k).GetDirection(l).SerializeTo(
directionsElement.AddChild("direction"));
}
}
}
void SpriteAnimationList::ExposeResources(gd::ArbitraryResourceWorker& worker) {
for (std::size_t j = 0; j < GetAnimationsCount(); j++) {
for (std::size_t k = 0; k < GetAnimation(j).GetDirectionsCount(); k++) {
for (std::size_t l = 0;
l < GetAnimation(j).GetDirection(k).GetSpritesCount();
l++) {
worker.ExposeImage(
GetAnimation(j).GetDirection(k).GetSprite(l).GetImageName());
}
}
}
}
bool SpriteAnimationList::HasAnimationNamed(const gd::String &name) const {
return !name.empty() && (find_if(animations.begin(), animations.end(),
[&name](const Animation &animation) {
return animation.GetName() == name;
}) != animations.end());
}
const Animation& SpriteAnimationList::GetAnimation(std::size_t nb) const {
if (nb >= animations.size()) return badAnimation;
return animations[nb];
}
Animation& SpriteAnimationList::GetAnimation(std::size_t nb) {
if (nb >= animations.size()) return badAnimation;
return animations[nb];
}
void SpriteAnimationList::AddAnimation(const Animation& animation) {
animations.push_back(animation);
}
bool SpriteAnimationList::RemoveAnimation(std::size_t nb) {
if (nb >= GetAnimationsCount()) return false;
animations.erase(animations.begin() + nb);
return true;
}
void SpriteAnimationList::SwapAnimations(std::size_t firstIndex,
std::size_t secondIndex) {
if (firstIndex < animations.size() && secondIndex < animations.size() &&
firstIndex != secondIndex)
std::swap(animations[firstIndex], animations[secondIndex]);
}
void SpriteAnimationList::MoveAnimation(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= animations.size() || newIndex >= animations.size()) return;
auto animation = animations[oldIndex];
animations.erase(animations.begin() + oldIndex);
animations.insert(animations.begin() + newIndex, animation);
}
} // namespace gd

View File

@@ -1,124 +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 "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
namespace gd {
class InitialInstance;
class SerializerElement;
class PropertyDescriptor;
class ArbitraryResourceWorker;
} // namespace gd
namespace gd {
/**
* \brief A list of animations, containing directions with images and collision mask.
*
* It's used in the configuration of object that implements image-based animations.
*
* \see Animation
* \see Direction
* \see Sprite
* \ingroup SpriteObjectExtension
*/
class GD_CORE_API SpriteAnimationList {
public:
SpriteAnimationList();
virtual ~SpriteAnimationList();
void ExposeResources(gd::ArbitraryResourceWorker& worker);
/**
* \brief Return the animation at the specified index.
* If the index is out of bound, a "bad animation" object is returned.
*/
const Animation& GetAnimation(std::size_t nb) const;
/**
* \brief Return the animation at the specified index.
* If the index is out of bound, a "bad animation" object is returned.
*/
Animation& GetAnimation(std::size_t nb);
/**
* \brief Return the number of animations this object has.
*/
std::size_t GetAnimationsCount() const { return animations.size(); };
/**
* \brief Return true if an animation exists for a given name.
*/
bool HasAnimationNamed(const gd::String &name) const;
/**
* \brief Add an animation at the end of the existing ones.
*/
void AddAnimation(const Animation& animation);
/**
* \brief Remove an animation.
*/
bool RemoveAnimation(std::size_t nb);
/**
* \brief Remove all animations.
*/
void RemoveAllAnimations() { animations.clear(); }
/**
* \brief Return true if the object hasn't any animation.
*/
bool HasNoAnimations() const { return animations.empty(); }
/**
* \brief Swap the position of two animations
*/
void SwapAnimations(std::size_t firstIndex, std::size_t secondIndex);
/**
* \brief Change the position of the specified animation
*/
void MoveAnimation(std::size_t oldIndex, std::size_t newIndex);
/**
* \brief Return a read-only reference to the vector containing all the
* animation of the object.
*/
const std::vector<Animation>& GetAllAnimations() const { return animations; }
/**
* @brief Check if the collision mask adapts automatically to the animation.
*/
bool AdaptCollisionMaskAutomatically() const {
return adaptCollisionMaskAutomatically;
}
/**
* @brief Set if the collision mask adapts automatically to the animation.
*/
void SetAdaptCollisionMaskAutomatically(bool enable) {
adaptCollisionMaskAutomatically = enable;
}
void UnserializeFrom(const gd::SerializerElement& element);
void SerializeTo(gd::SerializerElement& element) const;
private:
mutable std::vector<Animation> animations;
static Animation badAnimation; //< Bad animation when an out of bound
// animation is requested.
bool adaptCollisionMaskAutomatically; ///< If set to true, the collision
///< mask will be automatically
///< adapted to the animation of the
///< object.
};
} // namespace gd

View File

@@ -2,7 +2,7 @@
* 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.
* LicenFse.
*/
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
@@ -30,18 +30,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddObject<SpriteObject>("Sprite",
_("Sprite"),
_("Animated object which can be used for "
"most elements of a game."),
"most elements of a game"),
"CppPlatform/Extensions/spriteicon.png")
.SetCategoryFullName(_("General"))
.SetOpenFullEditorLabel(_("Edit animations"))
.AddDefaultBehavior("EffectCapability::EffectBehavior")
.AddDefaultBehavior("ResizableCapability::ResizableBehavior")
.AddDefaultBehavior("ScalableCapability::ScalableBehavior")
.AddDefaultBehavior("FlippableCapability::FlippableBehavior")
.AddDefaultBehavior("OpacityCapability::OpacityBehavior")
.AddDefaultBehavior("AnimatableCapability::AnimatableBehavior");
.SetCategoryFullName(_("General"));
// Deprecated
obj.AddAction("Opacity",
_("Sprite opacity"),
_("Change the opacity of a Sprite. 0 is fully transparent, 255 "
@@ -56,10 +48,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity (0-255)")))
.MarkAsSimple()
.SetHidden();
.MarkAsSimple();
// Deprecated
obj.AddAction("ChangeAnimation",
_("Change the animation"),
_("Change the animation of the object, using the animation "
@@ -72,10 +62,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction("SetAnimationName",
_("Change the animation (by name)"),
_("Change the animation of the object, using the name of the "
@@ -87,7 +75,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name"))
.SetHidden()
.MarkAsAdvanced();
obj.AddAction(
@@ -120,7 +107,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
// Deprecated
obj.AddAction("PauseAnimation",
_("Pause the animation"),
_("Pause the animation of the object"),
@@ -130,10 +116,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction("PlayAnimation",
_("Play the animation"),
_("Play the animation of the object"),
@@ -143,10 +127,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction(
"ChangeAnimationSpeedScale",
_("Animation speed scale"),
@@ -161,10 +143,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.UseStandardOperatorParameters(
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Speed scale")))
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddAction("TourneVersPos",
"Rotate an object toward a position",
"Rotate an object towards a position.",
@@ -179,9 +159,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("expression", _("Angular speed (degrees per second)"))
.SetDefaultValue("0")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
.SetHidden(); // Deprecated
// Deprecated
obj.AddAction("ChangeScale",
_("Scale"),
_("Modify the scale of the specified object."),
@@ -195,10 +174,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddAction("ChangeScaleWidth",
_("Scale on X axis"),
_("Modify the scale of the width of an object."),
@@ -212,10 +189,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddAction("ChangeScaleHeight",
_("Scale on Y axis"),
_("Modify the scale of the height of an object."),
@@ -229,10 +204,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddAction("ChangeWidth",
_("Width"),
_("Change the width of a Sprite object."),
@@ -244,10 +217,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("Width",
_("Width"),
_("Compare the width of a Sprite object."),
@@ -259,10 +230,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddAction("ChangeHeight",
_("Height"),
_("Change the height of a Sprite object."),
@@ -274,10 +243,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("Height",
_("Height"),
_("Compare the height of a Sprite object."),
@@ -289,10 +256,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddAction("SetSize",
_("Size"),
_("Change the size of an object."),
@@ -304,10 +269,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"))
.AddParameter("expression", _("Width"))
.AddParameter("expression", _("Height"))
.MarkAsAdvanced()
.SetHidden();
.MarkAsAdvanced();
// Deprecated
obj.AddCondition(
"Animation",
_("Current animation"),
@@ -320,13 +283,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("AnimationName",
_("Current animation name"),
_("Check the animation played by the object."),
_("Check the animation by played by the object."),
_("The animation of _PARAM0_ is _PARAM1_"),
_("Animations and images"),
"res/conditions/animation24.png",
@@ -334,7 +295,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name"))
.SetHidden()
.MarkAsAdvanced();
obj.AddCondition(
@@ -368,7 +328,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("AnimStopped",
_("Animation paused"),
_("Check if the animation of an object is paused."),
@@ -378,10 +337,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddCondition("AnimationEnded",
_("Animation finished"),
_("Check if the animation being played by the Sprite object "
@@ -395,7 +352,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.MarkAsSimple()
.SetHidden();
// Deprecated
obj.AddCondition("AnimationEnded2",
_("Animation finished"),
_("Check if the animation being played by the Sprite object "
@@ -406,10 +362,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple();
// Deprecated
obj.AddCondition("ScaleWidth",
_("Scale on X axis"),
_("Compare the scale of the width of an object."),
@@ -417,7 +371,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Size"),
"res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number",
@@ -425,7 +379,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale (1 by default)")))
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("ScaleHeight",
_("Scale on Y axis"),
_("Compare the scale of the height of an object."),
@@ -433,7 +386,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Size"),
"res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters(
"number",
@@ -441,7 +394,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale (1 by default)")))
.MarkAsAdvanced();
// Deprecated
obj.AddCondition("Opacity",
_("Opacity"),
_("Compare the opacity of a Sprite, between 0 (fully "
@@ -456,8 +408,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity to compare to (0-255)")))
.MarkAsSimple()
.SetHidden();
.MarkAsSimple();
obj.AddCondition(
"BlendMode",
@@ -505,9 +456,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple();
obj.AddAction("FlipY",
@@ -517,9 +468,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple();
obj.AddCondition("FlippedX",
@@ -529,8 +480,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipX24.png",
"res/actions/flipX.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden();
.AddParameter("object", _("Object"), "Sprite");
obj.AddCondition("FlippedY",
_("Vertically flipped"),
@@ -539,10 +490,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"),
"res/actions/flipY24.png",
"res/actions/flipY.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden();
// Deprecated
.AddParameter("object", _("Object"), "Sprite");
obj.AddAction("TourneVers",
"Rotate an object toward another",
"Rotate an object towards another.",
@@ -554,7 +504,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPtr", "Rotate toward this object")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
.SetHidden(); // Deprecated
obj.AddExpression("X",
_("X position of a point"),
@@ -592,7 +542,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point"));
// Deprecated
obj.AddExpression("Direc",
_("Direction"),
_("Direction of the object"),
@@ -601,7 +550,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Direction",
_("Direction"),
_("Direction of the object"),
@@ -611,7 +559,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
// interface.
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Anim",
_("Animation"),
_("Animation of the object"),
@@ -620,22 +567,18 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Animation",
_("Animation"),
_("Animation of the object"),
_("Animations and images"),
"res/actions/animation.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddStrExpression("AnimationName",
_("Animation name"),
_("Name of the animation of the object"),
_("Animations and images"),
"res/actions/animation.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("Sprite",
@@ -652,13 +595,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("AnimationSpeedScale",
_("Animation speed scale"),
_("Animation speed scale"),
_("Animations and images"),
"res/actions/animation.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleX",
@@ -666,7 +607,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale of the width of an object"),
_("Size"),
"res/actions/scaleWidth_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleY",
@@ -674,17 +614,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale of the height of an object"),
_("Size"),
"res/actions/scaleHeight_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Opacity",
_("Opacity"),
_("Opacity"),
_("Opacity"),
"res/actions/opacity.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden();
.AddParameter("object", _("Object"), "Sprite");
extension
.AddCondition("Collision",

View File

@@ -23,45 +23,122 @@
namespace gd {
SpriteObject::SpriteObject()
: updateIfNotVisible(false),
preScale(1) {}
Animation SpriteObject::badAnimation;
SpriteObject::SpriteObject() : updateIfNotVisible(false) {}
SpriteObject::~SpriteObject(){};
void SpriteObject::DoUnserializeFrom(gd::Project& project,
const gd::SerializerElement& element) {
updateIfNotVisible = element.GetBoolAttribute("updateIfNotVisible", true);
preScale = element.GetDoubleAttribute("preScale", 1);
animations.UnserializeFrom(element);
RemoveAllAnimations();
const gd::SerializerElement& animationsElement =
element.GetChild("animations", 0, "Animations");
animationsElement.ConsiderAsArrayOf("animation", "Animation");
for (std::size_t i = 0; i < animationsElement.GetChildrenCount(); ++i) {
const gd::SerializerElement& animationElement =
animationsElement.GetChild(i);
Animation newAnimation;
newAnimation.useMultipleDirections = animationElement.GetBoolAttribute(
"useMultipleDirections", false, "typeNormal");
newAnimation.SetName(animationElement.GetStringAttribute("name", ""));
// Compatibility with GD <= 3.3
if (animationElement.HasChild("Direction")) {
for (std::size_t j = 0;
j < animationElement.GetChildrenCount("Direction");
++j) {
Direction direction;
direction.UnserializeFrom(animationElement.GetChild("Direction", j));
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
newAnimation.SetDirection(direction,
newAnimation.GetDirectionsCount() - 1);
}
}
// End of compatibility code
else {
const gd::SerializerElement& directionsElement =
animationElement.GetChild("directions");
directionsElement.ConsiderAsArrayOf("direction");
for (std::size_t j = 0; j < directionsElement.GetChildrenCount(); ++j) {
Direction direction;
direction.UnserializeFrom(directionsElement.GetChild(j));
newAnimation.SetDirectionsCount(newAnimation.GetDirectionsCount() + 1);
newAnimation.SetDirection(direction,
newAnimation.GetDirectionsCount() - 1);
}
}
AddAnimation(newAnimation);
}
}
void SpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
element.SetAttribute("updateIfNotVisible", updateIfNotVisible);
if (preScale != 1) {
element.SetAttribute("preScale", preScale);
// Animations
gd::SerializerElement& animationsElement = element.AddChild("animations");
animationsElement.ConsiderAsArrayOf("animation");
for (std::size_t k = 0; k < GetAnimationsCount(); k++) {
gd::SerializerElement& animationElement =
animationsElement.AddChild("animation");
animationElement.SetAttribute("useMultipleDirections",
GetAnimation(k).useMultipleDirections);
animationElement.SetAttribute("name", GetAnimation(k).GetName());
gd::SerializerElement& directionsElement =
animationElement.AddChild("directions");
directionsElement.ConsiderAsArrayOf("direction");
for (std::size_t l = 0; l < GetAnimation(k).GetDirectionsCount(); l++) {
GetAnimation(k).GetDirection(l).SerializeTo(
directionsElement.AddChild("direction"));
}
}
animations.SerializeTo(element);
}
std::map<gd::String, gd::PropertyDescriptor> SpriteObject::GetProperties()
const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties[_("Animate even if hidden or far from the screen")]
.SetValue(updateIfNotVisible ? "true" : "false")
.SetType("Boolean");
properties["PLEASE_ALSO_SHOW_EDIT_BUTTON_THANKS"].SetValue("");
return properties;
}
bool SpriteObject::UpdateProperty(const gd::String& name,
const gd::String& value) {
if (name == _("Animate even if hidden or far from the screen"))
updateIfNotVisible = value == "1";
return true;
}
void SpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) {
animations.ExposeResources(worker);
for (std::size_t j = 0; j < GetAnimationsCount(); j++) {
for (std::size_t k = 0; k < GetAnimation(j).GetDirectionsCount(); k++) {
for (std::size_t l = 0;
l < GetAnimation(j).GetDirection(k).GetSpritesCount();
l++) {
worker.ExposeImage(
GetAnimation(j).GetDirection(k).GetSprite(l).GetImageName());
}
}
}
}
std::map<gd::String, gd::PropertyDescriptor>
SpriteObject::GetInitialInstanceProperties(
const gd::InitialInstance& initialInstance) {
const gd::InitialInstance& initialInstance,
gd::Project& project,
gd::Layout& scene) {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties["animation"] =
gd::PropertyDescriptor(
@@ -75,7 +152,9 @@ SpriteObject::GetInitialInstanceProperties(
bool SpriteObject::UpdateInitialInstanceProperty(
gd::InitialInstance& initialInstance,
const gd::String& name,
const gd::String& value) {
const gd::String& value,
gd::Project& project,
gd::Layout& scene) {
if (name == "animation") {
initialInstance.SetRawDoubleProperty(
"animation", std::max(0, value.empty() ? 0 : value.To<int>()));
@@ -84,25 +163,42 @@ bool SpriteObject::UpdateInitialInstanceProperty(
return true;
}
size_t SpriteObject::GetAnimationsCount() const {
return animations.GetAnimationsCount();
const Animation& SpriteObject::GetAnimation(std::size_t nb) const {
if (nb >= animations.size()) return badAnimation;
return animations[nb];
}
const gd::String &SpriteObject::GetAnimationName(size_t index) const {
return animations.GetAnimation(index).GetName();
Animation& SpriteObject::GetAnimation(std::size_t nb) {
if (nb >= animations.size()) return badAnimation;
return animations[nb];
}
bool SpriteObject::HasAnimationNamed(
const gd::String &name) const {
return animations.HasAnimationNamed(name);
void SpriteObject::AddAnimation(const Animation& animation) {
animations.push_back(animation);
}
const SpriteAnimationList& SpriteObject::GetAnimations() const {
return animations;
bool SpriteObject::RemoveAnimation(std::size_t nb) {
if (nb >= GetAnimationsCount()) return false;
animations.erase(animations.begin() + nb);
return true;
}
SpriteAnimationList& SpriteObject::GetAnimations() {
return animations;
void SpriteObject::SwapAnimations(std::size_t firstIndex,
std::size_t secondIndex) {
if (firstIndex < animations.size() && secondIndex < animations.size() &&
firstIndex != secondIndex)
std::swap(animations[firstIndex], animations[secondIndex]);
}
void SpriteObject::MoveAnimation(std::size_t oldIndex, std::size_t newIndex) {
if (oldIndex >= animations.size() || newIndex >= animations.size()) return;
auto animation = animations[oldIndex];
animations.erase(animations.begin() + oldIndex);
animations.insert(animations.begin() + newIndex, animation);
}
} // namespace gd

View File

@@ -4,15 +4,18 @@
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteAnimationList.h"
#ifndef GDCORE_SPRITEOBJECT_H
#define GDCORE_SPRITEOBJECT_H
#include "GDCore/Extensions/Builtin/SpriteExtension/Animation.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Direction.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Sprite.h"
#include "GDCore/Project/Object.h"
namespace gd {
class InitialInstance;
class Object;
class Layout;
class Sprite;
class Animation;
class SerializerElement;
class PropertyDescriptor;
} // namespace gd
@@ -44,72 +47,102 @@ class GD_CORE_API SpriteObject : public gd::ObjectConfiguration {
void ExposeResources(gd::ArbitraryResourceWorker& worker) override;
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const override;
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
bool UpdateProperty(const gd::String& name,
const gd::String& value) override;
std::map<gd::String, gd::PropertyDescriptor> GetInitialInstanceProperties(
const gd::InitialInstance& position) override;
const gd::InitialInstance& position,
gd::Project& project,
gd::Layout& scene) override;
bool UpdateInitialInstanceProperty(gd::InitialInstance& position,
const gd::String& name,
const gd::String& value) override;
const gd::String& value,
gd::Project& project,
gd::Layout& scene) override;
size_t GetAnimationsCount() const override;
const gd::String &GetAnimationName(size_t index) const override;
bool HasAnimationNamed(const gd::String &animationName) const override;
/**
* \brief Return the animation configuration.
/** \name Animations
* Methods related to animations management
*/
const SpriteAnimationList& GetAnimations() const;
///@{
/**
* @brief Return the animation configuration.
* \brief Return the animation at the specified index.
* If the index is out of bound, a "bad animation" object is returned.
*/
SpriteAnimationList& GetAnimations();
const Animation& GetAnimation(std::size_t nb) const;
/**
* \brief Set if the object animation should be played even if the object is
* hidden or far from the camera.
* \brief Return the animation at the specified index.
* If the index is out of bound, a "bad animation" object is returned.
*/
void SetUpdateIfNotVisible(bool updateIfNotVisible_) {
updateIfNotVisible = updateIfNotVisible_;
}
Animation& GetAnimation(std::size_t nb);
/**
* \brief Check if the object animation should be played even if the object
* is hidden or far from the camera (false by default).
* \brief Return the number of animations this object has.
*/
std::size_t GetAnimationsCount() const { return animations.size(); };
/**
* \brief Add an animation at the end of the existing ones.
*/
void AddAnimation(const Animation& animation);
/**
* \brief Remove an animation.
*/
bool RemoveAnimation(std::size_t nb);
/**
* \brief Remove all animations.
*/
void RemoveAllAnimations() { animations.clear(); }
/**
* \brief Return true if the object hasn't any animation.
*/
bool HasNoAnimations() const { return animations.empty(); }
/**
* \brief Swap the position of two animations
*/
void SwapAnimations(std::size_t firstIndex, std::size_t secondIndex);
/**
* \brief Change the position of the specified animation
*/
void MoveAnimation(std::size_t oldIndex, std::size_t newIndex);
/**
* \brief Return a read-only reference to the vector containing all the
* animation of the object.
*/
const std::vector<Animation>& GetAllAnimations() const { return animations; }
/**
* \brief Set if the object animation should be played even if the object is hidden
* or far from the camera.
*/
void SetUpdateIfNotVisible(bool updateIfNotVisible_) { updateIfNotVisible = updateIfNotVisible_; }
/**
* \brief Check if the object animation should be played even if the object is hidden
* or far from the camera (false by default).
*/
bool GetUpdateIfNotVisible() const { return updateIfNotVisible; }
/**
* \brief Return the scale applied to object to evaluate the default dimensions.
*/
double GetPreScale() { return preScale; }
/**
* \brief Set the scale applied to object to evaluate the default dimensions.
*
* Its value must be strictly positive.
*/
void SetPreScale(double preScale_) {
if (preScale_ <= 0) {
return;
}
preScale = preScale_;
}
///@}
private:
void DoUnserializeFrom(gd::Project& project,
const gd::SerializerElement& element) override;
void DoSerializeTo(gd::SerializerElement& element) const override;
SpriteAnimationList animations;
mutable std::vector<Animation> animations;
bool updateIfNotVisible; ///< If set to true, ask the game engine to play
///< object animation even if hidden or far from
///< the screen.
double preScale;
///< object animation even if hidden or far from the
///< screen.
static Animation badAnimation; //< Bad animation when an out of bound
// animation is requested.
};
} // namespace gd
#endif // GDCORE_SPRITEOBJECT_H

View File

@@ -172,7 +172,7 @@ BuiltinExtensionsImplementer::ImplementsStringInstructionsExtension(
_("Search the last occurrence in a text, starting from a position"),
_("Search in a text the last occurrence, starting from a position "
"(return "
"the position of the result, from the beginning of the string, or "
" the position of the result, from the beginning of the string, or "
"-1 if not found)"),
"",
"res/conditions/toujours24_black.png")

View File

@@ -25,286 +25,29 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
extension.AddInstructionOrExpressionGroupMetadata(_("Variables"))
.SetIcon("res/conditions/var24.png");
extension
.AddCondition("NumberVariable",
_("Variable value"),
_("Compare the number value of a variable."),
_("The variable _PARAM0_"),
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions());
extension
.AddCondition("StringVariable",
_("Variable value"),
_("Compare the text (string) of a variable."),
_("The variable _PARAM0_"),
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions());
extension
.AddCondition(
"BooleanVariable",
_("Variable value"),
_("Compare the boolean value of a variable."),
_("The variable _PARAM0_ is _PARAM1_"),
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variableOrPropertyOrParameter", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
// This parameter allows to keep the operand expression
// when the editor switch between variable instructions.
.AddCodeOnlyParameter("trueorfalse", "");
extension
.AddAction("SetNumberVariable",
_("Change variable value"),
_("Modify the number value of a variable."),
_("the variable _PARAM0_"),
"",
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variableOrProperty", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions());
extension
.AddAction("SetStringVariable",
_("Change text variable"),
_("Modify the text (string) of a variable."),
_("the variable _PARAM0_"),
"",
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variableOrProperty", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions());
extension
.AddAction(
"SetBooleanVariable",
_("Change boolean variable"),
_("Modify the boolean value of a variable."),
_("Change the variable _PARAM0_: _PARAM1_"),
"",
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variableOrProperty", _("Variable"))
.AddParameter("operator", _("Value"), "boolean")
// This parameter allows to keep the operand expression
// when the editor switch between variable instructions.
.AddCodeOnlyParameter("trueorfalse", "");
extension
.AddCondition(
"VariableChildCount",
_("Number of children"),
_("Compare the number of children in an array variable."),
_("The number of children in the array variable _PARAM0_"),
_("Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variable", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddCondition("VariableChildExists2",
_("Child existence"),
_("Check if the specified child of the structure "
"variable exists."),
_("Child _PARAM1_ of variable _PARAM0_ exists"),
_("Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("variable", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction(
"RemoveVariableChild",
_("Remove a child"),
_("Remove a child from a structure variable."),
_("Remove child _PARAM1_ from structure variable _PARAM0_"),
_("Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction("ClearVariableChildren",
_("Clear children"),
_("Remove all the children from the structure or array "
"variable."),
_("Clear children from variable _PARAM0_"),
_("Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction("PushVariable",
_("Add existing variable"),
_("Adds an existing variable at the end of an array "
"variable."),
_("Add variable _PARAM1_ to array variable _PARAM0_"),
_("Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("variable", _("Variable with the content to add"))
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction(
"PushString",
_("Add text variable"),
_("Adds a text (string) at the end of a array variable."),
_("Add the value _PARAM1_ to array variable _PARAM0_"),
_("Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction("PushNumber",
_("Add variable array value"),
_("Adds a number at the end of an array variable."),
_("Add the value _PARAM1_ to array variable _PARAM0_"),
_("Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction("PushBoolean",
_("Add boolean variable"),
_("Adds a boolean at the end of an array variable."),
_("Add the value _PARAM1_ to array variable _PARAM0_"),
_("Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddAction("RemoveVariableAt",
_("Remove variable by index"),
_("Removes a variable at the specified index of an array "
"variable."),
_("Remove variable at index _PARAM1_ from array "
"variable _PARAM0_"),
_("Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced();
extension
.AddStrExpression(
"VariableFirstString",
_("First text child"),
_("Get the value of the first element of an array variable, if "
"it is a text (string)."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
extension
.AddExpression(
"VariableFirstNumber",
_("First number child"),
_("Get the value of the first element of an array variable, if "
"it is a number."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
extension
.AddStrExpression(
"VariableLastString",
_("Last text child"),
_("Get the value of the last element of an array variable, if "
"it is a text (string)."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
extension
.AddExpression(
"VariableLastNumber",
_("Last number child"),
_("Get the value of the last element of an array variable, if "
"it is a number."),
_("Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/");
// Legacy instructions
extension
.AddCondition("VarScene",
_("Number variable"),
_("Compare the number value of a scene variable."),
_("The number of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
"number", ParameterOptions::MakeNewOptions());
extension
.AddCondition("VarSceneTxt",
_("Text variable"),
_("Compare the text (string) of a scene variable."),
_("The text of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
"string", ParameterOptions::MakeNewOptions());
extension
.AddCondition(
@@ -312,14 +55,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Boolean variable"),
_("Compare the boolean value of a scene variable."),
_("The boolean value of scene variable _PARAM0_ is _PARAM1_"),
_("External variables Scene variables"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetDefaultValue("true");
extension
.AddCondition("VariableChildExists",
@@ -327,14 +68,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Check if the specified child of the scene structure "
"variable exists."),
_("Child _PARAM1_ of scene variable _PARAM0_ exists"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -343,14 +81,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Check if the specified child of the global structure "
"variable exists."),
_("Child _PARAM1_ of global variable _PARAM0_ exists"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("string", _("Name of the child"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -358,7 +93,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"Variable defined",
"Test if the scene variable exists.",
"Scene variable _PARAM0_ is defined",
_("External variables Scene variables"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddCodeOnlyParameter("currentScene", "")
@@ -370,14 +105,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Number variable"),
_("Compare the number value of a global variable."),
_("the global variable _PARAM0_"),
_("External variables Global variables"),
_("Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -385,14 +118,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Text variable"),
_("Compare the text (string) of a global variable."),
_("the text of the global variable _PARAM0_"),
_("External variables Global variables"),
_("Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardRelationalOperatorParameters(
"string", ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -401,21 +132,19 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Boolean variable"),
_("Compare the boolean value of a global variable."),
_("The boolean value of global variable _PARAM0_ is _PARAM1_"),
_("External variables Global variables"),
_("Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("trueorfalse", _("Check if the value is"))
.SetDefaultValue("true")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.SetDefaultValue("true");
extension
.AddCondition("VarGlobalDef",
"Variable defined",
"Test if a global variable exists.",
"Global variable _PARAM0_ is defined",
_("External variables Global variables"),
_("Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddCodeOnlyParameter("currentScene", "")
@@ -428,28 +157,24 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change number variable"),
_("Modify the number value of a scene variable."),
_("the scene variable _PARAM0_"),
_("External variables Scene variables"),
_("Scene variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
ParameterOptions::MakeNewOptions());
extension
.AddAction("ModVarSceneTxt",
_("Change text variable"),
_("Modify the text (string) of a scene variable."),
_("the text of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("Scene variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
ParameterOptions::MakeNewOptions());
extension
.AddAction(
@@ -457,13 +182,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change boolean variable"),
_("Modify the boolean value of a scene variable."),
_("Set the boolean value of scene variable _PARAM0_ to _PARAM1_"),
_("External variables Scene variables"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.AddParameter("trueorfalse", _("New Value:"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("trueorfalse", _("New Value:"));
extension
.AddAction("ToggleSceneVariableAsBoolean",
@@ -472,26 +195,22 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("If it was true, it will become false, and if it was "
"false it will become true."),
_("Toggle the boolean value of scene variable _PARAM0_"),
_("External variables Scene variables"),
_("Scene variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("scenevar", _("Variable"));
extension
.AddAction("ModVarGlobal",
_("Change number variable"),
_("Modify the number value of a global variable."),
_("the global variable _PARAM0_"),
_("External variables Global variables"),
_("Global variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardOperatorParameters("number",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -499,14 +218,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change text variable"),
_("Modify the text (string) of a global variable."),
_("the text of global variable _PARAM0_"),
_("External variables Global variables"),
_("Global variables"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.UseStandardOperatorParameters("string",
ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -515,13 +232,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Change boolean variable"),
_("Modify the boolean value of a global variable."),
_("Set the boolean value of global variable _PARAM0_ to _PARAM1_"),
_("External variables Global variables"),
_("Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.AddParameter("trueorfalse", _("New Value:"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("trueorfalse", _("New Value:"));
extension
.AddAction("ToggleGlobalVariableAsBoolean",
@@ -530,12 +245,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("If it was true, it will become false, and if it was "
"false it will become true."),
_("Toggle the boolean value of global variable _PARAM0_"),
_("External variables Global variables"),
_("Global variables"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Variable"));
extension
.AddAction(
@@ -543,15 +256,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove a child"),
_("Remove a child from a scene structure variable."),
_("Remove child _PARAM1_ from scene structure variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.MarkAsAdvanced();
extension
.AddAction(
@@ -559,15 +269,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove a child"),
_("Remove a child from a global structure variable."),
_("Remove child _PARAM1_ from global structure variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Structure variable"))
.AddParameter("string", _("Child's name"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.MarkAsAdvanced()
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.MarkAsAdvanced();
extension
.AddAction("VariableClearChildren",
@@ -575,13 +282,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove all the children from the scene structure or array "
"variable."),
_("Clear children from scene variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -590,13 +294,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Remove all the children from the global structure or array "
"variable."),
_("Clear children from global variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Structure or array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -605,7 +306,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Adds an existing variable at the end of a scene array "
"variable."),
_("Add variable _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
@@ -613,9 +314,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -624,14 +322,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add text variable"),
_("Adds a text (string) at the end of a scene array variable."),
_("Add text _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -639,14 +334,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add number variable"),
_("Adds a number at the end of a scene array variable."),
_("Add number _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -654,14 +346,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add boolean variable"),
_("Adds a boolean at the end of a scene array variable."),
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -671,14 +360,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"variable."),
_("Remove variable at index _PARAM1_ from scene array "
"variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -687,15 +373,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Number of children"),
_("Compare the number of children in a scene array variable."),
_("The number of children in the array variable _PARAM0_"),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("scenevar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -704,12 +387,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("First text child"),
_("Get the value of the first element of a scene array variable, if "
"it is a text (string)."),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("scenevar", _("Array variable"));
extension
.AddExpression(
@@ -717,12 +397,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("First number child"),
_("Get the value of the first element of a scene array variable, if "
"it is a number."),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("scenevar", _("Array variable"));
extension
.AddStrExpression(
@@ -730,12 +407,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last text child"),
_("Get the value of the last element of a scene array variable, if "
"it is a text (string)."),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("scenevar", _("Array variable"));
extension
.AddExpression(
@@ -743,12 +417,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last number child"),
_("Get the value of the last element of a scene array variable, if "
"it is a number."),
_("External variables Scene variables Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("scenevar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("scenevar", _("Array variable"));
extension
.AddAction(
@@ -756,7 +427,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add existing variable"),
_("Adds an existing variable at the end of a global array variable."),
_("Add variable _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
@@ -764,9 +435,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
.SetParameterLongDescription(
_("The content of the variable will *be copied* and added at the "
"end of the array."))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -776,14 +444,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
"array variable."),
_("Remove variable at index _PARAM1_ from global array "
"variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Index to remove"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -792,14 +457,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add text variable"),
_("Adds a text (string) at the end of a global array variable."),
_("Add text _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("string", _("Text to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -807,14 +469,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add number variable"),
_("Adds a number at the end of a global array variable."),
_("Add number _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("expression", _("Number to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -822,14 +481,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Add boolean variable"),
_("Adds a boolean at the end of a global array variable."),
_("Add boolean _PARAM1_ to array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var24.png",
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.AddParameter("trueorfalse", _("Boolean to add"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -838,15 +494,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Number of children"),
_("Compare the number of children in a global array variable."),
_("The number of children of the array variable _PARAM0_"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/conditions/var24.png",
"res/conditions/var.png")
.AddParameter("globalvar", _("Array variable"))
.UseStandardRelationalOperatorParameters(
"number", ParameterOptions::MakeNewOptions())
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden()
.MarkAsAdvanced();
extension
@@ -854,24 +507,18 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("First text child"),
_("Value of the first element of a global array "
"variable, if it is a text (string) variable."),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Array variable"));
extension
.AddExpression("GlobalVariableFirstNumber",
_("First number child"),
_("Value of the first element of a global array "
"variable, if it is a number variable"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Array variable"));
extension
.AddStrExpression(
@@ -879,12 +526,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last text child"),
_("Value of the last element of a global array variable, if "
"it is a text (string) variable."),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Array variable"));
extension
.AddExpression(
@@ -892,73 +536,59 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsVariablesExtension(
_("Last number child"),
_("Value of the last element of a global array variable, if "
"it is a number variable"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Array variable"));
extension
.AddExpression("GlobalVariableChildCount",
_("Number of children"),
_("Number of children in a global array or "
"structure variable"),
_("External variables Global variables Arrays and structures"),
_("Global variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("globalvar", _("Array or structure variable"))
.SetHelpPath("/all-features/variables/structures-and-arrays/")
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Array or structure variable"));
extension
.AddExpression("VariableChildCount",
_("Number of children"),
_("Number of children in a scene array or "
"structure variable"),
_("Arrays and structures"),
_("Scene variables/Arrays and structures"),
"res/actions/var.png")
.AddParameter("variable", _("Array or structure variable"), "AllowUndeclaredVariable")
.SetHelpPath("/all-features/variables/structures-and-arrays/");
.AddParameter("scenevar", _("Array or structure variable"));
extension
.AddExpression("Variable",
_("Number variable"),
_("Number value of a scene variable"),
_("External variables Scene variables"),
_("Scene variables"),
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("scenevar", _("Variable"));
extension
.AddStrExpression("VariableString",
_("Text variable"),
_("Text of a scene variable"),
_("External variables Scene variables"),
_("Scene variables"),
"res/actions/var.png")
.AddParameter("scenevar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("scenevar", _("Variable"));
extension
.AddExpression("GlobalVariable",
_("Number variable"),
_("Number value of a global variable"),
_("External variables Global variables"),
_("Global variables"),
"res/actions/var.png")
.AddParameter("globalvar", _("Name of the global variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Name of the global variable"));
extension
.AddStrExpression("GlobalVariableString",
_("Text variable"),
_("Text of a global variable"),
_("External variables Global variables"),
_("Global variables"),
"res/actions/var.png")
.AddParameter("globalvar", _("Variable"))
.SetRelevantForFunctionEventsOnly()
.SetHidden();
.AddParameter("globalvar", _("Variable"));
}
} // namespace gd

View File

@@ -87,8 +87,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsWindowExtension(
extension
.AddAction(
"SetWindowSize",
_("Game window size"),
_("Changes the size of the game window. Note that this "
_("Change the size of the game window"),
_("This action changes the size of the game window. Note that this "
"will only work on platform supporting this operation: games "
"running in browsers or on mobile phones can not update their "
"window size. Game resolution can still be updated."),

View File

@@ -1,137 +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 <algorithm>
#include <functional>
#include <map>
#include <memory>
#include "GDCore/Events/Instruction.h"
#include "GDCore/String.h"
#include "ParameterMetadata.h"
#include "ParameterOptions.h"
namespace gd {
class Project;
class Layout;
class EventsCodeGenerator;
class EventsCodeGenerationContext;
class SerializerElement;
} // namespace gd
namespace gd {
/**
* \brief Describe user-friendly information about an expression or an
* instruction (action or condition), its parameters and the function name as
* well as other information for code generation.
*
* \ingroup Events
*/
class GD_CORE_API AbstractFunctionMetadata {
public:
AbstractFunctionMetadata(){};
virtual ~AbstractFunctionMetadata(){};
/**
* \see gd::InstructionMetadata::AddParameter
*/
virtual AbstractFunctionMetadata &
AddParameter(const gd::String &type, const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) = 0;
/**
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
virtual AbstractFunctionMetadata &
AddCodeOnlyParameter(const gd::String &type,
const gd::String &supplementaryInformation) = 0;
/**
* \see gd::InstructionMetadata::SetDefaultValue
*/
virtual AbstractFunctionMetadata &
SetDefaultValue(const gd::String &defaultValue) = 0;
/**
* \see gd::InstructionMetadata::SetParameterExtraInfo
*/
virtual AbstractFunctionMetadata &
SetParameterExtraInfo(const gd::String &defaultValue) = 0;
/**
* \see gd::InstructionMetadata::SetParameterLongDescription
*/
virtual AbstractFunctionMetadata &
SetParameterLongDescription(const gd::String &longDescription) = 0;
/**
* \see gd::InstructionMetadata::SetHidden
*/
virtual AbstractFunctionMetadata &SetHidden() = 0;
/**
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
virtual AbstractFunctionMetadata &SetPrivate() = 0;
/**
* Set that the instruction can be used in layouts or external events.
*/
virtual AbstractFunctionMetadata &SetRelevantForLayoutEventsOnly() = 0;
/**
* Set that the instruction can be used in function events.
*/
virtual AbstractFunctionMetadata &SetRelevantForFunctionEventsOnly() = 0;
/**
* Set that the instruction can be used in asynchronous function events.
*/
virtual AbstractFunctionMetadata &
SetRelevantForAsynchronousFunctionEventsOnly() = 0;
/**
* Set that the instruction can be used in custom object events.
*/
virtual AbstractFunctionMetadata &SetRelevantForCustomObjectEventsOnly() = 0;
/**
* \brief Set the function that should be called when generating the source
* code from events.
* \param functionName the name of the function to call
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
virtual AbstractFunctionMetadata &
SetFunctionName(const gd::String &functionName) = 0;
/**
* \brief Erase any existing include file and add the specified include.
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
* error prone.
*/
virtual AbstractFunctionMetadata &
SetIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Add a file to the already existing include files.
*/
virtual AbstractFunctionMetadata &
AddIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Get the files that must be included to use the instruction.
*/
virtual const std::vector<gd::String> &GetIncludeFiles() const = 0;
private:
};
} // namespace gd

View File

@@ -13,15 +13,12 @@
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Behavior.h"
#include "GDCore/Project/BehaviorsSharedData.h"
#include "GDCore/Project/PropertyDescriptor.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/MakeUnique.h"
#include "GDCore/Tools/Log.h"
namespace gd {
const std::map<gd::String, gd::PropertyDescriptor> BehaviorMetadata::badProperties;
BehaviorMetadata::BehaviorMetadata(
const gd::String& extensionNamespace_,
const gd::String& nameWithNamespace,
@@ -37,7 +34,8 @@ BehaviorMetadata::BehaviorMetadata(
className(className_),
iconFilename(icon24x24),
instance(instance_),
sharedDatasInstance(sharedDatasInstance_) {
sharedDatasInstance(sharedDatasInstance_),
isEventBased(false) {
SetFullName(gd::String(fullname_));
SetDescription(gd::String(description_));
SetDefaultName(gd::String(defaultName_));
@@ -50,16 +48,33 @@ BehaviorMetadata::BehaviorMetadata(
"BehaviorMetadata is valid for: " + nameWithNamespace);
}
if (instance) {
instance->SetTypeName(nameWithNamespace);
instance->InitializeContent();
}
if (sharedDatasInstance) {
sharedDatasInstance->SetTypeName(nameWithNamespace);
sharedDatasInstance->InitializeContent();
}
if (instance) instance->SetTypeName(nameWithNamespace);
if (sharedDatasInstance) sharedDatasInstance->SetTypeName(nameWithNamespace);
}
BehaviorMetadata::BehaviorMetadata(
const gd::String& extensionNamespace,
const gd::String& nameWithNamespace,
const gd::String& fullname_,
const gd::String& defaultName_,
const gd::String& description_,
const gd::String& group_,
const gd::String& icon24x24_): BehaviorMetadata(
extensionNamespace,
nameWithNamespace,
fullname_,
defaultName_,
description_,
group_,
icon24x24_,
// Class name is the name, actually unused
defaultName_,
// It is only used to get the name for GetName.
gd::make_unique<gd::Behavior>("", nameWithNamespace),
nullptr){
isEventBased = true;
};
gd::InstructionMetadata& BehaviorMetadata::AddCondition(
const gd::String& name,
const gd::String& fullname,
@@ -405,6 +420,10 @@ const gd::String& BehaviorMetadata::GetName() const {
}
gd::Behavior& BehaviorMetadata::Get() const {
if (isEventBased) {
gd::LogFatalError("Error: Event-based behaviors don't have blueprint. "
"This method should not never be called.");
}
if (!instance) {
gd::LogFatalError(
"Trying to get a behavior from a BehaviorMetadata that has no "
@@ -414,47 +433,12 @@ gd::Behavior& BehaviorMetadata::Get() const {
return *instance;
}
std::map<gd::String, gd::PropertyDescriptor> BehaviorMetadata::GetProperties() const {
if (!instance) {
return badProperties;
gd::BehaviorsSharedData* BehaviorMetadata::GetSharedDataInstance() const {
if (isEventBased) {
gd::LogFatalError("Error: Event-based behaviors don't have blueprint. "
"This method should not never be called.");
}
// TODO Properties should be declared on BehaviorMetadata directly.
// - Add 2 `properties` members (one for shared properties)
// - Add methods to declare new properties
return instance->GetProperties();
}
gd::BehaviorsSharedData* BehaviorMetadata::GetSharedDataInstance() const {
return sharedDatasInstance.get();
}
std::map<gd::String, gd::PropertyDescriptor> BehaviorMetadata::GetSharedProperties() const {
if (!sharedDatasInstance) {
return badProperties;
}
// TODO Properties should be declared on BehaviorMetadata directly.
// - Add 2 `properties` members (one for shared properties)
// - Add methods to declare new properties
return sharedDatasInstance->GetProperties();
}
const std::vector<gd::String>& BehaviorMetadata::GetRequiredBehaviorTypes() const {
requiredBehaviors.clear();
if (!instance) {
return requiredBehaviors;
}
for (auto& property : instance->GetProperties()) {
const String& propertyName = property.first;
const gd::PropertyDescriptor& propertyDescriptor = property.second;
if (propertyDescriptor.GetType() == "Behavior") {
const auto& extraInfos = propertyDescriptor.GetExtraInfo();
if (extraInfos.size() > 0) {
requiredBehaviors.push_back(extraInfos[0]);
}
}
}
return requiredBehaviors;
}
} // namespace gd

View File

@@ -3,23 +3,19 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "InstructionOrExpressionContainerMetadata.h"
#ifndef BEHAVIORMETADATA_H
#define BEHAVIORMETADATA_H
#include <map>
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h"
#include "GDCore/Project/QuickCustomization.h"
namespace gd {
class Behavior;
class BehaviorsSharedData;
class MultipleInstructionMetadata;
class InstructionMetadata;
class ExpressionMetadata;
class PropertyDescriptor;
} // namespace gd
namespace gd {
@@ -29,7 +25,7 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMetadata {
class GD_CORE_API BehaviorMetadata {
public:
BehaviorMetadata(
const gd::String& extensionNamespace,
@@ -42,10 +38,10 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& className_,
std::shared_ptr<gd::Behavior> instance,
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance);
/**
* \brief Construct a behavior metadata, without "blueprint" behavior.
*
*
* \note This is used by events based behaviors.
*/
BehaviorMetadata(
@@ -71,7 +67,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_) override;
const gd::String& smallicon_);
/**
* Declare a new action as being part of the behavior.
@@ -84,7 +80,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_) override;
const gd::String& smallicon_);
/**
* Declare a new condition as being part of the behavior.
@@ -95,7 +91,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_) override;
const gd::String& smallicon_);
/**
* Declare a new action as being part of the behavior.
@@ -106,7 +102,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& sentence_,
const gd::String& group_,
const gd::String& icon_,
const gd::String& smallicon_) override;
const gd::String& smallicon_);
/**
* Declare a new action as being part of the extension.
*/
@@ -114,7 +110,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_) override;
const gd::String& smallicon_);
/**
* Declare a new string expression as being part of the extension.
@@ -123,7 +119,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& fullname_,
const gd::String& description_,
const gd::String& group_,
const gd::String& smallicon_) override;
const gd::String& smallicon_);
/**
* \brief Declare a new expression and condition as being part of the
@@ -138,7 +134,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon) override;
const gd::String& icon);
/**
* \brief Declare a new expression, condition and action as being part of the
@@ -155,7 +151,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& description,
const gd::String& sentenceName,
const gd::String& group,
const gd::String& icon) override;
const gd::String& icon);
/**
* \brief Create a new action which is the duplicate of the specified one.
@@ -164,7 +160,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
* one.
*/
gd::InstructionMetadata& AddDuplicatedAction(
const gd::String& newActionName, const gd::String& copiedActionName) override;
const gd::String& newActionName, const gd::String& copiedActionName);
/**
* \brief Create a new condition which is the duplicate of the specified one.
@@ -174,7 +170,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
*/
gd::InstructionMetadata& AddDuplicatedCondition(
const gd::String& newConditionName,
const gd::String& copiedConditionName) override;
const gd::String& copiedConditionName);
/**
* \brief Create a new expression which is the duplicate of the specified one.
@@ -197,24 +193,22 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
const gd::String& newExpressionName,
const gd::String& copiedExpressionName);
BehaviorMetadata& SetFullName(const gd::String& fullname_) override;
BehaviorMetadata& SetFullName(const gd::String& fullname_);
BehaviorMetadata& SetDefaultName(const gd::String& defaultName_);
BehaviorMetadata& SetDescription(const gd::String& description_) override;
BehaviorMetadata& SetDescription(const gd::String& description_);
BehaviorMetadata& SetGroup(const gd::String& group_);
/**
* \brief Erase any existing include file and add the specified include.
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the behavior.
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
* error prone.
*/
BehaviorMetadata& SetIncludeFile(const gd::String& includeFile) override;
BehaviorMetadata& SetIncludeFile(const gd::String& includeFile);
/**
* \brief Add a file to the already existing include files.
*/
BehaviorMetadata& AddIncludeFile(const gd::String& includeFile) override;
BehaviorMetadata& AddIncludeFile(const gd::String& includeFile);
/**
* \brief Add a file to the already existing required files.
@@ -227,7 +221,7 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
* Get the help path of the behavior, relative to the GDevelop documentation
* root.
*/
const gd::String& GetHelpPath() const override { return helpPath; }
const gd::String& GetHelpPath() const { return helpPath; }
/**
* Set the help path of the behavior, relative to the GDevelop documentation
@@ -236,17 +230,17 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
* The behavior instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
BehaviorMetadata& SetHelpPath(const gd::String& path) override {
BehaviorMetadata& SetHelpPath(const gd::String& path) {
helpPath = path;
return *this;
}
const gd::String& GetName() const override;
const gd::String& GetFullName() const override { return fullname; }
const gd::String& GetName() const;
const gd::String& GetFullName() const { return fullname; }
const gd::String& GetDefaultName() const { return defaultName; }
const gd::String& GetDescription() const override { return description; }
const gd::String& GetDescription() const { return description; }
const gd::String& GetGroup() const { return group; }
const gd::String& GetIconFilename() const override { return iconFilename; }
const gd::String& GetIconFilename() const { return iconFilename; }
/**
* \brief Set the type of the object that this behavior can be used on.
@@ -263,16 +257,11 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
*/
const gd::String& GetObjectType() const { return objectType; }
/**
* \brief Get the types of the behaviors that are required by this behavior.
*/
const std::vector<gd::String>& GetRequiredBehaviorTypes() const;
/**
* Check if the behavior is private - it can't be used outside of its
* extension.
*/
bool IsPrivate() const override { return isPrivate; }
bool IsPrivate() const { return isPrivate; }
/**
* Set that the behavior is private - it can't be used outside of its
@@ -283,94 +272,43 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
return *this;
}
/**
* Check if the behavior is hidden - it can be used but not attached to
* objects by users.
*/
bool IsHidden() const { return isHidden; }
/**
* Set that the behavior is hidden - it can be used but not attached to
* objects by users.
*/
BehaviorMetadata &SetHidden() {
isHidden = true;
return *this;
}
QuickCustomization::Visibility GetQuickCustomizationVisibility() const {
return quickCustomizationVisibility;
}
BehaviorMetadata &SetQuickCustomizationVisibility(QuickCustomization::Visibility visibility) {
quickCustomizationVisibility = visibility;
return *this;
}
BehaviorMetadata &SetOpenFullEditorLabel(const gd::String& label) {
openFullEditorLabel = label;
return *this;
}
const gd::String& GetOpenFullEditorLabel() const {
return openFullEditorLabel;
}
/**
* \brief Return the associated gd::Behavior, handling behavior contents.
*
*
* \note Returns a dumb Behavior for events based behaviors as CustomBehavior
* are using EventBasedBehavior.
*/
gd::Behavior& Get() const;
/**
* \brief Called when the IDE wants to know about the custom properties of the
* behavior.
*
* \return a std::map with properties names as key.
* \see gd::PropertyDescriptor
*/
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const;
/**
* \brief Return the associated gd::BehaviorsSharedData, handling behavior
* shared data, if any (nullptr if none).
*
*
* \note Returns nullptr for events based behaviors as they don't declare
* shared data yet.
*/
gd::BehaviorsSharedData* GetSharedDataInstance() const;
/**
* \brief Called when the IDE wants to know about the custom shared properties
* of the behavior.
*
* \return a std::map with properties names as key.
* \see gd::PropertyDescriptor
*/
std::map<gd::String, gd::PropertyDescriptor> GetSharedProperties() const;
/**
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() override { return actionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllActions() { return actionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() override { return conditionsInfos; };
std::map<gd::String, gd::InstructionMetadata>& GetAllConditions() { return conditionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() override { return expressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllExpressions() { return expressionsInfos; };
/**
* \see gd::PlatformExtension::GetAllActions
*/
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() override { return strExpressionsInfos; };
std::map<gd::String, gd::ExpressionMetadata>& GetAllStrExpressions() { return strExpressionsInfos; };
std::map<gd::String, gd::InstructionMetadata> conditionsInfos;
std::map<gd::String, gd::InstructionMetadata> actionsInfos;
@@ -390,17 +328,14 @@ class GD_CORE_API BehaviorMetadata : public InstructionOrExpressionContainerMeta
gd::String group;
gd::String iconFilename;
gd::String objectType;
mutable std::vector<gd::String> requiredBehaviors;
bool isPrivate = false;
bool isHidden = false;
gd::String openFullEditorLabel;
QuickCustomization::Visibility quickCustomizationVisibility = QuickCustomization::Visibility::Default;
// TODO: Nitpicking: convert these to std::unique_ptr to clarify ownership.
std::shared_ptr<gd::Behavior> instance;
std::shared_ptr<gd::BehaviorsSharedData> sharedDatasInstance;
static const std::map<gd::String, gd::PropertyDescriptor> badProperties;
bool isEventBased;
};
} // namespace gd
#endif // BEHAVIORMETADATA_H

View File

@@ -65,8 +65,6 @@ class GD_CORE_API EffectMetadata {
/**
* \brief Clear any existing include file and add the specified include file.
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
* error prone.
*/
EffectMetadata& SetIncludeFile(const gd::String& includeFile);
@@ -185,10 +183,10 @@ class GD_CORE_API EffectMetadata {
gd::String fullname;
gd::String description;
std::vector<gd::String> includeFiles;
bool isMarkedAsNotWorkingForObjects = false;
bool isMarkedAsOnlyWorkingFor2D = false;
bool isMarkedAsOnlyWorkingFor3D = false;
bool isMarkedAsUnique = false;
bool isMarkedAsNotWorkingForObjects;
bool isMarkedAsOnlyWorkingFor2D;
bool isMarkedAsOnlyWorkingFor3D;
bool isMarkedAsUnique;
std::map<gd::String, gd::PropertyDescriptor> properties;
};

View File

@@ -19,8 +19,7 @@ EventMetadata::EventMetadata(const gd::String &name_,
: fullname(fullname_),
description(description_),
group(group_),
instance(instance_),
hasCustomCodeGenerator(false) {
instance(instance_) {
ClearCodeGenerationAndPreprocessing();
if (instance) instance->SetType(name_);
}

View File

@@ -83,7 +83,7 @@ class GD_CORE_API EventMetadata {
gd::String group;
std::shared_ptr<gd::BaseEvent> instance;
bool hasCustomCodeGenerator = false;
bool hasCustomCodeGenerator;
std::function<gd::String(gd::BaseEvent& event,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>

View File

@@ -5,7 +5,6 @@
*/
#include "ExpressionMetadata.h"
#include "GDCore/CommonTools.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/String.h"
namespace gd {
@@ -38,37 +37,45 @@ gd::ExpressionMetadata& ExpressionMetadata::AddParameter(
const gd::String& description,
const gd::String& supplementaryInformation,
bool parameterIsOptional) {
parameters.AddNewParameter("")
.SetType(type)
.SetDescription(description)
.SetCodeOnly(false)
.SetOptional(parameterIsOptional)
.SetExtraInfo(
gd::ParameterMetadata info;
info.SetType(type);
info.description = description;
info.codeOnly = false;
info.SetOptional(parameterIsOptional);
info.SetExtraInfo(
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& (supplementaryInformation.find(
PlatformExtension::GetNamespaceSeparator()) == gd::String::npos)
? (supplementaryInformation.empty()
? ""
: extensionNamespace + supplementaryInformation)
: supplementaryInformation));
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
supplementaryInformation //... so prefix it with the extension
// namespace.
)
: supplementaryInformation); // Otherwise don't change anything
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
parameters.push_back(info);
return *this;
}
gd::ExpressionMetadata &ExpressionMetadata::AddCodeOnlyParameter(
const gd::String &type, const gd::String &supplementaryInformation) {
parameters.AddNewParameter("").SetType(type).SetCodeOnly().SetExtraInfo(
supplementaryInformation);
gd::ExpressionMetadata& ExpressionMetadata::AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation) {
gd::ParameterMetadata info;
info.SetType(type);
info.codeOnly = true;
info.SetExtraInfo(supplementaryInformation);
parameters.push_back(info);
return *this;
}
gd::ExpressionMetadata& ExpressionMetadata::SetRequiresBaseObjectCapability(
const gd::String& capability) {
requiredBaseObjectCapability = capability;

View File

@@ -3,10 +3,9 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "AbstractFunctionMetadata.h"
#ifndef EXPRESSIONMETADATA_H
#define EXPRESSIONMETADATA_H
#if defined(GD_IDE_ONLY)
#include <functional>
#include <memory>
@@ -18,6 +17,7 @@ class Layout;
}
namespace gd {
/**
* \brief Information about how generate code for an expression
*/
@@ -27,7 +27,79 @@ class ExpressionCodeGenerationInformation {
: staticFunction(false), hasCustomCodeGenerator(false){};
virtual ~ExpressionCodeGenerationInformation(){};
// TODO Move these attributes to ExpressionMetadata.
/**
* \brief Set the function name which will be used when generating the code.
* \param functionName the name of the function to call
*/
ExpressionCodeGenerationInformation& SetFunctionName(
const gd::String& functionName) {
functionCallName = functionName;
return *this;
}
/**
* \brief Set that the function is static
*/
ExpressionCodeGenerationInformation& SetStatic() {
staticFunction = true;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionCodeGenerationInformation& SetIncludeFile(
const gd::String& includeFile) {
includeFiles.clear();
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionCodeGenerationInformation& AddIncludeFile(
const gd::String& includeFile) {
if (std::find(includeFiles.begin(), includeFiles.end(), includeFile) ==
includeFiles.end())
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return includeFiles;
};
/**
* \brief Set that the function must be generated using a custom code
* generator.
*/
ExpressionCodeGenerationInformation& SetCustomCodeGenerator(
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
codeGenerator) {
hasCustomCodeGenerator = true;
customCodeGenerator = codeGenerator;
return *this;
}
ExpressionCodeGenerationInformation& RemoveCustomCodeGenerator() {
hasCustomCodeGenerator = false;
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
emptyFunction;
customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return hasCustomCodeGenerator; }
bool staticFunction;
gd::String functionCallName;
bool hasCustomCodeGenerator;
@@ -35,6 +107,8 @@ class ExpressionCodeGenerationInformation {
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
customCodeGenerator;
private:
std::vector<gd::String> includeFiles;
};
@@ -44,7 +118,7 @@ class ExpressionCodeGenerationInformation {
*
* \ingroup Events
*/
class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
class GD_CORE_API ExpressionMetadata {
public:
/**
* Construct a new expression metadata.
@@ -70,7 +144,7 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
/**
* \brief Set the expression as not shown in the IDE.
*/
ExpressionMetadata& SetHidden() override;
ExpressionMetadata& SetHidden();
/**
* \brief Set the group of the instruction in the IDE.
@@ -105,7 +179,7 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
ExpressionMetadata& SetPrivate() override {
ExpressionMetadata& SetPrivate() {
isPrivate = true;
return *this;
}
@@ -142,7 +216,7 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in layouts or external events.
*/
ExpressionMetadata &SetRelevantForLayoutEventsOnly() override {
ExpressionMetadata &SetRelevantForLayoutEventsOnly() {
relevantContext = "Layout";
return *this;
}
@@ -150,7 +224,7 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in function events.
*/
ExpressionMetadata &SetRelevantForFunctionEventsOnly() override {
ExpressionMetadata &SetRelevantForFunctionEventsOnly() {
relevantContext = "Function";
return *this;
}
@@ -158,7 +232,7 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in asynchronous function events.
*/
ExpressionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
ExpressionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
relevantContext = "AsynchronousFunction";
return *this;
}
@@ -166,7 +240,7 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in custom object events.
*/
ExpressionMetadata &SetRelevantForCustomObjectEventsOnly() override {
ExpressionMetadata &SetRelevantForCustomObjectEventsOnly() {
relevantContext = "Object";
return *this;
}
@@ -174,17 +248,17 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
/**
* \see gd::InstructionMetadata::AddParameter
*/
gd::ExpressionMetadata &
AddParameter(const gd::String &type, const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) override;
gd::ExpressionMetadata& AddParameter(
const gd::String& type,
const gd::String& description,
const gd::String& supplementaryInformation = "",
bool parameterIsOptional = false);
/**
* \see gd::InstructionMetadata::AddCodeOnlyParameter
*/
gd::ExpressionMetadata &
AddCodeOnlyParameter(const gd::String &type,
const gd::String &supplementaryInformation) override;
gd::ExpressionMetadata& AddCodeOnlyParameter(
const gd::String& type, const gd::String& supplementaryInformation);
/**
* Set the default value used in editor (or if an optional parameter is empty
@@ -192,10 +266,8 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata &SetDefaultValue(const gd::String &defaultValue) override {
if (parameters.GetParametersCount() > 0) {
parameters.GetInternalVector().back()->SetDefaultValue(defaultValue);
}
ExpressionMetadata& SetDefaultValue(gd::String defaultValue_) {
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
return *this;
};
@@ -205,11 +277,9 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata &
SetParameterLongDescription(const gd::String &longDescription) override {
if (parameters.GetParametersCount() > 0) {
parameters.GetInternalVector().back()->SetLongDescription(longDescription);
}
ExpressionMetadata& SetParameterLongDescription(gd::String longDescription) {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
};
@@ -220,11 +290,8 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
*
* \see AddParameter
*/
ExpressionMetadata &SetParameterExtraInfo(
const gd::String &extraInfo) override {
if (parameters.GetParametersCount() > 0) {
parameters.GetInternalVector().back()->SetExtraInfo(extraInfo);
}
ExpressionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
}
@@ -245,6 +312,50 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
return requiredBaseObjectCapability;
};
/**
* \brief Set the function that should be called when generating the source
* code from events.
* \param functionName the name of the function to call
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
ExpressionCodeGenerationInformation& SetFunctionName(
const gd::String& functionName) {
return codeExtraInformation.SetFunctionName(functionName);
}
/**
* \brief Return the structure containing the information about code
* generation for the expression.
*/
ExpressionCodeGenerationInformation& GetCodeExtraInformation() {
return codeExtraInformation;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExpressionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
}
ExpressionCodeGenerationInformation codeExtraInformation;
bool IsShown() const { return shown; }
const gd::String& GetReturnType() const { return returnType; }
const gd::String& GetFullName() const { return fullname; }
@@ -252,109 +363,17 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
const gd::String& GetGroup() const { return group; }
const gd::String& GetSmallIconFilename() const { return smallIconFilename; }
const gd::ParameterMetadata& GetParameter(std::size_t id) const {
return parameters.GetParameter(id);
return parameters[id];
};
gd::ParameterMetadata& GetParameter(std::size_t id) {
return parameters.GetParameter(id);
return parameters[id];
};
std::size_t GetParametersCount() const { return parameters.GetParametersCount(); };
const gd::ParameterMetadataContainer& GetParameters() const {
std::size_t GetParametersCount() const { return parameters.size(); };
const std::vector<gd::ParameterMetadata>& GetParameters() const {
return parameters;
};
/**
* \brief Set the function name which will be used when generating the code.
* \param functionName the name of the function to call
*/
ExpressionMetadata& SetFunctionName(
const gd::String& functionName) override {
codeExtraInformation.functionCallName = functionName;
return *this;
}
/**
* \brief Return the name of the function which will be called in the generated code.
*/
const gd::String &GetFunctionName() {
return codeExtraInformation.functionCallName;
}
/**
* \brief Set that the function is static
*/
ExpressionMetadata& SetStatic() {
codeExtraInformation.staticFunction = true;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
* error prone.
*/
ExpressionMetadata& SetIncludeFile(
const gd::String& includeFile) override {
codeExtraInformation.includeFiles.clear();
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExpressionMetadata& AddIncludeFile(
const gd::String& includeFile) override {
if (std::find(codeExtraInformation.includeFiles.begin(), codeExtraInformation.includeFiles.end(), includeFile) ==
codeExtraInformation.includeFiles.end())
codeExtraInformation.includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String>& GetIncludeFiles() const override {
return codeExtraInformation.includeFiles;
};
/**
* \brief Set that the function must be generated using a custom code
* generator.
*/
ExpressionMetadata& SetCustomCodeGenerator(
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
codeGenerator) {
codeExtraInformation.hasCustomCodeGenerator = true;
codeExtraInformation.customCodeGenerator = codeGenerator;
return *this;
}
ExpressionMetadata& RemoveCustomCodeGenerator() {
codeExtraInformation.hasCustomCodeGenerator = false;
std::function<gd::String(const std::vector<gd::Expression>& parameters,
gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context)>
emptyFunction;
codeExtraInformation.customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return codeExtraInformation.hasCustomCodeGenerator; }
/**
* \brief Return the structure containing the information about code
* generation for the expression.
*
* \deprecated
*/
ExpressionMetadata& GetCodeExtraInformation() {
return *this;
}
ExpressionCodeGenerationInformation codeExtraInformation;
std::vector<gd::ParameterMetadata> parameters;
private:
gd::String returnType;
@@ -369,8 +388,9 @@ class GD_CORE_API ExpressionMetadata : public gd::AbstractFunctionMetadata {
bool isPrivate;
gd::String requiredBaseObjectCapability;
gd::String relevantContext;
gd::ParameterMetadataContainer parameters;
};
} // namespace gd
#endif
#endif // EXPRESSIONMETADATA_H

View File

@@ -8,8 +8,6 @@
#include <algorithm>
#include "GDCore/CommonTools.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/ParameterMetadataContainer.h"
#include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/Log.h"
@@ -66,19 +64,22 @@ InstructionMetadata& InstructionMetadata::AddParameter(
// For objects/behavior, the supplementary information
// parameter is an object/behavior type...
((gd::ParameterMetadata::IsObject(type) ||
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& (supplementaryInformation.find(
PlatformExtension::GetNamespaceSeparator()) == gd::String::npos)
? (supplementaryInformation.empty()
? ""
: extensionNamespace + supplementaryInformation)
: supplementaryInformation));
gd::ParameterMetadata::IsBehavior(type))
// Prefix with the namespace if it's not already there.
&& !(supplementaryInformation.rfind(extensionNamespace, 0) == 0))
? (supplementaryInformation.empty()
? ""
: extensionNamespace +
supplementaryInformation //... so prefix it with the
// extension
// namespace.
)
: supplementaryInformation); // Otherwise don't change anything
// TODO: Assert against supplementaryInformation === "emsc" (when running with
// Emscripten), and warn about a missing argument when calling addParameter.
parameters.AddParameter(info);
parameters.push_back(info);
return *this;
}
@@ -89,7 +90,7 @@ InstructionMetadata& InstructionMetadata::AddCodeOnlyParameter(
info.codeOnly = true;
info.SetExtraInfo(supplementaryInformation);
parameters.AddParameter(info);
parameters.push_back(info);
return *this;
}
@@ -103,7 +104,7 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
AddParameter(
"yesorno",
options.description.empty() ? _("New value") : options.description);
size_t valueParamIndex = parameters.GetParametersCount() - 1;
size_t valueParamIndex = parameters.size() - 1;
if (isObjectInstruction || isBehaviorInstruction) {
gd::String templateSentence = _("Set _PARAM0_ as <subject>: <value>");
@@ -128,8 +129,8 @@ InstructionMetadata& InstructionMetadata::UseStandardOperatorParameters(
options.description.empty() ? _("Value") : options.description,
options.typeExtraInfo);
size_t operatorParamIndex = parameters.GetParametersCount() - 2;
size_t valueParamIndex = parameters.GetParametersCount() - 1;
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;
if (isObjectInstruction || isBehaviorInstruction) {
gd::String templateSentence = _("Change <subject> of _PARAM0_: <operator> <value>");
@@ -182,14 +183,14 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
AddParameter(type,
options.description.empty() ? _("Value to compare") : options.description,
options.typeExtraInfo);
size_t operatorParamIndex = parameters.GetParametersCount() - 2;
size_t valueParamIndex = parameters.GetParametersCount() - 1;
size_t operatorParamIndex = parameters.size() - 2;
size_t valueParamIndex = parameters.size() - 1;
if (isObjectInstruction || isBehaviorInstruction) {
gd::String templateSentence = _("<subject> of _PARAM0_ <operator> <value>");
sentence =
templateSentence.FindAndReplace("<subject>", sentence.CapitalizeFirstLetter())
templateSentence.FindAndReplace("<subject>", sentence)
.FindAndReplace(
"<operator>",
"_PARAM" + gd::String::From(operatorParamIndex) + "_")
@@ -199,7 +200,7 @@ InstructionMetadata::UseStandardRelationalOperatorParameters(
gd::String templateSentence = _("<subject> <operator> <value>");
sentence =
templateSentence.FindAndReplace("<subject>", sentence.CapitalizeFirstLetter())
templateSentence.FindAndReplace("<subject>", sentence)
.FindAndReplace(
"<operator>",
"_PARAM" + gd::String::From(operatorParamIndex) + "_")

View File

@@ -4,17 +4,14 @@
* reserved. This project is released under the MIT License.
*/
#pragma once
#include "AbstractFunctionMetadata.h"
#ifndef INSTRUCTIONMETADATA_H
#define INSTRUCTIONMETADATA_H
#include <algorithm>
#include <functional>
#include <map>
#include <memory>
#include "GDCore/Events/Instruction.h"
#include "GDCore/Project/ParameterMetadataContainer.h"
#include "GDCore/String.h"
#include "ParameterMetadata.h"
#include "ParameterOptions.h"
@@ -36,7 +33,7 @@ namespace gd {
*
* \ingroup Events
*/
class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
class GD_CORE_API InstructionMetadata {
public:
/**
* Construct a new instruction metadata.
@@ -62,12 +59,12 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
const gd::String &GetDescription() const { return description; }
const gd::String &GetSentence() const { return sentence; }
const gd::String &GetGroup() const { return group; }
ParameterMetadata &GetParameter(size_t i) { return parameters.GetParameter(i); }
ParameterMetadata &GetParameter(size_t i) { return parameters[i]; }
const ParameterMetadata &GetParameter(size_t i) const {
return parameters.GetParameter(i);
return parameters[i];
}
size_t GetParametersCount() const { return parameters.GetParametersCount(); }
const ParameterMetadataContainer &GetParameters() const {
size_t GetParametersCount() const { return parameters.size(); }
const std::vector<ParameterMetadata> &GetParameters() const {
return parameters;
}
const gd::String &GetIconFilename() const { return iconFilename; }
@@ -99,7 +96,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
* Set that the instruction is private - it can't be used outside of the
* object/ behavior that it is attached too.
*/
InstructionMetadata &SetPrivate() override {
InstructionMetadata &SetPrivate() {
isPrivate = true;
return *this;
}
@@ -136,7 +133,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in layouts or external events.
*/
InstructionMetadata &SetRelevantForLayoutEventsOnly() override {
InstructionMetadata &SetRelevantForLayoutEventsOnly() {
relevantContext = "Layout";
return *this;
}
@@ -144,7 +141,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in function events.
*/
InstructionMetadata &SetRelevantForFunctionEventsOnly() override {
InstructionMetadata &SetRelevantForFunctionEventsOnly() {
relevantContext = "Function";
return *this;
}
@@ -152,7 +149,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in asynchronous function events.
*/
InstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() override {
InstructionMetadata &SetRelevantForAsynchronousFunctionEventsOnly() {
relevantContext = "AsynchronousFunction";
return *this;
}
@@ -160,7 +157,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
/**
* Set that the instruction can be used in custom object events.
*/
InstructionMetadata &SetRelevantForCustomObjectEventsOnly() override {
InstructionMetadata &SetRelevantForCustomObjectEventsOnly() {
relevantContext = "Object";
return *this;
}
@@ -195,7 +192,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
*
* Used mainly when an instruction is deprecated.
*/
InstructionMetadata &SetHidden() override {
InstructionMetadata &SetHidden() {
hidden = true;
return *this;
}
@@ -234,7 +231,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
const gd::String &type,
const gd::String &label,
const gd::String &supplementaryInformation = "",
bool parameterIsOptional = false) override;
bool parameterIsOptional = false);
/**
* \brief Add a parameter not displayed in editor.
@@ -248,7 +245,7 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
* \see EventsCodeGenerator::GenerateParametersCodes
*/
InstructionMetadata &AddCodeOnlyParameter(
const gd::String &type, const gd::String &supplementaryInformation) override;
const gd::String &type, const gd::String &supplementaryInformation);
/**
* \brief Set the default value used in editor (or if an optional parameter is
@@ -256,10 +253,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
*
* \see AddParameter
*/
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) override {
if (parameters.GetParametersCount() > 0) {
parameters.GetInternalVector().back()->SetDefaultValue(defaultValue_);
}
InstructionMetadata &SetDefaultValue(const gd::String &defaultValue_) {
if (!parameters.empty()) parameters.back().SetDefaultValue(defaultValue_);
return *this;
};
@@ -270,10 +265,9 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
* \see AddParameter
*/
InstructionMetadata &SetParameterLongDescription(
const gd::String &longDescription) override {
if (parameters.GetParametersCount() > 0) {
parameters.GetInternalVector().back()->SetLongDescription(longDescription);
}
const gd::String &longDescription) {
if (!parameters.empty())
parameters.back().SetLongDescription(longDescription);
return *this;
}
@@ -284,10 +278,8 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
*
* \see AddParameter
*/
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) override {
if (parameters.GetParametersCount() > 0) {
parameters.GetInternalVector().back()->SetExtraInfo(extraInfo);
}
InstructionMetadata &SetParameterExtraInfo(const gd::String &extraInfo) {
if (!parameters.empty()) parameters.back().SetExtraInfo(extraInfo);
return *this;
}
@@ -390,13 +382,128 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
/**
* \brief Defines information about how generate the code for an instruction
*/
class ExtraInformation {
class ExtraInformation {
public:
enum AccessType { Reference, MutatorAndOrAccessor, Mutators };
ExtraInformation() : accessType(Reference), hasCustomCodeGenerator(false){};
virtual ~ExtraInformation(){};
// TODO Move these attributes to InstructionMetadata.
/**
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
*/
ExtraInformation &SetFunctionName(const gd::String &functionName_) {
functionCallName = functionName_;
return *this;
}
/**
* Set the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*
* \param functionName the name of the function doing asynchronous work to
* call.
*/
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName_) {
asyncFunctionCallName = functionName_;
return *this;
}
/**
* Declare if the instruction being declared is somewhat manipulating in a
* standard way.
*/
ExtraInformation &SetManipulatedType(const gd::String &type_) {
type = type_;
return *this;
}
/**
* If InstructionMetadata::ExtraInformation::SetManipulatedType was called
* with "number" or "string", this function will tell the code generator the
* name of the getter function used to retrieve the data value.
*
* Usage example:
* \code
* obj.AddAction("String",
* _("Change the string"),
* _("Change the string of a text"),
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString");
*
* DECLARE_END_OBJECT_ACTION()
* \endcode
*/
ExtraInformation &SetGetter(const gd::String &getter) {
optionalAssociatedInstruction = getter;
accessType = MutatorAndOrAccessor;
return *this;
}
ExtraInformation &SetMutators(
const std::map<gd::String, gd::String> &mutators) {
optionalMutators = mutators;
accessType = Mutators;
return *this;
}
/**
* \brief Erase any existing include file and add the specified include.
*/
ExtraInformation &SetIncludeFile(const gd::String &includeFile) {
includeFiles.clear();
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
ExtraInformation &AddIncludeFile(const gd::String &includeFile) {
if (std::find(includeFiles.begin(), includeFiles.end(), includeFile) ==
includeFiles.end())
includeFiles.push_back(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const {
return includeFiles;
};
ExtraInformation &SetCustomCodeGenerator(
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
codeGenerator) {
hasCustomCodeGenerator = true;
customCodeGenerator = codeGenerator;
return *this;
}
ExtraInformation &RemoveCustomCodeGenerator() {
hasCustomCodeGenerator = false;
std::function<gd::String(Instruction & instruction,
gd::EventsCodeGenerator & codeGenerator,
gd::EventsCodeGenerationContext & context)>
emptyFunction;
customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return hasCustomCodeGenerator; }
gd::String functionCallName;
gd::String asyncFunctionCallName;
gd::String type;
@@ -405,168 +512,76 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
std::map<gd::String, gd::String> optionalMutators;
bool hasCustomCodeGenerator;
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
customCodeGenerator;
private:
std::vector<gd::String> includeFiles;
};
ExtraInformation codeExtraInformation; ///< Information about how generate
///< code for the instruction
/**
* \brief Return the structure containing the information about code
* generation for the instruction.
*/
ExtraInformation &GetCodeExtraInformation() { return codeExtraInformation; }
/**
* \brief Declare if the instruction being declared is somewhat manipulating
* in a standard way. \param type "number" or "string" \note Shortcut for
* `codeExtraInformation.SetManipulatedType(type)`.
*/
ExtraInformation &SetManipulatedType(const gd::String &type_) {
return codeExtraInformation.SetManipulatedType(type_);
}
/**
* Set the name of the function which will be called in the generated code.
* \param functionName the name of the function to call.
* \note Shortcut for `codeExtraInformation.SetFunctionName`.
*/
InstructionMetadata &SetFunctionName(const gd::String &functionName_) override {
codeExtraInformation.functionCallName = functionName_;
return *this;
ExtraInformation &SetFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetFunctionName(functionName);
}
/**
* Set the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
* Set the name of the function, doing asynchronous work, which will be called
* in the generated code. This function should return an asynchronous task
* (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*
* \param functionName the name of the function doing asynchronous work to
* call.
* call. \note Shortcut for `codeExtraInformation.SetAsyncFunctionName`.
*/
InstructionMetadata &SetAsyncFunctionName(const gd::String &functionName_) {
codeExtraInformation.asyncFunctionCallName = functionName_;
return *this;
}
/**
* Return the name of the function which will be called in the generated code.
*/
const gd::String &GetFunctionName() {
return codeExtraInformation.functionCallName;
}
/**
* Return the name of the function, doing asynchronous work, which will be
* called in the generated code. This function should return an asynchronous
* task (i.e: `gdjs.AsyncTask` in the JavaScript runtime).
*/
const gd::String &GetAsyncFunctionName() {
return codeExtraInformation.asyncFunctionCallName;
}
/**
* \brief Declare if the instruction being declared is somewhat manipulating
* in a standard way.
*
* \param type "number" or "string"
*/
InstructionMetadata &SetManipulatedType(const gd::String &type_) {
codeExtraInformation.type = type_;
return *this;
}
/**
* \brief Return the type manipulated in a standard way by the instruction.
*
* \param type "number" or "string"
*/
const gd::String &GetManipulatedType() const {
return codeExtraInformation.type;
}
/**
* If InstructionMetadata::ExtraInformation::SetManipulatedType was called
* with "number" or "string", this function will tell the code generator the
* name of the getter function used to retrieve the data value.
*
* Usage example:
* \code
* obj.AddAction("String",
* _("Change the string"),
* _("Change the string of a text"),
* _("the string"),
* _("Text"),
* "CppPlatform/Extensions/text24.png",
* "CppPlatform/Extensions/text_black.png");
*
* .AddParameter("object", _("Object"), "Text", false)
* .AddParameter("operator", _("Modification operator"), "string")
* .AddParameter("string", _("String"))
* .SetFunctionName("SetString").SetManipulatedType("string").SetGetter("GetString");
*
* DECLARE_END_OBJECT_ACTION()
* \endcode
*/
InstructionMetadata &SetGetter(const gd::String &getter) {
codeExtraInformation.optionalAssociatedInstruction = getter;
codeExtraInformation.accessType = codeExtraInformation.MutatorAndOrAccessor;
return *this;
}
InstructionMetadata &SetMutators(
const std::map<gd::String, gd::String> &mutators) {
codeExtraInformation.optionalMutators = mutators;
codeExtraInformation.accessType = codeExtraInformation.Mutators;
return *this;
ExtraInformation &SetAsyncFunctionName(const gd::String &functionName) {
return codeExtraInformation.SetAsyncFunctionName(functionName);
}
/**
* \brief Erase any existing include file and add the specified include.
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
* error prone.
*/
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) override {
codeExtraInformation.includeFiles.clear();
codeExtraInformation.includeFiles.push_back(includeFile);
InstructionMetadata &SetIncludeFile(const gd::String &includeFile) {
codeExtraInformation.SetIncludeFile(includeFile);
return *this;
}
/**
* \brief Add a file to the already existing include files.
*/
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) override {
if (std::find(codeExtraInformation.includeFiles.begin(), codeExtraInformation.includeFiles.end(), includeFile) ==
codeExtraInformation.includeFiles.end())
codeExtraInformation.includeFiles.push_back(includeFile);
InstructionMetadata &AddIncludeFile(const gd::String &includeFile) {
codeExtraInformation.AddIncludeFile(includeFile);
return *this;
}
/**
* \brief Get the files that must be included to use the instruction.
*/
const std::vector<gd::String> &GetIncludeFiles() const override {
return codeExtraInformation.includeFiles;
const std::vector<gd::String> &GetIncludeFiles() const {
return codeExtraInformation.GetIncludeFiles();
};
InstructionMetadata &SetCustomCodeGenerator(
std::function<gd::String(Instruction &instruction,
gd::EventsCodeGenerator &codeGenerator,
gd::EventsCodeGenerationContext &context)>
codeGenerator) {
codeExtraInformation.hasCustomCodeGenerator = true;
codeExtraInformation.customCodeGenerator = codeGenerator;
return *this;
}
InstructionMetadata &RemoveCustomCodeGenerator() {
codeExtraInformation.hasCustomCodeGenerator = false;
std::function<gd::String(Instruction & instruction,
gd::EventsCodeGenerator & codeGenerator,
gd::EventsCodeGenerationContext & context)>
emptyFunction;
codeExtraInformation.customCodeGenerator = emptyFunction;
return *this;
}
bool HasCustomCodeGenerator() const { return codeExtraInformation.hasCustomCodeGenerator; }
/**
* \brief Return the structure containing the information about code
* generation for the instruction.
*
* \deprecated
*/
InstructionMetadata &GetCodeExtraInformation() { return *this; }
ParameterMetadataContainer parameters;
std::vector<ParameterMetadata> parameters;
private:
gd::String fullname;
@@ -589,3 +604,5 @@ class GD_CORE_API InstructionMetadata : public gd::AbstractFunctionMetadata {
};
} // namespace gd
#endif // INSTRUCTIONMETADATA_H

View File

@@ -1,204 +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 <map>
#include "GDCore/Extensions/Metadata/ExpressionMetadata.h"
#include "GDCore/Extensions/Metadata/InstructionMetadata.h"
#include "GDCore/String.h"
namespace gd {
class Behavior;
class BehaviorsSharedData;
class MultipleInstructionMetadata;
class InstructionMetadata;
class ExpressionMetadata;
} // namespace gd
namespace gd {
/**
* \brief Contains user-friendly information about instructions and expressions
* (usually for a behavior or an object).
*
* \ingroup Events
*/
class GD_CORE_API InstructionOrExpressionContainerMetadata {
public:
InstructionOrExpressionContainerMetadata(){};
virtual ~InstructionOrExpressionContainerMetadata(){};
/**
* Declare a new condition as being part of the behavior or object.
* \deprecated Prefer using `AddScopedCondition`, to properly namespace
* the condition.
*/
virtual gd::InstructionMetadata &
AddCondition(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the behavior or object.
* \deprecated Prefer using `AddScopedAction`, to properly namespace
* the action.
*/
virtual gd::InstructionMetadata &
AddAction(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new condition as being part of the behavior or object.
*/
virtual gd::InstructionMetadata &
AddScopedCondition(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_,
const gd::String &sentence_, const gd::String &group_,
const gd::String &icon_, const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the behavior or object.
*/
virtual gd::InstructionMetadata &
AddScopedAction(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &sentence_,
const gd::String &group_, const gd::String &icon_,
const gd::String &smallicon_) = 0;
/**
* Declare a new action as being part of the extension.
*/
virtual gd::ExpressionMetadata &
AddExpression(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &group_,
const gd::String &smallicon_) = 0;
/**
* Declare a new string expression as being part of the extension.
*/
virtual gd::ExpressionMetadata &
AddStrExpression(const gd::String &name_, const gd::String &fullname_,
const gd::String &description_, const gd::String &group_,
const gd::String &smallicon_) = 0;
/**
* \brief Declare a new expression and condition as being part of the
* behavior.
* \note It's recommended to use this function to avoid declaring twice a
* similar expression/condition.
*/
virtual gd::MultipleInstructionMetadata AddExpressionAndCondition(
const gd::String &type, const gd::String &name,
const gd::String &fullname, const gd::String &description,
const gd::String &sentenceName, const gd::String &group,
const gd::String &icon) = 0;
/**
* \brief Declare a new expression, condition and action as being part of the
* behavior.
* \note The action name is prefixed by "Set" (and the namespace, as the
* condition).
* \note It's recommended to use this function to avoid declaring 3 times a
* similar expression/condition/action.
*/
virtual gd::MultipleInstructionMetadata AddExpressionAndConditionAndAction(
const gd::String &type, const gd::String &name,
const gd::String &fullname, const gd::String &description,
const gd::String &sentenceName, const gd::String &group,
const gd::String &icon) = 0;
/**
* \brief Create a new action which is the duplicate of the specified one.
*
* Useful for handling a deprecated action that is just a "copy" of the new
* one.
*/
virtual gd::InstructionMetadata &
AddDuplicatedAction(const gd::String &newActionName,
const gd::String &copiedActionName) = 0;
/**
* \brief Create a new condition which is the duplicate of the specified one.
*
* Useful for handling a deprecated condition that is just a "copy" of the new
* one.
*/
virtual gd::InstructionMetadata &
AddDuplicatedCondition(const gd::String &newConditionName,
const gd::String &copiedConditionName) = 0;
virtual InstructionOrExpressionContainerMetadata &
SetFullName(const gd::String &fullname_) = 0;
virtual InstructionOrExpressionContainerMetadata &
SetDescription(const gd::String &description_) = 0;
/**
* \brief Erase any existing include file and add the specified include.
* \note The requirement may vary depending on the platform: Most of the time,
* the include file contains the declaration of the behavior.
* \deprecated Use `AddIncludeFile` instead as clearing the list is more
* error prone.
*/
virtual InstructionOrExpressionContainerMetadata &
SetIncludeFile(const gd::String &includeFile) = 0;
/**
* \brief Add a file to the already existing include files.
*/
virtual InstructionOrExpressionContainerMetadata &
AddIncludeFile(const gd::String &includeFile) = 0;
/**
* Get the help path of the behavior, relative to the GDevelop documentation
* root.
*/
virtual const gd::String &GetHelpPath() const = 0;
/**
* Set the help path of the behavior, relative to the GDevelop documentation
* root.
*
* The behavior instructions will have this help path set by
* default, unless you call SetHelpPath on them.
*/
virtual InstructionOrExpressionContainerMetadata &
SetHelpPath(const gd::String &path) = 0;
virtual const gd::String &GetName() const = 0;
virtual const gd::String &GetFullName() const = 0;
virtual const gd::String &GetDescription() const = 0;
virtual const gd::String &GetIconFilename() const = 0;
virtual bool IsPrivate() const = 0;
/**
* \brief Return a reference to a map containing the names of the actions
* (as keys) and the metadata associated with (as values).
*/
virtual std::map<gd::String, gd::InstructionMetadata> &GetAllActions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::InstructionMetadata> &GetAllConditions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::ExpressionMetadata> &GetAllExpressions() = 0;
/**
* \see gd::PlatformExtension::GetAllActions
*/
virtual std::map<gd::String, gd::ExpressionMetadata> &
GetAllStrExpressions() = 0;
private:
};
} // namespace gd

View File

@@ -14,7 +14,6 @@
#include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/Project/Layout.h" // For GetTypeOfObject and GetTypeOfBehavior
#include "GDCore/Project/ObjectsContainersList.h"
#include "GDCore/String.h"
#include "GDCore/Events/Parsers/ExpressionParser2.h"
@@ -136,11 +135,11 @@ MetadataProvider::GetExtensionAndConditionMetadata(const gd::Platform& platform,
const auto& objects = extension->GetExtensionObjectsTypes();
for (const gd::String& extObjectType : objects) {
const auto& allObjectsConditions =
const auto& allObjetsConditions =
extension->GetAllConditionsForObject(extObjectType);
if (allObjectsConditions.find(conditionType) != allObjectsConditions.end())
if (allObjetsConditions.find(conditionType) != allObjetsConditions.end())
return ExtensionAndMetadata<InstructionMetadata>(
*extension, allObjectsConditions.find(conditionType)->second);
*extension, allObjetsConditions.find(conditionType)->second);
}
const auto& autos = extension->GetBehaviorsTypes();
@@ -392,19 +391,20 @@ MetadataProvider::GetBehaviorAnyExpressionMetadata(const gd::Platform& platform,
}
const gd::ExpressionMetadata& MetadataProvider::GetFunctionCallMetadata(
const gd::Platform& platform,
const gd::ObjectsContainersList &objectsContainersList,
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& node) {
if (!node.behaviorName.empty()) {
gd::String behaviorType =
objectsContainersList.GetTypeOfBehavior(node.behaviorName);
gd::String behaviorType =
GetTypeOfBehavior(globalObjectsContainer, objectsContainer, node.behaviorName);
return MetadataProvider::GetBehaviorAnyExpressionMetadata(
platform, behaviorType, node.functionName);
}
else if (!node.objectName.empty()) {
gd::String objectType =
objectsContainersList.GetTypeOfObject(node.objectName);
gd::String objectType =
GetTypeOfObject(globalObjectsContainer, objectsContainer, node.objectName);
return MetadataProvider::GetObjectAnyExpressionMetadata(
platform, objectType, node.functionName);
}
@@ -412,9 +412,10 @@ const gd::ExpressionMetadata& MetadataProvider::GetFunctionCallMetadata(
return MetadataProvider::GetAnyExpressionMetadata(platform, node.functionName);
}
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainersList &objectsContainersList,
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
ExpressionNode& parameter) {
int parameterIndex = -1;
@@ -428,15 +429,17 @@ const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
return nullptr;
}
return MetadataProvider::GetFunctionCallParameterMetadata(
platform,
objectsContainersList,
platform,
globalObjectsContainer,
objectsContainer,
functionCall,
parameterIndex);
}
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainersList &objectsContainersList,
const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
int parameterIndex) {
// Search the parameter metadata index skipping invisible ones.
@@ -445,7 +448,7 @@ const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
ExpressionParser2::WrittenParametersFirstIndex(
functionCall.objectName, functionCall.behaviorName);
const gd::ExpressionMetadata &metadata = MetadataProvider::GetFunctionCallMetadata(
platform, objectsContainersList, functionCall);
platform, globalObjectsContainer, objectsContainer, functionCall);
if (IsBadExpressionMetadata(metadata)) {
return nullptr;
@@ -454,12 +457,11 @@ const gd::ParameterMetadata* MetadataProvider::GetFunctionCallParameterMetadata(
// TODO use a badMetadata instead of a nullptr?
const gd::ParameterMetadata* parameterMetadata = nullptr;
while (metadataParameterIndex <
metadata.GetParameters().GetParametersCount()) {
if (!metadata.GetParameters().GetParameter(metadataParameterIndex)
metadata.parameters.size()) {
if (!metadata.parameters[metadataParameterIndex]
.IsCodeOnly()) {
if (visibleParameterIndex == parameterIndex) {
parameterMetadata =
&metadata.GetParameters().GetParameter(metadataParameterIndex);
parameterMetadata = &metadata.parameters[metadataParameterIndex];
}
visibleParameterIndex++;
}

View File

@@ -15,7 +15,6 @@ class ExpressionMetadata;
class ExpressionMetadata;
class Platform;
class PlatformExtension;
class ObjectsContainersList;
struct FunctionCallNode;
struct ExpressionNode;
} // namespace gd
@@ -238,19 +237,22 @@ class GD_CORE_API MetadataProvider {
const gd::Platform& platform, gd::String objectType, gd::String exprType);
static const gd::ExpressionMetadata& GetFunctionCallMetadata(
const gd::Platform& platform,
const gd::ObjectsContainersList &objectsContainersList,
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& node);
static const gd::ParameterMetadata* GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainersList &objectsContainersList,
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
ExpressionNode& parameter);
static const gd::ParameterMetadata* GetFunctionCallParameterMetadata(
const gd::Platform& platform,
const gd::ObjectsContainersList &objectsContainersList,
const gd::Platform& platform,
const gd::ObjectsContainer &globalObjectsContainer,
const gd::ObjectsContainer &objectsContainer,
FunctionCallNode& functionCall,
int parameterIndex);
@@ -273,10 +275,6 @@ class GD_CORE_API MetadataProvider {
return &metadata == &badBehaviorMetadata;
}
static bool IsBadObjectMetadata(const gd::ObjectMetadata& metadata) {
return &metadata == &badObjectInfo;
}
virtual ~MetadataProvider();
private:
@@ -288,8 +286,8 @@ class GD_CORE_API MetadataProvider {
static EffectMetadata badEffectMetadata;
static gd::InstructionMetadata badInstructionMetadata;
static gd::ExpressionMetadata badExpressionMetadata;
int useless = 0; // Useless member to avoid emscripten "must have a positive
// integer typeid pointer" runtime error.
int useless; // Useless member to avoid emscripten "must have a positive
// integer typeid pointer" runtime error.
};
} // namespace gd

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