Compare commits

..

28 Commits

Author SHA1 Message Date
Davy Hélard
55fc686a5b Fix expression default type. 2022-10-29 22:02:37 +02:00
Davy Hélard
5580189f88 Remove unused imports. 2022-10-29 20:49:29 +02:00
Davy Hélard
9a6d1d6d32 Remove useless lines added by mistake. 2022-10-29 19:42:54 +02:00
Davy Hélard
6c9739c01d Fix object parameter extraInfo declaration. 2022-10-29 19:41:07 +02:00
Davy Hélard
cd3c997b28 Review changes: more renaming 2022-10-29 17:53:15 +02:00
Davy Hélard
8064c4de57 Review changes: renaming 2022-10-29 14:54:09 +02:00
Davy Hélard
8666851f54 Documentation. 2022-10-29 13:40:53 +02:00
Davy Hélard
6d568b2f2c Fix type conversion to expressionType. 2022-10-29 13:40:52 +02:00
Davy Hélard
180d4318aa Add ValueTypeEditor to edit type definitions. 2022-10-29 13:40:52 +02:00
Davy Hélard
65a57f86da Allow to define type extraInfo for operands. 2022-10-29 13:40:52 +02:00
Davy Hélard
6a3e7f9c58 Define expression types with ValueTypeMetadata. 2022-10-29 13:40:52 +02:00
Davy Hélard
74f1d571ba Extract ValueTypeMetadata from ParameterMetadata. 2022-10-29 13:40:51 +02:00
Davy Hélard
a7cb3fc5a2 Add some comment about parameter types. 2022-10-29 13:40:51 +02:00
Davy Hélard
08d3c3323a Move out changes to mapFor. 2022-10-29 13:40:51 +02:00
Davy Hélard
fec603b811 Format 2022-10-29 13:40:51 +02:00
Davy Hélard
d68affc117 Add tests for shiftSentenceParamIndexes 2022-10-29 13:40:50 +02:00
Davy Hélard
77cd6c44d6 Review change: memory leak in test. 2022-10-29 13:40:50 +02:00
Davy Hélard
2b4c8813e4 Review changes 2022-10-29 13:40:50 +02:00
Davy Hélard
2ef9266ec4 Disable the "Add parameter" button for ActionWithOperator. 2022-10-29 13:40:49 +02:00
Davy Hélard
ceba6cf739 Split function types and returned types in 2 drop-down lists. 2022-10-29 13:40:49 +02:00
Davy Hélard
18f2085de7 Better disable parameters in UI. 2022-10-29 13:40:49 +02:00
Davy Hélard
b586fb87ed Show the right parameters in the editor. 2022-10-29 13:40:49 +02:00
Davy Hélard
8aed02ab17 Allow event extensions to define an action with an operator. 2022-10-29 13:40:48 +02:00
Davy Hélard
8c383fc448 Cleanup stories imports. 2022-10-29 13:40:48 +02:00
Davy Hélard
af3a2016f2 Fix flow. 2022-10-29 13:40:48 +02:00
Davy Hélard
7a20161794 Use the icon of expressions. 2022-10-29 13:40:47 +02:00
Davy Hélard
0feb4ef321 Put operator and operand first. 2022-10-29 13:40:47 +02:00
Davy Hélard
5cbcd16523 Allow event extensions to define a condition with an operator from an expression. 2022-10-29 13:40:47 +02:00
4536 changed files with 286244 additions and 520987 deletions

View File

@@ -11,25 +11,13 @@
version: 2.1 version: 2.1
orbs: orbs:
aws-cli: circleci/aws-cli@2.0.6 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)
win: circleci/windows@5.1.0
jobs: jobs:
# Build the **entire** app for macOS (including the GDevelop.js library). # Build the **entire** app for macOS.
build-macos: build-macos:
macos: macos:
xcode: 16.4.0 xcode: 12.5.1
resource_class: m4pro.medium
steps: steps:
- checkout - 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) # System dependencies (for Emscripten and upload)
- run: - run:
@@ -42,14 +30,14 @@ jobs:
- run: - run:
name: Install Emscripten (for GDevelop.js) name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd .. command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# GDevelop.js dependencies # GDevelop.js dependencies
- restore_cache: - restore_cache:
keys: keys:
- gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}-{{ checksum "GDJS/package-lock.json" }} - gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
# fallback to using the latest cache if no exact match is found # fallback to using the latest cache if no exact match is found
- gd-macos-nodejs-dependencies- - gd-macos-nodejs-dependencies---
- run: - run:
name: Install GDevelop.js dependencies name: Install GDevelop.js dependencies
@@ -70,55 +58,31 @@ jobs:
- newIDE/electron-app/node_modules - newIDE/electron-app/node_modules
- newIDE/app/node_modules - newIDE/app/node_modules
- GDevelop.js/node_modules - GDevelop.js/node_modules
- GDJS/node_modules key: gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
key: gd-macos-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}-{{ checksum "GDJS/package-lock.json" }}
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual) # Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
# Note: Code signing is done using CSC_LINK (see https://www.electron.build/code-signing). # 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: - run:
name: Build GDevelop IDE 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: - run:
name: Clean dist folder to keep only installers/binaries. name: Clean dist folder to keep only installers/binaries.
command: rm -rf "newIDE/electron-app/dist/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) # Upload artifacts (CircleCI)
- store_artifacts: - store_artifacts:
path: newIDE/electron-app/dist path: newIDE/electron-app/dist
# Upload artifacts (AWS) # Upload artifacts (AWS)
- run: - run:
name: Deploy to S3 (specific commit) name: Deploy to S3 (specific commit)
command: | command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/
export PATH=~/.local/bin:$PATH
for i in 1 2 3 4 5 6 7; do
aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/ && break
echo "Retry $i failed... retrying in 10 seconds"
sleep 10
done
if [ $i -eq 7 ]; then
echo "All retries for deployment failed!" >&2
exit 1
fi
- run: - run:
name: Deploy to S3 (latest) name: Deploy to S3 (latest)
command: | command: export PATH=~/.local/bin:$PATH && aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/
export PATH=~/.local/bin:$PATH
for i in 1 2 3 4 5 6 7; do
aws s3 sync newIDE/electron-app/dist s3://gdevelop-releases/$(git rev-parse --abbrev-ref HEAD)/latest/ && break
echo "Retry $i failed... retrying in 10 seconds"
sleep 10
done
if [ $i -eq 7 ]; then
echo "All retries for deployment failed!" >&2
exit 1
fi
# Build the app for Linux (using a pre-built GDevelop.js library). # Build the **entire** app for Linux.
build-linux: build-linux:
# CircleCI docker workers are failing if they don't have enough memory (no swap) # CircleCI docker workers are failing if they don't have enough memory (no swap)
resource_class: xlarge resource_class: xlarge
@@ -131,33 +95,50 @@ jobs:
- checkout - checkout
- aws-cli/setup - aws-cli/setup
# System dependencies (for Electron Builder) # System dependencies (for Electron Builder and Emscripten)
- run: - run:
name: Update system dependencies name: Install dependencies for Emscripten
command: sudo apt-get update command: sudo apt-get update && sudo apt install cmake
- run:
name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y
- run:
name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
- run: - run:
name: Install system dependencies for Electron builder name: Install system dependencies for Electron builder
command: sudo apt install icnsutils && sudo apt install graphicsmagick && sudo apt install rsync command: sudo apt install icnsutils && sudo apt install graphicsmagick && sudo apt install rsync
# GDevelop.js dependencies
- restore_cache: - restore_cache:
keys: keys:
- gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}-{{ checksum "GDJS/package-lock.json" }} - gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
# fallback to using the latest cache if no exact match is found # fallback to using the latest cache if no exact match is found
- gd-linux-nodejs-dependencies- - gd-linux-nodejs-dependencies---
# GDevelop IDE dependencies (using an exact version of GDevelop.js, built previously) - run:
name: Install GDevelop.js dependencies and build it
command: cd GDevelop.js && npm install && cd ..
# Build GDevelop.js (and run tests to ensure it works)
- run:
name: Build GDevelop.js
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test && cd ..
# GDevelop IDE dependencies (after building GDevelop.js to avoid downloading a pre-built version)
- run: - run:
name: Install GDevelop IDE dependencies name: Install GDevelop IDE dependencies
command: export REQUIRES_EXACT_LIBGD_JS_VERSION=true && cd newIDE/app && npm install && cd ../electron-app && npm install command: cd newIDE/app && npm install && cd ../electron-app && npm install
- save_cache: - save_cache:
paths: paths:
- newIDE/electron-app/node_modules - newIDE/electron-app/node_modules
- newIDE/app/node_modules - newIDE/app/node_modules
- GDevelop.js/node_modules - GDevelop.js/node_modules
- GDJS/node_modules key: gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}
key: gd-linux-nodejs-dependencies-{{ checksum "newIDE/app/package.json" }}-{{ checksum "newIDE/electron-app/package.json" }}-{{ checksum "GDevelop.js/package.json" }}-{{ checksum "GDJS/package-lock.json" }}
# Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual) # Build GDevelop IDE (seems like we need to allow Node.js to use more space than usual)
- run: - run:
@@ -182,7 +163,6 @@ jobs:
# Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use). # Build the WebAssembly library only (so that it's cached on a S3 and easy to re-use).
build-gdevelop_js-wasm-only: 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: docker:
- image: cimg/node:16.13 - image: cimg/node:16.13
@@ -198,12 +178,12 @@ jobs:
command: sudo apt-get update && sudo apt install cmake command: sudo apt-get update && sudo apt install cmake
- run: - run:
name: Install Python3 dependencies for Emscripten name: Install Python3 dependencies for Emscripten
command: sudo apt install python-is-python3 python3-distutils -y command: sudo apt install python-is-python3 python3-distutils -y
- run: - run:
name: Install Emscripten (for GDevelop.js) name: Install Emscripten (for GDevelop.js)
command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 3.1.21 && ./emsdk activate 3.1.21 && cd .. command: git clone https://github.com/juj/emsdk.git && cd emsdk && ./emsdk install 1.39.6 && ./emsdk activate 1.39.6 && cd ..
# GDevelop.js dependencies # GDevelop.js dependencies
- restore_cache: - restore_cache:
@@ -219,8 +199,7 @@ jobs:
# Build GDevelop.js (and run tests to ensure it works) # Build GDevelop.js (and run tests to ensure it works)
- run: - run:
name: Build GDevelop.js 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 && cd ..
command: cd GDevelop.js && source ../emsdk/emsdk_env.sh && npm run build && npm test -- --runInBand && cd ..
- save_cache: - save_cache:
paths: paths:
@@ -239,302 +218,17 @@ jobs:
name: Deploy to S3 (latest) name: Deploy to S3 (latest)
command: aws s3 sync Binaries/embuild/GDevelop.js s3://gdevelop-gdevelop.js/$(git rev-parse --abbrev-ref HEAD)/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)/
# Trigger AppVeyor build, which also does a Windows build (keep it for redundancy).
trigger-appveyor-windows-build:
docker:
- image: cimg/node:16.13
steps:
- run:
name: Trigger AppVeyor Windows build
command: |
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer ${APPVEYOR_API_KEY}" \
--data "{
\"accountName\": \"4ian\",
\"projectSlug\": \"gdevelop\",
\"branch\": \"${CIRCLE_BRANCH}\"
}" \
-X POST https://ci.appveyor.com/api/builds
build-windows:
executor:
name: win/default
size: medium
working_directory: /home/circleci/project
steps:
- checkout
- run:
# See https://www.ssl.com/how-to/how-to-integrate-esigner-cka-with-ci-cd-tools-for-automated-code-signing/
#
# This is necessary because of "signing to be FIPS-140 compliant". See
# https://github.com/electron-userland/electron-builder/issues/6158
#
# Make sure to DISABLE "malware blocker" in SSL.com to avoid errors like:
# Error information: "Error: SignerSign() failed." (-2146893821/0x80090003)
name: Download and Unzip eSignerCKA Setup
command: |
Invoke-WebRequest -OutFile eSigner_CKA_1.0.3.zip "https://www.ssl.com/download/ssl-com-esigner-cka-1-0-3"
Expand-Archive -Force eSigner_CKA_1.0.3.zip
Remove-Item eSigner_CKA_1.0.3.zip
Move-Item -Destination "eSigner_CKA_1.0.3.exe" -Path "eSigner_CKA_*\*.exe"
- run:
name: Setup eSignerCKA in Silent Mode
command: |
mkdir -p "/home/circleci/project/eSignerCKA"
./eSigner_CKA_1.0.3.exe /CURRENTUSER /VERYSILENT /SUPPRESSMSGBOXES /DIR="/home/circleci/project/eSignerCKA" | Out-Null
- run:
name: Config Account Information on eSignerCKA
command: |
/home/circleci/project/eSignerCKA/eSignerCKATool.exe config -mode product -user "$env:ESIGNER_USER_NAME" -pass "$env:ESIGNER_USER_PASSWORD" -totp "$env:ESIGNER_USER_TOTP" -key "/home/circleci/project/eSignerCKA/master.key" -r
- run:
name: Load Certificate into Windows Store
command: |
/home/circleci/project/eSignerCKA/eSignerCKATool.exe unload
/home/circleci/project/eSignerCKA/eSignerCKATool.exe load
- run:
name: Select Certificate From Windows Store and Sign Sample File with SignTool
command: |
$CodeSigningCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
echo Certificate: $CodeSigningCert
- restore_cache:
name: Restore node_modules cache
keys:
- v1-win-node-{{ checksum "newIDE/app/package-lock.json" }}-{{ checksum "newIDE/electron-app/package-lock.json" }}-{{ checksum "GDJS/package-lock.json" }}
- v1-win-node-
- run:
name: Install dependencies
no_output_timeout: 25m
# Remove package-lock.json because they seems to cause the npm install to be stuck. We should try again after re-generating them.
# Also install setuptools as something requires distutils in electron-app, and it was removed in Python 3.12.
# setuptools will make distutils available again (but we should migrate our packages probably).
command: |
pip install setuptools
cd newIDE\app
npm -v
Remove-Item package-lock.json
$Env:REQUIRES_EXACT_LIBGD_JS_VERSION = "true"
npm install
cd ..\electron-app
Remove-Item package-lock.json
npm install
cd ..\..
- save_cache:
name: Save node_modules cache
key: v1-win-node-{{ checksum "newIDE/app/package-lock.json" }}-{{ checksum "newIDE/electron-app/package-lock.json" }}-{{ checksum "GDJS/package-lock.json" }}
paths:
- newIDE/app/node_modules
- newIDE/electron-app/node_modules
- GDJS/node_modules
- run:
name: Build NSIS executable (with code signing)
command: |
cd newIDE\electron-app
$CodeSigningCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
echo Certificate: $CodeSigningCert
# Use a custom signtool path because of the signtool.exe bundled withy electron-builder not working for some reason.
# Can also be found in versioned folders like "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22000.0/x86/signtool.exe".
# or "C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\signtool.exe".
$Env:SIGNTOOL_PATH = "C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe"
# Extract thumbprint and subject name of the certificate (will be passed to electron-builder).
$Env:GD_SIGNTOOL_THUMBPRINT = $CodeSigningCert.Thumbprint
$Env:GD_SIGNTOOL_SUBJECT_NAME = ($CodeSigningCert.Subject -replace ", ?", "`n" | ConvertFrom-StringData).CN
# Build the nsis installer (signed: electron-builder will use SignTool.exe with the certificate)
node scripts/build.js --win nsis --publish=never
cd ..\..
- run:
name: Build AppX (without code signing)
# Don't sign the appx (it will be signed by the Microsoft Store).
command: |
cd newIDE\electron-app
# Build the appx (not signed). Ensure all variables used for code signing are empty.
$Env:GD_SIGNTOOL_THUMBPRINT = ''
$Env:GD_SIGNTOOL_SUBJECT_NAME = ''
$Env:CSC_LINK = ''
$Env:CSC_KEY_PASSWORD = ''
node scripts/build.js --skip-app-build --win appx --publish=never
cd ..\..
- run:
name: Clean binaries
shell: cmd.exe
command: |
rmdir /s /q newIDE\electron-app\dist\win-unpacked
- run:
name: Install AWS CLI
command: |
# Install the CLI for the current user
pip install --quiet --upgrade --user awscli
# Add the user-Scripts dir to PATH for this step and the next.
$binDir = (python -m site --user-base) + "\Scripts"
$Env:Path += ";$binDir"
# Sanity check:
aws --version
# Upload artifacts (S3)
- run:
name: Deploy to S3 (specific commit)
command: |
aws s3 sync newIDE\electron-app\dist "s3://gdevelop-releases/$Env:CIRCLE_BRANCH/commit/$Env:CIRCLE_SHA1/"
- run:
name: Deploy to S3 (latest)
command: |
aws s3 sync newIDE\electron-app\dist "s3://gdevelop-releases/$Env:CIRCLE_BRANCH/latest/"
# Upload artifacts (CircleCI)
- store_artifacts:
path: newIDE/electron-app/dist
workflows: workflows:
gdevelop_js-wasm-extra-checks:
jobs:
- build-gdevelop_js-debug-sanitizers-and-extra-checks:
# Extra checks are resource intensive so don't always run them.
filters:
branches:
only:
- master
- /experimental-build.*/
builds: builds:
jobs: jobs:
- build-gdevelop_js-wasm-only - build-gdevelop_js-wasm-only
- build-macos: - build-macos:
# The macOS version builds by itself GDevelop.js
# (so we verify we can build it on macOS).
# requires:
# - build-gdevelop_js-wasm-only
filters: filters:
branches: branches:
only: only:
- master - master
- /experimental-build.*/ - /experimental-build.*/
- build-linux: - build-linux:
requires:
- build-gdevelop_js-wasm-only
filters:
branches:
only:
- master
- /experimental-build.*/
- build-windows:
requires:
- build-gdevelop_js-wasm-only
filters:
branches:
only:
- master
- /experimental-build.*/
- trigger-appveyor-windows-build:
requires:
- build-gdevelop_js-wasm-only
filters: filters:
branches: branches:
only: only:

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

6
.devcontainer/Dockerfile Normal file
View File

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

16
.devcontainer/README.md Normal file
View File

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

View File

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

4
.gitattributes vendored
View File

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

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

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

View File

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

View File

@@ -9,10 +9,6 @@ name: Build Storybook
on: on:
# Launch on all commits. # Launch on all commits.
push: push:
branches:
- "**"
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab, # Allows to run this workflow manually from the Actions tab,
# to publish on Chromatic (not done by default). # to publish on Chromatic (not done by default).
workflow_dispatch: workflow_dispatch:
@@ -21,23 +17,27 @@ jobs:
build-storybook: build-storybook:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: 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 - name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2 uses: aws-actions/configure-aws-credentials@v1
with: with:
aws-access-key-id: ${{ secrets.BUILD_STORYBOOK_AWS_ACCESS_KEY_ID }} aws-access-key-id: ${{ secrets.BUILD_STORYBOOK_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.BUILD_STORYBOOK_AWS_SECRET_ACCESS_KEY }} aws-secret-access-key: ${{ secrets.BUILD_STORYBOOK_AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1 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 - name: Install newIDE dependencies
run: npm install run: npm install
working-directory: newIDE/app working-directory: newIDE/app
@@ -57,8 +57,8 @@ jobs:
- name: Log urls to the Storybook - name: Log urls to the Storybook
run: | run: |
echo "Find the latest Storybook for this branch on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html" echo "Find the latest Storybook for this branch on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/latest/index.html"
echo "Find the Storybook for this commit on https://gdevelop-storybook.s3.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html" echo "Find the Storybook for this commit on http://gdevelop-storybook.s3-website-us-east-1.amazonaws.com/$(git rev-parse --abbrev-ref HEAD)/commit/$(git rev-parse HEAD)/index.html"
# Publish on Chromatic, only when manually launched (too costly to run on every commit). # Publish on Chromatic, only when manually launched (too costly to run on every commit).
- name: Publish Storybook to Chromatic - name: Publish Storybook to Chromatic

View File

@@ -4,10 +4,6 @@ name: Extract translations
on: on:
# Execute for all commits (to ensure translations extraction works) # Execute for all commits (to ensure translations extraction works)
push: push:
branches:
- "**"
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab. # Allows to run this workflow manually from the Actions tab.
workflow_dispatch: workflow_dispatch:
@@ -15,18 +11,23 @@ jobs:
extract-translations: extract-translations:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: actions/setup-node@v3
# 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: with:
node-version: 16 # npm cache files are stored in `~/.npm` on Linux/macOS
cache: "npm" path: ~/.npm
cache-dependency-path: "newIDE/app/package-lock.json" key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
- name: Install gettext - name: Install gettext
run: sudo apt update && sudo apt install gettext -y run: sudo apt update && sudo apt install gettext -y
- name: Install newIDE dependencies - name: Install newIDE dependencies
run: npm ci run: npm install
working-directory: newIDE/app working-directory: newIDE/app
- name: Extract translations - name: Extract translations
@@ -37,7 +38,7 @@ jobs:
- name: Install Crowdin CLI - name: Install Crowdin CLI
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
run: npm i -g @crowdin/cli run: npm i -g @crowdin/cli
- name: Upload translations to Crowdin - name: Upload translations to Crowdin
run: crowdin upload sources run: crowdin upload sources
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'

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: issues:
types: [opened] types: [opened]
jobs: 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: autocomment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: contains(github.event.issue.body, 'The node to be removed is not a child of this node') if: contains(github.event.issue.body, 'The node to be removed is not a child of this node')
steps: steps:
- name: Autocomment indications on bug if it looks like #3453 - name: Autocomment indications on bug if it looks like #3453
uses: peter-evans/create-or-update-comment@v3 uses: peter-evans/create-or-update-comment@v1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} issue-number: ${{ github.event.issue.number }}
issue-number: ${{ github.event.issue.number }} body: |
body: | Hi @${{ github.actor }}!
Hi @${{ github.actor }}! Thank you for taking the time to open an issue.
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 name: GDevelop Issues automatic workflow
on: on:
pull_request: pull_request:
types: types: [opened]
- opened
- reopened
- synchronize
jobs: jobs:
read-locales-metadata: 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 runs-on: ubuntu-latest
env:
COMMENT_TITLE: "Translation ratio changes"
steps: steps:
- uses: actions/checkout@v3 - name: Read and format locales metadata
with: run: |
fetch-depth: 0 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"))
- name: Read and format locales metadata ADDS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\+\s*\"translationRatio\"" | sed -E "s/^\+ *\"translationRatio\": //g"))
env: SUBS=($(git diff HEAD^ HEAD --unified=0 newIDE/app/src/locales/LocalesMetadata.js | tail +6 | grep -E "^\-\s*\"translationRatio\"" | sed -E "s/^\- *\"translationRatio\": //g"))
BASE: ${{ github.event.pull_request.base.sha }} touch sumup.txt
HEAD: ${{ github.event.pull_request.head.sha }} for index in ${!ADDS[@]}; do
run: | echo ${LANS[index]} | sed -E "s/_/ /g" >> sumup.txt
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")) DELTA=$(bc <<< "scale=2;(${ADDS[index]}-${SUBS[index]})*100/1")
ADDS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\+\s*\"translationRatio\"" | sed -E "s/^\+ *\"translationRatio\": //g")) echo $DELTA % >> sumup.txt
SUBS=($(git diff $BASE...$HEAD -- newIDE/app/src/locales/LocalesMetadata.js | grep -E "^\-\s*\"translationRatio\"" | sed -E "s/^\- *\"translationRatio\": //g")) done
touch sumup.md - name: Store sumup in outputs
echo "## $COMMENT_TITLE" >> sumup.md id: sumup
echo "" >> sumup.md run: echo "::set-output name=sumupFileContent::$(cat sumup.txt)"
echo "| Language | Change |" >> sumup.md - name: Autocomment pull request with sumup
echo "| --- | --- |" >> sumup.md uses: peter-evans/create-or-update-comment@v1
for index in ${!ADDS[@]}; do with:
DELTA=$(echo "scale=3; (${ADDS[index]} - ${SUBS[index]})*100/1" | bc) issue-number: ${{ github.event.number }}
if (( $(echo "$DELTA == 0" | bc -l) )); then body: ${{ steps.sumup.outputs.sumupFileContent}}
continue token: ${{ secrets.GITHUB_TOKEN }}
fi
LANGUAGE=${LANS[index]//_/ }
echo "| $LANGUAGE | $(printf "%1.3f" $DELTA) % |" >> sumup.md
done
- name: Find Comment
uses: peter-evans/find-comment@v2
id: fc
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.number }}
body-includes: ${{ env.COMMENT_TITLE }}
- name: Autocomment pull request with sumup
uses: peter-evans/create-or-update-comment@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.number }}
comment-id: ${{ steps.fc.outputs.comment-id }}
edit-mode: replace
body-path: "sumup.md"

View File

@@ -1,47 +0,0 @@
# GitHub Action to update extension translations.
# It copies the latest messages.js files from the GDevelop-extensions repository
# and opens a Pull Request with the changes on GDevelop's repository.
name: Update extension translations
on:
push:
branches:
- master
tags-ignore:
- "**" # Don't run on new tags
workflow_dispatch: # Allows manual triggering from the Actions tab
jobs:
update-extension-translations:
runs-on: ubuntu-latest
steps:
- name: Checkout current repository
uses: actions/checkout@v3
- name: Clone GDevelop-extensions repository
run: git clone https://github.com/GDevelopApp/GDevelop-extensions.git /tmp/GDevelop-extensions
- name: Copy and rename translation files
run: |
mkdir -p newIDE/app/src/locales
for folder in /tmp/GDevelop-extensions/.translations/*; do
if [ -d "$folder" ]; then
lang=$(basename "$folder")
mkdir -p "newIDE/app/src/locales/$lang"
cp "$folder/messages.js" "newIDE/app/src/locales/$lang/extension-messages.js"
fi
done
cp /tmp/GDevelop-extensions/.translations/LocalesMetadata.js newIDE/app/src/locales/ExtensionLocalesMetadata.js
- name: Create Pull Request with updated translations
uses: peter-evans/create-pull-request@v6
with:
commit-message: Update extension translations [skip ci]
branch: chore/update-extension-translations
delete-branch: true
title: "[Auto PR] Update extension translations"
body: |
This updates the extension translations by copying the latest messages.js files from the GDevelop-extensions repository.
Each messages.js file is renamed to extension-messages.js and placed in the corresponding language folder under `newIDE/app/src/locales`.
Please review the changes carefully before merging.

View File

@@ -7,8 +7,6 @@ on:
push: push:
branches: branches:
- master - master
tags-ignore:
- "**" # Don't run on new tags
# Allows to run this workflow manually from the Actions tab. # Allows to run this workflow manually from the Actions tab.
workflow_dispatch: workflow_dispatch:
@@ -16,12 +14,17 @@ jobs:
update-translations: update-translations:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- uses: actions/setup-node@v3
# 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: with:
node-version: 20 # npm cache files are stored in `~/.npm` on Linux/macOS
cache: "npm" path: ~/.npm
cache-dependency-path: "newIDE/app/package-lock.json" key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('newIDE/app/package-lock.json') }}
- name: Install gettext - name: Install gettext
run: sudo apt update && sudo apt install gettext -y run: sudo apt update && sudo apt install gettext -y
@@ -41,7 +44,7 @@ jobs:
# (Build and) download the most recent translations (PO files) from Crowdin. # (Build and) download the most recent translations (PO files) from Crowdin.
- name: Install Crowdin CLI - name: Install Crowdin CLI
run: npm i -g @crowdin/cli run: npm i -g @crowdin/cli
- name: Download new translations from Crowdin - name: Download new translations from Crowdin
run: crowdin download run: crowdin download
env: env:
@@ -58,13 +61,13 @@ jobs:
working-directory: newIDE/app working-directory: newIDE/app
- name: Create a Pull Request with the changes - 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: with:
commit-message: Update translations [skip ci] commit-message: Update translations [skip ci]
branch: chore/update-translations branch: chore/update-translations
delete-branch: true delete-branch: true
title: "[Auto PR] Update translations" title: '[Auto PR] Update translations'
body: | body: |
This updates the translations by downloading them from Crowdin and compiling them for usage by the app. This updates the translations by downloading them from Crowdin and compiling them for usage by the app.
Please double check the values in `newIDE/app/src/locales/LocalesMetadata.js` to ensure the changes are sensible. Please double check the values in `newIDE/app/src/locales/LocalesMetadata.js` to ensure the changes are sensible.

1
.gitignore vendored
View File

@@ -33,4 +33,3 @@
.Spotlight-V100 .Spotlight-V100
.Trashes .Trashes
Thumbs.db Thumbs.db
.claude

View File

@@ -14,7 +14,7 @@ tasks:
init: | init: |
sudo apt-get update sudo apt-get update
sudo apt install cmake python-is-python3 python3-distutils -y 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 cd GDevelop.js
npm install npm install
source ../emsdk/emsdk_env.sh && npm run build -- --dev source ../emsdk/emsdk_env.sh && npm run build -- --dev

View File

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

View File

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

View File

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

4
.vscode/tasks.json vendored
View File

@@ -8,7 +8,6 @@
"group": "build", "group": "build",
"label": "Start development server", "label": "Start development server",
"detail": "Starts the GDevelop development server.", "detail": "Starts the GDevelop development server.",
"options": { "env": { "NODE_OPTIONS": "--max-old-space-size=8192" } },
"problemMatcher": [ "problemMatcher": [
{ {
"owner": "cra", "owner": "cra",
@@ -38,7 +37,8 @@
"presentation": { "presentation": {
"reveal": "silent" "reveal": "silent"
}, },
"isBackground": true "isBackground": true,
"runOptions": { "instanceLimit": 1, "runOn": "folderOpen" }
}, },
{ {
"type": "npm", "type": "npm",

View File

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

View File

@@ -1,106 +1,100 @@
# This is the CMake file used to build GDevelop. #This is the CMake file used to build GDevelop.
# For more information, see the README.md file. #For more information, see the Readme.md file.
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 2.6)
cmake_policy(SET CMP0011 NEW)
# Add utility functions # Add utility functions
include(scripts/CMakeClangUtils.txt) # To add clang-format and clang-tidy support to a target include(scripts/CMakeClangUtils.txt) # To add clang-format and clang-tidy support to a target
# Macro for defining an option # Macro for defining an option
macro(gd_set_option var default type docstring) macro(gd_set_option var default type docstring)
if(NOT DEFINED ${var}) if(NOT DEFINED ${var})
set(${var} ${default}) set(${var} ${default})
endif() endif()
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE) set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
endmacro() endmacro()
# Set options
gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library") gd_set_option(BUILD_CORE TRUE BOOL "TRUE to build GDevelop Core library")
gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform") gd_set_option(BUILD_GDJS TRUE BOOL "TRUE to build GDevelop JS Platform")
gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions") gd_set_option(BUILD_EXTENSIONS TRUE BOOL "TRUE to build the extensions")
gd_set_option(BUILD_TESTS TRUE BOOL "TRUE to build the tests") gd_set_option(BUILD_TESTS TRUE BOOL "TRUE to build the tests")
# Disable deprecated code # Disable deprecated code
set(NO_GUI TRUE CACHE BOOL "" FORCE) # Force disable old GUI related code. set(NO_GUI TRUE CACHE BOOL "" FORCE) #Force disable old GUI related code.
# Setting up installation directory, for Linux (has to be done before "project" command). #Setting up installation directory, for Linux (has to be done before "project" command).
if(NOT WIN32) IF(NOT WIN32)
if(NOT APPLE) if (NOT APPLE)
gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed") gd_set_option(GD_INSTALL_PREFIX "/opt/gdevelop/" STRING "The directory where GDevelop should be installed")
else() ELSE()
gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed") gd_set_option(GD_INSTALL_PREFIX "." STRING "The directory where GDevelop should be installed")
endif() ENDIF()
# As we embed SFML, prevent it to be installed system-wide #As we embed SFML, prevent it to be installed system-wide
set(CMAKE_INSTALL_PREFIX "${GD_INSTALL_PREFIX}/useless") set(CMAKE_INSTALL_PREFIX "${GD_INSTALL_PREFIX}/useless")
endif() ENDIF()
project(GDevelop) project(GDevelop)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS) IF(NOT WIN32 AND NOT APPLE AND NOT BUILD_TESTS)
set(CMAKE_SKIP_BUILD_RPATH TRUE) # Avoid errors when packaging for linux. SET(CMAKE_SKIP_BUILD_RPATH TRUE) #Avoid errors when packaging for linux.
endif() ENDIF()
if(APPLE) IF(APPLE)
set(CMAKE_MACOSX_RPATH 1) set(CMAKE_MACOSX_RPATH 1)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
set(CMAKE_INSTALL_RPATH ".") set(CMAKE_INSTALL_RPATH ".")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
add_compile_options( set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_")
-D_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
-Wno-potentially-evaluated-expression) ENDIF()
endif() #Sanity checks
# Sanity checks IF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
if("${CMAKE_BUILD_TYPE}" STREQUAL "") message( "CMAKE_BUILD_TYPE is empty, assuming build type is Release" )
message(STATUS "CMAKE_BUILD_TYPE is empty, assuming build type is Release")
set(CMAKE_BUILD_TYPE Release) set(CMAKE_BUILD_TYPE Release)
endif() ENDIF()
if("${CMAKE_BUILD_TYPE}" STREQUAL "Release" AND NOT WIN32 AND CMAKE_COMPILER_IS_GNUCXX) 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. SET(CMAKE_SHARED_LINKER_FLAGS "-s") #Force stripping to avoid errors when packaging for linux.
endif() ENDIF()
#Activate C++11 #Activate C++11
set(CMAKE_CXX_STANDARD 11) # Upgrading to C++17 should be tried. include(CheckCXXCompilerFlag)
set(CMAKE_CXX_STANDARD_REQUIRED ON) CHECK_CXX_COMPILER_FLAG("-std=gnu++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=gnu++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support (with GNU extensions). Please use a different C++ compiler.")
endif()
# Mark some warnings as errors # Mark some warnings as errors
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Activate as much warnings as possible to avoid errors like # Activate as much warnings as possible to avoid errors like
# uninitialized variables or other hard to debug bugs. # uninitialized variables or other hard to debug bugs.
add_compile_options( set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
-Wall set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-warning-option")
-Wextra set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-reorder-ctor -Wno-reorder -Wno-pessimizing-move -Wno-unused-variable -Wno-unused-private-field")
-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
# Make as much warnings considered as errors as possible (only one for now). # Make as much warnings considered as errors as possible (only one for now).
-Werror=return-stack-address set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-stack-address")
-Werror=return-type)
endif() endif()
# Define common directories: #Define common directories:
set(GD_base_dir ${CMAKE_CURRENT_SOURCE_DIR}) set(GD_base_dir ${CMAKE_CURRENT_SOURCE_DIR})
# Add all the CMakeLists: #Add all the CMakeLists:
add_subdirectory(ExtLibs) ADD_SUBDIRECTORY(ExtLibs)
if(BUILD_CORE) IF(BUILD_CORE)
add_subdirectory(Core) ADD_SUBDIRECTORY(Core)
endif() ENDIF()
if(BUILD_GDJS) IF(BUILD_GDJS)
add_subdirectory(GDJS) ADD_SUBDIRECTORY(GDJS)
endif() ENDIF()
if(EMSCRIPTEN) IF(EMSCRIPTEN)
add_subdirectory(GDevelop.js) ADD_SUBDIRECTORY(GDevelop.js)
endif() ENDIF()
if(BUILD_EXTENSIONS) IF(BUILD_EXTENSIONS)
add_subdirectory(Extensions) ADD_SUBDIRECTORY(Extensions)
endif() 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) project(GDCore)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) # Force use response file: useful for Ninja build system on Windows. SET(CMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS 1) #Force use response file: useful for Ninja build system on Windows.
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1) SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1) SET(CMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES 1)
set(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1) SET(CMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES 1)
# Define common directories: #Define common directories:
set(GDCORE_include_dir ${GD_base_dir}/Core PARENT_SCOPE) set(GDCORE_include_dir ${GD_base_dir}/Core PARENT_SCOPE)
set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME} PARENT_SCOPE) set(GDCORE_lib_dir ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME} PARENT_SCOPE)
# Create VersionPriv.h - only useful for testing. #Dependencies on external libraries:
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: #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 IF(WIN32)
# add_definitions( -DWINDOWS )
add_definitions(-DGD_IDE_ONLY) add_definitions( "-DGD_CORE_API=__declspec(dllexport)" )
if(EMSCRIPTEN) add_definitions( -D__GNUWIN32__ )
add_definitions(-DEMSCRIPTEN) ELSE()
endif() IF(APPLE)
if("${CMAKE_BUILD_TYPE}" MATCHES "Debug") add_definitions( -DMACOS )
add_definitions(-DDEBUG) ELSE()
else() add_definitions( -DLINUX )
add_definitions(-DRELEASE) ENDIF()
endif() add_definitions( -DGD_API= )
add_definitions( -DGD_CORE_API= )
ENDIF(WIN32)
if(WIN32) #The target
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
#
include_directories(.) include_directories(.)
file( file(GLOB_RECURSE source_files GDCore/*)
GLOB_RECURSE
source_files
GDCore/*)
file( file(GLOB_RECURSE formatted_source_files tests/* GDCore/Events/* GDCore/Extensions/* GDCore/IDE/* GDCore/Project/* GDCore/Serialization/* GDCore/Tools/*)
GLOB_RECURSE list(REMOVE_ITEM formatted_source_files "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.h" "${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs_dialogs_bitmaps.cpp")
formatted_source_files
tests/*
GDCore/Events/*
GDCore/Extensions/*
GDCore/IDE/*
GDCore/Project/*
GDCore/Serialization/*
GDCore/Tools/*)
list(
REMOVE_ITEM
formatted_source_files
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs.h"
"${CMAKE_CURRENT_SOURCE_DIR}/GDCore/IDE/Dialogs/GDCoreDialogs_dialogs_bitmaps.cpp")
gd_add_clang_utils(GDCore "${formatted_source_files}") gd_add_clang_utils(GDCore "${formatted_source_files}")
if(EMSCRIPTEN) IF(EMSCRIPTEN)
# Emscripten treats all libraries as static libraries # Emscripten treats all libraries as static libraries
add_library(GDCore STATIC ${source_files}) add_library(GDCore STATIC ${source_files})
else() ELSE()
add_library(GDCore SHARED ${source_files}) add_library(GDCore SHARED ${source_files})
endif() ENDIF()
if(EMSCRIPTEN) IF(EMSCRIPTEN)
set_target_properties(GDCore PROPERTIES SUFFIX ".bc") set_target_properties(GDCore PROPERTIES SUFFIX ".bc")
elseif(WIN32) ELSEIF(WIN32)
set_target_properties(GDCore PROPERTIES PREFIX "") set_target_properties(GDCore PROPERTIES PREFIX "")
else() ELSE()
set_target_properties(GDCore PROPERTIES PREFIX "lib") set_target_properties(GDCore PROPERTIES PREFIX "lib")
endif() ENDIF()
set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}) set(LIBRARY_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
set(ARCHIVE_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}) set(ARCHIVE_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
set(RUNTIME_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME}) set(RUNTIME_OUTPUT_PATH ${GD_base_dir}/Binaries/Output/${CMAKE_BUILD_TYPE}_${CMAKE_SYSTEM_NAME})
# Tests #Tests
# ###
if(BUILD_TESTS) if(BUILD_TESTS)
file( file(
GLOB_RECURSE GLOB_RECURSE
test_source_files test_source_files
tests/*) tests/*
)
add_executable(GDCore_tests ${test_source_files}) add_executable(GDCore_tests ${test_source_files})
set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) # Allow finding dependencies directly from build path on Mac OS X. set_target_properties(GDCore_tests PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE) #Allow finding dependencies directly from build path on Mac OS X.
target_link_libraries(GDCore_tests GDCore) target_link_libraries(GDCore_tests GDCore)
target_link_libraries(GDCore_tests ${CMAKE_DL_LIBS}) target_link_libraries(GDCore_tests ${CMAKE_DL_LIBS})
endif() endif()

View File

@@ -58,7 +58,99 @@
* Common functions and tools for programming. * 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 * \defgroup SpriteObjectExtension Standard Sprite Object extension
* \ingroup BuiltinExtensions * \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

@@ -38,7 +38,7 @@ void CommentEvent::SerializeTo(SerializerElement &element) const {
.SetAttribute("textB", textB); .SetAttribute("textB", textB);
element.AddChild("comment").SetValue(com1); element.AddChild("comment").SetValue(com1);
if (!com2.empty()) element.AddChild("comment2").SetValue(com2); element.AddChild("comment2").SetValue(com2);
} }
void CommentEvent::UnserializeFrom(gd::Project &project, void CommentEvent::UnserializeFrom(gd::Project &project,
@@ -53,9 +53,7 @@ void CommentEvent::UnserializeFrom(gd::Project &project,
textB = colorElement.GetIntAttribute("textB"); textB = colorElement.GetIntAttribute("textB");
com1 = element.GetChild("comment", 0, "Com1").GetValue().GetString(); com1 = element.GetChild("comment", 0, "Com1").GetValue().GetString();
if (element.HasChild("comment2")) { com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
com2 = element.GetChild("comment2", 0, "Com2").GetValue().GetString();
}
} }
} // namespace gd } // namespace gd

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,6 +10,7 @@
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/Serialization.h" #include "GDCore/Events/Serialization.h"
#include "GDCore/Serialization/SerializerElement.h" #include "GDCore/Serialization/SerializerElement.h"
#include "GDCore/TinyXml/tinyxml.h"
using namespace std; using namespace std;
@@ -61,12 +62,10 @@ void GroupEvent::UnserializeFrom(gd::Project& project,
project, events, element.GetChild("events")); project, events, element.GetChild("events"));
parameters.clear(); parameters.clear();
if (element.HasChild("parameters")) { gd::SerializerElement& parametersElement = element.GetChild("parameters");
gd::SerializerElement& parametersElement = element.GetChild("parameters"); parametersElement.ConsiderAsArrayOf("parameters");
parametersElement.ConsiderAsArrayOf("parameters"); for (std::size_t i = 0; i < parametersElement.GetChildrenCount(); ++i)
for (std::size_t i = 0; i < parametersElement.GetChildrenCount(); ++i) parameters.push_back(parametersElement.GetChild(i).GetValue().GetString());
parameters.push_back(parametersElement.GetChild(i).GetValue().GetString());
}
} }
void GroupEvent::SetBackgroundColor(unsigned int colorR_, void GroupEvent::SetBackgroundColor(unsigned int colorR_,

View File

@@ -13,7 +13,6 @@
namespace gd { namespace gd {
class Instruction; class Instruction;
class Project; class Project;
class EventVisitor;
} }
class EventsCodeGenerationContext; class EventsCodeGenerationContext;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -4,13 +4,13 @@
* reserved. This project is released under the MIT License. * 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/Event.h"
#include "GDCore/Events/EventsList.h" #include "GDCore/Events/EventsList.h"
#include "GDCore/Events/Instruction.h" #include "GDCore/Events/Instruction.h"
#include "GDCore/Events/InstructionsList.h" #include "GDCore/Events/InstructionsList.h"
#include "GDCore/Project/VariablesContainer.h"
namespace gd { namespace gd {
class Instruction; class Instruction;
class Project; class Project;
@@ -33,10 +33,6 @@ class GD_CORE_API StandardEvent : public gd::BaseEvent {
virtual const gd::EventsList& GetSubEvents() const { return events; }; virtual const gd::EventsList& GetSubEvents() const { return events; };
virtual gd::EventsList& GetSubEvents() { 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; }; const gd::InstructionsList& GetConditions() const { return conditions; };
gd::InstructionsList& GetConditions() { return conditions; }; gd::InstructionsList& GetConditions() { return conditions; };
@@ -57,7 +53,9 @@ class GD_CORE_API StandardEvent : public gd::BaseEvent {
gd::InstructionsList conditions; gd::InstructionsList conditions;
gd::InstructionsList actions; gd::InstructionsList actions;
EventsList events; EventsList events;
VariablesContainer variables;
}; };
} // namespace gd } // 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 ///< de/activate infinite loop warning when the
///< user create the event ///< user create the event
mutable unsigned int whileConditionsHeight;
int GetConditionsHeight() const; int GetConditionsHeight() const;
int GetActionsHeight() const; int GetActionsHeight() const;
int GetWhileConditionsHeight() 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/Layout.h"
#include "GDCore/Project/Object.h" #include "GDCore/Project/Object.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
#include "GDCore/Project/EventsFunctionsExtension.h"
#include "GDCore/IDE/ProjectBrowserHelper.h"
namespace gd { namespace gd {
void EffectsCodeGenerator::DoVisitObject(gd::Object &object) { void ExposeProjectEffects(
auto &effects = object.GetEffects(); const gd::Project& project,
for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) { const std::function<void(const gd::Effect& effect)>& worker) {
auto &effect = effects.GetEffect(e);
AddEffectIncludeFiles(effect);
}
};
void EffectsCodeGenerator::AddEffectIncludeFiles(const gd::Effect &effect) {
// TODO: this browse all the extensions every time we're trying to find
// a new effect. Might be a good idea to rework MetadataProvider to be
// faster (not sure if it is a bottleneck at all though - but could be
// for events code generation).
const gd::EffectMetadata &effectMetadata =
MetadataProvider::GetEffectMetadata(platform, effect.GetEffectType());
for (auto &includeFile : effectMetadata.GetIncludeFiles())
includeFiles.insert(includeFile);
};
void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
const gd::Platform &platform,
gd::Project &project,
std::set<gd::String> &includeFiles) {
// TODO Add unit tests on this function.
// TODO Merge with UsedExtensionsFinder.
// TODO Factorize with the iteration on all effects for resource exposure.
// TODO Implement an ArbitraryEffectWorker and add a method in ProjectBrowserHelper
// See also gd::Project::ExposeResources for a method that traverse the whole // See also gd::Project::ExposeResources for a method that traverse the whole
// project (this time for resources) and // project (this time for resources) and
// WholeProjectRefactorer::ExposeProjectEvents. // WholeProjectRefactorer::ExposeProjectEvents.
EffectsCodeGenerator effectsCodeGenerator(platform, includeFiles);
// Add layouts effects // Add layouts effects
for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) { for (std::size_t s = 0; s < project.GetLayoutsCount(); s++) {
auto& layout = project.GetLayout(s); auto& layout = project.GetLayout(s);
@@ -65,34 +33,47 @@ void EffectsCodeGenerator::GenerateEffectsIncludeFiles(
auto& effects = layout.GetLayer(l).GetEffects(); auto& effects = layout.GetLayer(l).GetEffects();
for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) { for (std::size_t e = 0; e < effects.GetEffectsCount(); ++e) {
auto& effect = effects.GetEffect(e); auto& effect = effects.GetEffect(e);
effectsCodeGenerator.AddEffectIncludeFiles(effect); worker(effect);
}
}
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 // Add global object effects
gd::ProjectBrowserHelper::ExposeProjectObjects(project, effectsCodeGenerator); for (std::size_t s = 0; s < project.GetObjectsCount(); s++) {
auto& effects = project.GetObject(s).GetEffects();
// Add event-based objects layouts effects for (std::size_t e = 0; e < effects.GetEffectsCount(); e++) {
for (std::size_t s = 0; s < project.GetEventsFunctionsExtensionsCount(); auto& effect = effects.GetEffect(e);
s++) { worker(effect);
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);
}
}
} }
} }
} }
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 } // namespace gd

View File

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

View File

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

View File

@@ -14,10 +14,8 @@
#include "GDCore/Extensions/Metadata/ParameterMetadataTools.h" #include "GDCore/Extensions/Metadata/ParameterMetadataTools.h"
#include "GDCore/Extensions/Platform.h" #include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h" #include "GDCore/Extensions/PlatformExtension.h"
#include "GDCore/IDE/Events/ExpressionVariableNameFinder.h"
#include "GDCore/Project/Layout.h" #include "GDCore/Project/Layout.h"
#include "GDCore/Project/ObjectsContainer.h" #include "GDCore/Project/ObjectsContainer.h"
#include "GDCore/Project/ObjectsContainersList.h"
#include "GDCore/Project/Project.h" #include "GDCore/Project/Project.h"
using namespace std; using namespace std;
@@ -42,15 +40,14 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
const vector<gd::String>& arguments, const vector<gd::String>& arguments,
const gd::String& callStartString, const gd::String& callStartString,
std::size_t startFromArgument) { std::size_t startFromArgument) {
std::size_t relationalOperatorIndex = instrInfos.parameters.GetParametersCount(); std::size_t relationalOperatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "relationalOperator") { if (instrInfos.parameters[i].GetType() == "relationalOperator")
relationalOperatorIndex = i; relationalOperatorIndex = i;
}
} }
// Ensure that there is at least one parameter after the relational operator // Ensure that there is at least one parameter after the relational operator
if (relationalOperatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) { if (relationalOperatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError(); ReportError();
return ""; return "";
} }
@@ -71,36 +68,8 @@ gd::String EventsCodeGenerator::GenerateRelationalOperatorCall(
} }
} }
auto lhs = callStartString + "(" + argumentsStr + ")"; return callStartString + "(" + argumentsStr + ") " + relationalOperator +
return GenerateRelationalOperation(relationalOperator, lhs, rhs); " " + rhs;
}
/**
* @brief Generate a relational operation
*
* @param relationalOperator the operator
* @param lhs the left hand operand
* @param rhs the right hand operand
* @return gd::String
*/
gd::String EventsCodeGenerator::GenerateRelationalOperation(
const gd::String& relationalOperator,
const gd::String& lhs,
const gd::String& rhs) {
return lhs + " " + GenerateRelationalOperatorCodes(relationalOperator) + " " + rhs;
}
const gd::String EventsCodeGenerator::GenerateRelationalOperatorCodes(const gd::String &operatorString) {
if (operatorString == "=") {
return "==";
}
if (operatorString != "<" && operatorString != ">" &&
operatorString != "<=" && operatorString != ">=" && operatorString != "!=" &&
operatorString != "startsWith" && operatorString != "endsWith" && operatorString != "contains") {
cout << "Warning: Bad relational operator: Set to == by default." << endl;
return "==";
}
return operatorString;
} }
/** /**
@@ -123,16 +92,14 @@ gd::String EventsCodeGenerator::GenerateOperatorCall(
const gd::String& callStartString, const gd::String& callStartString,
const gd::String& getterStartString, const gd::String& getterStartString,
std::size_t startFromArgument) { std::size_t startFromArgument) {
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount(); std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") { if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
operatorIndex = i;
}
} }
// Ensure that there is at least one parameter after the operator // Ensure that there is at least one parameter after the operator
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) { if (operatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError(); ReportError();
return ""; return "";
} }
@@ -194,16 +161,14 @@ gd::String EventsCodeGenerator::GenerateCompoundOperatorCall(
const vector<gd::String>& arguments, const vector<gd::String>& arguments,
const gd::String& callStartString, const gd::String& callStartString,
std::size_t startFromArgument) { std::size_t startFromArgument) {
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount(); std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") { if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
operatorIndex = i;
}
} }
// Ensure that there is at least one parameter after the operator // Ensure that there is at least one parameter after the operator
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) { if (operatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError(); ReportError();
return ""; return "";
} }
@@ -247,27 +212,25 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
const vector<gd::String>& arguments, const vector<gd::String>& arguments,
const gd::String& callStartString, const gd::String& callStartString,
std::size_t startFromArgument) { std::size_t startFromArgument) {
std::size_t operatorIndex = instrInfos.parameters.GetParametersCount(); std::size_t operatorIndex = instrInfos.parameters.size();
for (std::size_t i = startFromArgument; i < instrInfos.parameters.GetParametersCount(); for (std::size_t i = startFromArgument; i < instrInfos.parameters.size();
++i) { ++i) {
if (instrInfos.parameters.GetParameter(i).GetType() == "operator") { if (instrInfos.parameters[i].GetType() == "operator") operatorIndex = i;
operatorIndex = i;
}
} }
// Ensure that there is at least one parameter after the operator // Ensure that there is at least one parameter after the operator
if (operatorIndex + 1 >= instrInfos.parameters.GetParametersCount()) { if (operatorIndex + 1 >= instrInfos.parameters.size()) {
ReportError(); ReportError();
return ""; return "";
} }
gd::String operatorStr = arguments[operatorIndex]; gd::String operatorStr = arguments[operatorIndex];
if (operatorStr.size() > 2 && operatorStr[0] == '\"') { if (operatorStr.size() > 2)
operatorStr = operatorStr.substr( operatorStr = operatorStr.substr(
1, 1,
operatorStr.length() - 1 - operatorStr.length() - 1 -
1); // Operator contains quote which must be removed. 1); // Operator contains quote which must be removed.
}
auto mutators = instrInfos.codeExtraInformation.optionalMutators; auto mutators = instrInfos.codeExtraInformation.optionalMutators;
auto mutator = mutators.find(operatorStr); auto mutator = mutators.find(operatorStr);
if (mutator == mutators.end()) { if (mutator == mutators.end()) {
@@ -287,9 +250,6 @@ gd::String EventsCodeGenerator::GenerateMutatorCall(
argumentsStr += arguments[i]; argumentsStr += arguments[i];
} }
} }
if (instrInfos.GetManipulatedType() == "boolean") {
return callStartString + "(" + argumentsStr + ")." + mutator->second;
}
return callStartString + "(" + argumentsStr + ")." + mutator->second + "(" + return callStartString + "(" + argumentsStr + ")." + mutator->second + "(" +
rhs + ")"; rhs + ")";
@@ -307,12 +267,14 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
return "/* Unknown instruction - skipped. */"; return "/* Unknown instruction - skipped. */";
} }
AddIncludeFiles(instrInfos.GetIncludeFiles()); AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
maxConditionsListsSize = maxConditionsListsSize =
std::max(maxConditionsListsSize, condition.GetSubInstructions().size()); std::max(maxConditionsListsSize, condition.GetSubInstructions().size());
if (instrInfos.HasCustomCodeGenerator()) { if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
context.EnterCustomCondition(); context.EnterCustomCondition();
conditionCode += GenerateReferenceToUpperScopeBoolean(
"conditionTrue", returnBoolean, context);
conditionCode += instrInfos.codeExtraInformation.customCodeGenerator( conditionCode += instrInfos.codeExtraInformation.customCodeGenerator(
condition, *this, context); condition, *this, context);
maxCustomConditionsDepth = maxCustomConditionsDepth =
@@ -323,36 +285,29 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
} }
// Insert code only parameters and be sure there is no lack of parameter. // 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(); vector<gd::Expression> parameters = condition.GetParameters();
parameters.push_back(gd::Expression("")); parameters.push_back(gd::Expression(""));
condition.SetParameters(parameters); condition.SetParameters(parameters);
} }
gd::EventsCodeGenerator::CheckBehaviorParameters(condition, instrInfos); // Verify that there are no mismatchs between object type in parameters.
// Verify that there are no mismatches between object type in parameters. for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) { if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
gd::String objectInParameter = gd::String objectInParameter =
condition.GetParameter(pNb).GetPlainString(); condition.GetParameter(pNb).GetPlainString();
const auto &expectedObjectType = if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
instrInfos.parameters.GetParameter(pNb).GetExtraInfo(); !GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
const auto &actualObjectType = !GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
GetObjectsContainersList().GetTypeOfObject(objectInParameter); !GetGlobalObjectsAndGroups().GetObjectGroups().Has(
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
objectInParameter)) { objectInParameter)) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
objectInParameter, "");
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
return "/* Unknown object - skipped. */"; return "/* Unknown object - skipped. */";
} else if (!expectedObjectType.empty() && } else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
actualObjectType != expectedObjectType) { gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
gd::ProjectDiagnostic projectDiagnostic( GetObjectsAndGroups(),
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "", objectInParameter) !=
actualObjectType, expectedObjectType, objectInParameter); instrInfos.parameters[pNb].GetExtraInfo()) {
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
return "/* Mismatched object type - skipped. */"; return "/* Mismatched object type - skipped. */";
} }
} }
@@ -360,15 +315,21 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
if (instrInfos.IsObjectInstruction()) { if (instrInfos.IsObjectInstruction()) {
gd::String objectName = condition.GetParameter(0).GetPlainString(); 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 = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Set up the context // Set up the context
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]); gd::String objectType = gd::GetTypeOfObject(
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), realObjects[i]);
const ObjectMetadata& objInfo = const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType); MetadataProvider::GetObjectMetadata(platform, objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
instrInfos.GetRequiredBaseObjectCapability())) {
conditionCode +=
"/* Object with unsupported capability - skipped. */\n";
} else {
AddIncludeFiles(objInfo.includeFiles); AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]); context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]); context.ObjectsListNeeded(realObjects[i]);
@@ -385,25 +346,22 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
context); context);
context.SetNoCurrentObject(); context.SetNoCurrentObject();
}
} }
} }
} else if (instrInfos.IsBehaviorInstruction()) { } else if (instrInfos.IsBehaviorInstruction()) {
if (instrInfos.parameters.GetParametersCount() >= 2) { gd::String objectName = condition.GetParameter(0).GetPlainString();
const gd::String &objectName = condition.GetParameter(0).GetPlainString(); gd::String behaviorType =
const gd::String &behaviorName = gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
condition.GetParameter(1).GetPlainString(); GetObjectsAndGroups(),
const gd::String &actualBehaviorType = condition.GetParameter(1).GetPlainString());
GetObjectsContainersList().GetTypeOfBehavior(behaviorName); if (instrInfos.parameters.size() >= 2) {
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName( ExpandObjectsName(objectName, context);
objectName, context.GetCurrentObject());
const BehaviorMetadata &autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context // Setup context
const BehaviorMetadata& autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
AddIncludeFiles(autoInfo.includeFiles); AddIncludeFiles(autoInfo.includeFiles);
context.SetCurrentObject(realObjects[i]); context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]); context.ObjectsListNeeded(realObjects[i]);
@@ -413,7 +371,7 @@ gd::String EventsCodeGenerator::GenerateConditionCode(
condition.GetParameters(), instrInfos.parameters, context); condition.GetParameters(), instrInfos.parameters, context);
conditionCode += GenerateBehaviorCondition( conditionCode += GenerateBehaviorCondition(
realObjects[i], realObjects[i],
behaviorName, condition.GetParameter(1).GetPlainString(),
autoInfo, autoInfo,
arguments, arguments,
instrInfos, instrInfos,
@@ -488,33 +446,6 @@ gd::String EventsCodeGenerator::GenerateConditionsListCode(
return outputCode; 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. * Generate code for an action.
*/ */
@@ -530,9 +461,9 @@ gd::String EventsCodeGenerator::GenerateActionCode(
return "/* Unknown instruction - skipped. */"; return "/* Unknown instruction - skipped. */";
} }
AddIncludeFiles(instrInfos.GetIncludeFiles()); AddIncludeFiles(instrInfos.codeExtraInformation.GetIncludeFiles());
if (instrInfos.HasCustomCodeGenerator()) { if (instrInfos.codeExtraInformation.HasCustomCodeGenerator()) {
return instrInfos.codeExtraInformation.customCodeGenerator( return instrInfos.codeExtraInformation.customCodeGenerator(
action, *this, context); action, *this, context);
} }
@@ -546,35 +477,27 @@ gd::String EventsCodeGenerator::GenerateActionCode(
: instrInfos.codeExtraInformation.functionCallName; : instrInfos.codeExtraInformation.functionCallName;
// Be sure there is no lack of parameter. // Be sure there is no lack of parameter.
while (action.GetParameters().size() < instrInfos.parameters.GetParametersCount()) { while (action.GetParameters().size() < instrInfos.parameters.size()) {
vector<gd::Expression> parameters = action.GetParameters(); vector<gd::Expression> parameters = action.GetParameters();
parameters.push_back(gd::Expression("")); parameters.push_back(gd::Expression(""));
action.SetParameters(parameters); action.SetParameters(parameters);
} }
gd::EventsCodeGenerator::CheckBehaviorParameters(action, instrInfos); // Verify that there are no mismatchs between object type in parameters.
// Verify that there are no mismatches between object type in parameters. for (std::size_t pNb = 0; pNb < instrInfos.parameters.size(); ++pNb) {
for (std::size_t pNb = 0; pNb < instrInfos.parameters.GetParametersCount(); ++pNb) { if (ParameterMetadata::IsObject(instrInfos.parameters[pNb].GetType())) {
if (ParameterMetadata::IsObject(instrInfos.parameters.GetParameter(pNb).GetType())) {
gd::String objectInParameter = action.GetParameter(pNb).GetPlainString(); gd::String objectInParameter = action.GetParameter(pNb).GetPlainString();
if (!GetObjectsAndGroups().HasObjectNamed(objectInParameter) &&
const auto &expectedObjectType = !GetGlobalObjectsAndGroups().HasObjectNamed(objectInParameter) &&
instrInfos.parameters.GetParameter(pNb).GetExtraInfo(); !GetObjectsAndGroups().GetObjectGroups().Has(objectInParameter) &&
const auto &actualObjectType = !GetGlobalObjectsAndGroups().GetObjectGroups().Has(
GetObjectsContainersList().GetTypeOfObject(objectInParameter);
if (!GetObjectsContainersList().HasObjectOrGroupNamed(
objectInParameter)) { objectInParameter)) {
gd::ProjectDiagnostic projectDiagnostic(
gd::ProjectDiagnostic::ErrorType::UnknownObject, "",
objectInParameter, "");
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
return "/* Unknown object - skipped. */"; return "/* Unknown object - skipped. */";
} else if (!expectedObjectType.empty() && } else if (!instrInfos.parameters[pNb].GetExtraInfo().empty() &&
actualObjectType != expectedObjectType) { gd::GetTypeOfObject(GetGlobalObjectsAndGroups(),
gd::ProjectDiagnostic projectDiagnostic( GetObjectsAndGroups(),
gd::ProjectDiagnostic::ErrorType::MismatchedObjectType, "", objectInParameter) !=
actualObjectType, expectedObjectType, objectInParameter); instrInfos.parameters[pNb].GetExtraInfo()) {
if (diagnosticReport) diagnosticReport->Add(projectDiagnostic);
return "/* Mismatched object type - skipped. */"; return "/* Mismatched object type - skipped. */";
} }
} }
@@ -584,15 +507,20 @@ gd::String EventsCodeGenerator::GenerateActionCode(
if (instrInfos.IsObjectInstruction()) { if (instrInfos.IsObjectInstruction()) {
gd::String objectName = action.GetParameter(0).GetPlainString(); gd::String objectName = action.GetParameter(0).GetPlainString();
if (instrInfos.parameters.GetParametersCount() > 0) { if (!instrInfos.parameters.empty()) {
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName(objectName, context.GetCurrentObject()); ExpandObjectsName(objectName, context);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context // Setup context
gd::String objectType = GetObjectsContainersList().GetTypeOfObject(realObjects[i]); gd::String objectType = gd::GetTypeOfObject(
GetGlobalObjectsAndGroups(), GetObjectsAndGroups(), realObjects[i]);
const ObjectMetadata& objInfo = const ObjectMetadata& objInfo =
MetadataProvider::GetObjectMetadata(platform, objectType); MetadataProvider::GetObjectMetadata(platform, objectType);
if (objInfo.IsUnsupportedBaseObjectCapability(
instrInfos.GetRequiredBaseObjectCapability())) {
actionCode += "/* Object with unsupported capability - skipped. */\n";
} else {
AddIncludeFiles(objInfo.includeFiles); AddIncludeFiles(objInfo.includeFiles);
context.SetCurrentObject(realObjects[i]); context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]); context.ObjectsListNeeded(realObjects[i]);
@@ -609,25 +537,24 @@ gd::String EventsCodeGenerator::GenerateActionCode(
optionalAsyncCallbackName); optionalAsyncCallbackName);
context.SetNoCurrentObject(); context.SetNoCurrentObject();
}
} }
} }
} else if (instrInfos.IsBehaviorInstruction()) { } else if (instrInfos.IsBehaviorInstruction()) {
if (instrInfos.parameters.GetParametersCount() >= 2) { gd::String objectName = action.GetParameter(0).GetPlainString();
const gd::String &objectName = action.GetParameter(0).GetPlainString(); gd::String behaviorType =
const gd::String &behaviorName = action.GetParameter(1).GetPlainString(); gd::GetTypeOfBehavior(GetGlobalObjectsAndGroups(),
const gd::String &actualBehaviorType = GetObjectsAndGroups(),
GetObjectsContainersList().GetTypeOfBehavior(behaviorName); action.GetParameter(1).GetPlainString());
if (instrInfos.parameters.size() >= 2) {
std::vector<gd::String> realObjects = std::vector<gd::String> realObjects =
GetObjectsContainersList().ExpandObjectName( ExpandObjectsName(objectName, context);
objectName, context.GetCurrentObject());
const BehaviorMetadata &autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, actualBehaviorType);
AddIncludeFiles(autoInfo.includeFiles);
for (std::size_t i = 0; i < realObjects.size(); ++i) { for (std::size_t i = 0; i < realObjects.size(); ++i) {
// Setup context // Setup context
const BehaviorMetadata& autoInfo =
MetadataProvider::GetBehaviorMetadata(platform, behaviorType);
AddIncludeFiles(autoInfo.includeFiles);
context.SetCurrentObject(realObjects[i]); context.SetCurrentObject(realObjects[i]);
context.ObjectsListNeeded(realObjects[i]); context.ObjectsListNeeded(realObjects[i]);
@@ -636,7 +563,7 @@ gd::String EventsCodeGenerator::GenerateActionCode(
action.GetParameters(), instrInfos.parameters, context); action.GetParameters(), instrInfos.parameters, context);
actionCode += actionCode +=
GenerateBehaviorAction(realObjects[i], GenerateBehaviorAction(realObjects[i],
behaviorName, action.GetParameter(1).GetPlainString(),
autoInfo, autoInfo,
functionCallName, functionCallName,
arguments, arguments,
@@ -660,29 +587,6 @@ gd::String EventsCodeGenerator::GenerateActionCode(
return actionCode; 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 const EventsCodeGenerator::CallbackDescriptor
EventsCodeGenerator::GenerateCallback( EventsCodeGenerator::GenerateCallback(
const gd::String& callbackID, const gd::String& callbackID,
@@ -707,23 +611,14 @@ EventsCodeGenerator::GenerateCallback(
actionsCode += "} //End of subevents\n"; actionsCode += "} //End of subevents\n";
} }
gd::String restoreLocalVariablesCode;
restoreLocalVariablesCode +=
"asyncObjectsList.restoreLocalVariablesContainers(" +
GenerateLocalVariablesStackAccessor() + ");\n";
// Compose the callback function and add outside main // Compose the callback function and add outside main
const gd::String actionsDeclarationsCode = const gd::String actionsDeclarationsCode =
GenerateObjectsDeclarationCode(callbackContext); GenerateObjectsDeclarationCode(callbackContext);
const gd::String clearLocalVariablesCode =
GenerateLocalVariablesStackAccessor() + ".length = 0;\n";
const gd::String callbackCode = callbackFunctionName + " = function (" + const gd::String callbackCode = callbackFunctionName + " = function (" +
GenerateEventsParameters(callbackContext) + GenerateEventsParameters(callbackContext) +
") {\n" + restoreLocalVariablesCode + ") {\n" + actionsDeclarationsCode +
actionsDeclarationsCode + actionsCode + actionsCode + "}\n";
clearLocalVariablesCode + "}\n";
AddCustomCodeOutsideMain(callbackCode); AddCustomCodeOutsideMain(callbackCode);
@@ -786,26 +681,32 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
if (ParameterMetadata::IsExpression("number", metadata.GetType())) { if (ParameterMetadata::IsExpression("number", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode( argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "number", parameter, lastObjectName, metadata.GetExtraInfo()); *this, context, "number", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("string", metadata.GetType())) { } else if (ParameterMetadata::IsExpression("string", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode( argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, "string", parameter, lastObjectName, metadata.GetExtraInfo()); *this, context, "string", parameter, lastObjectName);
} else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) { } else if (ParameterMetadata::IsExpression("variable", metadata.GetType())) {
argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode( argOutput = gd::ExpressionCodeGenerator::GenerateExpressionCode(
*this, context, metadata.GetType(), parameter, lastObjectName, metadata.GetExtraInfo()); *this, context, metadata.GetType(), parameter, lastObjectName);
} else if (ParameterMetadata::IsObject(metadata.GetType())) { } else if (ParameterMetadata::IsObject(metadata.GetType())) {
// It would be possible to run a gd::ExpressionCodeGenerator if later // It would be possible to run a gd::ExpressionCodeGenerator if later
// objects can have nested objects, or function returning objects. // objects can have nested objects, or function returning objects.
argOutput = argOutput =
GenerateObject(parameter.GetPlainString(), metadata.GetType(), context); GenerateObject(parameter.GetPlainString(), metadata.GetType(), context);
} else if (metadata.GetType() == "relationalOperator") { } else if (metadata.GetType() == "relationalOperator") {
argOutput += parameter.GetPlainString(); auto parameterString = parameter.GetPlainString();
argOutput += parameterString == "=" ? "==" : parameterString;
if (argOutput != "==" && argOutput != "<" && argOutput != ">" &&
argOutput != "<=" && argOutput != ">=" && argOutput != "!=") {
cout << "Warning: Bad relational operator: Set to == by default." << endl;
argOutput = "==";
}
argOutput = "\"" + argOutput + "\""; argOutput = "\"" + argOutput + "\"";
} else if (metadata.GetType() == "operator") { } else if (metadata.GetType() == "operator") {
argOutput += parameter.GetPlainString(); argOutput += parameter.GetPlainString();
if (argOutput != "=" && argOutput != "+" && argOutput != "-" && if (argOutput != "=" && argOutput != "+" && argOutput != "-" &&
argOutput != "/" && argOutput != "*" && argOutput != "True" && argOutput != "/" && argOutput != "*") {
argOutput != "False" && argOutput != "Toggle") {
cout << "Warning: Bad operator: Set to = by default." << endl; cout << "Warning: Bad operator: Set to = by default." << endl;
argOutput = "="; argOutput = "=";
} }
@@ -820,15 +721,10 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
metadata.GetType() == "fontResource" || metadata.GetType() == "fontResource" ||
metadata.GetType() == "imageResource" || metadata.GetType() == "imageResource" ||
metadata.GetType() == "jsonResource" || metadata.GetType() == "jsonResource" ||
metadata.GetType() == "tilemapResource" ||
metadata.GetType() == "tilesetResource" ||
metadata.GetType() == "videoResource" || metadata.GetType() == "videoResource" ||
metadata.GetType() == "model3DResource" ||
metadata.GetType() == "atlasResource" ||
metadata.GetType() == "spineResource" ||
// Deprecated, old parameter names: // Deprecated, old parameter names:
metadata.GetType() == "password" || metadata.GetType() == "musicfile" || metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
metadata.GetType() == "soundfile") { metadata.GetType() == "soundfile" || metadata.GetType() == "police") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\""; argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
} else if (metadata.GetType() == "mouse") { } else if (metadata.GetType() == "mouse") {
argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\""; argOutput = "\"" + ConvertToString(parameter.GetPlainString()) + "\"";
@@ -870,7 +766,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
vector<gd::String> EventsCodeGenerator::GenerateParametersCodes( vector<gd::String> EventsCodeGenerator::GenerateParametersCodes(
const vector<gd::Expression>& parameters, const vector<gd::Expression>& parameters,
const ParameterMetadataContainer& parametersInfo, const vector<gd::ParameterMetadata>& parametersInfo,
EventsCodeGenerationContext& context, EventsCodeGenerationContext& context,
std::vector<std::pair<gd::String, gd::String> >* std::vector<std::pair<gd::String, gd::String> >*
supplementaryParametersTypes) { supplementaryParametersTypes) {
@@ -975,11 +871,6 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
gd::EventsList& events, EventsCodeGenerationContext& parentContext) { gd::EventsList& events, EventsCodeGenerationContext& parentContext) {
gd::String output; gd::String output;
for (std::size_t eId = 0; eId < events.size(); ++eId) { for (std::size_t eId = 0; eId < events.size(); ++eId) {
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 // Each event has its own context : Objects picked in an event are totally
// different than the one picked in another. // different than the one picked in another.
gd::EventsCodeGenerationContext newContext; gd::EventsCodeGenerationContext newContext;
@@ -1000,17 +891,13 @@ gd::String EventsCodeGenerator::GenerateEventsListCode(
auto& context = reuseParentContext ? reusedContext : newContext; 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 scopeBegin = GenerateScopeBegin(context);
gd::String scopeEnd = GenerateScopeEnd(context); gd::String scopeEnd = GenerateScopeEnd(context);
gd::String declarationsCode = GenerateObjectsDeclarationCode(context); gd::String declarationsCode = GenerateObjectsDeclarationCode(context);
output += "\n" + scopeBegin + "\n" + declarationsCode + "\n" + output += "\n" + scopeBegin + "\n" + declarationsCode + "\n" +
eventCoreCode + "\n" + scopeEnd + "\n"; eventCoreCode + "\n" + scopeEnd + "\n";
if (event.HasVariables()) {
GetProjectScopedContainers().GetVariablesContainersList().Pop();
}
} }
return output; return output;
@@ -1030,6 +917,41 @@ gd::String EventsCodeGenerator::ConvertToStringExplicit(
return "\"" + ConvertToString(plainString) + "\""; return "\"" + ConvertToString(plainString) + "\"";
} }
std::vector<gd::String> EventsCodeGenerator::ExpandObjectsName(
const gd::String& objectName,
const EventsCodeGenerationContext& context) const {
// Note: this logic is duplicated in EventsContextAnalyzer::ExpandObjectsName
std::vector<gd::String> realObjects;
if (globalObjectsAndGroups.GetObjectGroups().Has(objectName))
realObjects = globalObjectsAndGroups.GetObjectGroups()
.Get(objectName)
.GetAllObjectsNames();
else if (objectsAndGroups.GetObjectGroups().Has(objectName))
realObjects =
objectsAndGroups.GetObjectGroups().Get(objectName).GetAllObjectsNames();
else
realObjects.push_back(objectName);
// If current object is present, use it and only it.
if (find(realObjects.begin(),
realObjects.end(),
context.GetCurrentObject()) != realObjects.end()) {
realObjects.clear();
realObjects.push_back(context.GetCurrentObject());
}
// Ensure that all returned objects actually exists.
for (std::size_t i = 0; i < realObjects.size();) {
if (!objectsAndGroups.HasObjectNamed(realObjects[i]) &&
!globalObjectsAndGroups.HasObjectNamed(realObjects[i]))
realObjects.erase(realObjects.begin() + i);
else
++i;
}
return realObjects;
}
void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) { void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) {
for (std::size_t eId = events.size() - 1; eId < events.size(); --eId) { for (std::size_t eId = events.size() - 1; eId < events.size(); --eId) {
if (events[eId].CanHaveSubEvents()) // Process sub events, if any if (events[eId].CanHaveSubEvents()) // Process sub events, if any
@@ -1046,8 +968,6 @@ void EventsCodeGenerator::DeleteUselessEvents(gd::EventsList& events) {
*/ */
void EventsCodeGenerator::PreprocessEventList(gd::EventsList& listEvent) { void EventsCodeGenerator::PreprocessEventList(gd::EventsList& listEvent) {
for (std::size_t i = 0; i < listEvent.GetEventsCount(); ++i) { for (std::size_t i = 0; i < listEvent.GetEventsCount(); ++i) {
if (listEvent[i].IsDisabled()) continue;
listEvent[i].Preprocess(*this, listEvent, i); listEvent[i].Preprocess(*this, listEvent, i);
if (i < if (i <
listEvent.GetEventsCount()) { // Be sure that that there is still an listEvent.GetEventsCount()) { // Be sure that that there is still an
@@ -1093,31 +1013,31 @@ gd::String EventsCodeGenerator::GenerateFreeCondition(
bool conditionInverted, bool conditionInverted,
gd::EventsCodeGenerationContext& context) { gd::EventsCodeGenerationContext& context) {
// Generate call // Generate call
gd::String predicate; gd::String predicat;
if (instrInfos.codeExtraInformation.type == "number" || if (instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string") { instrInfos.codeExtraInformation.type == "string") {
predicate = GenerateRelationalOperatorCall( predicat = GenerateRelationalOperatorCall(
instrInfos, instrInfos,
arguments, arguments,
instrInfos.codeExtraInformation.functionCallName); instrInfos.codeExtraInformation.functionCallName);
} else { } else {
predicate = instrInfos.codeExtraInformation.functionCallName + "(" + predicat = instrInfos.codeExtraInformation.functionCallName + "(" +
GenerateArgumentsList(arguments, 0) + ")"; GenerateArgumentsList(arguments, 0) + ")";
} }
// Add logical not if needed // Add logical not if needed
bool conditionAlreadyTakeCareOfInversion = false; 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 ++i) // Some conditions already have a "conditionInverted" parameter
{ {
if (instrInfos.parameters.GetParameter(i).GetType() == "conditionInverted") if (instrInfos.parameters[i].GetType() == "conditionInverted")
conditionAlreadyTakeCareOfInversion = true; conditionAlreadyTakeCareOfInversion = true;
} }
if (!conditionAlreadyTakeCareOfInversion && conditionInverted) if (!conditionAlreadyTakeCareOfInversion && conditionInverted)
predicate = GenerateNegatedPredicate(predicate); predicat = GenerateNegatedPredicat(predicat);
// Generate condition code // Generate condition code
return returnBoolean + " = " + predicate + ";\n"; return returnBoolean + " = " + predicat + ";\n";
} }
gd::String EventsCodeGenerator::GenerateObjectCondition( gd::String EventsCodeGenerator::GenerateObjectCondition(
@@ -1131,7 +1051,7 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
// Prepare call // Prepare call
// Add a static_cast if necessary // Add a static_cast if necessary
gd::String objectFunctionCallNamePart = gd::String objectFunctionCallNamePart =
(!instrInfos.parameters.GetParameter(0).GetExtraInfo().empty()) (!instrInfos.parameters[0].GetExtraInfo().empty())
? "static_cast<" + objInfo.className + "*>(" + ? "static_cast<" + objInfo.className + "*>(" +
GetObjectListName(objectName, context) + "[i])->" + GetObjectListName(objectName, context) + "[i])->" +
instrInfos.codeExtraInformation.functionCallName instrInfos.codeExtraInformation.functionCallName
@@ -1139,18 +1059,18 @@ gd::String EventsCodeGenerator::GenerateObjectCondition(
instrInfos.codeExtraInformation.functionCallName; instrInfos.codeExtraInformation.functionCallName;
// Create call // Create call
gd::String predicate; gd::String predicat;
if ((instrInfos.codeExtraInformation.type == "number" || if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) { instrInfos.codeExtraInformation.type == "string")) {
predicate = GenerateRelationalOperatorCall( predicat = GenerateRelationalOperatorCall(
instrInfos, arguments, objectFunctionCallNamePart, 1); instrInfos, arguments, objectFunctionCallNamePart, 1);
} else { } else {
predicate = objectFunctionCallNamePart + "(" + predicat = objectFunctionCallNamePart + "(" +
GenerateArgumentsList(arguments, 1) + ")"; GenerateArgumentsList(arguments, 1) + ")";
} }
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate); if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
return "For each picked object \"" + objectName + "\", check " + predicate + return "For each picked object \"" + objectName + "\", check " + predicat +
".\n"; ".\n";
} }
@@ -1164,16 +1084,16 @@ gd::String EventsCodeGenerator::GenerateBehaviorCondition(
bool conditionInverted, bool conditionInverted,
gd::EventsCodeGenerationContext& context) { gd::EventsCodeGenerationContext& context) {
// Create call // Create call
gd::String predicate; gd::String predicat;
if ((instrInfos.codeExtraInformation.type == "number" || if ((instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string")) { instrInfos.codeExtraInformation.type == "string")) {
predicate = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2); predicat = GenerateRelationalOperatorCall(instrInfos, arguments, "", 2);
} else { } else {
predicate = "(" + GenerateArgumentsList(arguments, 2) + ")"; predicat = "(" + GenerateArgumentsList(arguments, 2) + ")";
} }
if (conditionInverted) predicate = GenerateNegatedPredicate(predicate); if (conditionInverted) predicat = GenerateNegatedPredicat(predicat);
return "For each picked object \"" + objectName + "\", check " + predicate + return "For each picked object \"" + objectName + "\", check " + predicat +
" for behavior \"" + behaviorName + "\".\n"; " for behavior \"" + behaviorName + "\".\n";
} }
@@ -1186,13 +1106,7 @@ gd::String EventsCodeGenerator::GenerateFreeAction(
// Generate call // Generate call
gd::String call; gd::String call;
if (instrInfos.codeExtraInformation.type == "number" || if (instrInfos.codeExtraInformation.type == "number" ||
instrInfos.codeExtraInformation.type == "string" || 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)) {
if (instrInfos.codeExtraInformation.accessType == if (instrInfos.codeExtraInformation.accessType ==
gd::InstructionMetadata::ExtraInformation::MutatorAndOrAccessor) gd::InstructionMetadata::ExtraInformation::MutatorAndOrAccessor)
call = GenerateOperatorCall( call = GenerateOperatorCall(
@@ -1319,7 +1233,7 @@ size_t EventsCodeGenerator::GenerateSingleUsageUniqueIdFor(
<< std::endl; << std::endl;
} }
// Base the unique id on the address in memory so that the same instruction // Base the unique id on the adress in memory so that the same instruction
// in memory will get the same id across different code generations. // in memory will get the same id across different code generations.
size_t uniqueId = (size_t)instruction; size_t uniqueId = (size_t)instruction;
@@ -1351,42 +1265,12 @@ gd::String EventsCodeGenerator::GenerateArgumentsList(
return argumentsStr; 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_, EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
const gd::Layout& layout, const gd::Layout& layout,
const gd::Platform& platform_) const gd::Platform& platform_)
: platform(platform_), : platform(platform_),
projectScopedContainers(gd::ProjectScopedContainers::MakeNewProjectScopedContainersForProjectAndLayout(project_, layout)), globalObjectsAndGroups(project_),
objectsAndGroups(layout),
hasProjectAndLayout(true), hasProjectAndLayout(true),
project(&project_), project(&project_),
scene(&layout), scene(&layout),
@@ -1394,14 +1278,15 @@ EventsCodeGenerator::EventsCodeGenerator(const gd::Project& project_,
compilationForRuntime(false), compilationForRuntime(false),
maxCustomConditionsDepth(0), maxCustomConditionsDepth(0),
maxConditionsListsSize(0), maxConditionsListsSize(0),
eventsListNextUniqueId(0), eventsListNextUniqueId(0){};
diagnosticReport(nullptr){};
EventsCodeGenerator::EventsCodeGenerator( EventsCodeGenerator::EventsCodeGenerator(
const gd::Platform& platform_, const gd::Platform& platform_,
const gd::ProjectScopedContainers& projectScopedContainers_) const gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ObjectsContainer& objectsAndGroups_)
: platform(platform_), : platform(platform_),
projectScopedContainers(projectScopedContainers_), globalObjectsAndGroups(globalObjectsAndGroups_),
objectsAndGroups(objectsAndGroups_),
hasProjectAndLayout(false), hasProjectAndLayout(false),
project(nullptr), project(nullptr),
scene(nullptr), scene(nullptr),
@@ -1409,7 +1294,6 @@ EventsCodeGenerator::EventsCodeGenerator(
compilationForRuntime(false), compilationForRuntime(false),
maxCustomConditionsDepth(0), maxCustomConditionsDepth(0),
maxConditionsListsSize(0), maxConditionsListsSize(0),
eventsListNextUniqueId(0), eventsListNextUniqueId(0){};
diagnosticReport(nullptr){};
} // namespace gd } // namespace gd

View File

@@ -3,7 +3,8 @@
* Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights * Copyright 2008-present Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#pragma once #ifndef GDCORE_EVENTSCODEGENERATOR_H
#define GDCORE_EVENTSCODEGENERATOR_H
#include <set> #include <set>
#include <utility> #include <utility>
@@ -11,17 +12,13 @@
#include "GDCore/Events/Event.h" #include "GDCore/Events/Event.h"
#include "GDCore/Events/Instruction.h" #include "GDCore/Events/Instruction.h"
#include "GDCore/Events/CodeGeneration/DiagnosticReport.h"
#include "GDCore/Project/ProjectScopedContainers.h"
#include "GDCore/String.h" #include "GDCore/String.h"
namespace gd { namespace gd {
class EventsList; class EventsList;
class Expression; class Expression;
class Project; class Project;
class Layout; class Layout;
class ObjectsContainer; class ObjectsContainer;
class ObjectsContainersList;
class ExternalEvents; class ExternalEvents;
class ParameterMetadata; class ParameterMetadata;
class ObjectMetadata; class ObjectMetadata;
@@ -59,9 +56,9 @@ class GD_CORE_API EventsCodeGenerator {
* \brief Construct a code generator for the specified * \brief Construct a code generator for the specified
* objects/groups and platform * objects/groups and platform
*/ */
EventsCodeGenerator( EventsCodeGenerator(const gd::Platform& platform,
const gd::Platform& platform, const gd::ObjectsContainer& globalObjectsAndGroups_,
const gd::ProjectScopedContainers& projectScopedContainers_); const gd::ObjectsContainer& objectsAndGroups_);
virtual ~EventsCodeGenerator(){}; virtual ~EventsCodeGenerator(){};
/** /**
@@ -128,7 +125,7 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
std::vector<gd::String> GenerateParametersCodes( std::vector<gd::String> GenerateParametersCodes(
const std::vector<gd::Expression>& parameters, const std::vector<gd::Expression>& parameters,
const ParameterMetadataContainer& parametersInfo, const std::vector<gd::ParameterMetadata>& parametersInfo,
EventsCodeGenerationContext& context, EventsCodeGenerationContext& context,
std::vector<std::pair<gd::String, gd::String> >* std::vector<std::pair<gd::String, gd::String> >*
supplementaryParametersTypes = 0); supplementaryParametersTypes = 0);
@@ -329,22 +326,18 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
bool ErrorOccurred() const { return errorOccurred; }; bool ErrorOccurred() const { return errorOccurred; };
const gd::ObjectsContainersList& GetObjectsContainersList() const { /**
return projectScopedContainers.GetObjectsContainersList(); * \brief Get the global objects/groups used for code generation.
}; */
const gd::ObjectsContainer& GetGlobalObjectsAndGroups() const {
const gd::ProjectScopedContainers& GetProjectScopedContainers() const { return globalObjectsAndGroups;
return projectScopedContainers;
} }
/** /**
* @brief Give access to the project scoped containers as code generation might * \brief Get the objects/groups used for code generation.
* 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.
*/ */
gd::ProjectScopedContainers& GetProjectScopedContainers() { const gd::ObjectsContainer& GetObjectsAndGroups() const {
return projectScopedContainers; return objectsAndGroups;
} }
/** /**
@@ -370,6 +363,22 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
const gd::Platform& GetPlatform() const { return platform; } const gd::Platform& GetPlatform() const { return platform; }
/**
* \brief Convert a group name to the full list of objects contained in the
* group.
*
* Get a list containing the "real" objects name when the events refers to \a
* objectName :<br> If \a objectName is really an object, the list will only
* contains \a objectName unchanged.<br> If \a objectName is a group, the list
* will contains all the objects of the group.<br> If \a objectName is the
* "current" object in the context ( i.e: The object being used for launching
* an action... ), none of the two rules below apply, and the list will only
* contains the context "current" object name.
*/
std::vector<gd::String> ExpandObjectsName(
const gd::String& objectName,
const EventsCodeGenerationContext& context) const;
/** /**
* \brief Get the maximum depth of custom conditions reached during code * \brief Get the maximum depth of custom conditions reached during code
* generation. * generation.
@@ -383,14 +392,6 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
size_t GetMaxConditionsListsSize() const { return maxConditionsListsSize; } 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 * \brief Generate the full name for accessing to a boolean variable used for
* conditions. * conditions.
@@ -403,18 +404,6 @@ class GD_CORE_API EventsCodeGenerator {
return boolName; return boolName;
} }
/**
* \brief Generate the full name for accessing to a boolean variable used for
* conditions.
*
* Default implementation just returns the boolean name passed as argument.
*/
virtual gd::String GenerateUpperScopeBooleanFullName(
const gd::String& boolName,
const gd::EventsCodeGenerationContext& context) {
return boolName;
}
/** /**
* \brief Must create a boolean. Its value must be false. * \brief Must create a boolean. Its value must be false.
* *
@@ -467,14 +456,7 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
virtual gd::String GetCodeNamespace() { return ""; }; virtual gd::String GetCodeNamespace() { return ""; };
enum VariableScope { enum VariableScope { LAYOUT_VARIABLE = 0, PROJECT_VARIABLE, OBJECT_VARIABLE };
LAYOUT_VARIABLE = 0,
PROJECT_VARIABLE,
OBJECT_VARIABLE,
ANY_VARIABLE,
VARIABLE_OR_PROPERTY,
VARIABLE_OR_PROPERTY_OR_PARAMETER
};
/** /**
* Generate a single unique number for the specified instruction. * Generate a single unique number for the specified instruction.
@@ -499,33 +481,7 @@ class GD_CORE_API EventsCodeGenerator {
*/ */
size_t GenerateSingleUsageUniqueIdForEventsList(); size_t GenerateSingleUsageUniqueIdForEventsList();
virtual gd::String GenerateRelationalOperation( protected:
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);
/** /**
* \brief Generate the code for a single parameter. * \brief Generate the code for a single parameter.
* *
@@ -534,13 +490,13 @@ protected:
* - object : Object name -> string * - object : Object name -> string
* - expression : Mathematical expression -> number (double) * - expression : Mathematical expression -> number (double)
* - string : %Text expression -> string * - string : %Text expression -> string
* - layer, color, file, stringWithSelector : Same as string * - layer, color, file, joyaxis : Same as string
* - relationalOperator : Used to make a comparison between the function * - relationalOperator : Used to make a comparison between the function
return value and value of the parameter preceding the relationOperator resturn value and value of the parameter preceding the relationOperator
parameter -> string parameter -> string
* - operator : Used to update a value using a setter and a getter -> string * - operator : Used to update a value using a setter and a getter -> string
* - key, mouse, objectvar, scenevar, globalvar, password, musicfile, * - key, mouse, objectvar, scenevar, globalvar, password, musicfile,
soundfile -> string soundfile, police -> string
* - trueorfalse, yesorno -> boolean ( See GenerateTrue/GenerateFalse ). * - trueorfalse, yesorno -> boolean ( See GenerateTrue/GenerateFalse ).
* *
* <br><br> * <br><br>
@@ -577,19 +533,12 @@ protected:
const gd::String& variableName, const gd::String& variableName,
const VariableScope& scope, const VariableScope& scope,
gd::EventsCodeGenerationContext& context, gd::EventsCodeGenerationContext& context,
const gd::String& objectName, const gd::String& objectName) {
bool hasChild) {
// This code is only used as a mock.
// See the real implementation in GDJS.
if (scope == LAYOUT_VARIABLE) { if (scope == LAYOUT_VARIABLE) {
return "getLayoutVariable(" + variableName + ")"; return "getLayoutVariable(" + variableName + ")";
} else if (scope == PROJECT_VARIABLE) { } else if (scope == PROJECT_VARIABLE) {
return "getProjectVariable(" + variableName + ")"; 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 + ")"; return "getVariableForObject(" + objectName + ", " + variableName + ")";
@@ -602,12 +551,6 @@ protected:
return ".getChild(" + ConvertToStringExplicit(childName) + ")"; return ".getChild(" + ConvertToStringExplicit(childName) + ")";
}; };
virtual gd::String GenerateVariableValueAs(const gd::String& type) {
return type == "number|string" ? ".getAsNumberOrString()"
: type == "string" ? ".getAsString()"
: ".getAsNumber()";
}
/** /**
* \brief Generate the code to get the child of a variable, * \brief Generate the code to get the child of a variable,
* using generated the expression. * using generated the expression.
@@ -636,24 +579,6 @@ protected:
return "fakeObjectListOf_" + objectName; return "fakeObjectListOf_" + objectName;
} }
virtual gd::String GeneratePropertyGetter(
const gd::PropertiesContainer& propertiesContainer,
const gd::NamedPropertyDescriptor& property,
const gd::String& type,
gd::EventsCodeGenerationContext& context);
virtual gd::String 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 * \brief Generate the code to reference an object which is
* in an empty/null state. * in an empty/null state.
@@ -728,16 +653,28 @@ 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 !. * inside parenthesis and add a !.
*/ */
virtual gd::String GenerateNegatedPredicate( virtual gd::String GenerateNegatedPredicat(const gd::String& predicat) const {
const gd::String& predicate) const { return "!(" + predicat + ")";
return "!(" + predicate + ")";
}; };
/**
* \brief Must create a boolean which is a reference to a boolean declared in
* the parent scope.
*
* The default implementation generates C-style code.
*/
virtual gd::String GenerateReferenceToUpperScopeBoolean(
const gd::String& referenceName,
const gd::String& referencedBoolean,
gd::EventsCodeGenerationContext& context) {
return "bool & " + referenceName + " = " + referencedBoolean + ";\n";
}
virtual gd::String GenerateFreeCondition( virtual gd::String GenerateFreeCondition(
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::InstructionMetadata& instrInfos, const gd::InstructionMetadata& instrInfos,
@@ -795,7 +732,6 @@ protected:
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::String& callStartString, const gd::String& callStartString,
std::size_t startFromArgument = 0); std::size_t startFromArgument = 0);
gd::String GenerateOperatorCall(const gd::InstructionMetadata& instrInfos, gd::String GenerateOperatorCall(const gd::InstructionMetadata& instrInfos,
const std::vector<gd::String>& arguments, const std::vector<gd::String>& arguments,
const gd::String& callStartString, const gd::String& callStartString,
@@ -837,20 +773,17 @@ protected:
virtual gd::String GenerateGetBehaviorNameCode( virtual gd::String GenerateGetBehaviorNameCode(
const gd::String& behaviorName); const gd::String& behaviorName);
void CheckBehaviorParameters(
const gd::Instruction &instruction,
const gd::InstructionMetadata &instrInfos);
const gd::Platform& platform; ///< The platform being used. 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 bool hasProjectAndLayout; ///< true only if project and layout are valid
///< references. If false, they should not be used. ///< references. If false, they should not be used.
const gd::Project* project; ///< The project being used. const gd::Project* project; ///< The project being used.
const gd::Layout* scene; ///< The scene being generated. const gd::Layout* scene; ///< The scene being generated.
bool errorOccurred; ///< Must be set to true if an error occurred. bool errorOccurred; ///< Must be set to true if an error occured.
bool compilationForRuntime; ///< Is set to true if the code generation is bool compilationForRuntime; ///< Is set to true if the code generation is
///< made for runtime only. ///< made for runtime only.
@@ -871,9 +804,8 @@ protected:
instructionUniqueIds; ///< The unique ids generated for instructions. instructionUniqueIds; ///< The unique ids generated for instructions.
size_t eventsListNextUniqueId; ///< The next identifier to use for an events size_t eventsListNextUniqueId; ///< The next identifier to use for an events
///< list function name. ///< list function name.
gd::DiagnosticReport* diagnosticReport;
}; };
} // namespace gd } // namespace gd
#endif // GDCORE_EVENTSCODEGENERATOR_H

View File

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

View File

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

View File

@@ -9,7 +9,6 @@
#include "GDCore/Events/Builtin/AsyncEvent.h" #include "GDCore/Events/Builtin/AsyncEvent.h"
#include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h"
#include "GDCore/Events/EventsList.h" #include "GDCore/Events/EventsList.h"
#include "GDCore/Events/EventVisitor.h"
#include "GDCore/Extensions/Metadata/MetadataProvider.h" #include "GDCore/Extensions/Metadata/MetadataProvider.h"
#include "GDCore/Extensions/Platform.h" #include "GDCore/Extensions/Platform.h"
#include "GDCore/Extensions/PlatformExtension.h" #include "GDCore/Extensions/PlatformExtension.h"
@@ -17,7 +16,8 @@
namespace gd { namespace gd {
EventsList BaseEvent::badSubEvents; EventsList BaseEvent::badSubEvents;
VariablesContainer BaseEvent::badLocalVariables; std::vector<gd::String> BaseEvent::emptyDependencies;
gd::String BaseEvent::emptySourceFile;
BaseEvent::BaseEvent() BaseEvent::BaseEvent()
: totalTimeDuringLastSession(0), : totalTimeDuringLastSession(0),
@@ -27,8 +27,6 @@ BaseEvent::BaseEvent()
bool BaseEvent::HasSubEvents() const { return !GetSubEvents().IsEmpty(); } bool BaseEvent::HasSubEvents() const { return !GetSubEvents().IsEmpty(); }
bool BaseEvent::HasVariables() const { return GetVariables().Count() > 0; }
gd::String BaseEvent::GenerateEventCode( gd::String BaseEvent::GenerateEventCode(
gd::EventsCodeGenerator& codeGenerator, gd::EventsCodeGenerator& codeGenerator,
gd::EventsCodeGenerationContext& context) { gd::EventsCodeGenerationContext& context) {
@@ -142,14 +140,6 @@ void BaseEvent::Preprocess(gd::EventsCodeGenerator& codeGenerator,
} }
} }
bool BaseEvent::AcceptVisitor(gd::EventVisitor& eventVisitor) {
return eventVisitor.VisitEvent(*this);
}
void BaseEvent::AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const {
eventVisitor.VisitEvent(*this);
}
BaseEventSPtr GD_CORE_API CloneRememberingOriginalEvent(BaseEventSPtr event) { BaseEventSPtr GD_CORE_API CloneRememberingOriginalEvent(BaseEventSPtr event) {
gd::BaseEventSPtr copy(event->Clone()); gd::BaseEventSPtr copy(event->Clone());
// Original event is either the original event of the copied event, or the // Original event is either the original event of the copied event, or the

View File

@@ -3,7 +3,9 @@
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#pragma once #if defined(GD_IDE_ONLY)
#ifndef GDCORE_EVENT_H
#define GDCORE_EVENT_H
#include <iostream> #include <iostream>
#include <memory> #include <memory>
@@ -22,9 +24,6 @@ class EventsCodeGenerationContext;
class Platform; class Platform;
class SerializerElement; class SerializerElement;
class Instruction; class Instruction;
class EventVisitor;
class ReadOnlyEventVisitor;
class VariablesContainer;
} // namespace gd } // namespace gd
namespace gd { namespace gd {
@@ -91,32 +90,6 @@ class GD_CORE_API BaseEvent {
*/ */
bool HasSubEvents() const; 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. * \brief Return a list of all conditions of the event.
* \note Used to preprocess or search in the conditions. * \note Used to preprocess or search in the conditions.
@@ -175,6 +148,26 @@ class GD_CORE_API BaseEvent {
noExpr; noExpr;
return 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 /** \name Code generation
@@ -245,9 +238,6 @@ class GD_CORE_API BaseEvent {
*/ */
virtual void UnserializeFrom(gd::Project& project, virtual void UnserializeFrom(gd::Project& project,
const SerializerElement& element){}; const SerializerElement& element){};
virtual bool AcceptVisitor(gd::EventVisitor& eventVisitor);
virtual void AcceptVisitor(gd::ReadOnlyEventVisitor& eventVisitor) const;
///@} ///@}
/** \name Common properties /** \name Common properties
@@ -287,19 +277,6 @@ class GD_CORE_API BaseEvent {
*/ */
bool IsFolded() const { return folded; } bool IsFolded() const { return folded; }
/**
* \brief Set the AI generated event ID.
*/
void SetAiGeneratedEventId(const gd::String& aiGeneratedEventId_) {
aiGeneratedEventId = aiGeneratedEventId_;
}
/**
* \brief Get the AI generated event ID.
*/
const gd::String& GetAiGeneratedEventId() const {
return aiGeneratedEventId;
}
///@} ///@}
std::weak_ptr<gd::BaseEvent> std::weak_ptr<gd::BaseEvent>
@@ -318,10 +295,10 @@ class GD_CORE_API BaseEvent {
bool disabled; ///< True if the event is disabled and must not be executed bool disabled; ///< True if the event is disabled and must not be executed
gd::String type; ///< Type of the event. Must be assigned at the creation. gd::String type; ///< Type of the event. Must be assigned at the creation.
///< Used for saving the event for instance. ///< Used for saving the event for instance.
gd::String aiGeneratedEventId; ///< When generated by an AI/external tool.
static gd::EventsList badSubEvents; static gd::EventsList badSubEvents;
static gd::VariablesContainer badLocalVariables; static std::vector<gd::String> emptyDependencies;
static gd::String emptySourceFile;
}; };
/** /**
@@ -344,3 +321,6 @@ class EmptyEvent : public BaseEvent {
}; };
} // namespace gd } // namespace gd
#endif // GDCORE_EVENT_H
#endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -123,11 +123,6 @@ class GD_CORE_API Instruction {
*/ */
void SetParameter(std::size_t nb, const gd::Expression& val); void SetParameter(std::size_t nb, const gd::Expression& val);
/** Add a parameter at the end
* \param val The new value of the parameter
*/
void AddParameter(const gd::Expression& val);
/** \brief Get a reference to the std::vector containing the parameters. /** \brief Get a reference to the std::vector containing the parameters.
* \return A std::vector containing the parameters * \return A std::vector containing the parameters
*/ */

View File

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

View File

@@ -18,7 +18,6 @@
#include "GDCore/String.h" #include "GDCore/String.h"
#include "GDCore/Tools/Localization.h" #include "GDCore/Tools/Localization.h"
#include "GDCore/Tools/MakeUnique.h" #include "GDCore/Tools/MakeUnique.h"
#include "GrammarTerminals.h"
namespace gd { namespace gd {
class Expression; class Expression;
class ObjectsContainer; class ObjectsContainer;
@@ -29,8 +28,6 @@ class ExpressionMetadata;
namespace gd { namespace gd {
using namespace gd::GrammarTerminals;
/** \brief Parse an expression, returning a tree of node corresponding /** \brief Parse an expression, returning a tree of node corresponding
* to the parsed expression. * to the parsed expression.
* *
@@ -38,7 +35,7 @@ using namespace gd::GrammarTerminals;
* parser by refactoring out the dependency on gd::MetadataProvider (injecting * parser by refactoring out the dependency on gd::MetadataProvider (injecting
* instead functions to be called to query supported functions). * instead functions to be called to query supported functions).
* *
* \see gd::ExpressionParserError * \see gd::ExpressionParserDiagnostic
* \see gd::ExpressionNode * \see gd::ExpressionNode
*/ */
class GD_CORE_API ExpressionParser2 { class GD_CORE_API ExpressionParser2 {
@@ -47,9 +44,14 @@ class GD_CORE_API ExpressionParser2 {
virtual ~ExpressionParser2(){}; virtual ~ExpressionParser2(){};
/** /**
* Parse the given expression into a tree of nodes. * Parse the given expression with the specified type.
* *
* \param expression The expression to parse. * \param type Type of the expression: "string", "number",
* type supported by gd::ParameterMetadata::IsObject, types supported by
* gd::ParameterMetadata::IsExpression or "unknown".
* \param expression The expression to parse
* \param objectName Specify the object name, only for the
* case of "objectvar" type.
* *
* \return The node representing the expression as a parsed tree. * \return The node representing the expression as a parsed tree.
*/ */
@@ -209,7 +211,7 @@ class GD_CORE_API ExpressionParser2 {
} }
SkipIfChar(IsClosingParenthesis); SkipIfChar(IsClosingParenthesis);
return factor; return factor;
} else if (CheckIfChar(IsAllowedInIdentifier)) { } else if (IsIdentifierAllowedChar()) {
return Identifier(); return Identifier();
} }
@@ -262,11 +264,12 @@ class GD_CORE_API ExpressionParser2 {
} else if (CheckIfChar(IsDot)) { } else if (CheckIfChar(IsDot)) {
ExpressionParserLocation dotLocation = SkipChar(); ExpressionParserLocation dotLocation = SkipChar();
SkipAllWhitespaces(); SkipAllWhitespaces();
return ObjectFunctionOrBehaviorFunctionOrVariable( return ObjectFunctionOrBehaviorFunction(
name, nameLocation, dotLocation); name, nameLocation, dotLocation);
} else if (CheckIfChar(IsOpeningSquareBracket)) { } else if (CheckIfChar(IsOpeningSquareBracket)) {
return Variable(name, nameLocation); return Variable(name, nameLocation);
} else { }
else {
auto identifier = gd::make_unique<IdentifierNode>(name); auto identifier = gd::make_unique<IdentifierNode>(name);
identifier->location = ExpressionParserLocation( identifier->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition()); nameLocation.GetStartPosition(), GetCurrentPosition());
@@ -277,11 +280,8 @@ class GD_CORE_API ExpressionParser2 {
std::unique_ptr<VariableNode> Variable(const gd::String &name, gd::ExpressionParserLocation nameLocation) { std::unique_ptr<VariableNode> Variable(const gd::String &name, gd::ExpressionParserLocation nameLocation) {
auto variable = gd::make_unique<VariableNode>(name); auto variable = gd::make_unique<VariableNode>(name);
variable->child = VariableAccessorOrVariableBracketAccessor();
if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) { variable->child->parent = variable.get();
variable->child = VariableAccessorOrVariableBracketAccessor();
variable->child->parent = variable.get();
}
variable->location = ExpressionParserLocation( variable->location = ExpressionParserLocation(
nameLocation.GetStartPosition(), GetCurrentPosition()); nameLocation.GetStartPosition(), GetCurrentPosition());
@@ -305,12 +305,8 @@ class GD_CORE_API ExpressionParser2 {
"bracket for each opening bracket.")); "bracket for each opening bracket."));
} }
SkipIfChar(IsClosingSquareBracket); SkipIfChar(IsClosingSquareBracket);
child->child = VariableAccessorOrVariableBracketAccessor();
SkipAllWhitespaces(); child->child->parent = child.get();
if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
}
child->location = child->location =
ExpressionParserLocation(childStartPosition, GetCurrentPosition()); ExpressionParserLocation(childStartPosition, GetCurrentPosition());
@@ -319,18 +315,11 @@ class GD_CORE_API ExpressionParser2 {
auto dotLocation = SkipChar(); auto dotLocation = SkipChar();
SkipAllWhitespaces(); SkipAllWhitespaces();
auto identifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false); auto identifierAndLocation = ReadIdentifierName();
auto child = auto child =
gd::make_unique<VariableAccessorNode>(identifierAndLocation.name); gd::make_unique<VariableAccessorNode>(identifierAndLocation.name);
if (identifierAndLocation.name.empty()) { child->child = VariableAccessorOrVariableBracketAccessor();
child->diagnostic = RaiseSyntaxError(_("A name should be entered after the dot.")); child->child->parent = child.get();
}
SkipAllWhitespaces();
if (CheckIfChar(IsOpeningSquareBracket) || CheckIfChar(IsDot)) {
child->child = VariableAccessorOrVariableBracketAccessor();
child->child->parent = child.get();
}
child->nameLocation = identifierAndLocation.location; child->nameLocation = identifierAndLocation.location;
child->dotLocation = dotLocation; child->dotLocation = dotLocation;
child->location = child->location =
@@ -339,11 +328,7 @@ class GD_CORE_API ExpressionParser2 {
return std::move(child); return std::move(child);
} }
// Should never happen, unless a node called this function without checking if the current character return std::move(gd::make_unique<VariableAccessorOrVariableBracketAccessorNode>());
// 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);
} }
std::unique_ptr<FunctionCallNode> FreeFunction( std::unique_ptr<FunctionCallNode> FreeFunction(
@@ -370,33 +355,27 @@ class GD_CORE_API ExpressionParser2 {
} }
std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode> std::unique_ptr<IdentifierOrFunctionCallOrObjectFunctionNameOrEmptyNode>
ObjectFunctionOrBehaviorFunctionOrVariable( ObjectFunctionOrBehaviorFunction(
const gd::String &parentIdentifier, const gd::String &parentIdentifier,
const ExpressionParserLocation &parentIdentifierLocation, const ExpressionParserLocation &parentIdentifierLocation,
const ExpressionParserLocation &parentIdentifierDotLocation) { const ExpressionParserLocation &parentIdentifierDotLocation) {
auto childIdentifierAndLocation = ReadIdentifierName(/*allowDeprecatedSpacesInName=*/ false); auto childIdentifierAndLocation = ReadIdentifierName();
const gd::String &childIdentifierName = childIdentifierAndLocation.name; const gd::String &childIdentifierName = childIdentifierAndLocation.name;
const auto &childIdentifierNameLocation = const auto &childIdentifierNameLocation =
childIdentifierAndLocation.location; childIdentifierAndLocation.location;
std::unique_ptr<gd::ExpressionParserError> emptyNameError = childIdentifierName.empty() ?
RaiseSyntaxError(_("A name should be entered after the dot.")) : nullptr;
SkipAllWhitespaces(); SkipAllWhitespaces();
if (IsNamespaceSeparator()) { if (IsNamespaceSeparator()) {
ExpressionParserLocation namespaceSeparatorLocation = ExpressionParserLocation namespaceSeparatorLocation =
SkipNamespaceSeparator(); SkipNamespaceSeparator();
SkipAllWhitespaces(); SkipAllWhitespaces();
auto behaviorFunction = BehaviorFunction(parentIdentifier, return BehaviorFunction(parentIdentifier,
childIdentifierName, childIdentifierName,
parentIdentifierLocation, parentIdentifierLocation,
parentIdentifierDotLocation, parentIdentifierDotLocation,
childIdentifierNameLocation, childIdentifierNameLocation,
namespaceSeparatorLocation); namespaceSeparatorLocation);
if (emptyNameError) behaviorFunction->diagnostic = std::move(emptyNameError);
return std::move(behaviorFunction);
} else if (CheckIfChar(IsOpeningParenthesis)) { } else if (CheckIfChar(IsOpeningParenthesis)) {
ExpressionParserLocation openingParenthesisLocation = SkipChar(); ExpressionParserLocation openingParenthesisLocation = SkipChar();
@@ -405,7 +384,7 @@ class GD_CORE_API ExpressionParser2 {
childIdentifierName); childIdentifierName);
auto parametersNode = Parameters(function.get(), parentIdentifier); auto parametersNode = Parameters(function.get(), parentIdentifier);
function->parameters = std::move(parametersNode.parameters), 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( function->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition()); parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
@@ -418,8 +397,6 @@ class GD_CORE_API ExpressionParser2 {
return std::move(function); return std::move(function);
} else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) { } else if (CheckIfChar(IsDot) || CheckIfChar(IsOpeningSquareBracket)) {
auto variable = gd::make_unique<VariableNode>(parentIdentifier); auto variable = gd::make_unique<VariableNode>(parentIdentifier);
variable->diagnostic = std::move(emptyNameError);
auto child = auto child =
gd::make_unique<VariableAccessorNode>(childIdentifierName); gd::make_unique<VariableAccessorNode>(childIdentifierName);
child->child = VariableAccessorOrVariableBracketAccessor(); child->child = VariableAccessorOrVariableBracketAccessor();
@@ -440,12 +417,17 @@ class GD_CORE_API ExpressionParser2 {
auto node = gd::make_unique<IdentifierNode>( auto node = gd::make_unique<IdentifierNode>(
parentIdentifier, childIdentifierName); 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( node->location = ExpressionParserLocation(
parentIdentifierLocation.GetStartPosition(), GetCurrentPosition()); parentIdentifierLocation.GetStartPosition(), GetCurrentPosition());
node->identifierNameLocation = parentIdentifierLocation; node->identifierNameLocation = parentIdentifierLocation;
node->identifierNameDotLocation = parentIdentifierDotLocation; node->identifierNameDotLocation = parentIdentifierDotLocation;
node->childIdentifierNameLocation = childIdentifierNameLocation; node->childIdentifierNameLocation = childIdentifierNameLocation;
node->diagnostic = std::move(emptyNameError);
return std::move(node); return std::move(node);
} }
@@ -518,6 +500,11 @@ class GD_CORE_API ExpressionParser2 {
std::vector<std::unique_ptr<ExpressionNode>> parameters; std::vector<std::unique_ptr<ExpressionNode>> parameters;
gd::String lastObjectName = ""; 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; bool previousCharacterIsParameterSeparator = false;
while (!IsEndReached()) { while (!IsEndReached()) {
SkipAllWhitespaces(); SkipAllWhitespaces();
@@ -536,6 +523,7 @@ class GD_CORE_API ExpressionParser2 {
SkipAllWhitespaces(); SkipAllWhitespaces();
previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator); previousCharacterIsParameterSeparator = CheckIfChar(IsParameterSeparator);
SkipIfChar(IsParameterSeparator); SkipIfChar(IsParameterSeparator);
parameterIndex++;
} }
ExpressionParserLocation invalidClosingParenthesisLocation; 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) { gd::String::value_type operatorChar) {
if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' || if (operatorChar == '+' || operatorChar == '-' || operatorChar == '/' ||
operatorChar == '*') { operatorChar == '*') {
return std::unique_ptr<ExpressionParserError>(nullptr); return gd::make_unique<ExpressionParserDiagnostic>();
} }
return gd::make_unique<ExpressionParserError>( return gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::InvalidOperator, "invalid_operator",
_("You've used an operator that is not supported. Operator should be " _("You've used an operator that is not supported. Operator should be "
"either +, -, / or *."), "either +, -, / or *."),
GetCurrentPosition()); GetCurrentPosition());
} }
std::unique_ptr<ExpressionParserError> ValidateUnaryOperator( std::unique_ptr<ExpressionParserDiagnostic> ValidateUnaryOperator(
gd::String::value_type operatorChar, gd::String::value_type operatorChar,
size_t position) { size_t position) {
if (operatorChar == '+' || operatorChar == '-') { if (operatorChar == '+' || operatorChar == '-') {
return std::unique_ptr<ExpressionParserError>(nullptr); return gd::make_unique<ExpressionParserDiagnostic>();
} }
return gd::make_unique<ExpressionParserError>( return gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::InvalidOperator, "invalid_operator",
_("You've used an \"unary\" operator that is not supported. Operator " _("You've used an \"unary\" operator that is not supported. Operator "
"should be " "should be "
"either + or -."), "either + or -."),
@@ -618,6 +606,95 @@ class GD_CORE_API ExpressionParser2 {
return predicate(character); return predicate(character);
} }
bool IsIdentifierAllowedChar() {
if (currentPosition >= expression.size()) return false;
gd::String::value_type character = expression[currentPosition];
// Quickly compare if the character is a number or ASCII character.
if ((character >= '0' && character <= '9') ||
(character >= 'A' && character <= 'Z') ||
(character >= 'a' && character <= 'z'))
return true;
// Otherwise do the full check against separators forbidden in identifiers.
if (!IsParameterSeparator(character) && !IsDot(character) &&
!IsQuote(character) && !IsBracket(character) &&
!IsExpressionOperator(character) && !IsTermOperator(character)) {
return true;
}
return false;
}
static bool IsWhitespace(gd::String::value_type character) {
return character == ' ' || character == '\n' || character == '\r';
}
static bool IsParameterSeparator(gd::String::value_type character) {
return character == ',';
}
static bool IsDot(gd::String::value_type character) {
return character == '.';
}
static bool IsQuote(gd::String::value_type character) {
return character == '"';
}
static bool IsBracket(gd::String::value_type character) {
return character == '(' || character == ')' || character == '[' ||
character == ']' || character == '{' || character == '}';
}
static bool IsOpeningParenthesis(gd::String::value_type character) {
return character == '(';
}
static bool IsClosingParenthesis(gd::String::value_type character) {
return character == ')';
}
static bool IsOpeningSquareBracket(gd::String::value_type character) {
return character == '[';
}
static bool IsClosingSquareBracket(gd::String::value_type character) {
return character == ']';
}
static bool IsExpressionEndingChar(gd::String::value_type character) {
return character == ',' || IsClosingParenthesis(character) ||
IsClosingSquareBracket(character);
}
static bool IsExpressionOperator(gd::String::value_type character) {
return character == '+' || character == '-' || character == '<' ||
character == '>' || character == '?' || character == '^' ||
character == '=' || character == '\\' || character == ':' ||
character == '!';
}
static bool IsUnaryOperator(gd::String::value_type character) {
return character == '+' || character == '-';
}
static bool IsTermOperator(gd::String::value_type character) {
return character == '/' || character == '*';
}
static bool IsNumberFirstChar(gd::String::value_type character) {
return character == '.' || (character >= '0' && character <= '9');
}
static bool IsNonZeroDigit(gd::String::value_type character) {
return (character >= '1' && character <= '9');
}
static bool IsZeroDigit(gd::String::value_type character) {
return character == '0';
}
bool IsNamespaceSeparator() { bool IsNamespaceSeparator() {
// Namespace separator is a special kind of delimiter as it is 2 characters // Namespace separator is a special kind of delimiter as it is 2 characters
// long // long
@@ -634,13 +711,13 @@ class GD_CORE_API ExpressionParser2 {
ExpressionParserLocation location; ExpressionParserLocation location;
}; };
IdentifierAndLocation ReadIdentifierName(bool allowDeprecatedSpacesInName = true) { IdentifierAndLocation ReadIdentifierName() {
gd::String name; gd::String name;
size_t startPosition = currentPosition; size_t startPosition = currentPosition;
while (currentPosition < expression.size() && while (currentPosition < expression.size() &&
(CheckIfChar(IsAllowedInIdentifier) (IsIdentifierAllowedChar()
// Allow whitespace in identifier name for compatibility // Allow whitespace in identifier name for compatibility
|| (allowDeprecatedSpacesInName && expression[currentPosition] == ' '))) { || expression[currentPosition] == ' ')) {
name += expression[currentPosition]; name += expression[currentPosition];
currentPosition++; currentPosition++;
} }
@@ -719,15 +796,13 @@ class GD_CORE_API ExpressionParser2 {
std::unique_ptr<ExpressionParserError> RaiseSyntaxError( std::unique_ptr<ExpressionParserError> RaiseSyntaxError(
const gd::String &message) { const gd::String &message) {
return std::move(gd::make_unique<ExpressionParserError>( return std::move(gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::SyntaxError, message, "syntax_error", message, GetCurrentPosition()));
GetCurrentPosition()));
} }
std::unique_ptr<ExpressionParserError> RaiseTypeError( std::unique_ptr<ExpressionParserError> RaiseTypeError(
const gd::String &message, size_t beginningPosition) { const gd::String &message, size_t beginningPosition) {
return std::move(gd::make_unique<ExpressionParserError>( return std::move(gd::make_unique<ExpressionParserError>(
gd::ExpressionParserError::ErrorType::MismatchedType, message, "type_error", message, beginningPosition, GetCurrentPosition()));
beginningPosition, GetCurrentPosition()));
} }
///@} ///@}

View File

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

View File

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

View File

@@ -8,7 +8,6 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "GDCore/Events/Parsers/ExpressionParser2Node.h" #include "GDCore/Events/Parsers/ExpressionParser2Node.h"
#include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h" #include "GDCore/Events/Parsers/ExpressionParser2NodeWorker.h"
namespace gd { namespace gd {
@@ -44,11 +43,6 @@ class GD_CORE_API ExpressionParser2NodePrinter
*/ */
const gd::String& GetOutput() { return output; }; const gd::String& GetOutput() { return output; };
static gd::String PrintStringLiteral(const gd::String& str) {
return "\"" +
str.FindAndReplace("\\", "\\\\").FindAndReplace("\"", "\\\"") + "\"";
}
protected: protected:
void OnVisitSubExpressionNode(SubExpressionNode& node) override { void OnVisitSubExpressionNode(SubExpressionNode& node) override {
output += "("; output += "(";
@@ -75,7 +69,10 @@ class GD_CORE_API ExpressionParser2NodePrinter
} }
void OnVisitNumberNode(NumberNode& node) override { output += node.number; } void OnVisitNumberNode(NumberNode& node) override { output += node.number; }
void OnVisitTextNode(TextNode& node) override { void OnVisitTextNode(TextNode& node) override {
output += PrintStringLiteral(node.text); output +=
"\"" +
node.text.FindAndReplace("\\", "\\\\").FindAndReplace("\"", "\\\"") +
"\"";
} }
void OnVisitVariableNode(VariableNode& node) override { void OnVisitVariableNode(VariableNode& node) override {
output += node.name; output += node.name;
@@ -100,8 +97,8 @@ class GD_CORE_API ExpressionParser2NodePrinter
} }
void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override { void OnVisitObjectFunctionNameNode(ObjectFunctionNameNode& node) override {
if (!node.behaviorFunctionName.empty()) { if (!node.behaviorFunctionName.empty()) {
output += node.objectName + "." + node.objectFunctionOrBehaviorName + output +=
"::" + node.behaviorFunctionName; node.objectName + "." + node.objectFunctionOrBehaviorName + "::" + node.behaviorFunctionName;
} else { } else {
output += node.objectName + "." + node.objectFunctionOrBehaviorName; 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 // Common updates for some parameters
const std::vector<gd::Expression>& parameters = instr.GetParameters(); const std::vector<gd::Expression>& parameters = instr.GetParameters();
for (std::size_t j = 0; for (std::size_t j = 0;
j < parameters.size() && j < metadata.parameters.GetParametersCount(); j < parameters.size() && j < metadata.parameters.size();
++j) { ++j) {
if (metadata.parameters.GetParameter(j).GetType() == "relationalOperator" || if (metadata.parameters[j].GetType() == "relationalOperator" ||
metadata.parameters.GetParameter(j).GetType() == "operator") { metadata.parameters[j].GetType() == "operator") {
if (j == parameters.size() - 1) { if (j == parameters.size() - 1) {
std::cout << "ERROR: No more parameters after a [relational]operator " std::cout << "ERROR: No more parameters after a [relational]operator "
"when trying to update an instruction from GD2.x"; "when trying to update an instruction from GD2.x";
@@ -221,8 +221,6 @@ void EventsListSerialization::UnserializeEventsFrom(
event->SetDisabled(eventElem.GetBoolAttribute("disabled", false)); event->SetDisabled(eventElem.GetBoolAttribute("disabled", false));
event->SetFolded(eventElem.GetBoolAttribute("folded", false)); event->SetFolded(eventElem.GetBoolAttribute("folded", false));
event->SetAiGeneratedEventId(
eventElem.GetStringAttribute("aiGeneratedEventId", ""));
list.InsertEvent(event, list.GetEventsCount()); list.InsertEvent(event, list.GetEventsCount());
} }
@@ -238,8 +236,6 @@ void EventsListSerialization::SerializeEventsTo(const EventsList& list,
if (event.IsDisabled()) if (event.IsDisabled())
eventElem.SetAttribute("disabled", event.IsDisabled()); eventElem.SetAttribute("disabled", event.IsDisabled());
if (event.IsFolded()) eventElem.SetAttribute("folded", event.IsFolded()); if (event.IsFolded()) eventElem.SetAttribute("folded", event.IsFolded());
if (!event.GetAiGeneratedEventId().empty())
eventElem.SetAttribute("aiGeneratedEventId", event.GetAiGeneratedEventId());
eventElem.AddChild("type").SetValue(event.GetType()); eventElem.AddChild("type").SetValue(event.GetType());
event.SerializeTo(eventElem); event.SerializeTo(eventElem);

View File

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

View File

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

View File

@@ -33,8 +33,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png", "res/function32.png",
"res/function32.png") "res/function32.png")
.SetHelpPath("/events/functions/return") .SetHelpPath("/events/functions/return")
.AddParameter("expression", _("The number to be returned")) .AddParameter("expression", "The number to be returned")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -48,8 +47,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png", "res/function32.png",
"res/function32.png") "res/function32.png")
.SetHelpPath("/events/functions/return") .SetHelpPath("/events/functions/return")
.AddParameter("string", _("The text to be returned")) .AddParameter("string", "The text to be returned")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -62,70 +60,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"res/function32.png", "res/function32.png",
"res/function32.png") "res/function32.png")
.SetHelpPath("/events/functions/return") .SetHelpPath("/events/functions/return")
.AddParameter("trueorfalse", _("Should the condition be true or false?")) .AddParameter("trueorfalse", "Should the condition be true or false?")
.SetRelevantForFunctionEventsOnly()
.MarkAsAdvanced();
// Deprecated
extension
.AddAction("CopyArgumentToVariable",
_("Copy function parameter to variable"),
_("Copy a function parameter (also called \"argument\") to a variable. "
"The parameter type must be a variable."),
_("Copy the parameter _PARAM0_ into the variable _PARAM1_"),
"",
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.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"),
_("Copy a variable to function parameter (also called \"argument\"). "
"The parameter type must be a variable."),
_("Copy the variable _PARAM1_ into the parameter _PARAM0_"),
"",
"res/function32.png",
"res/function32.png")
.SetHelpPath("/events/functions/return")
.AddParameter("functionParameterName", _("Parameter name"), "variable")
.AddParameter("scenevar", _("Scene variable"))
.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(); .MarkAsAdvanced();
extension extension
@@ -139,62 +74,26 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAdvancedExtension(
"", "",
"res/function32.png", "res/function32.png",
"res/function32.png") "res/function32.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean") .AddParameter("functionParameterName", "Parameter name")
.SetRelevantForFunctionEventsOnly() .MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
extension extension
.AddExpression( .AddExpression(
"GetArgumentAsNumber", "GetArgumentAsNumber",
_("Get function parameter value"), _("Get function parameter value"),
_("Get function parameter (also called \"argument\") value. You don't need this most of the time as you can simply write the parameter name in an expression."), _("Get function parameter (also called \"argument\") value"),
"", "",
"res/function16.png") "res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean") .AddParameter("functionParameterName", "Parameter name");
.SetRelevantForFunctionEventsOnly()
.SetHidden();
extension extension
.AddStrExpression( .AddStrExpression(
"GetArgumentAsString", "GetArgumentAsString",
_("Get function parameter text"), _("Get function parameter text"),
_("Get function parameter (also called \"argument\") text. You don't need this most of the time as you can simply write the parameter name in an expression."), _("Get function parameter (also called \"argument\") text "),
"", "",
"res/function16.png") "res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean") .AddParameter("functionParameterName", "Parameter name");
.SetRelevantForFunctionEventsOnly()
.SetHidden();
extension
.AddCondition(
"CompareArgumentAsNumber",
_("Compare function parameter value"),
_("Compare function parameter (also called \"argument\") value."),
_("Parameter _PARAM0_"),
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"number", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
extension
.AddCondition(
"CompareArgumentAsString",
_("Compare function parameter text"),
_("Compare function parameter (also called \"argument\") text."),
_("Parameter _PARAM0_"),
"",
"res/function32.png",
"res/function16.png")
.AddParameter("functionParameterName", _("Parameter name"), "number,string,boolean")
.UseStandardRelationalOperatorParameters(
"string", gd::ParameterOptions::MakeNewOptions())
.SetRelevantForFunctionEventsOnly()
.SetHidden();
} }
} // namespace gd } // namespace gd

View File

@@ -43,13 +43,6 @@ class GD_CORE_API BuiltinExtensionsImplementer {
static void ImplementsVariablesExtension(gd::PlatformExtension& extension); static void ImplementsVariablesExtension(gd::PlatformExtension& extension);
static void ImplementsWindowExtension(gd::PlatformExtension& extension); static void ImplementsWindowExtension(gd::PlatformExtension& extension);
static void ImplementsAsyncExtension(gd::PlatformExtension& extension); static void ImplementsAsyncExtension(gd::PlatformExtension& extension);
static void ImplementsResizableExtension(gd::PlatformExtension& extension);
static void ImplementsScalableExtension(gd::PlatformExtension& extension);
static void ImplementsFlippableExtension(gd::PlatformExtension& extension);
static void ImplementsAnimatableExtension(gd::PlatformExtension& extension);
static void ImplementsEffectExtension(gd::PlatformExtension& extension);
static void ImplementsOpacityExtension(gd::PlatformExtension& extension);
static void ImplementsTextContainerExtension(gd::PlatformExtension& extension);
}; };
} // namespace gd } // namespace gd

View File

@@ -15,13 +15,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
extension extension
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinAsync", "BuiltinAsync",
_("Asynchronous functions"), _("Async functions"),
_("Functions that defer the execution of the events after it."), _("Functions that defer the execution of the events after it."),
"Arthur Pacaud (arthuro555)", "Arthur Pacaud (arthuro555)",
"Open source (MIT License)") "Open source (MIT License)")
.SetCategory("Advanced"); .SetCategory("Advanced");
extension.AddInstructionOrExpressionGroupMetadata(_("Asynchronous functions"))
.SetIcon("res/function32.png");
extension.AddEvent("Async", extension.AddEvent("Async",
_("Async event"), _("Async event"),
@@ -29,19 +27,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAsyncExtension(
"", "",
"res/eventaddicon.png", "res/eventaddicon.png",
std::make_shared<gd::AsyncEvent>()); std::make_shared<gd::AsyncEvent>());
extension
.AddAction(
"ResolveAsyncEventsFunction",
_("End asynchronous function"),
_("Mark an asynchronous function as finished. This will allow the "
"actions and subevents following it to be run."),
"Mark asynchronous function as ended",
"",
"res/actions/quit24.png",
"res/actions/quit.png")
.AddCodeOnlyParameter("eventsFunctionContext", "")
.SetRelevantForAsynchronousFunctionEventsOnly();
} }
} // namespace gd } // namespace gd

View File

@@ -23,8 +23,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.SetCategory("Audio"); .SetCategory("Audio");
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds and music")) extension.AddInstructionOrExpressionGroupMetadata(_("Sounds and music"))
.SetIcon("res/actions/music24.png"); .SetIcon("res/actions/music24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Sounds on channels"))
.SetIcon("res/actions/son24.png");
extension extension
.AddAction("PlaySoundCanal", .AddAction("PlaySoundCanal",
@@ -148,83 +146,69 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddAction("ModVolumeSoundCanal", .AddAction("ModVolumeSoundCanal",
_("Volume of the sound on a channel"), _("Volume of the sound on a channel"),
_("This action modifies the volume of the sound on the " _("This action modifies the volume of the sound on the "
"specified channel."), "specified channel. The volume is between 0 and 100."),
_("the volume of the sound on channel _PARAM1_"), _("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Sounds on channels"),
"res/actions/sonVolume24.png", "res/actions/sonVolume24.png",
"res/actions/sonVolume.png") "res/actions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ModVolumeMusicCanal", .AddAction("ModVolumeMusicCanal",
_("Volume of the music on a channel"), _("Volume of the music on a channel"),
_("This action modifies the volume of the music on the " _("This action modifies the volume of the music on the "
"specified channel."), "specified channel. The volume is between 0 and 100."),
_("the volume of the music on channel _PARAM1_"), _("the volume of the music on channel _PARAM1_"),
_("Music on channels"), _("Music on channels"),
"res/actions/musicVolume24.png", "res/actions/musicVolume24.png",
"res/actions/musicVolume.png") "res/actions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ModGlobalVolume", .AddAction("ModGlobalVolume",
_("Game global volume"), _("Game global volume"),
_("This action modifies the global volume of the game."), _("This action modifies the global volume of the game. The "
"volume is between 0 and 100."),
_("the global sound level"), _("the global sound level"),
"", "",
"res/actions/volume24.png", "res/actions/volume24.png",
"res/actions/volume.png") "res/actions/volume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume (0-100)")))
.MarkAsSimple(); .MarkAsSimple();
extension extension
.AddAction("ModPitchSoundChannel", .AddAction("ModPitchSoundChannel",
_("Pitch of the sound of a channel"), _("Pitch of the sound of a channel"),
_("This action modifies the pitch (speed) of the sound on a " _("This action modifies the pitch (speed) of the sound on a "
"channel."), "channel.\n1 is the default pitch."),
_("the pitch of the sound on channel _PARAM1_"), _("the pitch of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Sounds on channels"),
"res/actions/son24.png", "res/actions/son24.png",
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ModPitchMusicChannel", .AddAction("ModPitchMusicChannel",
_("Pitch of the music on a channel"), _("Pitch of the music on a channel"),
_("This action modifies the pitch of the music on the " _("This action modifies the pitch of the music on the "
"specified channel."), "specified channel. 1 is the default pitch"),
_("the pitch of the music on channel _PARAM1_"), _("the pitch of the music on channel _PARAM1_"),
_("Music on channels"), _("Music on channels"),
"res/actions/music24.png", "res/actions/music24.png",
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -238,10 +222,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/son.png") "res/actions/son.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -255,10 +236,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/actions/music.png") "res/actions/music.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -470,17 +448,15 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
.AddCondition( .AddCondition(
"SoundCanalVolume", "SoundCanalVolume",
_("Volume of the sound on a channel"), _("Volume of the sound on a channel"),
_("Test the volume of the sound on the specified channel."), _("Test the volume of the sound on the specified channel. The volume "
"is between 0 and 100."),
_("the volume of the sound on channel _PARAM1_"), _("the volume of the sound on channel _PARAM1_"),
_("Sounds on channels"), _("Sounds on channels"),
"res/conditions/sonVolume24.png", "res/conditions/sonVolume24.png",
"res/conditions/sonVolume.png") "res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -495,10 +471,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/musicVolume.png") "res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -511,10 +484,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/volume24.png", "res/conditions/volume24.png",
"res/conditions/volume.png") "res/conditions/volume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number");
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Volume to compare to (0-100)")));
extension extension
.AddCondition( .AddCondition(
@@ -528,27 +498,22 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/sonVolume.png") "res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddCondition( .AddCondition(
"MusicChannelPitch", "MusicChannelPitch",
_("Pitch of the music on a channel"), _("Pitch of the music on a channel"),
_("Test the pitch (speed) of the music on a specified channel."), _("Test the pitch (speed) of the music on a specified channel. 1 is "
"the default pitch."),
_("the pitch of the music on channel _PARAM1_"), _("the pitch of the music on channel _PARAM1_"),
_("Music on channels"), _("Music on channels"),
"res/conditions/musicVolume24.png", "res/conditions/musicVolume24.png",
"res/conditions/musicVolume.png") "res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Pitch to compare to (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -562,10 +527,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/sonVolume.png") "res/conditions/sonVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -579,10 +541,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsAudioExtension(
"res/conditions/musicVolume.png") "res/conditions/musicVolume.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Channel identifier")) .AddParameter("expression", _("Channel identifier"))
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Position to compare to (in seconds)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension

File diff suppressed because it is too large Load Diff

View File

@@ -26,8 +26,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras"); .SetExtensionHelpPath("/interface/scene-editor/layers-and-cameras");
extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras")) extension.AddInstructionOrExpressionGroupMetadata(_("Layers and cameras"))
.SetIcon("res/conditions/camera24.png"); .SetIcon("res/conditions/camera24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect_black.svg");
extension extension
.AddExpressionAndConditionAndAction( .AddExpressionAndConditionAndAction(
@@ -39,8 +37,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
@@ -71,8 +69,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
@@ -103,10 +101,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -119,10 +117,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -136,10 +134,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -153,10 +151,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -170,10 +168,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -187,10 +185,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number"), "", true) .AddParameter("expression", _("Camera number"), "", true)
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -203,8 +201,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/conditions/camera24.png") "res/conditions/camera24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
@@ -322,30 +320,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", .AddParameter("expression",
_("Value (1:Initial zoom, 2:Zoom x2, 0.5:Unzoom x2...)")) _("Value (1:Initial zoom, 2:Zoom x2, 0.5:Unzoom x2...)"))
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
extension // TODO Deprecated: hide this action in a future release.
.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();
extension extension
.AddAction( .AddAction(
"FixCamera", "FixCamera",
@@ -357,7 +337,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.SetHidden()
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("objectPtr", _("Object")) .AddParameter("objectPtr", _("Object"))
.AddParameter("expression", .AddParameter("expression",
@@ -373,41 +352,46 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
true) true)
.SetDefaultValue("yes") .SetDefaultValue("yes")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("ClampCamera", .AddAction(
_("Enforce camera boundaries"), "ClampCamera",
_("Enforce camera boundaries by moving the camera back inside " _("Enforce camera boundaries"),
"specified boundaries."), _("Enforce camera boundaries by moving the camera back inside specified boundaries."),
_("Enforce camera boundaries (left: _PARAM1_, top: _PARAM2_ " _("Enforce camera boundaries (left: _PARAM1_, top: _PARAM2_ "
"right: _PARAM3_, bottom: _PARAM4_, layer: _PARAM5_)"), "right: _PARAM3_, bottom: _PARAM4_, layer: _PARAM5_)"),
"", "",
"res/actions/camera24.png", "res/actions/camera24.png",
"res/actions/camera.png") "res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Left bound X Position")) .AddParameter("expression",
.AddParameter("expression", _("Top bound Y Position")) _("Left bound X Position"))
.AddParameter("expression", _("Right bound X Position")) .AddParameter("expression",
.AddParameter("expression", _("Bottom bound Y Position")) _("Top bound Y Position"))
.AddParameter("layer", _("Layer"), "", true) .AddParameter("expression",
_("Right bound X Position"))
.AddParameter("expression",
_("Bottom bound Y Position"))
.AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction("CentreCamera", .AddAction(
_("Center the camera on an object"), "CentreCamera",
_("Center the camera on the specified object."), _("Center the camera on an object"),
_("Center camera on _PARAM1_ (layer: _PARAM3_)"), _("Center the camera on the specified object."),
_("Layers and cameras"), _("Center camera on _PARAM1_ (layer: _PARAM3_)"),
"res/actions/camera24.png", "",
"res/actions/camera.png") "res/actions/camera24.png",
"res/actions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("objectPtr", _("Object")) .AddParameter("objectPtr", _("Object"))
.AddParameter("yesorno", .AddParameter("yesorno",
@@ -415,7 +399,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"", "",
true) true)
.SetDefaultValue("yes") .SetDefaultValue("yes")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0") .SetDefaultValue("0")
@@ -463,58 +447,58 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
extension extension
.AddAction( .AddAction(
"SetLayerEffectParameter", "SetLayerEffectParameter",
_("Effect property (number)"), _("Effect parameter (number)"),
_("Change the value of a property of an effect.") + "\n" + _("Change the value of a parameter of an effect.") + "\n" +
_("You can find the property names (and change the effect " _("You can find the parameter names (and change the effect "
"names) in the effects window."), "names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"), _("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"), _("Effects"),
"res/actions/effect_black.svg", "res/conditions/camera24.png",
"res/actions/effect_black.svg") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Property name")) .AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("expression", _("New value")) .AddParameter("expression", _("New value"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
"SetLayerEffectStringParameter", "SetLayerEffectStringParameter",
_("Effect property (string)"), _("Effect parameter (string)"),
_("Change the value (string) of a property of an effect.") + "\n" + _("Change the value (string) of a parameter of an effect.") + "\n" +
_("You can find the property names (and change the effect " _("You can find the parameter names (and change the effect "
"names) in the effects window."), "names) in the effects window."),
_("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"), _("Set _PARAM3_ to _PARAM4_ for effect _PARAM2_ of layer _PARAM1_"),
_("Effects"), _("Effects"),
"res/actions/effect_black.svg", "res/conditions/camera24.png",
"res/actions/effect_black.svg") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Property name")) .AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("string", _("New value")) .AddParameter("string", _("New value"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
"SetLayerEffectBooleanParameter", "SetLayerEffectBooleanParameter",
_("Effect property (enable or disable)"), _("Effect parameter (enable or disable)"),
_("Enable or disable a property of an effect.") + "\n" + _("Enable or disable a parameter of an effect.") + "\n" +
_("You can find the property names (and change the effect " _("You can find the parameter names (and change the effect "
"names) in the effects window."), "names) in the effects window."),
_("Enable _PARAM3_ for effect _PARAM2_ of layer _PARAM1_: _PARAM4_"), _("Enable _PARAM3_ for effect _PARAM2_ of layer _PARAM1_: _PARAM4_"),
_("Effects"), _("Effects"),
"res/actions/effect_black.svg", "res/conditions/camera24.png",
"res/actions/effect_black.svg") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("layerEffectName", _("Effect name"))
.AddParameter("layerEffectParameterName", _("Property name")) .AddParameter("layerEffectParameterName", _("Parameter name"))
.AddParameter("yesorno", _("Enable this property")) .AddParameter("yesorno", _("Enable this parameter"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -522,11 +506,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Layer effect is enabled"), _("Layer effect is enabled"),
_("The effect on a layer is enabled"), _("The effect on a layer is enabled"),
_("Effect _PARAM2_ on layer _PARAM1_ is enabled"), _("Effect _PARAM2_ on layer _PARAM1_ is enabled"),
_(""), _("Effects"),
"res/actions/effect_black.svg", "res/conditions/camera24.png",
"res/actions/effect_black.svg") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("layerEffectName", _("Effect name"))
.MarkAsAdvanced(); .MarkAsAdvanced();
@@ -537,10 +521,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
_("Enable an effect on a layer"), _("Enable an effect on a layer"),
_("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"), _("Enable effect _PARAM2_ on layer _PARAM1_: _PARAM3_"),
_("Effects"), _("Effects"),
"res/actions/effect_black.svg", "res/conditions/camera24.png",
"res/actions/effect_black.svg") "res/conditions/camera.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("layerEffectName", _("Effect name")) .AddParameter("layerEffectName", _("Effect name"))
.AddParameter("yesorno", _("Enable"), "", true) .AddParameter("yesorno", _("Enable"), "", true)
@@ -556,25 +540,22 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/time24.png", "res/conditions/time24.png",
"res/conditions/time.png") "res/conditions/time.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
gd::ParameterOptions::MakeNewOptions().SetDescription(
_("Time scale (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddAction( .AddAction(
"ChangeLayerTimeScale", "ChangeLayerTimeScale",
_("Layer time scale"), _("Change layer time scale"),
_("Change the time scale applied to the objects of the layer."), _("Change the time scale applied to the objects of the layer."),
_("Set the time scale of layer _PARAM1_ to _PARAM2_"), _("Set the time scale of layer _PARAM1_ to _PARAM2_"),
"", "",
"res/actions/time24.png", "res/actions/time24.png",
"res/actions/time.png") "res/actions/time.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", .AddParameter("expression",
_("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)")); _("Scale (1: Default, 2: 2x faster, 0.5: 2x slower...)"));
@@ -589,10 +570,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/conditions/layer24.png", "res/conditions/layer24.png",
"res/conditions/layer.png") "res/conditions/layer.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", gd::ParameterOptions::MakeNewOptions())
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
@@ -606,22 +586,22 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsCameraExtension(
"res/actions/layer24.png", "res/actions/layer24.png",
"res/actions/layer.png") "res/actions/layer.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("New default Z order")); .AddParameter("expression", _("New default Z order"));
extension extension
.AddAction( .AddAction(
"SetLayerAmbientLightColor", "SetLayerAmbientLightColor",
_("Ambient light color"), _("Set the ambient light color"),
_("Set the ambient light color of the lighting layer in format " _("Set the ambient light color of the lighting layer in format "
"\"R;G;B\" string."), "\"R;G;B\" string."),
_("Set the ambient color of the lighting layer _PARAM1_ to _PARAM2_"), _("Set the ambient color of the lighting layer _PARAM1_ to _PARAM2_"),
_(""), _("Lighting"),
"res/actions/color24.png", "res/actions/color24.png",
"res/actions/color.png") "res/actions/color.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"Lighting\"") .SetDefaultValue("\"Lighting\"")
.AddParameter("color", _("Color")) .AddParameter("color", _("Color"))
.MarkAsAdvanced(); .MarkAsAdvanced();

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",
_("Objects with animations"),
_("Actions and conditions for objects having animations (sprite, 3D models...)."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Objects with animations"))
.SetIcon("res/actions/animation24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Animations and images"))
.SetIcon("res/actions/animation24.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"AnimatableBehavior",
_("Objects with animations"),
"Animation",
_("Actions and conditions for objects having animations (sprite, 3D models...).."),
"",
"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",
_("Objects with effects"),
_("Actions/conditions to enable/disable and change parameters of visual effects applied on objects."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect_black.svg");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"EffectBehavior",
_("Objects with effects"),
"Effect",
_("Actions/conditions to enable/disable and change parameters of visual effects applied on 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 objects"),
_("Actions/conditions for objects which can be flipped horizontally or vertically."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Effects"))
.SetIcon("res/actions/effect_black.svg");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"FlippableBehavior",
_("Flippable objects"),
"Flippable",
_("Actions/conditions for objects which can be flipped horizontally or vertically."),
"",
"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,66 +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",
_("Objects with opacity"),
_("Action/condition/expression to change or "
"check the opacity of an object (0-255)."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Objects with opacity"))
.SetIcon("res/actions/opacity24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Visibility"))
.SetIcon("res/actions/opacity24.png");
gd::BehaviorMetadata& aut =
extension
.AddBehavior("OpacityBehavior",
_("Objects with opacity"),
"Opacity",
_("Action/condition/expression to change or check the "
"opacity of an object (0-255)."),
"",
"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,115 +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 objects"),
_("Change or compare the size (width/height) of an object which can "
"be resized (i.e: most objects)."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
"res/actions/scale24_black.png");
gd::BehaviorMetadata &aut =
extension
.AddBehavior("ResizableBehavior",
_("Resizable objects"),
"Resizable",
_("Change or compare the size (width/height) of an "
"object which can be resized (i.e: most objects)."),
"",
"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,98 +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 objects"),
_("Actions/conditions/expression to change or "
"check the scale of an object (default: 1)."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Scalable objects"))
.SetIcon("res/actions/scale24_black.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Size")).SetIcon(
"res/actions/scale24_black.png");
gd::BehaviorMetadata& aut =
extension
.AddBehavior("ScalableBehavior",
_("Scalable objects"),
"Scale",
_("Actions/conditions/expression to change or check the "
"scale of an object (default: 1)."),
"",
"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",
_("Objects containing a text"),
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
"Florian Rival",
"Open source (MIT License)")
.SetExtensionHelpPath("/objects");
extension.AddInstructionOrExpressionGroupMetadata(_("Objects containing a text"))
.SetIcon("res/conditions/text24_black.png");
gd::BehaviorMetadata& aut = extension.AddBehavior(
"TextContainerBehavior",
_("Objects containing a text"),
"Text",
_("Allows an object to contain a text, usually shown on screen, that can be modified."),
"",
"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

@@ -16,9 +16,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinCommonConversions", "BuiltinCommonConversions",
_("Conversion"), _("Conversion"),
"Expressions to convert numbers to string, strings to numbers, " "Expressions to convert number, texts and quantities.",
"angles (degrees from/to radians) and a GDevelop variable to/from a "
"JSON string.",
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/common-conversions"); .SetExtensionHelpPath("/all-features/common-conversions");
@@ -43,7 +41,7 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
extension extension
.AddStrExpression("LargeNumberToString", .AddStrExpression("LargeNumberToString",
_("Number > Text (without scientific notation)"), _("Number > Text ( without scientific notation )"),
_("Convert the result of the expression to text, " _("Convert the result of the expression to text, "
"without using the scientific notation"), "without using the scientific notation"),
"", "",
@@ -70,23 +68,19 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
extension extension
.AddStrExpression("ToJSON", .AddStrExpression("ToJSON",
_("Convert variable to JSON"), _("Convert scene variable to JSON"),
_("Convert a variable to JSON"), _("Convert a scene variable to JSON"),
_("JSON"), _("JSON"),
"res/conditions/toujours24_black.png") "res/conditions/toujours24_black.png")
.AddParameter("variable", .AddParameter("scenevar", _("Scene variable to be stringified"));
_("The variable to be stringified"),
"AllowUndeclaredVariable");
// Deprecated
extension extension
.AddStrExpression("GlobalVarToJSON", .AddStrExpression("GlobalVarToJSON",
_("Convert global variable to JSON"), _("Convert global variable to JSON"),
_("Convert a global variable to JSON"), _("Convert a global variable to JSON"),
_("JSON"), _("JSON"),
"res/conditions/toujours24_black.png") "res/conditions/toujours24_black.png")
.AddParameter("globalvar", _("The global variable to be stringified")) .AddParameter("globalvar", _("The global variable to be stringified"));
.SetHidden();
extension extension
.AddStrExpression("ObjectVarToJSON", .AddStrExpression("ObjectVarToJSON",
@@ -97,27 +91,24 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
.AddParameter("objectPtr", _("The object with the variable")) .AddParameter("objectPtr", _("The object with the variable"))
.AddParameter("objectvar", _("The object variable to be stringified")); .AddParameter("objectvar", _("The object variable to be stringified"));
// Deprecated
extension extension
.AddAction( .AddAction(
"JSONToVariableStructure", "JSONToVariableStructure",
_("Convert JSON to a scene variable"), _("Convert JSON to a scene variable"),
_("Parse a JSON object and store it into a scene variable"), _("Parse a JSON object and store it into a scene variable"),
_("Convert JSON string _PARAM0_ and store it into variable _PARAM1_"), _("Parse JSON string _PARAM0_ and store it into variable _PARAM1_"),
"", "",
"res/actions/net24.png", "res/actions/net24.png",
"res/actions/net.png") "res/actions/net.png")
.AddParameter("string", _("JSON string")) .AddParameter("string", _("JSON string"))
.AddParameter("scenevar", _("Variable where store the JSON object")) .AddParameter("scenevar", _("Variable where store the JSON object"))
.MarkAsAdvanced() .MarkAsAdvanced();
.SetHidden();
// Deprecated
extension extension
.AddAction("JSONToGlobalVariableStructure", .AddAction("JSONToGlobalVariableStructure",
_("Convert JSON to global variable"), _("Convert JSON to global variable"),
_("Parse a JSON object and store it into a global variable"), _("Parse a JSON object and store it into a global variable"),
_("Convert JSON string _PARAM0_ and store it into global " _("Parse JSON string _PARAM0_ and store it into global "
"variable _PARAM1_"), "variable _PARAM1_"),
"", "",
"res/actions/net24.png", "res/actions/net24.png",
@@ -125,20 +116,6 @@ BuiltinExtensionsImplementer::ImplementsCommonConversionsExtension(
.AddParameter("string", _("JSON string")) .AddParameter("string", _("JSON string"))
.AddParameter("globalvar", .AddParameter("globalvar",
_("Global variable where store the JSON object")) _("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(); .MarkAsAdvanced();
extension extension

View File

@@ -35,8 +35,6 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
.AddInstructionOrExpressionGroupMetadata(_("Events and control flow")) .AddInstructionOrExpressionGroupMetadata(_("Events and control flow"))
.SetIcon("res/conditions/toujours24_black.png"); .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 extension
.AddCondition("Always", .AddCondition("Always",
_("Always"), _("Always"),
@@ -48,8 +46,7 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
"res/conditions/toujours_black.png") "res/conditions/toujours_black.png")
.SetHelpPath("/all-features/advanced-conditions") .SetHelpPath("/all-features/advanced-conditions")
.AddCodeOnlyParameter("conditionInverted", "") .AddCodeOnlyParameter("conditionInverted", "")
.MarkAsAdvanced() .MarkAsAdvanced();
.SetHidden();
// Compatibility with GD <= 5.0.127 // Compatibility with GD <= 5.0.127
extension extension
@@ -59,57 +56,47 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
// end of compatibility code // end of compatibility code
extension extension
.AddCondition( .AddCondition("Or",
"Or", _("Or"),
_("Or"), _("Check if one of the sub conditions is true"),
_("Checks if at least one sub-condition is true. If no " _("If one of these conditions is true:"),
"sub-condition is specified, it will always be false. " "",
"This is rarely used — multiple events and sub-events are " "res/conditions/or24_black.png",
"usually a better approach."), "res/conditions/or_black.png")
_("If one of these conditions is true:"), .SetCanHaveSubInstructions()
"", .MarkAsAdvanced();
"res/conditions/or24_black.png",
"res/conditions/or_black.png") extension
.AddCondition("And",
_("And"),
_("Check if all sub conditions are true"),
_("If all of these conditions are true:"),
"",
"res/conditions/and24_black.png",
"res/conditions/and_black.png")
.SetCanHaveSubInstructions() .SetCanHaveSubInstructions()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension
.AddCondition( .AddCondition(
"And", "Not",
_("And"), _("Not"),
_("Checks if all sub-conditions are true. If no sub-condition is " _("Return the contrary of the result of the sub conditions"),
"specified, it will always be false. This is rarely needed, as " _("Invert the logical result of these conditions:"),
"events already check all conditions before running actions."),
_("If all of these conditions are true:"),
"", "",
"res/conditions/and24_black.png", "res/conditions/not24_black.png",
"res/conditions/and_black.png") "res/conditions/not_black.png")
.SetCanHaveSubInstructions() .SetCanHaveSubInstructions()
.MarkAsAdvanced(); .MarkAsAdvanced();
extension extension.AddCondition(
.AddCondition("Not", "Once",
_("Not"), _("Trigger once while true"),
_("Returns the opposite of the sub-condition(s) result. " _("Run actions only once, for each time the conditions have been met."),
"This is rarely needed, as most conditions can be " _("Trigger once"),
"inverted or expressed more simply."), "",
_("Invert the logical result of these conditions:"), "res/conditions/once24.png",
"", "res/conditions/once.png");
"res/conditions/not24_black.png",
"res/conditions/not_black.png")
.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 extension
.AddCondition("CompareNumbers", .AddCondition("CompareNumbers",
@@ -127,9 +114,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
// Compatibility with GD <= 5.0.127 // Compatibility with GD <= 5.0.127
extension extension
.AddDuplicatedCondition("Egal", .AddDuplicatedCondition(
"BuiltinCommonInstructions::CompareNumbers", "Egal", "BuiltinCommonInstructions::CompareNumbers", {.unscoped = true})
{.unscoped = true})
.SetHidden(); .SetHidden();
// end of compatibility code // end of compatibility code
@@ -149,9 +135,8 @@ BuiltinExtensionsImplementer::ImplementsCommonInstructionsExtension(
// Compatibility with GD <= 5.0.127 // Compatibility with GD <= 5.0.127
extension extension
.AddDuplicatedCondition("StrEqual", .AddDuplicatedCondition(
"BuiltinCommonInstructions::CompareStrings", "StrEqual", "BuiltinCommonInstructions::CompareStrings", {.unscoped = true})
{.unscoped = true})
.SetHidden(); .SetHidden();
// end of compatibility code // end of compatibility code

View File

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

View File

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

View File

@@ -15,11 +15,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinKeyboard", "BuiltinKeyboard",
_("Keyboard"), _("Keyboard"),
_("Conditions to check keys pressed on a keyboard. Note that this " _("Allows your game to respond to keyboard input. Note that this "
"does not work with on-screen keyboard on touch devices: use " "does not work with on-screen keyboard on touch devices: use "
"instead mouse/touch conditions when making a game for " "instead conditions related to touch when making a game for "
"mobile/touchscreen devices or when making a new game from " "mobile/touchscreen devices."),
"scratch."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/keyboard") .SetExtensionHelpPath("/all-features/keyboard")
@@ -36,8 +35,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("key", _("Key to check")) .AddParameter("key", _("Key"));
.SetHidden();
extension extension
.AddCondition("KeyReleased", .AddCondition("KeyReleased",
@@ -48,32 +46,33 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("key", _("Key to check")) .AddParameter("key", _("Key"));
.SetHidden();
extension extension
.AddCondition("KeyFromTextPressed", .AddCondition("KeyFromTextPressed",
_("Key pressed"), _("Key pressed (text expression)"),
_("Check if a key is pressed"), _("Check if a key, retrieved from the result of the "
"expression, is pressed"),
_("_PARAM1_ key is pressed"), _("_PARAM1_ key is pressed"),
"", "",
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("keyboardKey", _("Key to check")) .AddParameter("string", _("Expression generating the key to check"))
.MarkAsSimple(); .MarkAsAdvanced();
extension extension
.AddCondition("KeyFromTextReleased", .AddCondition("KeyFromTextReleased",
_("Key released"), _("Key released (text expression)"),
_("Check if a key was just released"), _("Check if a key, retrieved from the result of the "
"expression, was just released"),
_("_PARAM1_ key is released"), _("_PARAM1_ key is released"),
"", "",
"res/conditions/keyboard24.png", "res/conditions/keyboard24.png",
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("keyboardKey", _("Key to check")) .AddParameter("string", _("Expression generating the key to check"))
.MarkAsSimple(); .MarkAsAdvanced();
extension extension
.AddCondition("AnyKeyPressed", .AddCondition("AnyKeyPressed",
@@ -85,7 +84,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsKeyboardExtension(
"res/conditions/keyboard.png") "res/conditions/keyboard.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
extension extension
.AddCondition("AnyKeyReleased", .AddCondition("AnyKeyReleased",
_("Any key released"), _("Any key released"),
_("Check if any key is released"), _("Check if any key is released"),

View File

@@ -72,8 +72,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension extension
.AddExpression("normalize", .AddExpression("normalize",
_("Normalize a value between `min` and `max` to a value " _("Normalize a value between `min` and `max` to a value between 0 and 1."),
"between 0 and 1."),
_("Remap a value between 0 and 1."), _("Remap a value between 0 and 1."),
"", "",
"res/mathfunction.png") "res/mathfunction.png")
@@ -125,8 +124,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension extension
.AddExpression("mod", .AddExpression("mod",
_("Modulo"), _("Modulo"),
_("Compute \"x mod y\". GDevelop does NOT support the \% " _("x mod y"),
"operator. Use this mod(x, y) function instead."),
"", "",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("x (as in x mod y)")) .AddParameter("expression", _("x (as in x mod y)"))
@@ -153,8 +151,7 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
extension extension
.AddExpression("abs", .AddExpression("abs",
_("Absolute value"), _("Absolute value"),
_("Return the non-negative value by removing the sign. " _("Absolute value"),
"The absolute value of -8 is 8."),
"", "",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -186,8 +183,11 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("asinh",
"asinh", _("Arcsine"), _("Arcsine"), "", "res/mathfunction.png") _("Arcsine"),
_("Arcsine"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
@@ -217,8 +217,11 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("cbrt",
"cbrt", _("Cube root"), _("Cube root"), "", "res/mathfunction.png") _("Cube root"),
_("Cube root"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
@@ -256,13 +259,12 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Expression"), "", true); .AddParameter("expression", _("Expression"), "", true);
extension extension
.AddExpression( .AddExpression("cos",
"cos", _("Cosine"),
_("Cosine"), _("Cosine of an angle (in radian). "
_("Cosine of an angle (in radian). " "If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."),
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."), "",
"", "res/mathfunction.png")
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
@@ -290,20 +292,29 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("int",
"int", _("Round"), _("Round a number"), "", "res/mathfunction.png") _("Round"),
_("Round a number"),
"",
"res/mathfunction.png")
.SetHidden() .SetHidden()
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("rint",
"rint", _("Round"), _("Round a number"), "", "res/mathfunction.png") _("Round"),
_("Round a number"),
"",
"res/mathfunction.png")
.SetHidden() .SetHidden()
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("round",
"round", _("Round"), _("Round a number"), "", "res/mathfunction.png") _("Round"),
_("Round a number"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
@@ -312,8 +323,8 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
_("Round a number to the Nth decimal place"), _("Round a number to the Nth decimal place"),
"", "",
"res/mathfunction.png") "res/mathfunction.png")
.AddParameter("expression", _("Number to Round")) .AddParameter("expression", _("Expression"))
.AddParameter("expression", _("Decimal Places"), "", true); .AddParameter("expression", _("Expression"), "", true);
extension extension
.AddExpression("exp", .AddExpression("exp",
@@ -324,13 +335,19 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("log",
"log", _("Logarithm"), _("Logarithm"), "", "res/mathfunction.png") _("Logarithm"),
_("Logarithm"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("ln",
"ln", _("Logarithm"), _("Logarithm"), "", "res/mathfunction.png") _("Logarithm"),
_("Logarithm"),
"",
"res/mathfunction.png")
.SetHidden() .SetHidden()
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
@@ -369,8 +386,11 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("The exponent (n in x^n)")); .AddParameter("expression", _("The exponent (n in x^n)"));
extension extension
.AddExpression( .AddExpression("sec",
"sec", _("Secant"), _("Secant"), "", "res/mathfunction.png") _("Secant"),
_("Secant"),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
@@ -382,13 +402,12 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("sin",
"sin", _("Sine"),
_("Sine"), _("Sine of an angle (in radian). "
_("Sine of an angle (in radian). " "If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."),
"If you want to use degrees, use`ToRad`: `sin(ToRad(45))`."), "",
"", "res/mathfunction.png")
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
@@ -408,13 +427,12 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
.AddExpression( .AddExpression("tan",
"tan", _("Tangent"),
_("Tangent"), _("Tangent of an angle (in radian). "
_("Tangent of an angle (in radian). " "If you want to use degrees, use`ToRad`: `tan(ToRad(45))`."),
"If you want to use degrees, use`ToRad`: `tan(ToRad(45))`."), "",
"", "res/mathfunction.png")
"res/mathfunction.png")
.AddParameter("expression", _("Expression")); .AddParameter("expression", _("Expression"));
extension extension
@@ -444,28 +462,26 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
.AddParameter("expression", _("x (in a+(b-a)*x)")); .AddParameter("expression", _("x (in a+(b-a)*x)"));
extension extension
.AddExpression( .AddExpression("XFromAngleAndDistance",
"XFromAngleAndDistance", _("X position from angle and distance"),
_("X position from angle and distance"), _("Compute the X position when given an angle and distance "
_("Compute the X position when given an angle and distance " "relative to the origin (0;0). This is also known as "
"relative to the origin (0;0). This is also known as " "getting the cartesian coordinates of a 2D vector, using "
"getting the cartesian coordinates of a 2D vector, using " "its polar coordinates."),
"its polar coordinates."), "",
"", "res/mathfunction.png")
"res/mathfunction.png")
.AddParameter("expression", _("Angle, in degrees")) .AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance")); .AddParameter("expression", _("Distance"));
extension extension
.AddExpression( .AddExpression("YFromAngleAndDistance",
"YFromAngleAndDistance", _("Y position from angle and distance"),
_("Y position from angle and distance"), _("Compute the Y position when given an angle and distance "
_("Compute the Y position when given an angle and distance " "relative to the origin (0;0). This is also known as "
"relative to the origin (0;0). This is also known as " "getting the cartesian coordinates of a 2D vector, using "
"getting the cartesian coordinates of a 2D vector, using " "its polar coordinates."),
"its polar coordinates."), "",
"", "res/mathfunction.png")
"res/mathfunction.png")
.AddParameter("expression", _("Angle, in degrees")) .AddParameter("expression", _("Angle, in degrees"))
.AddParameter("expression", _("Distance")); .AddParameter("expression", _("Distance"));
@@ -476,17 +492,6 @@ BuiltinExtensionsImplementer::ImplementsMathematicalToolsExtension(
"", "",
"res/mathfunction.png") "res/mathfunction.png")
.SetHelpPath("/all-features/expressions"); .SetHelpPath("/all-features/expressions");
extension
.AddExpression("lerpAngle",
_("Lerp (Linear interpolation) between two angles"),
_("Linearly interpolates between two angles (in degrees) "
"by taking the shortest direction around the circle."),
"",
"res/mathfunction.png")
.AddParameter("expression", _("Starting angle, in degrees"))
.AddParameter("expression", _("Destination angle, in degrees"))
.AddParameter("expression", _("Interpolation value between 0 and 1."));
} }
} // namespace gd } // namespace gd

View File

@@ -16,11 +16,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinMouse", "BuiltinMouse",
_("Mouse and touch"), _("Mouse and touch"),
"Conditions, actions and expressions to handle either the mouse or " "Conditions and actions to handle either the mouse or touches on "
"touches on a touchscreen. Notably: cursor position, mouse wheel, " "touchscreen. By default, conditions related to the mouse will also "
"mouse buttons, touch positions, started/end touches, etc...\n"
"\n"
"By default, conditions related to the mouse will also "
"handle the touches - so that it's easier to handle both in your " "handle the touches - so that it's easier to handle both in your "
"game. You can disable this behavior if you want to handle them " "game. You can disable this behavior if you want to handle them "
"separately in different events.", "separately in different events.",
@@ -30,8 +27,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.SetCategory("Input"); .SetCategory("Input");
extension.AddInstructionOrExpressionGroupMetadata(_("Mouse and touch")) extension.AddInstructionOrExpressionGroupMetadata(_("Mouse and touch"))
.SetIcon("res/actions/mouse24.png"); .SetIcon("res/actions/mouse24.png");
extension.AddInstructionOrExpressionGroupMetadata(_("Multitouch"))
.SetIcon("res/conditions/touch24.png");
extension extension
.AddCondition( .AddCondition(
@@ -158,80 +153,42 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
extension extension
.AddExpressionAndCondition( .AddExpressionAndCondition(
"number", "number",
"CursorX", "MouseX",
_("Cursor X position"), _("Cursor X position"),
_("the X position of the cursor or of a touch"), _("the X position of the cursor or of a touch"),
_("the cursor (or touch) X position"), _("the cursor (or touch) X position"),
"", "",
"res/conditions/mouse24.png") "res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
// Support for deprecated names: // Support for deprecated names:
extension.AddDuplicatedCondition("MouseX", "CursorX").SetHidden(); extension.AddDuplicatedCondition("SourisX", "MouseX").SetHidden();
extension.AddDuplicatedExpression("MouseX", "CursorX").SetHidden(); extension.AddDuplicatedExpression("SourisX", "MouseX").SetHidden();
extension.AddDuplicatedCondition("SourisX", "CursorX").SetHidden();
extension.AddDuplicatedExpression("SourisX", "CursorX").SetHidden();
extension extension
.AddExpressionAndCondition( .AddExpressionAndCondition(
"number", "number",
"CursorY", "MouseY",
_("Cursor Y position"), _("Cursor Y position"),
_("the Y position of the cursor or of a touch"), _("the Y position of the cursor or of a touch"),
_("the cursor (or touch) Y position"), _("the cursor (or touch) Y position"),
"", "",
"res/conditions/mouse24.png") "res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
// Support for deprecated names: // Support for deprecated names:
extension.AddDuplicatedCondition("MouseY", "CursorY").SetHidden(); extension.AddDuplicatedCondition("SourisY", "MouseY").SetHidden();
extension.AddDuplicatedExpression("MouseY", "CursorY").SetHidden(); extension.AddDuplicatedExpression("SourisY", "MouseY").SetHidden();
extension.AddDuplicatedCondition("SourisY", "CursorY").SetHidden();
extension.AddDuplicatedExpression("SourisY", "CursorY").SetHidden();
extension
.AddExpressionAndCondition("number",
"MouseOnlyCursorX",
_("Mouse cursor X position"),
_("the X position of the mouse cursor"),
_("the mouse cursor X position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
// It's only useful for extensions as they can't use TouchSimulateMouse.
.SetHidden();
extension
.AddExpressionAndCondition("number",
"MouseOnlyCursorY",
_("Mouse cursor Y position"),
_("the Y position of the mouse cursor"),
_("the mouse cursor Y position"),
"",
"res/conditions/mouse24.png")
.AddCodeOnlyParameter("currentScene", "")
.UseStandardParameters("number", ParameterOptions::MakeNewOptions())
.AddParameter("layer", _("Layer"), "", true)
.SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0")
// It's only useful for extensions as they can't use TouchSimulateMouse.
.SetHidden();
extension extension
.AddCondition("IsMouseInsideCanvas", .AddCondition("IsMouseInsideCanvas",
@@ -255,8 +212,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/mouse.png") "res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("mouse", _("Button to check")) .AddParameter("mouse", _("Button to check"))
.MarkAsSimple() .MarkAsSimple();
.SetHidden();
// Support for deprecated names: // Support for deprecated names:
extension.AddDuplicatedCondition("SourisBouton", "MouseButtonPressed") extension.AddDuplicatedCondition("SourisBouton", "MouseButtonPressed")
@@ -266,39 +222,49 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCondition("MouseButtonReleased", .AddCondition("MouseButtonReleased",
_("Mouse button released"), _("Mouse button released"),
_("Check if the specified mouse button was 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/mouse24.png",
"res/conditions/mouse.png") "res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("mouse", _("Button to check")) .AddParameter("mouse", _("Button to check"))
.MarkAsSimple()
.SetHidden();
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"),
"",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("mouseButton", _("Button to check"))
.MarkAsSimple(); .MarkAsSimple();
extension extension
.AddCondition("MouseButtonFromTextReleased", .AddCondition(
_("Mouse button released"), "MouseButtonFromTextPressed",
_("Check if the specified mouse button was released."), _("Mouse button pressed or touch held (text expression)"),
_("Touch or _PARAM1_ mouse button is released"), _("Check if a mouse button, retrieved from the result of the "
"", "expression, is pressed."),
"res/conditions/mouse24.png", _("_PARAM1_ mouse button is pressed"),
"res/conditions/mouse.png") "",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("mouseButton", _("Button to check")) .AddParameter("stringWithSelector",
.MarkAsSimple(); _("Expression generating the mouse button to check"),
"[\"Left\", \"Right\", \"Middle\"]")
.SetParameterLongDescription(
_("Possible values are Left, Right and Middle."))
.MarkAsAdvanced();
extension
.AddCondition(
"MouseButtonFromTextReleased",
_("Mouse button released (text expression)"),
_("Check if a mouse button, retrieved from the result of the "
"expression, was just released."),
_("_PARAM1_ mouse button is released"),
"",
"res/conditions/mouse24.png",
"res/conditions/mouse.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("stringWithSelector",
_("Expression generating the mouse button to check"),
"[\"Left\", \"Right\", \"Middle\"]")
.SetParameterLongDescription(
_("Possible values are Left, Right and Middle."))
.MarkAsAdvanced();
extension extension
.AddExpressionAndCondition("number", .AddExpressionAndCondition("number",
@@ -310,8 +276,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/touch24.png") "res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier")) .AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
@@ -326,13 +292,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
"res/conditions/touch24.png") "res/conditions/touch24.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier")) .AddParameter("expression", _("Touch identifier"))
.UseStandardParameters("number", ParameterOptions::MakeNewOptions()) .UseStandardParameters("number")
.AddParameter("layer", _("Layer"), "", true) .AddParameter("layer", _("Layer (base layer if empty)"), "", true)
.SetDefaultValue("\"\"") .SetDefaultValue("\"\"")
.AddParameter("expression", _("Camera number (default : 0)"), "", true) .AddParameter("expression", _("Camera number (default : 0)"), "", true)
.SetDefaultValue("0"); .SetDefaultValue("0");
// Deprecated
extension extension
.AddCondition( .AddCondition(
"PopStartedTouch", "PopStartedTouch",
@@ -349,7 +314,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.SetHidden(); .SetHidden();
// Deprecated
extension extension
.AddCondition( .AddCondition(
"PopEndedTouch", "PopEndedTouch",
@@ -366,90 +330,48 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsMouseExtension(
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.SetHidden(); .SetHidden();
// Deprecated
extension extension
.AddCondition( .AddCondition(
"HasAnyTouchStarted", "HasAnyTouchStarted",
_("A new touch has started"), _("A new touch has started"),
_("Check if a touch has just started on this frame. The touch " _("Check if a touch has just started on this frame. The touch identifiers can be "
"identifiers can be "
"accessed using StartedTouchId() and StartedTouchCount()."), "accessed using StartedTouchId() and StartedTouchCount()."),
_("A new touch has started"), _("A new touch has started"),
_("Multitouch"), _("Multitouch"),
"res/conditions/touch24.png", "res/conditions/touch24.png",
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression("StartedTouchCount",
_("Started touch count"),
_("The number of touches that have just started on this "
"frame. The touch identifiers can be "
"accessed using StartedTouchId()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.SetHidden();
extension
.AddExpression("StartedTouchId",
_("Started touch identifier"),
_("The identifier of the touch that has just started on "
"this frame. The number of touches can be "
"accessed using StartedTouchCount()."),
_("Multitouch"),
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index"))
.SetHidden();
extension
.AddCondition(
"HasAnyTouchOrMouseStarted",
_("A new touch has started"),
_("Check if a touch has just started or the mouse left button has "
"been pressed on this frame. The touch identifiers can be "
"accessed using StartedTouchOrMouseId() and "
"StartedTouchOrMouseCount()."),
_("A new touch has started"),
_("Multitouch"),
"res/conditions/touch24.png",
"res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
extension extension
.AddExpression( .AddExpression(
"StartedTouchOrMouseCount", "StartedTouchCount",
_("Started touch count"), _("Started touch count"),
_("The number of touches (including the mouse) that have just " _("The number of touches that have just started on this frame. The touch identifiers can be "
"started on this frame. The touch identifiers can be " "accessed using StartedTouchId()."),
"accessed using StartedTouchOrMouseId()."),
_("Multitouch"), _("Multitouch"),
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", ""); .AddCodeOnlyParameter("currentScene", "");
extension extension
.AddExpression( .AddExpression(
"StartedTouchOrMouseId", "StartedTouchId",
_("Started touch identifier"), _("Started touch identifier"),
_("The identifier of the touch or mouse that has just started on " _("The identifier of the touch that has just started on this frame. The touch number of touches can be "
"this frame. The number of touches can be " "accessed using StartedTouchCount()."),
"accessed using StartedTouchOrMouseCount()."),
_("Multitouch"), _("Multitouch"),
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch index")); .AddParameter("expression", _("Touch index"));
extension extension
.AddCondition("HasTouchEnded", .AddCondition(
_("A touch has ended"), "HasTouchEnded",
_("Check if a touch has ended or a mouse left button has " _("A touch has ended"),
"been released."), _("Check if a touch has ended."),
_("The touch with identifier _PARAM1_ has ended"), _("The touch with identifier _PARAM1_ has ended"),
_("Multitouch"), _("Multitouch"),
"res/conditions/touch24.png", "res/conditions/touch24.png",
"res/conditions/touch.png") "res/conditions/touch.png")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("expression", _("Touch identifier")); .AddParameter("expression", _("Touch identifier"));

View File

@@ -15,9 +15,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinNetwork", "BuiltinNetwork",
_("Network"), _("Network"),
_("Actions to send web requests, communicate with external \"APIs\" " _("Features to send web requests, communicate with external \"APIs\" "
"and other network related tasks. Also contains an action to open " "and other network related tasks."),
"a URL on the device browser."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("/all-features/network") .SetExtensionHelpPath("/all-features/network")
@@ -49,7 +48,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsNetworkExtension(
.AddParameter("string", "Content type", "", true) .AddParameter("string", "Content type", "", true)
.SetParameterLongDescription( .SetParameterLongDescription(
"If empty, \"application/x-www-form-urlencoded\" will be used.") "If empty, \"application/x-www-form-urlencoded\" will be used.")
.AddParameter("scenevar", "Response scene variable", "", true) .AddParameter("scenevar", "Reponse scene variable", "", true)
.SetParameterLongDescription( .SetParameterLongDescription(
"The response of the server will be stored, as a string, in this " "The response of the server will be stored, as a string, in this "
"variable. If the server returns *JSON*, you may want to use the " "variable. If the server returns *JSON*, you may want to use the "

View File

@@ -4,7 +4,6 @@
* reserved. This project is released under the MIT License. * reserved. This project is released under the MIT License.
*/ */
#include "AllBuiltinExtensions.h" #include "AllBuiltinExtensions.h"
#include "GDCore/Extensions/Metadata/MultipleInstructionMetadata.h"
#include "GDCore/Tools/Localization.h" #include "GDCore/Tools/Localization.h"
using namespace std; using namespace std;
@@ -16,11 +15,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.SetExtensionInformation( .SetExtensionInformation(
"BuiltinScene", "BuiltinScene",
_("Scene"), _("Scene"),
_("Actions/conditions to change the current scene (or pause it and " _("Actions and conditions to manipulate the scenes during the game."),
"launch another one, or go back to the previous one), check if a "
"scene or the game has just started/resumed, preload assets of a "
"scene, get the current scene name or loading progress, quit the "
"game, set background color, or disable input when focus is lost."),
"Florian Rival", "Florian Rival",
"Open source (MIT License)") "Open source (MIT License)")
.SetExtensionHelpPath("" /*TODO: Add a documentation page for this */); .SetExtensionHelpPath("" /*TODO: Add a documentation page for this */);
@@ -59,19 +54,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.MarkAsSimple(); .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 extension
.AddAction("Scene", .AddAction("Scene",
_("Change the scene"), _("Change the scene"),
@@ -154,63 +136,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSceneExtension(
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.AddParameter("yesorno", _("Deactivate input when focus is lost")) .AddParameter("yesorno", _("Deactivate input when focus is lost"))
.MarkAsAdvanced(); .MarkAsAdvanced();
extension
.AddCondition(
"HasGameJustResumed",
_("Game has just resumed"),
_("Check if the game has just resumed from being hidden. It "
"happens when the game tab is selected, a minimized window is "
"restored or the application is put back on front."),
_("Game has just resumed"),
"",
"res/actions/window24.png",
"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)."),
_("_PARAM1_ 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 } // namespace gd

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,9 +5,8 @@
*/ */
#ifndef GDCORE_POLYGON_H #ifndef GDCORE_POLYGON_H
#define GDCORE_POLYGON_H #define GDCORE_POLYGON_H
#include <vector>
#include "GDCore/Vector2.h" #include "GDCore/Vector2.h"
#include <vector>
/** /**
* \brief Represents a polygon. Usually used for collisions masks. * \brief Represents a polygon. Usually used for collisions masks.
@@ -43,7 +42,7 @@ class GD_CORE_API Polygon2d {
* \note Edges are updated, there is no need to call ComputeEdges after * \note Edges are updated, there is no need to call ComputeEdges after
* calling Move. * calling Move.
*/ */
void Move(double x, double y); void Move(float x, float y);
/** /**
* \brief Rotate the polygon. * \brief Rotate the polygon.
@@ -53,7 +52,7 @@ class GD_CORE_API Polygon2d {
* \warning edges vector is not updated, you have to call ComputeEdges if * \warning edges vector is not updated, you have to call ComputeEdges if
* needed. * needed.
*/ */
void Rotate(double angle); void Rotate(float angle);
/** /**
* \brief Automatically fill edges vector using vertices. * \brief Automatically fill edges vector using vertices.
@@ -78,7 +77,7 @@ class GD_CORE_API Polygon2d {
/** /**
* \brief Create a rectangle * \brief Create a rectangle
*/ */
static Polygon2d CreateRectangle(double width, double height); static Polygon2d CreateRectangle(float width, float height);
///@} ///@}
}; };

View File

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

View File

@@ -7,7 +7,6 @@
#ifndef SPRITE_H #ifndef SPRITE_H
#define SPRITE_H #define SPRITE_H
#include <memory> #include <memory>
#include "GDCore/Extensions/Builtin/SpriteExtension/Point.h" #include "GDCore/Extensions/Builtin/SpriteExtension/Point.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h" #include "GDCore/Extensions/Builtin/SpriteExtension/Polygon2d.h"
#include "GDCore/String.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 * \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 * \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. * 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. * \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); 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 * \brief Return true if the collision mask is a bounding box, false if a
* custom collision mask is used. * custom collision mask is used.
*/ */
inline bool IsFullImageCollisionMask() const { inline bool IsCollisionMaskAutomatic() const {
return fullImageCollisionMask; return automaticCollisionMask;
} }
/** /**
* \brief Un/set use of the custom collision mask. * \brief Un/set use of the custom collision mask.
*/ */
inline void SetFullImageCollisionMask(bool enabled) { inline void SetCollisionMaskAutomatic(bool enabled) {
fullImageCollisionMask = enabled; automaticCollisionMask = enabled;
}; };
/** /**
@@ -162,9 +161,9 @@ class GD_CORE_API Sprite {
private: private:
gd::String image; ///< Name of the image to be loaded in Image Manager. gd::String image; ///< Name of the image to be loaded in Image Manager.
bool fullImageCollisionMask; ///< True to use a bounding box wrapping the bool automaticCollisionMask; ///< True to use the custom collision mask.
///< whole image as collision mask. If false, ///< Otherwise, a basic bounding box is returned
///< custom collision mask is used. ///< by GetCollisionMask()
std::vector<Polygon2d> customCollisionMask; ///< Custom collision mask std::vector<Polygon2d> customCollisionMask; ///< Custom collision mask
std::vector<Point> points; ///< List of the points used by the sprite 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 * GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights
* reserved. This project is released under the GNU Lesser General Public * reserved. This project is released under the GNU Lesser General Public
* License. * LicenFse.
*/ */
#include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h" #include "GDCore/Extensions/Builtin/AllBuiltinExtensions.h"
#include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h" #include "GDCore/Extensions/Builtin/SpriteExtension/SpriteObject.h"
@@ -15,13 +15,12 @@ namespace gd {
void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension( void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
gd::PlatformExtension& extension) { gd::PlatformExtension& extension) {
extension extension
.SetExtensionInformation( .SetExtensionInformation("Sprite",
"Sprite", _("Sprite"),
_("Sprite"), _("Sprite are animated object which can be used "
_("Sprite are animated objects which can be used " "for most elements of a game."),
"for most elements of a 2D game."), "Florian Rival",
"Florian Rival", "Open source (MIT License)")
"Open source (MIT License)")
.SetExtensionHelpPath("/objects/sprite"); .SetExtensionHelpPath("/objects/sprite");
extension.AddInstructionOrExpressionGroupMetadata(_("Sprite")) extension.AddInstructionOrExpressionGroupMetadata(_("Sprite"))
.SetIcon("CppPlatform/Extensions/spriteicon.png"); .SetIcon("CppPlatform/Extensions/spriteicon.png");
@@ -31,18 +30,10 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddObject<SpriteObject>("Sprite", .AddObject<SpriteObject>("Sprite",
_("Sprite"), _("Sprite"),
_("Animated object which can be used for " _("Animated object which can be used for "
"most elements of a 2D game."), "most elements of a game"),
"CppPlatform/Extensions/spriteicon.png") "CppPlatform/Extensions/spriteicon.png")
.SetCategoryFullName(_("General")) .SetCategoryFullName(_("General"));
.SetOpenFullEditorLabel(_("Edit animations"))
.AddDefaultBehavior("EffectCapability::EffectBehavior")
.AddDefaultBehavior("ResizableCapability::ResizableBehavior")
.AddDefaultBehavior("ScalableCapability::ScalableBehavior")
.AddDefaultBehavior("FlippableCapability::FlippableBehavior")
.AddDefaultBehavior("OpacityCapability::OpacityBehavior")
.AddDefaultBehavior("AnimatableCapability::AnimatableBehavior");
// Deprecated
obj.AddAction("Opacity", obj.AddAction("Opacity",
_("Sprite opacity"), _("Sprite opacity"),
_("Change the opacity of a Sprite. 0 is fully transparent, 255 " _("Change the opacity of a Sprite. 0 is fully transparent, 255 "
@@ -53,14 +44,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/opacity.png") "res/actions/opacity.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number", .MarkAsSimple();
ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity (0-255)")))
.MarkAsSimple()
.SetHidden();
// Deprecated
obj.AddAction("ChangeAnimation", obj.AddAction("ChangeAnimation",
_("Change the animation"), _("Change the animation"),
_("Change the animation of the object, using the animation " _("Change the animation of the object, using the animation "
@@ -71,12 +57,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png") "res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number", .UseStandardOperatorParameters("number")
ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
// Deprecated
obj.AddAction("SetAnimationName", obj.AddAction("SetAnimationName",
_("Change the animation (by name)"), _("Change the animation (by name)"),
_("Change the animation of the object, using the name of the " _("Change the animation of the object, using the name of the "
@@ -88,7 +71,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name")) .AddParameter("objectAnimationName", _("Animation name"))
.SetHidden()
.MarkAsAdvanced(); .MarkAsAdvanced();
obj.AddAction( obj.AddAction(
@@ -104,8 +86,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden() // Hide as 8 direction is not supported officially in the .SetHidden() // Hide as 8 direction is not supported officially in the
// interface. // interface.
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number", .UseStandardOperatorParameters("number")
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced(); .MarkAsAdvanced();
obj.AddAction("ChangeSprite", obj.AddAction("ChangeSprite",
@@ -117,11 +98,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/sprite.png") "res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number", .UseStandardOperatorParameters("number")
ParameterOptions::MakeNewOptions())
.MarkAsAdvanced(); .MarkAsAdvanced();
// Deprecated
obj.AddAction("PauseAnimation", obj.AddAction("PauseAnimation",
_("Pause the animation"), _("Pause the animation"),
_("Pause the animation of the object"), _("Pause the animation of the object"),
@@ -131,10 +110,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png") "res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
// Deprecated
obj.AddAction("PlayAnimation", obj.AddAction("PlayAnimation",
_("Play the animation"), _("Play the animation"),
_("Play the animation of the object"), _("Play the animation of the object"),
@@ -144,10 +121,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png") "res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
// Deprecated
obj.AddAction( obj.AddAction(
"ChangeAnimationSpeedScale", "ChangeAnimationSpeedScale",
_("Animation speed scale"), _("Animation speed scale"),
@@ -159,13 +134,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/animation.png") "res/actions/animation.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(_("Speed scale")))
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
// Deprecated
obj.AddAction("TourneVersPos", obj.AddAction("TourneVersPos",
"Rotate an object toward a position", "Rotate an object toward a position",
"Rotate an object towards a position.", "Rotate an object towards a position.",
@@ -180,9 +151,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("expression", _("Angular speed (degrees per second)")) .AddParameter("expression", _("Angular speed (degrees per second)"))
.SetDefaultValue("0") .SetDefaultValue("0")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.SetHidden(); .SetHidden(); // Deprecated
// Deprecated
obj.AddAction("ChangeScale", obj.AddAction("ChangeScale",
_("Scale"), _("Scale"),
_("Modify the scale of the specified object."), _("Modify the scale of the specified object."),
@@ -192,14 +162,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scale_black.png") "res/actions/scale_black.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number", .MarkAsAdvanced();
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeScaleWidth", obj.AddAction("ChangeScaleWidth",
_("Scale on X axis"), _("Scale on X axis"),
_("Modify the scale of the width of an object."), _("Modify the scale of the width of an object."),
@@ -209,14 +174,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleWidth_black.png") "res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number", .MarkAsAdvanced();
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeScaleHeight", obj.AddAction("ChangeScaleHeight",
_("Scale on Y axis"), _("Scale on Y axis"),
_("Modify the scale of the height of an object."), _("Modify the scale of the height of an object."),
@@ -226,14 +186,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleHeight_black.png") "res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters( .UseStandardOperatorParameters("number")
"number", .MarkAsAdvanced();
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeWidth", obj.AddAction("ChangeWidth",
_("Width"), _("Width"),
_("Change the width of a Sprite object."), _("Change the width of a Sprite object."),
@@ -243,12 +198,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleWidth_black.png") "res/actions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number", .UseStandardOperatorParameters("number")
ParameterOptions::MakeNewOptions()) .MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddCondition("Width", obj.AddCondition("Width",
_("Width"), _("Width"),
_("Compare the width of a Sprite object."), _("Compare the width of a Sprite object."),
@@ -258,12 +210,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/scaleWidth_black.png") "res/conditions/scaleWidth_black.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", ParameterOptions::MakeNewOptions()) .MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("ChangeHeight", obj.AddAction("ChangeHeight",
_("Height"), _("Height"),
_("Change the height of a Sprite object."), _("Change the height of a Sprite object."),
@@ -273,12 +222,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/actions/scaleHeight_black.png") "res/actions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardOperatorParameters("number", .UseStandardOperatorParameters("number")
ParameterOptions::MakeNewOptions()) .MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddCondition("Height", obj.AddCondition("Height",
_("Height"), _("Height"),
_("Compare the height of a Sprite object."), _("Compare the height of a Sprite object."),
@@ -288,12 +234,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/scaleHeight_black.png") "res/conditions/scaleHeight_black.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", ParameterOptions::MakeNewOptions()) .MarkAsAdvanced();
.MarkAsAdvanced()
.SetHidden();
// Deprecated
obj.AddAction("SetSize", obj.AddAction("SetSize",
_("Size"), _("Size"),
_("Change the size of an object."), _("Change the size of an object."),
@@ -305,10 +248,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object")) .AddParameter("object", _("Object"))
.AddParameter("expression", _("Width")) .AddParameter("expression", _("Width"))
.AddParameter("expression", _("Height")) .AddParameter("expression", _("Height"))
.MarkAsAdvanced() .MarkAsAdvanced();
.SetHidden();
// Deprecated
obj.AddCondition( obj.AddCondition(
"Animation", "Animation",
_("Current animation"), _("Current animation"),
@@ -319,15 +260,12 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png") "res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", ParameterOptions::MakeNewOptions())
.SetHidden()
.MarkAsAdvanced(); .MarkAsAdvanced();
// Deprecated
obj.AddCondition("AnimationName", obj.AddCondition("AnimationName",
_("Current animation name"), _("Current animation name"),
_("Check the animation played by the object."), _("Check the animation by played by the object."),
_("The animation of _PARAM0_ is _PARAM1_"), _("The animation of _PARAM0_ is _PARAM1_"),
_("Animations and images"), _("Animations and images"),
"res/conditions/animation24.png", "res/conditions/animation24.png",
@@ -335,7 +273,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectAnimationName", _("Animation name")) .AddParameter("objectAnimationName", _("Animation name"))
.SetHidden()
.MarkAsAdvanced(); .MarkAsAdvanced();
obj.AddCondition( obj.AddCondition(
@@ -351,8 +288,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden() // Hide as 8 direction is not supported officially in the .SetHidden() // Hide as 8 direction is not supported officially in the
// interface. // interface.
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number");
"number", ParameterOptions::MakeNewOptions());
obj.AddCondition("Sprite", obj.AddCondition("Sprite",
_("Current frame"), _("Current frame"),
@@ -365,11 +301,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/sprite.png") "res/conditions/sprite.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced(); .MarkAsAdvanced();
// Deprecated
obj.AddCondition("AnimStopped", obj.AddCondition("AnimStopped",
_("Animation paused"), _("Animation paused"),
_("Check if the animation of an object is paused."), _("Check if the animation of an object is paused."),
@@ -379,10 +313,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png") "res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
// Deprecated
obj.AddCondition("AnimationEnded", obj.AddCondition("AnimationEnded",
_("Animation finished"), _("Animation finished"),
_("Check if the animation being played by the Sprite object " _("Check if the animation being played by the Sprite object "
@@ -393,24 +325,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/animation.png") "res/conditions/animation.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.MarkAsSimple()
.SetHidden();
// Deprecated
obj.AddCondition("AnimationEnded2",
_("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"), "Sprite")
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
// Deprecated
obj.AddCondition("ScaleWidth", obj.AddCondition("ScaleWidth",
_("Scale on X axis"), _("Scale on X axis"),
_("Compare the scale of the width of an object."), _("Compare the scale of the width of an object."),
@@ -418,15 +334,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Size"), _("Size"),
"res/conditions/scaleWidth24_black.png", "res/conditions/scaleWidth24_black.png",
"res/conditions/scaleWidth_black.png") "res/conditions/scaleWidth_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
// Deprecated
obj.AddCondition("ScaleHeight", obj.AddCondition("ScaleHeight",
_("Scale on Y axis"), _("Scale on Y axis"),
_("Compare the scale of the height of an object."), _("Compare the scale of the height of an object."),
@@ -434,15 +346,11 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Size"), _("Size"),
"res/conditions/scaleHeight24_black.png", "res/conditions/scaleHeight24_black.png",
"res/conditions/scaleHeight_black.png") "res/conditions/scaleHeight_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number",
ParameterOptions::MakeNewOptions().SetDescription(
_("Scale (1 by default)")))
.MarkAsAdvanced(); .MarkAsAdvanced();
// Deprecated
obj.AddCondition("Opacity", obj.AddCondition("Opacity",
_("Opacity"), _("Opacity"),
_("Compare the opacity of a Sprite, between 0 (fully " _("Compare the opacity of a Sprite, between 0 (fully "
@@ -453,12 +361,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/opacity.png") "res/conditions/opacity.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", .MarkAsSimple();
ParameterOptions::MakeNewOptions().SetDescription(
_("Opacity to compare to (0-255)")))
.MarkAsSimple()
.SetHidden();
obj.AddCondition( obj.AddCondition(
"BlendMode", "BlendMode",
@@ -470,8 +374,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
"res/conditions/opacity.png") "res/conditions/opacity.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.UseStandardRelationalOperatorParameters( .UseStandardRelationalOperatorParameters("number")
"number", ParameterOptions::MakeNewOptions())
.MarkAsAdvanced(); .MarkAsAdvanced();
obj.AddAction("ChangeColor", obj.AddAction("ChangeColor",
@@ -506,9 +409,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"), _("Effects"),
"res/actions/flipX24.png", "res/actions/flipX24.png",
"res/actions/flipX.png") "res/actions/flipX.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.AddParameter("yesorno", _("Activate flipping")) .AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
obj.AddAction("FlipY", obj.AddAction("FlipY",
@@ -518,9 +421,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"), _("Effects"),
"res/actions/flipY24.png", "res/actions/flipY24.png",
"res/actions/flipY.png") "res/actions/flipY.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.AddParameter("yesorno", _("Activate flipping")) .AddParameter("yesorno", _("Activate flipping"))
.SetHidden()
.MarkAsSimple(); .MarkAsSimple();
obj.AddCondition("FlippedX", obj.AddCondition("FlippedX",
@@ -530,8 +433,8 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"), _("Effects"),
"res/actions/flipX24.png", "res/actions/flipX24.png",
"res/actions/flipX.png") "res/actions/flipX.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden(); .AddParameter("object", _("Object"), "Sprite");
obj.AddCondition("FlippedY", obj.AddCondition("FlippedY",
_("Vertically flipped"), _("Vertically flipped"),
@@ -540,10 +443,9 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Effects"), _("Effects"),
"res/actions/flipY24.png", "res/actions/flipY24.png",
"res/actions/flipY.png") "res/actions/flipY.png")
.AddParameter("object", _("Object"), "Sprite")
.SetHidden();
// Deprecated .AddParameter("object", _("Object"), "Sprite");
obj.AddAction("TourneVers", obj.AddAction("TourneVers",
"Rotate an object toward another", "Rotate an object toward another",
"Rotate an object towards another.", "Rotate an object towards another.",
@@ -555,7 +457,7 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPtr", "Rotate toward this object") .AddParameter("objectPtr", "Rotate toward this object")
.AddCodeOnlyParameter("currentScene", "") .AddCodeOnlyParameter("currentScene", "")
.SetHidden(); .SetHidden(); // Deprecated
obj.AddExpression("X", obj.AddExpression("X",
_("X position of a point"), _("X position of a point"),
@@ -593,7 +495,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite")
.AddParameter("objectPointName", _("Name of the point")); .AddParameter("objectPointName", _("Name of the point"));
// Deprecated
obj.AddExpression("Direc", obj.AddExpression("Direc",
_("Direction"), _("Direction"),
_("Direction of the object"), _("Direction of the object"),
@@ -602,7 +503,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden() .SetHidden()
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Direction", obj.AddExpression("Direction",
_("Direction"), _("Direction"),
_("Direction of the object"), _("Direction of the object"),
@@ -612,7 +512,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
// interface. // interface.
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Anim", obj.AddExpression("Anim",
_("Animation"), _("Animation"),
_("Animation of the object"), _("Animation of the object"),
@@ -621,46 +520,32 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
.SetHidden() .SetHidden()
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Animation", obj.AddExpression("Animation",
_("Animation"), _("Animation"),
_("Animation of the object"), _("Animation of the object"),
_("Animations and images"), _("Animations and images"),
"res/actions/animation.png") "res/actions/animation.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddStrExpression("AnimationName", obj.AddStrExpression("AnimationName",
_("Animation name"), _("Animation name"),
_("Name of the animation of the object"), _("Name of the animation of the object"),
_("Animations and images"), _("Animations and images"),
"res/actions/animation.png") "res/actions/animation.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("Sprite", obj.AddExpression("Sprite",
_("Image"), _("Image"),
_("Current frame of the animation of the object"), _("Animation frame of the object"),
_("Animations and images"), _("Animations and images"),
"res/actions/sprite.png") "res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
obj.AddExpression(
"AnimationFrameCount",
_("Number of frames"),
_("Number of frames in the current animation of the object"),
_("Animations and images"),
"res/actions/sprite.png")
.AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("AnimationSpeedScale", obj.AddExpression("AnimationSpeedScale",
_("Animation speed scale"), _("Animation speed scale"),
_("Animation speed scale"), _("Animation speed scale"),
_("Animations and images"), _("Animations and images"),
"res/actions/animation.png") "res/actions/animation.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleX", obj.AddExpression("ScaleX",
@@ -668,7 +553,6 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale of the width of an object"), _("Scale of the width of an object"),
_("Size"), _("Size"),
"res/actions/scaleWidth_black.png") "res/actions/scaleWidth_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
obj.AddExpression("ScaleY", obj.AddExpression("ScaleY",
@@ -676,17 +560,14 @@ void GD_CORE_API BuiltinExtensionsImplementer::ImplementsSpriteExtension(
_("Scale of the height of an object"), _("Scale of the height of an object"),
_("Size"), _("Size"),
"res/actions/scaleHeight_black.png") "res/actions/scaleHeight_black.png")
.SetHidden()
.AddParameter("object", _("Object"), "Sprite"); .AddParameter("object", _("Object"), "Sprite");
// Deprecated
obj.AddExpression("Opacity", obj.AddExpression("Opacity",
_("Opacity"), _("Opacity"),
_("Opacity"), _("Opacity"),
_("Opacity"), _("Opacity"),
"res/actions/opacity.png") "res/actions/opacity.png")
.AddParameter("object", _("Object"), "Sprite") .AddParameter("object", _("Object"), "Sprite");
.SetHidden();
extension extension
.AddCondition("Collision", .AddCondition("Collision",

View File

@@ -23,45 +23,122 @@
namespace gd { namespace gd {
SpriteObject::SpriteObject() Animation SpriteObject::badAnimation;
: updateIfNotVisible(false),
preScale(1) {} SpriteObject::SpriteObject() : updateIfNotVisible(false) {}
SpriteObject::~SpriteObject(){}; SpriteObject::~SpriteObject(){};
void SpriteObject::DoUnserializeFrom(gd::Project& project, void SpriteObject::DoUnserializeFrom(gd::Project& project,
const gd::SerializerElement& element) { const gd::SerializerElement& element) {
updateIfNotVisible = element.GetBoolAttribute("updateIfNotVisible", true); 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 { void SpriteObject::DoSerializeTo(gd::SerializerElement& element) const {
element.SetAttribute("updateIfNotVisible", updateIfNotVisible); 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() std::map<gd::String, gd::PropertyDescriptor> SpriteObject::GetProperties()
const { const {
std::map<gd::String, gd::PropertyDescriptor> properties; 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; return properties;
} }
bool SpriteObject::UpdateProperty(const gd::String& name, bool SpriteObject::UpdateProperty(const gd::String& name,
const gd::String& value) { const gd::String& value) {
if (name == _("Animate even if hidden or far from the screen"))
updateIfNotVisible = value == "1";
return true; return true;
} }
void SpriteObject::ExposeResources(gd::ArbitraryResourceWorker& worker) { 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> std::map<gd::String, gd::PropertyDescriptor>
SpriteObject::GetInitialInstanceProperties( SpriteObject::GetInitialInstanceProperties(
const gd::InitialInstance& initialInstance) { const gd::InitialInstance& initialInstance,
gd::Project& project,
gd::Layout& scene) {
std::map<gd::String, gd::PropertyDescriptor> properties; std::map<gd::String, gd::PropertyDescriptor> properties;
properties["animation"] = properties["animation"] =
gd::PropertyDescriptor( gd::PropertyDescriptor(
@@ -75,7 +152,9 @@ SpriteObject::GetInitialInstanceProperties(
bool SpriteObject::UpdateInitialInstanceProperty( bool SpriteObject::UpdateInitialInstanceProperty(
gd::InitialInstance& initialInstance, gd::InitialInstance& initialInstance,
const gd::String& name, const gd::String& name,
const gd::String& value) { const gd::String& value,
gd::Project& project,
gd::Layout& scene) {
if (name == "animation") { if (name == "animation") {
initialInstance.SetRawDoubleProperty( initialInstance.SetRawDoubleProperty(
"animation", std::max(0, value.empty() ? 0 : value.To<int>())); "animation", std::max(0, value.empty() ? 0 : value.To<int>()));
@@ -84,25 +163,42 @@ bool SpriteObject::UpdateInitialInstanceProperty(
return true; return true;
} }
size_t SpriteObject::GetAnimationsCount() const { const Animation& SpriteObject::GetAnimation(std::size_t nb) const {
return animations.GetAnimationsCount(); if (nb >= animations.size()) return badAnimation;
return animations[nb];
} }
const gd::String &SpriteObject::GetAnimationName(size_t index) const { Animation& SpriteObject::GetAnimation(std::size_t nb) {
return animations.GetAnimation(index).GetName(); if (nb >= animations.size()) return badAnimation;
return animations[nb];
} }
bool SpriteObject::HasAnimationNamed( void SpriteObject::AddAnimation(const Animation& animation) {
const gd::String &name) const { animations.push_back(animation);
return animations.HasAnimationNamed(name);
} }
const SpriteAnimationList& SpriteObject::GetAnimations() const { bool SpriteObject::RemoveAnimation(std::size_t nb) {
return animations; if (nb >= GetAnimationsCount()) return false;
animations.erase(animations.begin() + nb);
return true;
} }
SpriteAnimationList& SpriteObject::GetAnimations() { void SpriteObject::SwapAnimations(std::size_t firstIndex,
return animations; 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 } // namespace gd

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